使用SSAO Opengl Implmentation

时间:2018-06-03 18:58:04

标签: c++11 opengl glsl shader ssao

我一直在努力将SSAO应用到我正在编写的引擎中,并且出现了一个重大问题。在我意识到我的SSAO工作不正常之前,一切都很顺利。我发现有两件事我的SSAO错了,我无法弄清楚如何补救它们。

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

首先,如下面的屏幕截图所示,根据观看角度出现了一些奇怪的文物。到目前为止,我假设我实现View矩阵的方式是错误的。我已经做了很多关于这一切应该如何工作的研究,我在理论上理解它。然而,在实践中事​​情并没有像我期望的那样改变。 Strange artifacting on ssao shader.

其次,每当我接近块时,我会在屏幕边缘出现非常奇怪的三角形阴影,如下一个屏幕截图所示。 [![屏幕周围的奇数三角形阴影] [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;
}

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

接下来是我的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纹理的方式。这使得所有内核样本都非常奇怪。我修好了,现在我得到的东西就像下面的图片,其中一半的屏幕较暗,一半的屏幕在一侧较亮而在另一侧较暗。对比线随相机移动。 Wierd line

对此问题的任何帮助都会非常感激!

1 个答案:

答案 0 :(得分:0)

我发现有两处错误,这些错误大部分可以解决当前帖子所涉及的问题。

首先,我在kernelMap中传递的格式已关闭,因此所有值都偏斜了。

第二,我无法弄清楚为什么,但是当我将位置和法线值传递给世界空间中的Lightingfragment着色器,然后将视图矩阵和投影矩阵应用于它们时,结果会很奇怪。但是,如果我将视图矩阵和投影矩阵应用于BaseGeometry着色器中的位置和法线值,然后将其还原到Lighting着色器中,则一切运行正常。

如果我发现更多信息,我会很乐意在这里发布以更新任何将来的搜索者。