使用 SSAO Opengl 实现有一些奇怪的伪影和奇怪的三角形阴影

Having some wierd artifacting and odd triangle shadows with SSAO Opengl Implmentation

我一直在努力将 SSAO 实现到我正在编写的引擎中,但一个主要问题出现了。一切都进行得很顺利,直到我意识到我的 SSAO 无法正常工作。我发现我的 SSAO 有两处错误,我不知道如何补救它们。

我的着色器代码在这个 post 的末尾,在此之前我将描述图像的问题。

首先,如下面的屏幕截图所示,根据视角会出现一些奇怪的瑕疵。到目前为止,我假设我实现视图矩阵的方式是错误的。我已经对这一切应该如何运作进行了大量研究,并且我在理论上理解它。然而,实际上事情并没有像我预期的那样改变。

其次,每当我靠近方块时,屏幕边缘就会出现非常奇怪的三角形阴影,如下一个屏幕截图所示。 [![屏幕周围出现奇怪的三角形阴影][2]][2]

这两张图片显示了我遇到的主要问题。我正在使用延迟类型渲染器将几何图形渲染为一些纹理(位置、法线、颜色),然后导入这些纹理并使用它们来操纵最终输出。前两个代码块分别是顶点着色器和片段着色器,用于将几何图形转换为纹理。

顶点着色器 #version 430 核心

layout(location=0) in mat4 modelMatrix;
layout(location=4) in vec4 VertexPosition;
layout(location=5) in vec4 VertexNormal;
layout(location=6) in vec3 VertexColor;
layout(location=7) in vec2 TextureCoords;
out vec4 vNormal;
out vec3 vColor;
out vec4 shaderCoord;
out vec2 texCoords;

layout(location=8) uniform mat4 V;
layout(location=12) uniform mat4 P;



void main()
{

    shaderCoord = (V*modelMatrix * VertexPosition);

     mat4 normalMatrix = transpose(inverse(V*modelMatrix));
    vNormal = (normalMatrix*VertexNormal);

    texCoords = TextureCoords;
    vColor = VertexColor;
    gl_Position =  P*shaderCoord;
}

片段着色器

#version 430 core

in vec4 vNormal;
in vec3 vColor;
in vec4 shaderCoord;
in vec2 texCoords;
layout (location=0) out vec4 NormalBuffer;
layout (location=1) out vec4 ColorBuffer;
layout (location=2) out vec4 PositionBuffer;
layout (location=3) out vec4 TextureCoordBuffer;
out float fragDepth;

//Start of the main function.
void main()
{   
    NormalBuffer = vec4(normalize(vNormal).xyz, 1.0);
    ColorBuffer = vec4(vColor, 1.0);
    PositionBuffer = vec4(shaderCoord.xyz, 1.0);
    TextureCoordBuffer = vec4(texCoords, 0.0, 1.0);
    fragDepth = gl_FragCoord.z;
}

如您所见,在将它们写入纹理之前,我正在翻译从世界 space 到视图 space 的所有内容。我更愿意将它们保留在世界中 space 但是当我这样做时,整个屏幕看起来都是白色的,偶尔会有阴影的迹象,但背景会根据相机角度在白色和黑色之间切换。

接下来是我的 SSAO 着色器,为了实现这些我遵循了一些教程,所以它们看起来可能很熟悉。如果教程是正确的,接下来的两个着色器应该可以正常工作,但它们不是。

仅创建四边形并将最终纹理应用于其的 Vetex 着色器。 #version 430 核心

layout (location=0) in vec3 VertexPosition;
layout (location=1) in vec2 TextureCoords;

out vec2 texCoords;

void main (){
    texCoords = TextureCoords;
    gl_Position = vec4(VertexPosition, 1.0);
}

SSAO 的片段着色器

#version 430 core

in vec2 texCoords;

layout (location=0) out vec4 fColor;

uniform sampler2D NormalBuffer;
uniform sampler2D positionBuffer;

uniform sampler2DArrayShadow shadowMap;
uniform sampler1D SSAOKernelMap;
uniform sampler2D SSAONoiseMap; 

layout(location=12) uniform mat4 P;
layout(location=8) uniform mat4 V;

uniform uint kernelSize;
uniform vec2 windowSize;

//Define Variables for SSAO Processing.
float radius = 0.5;
float SSAOBias = 0.025;
float power = 1.5;
//mat4 biasMatrix = mat4(0.5,0.0,0.0,0.0,0.0,0.5,0.0,0.0,0.0,0.0,0.5,0.0,0.5,0.5,0.5,1.0);

void main()
{   
    //Retrieve from textures
    vec3 shaderCoord = (texture(positionBuffer, texCoords)).xyz;
    vec3 vNormal = normalize((texture(NormalBuffer, texCoords)).rgb);
    //process SSAO
    vec2 NoiseScale = vec2(windowSize.x/4.0, windowSize.y/4.0);
    vec3 randVec = normalize(texture(SSAONoiseMap, texCoords*NoiseScale).xyz);

    vec3 tangent = normalize(randVec - vNormal * dot(randVec, vNormal));
    vec3 bitTangent = cross(vNormal, tangent);
    mat3 TBN = mat3(tangent, bitTangent, vNormal);

    //Begin Processing of SSAO with inputed Kernel Samples
    float Occlusion = 0.0;
    for(int i=0; i<kernelSize; i++){
        vec4 kernelSample = texture(SSAOKernelMap, i);
        vec3 TSample = TBN*kernelSample.rgb;
        TSample = shaderCoord + TSample * radius;

        vec4 newCoord = vec4(TSample, 1.0);
        newCoord = P*newCoord;
        newCoord.xyz /= newCoord.w;
        newCoord.xyz = newCoord.xyz * 0.5 + 0.5;


        float sampleDepth = texture(positionBuffer,newCoord.xy).z;
        //float rangeCheck = smoothstep(0.0,1.0, radius / abs(shaderCoord.z-sampleDepth));
        Occlusion += (sampleDepth >= TSample.z+SSAOBias?1.0:0.0);
    }
    Occlusion =  1.0 - (Occlusion/kernelSize);
    fColor = vec4(vec3(Occlusion),1.0f);
}

这就是我最初能想到的所有信息。你们可以提供的任何帮助都会非常有帮助!如果任何其他信息有帮助,请告诉我,我很乐意提供。

编辑: 我发现我的问题之一是我访问上面的 1D 纹理的方式。这让所有的内核样本都变得非常奇怪。我解决了这个问题,现在我得到了如下图所示的效果,其中一半屏幕较暗,一半屏幕一侧较亮,另一侧较暗。对比线随相机移动。

非常感谢任何对此问题的帮助!

我发现了两件错误的事情,它们主要解决了当前 post 所涉及的问题。

首先,我在 kernelMap 中传递的格式已关闭,因此所有值都非常不正确。

其次,我无法弄清楚为什么,但是当我将位置和法线值传递给世界 space 中的 Lightingfragment 着色器,然后将视图和投影矩阵应用于它们时,它们会变得非常奇怪的是。但是,如果我将视图和投影矩阵应用到 BaseGeometry 着色器中的位置和法线值,然后在光照着色器中恢复该应用程序,一切正常。

如果我找到更多信息,我会很乐意 post 在这里更新任何未来的搜索者。