【发布时间】:2018-06-03 18:58:03
【问题描述】:
我一直在努力将 SSAO 应用到我正在编写的引擎中,但出现了一个主要问题。一切都很顺利,直到我意识到我的 SSAO 工作不正常。我发现我的 SSAO 有两处问题,我不知道如何解决它们。
我的着色器代码在这篇文章的末尾,在此之前我将描述图像的问题。
首先,如下面的屏幕截图所示,根据视角会出现一些奇怪的伪影。到目前为止,我假设我实现 View 矩阵的方式是错误的。我已经对这一切应该如何运作进行了大量研究,并且我在理论上理解它。然而,在实践中,事情并没有像我预期的那样发生变化。
其次,每当我靠近方块时,屏幕边缘都会出现非常奇怪的三角形阴影,如下一个屏幕截图所示。 [![屏幕周围出现奇怪的三角形阴影][2]][2]
这两张图片显示了我遇到的主要问题。我正在使用延迟类型渲染器将几何图形渲染为一些纹理(位置、法线、颜色),然后导入这些纹理并使用它们来操作最终输出。前两个代码块分别是顶点和片段着色器,用于将几何图形转换为纹理。
顶点着色器 #版本 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 着色器。 #版本 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);
}
这就是我最初能想到的所有信息。你们可以提供的任何帮助都会非常有帮助!如果任何其他信息有帮助,请告诉我,我很乐意提供。
编辑: 我发现我的问题之一是我访问上面的一维纹理的方式。这让所有的内核样本都很奇怪。我修复了这个问题,现在我得到了如下图所示的内容,其中一半屏幕较暗,一半屏幕一侧较亮,另一侧较暗。对比线随相机移动。
非常感谢您对此问题的任何帮助!
【问题讨论】:
-
以上所有图像都在另一个通道中通过基本的 4x4 模糊着色器运行。我可以得到一张实际 ssao 输出的图像,它基本上是相同的,但正如人们所期望的那样被点画了。在这个例子中,噪声纹理是 4x4,内核大小是 64。我相信这已经足够了,但也许我需要做更多?
-
好的,我会尝试并报告,谢谢你的可能性。
-
感谢您的建议,在调整了半径并将 ssao 集成到实际的光照引擎中之后,我对上面的结果更加怀疑。我现在的问题是我必须将坐标从视图空间输出到法线并将位置缓冲区更改为世界空间。这导致大量新问题出现在 ssao 的输出中。无论我做什么,我似乎都无法让它看起来正确。
-
我已经添加了一个编辑,对此的任何帮助将不胜感激!
标签: c++11 opengl glsl shader ssao