在“《战地风云3》中的DirectX 11渲染”幻灯片中的一张幻灯片中,我注意到了以下代码:
struct Light {
float3 pos; float sqrRadius;
float3 color; float invSqrRadius;
}
我不明白为什么他们要存储半径的平方,甚至是平方的倒数(我相信只是平方的半径),而不是仅仅存储半径?他们如何在计算中使用这些数据?此外,锥形和线形灯又如何呢?该结构只能用于点光源,我看不到它可用于其他类型-没有足够的数据。我仍然很想知道他们如何使用该平方和invSquare。
更新:好的,我终于明白了。
这是经典的光衰减方程式,很容易在网上找到:
float3 lightVector = lightPosition - surfacePosition;
float attenuation = saturate(1 - length(lightVector)/lightRadius);
length(lightVector)
这样做实际上是相对昂贵的:
length(lightVector) = sqrt(dot(lightVector, lightVector);
此外,分割操作(/lightRadius)
也相当昂贵。
不用这种方法来计算光衰减,您可以通过以下方法进行计算,这将更快。
attenuation = saturate(1 - dot(lightVector, lightVector)*invRadiusSqr);
其中invRadiusSqr可以在CPU级别上预先计算并作为着色器常量传递。
而且,结果是得到了二次光衰减(而不是前一种情况下的线性光衰减),这更好,因为IRL光已显示出二次衰减。
谢谢大家的帮助!