Java OpenGL 屏幕大小的纹理映射四边形
我有一个 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();
最终结果是一个四边形,它没有覆盖整个视口(它部分打开)并且不包含缓冲区中的像素。我在这里做错了什么?
谢谢, 杰夫
I have a Java OpenGL (JOGL) app, and I'm trying to create a texture mapped quad that covers the entire screen. In draw some pixels to a buffer and then I want to read those pixels into a texture and redraw them on screen (with a fragment shader applied). My code for mapping the texture to the viewport is:
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();
The end result is a quad that is not covering the whole viewport (it's partially on) and that does not contain the pixels from the buffer. What am I doing incorrectly here?
thanks,
Jeff
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,您应该只在初始化代码中创建纹理。您不应该每帧都调用 glTexImage2D。仅当纹理大小发生变化时才再次调用glTexImage2D; glTexSubImage2D 可用于将数据上传到纹理。将 glTexImage2D 视为“新的”,而将 glTexSubImage2D 视为内存副本。
初始化 OpenGL 后执行此操作一次。
然后,在每个帧中执行以下操作:
通过使用投影和模型视图的恒等性,我们能够直接在剪辑空间中提供顶点坐标。剪辑空间中的 [-1, 1] 范围映射到窗口空间中的 [0, 宽度/高度]。所以我们不必知道或关心窗口有多大;只要 glViewport 设置正确,这应该可以工作。
First, you should only create the texture in your initialization code. You should not be calling glTexImage2D every frame. Only call glTexImage2D again if the size of the texture changes; glTexSubImage2D can be used to upload data to the texture. Think of glTexImage2D as "new", while glTexSubImage2D as a memory copy.
Do this once, after initializing OpenGL.
Then, each frame, do this:
By using identity for projection and modelview, we are able to supply vertex coordinates directly in clip-space. The [-1, 1] range in clip-space maps to [0, width/height] in window space. So we don't have to know or care about how big the window is; as long as the glViewport was set up correctly, this should work.
这可能不是问题,但它不会有帮助:您将在一次推送中弹出模型视图矩阵两次。您根本没有弹出投影矩阵。
我建议在启动时设置一次投影矩阵,而不进行任何推送或弹出操作。您实际上也不需要推送和弹出模型视图矩阵。 (您也可以在启动时进行一次纹理设置。)
It may not be the problem, but it won't be helping: You are popping the modelview matrix twice for a single push. You are not popping the projection matrix at all.
I would recommend setting the projection matrix once at startup, without doing any pushes or pops. You don't really need to push and pop the modelview matrix either. (You could do your texture setup once at startup, too.)
我将首先使用如下代码检查 glError 。请注意,我使用 GL2 对象是因为旧版本的 JOGL 和 GL 对象存在一些问题,比如 GL_QUADS 不存在等愚蠢的事情。
如果您使用上述代码启用了着色器,则需要通过读取采样器来进行纹理化。如果是这样,请附上您与此渲染代码一起使用的着色器代码。
如果纹理不会改变,我也会尝试避免在每一帧生成纹理。您可以保存textureId并稍后绑定它。
I would start with checking glError with code like the below. Note I used the GL2 object because there were some issues with older versions of JOGL and the GL object, silly things like GL_QUADS not being there.
If you have a shader enabled with the above code, you need to do the texturing by reading the sampler. If so, please attach the shader code you are using with this rendering code.
I would also try to avoid generating the texture every frame if it is something that doesn't change. You can save the textureId and bind it later.