我终于让我的 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 和/或所有其他处理。