我在使用 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);
}
我希望有人知道这里发生了什么,提前谢谢!