【发布时间】:2013-09-13 01:22:37
【问题描述】:
我终于让我的 GBuffer 工作了(不是真的),但现在我遇到了一些奇怪的问题,我不知道为什么。
当我在屏幕上绘制法线纹理时,法线总是显示给我(蓝色总是指向相机)。我不知道如何正确解释,所以这里有一些屏幕:
(我认为这就是为什么我的光照通道看起来很奇怪的问题)
这是我创建 GBuffer 的方法:
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
// generate texture object
glGenTextures(GBUFFER_NUM_TEXTURES, textures);
for (unsigned int i = 0; i < 4; i++)
{
glBindTexture(GL_TEXTURE_2D, textures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, textures[i], 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
// generate depth texture object
glGenTextures(1, &depthStencilTexture);
glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT,NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthStencilTexture, 0);
// generate output texture object
glGenTextures(1, &outputTexture);
glBindTexture(GL_TEXTURE_2D, outputTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, outputTexture, 0);
GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(Status == GL_FRAMEBUFFER_COMPLETE);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
这里是几何通道:
glEnable(GL_DEPTH_TEST);
glDepthMask(true);
glCullFace(GL_BACK);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
GLenum DrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
glDrawBuffers(GBUFFER_NUM_TEXTURES, DrawBuffers);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
camera.Render();
geoProgram->Use();
GLfloat mat[16];
glPushMatrix();
glTranslatef(0,0,-20);
glRotatef(rot, 1.0, 0, 0);
glGetFloatv(GL_MODELVIEW_MATRIX,mat);
glUniformMatrix4fv(worldMatrixLocation, 1, GL_FALSE, mat);
glutSolidCube(5);
glPopMatrix();
glPushMatrix();
glTranslatef(0,0,0);
glGetFloatv(GL_MODELVIEW_MATRIX,mat);
glUniformMatrix4fv(worldMatrixLocation, 1, GL_FALSE, mat);
gluSphere(sphere, 3.0, 20, 20);
glPopMatrix();
glDepthMask(false);
glDisable(GL_DEPTH_TEST);
这里是几何通道着色器:
[Vertex]
varying vec3 normal;
varying vec4 position;
uniform mat4 worldMatrix;
void main( void )
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
position = worldMatrix * gl_Vertex;
normal = (worldMatrix * vec4(gl_Normal, 0.0)).xyz;
gl_TexCoord[0]=gl_MultiTexCoord0;
}
[Fragment]
varying vec3 normal;
varying vec4 position;
void main( void )
{
gl_FragData[0] = vec4(0.5, 0.5, 0.5, 1);//gl_Color;
gl_FragData[1] = position;
gl_FragData[2] = vec4(normalize(normal),0);
gl_FragData[3] = vec4(gl_TexCoord[0].st, 0, 0);
}
抱歉,问题/代码片段太长,但我不知道下一步该做什么,我用其他 GBuffer 实现检查了所有内容,但找不到错误。
//编辑:
好吧,看来你是对的,问题不在于 gbuffer,而在于光照通道。我玩了很多,但不能让它工作:(
这是光照通道:
[vs]
void main( void )
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
[fs]
uniform sampler2D colorMap;
uniform sampler2D positionMap;
uniform sampler2D normalMap;
uniform sampler2D texcoordMap;
uniform vec2 screenSize;
uniform vec3 pointLightPostion;
uniform vec3 pointLightColor;
uniform float pointLightRadius;
void main( void )
{
float lightDiffuse = 0.5;
float lightSpecular = 0.7;
vec3 lightAttenuation = vec3(1.4, 0.045, 0.00075);
vec2 TexCoord = gl_FragCoord.xy / screenSize.xy;
vec3 WorldPos = texture2D(positionMap, TexCoord).xyz;
vec3 Color = texture(colorMap, TexCoord).xyz;
vec3 normal = texture(normalMap, TexCoord).xyz;
normal = normalize(normal);
vec3 lightVector = WorldPos - pointLightPostion;
float dist = length(lightVector);
lightVector = normalize(lightVector);
float nDotL = max(dot(normal, lightVector), 0.0);
vec3 halfVector = normalize(lightVector - WorldPos);
float nDotHV = max(dot(normal, halfVector), 0.0);
vec3 lightColor = pointLightColor;
vec3 diffuse = lightDiffuse * nDotL;
vec3 specular = lightSpecular * pow(nDotHV, 1.0) * nDotL;
lightColor += diffuse + specular;
float attenuation = clamp(1.0 / (lightAttenuation.x + lightAttenuation.y * dist + lightAttenuation.z * dist * dist), 0.0, 1.0);
gl_FragColor = vec4(vec3(Color * lightColor * attenuation), 1.0);
}
如有必要,我还可以发布 sencil pass 和/或所有其他处理。
【问题讨论】:
-
右上角是纹理位置,左下角是反照率。目前我只为球体设置了纹理位置,反照率只是纯色
-
好吧,我觉得一切正常。实际问题是什么?顺便说一句,如果您想减少必须渲染到的缓冲区数量(节省内存并提高帧速率),您应该将反照率系数写入普通缓冲区的 alpha 通道。并且不要费心将法线/反照率存储在 FP16 中,RGBA8 应该适用于除位置之外的所有内容。
-
法线总是指向你,因为它们在视图空间中,如果这是你的问题?如果您不费心将它们乘以“worldMatrix”,您总是可以将它们放在世界空间中。但是你需要对它们进行偏置和缩放,因为一些法线会指向负方向。
-
即使有图片,我仍然没有遇到您实际遇到的问题(撇开正确的图像实际编码的内容不谈)。正常的图像对我来说看起来很合理。
-
可能“我的光照通道看起来很奇怪的问题”在光照通道中,因为你的 G 通道在每个人看来都很好。请注意您正在使用的空间。您对位置和法线使用相同的矩阵,因此它们都在视图空间中(这很好)。因此,在您的光照通道中,所有内容都必须在视图空间中(例如灯光的位置)。
标签: opengl glsl shader deferred-shading