【问题标题】:Deferred renderer with light volumes produce strange banding具有光量的延迟渲染器会产生奇怪的条带
【发布时间】:2015-04-04 16:32:16
【问题描述】:

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

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

片段着色器代码如下:

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 &lt;= lights[i].Size) 时,我没有遇到奇怪的边框问题。

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

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

当我将距离检查方程更改为if(distance &lt;= lights[i].Size * 2.0f)(以显着增加光的半径)时,我会明显减少边界带,但如果我看起来足够近,我确实会不时看到它们,所以即使这样也不会彻底解决问题。

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

【问题讨论】:

  • 您确定您的lights[i].Size 和/或.Linear 参数实际上是正确的吗?作为一个快速测试,您可以尝试if(distance &lt;= 1.0/lights[i].Linear),以确保您测试的边界与实际用于衰减项的边界相同吗?
  • 我用if(distance &lt;= 1.0/lights[i].Linear) 试了一下,结果是一样的。这很奇怪,因为您希望边界完全正确(因为这和衰减函数彼此相反)

标签: c++ opengl lighting deferred-rendering


【解决方案1】:

本节:

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

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

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

【讨论】:

  • 你是对的;一直认为 GLSL 会正确默认初始化变量,但我想我错了。这解决了条带问题。您(或其他人)是否知道这如何可能导致条带?也许它将其初始化为低于0.0的值?
  • 我可能从 0.0 开始,但它永远不会被清除,因此每次迭代照明都会增加。因此,如果三盏灯重叠,最后一盏灯将包括前两盏灯的照明。
  • 是的,这是有道理的。再次感谢您的回答。
猜你喜欢
  • 1970-01-01
  • 2019-03-08
  • 2012-04-12
  • 2012-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多