【发布时间】:2016-09-04 14:23:32
【问题描述】:
我目前正在尝试在 OpenGL 3.2 中实现延迟着色,并且遇到了一个无论我如何尝试都无法解决的问题。
我按照预期分两步(几何传递和光照传递)实现了它。编译并运行它后,屏幕显示了我准备的场景,几乎就像人们期望的那样。物体的颜色是正确的,它们也被放置在我想要的位置和位置。
问题是,光线计算似乎对颜色没有影响,无论如何。很多小时后,我发现位置和法线的纹理似乎包含与颜色纹理相同的内容。
如果将光照片段着色器中的最后一行从fragColor = lightIntensity * color; 更改为fragColor = lightIntensity * norm; 或fragColor = lightIntensity * pos;,它绝对不会影响屏幕的渲染方式。
我已经尝试了很多来找出问题所在,但老实说不知道它可能是什么。
如果有人可以帮助我,那就太好了。
我的渲染方法如下所示:
void render()
{
//geometry pass
gBuffer->bindForWriting();
geometryShader->use(true);
calculateGBuffer();
//lighting pass
gBuffer->bindForReading(lightShader->programID());
lightShader->use(true);
drawOnScreen();
}
gBuffer对象的初始化是这样的:
void GBuffer::initializeFBO(int viewWidth, int viewHeight)
{
//initialize fbo and corresponding textures;
glGenFramebuffers(1, &fbo_ID);
glBindFramebuffer(GL_FRAMEBUFFER, fbo_ID);
glGenTextures(1, &colorTexture_ID);
glBindTexture(GL_TEXTURE_2D, colorTexture_ID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, viewWidth, viewHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture_ID, 0);
glGenTextures(1, &posTexture_ID);
glBindTexture(GL_TEXTURE_2D, posTexture_ID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, viewWidth, viewHeight, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, posTexture_ID, 0);
glGenTextures(1, &normTexture_ID);
glBindTexture(GL_TEXTURE_2D, normTexture_ID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, viewWidth, viewHeight, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, normTexture_ID, 0);
GLuint attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, attachments);
glGenRenderbuffers(1, &depthBuffer_ID);
glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer_ID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, viewWidth, viewHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer_ID);
//Check Status
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
qDebug() << "error while initializing framebuffer" << glCheckFramebufferStatus(GL_FRAMEBUFFER);
else{
qDebug() << "framebuffer successfully created";
initialized = true;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
bindForReading 和 bindForWriting 方法:
void GBuffer::bindForWriting()
{
glBindFramebuffer(GL_FRAMEBUFFER, fbo_ID);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void GBuffer::bindForReading(GLuint programID)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, colorTexture_ID);
GLuint samplerTexture_ID = glGetUniformLocation(programID, "colorTexture");
glUniform1i(samplerTexture_ID, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, posTexture_ID);
samplerTexture_ID = glGetUniformLocation(programID, "positionTexture");
glUniform1i(samplerTexture_ID, 1);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, normTexture_ID);
samplerTexture_ID = glGetUniformLocation(programID, "normTexture");
glUniform1i(samplerTexture_ID, 2);
}
最后还有 4 个着色器:
几何顶点着色器:
#version 150
#extension GL_ARB_separate_shader_objects : enable
uniform mat4 MVPMatrix;
uniform mat4 modelMatrix;
in vec4 in_position;
in vec4 in_color;
in vec2 in_texcoord;
in vec3 in_norm;
out vec4 color_varying;
out vec3 frag_position;
out vec3 norm_vec;
out vec2 texcoord_varying;
void main()
{
gl_Position = MVPMatrix * in_position;
vec4 worldPosition = (modelMatrix * in_position);
frag_position = worldPosition.xyz;
norm_vec = in_norm;
color_varying = in_color;
texcoord_varying = in_texcoord;
}
几何片段着色器:
#version 150
#extension GL_ARB_explicit_attrib_location : enable
in vec4 color_varying;
in vec3 frag_position;
in vec3 norm_vec;
in vec2 texcoord_varying;
layout (location = 0) out vec4 fragColor;
layout (location = 1) out vec3 fragPosition;
layout (location = 2) out vec3 frag_norm_vec;
uniform sampler2D myTexture;
void main()
{
vec4 texel = texture(myTexture, texcoord_varying);
fragColor = texel * color_varying;
fragPosition = frag_position;
frag_norm_vec = normalize(norm_vec);
}
光照顶点着色器:
#version 150
#extension GL_ARB_explicit_attrib_location : enable
layout (location = 0) in vec2 in_position;
out vec2 texCoord;
void main()
{
gl_Position = vec4(in_position, 0, 1.0f);
texCoord = in_position;
if(texCoord.x == -1.0f)
texCoord.x = 0.0f;
if(texCoord.y == -1.0f)
texCoord.y = 0.0f;
}
Lighting Fragment Shader(没有光照计算使其更短)
#version 150
#extension GL_ARB_separate_shader_objects : enable
out vec4 fragColor;
in vec2 texCoord;
uniform sampler2D colorTexture;
uniform sampler2D positionTexture;
uniform sampler2D normTexture;
void main()
{
//extract fragment data from fbo
vec3 pos = texture(positionTexture, texCoord).rgb;
vec3 norm = texture(normTexture, texCoord).rgb;
vec4 color = texture(colorTexture, texCoord);
fragColor = lightIntensity * color;
}
为代码垃圾邮件道歉,但我无法缩小错误范围。
【问题讨论】:
-
"几何顶点着色器:" 小心在“着色器”旁边使用“几何”等术语。因为我们有一个着色器阶段,我第一次读到这个名字让我觉得这就是你使用的。
-
"OpenGL 3.1" 那么为什么你的着色器使用
#version 150?那是从 GL 3.2 开始的。这不是你的问题,但你应该清楚你使用的是什么版本的 OpenGL。 -
哦.. 当然我是在 3.2 版下开发的,我编辑过。
-
“几何着色器”这个词有什么问题?着色器不只是在 gpu 上运行的程序吗?在那种情况下,它正在计算场景的几何形状?
-
因为术语“Geometry Shader”是为特定的着色器阶段保留的。这是一种独立于顶点着色器和片段着色器的着色器。 OpenGL 3.2 是他们进入核心 OpenGL 的第一个版本,所以你可以一直在谈论/使用它。