OpenGL 纹理坐标错误
OpenGL texture coordinates wrong
使用我 的答案,我已经成功地将整个字体图集呈现到屏幕上。但是,当涉及到从图集中渲染单个字符时,我的坐标似乎有些错误:
alt text http://img.condorcraft110.net/font%20renderer%20fail.png
据此(文本应该是 'Test font renderer text')我可以假设纹理坐标是错误的。但是他们怎么错了?
完整的工作示例:
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
)。
好的,我设法解决了这个问题。我按浮点数划分,所以我得到了小数位,这弄乱了坐标。
修改后的代码:
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;
}
}
使用我
alt text http://img.condorcraft110.net/font%20renderer%20fail.png
据此(文本应该是 'Test font renderer text')我可以假设纹理坐标是错误的。但是他们怎么错了?
完整的工作示例:
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
)。
好的,我设法解决了这个问题。我按浮点数划分,所以我得到了小数位,这弄乱了坐标。
修改后的代码:
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;
}
}