延迟渲染不能按预期工作

时间:2013-10-09 21:11:47

标签: opengl sdl lighting deferred-rendering

我对opengl和GLSL很有经验。对于我的引擎,我想实现延迟照明,知道它不会是一项微不足道的任务。几个小时后,我得到了大部分工作。这是我呈现的所有缓冲区的屏幕截图:

enter image description here 左上角是法线,右上角是反照率,左下角是位置,右下角是最终渲染。 (现在只有一盏灯正在渲染。) 我使用各种着色器将所有内容渲染到帧缓冲区。我之前使用过前向渲染照明着色器。为了提供相同的结果,我使用来自该顶点着色器的相同数据来渲染不同的缓冲区。与我的前向渲染器不同,光源会根据相机的位置移动和更改。这是顶点着色器的代码(片段只是渲染它们从顶点得到的像素)

位置着色器:

varying vec4 pos;
void main(void)
{
    gl_Position =gl_ModelViewProjectionMatrix*gl_Vertex;
    pos = gl_ModelViewMatrix*gl_Vertex;
}

普通着色器

varying vec3 normal;
void main(void)
{
     gl_Position =gl_ModelViewProjectionMatrix*gl_Vertex;
    normal = normalize(gl_NormalMatrix*gl_Normal);
}

对于反照率,我只使用opengl的常规着色器并绑定纹理。

这是最终的灯光着色器,它在屏幕上呈现为四边形:

uniform sampler2D positionMap;
uniform sampler2D normalMap;
uniform sampler2D albedoMap;
varying vec2 texcoord;
uniform mat4 matrix;
void main()
{
    vec3 position = vec3(texture2D(positionMap,texcoord));
    vec3 normal = vec3(texture2D(normalMap,texcoord));

    vec3 L = normalize(gl_LightSource[0].position.xyz - position);
    float l = length(L)/5.0;
    float att = 1.0/(l*l+l);

    //render sun light
    vec4 diffuselight = max(dot(normal,L), 0.0)*vec4(att,att,att,att);
    diffuselight = clamp(diffuselight, 0.0, 1.0)*2.0;
    vec4 amb = vec4(.2,.2,.2,0);

    vec4 texture = texture2D(albedoMap,texcoord);

    gl_FragColor =  ((diffuselight)+amb)*texture;

}

这里有许多其他地方引用的功能,但我认为你可以从图片和代码中获得一般基础。这是主要的渲染功能:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

//render skybox
glLoadIdentity();
renderSkybox();
//skybox.renderObject();
glLoadIdentity();
renderViewModel();


renderCamera();
glMatrixMode(GL_MODELVIEW);
GLfloat position[] = {-Lighting.x,-Lighting.y,-Lighting.z,1};
glLightfv(GL_LIGHT0, GL_POSITION, position);
glDisable(GL_LIGHTING);

glm::mat4 modelView,projection,final;
glGetFloatv(GL_MODELVIEW_MATRIX, &modelView[0][0]);
glGetFloatv(GL_PROJECTION_MATRIX, &projection[0][0]);
final=modelView*projection;

Lighting.setupDepthImage();
glLoadIdentity();

for (int i = 0; i < objects.size(); i++)
{
   objects[i].renderObjectForDepth();
}
    Lighting.finishDepthImage();

//render the 3 buffers

//normal buffer
glBindFramebuffer(GL_FRAMEBUFFER, Lighting.Normal.frameBuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int i = 0; i < objects.size(); i++)
{
  objects[i].renderObjectWithProgram(Lighting.normalShader);
}
//albedo
glBindFramebuffer(GL_FRAMEBUFFER, Lighting.Albedo.frameBuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int i = 0; i < objects.size(); i++)
{
    objects[i].renderObjectWithProgram(0);
}
//position
glBindFramebuffer(GL_FRAMEBUFFER, Lighting.Position.frameBuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int i = 0; i < objects.size(); i++)
{
    objects[i].renderObjectWithProgram(Lighting.positionShader);
}
//go back to rendering directly to the screen
 glBindFramebuffer(GL_FRAMEBUFFER, 0);


renderCamera();
glTranslatef(-test.position.x, test.position.y, -test.position.z);
test.updateParticle(1);

//render the buffers for debugging
renderViewModel();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1280, 800, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

//render the full screen quad for the sun
glUseProgram(Lighting.sunShader);

glUniform1i(glGetUniformLocation(Lighting.sunShader,"normalMap"),0);
glUniform1i(glGetUniformLocation(Lighting.sunShader,"albedoMap"),1);
glUniform1i(glGetUniformLocation(Lighting.sunShader,"positionMap"),2);
glUniformMatrix4fv(glGetUniformLocation(Lighting.sunShader, "matrix"), 1, GL_FALSE, &final[0][0]);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, Lighting.Normal.texture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, Lighting.Albedo.texture);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, Lighting.Position.texture);




glBindFramebuffer(GL_FRAMEBUFFER, Lighting.debugFinal.frameBuffer);
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex2f(0, 0);
glTexCoord2f(1, 1);
glVertex2f(1280, 0);
glTexCoord2f(1, 0);
glVertex2f(1280, 800);
glTexCoord2f(0, 0);
glVertex2f(0, 800);
glEnd();

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);

glUseProgram(0);
//normals
glBindTexture(GL_TEXTURE_2D,Lighting.Normal.texture);
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex2f(0, 0);
glTexCoord2f(1, 1);
glVertex2f(640, 0);
glTexCoord2f(1, 0);
glVertex2f(640, 400);
glTexCoord2f(0, 0);
glVertex2f(0, 400);
glEnd();
//albedo
glBindTexture(GL_TEXTURE_2D,Lighting.Albedo.texture);
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex2f(640, 0);
glTexCoord2f(1, 1);
glVertex2f(1280, 0);
glTexCoord2f(1, 0);
glVertex2f(1280, 400);
glTexCoord2f(0, 0);
glVertex2f(640, 400);
glEnd();
//position
glBindTexture(GL_TEXTURE_2D,Lighting.Position.texture);
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex2f(0, 400);
glTexCoord2f(1, 1);
glVertex2f(640, 400);
glTexCoord2f(1, 0);
glVertex2f(640, 800);
glTexCoord2f(0, 0);
glVertex2f(0, 800);
glEnd();
//final image
glBindTexture(GL_TEXTURE_2D,Lighting.debugFinal.texture);
glBegin(GL_QUADS);
glTexCoord2f(0, 1);
glVertex2f(640, 400);
glTexCoord2f(1, 1);
glVertex2f(1280, 400);
glTexCoord2f(1, 0);
glVertex2f(1280, 800);
glTexCoord2f(0, 0);
glVertex2f(640, 800);
glEnd();
View3D();



SDL_GL_SwapWindow(window);
glLoadIdentity();

这里有一些不相关的东西,只是忽略它们。如你所见,我使用GLSL的默认方法得到了光的位置。我认为,因为我处于正交视图中,所以有些事情与灯光的位置紧密相关。这可能是问题,还是还有别的东西,也许是在计算法线等等?

1 个答案:

答案 0 :(得分:1)

人们可能不会觉得这很有用,但我已经解决了我的问题。我在着色器中使用常规opengl灯进行照明。当我设置位置时,我将w值设为1,这将使它成为定向光,而不是点光源,因此给出了光线移动的行为。

作为一方,我没有改变从深度缓冲区重建的位置以及其他一些改进G缓冲区的东西。