【问题标题】:Java OpenGL screen sized texture mapped quadJava OpenGL 屏幕大小的纹理映射四边形
【发布时间】:2011-06-10 04:20:25
【问题描述】:

我有一个 Java OpenGL (JOGL) 应用程序,我正在尝试创建一个覆盖整个屏幕的纹理映射四边形。在将一些像素绘制到缓冲区中,然后我想将这些像素读入纹理并在屏幕上重绘它们(应用了片段着色器)。我将纹理映射到视口的代码是:

        gl.glMatrixMode(GL.GL_PROJECTION);                                        
        gl.glPushMatrix();                                                 
        gl.glLoadIdentity();                                               
        gl.glOrtho( 0, width, height, 0, -1, 1 );                          
        gl.glMatrixMode(GL.GL_MODELVIEW);                                  
        gl.glPushMatrix();                                                 
        gl.glLoadIdentity();
        IntBuffer ib = IntBuffer.allocate(1);
        gl.glEnable(GL.GL_TEXTURE_2D);
        gl.glGenTextures(1, ib);
        gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);
        //buff contains pixels read from glReadPixels
        gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buff);
        gl.glBindTexture(GL.GL_TEXTURE_2D, ib.get(0));
        gl.glBegin(GL.GL_QUADS);
        gl.glTexCoord2f(0,1);
        gl.glVertex2f(0,0); 
        gl.glTexCoord2f(0,0);
        gl.glVertex2f(0,height);
        gl.glTexCoord2f(1,0);   
        gl.glVertex2f(width,height);
        gl.glTexCoord2f(1,1);      
        gl.glVertex2f(width,0);
        gl.glEnd();
        gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
        gl.glPopMatrix();
        gl.glPopMatrix();

最终结果是一个四边形,它没有覆盖整个视口(它是部分打开的)并且不包含缓冲区中的像素。我在这里做错了什么?

谢谢, 杰夫

【问题讨论】:

  • 您还应该记住,垂直翻转屏幕(在您的glOrtho 调用中)会有效地反转您的面部方向。但既然你至少看到了一些东西,那将不是你的问题,因为剔除你根本看不到任何东西。

标签: java opengl jogl texture2d


【解决方案1】:

首先,您应该只在初始化代码中创建纹理。您不应该每帧都调用 glTexImage2D 。只有在纹理大小发生变化时才再次调用 glTexImage2D; glTexSubImage2D 可用于将数据上传到纹理。将 glTexImage2D 视为“新”,而将 glTexSubImage2D 视为内存副本。

在初始化 OpenGL 之后执行一次。

IntBuffer ib = IntBuffer.allocate(1);  //Store this in your object
gl.glGenTextures(1, ib);
gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);
//buff contains pixels read from glReadPixels
gl.glBindTexture(GL.GL_TEXTURE_2D, ib.get(0));
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, 0);
gl.glBindTexture(GL.GL_TEXTURE_2D, 0);

然后,每一帧,都这样做:

gl.glMatrixMode(GL.GL_PROJECTION);                                        
gl.glPushMatrix();                                                 
gl.glLoadIdentity();                                               
gl.glMatrixMode(GL.GL_MODELVIEW);                                  
gl.glPushMatrix();                                                 
gl.glLoadIdentity();

gl.glBindTexture(GL.GL_TEXTURE_2D, ib.get(0));  //Retrieved from your object
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, buff);

gl.glBegin(GL.GL_QUADS);
    gl.glTexCoord2f(0,1);
    gl.glVertex2f(-1, -1); 
    gl.glTexCoord2f(0, 0);
    gl.glVertex2f(-1, 1);
    gl.glTexCoord2f(1, 0);   
    gl.glVertex2f(1, 1);
    gl.glTexCoord2f(1, 1);      
    gl.glVertex2f(1, -1);
gl.glEnd();

gl.glMatrixMode(GL.GL_MODELVIEW);                                  
gl.glPopMatrix();   
gl.glMatrixMode(GL.GL_PROJECTION);                                        
gl.glPopMatrix();   
gl.glMatrixMode(GL.GL_MODELVIEW);                                  

通过对投影和模型视图使用标识,我们能够直接在剪辑空间中提供顶点坐标。剪辑空间中的 [-1, 1] 范围映射到窗口空间中的 [0, width/height]。所以我们不必知道或关心窗口有多大;只要 glViewport 设置正确,这应该可以工作。

【讨论】:

    【解决方案2】:

    这可能不是问题,但它不会有帮助:您为单次推送弹出模型视图矩阵两次。你根本没有弹出投影矩阵。

    我建议在启动时设置一次投影矩阵,而不进行任何推送或弹出操作。您也不需要真正推送和弹出模型视图矩阵。 (您也可以在启动时进行一次纹理设置。)

    【讨论】:

    • 这不是问题,但这些仍然是很好的建议和更正,所以+1。
    【解决方案3】:

    我将从使用如下代码检查 glError 开始。注意我使用了 GL2 对象,因为旧版本的 JOGL 和 GL 对象存在一些问题,像 GL_QUADS 这样的愚蠢的东西不存在。

    如果您使用上述代码启用了着色器,则需要通过读取采样器来进行纹理处理。如果是这样,请附上您在此渲染代码中使用的着色器代码。

    private static void checkForGLErrors(GL2 gl) {
        int errno = gl.glGetError();
        switch (errno) {
            case GL2.GL_INVALID_ENUM:
                System.err.println("OpenGL Error: Invalid ENUM");
                break;
            case GL2.GL_INVALID_VALUE:
                System.err.println("OpenGL Error: Invalid Value");
                break;
            case GL2.GL_INVALID_OPERATION:
                System.err.println("OpenGL Error: Invalid Operation");
                break;
            case GL2.GL_STACK_OVERFLOW:
                System.err.println("OpenGL Error: Stack Overflow");
                break;
            case GL2.GL_STACK_UNDERFLOW:
                System.err.println("OpenGL Error: Stack Underflow");
                break;
            case GL2.GL_OUT_OF_MEMORY:
                System.err.println("OpenGL Error: Out of Memory");
                break;
            default:
                return;
        }
    }
    

    如果纹理不变,我也会尽量避免每帧生成纹理。你可以保存textureId,以后再绑定。

    【讨论】:

    • GL 错误码返回 0,所以此时没有错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    相关资源
    最近更新 更多