如何使用OpenGL渲染到多个纹理
How To Render To Multiple Textures With OpenGL?
这是我对渲染到多个纹理的基本步骤的理解。
1) 绑定着色器位置以在处渲染
m_uihDiffuseMap = glGetUniformLocation( m_iShaderProgramHandle, "diffuseMap" );
if( m_uihDiffuseMap != -1 )
glUniform1i( m_uihDiffuseMap, 0 );
m_uihNormalMap = glGetUniformLocation( m_iShaderProgramHandle, "normalMap" );
if( m_uihNormalMap != -1 )
glUniform1i( m_uihNormalMap, 1 );
2) 绑定到要渲染到的内容
glBindFramebuffer( GL_FRAMEBUFFER, m_uifboHandle );
//diffuse texture binding
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_uiTextureHandle1, 0);
//normal texture binding
(or GL_COLOR_ATTACHMENT1)
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+1, m_uiTextureHandle2, 0);
3) 清除缓冲区&指定要提取到的缓冲区
glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, buffers);
4) 设置渲染的着色器程序
glUseProgram( m_uiShaderProgramHandle );
5) 将变量传递到着色器,如我们的2种不同纹理
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, uihDiffuseMap );
//or(GL_TEXTURE1)
glActiveTexture( GL_TEXTURE0+1 );
glBindTexture( GL_TEXTURE_2D, uihNormalMap );
6) 进行渲染调用
//Draw stuff
7) 如果您有其他使用的渲染过程,请将其设置回默认值
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glUseProgram( 0 );
------------------------------碎片着色器-------------------------------
在片段着色器中,你必须像这样输出2个结果,对吗?
#version 330
in vec2 vTexCoordVary;
uniform sampler2D diffuseMap;
uniform sampler2D normalMap;
out vec4 fragColor[2];
void main( void )
{
fragColor[0] = texture( diffuseMap, vTexCoordVary );
fragColor[1] = texture( normalMap, vTexCoordVary );
};
我已仔细检查
-我的漫反射纹理和法线纹理加载良好。如果我将我的法线纹理作为要用作TEXTURE0的纹理,它将显示出来。-我得到fragColor[0]很好。当我在屏幕上显示fragColor[1]时,我得到了与第一个相同的结果。但我也对fragColor[1]进行了硬编码,以返回着色器内部的纯灰色作为测试用例,它起到了作用。
所以我的假设是,当我将纹理传递给着色器时,它会假设"normalMap"是"diffuseMap"?这是我唯一理解的为什么我会在fragColor[0]和[1]中得到相同的结果。
是的,到目前为止,采样器如何映射到纹理槽的信息丢失,导致两者都引用漫反射贴图。使用glUniform1i()
将正确纹理的索引绑定到每个统一槽。
看起来步骤1和步骤4的顺序不对。这是在步骤1:
if( m_uihDiffuseMap != -1 )
glUniform1i( m_uihDiffuseMap, 0 );
if( m_uihNormalMap != -1 )
glUniform1i( m_uihNormalMap, 1 );
在步骤4:
glUseProgram( m_uiShaderProgramHandle );
glUniform*()
调用适用于当前活动程序。因此,必须在glUniform1i()
调用之前调用glUseProgram()
。
专门设置out
变量的位置也是一个好主意:
layout(location = 0) out vec4 fragColor[2];
我不认为这会导致您的问题,但我在规范中没有看到任何内容表明,如果没有明确指定位置,链接器会分配从0开始的位置。
如果有人像我一样通过搜索引擎偶然发现这里,我在写入多个纹理时遇到的问题是打字错误。我的帧缓冲区初始化代码如下:
glGenFramebuffers(1, &renderer.gbufferFboId);
glBindFramebuffer(GL_FRAMEBUFFER, renderer.gbufferFboId);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, renderer.gbufferDepthTexId, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderer.gbufferColorPositionId, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, renderer.gbufferColorColorId, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, renderer.gbufferColorNormalId, 0);
opengl::fbo_check_current_status();
const GLenum drawBuffers[]
{
GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2
};
glDrawBuffers(1, drawBuffers);
你能发现错误吗?这是glDrawBuffer
调用中的一个小拼写错误。它当然应该相当于缓冲区的数量:
glDrawBuffers(3, drawBuffers);
- 使用 CUDA 和纹理进行图像减法
- 在不使用统一的情况下将纹理传递给 GLSL 着色器?
- 将使用太多的纹理插值器 - 带旋转的着色器
- 如何使用 DXGI 格式DXGI_FORMAT_R1_UNORM创建 2D 纹理?
- 使用 C++在 OpenGL 中对 3D 多边形进行纹理处理
- SFML 纹理使用问题
- SDL + OpenGL ES 2.0 使用着色器显示纹理
- 使用 assimp 获取纹理比例
- Assimp - 如何使用任何文件格式导入带有纹理的网格?
- 使用程序生成来创建磁盘,但纹理无法正常工作
- 如何使用 openGL 在屏幕上显示加载的纹理
- 使用片段着色器写入 1D 纹理后从 1D 纹理读回不起作用
- 使用 SDL2 操作硬件纹理
- 如何在 Opengl 中使用多个纹理解决此问题
- 如何使用着色器在 opengl es 中渲染四边形内部的部分纹理
- 如何使用Qt多媒体和C++将.mp4视频从OpenGL纹理中保存出来
- 在 SFML 中不使用动态内存时显示白色纹理代替实际纹理
- 使用两个纹理 SDL2 显示视频
- OpenGL 纹理状态使用警告:
- OpenGL在纹理上使用着色器