带有光量的延迟渲染器会产生奇怪的条带

问题描述:

我有一个延迟渲染器,当当前片段位于光源范围内时,它只计算光照方程。我通过计算应用程序中的光量大小来实现此目的,并将其他光信息发送给着色器。然后检查片段和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线性衰减值I产生的光的大小/半径为:

Size = 1.0/Linear; 

一些观察

当我删除的距离检查if(distance <= lights[i].Size)我不要得到奇怪的边界问题。

如果我可视化单一光源的照明值和可视化的距离为distance/lights.Size我得到以下2个图像:

Deferred renderer banding

其看起来好像光半径/距离计算和光衰减在半径上是相似的。

当我将距离检查方程更改为if(distance <= lights[i].Size * 2.0f)(以大幅增加光线的半径)时,我得到的边界条纹明显更少,但是如果我看起来足够接近,我不时会看到它们,即使那样也不完全删除问题。

我不知道是什么导致了这一点,我目前没有选择。

+0

您确定您的'lights [i] .Size'和/或'.Linear'参数实际上是否正确?作为一个快速测试,你可以试试'if(distance derhass 2015-04-04 17:44:57

+0

我用'if(distance ABHAY 2015-04-04 17:48:10

本节:

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

您要添加到它之前从来没有初始化的照明。我认为这可能会导致未定义的行为。尝试将其更改为:

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

你是对的;总是认为GLSL会正确地默认初始化变量,但我想我错了。这固定了带状问题。你(或其他人)有没有想法这可能会导致绑定?也许它初始化为低于'0.0'的值? – ABHAY 2015-04-09 07:37:44

+0

我可能从0.0开始,但它永远不会被清除,因此每次迭代照明都会增加。所以如果三个灯重叠,最后一个灯将包括前两个灯的照明。 – bofjas 2015-04-09 12:10:13

+0

是的,这是有道理的。再次感谢您的回答。 – ABHAY 2015-04-09 12:45:11