【问题标题】:OpenGL texture coordinates wrongOpenGL纹理坐标错误
【发布时间】:2015-04-23 03:44:41
【问题描述】:

使用我的previous question 的答案,我设法将整个字体图集渲染到屏幕上。但是,在从地图集中渲染单个字符时,我的坐标似乎有些错误:

alt text http://img.condorcraft110.net/font%20renderer%20fail.png

从那(文本应该是“测试字体渲染器文本”)我可以假设纹理坐标是错误的。但他们哪里错了?

完整的工作示例:

import java.awt.image.*;
import java.io.*;
import java.nio.*;
import javax.imageio.*;
import org.lwjgl.*;
import org.lwjgl.opengl.*;

public class OpenGLFontRendererTest
{
    private static int textureID;

    public static void main(String[] args) throws Exception
    {
        Display.setTitle("OpenGL Font Renderer Test");
        Display.setDisplayMode(new DisplayMode(640, 480));
        Display.create();

        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glOrtho(0, 640, 0, 480, 1, -1);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);

        textureID = bindTextureFile("textures/font.png");

        while(!Display.isCloseRequested())
        {
            Display.sync(60);

            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            GL11.glClearColor(0, 0, 0, 1);

            GL11.glColor4f(1, 1, 1, 1);
            drawText(20, 20, "Test font renderer text");

            Display.update();
        }

        Display.destroy();
    }

    private static void drawText(int x, int y, String text)
    {
        GL11.glPushMatrix();
            GL11.glTranslatef(x, y, 0);
            GL11.glDisable(GL11.GL_DEPTH_TEST);
            GL11.glEnable(GL11.GL_TEXTURE_2D);
            GL11.glEnable(GL11.GL_BLEND);
                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
                GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
                GL11.glBegin(GL11.GL_QUADS);
                    int xOff = 0;
                    int yOff = 0;
                    for(char c : text.toCharArray())
                    {
                        if(c == '\n')
                        {
                            xOff = 0;
                            yOff += 17;
                            continue;
                        }
                        else if(c == '\r')
                        {
                            xOff = 0;
                            continue;
                        }

                        float pos = (float)c;

                        float textureX = (pos % 16F) / 16F;
                        float textureY = (pos / 16F) / 16F;

                        GL11.glTexCoord2f(textureX, textureY + 0.0625F);
                        GL11.glVertex2i(xOff, yOff);

                        GL11.glTexCoord2f(textureX, textureY);
                        GL11.glVertex2i(xOff, yOff + 16);

                        GL11.glTexCoord2f(textureX + 0.0625F, textureY);
                        GL11.glVertex2i(xOff + 16, yOff + 16);

                        GL11.glTexCoord2f(textureX + 0.0625F, textureY + 0.0625F);
                        GL11.glVertex2i(xOff + 16, yOff);

                        xOff += 17;
                    }
                GL11.glEnd();
            GL11.glDisable(GL11.GL_BLEND);
            GL11.glDisable(GL11.GL_TEXTURE_2D);
            GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glPopMatrix();
    }

    private static int bindTextureFile(String file)
    {
        try
        {
            BufferedImage image = ImageIO.read(new FileInputStream(file));

            int[] pixels = new int[image.getWidth() * image.getHeight()];

            image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());

            ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4);

            for(int y = 0; y < image.getWidth(); y++)
            {
                for(int x = 0; x < image.getHeight(); x++)
                {
                    int pixel = pixels[y * image.getWidth() + x];

                    buffer.put((byte)((pixel >> 16) & 0xFF));
                    buffer.put((byte)((pixel >> 8) & 0xFF));
                    buffer.put((byte)(pixel & 0xFF));
                    buffer.put((byte)((pixel >> 24) & 0xFF));
                }
            }

            buffer.flip();

            int textureID = GL11.glGenTextures();

            GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);

            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);

            GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, image.getWidth(), image.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);

            return textureID;
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

        return -1;
    }
}

font.png 再次成为用于测试目的的默认 Minecraft 字体文件 (/fonts/default.png)。

【问题讨论】:

  • 你能附上你正在使用的实际 font.png 吗?好像有好几个。 FWIW:我通常将绘制单个字符与绘制整个字符串分开。这样,您就可以独立地测试一个。
  • @Jongware 这是default.png - 由于版权,我认为我不能发布它。
  • 两个有根据的猜测:(1)你从(0,16)(除以16)获取源像素,你应该使用(0,15); (2)% may show unexpected behavior(另见stackoverflow.com/a/2947064/2564301)。将c 的强制转换推迟到float 直到除法之前,因此除法和模数改为整数。这可能会解决几个像素的问题。
  • JOGL 可能更适合文本渲染...因为它有一个 TextRenderer 类,可以非常轻松地在 OpenGL 中操作文本

