0

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

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

在此处输入图像描述

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

使用 NSight 查看应该是红色(或与蓝光像素混合)的线旁边的像素的历史,我可以看到: 在此处输入图像描述

所以像素实际上被红光着色,但随后又变回蓝色,我真的不明白为什么。

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

//
//  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 是一个二十面体球体网格)

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);
}

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

4

1 回答 1

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
// ...
//
于 2015-03-05T10:01:17.553 回答