使用单个 FBO 将单个场景从多个视点绘制到多个纹理中(每个视点 1 个)仅产生一个有效纹理
Posted
技术标签:
【中文标题】使用单个 FBO 将单个场景从多个视点绘制到多个纹理中(每个视点 1 个)仅产生一个有效纹理【英文标题】:Using a single FBO to draw a single scene from multiple viewpoints into multiple textures (1 per viewpoint) yields only one valid texture 【发布时间】:2013-11-26 04:53:07 【问题描述】:我目前正在处理一项任务,该任务要求我们生成用于环境映射的立方体贴图(不使用任何内置的 OpenGL 立方体映射功能)。目前只有最后渲染的图像是有效的。其余的全是黑色的,不管我设置了什么清晰的颜色。
似乎从 FBO 中分离纹理会使其无效(将其清除为黑色)。如果我绘制到一个纹理,然后通过调用glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0)
将纹理从 fbo 中分离出来,我刚刚写入的纹理是黑色的。
伪代码:
bind FBO
for each viewpoint to be rendered (+- each axis, 6 total)
calculate transformation matrices needed for viewpoint
attach next texture to FBO at GL_COLOR_ATTACHMENT0
clear color and depth
render scene
unbind FBO
这是将同一场景渲染到多个纹理的合理方法,还是应该使用多个 FBO? 推荐的方法是什么(再次,避免使用 OpenGL 立方体贴图功能)?
C++ 代码:
初始化 FBO
// Setup FBO
glGenFramebuffers(1, &_env_map_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, _env_map_fbo);
// Setup depth buffer
glGenTextures(1, &_env_map_depth);
glBindTexture(GL_TEXTURE_2D, _env_map_depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, 512, 512, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0); // unbind depth texture
// Attach depth buffer to FBO
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, _env_map_depth, 0);
// Configure FBO
glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(GL_NONE);
glViewport(0, 0, 512, 512);
// Verify framebuffer is complete
GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);(void)fb_status;
pcerror_if(fb_status != GL_FRAMEBUFFER_COMPLETE, "Error setting up FBO!");
初始化纹理
glGenTextures(6, _tex_ids);
for(uint i = 0; i < 6; ++i)
glBindTexture(GL_TEXTURE_2D, _tex_ids[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 512, 512, 0, GL_RGB, GL_FLOAT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glBindTexture(GL_TEXTURE_2D, 0);
内部渲染循环
// Bind frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, _env_map_fbo);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
// Calculate transformation matrices for viewpoint 1
// ...
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _tex_ids[0], 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_graphics.render(); // Render entire scene using the same code I normally use.
// Calculate transformation matrices for viewpoint 2
// ...
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _tex_ids[1], 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_graphics.render();
// Etc. for each viewpoint
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDrawBuffer(GL_BACK);
// Draw scene as normal
如果有用,请提供更多信息:
我正在使用 gDEBugger 检查渲染结果。 纹理在此处使用时不应绑定到其他任何地方。【问题讨论】:
【参考方案1】:看来我的方法确实有效。我对 gDEBugger 过于信任了。将纹理绘制到 HUD 我看到了我期望的输出。
我的结果 gDEBugger
【讨论】:
【参考方案2】:您没有完全初始化纹理。在调用glTexImage…
或glTexStorage…
之前,纹理对象不会完全初始化。在将纹理的层/面绑定到 FBO 之前,您必须这样做。同样对于渲染到立方体贴图,您需要创建一个立方体贴图纹理,并且只将其每个面依次绑定到 FBO。
【讨论】:
我为所有纹理调用 glTexImage2D:glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, 512, 512, 0, GL_RGB, GL_FLOAT, nullptr); // Color attachments
, glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, 512, 512, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); // Depth buffer
就立方体贴图部分而言,我确实声明我正在处理的任务要求我们“不使用任何内置的 OpenGL 立方体贴图功能”,即我们必须制作 6 种不同的纹理,然后选择我们要在片段着色器中使用哪一种(效率不高,仅用于学习目的)。以上是关于使用单个 FBO 将单个场景从多个视点绘制到多个纹理中(每个视点 1 个)仅产生一个有效纹理的主要内容,如果未能解决你的问题,请参考以下文章
从单个 jupyter/ipython 单元格绘制多个 python-igraph 图