当前位置: 首页 > 面试题库 >

LWJGL纹理在显示时上下颠倒

蓝宜
2023-03-14
问题内容

我遵循了一个教程,用于读取图片并从中创建纹理,但是,渲染时它会上下翻转。图像是2的幂。

主班

public class Main {
public static void main(String args[]) throws IOException{
    Main quadExample = new Main();
    quadExample.start();
}

public void start() throws IOException {
    try {
    Display.setDisplayMode(new DisplayMode(1280,720));
    Display.create();
} catch (LWJGLException e) {
    e.printStackTrace();
    System.exit(0);
}

// init OpenGL
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 1280, 0, 720, -1, 1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glClearColor(0, 1, 0, 0);

GL11.glEnable(GL11.GL_TEXTURE_2D);

BufferedImage image = TextureLoader.loadImage("C:\\test.png");
final int textureID = TextureLoader.loadTexture(image);

while (!Display.isCloseRequested()) {
    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.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
    GL11.glBegin(GL11.GL_QUADS);
    GL11.glTexCoord2f(0, 0);
    GL11.glVertex2f(0, 0);

    GL11.glTexCoord2f(1, 0);
    GL11.glVertex2f(256, 0);

    GL11.glTexCoord2f(1, 1);
    GL11.glVertex2f(256, 256);

    GL11.glTexCoord2f(0, 1);
    GL11.glVertex2f(0, 256);
    GL11.glEnd();

    Display.update();
}

Display.destroy();
}

}

纹理加载器

public class TextureLoader {
private static final int BYTES_PER_PIXEL = 4;

public static int loadTexture(BufferedImage image) {
    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() * BYTES_PER_PIXEL);

    for (int y = 0; y < image.getHeight(); y++) {
        for (int x = 0; x < image.getWidth(); 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 = glGenTextures();
    glBindTexture(GL_TEXTURE_2D, textureID);

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

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

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

    return textureID;
}

public static BufferedImage loadImage(String location) {
    try {
        return ImageIO.read(new File(location));
    } catch (IOException e) {
        System.out.println(Errors.IOException);
        e.printStackTrace();
    }
    return null;
}

代码是否有问题,还是必须在创建纹理之前翻转图像?


问题答案:

大多数图像格式从上到下存储数据。除非您在加载图像时重新整理数据,否则这也是读取图像后在内存中的顺序。

从加载的图像创建OpenGL纹理时,除非明确更改顺序,否则将维持此内存顺序。因此,纹理内存中的顺序仍然是从上到下。

OpenGL确实没有图像/纹理方向。但是,当您使用纹理坐标时,它们将按照存储在内存中的顺序处理纹理。这意味着对于t坐标的两个极值:

  • t = 0.0对应于内存中图像的开始,即图像的顶部边缘。
  • t = 1.0对应于内存中图像的末尾,即图像的底部边缘。

现在,查看您的抽奖电话:

GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(0, 0);

GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(256, 0);

GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(256, 256);

GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(0, 256);

在默认的OpenGL坐标系中,y坐标从下到上。因此,前两个顶点是四边形的底部顶点(因为它们的y坐标较小),其余两个顶点是顶部的两个顶点。

由于您对前两个顶点使用了t = 0.0,它们位于四边形的底部,并且t =
0.0对应于图像的顶部,因此图像的顶部在四边形的底部。反之亦然,对于后两个顶点(位于四边形的顶部)使用t = 1.0,并且t =
1.0对应于图像的底部。因此,您的图像看起来是颠倒的。

到目前为止,最简单的解决方法是更改​​纹理坐标。底部的两个顶点使用t = 1.0,顶部的两个顶点使用t = 0.0,图像方向现在与屏幕上四边形的方向匹配:

GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex2f(0.0f, 0.0f);

GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex2f(256.0f, 0.0f);

GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex2f(256.0f, 256.0f);

GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex2f(0.0f, 256.0f);

另一种选择是在读入图像时翻转图像,例如,将for循环的顺序更改为:

for (int y = 0; y < image.getHeight(); y++) {

至:

for (int y = image.getHeight() - 1; y >= 0; y--) {

但是在内存中以自上而下的顺序放置图像是很常见的,如果您使用系统库/框架读取图像,则通常无法控制它。因此,使用纹理坐标在所需方向上渲染它们是一种常用的方法,并且IMHO优于将数据改组。



 类似资料:
  • 有问题显示纹理在我的3D框在LWJGL使用光滑。早些时候我犯了一个错误: BasicShader类: BasicVertex.vs basicfragment.fs

  • 假设我有一个金字塔…我知道如何绘制它,我知道如何为整个金字塔设置纹理,但如何为每面墙设置不同的纹理? 我通过在 我试图通过添加<code>GL11.glBindTexture(GL11.GL_TEXTURE_2D,TEXTURE.getTextureID())来绑定纹理 后,但

  • 我试图弄清楚为什么我不能用LWJGL 3渲染任何纹理。我尝试了多种加载(PNGDecoder、STB、BufferedImage)和渲染纹理的方法。但结果总是一个白色的四边形。 主要类: 加载方法: 渲染方法: ModelTexture类只是存储一些现在不使用的信息,blue.png是16x16的png文件。 这是我在启动程序时得到的输出:

  • 我试图用opengl在Qt中显示纹理,但当我运行时它就是不显示纹理。 我做了一些研究,发现我需要将纹理的高度和宽度设为2的幂。我的纹理现在是(1024x1024)。 我还添加了很多glTexParameterf,可以解决我的问题,但仍然没有运气。 EDIT1:是不是我的质地太大了? EDIT2:glBindTexture(GL_TEXTURE_2D,m_textureID);放置在glBindTe

  • 问题内容: 是否可以使用Slick框架在不使用的情况下加载PNG纹理并绘制字符串? 每当我在Google上搜索 “如何在lwjgl中加载png图像”时,都会 得到类似的答案-> “嘿,只需使用光滑框架 中的textureloader即可 。 与 “如何在lwjgl中绘制字符串” -> “仅使用光滑框架中的TTFFont类”相同 但是我不想使用这种中途跨框架设计。因为我不认为这是最好的方法。 是否有

  • 我试图用lwjgl创建一个简单的OpenGL程序,但目前我还停留在创建纹理渲染上。 我得到的错误是一个分段错误: 机器信息: 有问题的JVM线程堆栈: 最后是我处理纹理创建的代码: 我创建的图像类工作得很好,我使用的示例图像是2 x 2像素,并且具有12字节长度的内部缓冲区,因此segvault不应该由太短的缓冲区引起。