延迟渲染奇怪的行为

时间:2015-03-04 19:42:52

标签: opengl deferred-rendering

我在使用OpenGL实现延迟渲染引擎时遇到一些麻烦。 我可以渲染到纹理,所有数据都适用于第一遍(计算反照率,法线和深度),但是当计算闪电的纹理(发射和镜面反射)时,我有一些麻烦。< / p>

这是我到目前为止所得到的:

enter image description here

问题是,正如你可能已经猜到的那样,那条线显示出我的红光和蓝光之间的某种划分。

使用NSight查看应该是红色(或与蓝色光像素混合)的行旁边的像素的历史记录,我可以看到: enter image description here

因此,像素IS实际上被红灯染色,但随后又变回蓝色,我真的无法理解为什么。

这是我用来做延迟绘图的代码:

//
//  Preparing albedo, normals and depth
//
GetGBuffer("PrepassBuffer")->BindAsRenderTarget();
Start(stage);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);

DeferredPreparePass(stage, shadersManager->GetProgramFromName("deferred-prepare"));
Finish(stage);

//
//  Peparing light emissive and specular textures
//
GetGBuffer("LightsBuffer")->BindAsRenderTarget();
Start(stage);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);

DeferredPointPass(stage, shadersManager->GetProgramFromName("deferred-point"));
glCullFace(GL_BACK);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Finish(stage);

//
//  Final composition of the image
//
Start(stage);   
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

DeferredCombinePass(stage, shadersManager->GetProgramFromName("deferred-combine"));
Finish(stage);

这是我用来做点光传递的代码(上面的DeferredPointPass函数调用)(_ pointLightMesh是Icosahedron Sphere网格)

for (ASizeT i = 0; i < nLights; i++)
{
    AnimaLight* light = lightsManager->GetLight((AUint)i);
    if (!light->IsPointLight())
        continue;

    AnimaVertex3f lPos = light->GetPosition();
    AFloat range = light->GetRange();

    AnimaMatrix m1, m2, m3;
    m1.Translate(lPos);
    m2.Scale(range, range, range, 1.0f);
    m3 = m1 * m2;

    float dist = (lPos - activeCamera->GetPosition()).Length();
    if (dist < light->GetRange())
        glCullFace(GL_FRONT);
    else
        glCullFace(GL_BACK);

    program->UpdateLightProperies(light);
    program->UpdateMeshProperies(_pointLightMesh, m3);
    program->UpdateRenderingManagerProperies(this);

    program->EnableInputs(_pointLightMesh);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _pointLightMesh->GetIndexesBufferObject());
    glDrawElements(GL_TRIANGLES, _pointLightMesh->GetFacesIndicesCount(), GL_UNSIGNED_INT, 0);
    program->DisableInputs();
}

这是我用来计算点光源传递的发光和高光贴图的着色器:

#version 150 core

in mat4 frag_inverseProjectionViewMatrix;
out vec4 FragColor[2];

uniform sampler2D REN_GB_PrepassBuffer_DepthMap;
uniform sampler2D REN_GB_PrepassBuffer_NormalMap;
uniform vec2 REN_InverseScreenSize;
uniform vec3 CAM_Position;

uniform float PTL_Range;
uniform vec3 PTL_Position;
uniform vec3 PTL_Color;
uniform float PTL_ConstantAttenuation;
uniform float PTL_LinearAttenuation;
uniform float PTL_ExponentAttenuation;

void main()
{
vec3 pos    = vec3((gl_FragCoord.x * REN_InverseScreenSize.x), (gl_FragCoord.y * REN_InverseScreenSize.y), 0.0f);
pos.z       = texture(REN_GB_PrepassBuffer_DepthMap, pos.xy).r;

vec3 normal = normalize(texture(REN_GB_PrepassBuffer_NormalMap, pos.xy).xyz * 2.0f - 1.0f);
vec4 clip   = frag_inverseProjectionViewMatrix * vec4(pos * 2.0f - 1.0f, 1.0f);
pos         = clip.xyz / clip.w;

float dist  = length(PTL_Position - pos);

if(dist > PTL_Range)
{
    discard;
}

float atten = (PTL_ConstantAttenuation + PTL_LinearAttenuation * dist +  PTL_ExponentAttenuation * dist * dist + 0.00001);

vec3 incident   = normalize(PTL_Position - pos);
vec3 viewDir    = normalize(CAM_Position - pos);
vec3 halfDir    = normalize(incident + viewDir);

float lambert   = clamp(dot(incident, normal), 0.0f, 1.0f);
float rFactor   = clamp(dot(halfDir, normal), 0.0f, 1.0f);
float sFactor   = pow(rFactor, 33.0f);

FragColor[0] = vec4(PTL_Color * lambert / atten, 1.0f);
FragColor[1] = vec4(PTL_Color * sFactor / atten * 0.33f, 1.0f);
}

我希望有人知道这里发生了什么,提前谢谢!

1 个答案:

答案 0 :(得分:0)

好的,我发现了我所缺少的东西。我需要在执行点光通过之前禁用深度测试,并重新启用它以组合最终图像。

我的延迟渲染函数的代码现在看起来像这样(其余的仍然是相同的):

// Same as before
// ...
//

//
//  Peparing light emissive and specular textures
//
GetGBuffer("LightsBuffer")->BindAsRenderTarget();
Start(stage);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glDepthMask(GL_FALSE);  // <---- this is what I was missing

DeferredPointPass(stage, shadersManager->GetProgramFromName("deferred-point"));
glCullFace(GL_BACK);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthMask(GL_TRUE);   // <---- this is what I was missing
Finish(stage);

// Same as before
// ...
//