标签: java opengl lwjgl


【解决方案1】:

好的,我设法解决了这个问题。我是作为浮点数进行划分的,所以我得到了小数位,这弄乱了坐标。

修改后的代码:

import java.awt.image.*;
import java.io.*;
import java.nio.*;
import javax.imageio.*;
import org.lwjgl.*;
import org.lwjgl.opengl.*;

public class OpenGLFontRendererTest
{
    private static int textureID;

    public static void main(String[] args) throws Exception
    {
        Display.setTitle("OpenGL Font Renderer Test");
        Display.setDisplayMode(new DisplayMode(640, 480));
        Display.create();

        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glOrtho(0, 640, 0, 480, 1, -1);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);

        textureID = bindTextureFile("textures/font.png");

        while(!Display.isCloseRequested())
        {
            Display.sync(60);

            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            GL11.glClearColor(0, 0, 0, 1);

            GL11.glColor4f(1, 1, 1, 1);
            drawText(20, 20, "Test font renderer text");

            Display.update();
        }

        Display.destroy();
    }

    private static void drawText(int x, int y, String text)
    {
        GL11.glPushMatrix();
            GL11.glTranslatef(x, y, 0);
            GL11.glDisable(GL11.GL_DEPTH_TEST);
            GL11.glEnable(GL11.GL_TEXTURE_2D);
            GL11.glEnable(GL11.GL_BLEND);
                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
                GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
                GL11.glBegin(GL11.GL_QUADS);
                    int xOff = 0;
                    int yOff = 0;
                    for(char c : text.toCharArray())
                    {
                        if(c == '\n')
                        {
                            xOff = 0;
                            yOff -= 17;
                            continue;
                        }
                        else if(c == '\r')
                        {
                            xOff = 0;
                            continue;
                        }

                        int pos = (int)c; // THESE

                        float textureX = (float)(pos % 16F) / 16F; // THREE
                        float textureY = (float)(pos / 16) / 16F; // LINES

                        GL11.glTexCoord2f(textureX, textureY + 0.0625F);
                        GL11.glVertex2i(xOff, yOff);

                        GL11.glTexCoord2f(textureX, textureY);
                        GL11.glVertex2i(xOff, yOff + 16);

                        GL11.glTexCoord2f(textureX + 0.0625F, textureY);
                        GL11.glVertex2i(xOff + 16, yOff + 16);

                        GL11.glTexCoord2f(textureX + 0.0625F, textureY + 0.0625F);
                        GL11.glVertex2i(xOff + 16, yOff);

                        xOff += 17;
                    }
                GL11.glEnd();
            GL11.glDisable(GL11.GL_BLEND);
            GL11.glDisable(GL11.GL_TEXTURE_2D);
            GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glPopMatrix();
    }

    private static int bindTextureFile(String file)
    {
        try
        {
            BufferedImage image = ImageIO.read(new FileInputStream(file));

            int[] pixels = new int[image.getWidth() * image.getHeight()];

            image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());

            ByteBuffer buffer = BufferUtils.createByteBuffer(image.getWidth() * image.getHeight() * 4);

            for(int y = 0; y < image.getWidth(); y++)
            {
                for(int x = 0; x < image.getHeight(); x++)
                {
                    int pixel = pixels[y * image.getWidth() + x];

                    buffer.put((byte)((pixel >> 16) & 0xFF));
                    buffer.put((byte)((pixel >> 8) & 0xFF));
                    buffer.put((byte)(pixel & 0xFF));
                    buffer.put((byte)((pixel >> 24) & 0xFF));
                }
            }

            buffer.flip();

            int textureID = GL11.glGenTextures();

            GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);

            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
            GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);

            GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, image.getWidth(), image.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);

            return textureID;
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

        return -1;
    }
}

【讨论】:

    猜你喜欢
    • 2012-12-31
    • 2011-07-26
    • 1970-01-01
    • 2015-02-03
    • 2012-03-06
    • 2012-04-08
    • 1970-01-01
    • 1970-01-01
    • 2012-05-16
    相关资源
    最近更新 更多