具有轻量级的延迟渲染器会产生奇怪的条带

时间:2015-04-04 16:32:17

标签: c++ opengl lighting deferred-rendering

我有一个延迟渲染器,它只在当前片段在光源范围内时计算光照方程。我这样做是通过计算应用程序中光量的大小,并将其与其他光信息一起发送到着色器。然后我检查片段和lightPos(每个灯光)之间的距离,并使用灯光的音量作为阈值。

为简单起见,我使用线性方程(二次方程产生太大的光量)来减弱光衰。所有的照明方程都可以正常工作,但是当我使用多个灯时,我有时会看到奇怪的圆形边框,好像距离检查会导致灯光计算过早停止,导致灯光突然变化。您可以在下图中看到此效果:

Deferred renderer banding

片段着色器代码如下:

vec3 position = texture(worldPos, fs_in.TexCoords).rgb;        
vec3 normal = texture(normals, fs_in.TexCoords).rgb;
normal = normalize(normal * 2.0 - 1.0);
vec3 color = texture(albedo, fs_in.TexCoords).rgb;
float depth = texture(worldPos, fs_in.TexCoords).a;
// Add global ambient value
fragColor = vec4(vec3(0.1) * color, 0.0);
for(int i = 0; i < NR_LIGHTS; ++i)
{
    float distance = abs(length(position - lights[i].Position.xyz));
    if(distance <= lights[i].Size)
    {
        vec3 lighting;                
        // Ambient            
        lighting += lights[i].Ambient * color;            
        // Diffuse
        vec3 lightDir = normalize(lights[i].Position.xyz - position);
        float diffuse = max(dot(normal, lightDir), 0.0);
        lighting += diffuse * lights[i].Diffuse * color;
        // Specular
        vec3 viewDir = normalize(viewPos - position);
        vec3 reflectDir = reflect(-lightDir, normal);
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), 8);
        lighting += spec * lights[i].Specular;

        // Calculate attenuation
        float attenuation = max(1.0f - lights[i].Linear * distance, 0.0);
        lighting *= attenuation;
        fragColor += vec4(lighting, 0.0);
    }
}
fragColor.a = 1.0;    

衰减函数是片段位置和每个光源之间距离的线性函数。

在这个特定场景中,我使用线性衰减值0.075,我将其生成灯光的大小/半径:

Size = 1.0 / Linear;

一些观察

当我删除距离检查if(distance <= lights[i].Size)时,我没有遇到奇怪的边框问题。

如果我可视化单个光源的光照值并将距离可视化为distance/lights.Size,我会得到以下2张图像:

Deferred renderer banding

看起来光半径/距离计算和光衰减的半径相似。

当我将距离检查等式更改为if(distance <= lights[i].Size * 2.0f)时(为了大幅增加光线的半径)我的边界条带明显减少,但如果我看得够近,我会不时看到它们,所以即便如此完全消除了这个问题。

我不知道造成这种情况的原因是什么,目前我没有选择。

1 个答案:

答案 0 :(得分:3)

本节:

    vec3 lighting;                
    // Ambient            
    lighting += lights[i].Ambient * color;   

在添加照明之前,您永远不会初始化照明。我认为这会导致未定义的行为。尝试将其更改为:

    // Ambient            
    vec3 lighting = lights[i].Ambient * color;