Java OpenGL中的Textured Quad问题

时间:2014-03-17 18:22:46

标签: java opengl lwjgl

首先,我将从我的代码开始,因为我已经确定哪个块导致了问题。

// init
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 800, 0, 600, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glEnable(GL11.GL_TEXTURE_2D);

// BEGINNING OF OFFENDING CODE

BufferedImage image = ImageIO.read(new File("res/button.png"));
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
IntBuffer buffer = BufferUtils.createIntBuffer(pixels.length);
for (int pixel : pixels)
    buffer.put(pixel);
buffer.flip();

int button = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, button);
//Setup wrap mode
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP);

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_RGBA8, image.getWidth(), image.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);

// END OF OFFENDING CODE

这就是没有纹理四边形的情况。

This is how things are supposed to look before the button.

当我使用有问题的代码(带有纹理四边形)进行渲染时会发生这种情况。

What I'm getting

当我使用有问题的代码(没有纹理四边形)渲染时会发生这种情况。

What I get when I comment out the code for the button

作为参考,这是纹理

What the button should look like


我似乎无法弄清楚哪个GL11通话影响了显示器的其余部分,以及为什么它会影响显示器的其余部分。根据我的理解,GL11.glBindTexture后面的所有调用仅限于绑定纹理,不是吗?


编辑:其他渲染代码

private static void renderQuad(int x, int y, int width, int height) {
    GL11.glPushMatrix();
    GL11.glBegin(GL11.GL_QUADS);
        GL11.glVertex2f(x, y);
        GL11.glVertex2f(x + width, y);
        GL11.glVertex2f(x + width, y + height);
        GL11.glVertex2f(x, y + height);
    GL11.glEnd();
    GL11.glPopMatrix();
}

用于红色四边形的方法。

GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glColor3f(0.5f,0.5f,1.0f);
renderQuad(0, 0, 800, 600);

// render action bar
GL11.glColor3f(0.2f,0.2f,1.0f);
renderQuad(0, 0, 800, 200);

GL11.glColor3f(1.0f,0.0f,0.0f);
renderQuad(50, 50, 100, 60);

renderQuad(200, 50, 100, 60);

// render textured quad
GL11.glPushMatrix();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, button);
GL11.glBegin(GL11.GL_QUADS);
    GL11.glTexCoord2d(0.0,1.0); 
    GL11.glVertex2f(x, y);
    GL11.glTexCoord2d(1.0,1.0); 
    GL11.glVertex2f(x + width, y);
    GL11.glTexCoord2d(1.0,0.0); 
    GL11.glVertex2f(x + width, y + height);
    GL11.glTexCoord2d(0.0,0.0); 
    GL11.glVertex2f(x, y + height);
GL11.glEnd();
GL11.glPopMatrix();

1 个答案:

答案 0 :(得分:1)

首先,我认为纹理加载存在问题。我相信字节的顺序是相反的或类似的,这就是为什么你得到黑色的红色。这是一个从我自己的代码中获取的工作load-texture-from-BufferedImage示例:

     BufferedImage image = ImageIO.read(new File("<file path>.png"));
     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.getHeight(); y++){
         for(int x = 0; x < image.getWidth(); x++){
             int pixel = pixels[y * image.getWidth() + x];
             buffer.put((byte) ((pixel >> 16) & 0xFF));     // Red component
             buffer.put((byte) ((pixel >> 8) & 0xFF));      // Green component
             buffer.put((byte) (pixel & 0xFF));               // Blue component
             buffer.put((byte) ((pixel >> 24) & 0xFF));    // Alpha component. Only for RGBA
         }
     }

     buffer.flip(); //FOR THE LOVE OF GOD DO NOT FORGET THIS

     // You now have a ByteBuffer filled with the color data of each pixel.
     // Now just create a texture ID and bind it. Then you can load it using 
     // whatever OpenGL method you want, for example:

     int textureID = GL11.glGenTextures(); //Generate texture ID
     GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID); //Bind texture ID

     //Setup wrap mode
     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);

     //Setup texture scaling filtering
     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);

     //Send texel data to OpenGL
     GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, image.getWidth(), image.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);

现在,对于实际的渲染问题:

对于OpenGL,必须启用或禁用GL_TEXTURE_2D,具体取决于您绘制的多边形是否有纹理。如果不为每个顶点提供纹理坐标,则最后一个纹理坐标调用仍然保持并用于每个顶点。因此,您将使用一个像素的纹理来获得四边形。这就是导致黑色四边形的原因 - 它从你的不正确加载的纹理的一个角落中取出一个像素。那么,你的固定渲染代码:

GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

GL11.glDisable(GL11.GL_TEXTURE_2D);

GL11.glColor3f(0.5f,0.5f,1.0f);
renderQuad(0, 0, 800, 600);

// render action bar
GL11.glColor3f(0.2f,0.2f,1.0f);
renderQuad(0, 0, 800, 200);

GL11.glColor3f(1.0f,0.0f,0.0f);
renderQuad(50, 50, 100, 60);

renderQuad(200, 50, 100, 60);

GL11.glEnable(GL11.GL_TEXTURE_2D);

// render textured quad
GL11.glColor3f(1.0f, 1.0f, 1.0f);
GL11.glPushMatrix();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, button);
GL11.glBegin(GL11.GL_QUADS);
    GL11.glTexCoord2d(0.0,1.0); 
    GL11.glVertex2f(x, y);
    GL11.glTexCoord2d(1.0,1.0); 
    GL11.glVertex2f(x + width, y);
    GL11.glTexCoord2d(1.0,0.0); 
    GL11.glVertex2f(x + width, y + height);
    GL11.glTexCoord2d(0.0,0.0); 
    GL11.glVertex2f(x, y + height);
GL11.glEnd();
GL11.glPopMatrix();

另外,如果您这样做,可以使用glEnable()代替GL11.glEnable():

import static org.lwjgl.opengl.GL11.*;

而不是简单

import org.lwjgl.opengl.GL11;