OpenGL FrameBuffer 不在屏幕外渲染
OpenGL FrameBuffer not rendering off-screen
好的,这是我当前的渲染工作流程。我创建了一个没有 depth/stencil 附件且只有颜色纹理附件的帧缓冲区对象。我绑定帧缓冲区并将我所有的纹理渲染到它上面。然后我将纹理数据从渲染缓冲区纹理复制到另一个纹理(尽管这部分并不真正相关,因为渲染到帧缓冲区时会出现问题)。所以问题是一旦渲染超过 window 边界,它就会停止绘制。所以这是当前呈现的图像(抱歉,我必须 post 链接,我还没有足够的声誉来 post 图像):
这是实际纹理数据的图像(由 gDEBUgger 提供)。
如您所见,它切断的部分是 window 宽度所在的位置。使用 glClear
也仅涵盖纹理的 window 大小,仅此而已。
我已经尝试将 glDisable(GL_SCISSOR_TEST)
与 glViewport(0, 0, texture_width, texture_height)
一起使用,但它仍然会切断纹理。缩小视口会在同一点切断,增大视口只会拉伸图像并切断更多纹理。
我的意思是,这是有道理的,当您甚至看不到像素时,为什么要在屏幕外绘制像素,这对性能来说太糟糕了。但就我而言,我需要这样做。这就是为什么我正在寻找一种方法来禁用它或类似的东西。
另请注意,我已禁用深度测试,因此自从我禁用深度测试以来,深度清除不会超过 window 界限。
有人有什么想法吗?
编辑: 以防万一以后有人看到这个帖子,我只是想说说是什么为我解决了这个问题。我只需要将视口设置为纹理的大小 AND 在渲染时将透视矩阵缩放到相同的大小。就我而言,我使用了自己的矩阵 class。这是一个例子:
glViewport(0, 0, texture_width, texture_height);
perspective_mat.identity();
perspective_mat.scale(1.0f / (texture_width / 2), -1.0f / (texture_height / 2));
perspective_mat.translate(-1.0f, 1.0f);
如果您使用的是固定管道(无着色器等),那么您可以使用 openGL 矩阵函数来缩放和平移。 :)
没有看到您的实际代码,很难说出了什么问题,但这段代码有效。
// ************************************** Save the Current Viewport Size
GLint screenViewPort[4];
glGetIntegerv(GL_VIEWPORT, screenViewPort);
// ***************************** Define a Second Output Buffer and Bind it for Writing
glGenFramebuffersEXT(1, wispSecondOutputBuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wispSecondOutputBuffer[0]);
// ******************************* Set the Viewport to the Texture Size and Reshape
glViewport(0,0,TEXTUREWIDTH, TEXTUREHEIGHT);
[self resizeTextureGL];
// ************************************** Create the Output Imgage Texture
glGenTextures( 1, wispOutputTexture);
glBindTexture(GL_TEXTURE_2D, wispOutputTexture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)TEXTUREWIDTH, (GLsizei)TEXTUREHEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// ********************************* Attach the Output Texture to the Frame Buffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, wispOutputTexture[0], 0);
GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, DrawBuffers);
// ************************************ Check that the Frame Buffer is Complete
GLenum frameBufferStatus;
frameBufferStatus = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if(frameBufferStatus != GL_FRAMEBUFFER_COMPLETE_EXT) NSLog(@"There is a problem with the output frame buffer");
// ****************************************** Render to the Texture
[self runTextureShaders];
[self runTextureShaders2];
// ************************************ Reset the Viewport and Frame Buffer
glViewport(screenViewPort[0],screenViewPort[1],(GLsizei)screenViewPort[2], (GLsizei)screenViewPort[3]);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
// ******************************* Copy the Texture Data Into the Bitmap Image
glBindTexture(GL_TEXTURE_2D, wispOutputTexture[0]);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmapData);
调用 resizeTextureGL 计算模型、视图和投影矩阵。
稍后在代码中我还有:
// ******************************************* Cleanup Memory
glDeleteTextures(1, wispOutputTexture);
glDeleteFramebuffersEXT(1, wispSecondOutputBuffer);
好的,这是我当前的渲染工作流程。我创建了一个没有 depth/stencil 附件且只有颜色纹理附件的帧缓冲区对象。我绑定帧缓冲区并将我所有的纹理渲染到它上面。然后我将纹理数据从渲染缓冲区纹理复制到另一个纹理(尽管这部分并不真正相关,因为渲染到帧缓冲区时会出现问题)。所以问题是一旦渲染超过 window 边界,它就会停止绘制。所以这是当前呈现的图像(抱歉,我必须 post 链接,我还没有足够的声誉来 post 图像):
这是实际纹理数据的图像(由 gDEBUgger 提供)。
如您所见,它切断的部分是 window 宽度所在的位置。使用 glClear
也仅涵盖纹理的 window 大小,仅此而已。
我已经尝试将 glDisable(GL_SCISSOR_TEST)
与 glViewport(0, 0, texture_width, texture_height)
一起使用,但它仍然会切断纹理。缩小视口会在同一点切断,增大视口只会拉伸图像并切断更多纹理。
我的意思是,这是有道理的,当您甚至看不到像素时,为什么要在屏幕外绘制像素,这对性能来说太糟糕了。但就我而言,我需要这样做。这就是为什么我正在寻找一种方法来禁用它或类似的东西。
另请注意,我已禁用深度测试,因此自从我禁用深度测试以来,深度清除不会超过 window 界限。
有人有什么想法吗?
编辑: 以防万一以后有人看到这个帖子,我只是想说说是什么为我解决了这个问题。我只需要将视口设置为纹理的大小 AND 在渲染时将透视矩阵缩放到相同的大小。就我而言,我使用了自己的矩阵 class。这是一个例子:
glViewport(0, 0, texture_width, texture_height);
perspective_mat.identity();
perspective_mat.scale(1.0f / (texture_width / 2), -1.0f / (texture_height / 2));
perspective_mat.translate(-1.0f, 1.0f);
如果您使用的是固定管道(无着色器等),那么您可以使用 openGL 矩阵函数来缩放和平移。 :)
没有看到您的实际代码,很难说出了什么问题,但这段代码有效。
// ************************************** Save the Current Viewport Size
GLint screenViewPort[4];
glGetIntegerv(GL_VIEWPORT, screenViewPort);
// ***************************** Define a Second Output Buffer and Bind it for Writing
glGenFramebuffersEXT(1, wispSecondOutputBuffer);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wispSecondOutputBuffer[0]);
// ******************************* Set the Viewport to the Texture Size and Reshape
glViewport(0,0,TEXTUREWIDTH, TEXTUREHEIGHT);
[self resizeTextureGL];
// ************************************** Create the Output Imgage Texture
glGenTextures( 1, wispOutputTexture);
glBindTexture(GL_TEXTURE_2D, wispOutputTexture[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)TEXTUREWIDTH, (GLsizei)TEXTUREHEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// ********************************* Attach the Output Texture to the Frame Buffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, wispOutputTexture[0], 0);
GLenum DrawBuffers[1] = {GL_COLOR_ATTACHMENT0};
glDrawBuffers(1, DrawBuffers);
// ************************************ Check that the Frame Buffer is Complete
GLenum frameBufferStatus;
frameBufferStatus = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if(frameBufferStatus != GL_FRAMEBUFFER_COMPLETE_EXT) NSLog(@"There is a problem with the output frame buffer");
// ****************************************** Render to the Texture
[self runTextureShaders];
[self runTextureShaders2];
// ************************************ Reset the Viewport and Frame Buffer
glViewport(screenViewPort[0],screenViewPort[1],(GLsizei)screenViewPort[2], (GLsizei)screenViewPort[3]);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
// ******************************* Copy the Texture Data Into the Bitmap Image
glBindTexture(GL_TEXTURE_2D, wispOutputTexture[0]);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmapData);
调用 resizeTextureGL 计算模型、视图和投影矩阵。
稍后在代码中我还有:
// ******************************************* Cleanup Memory
glDeleteTextures(1, wispOutputTexture);
glDeleteFramebuffersEXT(1, wispSecondOutputBuffer);