En una de las diapositivas de PowerPoint "Representación de DirectX 11 en Battlefield 3", noté el siguiente código:
struct Light {
float3 pos; float sqrRadius;
float3 color; float invSqrRadius;
}
No entiendo por qué almacenarían el radio cuadrado e incluso el cuadrado inverso (que creo que es simplemente un radio de 1 cuadrado) en lugar de simplemente almacenar el radio. ¿Cómo están utilizando estos datos en sus cálculos? Además, ¿qué pasa con las luces de cono y línea? Esta estructura debe ser solo para las luces de punto, no puedo ver que funcione para otros tipos, no hay suficientes datos. Aún así, me encantaría saber cómo usan ese cuadrado e invSquare.
ACTUALIZACIÓN: Ok, finalmente lo entendí.
Aquí está la ecuación clásica de atenuación de luz, que se encuentra fácilmente en la red:
float3 lightVector = lightPosition - surfacePosition;
float attenuation = saturate(1 - length(lightVector)/lightRadius);
Es relativamente costoso ya length(lightVector)
que en realidad está haciendo esto:
length(lightVector) = sqrt(dot(lightVector, lightVector);
Además, la operación de división (/lightRadius)
también es bastante costosa.
En lugar de calcular la atenuación de la luz de esta manera, puede calcularla de la siguiente manera, lo que sería mucho más rápido:
attenuation = saturate(1 - dot(lightVector, lightVector)*invRadiusSqr);
donde invRadiusSqr se puede calcular previamente a nivel de CPU y pasar como una constante de sombreador.
Además, obtienes una atenuación de luz cuadrática como resultado (en lugar de lineal en el primer caso), lo que es aún mejor, ya que la luz IRL ha demostrado tener una caída cuadrática.
¡Gracias a todos por su ayuda!