GLSL光线(衰减,颜色和强度)公式


17

我正在Voxel引擎中实现点光源,我真的在努力获得良好的光流,从光源附近的100%到光半径的0%。

我对该函数有5个参数:

  1. 浅色(Vec3)
  2. 光强度(距光的距离,直到衰减为100%的距离)
  3. 光线到碎片的距离
  4. 从片段法线到光的角度
  5. 灯的位置

谁能按正确的方向推动我创建用于计算片段颜色的函数?

我的其中一项实验的图片:

体素引擎每片段照明测试

编辑(字节请求当前代码)请注意,这只是我这边的一些实验代码。我从一个网站上获得了一个float att,它虽然可以正常工作,但远非完美。

void main()
{
// Light color
vec3 torchColor = vec3(1.0f, 1.0f, 1.0f);

float lightAdd = 0.0f;
for (int i=0; i<5; i++) {
    vec3 pos = lights[i];
    if (pos.x == 0.0f) continue;

    float dist = distance(vertex_pos, pos);
    if (dist < 9) {
        float att=1.0/(1.0+0.1*dist+0.01*dist*dist);
        vec3 surf2light = normalize(pos - vertex_pos);
        vec3 norm = normalize(normal);
        float dcont=max(0.0,dot(norm,surf2light));
        lightAdd += att*(dcont+0.4);
    }
}

vec3 textureColor = texture2D(texture, texture_coordinate).rgb;
vec3 torch_output = lightAdd * torchColor;

vec3 final_color = ((0.1+torch_output) * textureColor);

gl_FragColor = vec4(final_color, 1.0f); 
}

6
您仍然在说诸如“努力获得漂亮的外观自然采光 ”和“有效但远非完美 ”之类的东西。您需要包括特定的确切语言。我们不知道您看起来是什么样,或者自然光是什么样,或者完美是什么。
MichaelHouse

2
您是否尝试过删除if (dist < 9)?另外,您可以att使用一个函数进行计算,该函数在距离为0时返回1,在距离为9时返回0。例如mix(1.0, 0.0, dist / 9.0)
msell,

Answers:


39

您所拥有的衰减功能,

att = 1.0 / (1.0 + 0.1*dist + 0.01*dist*dist)

在计算机图形学中是一种相当普遍的语言-或更一般而言,1.0 / (1.0 + a*dist + b*dist*dist))对于某些可调整的参数ab。要了解此曲线的工作方式,以交互方式使用参数很有帮助。该曲线之所以不错,是因为它在大距离上接近物理上正确的平方反比定律,但在短距离上不会射向无穷大。实际上,a = 0它是球形区域光的一个很好的模型。

然而,它的一个缺点是光在任何有限距离处都不会完全变为零。出于实时CG的实际目的,我们通常需要像在处理该if (dist < 9)子句时一样,在有限距离内切断灯光。但是,9的半径太短-在衰减功能中进行了设置,直到dist大约为100时,光线才会接近于零。

您可以根据b衰减函数中的参数计算光的半径(因为二次项在较大距离处占优势)。假设您要在衰减达到某个值minLight(例如0.01)时将其切断。然后设置

radius = sqrt(1.0 / (b * minLight))

这给出了100的半径b = 0.01minLight = 0.01。另外,您可以设置半径并计算b以匹配:

b = 1.0 / (radius*radius * minLight)

对于radius = 9minLight = 0.01,给出了b = 1.23。您可以使用任何一种方式进行设置,但关键是使半径和衰减函数匹配,以便在衰减函数已经非常低之前不要切断光源,这样就不会看到锐利的边缘。


综上所述,您可以使用其他衰减功能。另一个相当常见的是:

att = clamp(1.0 - dist/radius, 0.0, 1.0); att *= att

或稍微更高级:

att = clamp(1.0 - dist*dist/(radius*radius), 0.0, 1.0); att *= att

也可以使用那些参数。这些曲线的优点是,在给定的半径处精确地变为零,同时看起来仍然像自然的平方反比定律。


大!虽然,我会使用maxclamp的只有表现的原因。
Mike Weir

4
实际上,在许多GPU上,将@MikeWeir钳制为[0,1]是免费的。这是一种非常常见的操作,他们将其用作指令修饰符。
内森·里德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.