具有光体积的延迟渲染器产生奇怪的条带
Deferred renderer with light volumes produce strange banding
我有一个延迟渲染器,它只在当前片段在光源范围内时才计算光照方程。我通过计算我的应用程序中光体积的大小并将其与其他光信息一起发送到着色器来执行此操作。然后我检查片段和 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/radius 为:
Size = 1.0 / Linear;
一些观察
当我删除距离检查时 if(distance <= lights[i].Size)
我没有遇到奇怪的边界问题。
如果我可视化单个光源的照明值并将距离可视化为 distance/lights.Size
我得到以下 2 个图像:
看起来好像光radius/distance-calculations和光衰减在半径上是相似的。
当我将距离检查方程式更改为 if(distance <= lights[i].Size * 2.0f)
(以大幅增加光的半径)时,我得到的边界条带明显减少,但如果我看得足够近,我会时不时地看到它们,所以即使这并不能完全解决问题。
我不知道是什么原因造成的,目前我没有选择。
本节:
vec3 lighting;
// Ambient
lighting += lights[i].Ambient * color;
您永远不会在添加之前初始化照明。我认为这会导致未定义的行为。尝试将其更改为:
// Ambient
vec3 lighting = lights[i].Ambient * color;
我有一个延迟渲染器,它只在当前片段在光源范围内时才计算光照方程。我通过计算我的应用程序中光体积的大小并将其与其他光信息一起发送到着色器来执行此操作。然后我检查片段和 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/radius 为:
Size = 1.0 / Linear;
一些观察
当我删除距离检查时 if(distance <= lights[i].Size)
我没有遇到奇怪的边界问题。
如果我可视化单个光源的照明值并将距离可视化为 distance/lights.Size
我得到以下 2 个图像:
看起来好像光radius/distance-calculations和光衰减在半径上是相似的。
当我将距离检查方程式更改为 if(distance <= lights[i].Size * 2.0f)
(以大幅增加光的半径)时,我得到的边界条带明显减少,但如果我看得足够近,我会时不时地看到它们,所以即使这并不能完全解决问题。
我不知道是什么原因造成的,目前我没有选择。
本节:
vec3 lighting;
// Ambient
lighting += lights[i].Ambient * color;
您永远不会在添加之前初始化照明。我认为这会导致未定义的行为。尝试将其更改为:
// Ambient
vec3 lighting = lights[i].Ambient * color;