En effet, c'est tout ce dont vous avez besoin pour la radiosité. Il existe deux formulations différentes (mais égales). La première consiste à «rayonner» ou à projeter de la lumière à partir de chaque patch (dans votre cas, probablement un visage), et l'autre consiste à «recueillir» ou à recevoir de la lumière dans chaque patch. Si vous le faites de manière itérative suffisamment de fois, vous obtenez la radiosité.
La première étape consiste à déterminer d'où provient la lumière, car dans l'une ou l'autre méthode, il doit y avoir une source de lumière. Si vous allez faire la méthode de collecte, je dois vous avertir qu'elle ne gère pas très bien les lumières ponctuelles. Vous devez semer les patchs avec de la lumière (le calculer séparément) ou vous obtenez des résultats étranges. Dans la méthode par rayonnement, vous émettez des lumières ponctuelles comme d'habitude, mais vous les ignorez en tant que récepteurs d'autres patchs.
Vous pouvez vous arrêter après un certain nombre de rebonds (ou d'itérations), mais plus vous en faites, meilleure est la solution. Vous pouvez facilement créer des correctifs, car vous pouvez considérer chaque côté de vos cubes comme un correctif. Si vous voulez quelque chose de plus détaillé, vous pouvez subdiviser ces faces encore plus loin.
Dans un exemple rayonnant, cela pourrait être utilisé comme base pour votre boucle:
while(!done) {
foreach Patch a {
a.shootRays(n);
foreach ray r {
Patch b = r.firstIntersectingPatch();
float modifier = 1 / ((distance(a,b)^2)
b.incidentLight += (a.exidentLight / n) * modifier;
}
}
foreach Patch a {
float modifier = a.absorption;
a.exidentLight = (a.incidentLight * modifier) + a.emission;
a.incidentLight = 0;
}
done = goodEnough() ? true : false;
}
Pour une méthode de collecte, vous auriez la première boucle légèrement différente:
foreach Patch a {
a.shootRays(n);
foreach ray r {
Patch b = r.firstIntersectingPatch();
float modifier = 1 / ((distance(a,b)^2)
a.incidentLight += b.exidentLight * modifier;
}
a.incidentLight /= n;
}
Le premier modificateur est utilisé pour la modification par patch de la lumière entrante. L'utilisation la plus courante serait la chute à distance comme je l'ai fait ci-dessus. Le deuxième modificateur est destiné à la modification globale de la lumière entrante comme l'absorption de matériaux. La variable a.emission serait 0 pour la plupart des correctifs.
Seules celles qui sont des sources lumineuses (ou directement affectées par des sources lumineuses ponctuelles si vous utilisez une méthode de collecte comme indiqué ci-dessus) doivent avoir des valeurs d'émission non nulles.
La fonction goodEnough () pourrait être beaucoup de choses. Il peut s'agir simplement de compter le nombre d'itérations, ou de regarder la quantité totale de lumière dans la scène, ou ce peut être un autre test que vous imaginez. Cette partie est vraiment à vous et ce que vous pensez semble assez bon mais se termine toujours dans un délai raisonnable.
Plus vous tirez de rayons, plus votre solution est précise, mais plus le processus est lent. Il en va de même pour le nombre de patchs et le nombre d'itérations dans la boucle. La façon dont vous stockez la valeur lumineuse finale dépend de vous. Il pourrait être dans une texture ou stocké en tant que valeur dans vos cubes, mais je ne pense pas que ce serait faisable en temps réel avec un nombre décent de correctifs.