J'ai étudié les exemples de Nvidia du SDK, en particulier le projet Island11 et j'ai trouvé quelque chose de curieux sur un morceau de code HLSL qui corrige les réflexions de haut en bas en fonction de l'état de la hauteur de la vague.
Naturellement, après avoir examiné le bref paragraphe de code:
// calculating correction that shifts reflection up/down according to water wave Y position
float4 projected_waveheight = mul(float4(input.positionWS.x,input.positionWS.y,input.positionWS.z,1),g_ModelViewProjectionMatrix);
float waveheight_correction=-0.5*projected_waveheight.y/projected_waveheight.w;
projected_waveheight = mul(float4(input.positionWS.x,-0.8,input.positionWS.z,1),g_ModelViewProjectionMatrix);
waveheight_correction+=0.5*projected_waveheight.y/projected_waveheight.w;
reflection_disturbance.y=max(-0.15,waveheight_correction+reflection_disturbance.y);
Ma première supposition était qu'elle compense la réflexion planaire lorsqu'elle est soumise à une perturbation verticale (les ondes), déplaçant la géométrie réfléchie à un point où il n'y a rien et l'eau est juste rendue comme s'il n'y avait rien là-bas ou juste le ciel:
Maintenant, c'est le ciel qui reflète où nous devrions voir la réflexion verte / grise / jaunâtre du terrain lerpée avec la ligne de base de l'eau. Mon problème est maintenant que je ne peux pas vraiment identifier quelle est la logique derrière cela. Projeter la position spatiale mondiale réelle d'un point de la géométrie vague / eau, puis multiplier par -.5f, pour prendre une autre projection du même point, cette fois avec sa coordonnée y changée en -0.8 (pourquoi -0.8?).
Des indices dans le code semblent indiquer qu'il a été dérivé avec essais et erreurs car il y a redondance. Par exemple, l'auteur prend la moitié négative de la coordonnée y projetée (après la division w):
float waveheight_correction=-0.5*projected_waveheight.y/projected_waveheight.w;
Et puis fait la même chose pour le deuxième point (seulement positif, pour obtenir une différence quelconque, je présume) et les combine:
waveheight_correction+=0.5*projected_waveheight.y/projected_waveheight.w;
En supprimant le fossé par 2, je ne vois aucune différence dans l'amélioration de la qualité (si quelqu'un veut me corriger, veuillez le faire). Le nœud semble être la différence dans le y projeté, pourquoi est-ce? Cette redondance et la sélection apparemment arbitraire de -.8f et -0.15f m'amènent à conclure que cela pourrait être une combinaison d'heuristique / travail de supposition. Y a-t-il un fondement logique à cela ou est-ce juste un hack désespéré?
Voici une exagération du problème initial que le fragment de code corrige, observe au niveau de pavage le plus bas. J'espère que cela pourrait déclencher une idée qui me manque. Le -.8f peut être une hauteur de référence à partir de laquelle déduire le degré de perturbation de la coordonnée de texture échantillonnant le rendu géométrique réfléchi et -.15f peut être la limite inférieure, une mesure de sécurité.