Ich habe Nvidias Beispiele aus dem SDK studiert, insbesondere das Island11- Projekt, und ich habe etwas Merkwürdiges an einem Stück HLSL-Code gefunden, das die Reflexionen je nach Höhe der Welle nach oben und unten korrigiert.
Natürlich nach Prüfung des kurzen Absatzes des Codes:
// 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);
Meine erste Vermutung war, dass es die planare Reflexion kompensiert, wenn es einer vertikalen Störung (den Wellen) ausgesetzt ist, wobei die reflektierte Geometrie an einen Punkt verschoben wird, an dem nichts ist und das Wasser nur so gerendert wird, als wäre nichts da oder nur der Himmel:
Das ist der Himmel, der reflektiert, wo wir die grün / grau / gelbliche Reflexion des Geländes sehen sollten, die mit der Grundlinie des Wassers lerpiert ist. Mein Problem ist jetzt, dass ich nicht genau sagen kann, was die Logik dahinter ist. Projizieren Sie die tatsächliche Weltraumposition eines Punktes der Wellen- / Wassergeometrie und multiplizieren Sie sie dann mit -5f, um eine weitere Projektion desselben Punktes zu erhalten. Diesmal wird die y-Koordinate auf -0,8 geändert (warum -0,8?).
Hinweise im Code scheinen darauf hinzudeuten, dass er durch Ausprobieren abgeleitet wurde, da es Redundanz gibt. Zum Beispiel nimmt der Autor die negative Hälfte der projizierten y-Koordinate (nach der w-Teilung):
float waveheight_correction=-0.5*projected_waveheight.y/projected_waveheight.w;
Und dann das Gleiche für den zweiten Punkt (nur positiv, um einen Unterschied zu bekommen, nehme ich an) und kombiniert sie:
waveheight_correction+=0.5*projected_waveheight.y/projected_waveheight.w;
Durch Entfernen der Division durch 2 sehe ich keinen Unterschied in der Qualitätsverbesserung (wenn jemand mich korrigieren möchte, bitte tun Sie dies). Der springende Punkt scheint der Unterschied im projizierten y zu sein, warum ist das so? Diese Redundanz und die scheinbar willkürliche Auswahl von -8f und -0.15f lassen mich den Schluss ziehen, dass dies eine Kombination aus Heuristik / Vermutungsarbeit sein könnte. Gibt es eine logische Grundlage dafür oder ist es nur ein verzweifelter Hack?
Hier ist eine Übertreibung des anfänglichen Problems, das das Codefragment behebt, und zwar auf der niedrigsten Tessellationsebene. Hoffentlich könnte es eine Idee auslösen, die ich vermisse. -.8f kann eine Bezugshöhe sein, aus der sich ableiten lässt, wie stark die Texturkoordinate gestört werden soll, mit der die planar reflektierte Geometrie wiedergegeben wird, und -.15f kann die Untergrenze sein, eine Sicherheitsmaßnahme.