Sur l'une des diapositives de PowerPoint "Rendu DirectX 11 dans Battlefield 3", j'ai remarqué le code suivant:
struct Light {
float3 pos; float sqrRadius;
float3 color; float invSqrRadius;
}
Je ne comprends pas pourquoi stockeraient-ils le rayon carré et même l'inverse du carré (qui, je crois, est simplement un rayon de 1 carré) au lieu de simplement stocker le rayon? Comment utilisent-ils ces données dans leurs calculs? De plus, qu'en est-il des lampes à cône et à ligne? Cette structure ne doit être que pour les lumières ponctuelles, je ne la vois pas fonctionner pour d'autres types - il n'y a pas assez de données. J'aimerais quand même savoir comment ils utilisent ce carré et invSquare.
MISE À JOUR: Ok, je l'ai enfin compris.
Voici l'équation classique d'atténuation de la lumière, facilement trouvée sur le net:
float3 lightVector = lightPosition - surfacePosition;
float attenuation = saturate(1 - length(lightVector)/lightRadius);
C'est relativement coûteux, comme length(lightVector)
c'est le cas en réalité:
length(lightVector) = sqrt(dot(lightVector, lightVector);
en outre, l'opération de division (/lightRadius)
est également très coûteuse.
Au lieu de calculer l'atténuation de la lumière de cette façon, vous pouvez la calculer de la manière suivante, ce qui serait beaucoup plus rapide:
attenuation = saturate(1 - dot(lightVector, lightVector)*invRadiusSqr);
où invRadiusSqr peut être précalculé au niveau du processeur et passé en tant que constante de shader.
De plus, vous obtenez une atténuation de la lumière quadratique en conséquence (au lieu de linéaire dans le premier cas), ce qui est encore mieux, car la lumière IRL a montré une atténuation quadratique.
Merci à tous pour votre aide!
Réponses:
Il s'agit simplement d'une sorte d'optimisation étant donné qu'au
invSqrRadius = 1/SqrRadius
lieu de calculer le rayon carré inverse pour chaque lumière chaque fois qu'ils la mettent simplement en cache, la raison est que la division est généralement une opération "lente" au moins par rapport à la multiplication.Cette optimisation est pertinente notamment:
En ce qui concerne la façon dont il est utilisé, je ne suis pas sûr de leur mise en œuvre spécifique, mais en ce qui concerne
1/sqrRadius
, cela est simplement utilisé pour l'atténuation de la lumière, l'atténuation et l'abattage. Il est également pertinent pour la direction et le projecteur, la seule différence en cas de projecteur est que vous devez calculer le facteur de projecteur après avoir appliqué l'atténuation . En ce qui concerne les lumières directionnelles comme le soleil, il n'y a généralement pas d'atténuation ni d'atténuation, donc je suppose qu'il sera ignoré.[EDIT] Juste pour développer davantage, ce ne sont pas des données non pertinentes. L'irradiance lumineuse peut être calculée en utilisant l'équation suivante:
Cette équation explique pourquoi la quantité d'énergie reçue diminue avec la distance au carré.
Un autre point est que vous devez calculer la distance entre le sommet et la lumière pour calculer la contribution de la lumière sur un sommet spécifique (cette valeur est peu susceptible d'être mise en cache), le sommet peut être dans ou en dehors de la plage de lumière qui nous amène au point suivant où
Radius Square
est utile pour l'abattage.Si vous voulez un exemple pratique pour calculer l'atténuation de la lumière et l'abattage, c'est particulièrement utile dans les rendus différés en mosaïque, voici un exemple .
la source
invSqrRadius n'est pas 1 - sqrRadius; c'est 1 / sqrRadius.
Cela signifie que vous pouvez multiplier par invSqrRadius, au lieu de diviser par sqrRadius (car la division est généralement beaucoup plus coûteuse que la multiplication)
la source
Les autres réponses ici concernaient le rayon carré inverse, mais je vais plutôt regarder le rayon carré (dont concept3d a parlé, mais je crois qu'il mérite une discussion plus approfondie).
Les carrés sont utiles pour les comparaisons de distance. Nous savons que le calcul de la distance entre deux points implique une racine carrée, et les racines carrées sont coûteuses à calculer, mais si tout ce que nous voulons faire est de comparer les distances (afin de trouver ce qui est inférieur ou supérieur, et faire quelque chose d'intéressant en fonction de la résultat) nous pouvons jeter la racine carrée.
Si sqrt (x)> sqrt (y) alors c'est aussi le cas que x> y.
Pour une lumière, le rayon carré est le même que la distance entre le centre de la lumière et son étendue maximale - au carré, bien sûr.
Pour les calculs d'éclairage, cela peut être utilisé pour un cas de sortie anticipée. Si la distance entre le point que vous allumez et le centre de la lumière (au carré) est supérieure au rayon carré, le point ne reçoit aucune lumière et vous n'avez pas besoin d'exécuter le reste de vos calculs. Il ne s'agit donc que d'une optimisation (assez courante) - nous pouvons utiliser le rayon carré pour faire la comparaison de distance sans racines carrées coûteuses, et au prix d'une soustraction et d'un produit scalaire.
Bien sûr, je ne sais pas si c'est exactement pour cela que BF3 l'utilise, mais je m'attends à ce que je ne sois pas trop loin de la cible.
la source