这是我用来渲染场景的过程:
以下是我的着色器(其中实现了 SSAO,但似乎与此无关)。
- 绑定 MSAA x4 GBuffer(4个颜色附件,位置、法线、颜色和非光照颜色(仅天空盒)。我还有一个深度组件/纹理)。
- 绘制天空盒
- 绘制几何体
- 将所有颜色和深度组件合并到一个单样本 FBO 中
- 应用光照(我使用深度纹理检查是否应该被照亮,通过检查深度纹理值是否小于1)。
- 渲染四边形
以下是我的着色器(其中实现了 SSAO,但似乎与此无关)。
#version 410 core
in vec2 Texcoord;
out vec4 outColor;
uniform sampler2D texFramebuffer;
uniform sampler2D ssaoTex;
uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedo;
uniform sampler2D gAlbedoUnlit;
uniform sampler2D gDepth;
uniform mat4 View;
struct Light {
vec3 Pos;
vec3 Color;
float Linear;
float Quadratic;
float Radius;
};
const int MAX_LIGHTS = 32;
uniform Light lights[MAX_LIGHTS];
uniform vec3 viewPos;
uniform bool SSAO;
void main()
{
vec3 color = texture(gAlbedo, Texcoord).rgb;
vec3 colorUnlit = texture(gAlbedoUnlit, Texcoord).rgb;
vec3 pos = texture(gPosition, Texcoord).rgb;
vec3 norm = normalize(texture( gNormal, Texcoord)).rgb;
vec3 depth = texture(gDepth, Texcoord).rgb;
float ssaoValue = texture(ssaoTex, Texcoord).r;
// then calculate lighting as usual
vec3 lighting;
if(SSAO)
{
lighting = vec3(0.3 * color.rgb * ssaoValue); // hard-coded ambient component
}
else
{
lighting = vec3(0.3 * color.rgb); // hard-coded ambient component
}
vec3 posWorld = pos.rgb;
vec3 viewDir = normalize(viewPos - posWorld);
for(int i = 0; i < MAX_LIGHTS; ++i)
{
vec4 lightPos = View * vec4(lights[i].Pos,1.0);
vec3 normLight = normalize(lightPos.xyz);
float distance = length(lightPos.xyz - posWorld);
if(distance < lights[i].Radius)
{
// diffuse
vec3 lightDir = normalize(lightPos.xyz - posWorld);
vec3 diffuse = max(dot(norm.rgb, lightDir), 0.0) * color.rgb *
lights[i].Color;
float attenuation = 1.0 / (1.0 + lights[i].Linear * distance + lights[i].Quadratic * distance * distance);
lighting += (diffuse*attenuation);
}
}
if(depth.r >= 1)
{
outColor = vec4(colorUnlit, 1.0);
}
else
{
outColor = vec4(lighting, 1.0);
}
}
所以,最后一个if语句检查它是否在深度纹理中,如果是,则应用光照,如果不是,则只绘制天空盒(这样就不会对天空盒应用光照)。
我已经花了几天时间尝试解决这个问题,改变了检查是否需要光照的方式,比较法线、位置和深度,将格式更改为更高的分辨率(例如使用RGB16F而不是RGB8等),但我无法弄清楚是什么原因导致这种情况发生,每个样本单独进行光照处理(使用texel fetch)会非常耗费性能。
有什么想法吗?