OpenGL FrameBuffer 和 glViewport

Posted

技术标签:

【中文标题】OpenGL FrameBuffer 和 glViewport【英文标题】:OpenGL FrameBuffer and glViewport 【发布时间】:2017-03-13 06:15:04 【问题描述】:

我正在对 FrameBufferObject 进行渲染过程,这样我就可以在下一个渲染过程中将结果用作纹理。看教程,我需要打电话:

glBindFramebuffer(GL_TEXTURE2D, mFrameBufferObjectID);
glViewport(0, 0, mWidth, mHeight);

其中 mWidth 和 mHeight 是帧缓冲区对象的宽度和高度。似乎没有这个 glViewport 调用,什么都不能正确绘制。奇怪的是,在开始下一帧时,我需要调用:

glViewport(0, 0, window_width, window_height);

这样我就可以回到之前的窗口宽度/高度;但调用它似乎只能以原始窗口大小的一半呈现我的东西。所以我实际上只看到我的屏幕的四分之一得到了渲染(是的,整个场景都在上面)。我尝试设置一个断点并查看宽度和高度值,它们是原始值(1024、640)。为什么会这样?我尝试将它们加倍,它正确地绘制在我的整个窗口上。

我在 Mac 上通过 xcode 和 glew 执行此操作。

【问题讨论】:

问题可能出在你没有显示的代码中。 这是带有视网膜屏幕的 Mac 吗?您可能会混淆逻辑像素的分辨率和屏幕上的实际物理像素。或者无论正确的术语是什么...... 是的,我在 Mac xcode 上使用它。 在配备 Retina 显示器的 Mac 上,帧缓冲区在每个维度上比窗口大 2 倍。需要针对屏幕调整带有 window_width 和 window_height 的 glViewport 调用。如果您使用 glfw,您可以通过以下方式检索它们:glfw.org/docs/latest/window_guide.html#window_fbsize 【参考方案1】:

视口设置存储在全局状态中。因此,如果您更改它,它会保持新值,直到您再次调用 glViewport。正如您已经指出的,每当您想要渲染到与先前绑定的大小不同的 FBO(或后备缓冲区)时,您都必须设置大小。

【讨论】:

我的问题是,在调用 glViewport(0, 0, 1024, 1024) 渲染 fbo 之后,我想将视口恢复到分辨率为 (1024, 680) 的屏幕。调用 glViewport(0, 0, 1024, 680) 只会渲染四分之一的屏幕,而不是全屏。 我明白了。请准确显示您执行命令的顺序。重置视口的正确位置是直接在绘制到屏幕之前。 我一遍又一遍地查看所有内容。看起来 glViewport(0, 0, X, Y) 确实给了我 X/2 和 Y/2 窗口的宽度和高度。也许这就是 Mac 的“高分辨率”像素?【参考方案2】:

如果您启用了剪刀测试,请尝试调整剪刀框和视口

glEnable(GL_SCISSOR_TEST);

为了解决你的问题写

glViewport(0, 0, mWidth, mHeight);
glScissor(0, 0, mWidth, mHeight);

glViewport(0, 0, window_width, window_height);
glScissor(0, 0, window_width, window_height);

每当您切换到与前一个大小不同的新帧缓冲区时,或者总是为了安全起见。

查看参考glScissor的这个链接 或其他帖子解释它的目的https://gamedev.stackexchange.com/questions/40704/what-is-the-purpose-of-glscissor

【讨论】:

谢谢你的朋友 - 这对我有帮助,帧缓冲区大小与屏幕不同;每次绑定/取消绑定时,我都忘记更新视口。现在很明显...

以上是关于OpenGL FrameBuffer 和 glViewport的主要内容,如果未能解决你的问题,请参考以下文章

Linux OpenGL 实践篇-3 framebuffer

OpenGL进阶之帧缓冲FrameBuffer

OpenGL进阶之帧缓冲FrameBuffer

OpenGL 渲染到 Framebuffer 会产生一个白色的矩形纹理

OpenGL 不会通过调用 glBindFramebuffer(GL_FRAMEBUFFER,0) 渲染到屏幕

OpenGL ES 2.0 Framebuffer 渲染到纹理 iOS:没有显示