我按照屏幕空间环境光遮蔽 (SSAO) 的教程进行操作,但似乎有些东西没有按应有的方式工作。
正如您从屏幕截图中看到的,在环境光遮蔽最明显的较暗区域中有一些图案。
我怀疑示例内核有问题,但我严格按照教程进行操作。唯一的区别是我还考虑调整窗口大小和相机的移动。
这些是相关的代码片段。
SSAO 顶点着色器
#version 450 core
out VertData
{
smooth vec2 texcoord;
} vert;
void main()
{
switch (gl_VertexID)
{
case 0:
vert.texcoord = vec2(0.0f, 0.0f);
break;
case 1:
vert.texcoord = vec2(0.0f, 1.0f);
break;
case 2:
vert.texcoord = vec2(1.0f, 0.0f);
break;
case 3:
vert.texcoord = vec2(1.0f, 1.0f);
break;
}
vec2 position = vert.texcoord * 2.0f - 1.0f;
gl_Position = vec4(position, 0.0f, 1.0f);
}
SSAO 片段着色器
#version 450 core
struct FragData {
vec3 position;
vec3 normal;
vec3 noise;
};
uniform sampler2D position;
uniform sampler2D normal;
uniform sampler2D KernelTexture;
uniform sampler2D noise;
in VertData
{
smooth vec2 texcoord;
} vert;
out float occlusion;
uniform int KernelSize;
uniform vec2 NoiseScale;
uniform float radius;
uniform float bias;
uniform mat4 projection;
void main()
{
FragData frag;
frag.position = texture(position, vert.texcoord).xyz;
frag.normal = normalize(texture(normal, vert.texcoord).xyz);
frag.noise = normalize(texture(noise, vert.texcoord * NoiseScale).xyz);
// TBN matrix
vec3 tangent = normalize(frag.noise - frag.normal * dot(frag.noise, frag.normal));
vec3 bitangent = cross(frag.normal, tangent);
mat3 TBN = mat3(tangent, bitangent, frag.normal);
occlusion = 0.0f;
for(int i = 0; i < KernelSize; i++)
{
float x = float(i) / float(KernelSize);
for(int j = 0; j < KernelSize; j++)
{
float y = float(j) / float(KernelSize);
vec3 MySample = TBN * texture(KernelTexture, vec2(x, y)).xyz;
MySample = frag.position + MySample * radius;
vec4 offset = vec4(MySample, 1.0f);
offset = projection * offset;
offset.xyz /= offset.w;
offset.xyz = offset.xyz * 0.5f + 0.5f;
float depth = texture(position, offset.xy).z;
float range = smoothstep(0.0f, 1.0f, radius / abs(frag.position.z - depth));
occlusion += ((depth >= MySample.z + bias) ? 1.0f : 0.0f) * range;
}
}
occlusion = 1.0f - (occlusion / float(KernelSize * KernelSize));
}
内核配置
void setKernel()
{
auto lerp = [] (float a, float b, float f)
{
return a + f * (b - a);
};
kernel.clear();
for (int i = 0; i < KernelSize * KernelSize; i++)
{
float x = RandomZeroOne();
float y = RandomZeroOne();
float z = RandomZeroOne();
QVector3D sample = { x * 2.0f - 1.0f, y * 2.0f - 1.0f, z };
sample.normalize();
sample *= RandomZeroOne();
float scale = static_cast<float>(i) / static_cast<float>(KernelSize);
scale = lerp(0.1f, 1.0f, scale * scale);
sample *= scale;
kernel.append(sample);
}
}
void setKernelTexture()
{
glBindTexture(GL_TEXTURE_2D, textures[TextureIndex::KERNEL]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, KernelSize, KernelSize, 0, GL_RGB, GL_FLOAT, &(kernel[0]));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
==================== 更新====================
我想我找到了问题所在。调整窗口大小时,我没有更新 NoiseScale。
void resizeGL(int w, int h)
{
/* ... */
// now updating NoiseScale
NoiseScale.setX(static_cast<float>(geometry().width()));
NoiseScale.setY(static_cast<float>(geometry().height()));
NoiseScale /= static_cast<float>(NoiseSize);
/* ... */
}
这是结果:
但是现在性能很差。使用 64 个样本内核和 4x4 噪声矩阵,我得到 3-4 fps 的帧速率。
我怎样才能提高性能?谢谢!