Studiowałem przykłady Nvidii z SDK, w szczególności projekt Island11 i znalazłem coś ciekawego w kawałku kodu HLSL, który koryguje odbicia w górę iw dół w zależności od stanu wysokości fali.
Oczywiście po przeanalizowaniu krótkiego akapitu kodu:
// 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);
Moje pierwsze przypuszczenie było takie, że kompensuje odbicie planarne, gdy jest poddawane pionowym zaburzeniom (falom), przesuwając odbijaną geometrię do punktu, w którym nic nie ma, a woda jest renderowana tak, jakby nic tam nie było lub tylko niebo:
Teraz to niebo odbija się w miejscu, w którym powinniśmy zobaczyć zielone / szare / żółtawe odbicie terenu z linią bazową wody. Mój problem polega teraz na tym, że nie jestem w stanie dokładnie określić logiki, która się za tym kryje. Rzutowanie rzeczywistej pozycji w przestrzeni świata punktu geometrii fali / wody, a następnie pomnożenie przez -5f, tylko po to, aby wykonać kolejną projekcję tego samego punktu, tym razem ze współrzędną y zmieniono na -0,8 (dlaczego -0,8?).
Wskazówki w kodzie wydają się wskazywać, że został uzyskany metodą prób i błędów, ponieważ występuje nadmiarowość. Na przykład autor przyjmuje ujemną połowę rzutowanej współrzędnej y (po podziale w):
float waveheight_correction=-0.5*projected_waveheight.y/projected_waveheight.w;
A potem robi to samo dla drugiego punktu (tylko pozytywne, aby uzyskać jakąś różnicę, jak sądzę) i łączy je:
waveheight_correction+=0.5*projected_waveheight.y/projected_waveheight.w;
Po usunięciu podziału przez 2 nie widzę żadnej różnicy w poprawie jakości (jeśli ktoś chce mnie poprawić, proszę). Sednem tego wydaje się być różnica w rzutowanym y, dlaczego tak jest? Ta redundancja i pozornie arbitralny wybór -8f i -0,15f doprowadziły mnie do wniosku, że może to być kombinacja pracy heurystycznej / zgadywania. Czy jest to uzasadnione logicznie, czy jest to desperacki hack?
Oto przesada pierwotnego problemu, który naprawia fragment kodu, obserwowany na najniższym poziomie teselacji. Mam nadzieję, że zrodzi to pomysł, za którym tęsknię. -8f może być wysokością odniesienia, na podstawie której można wywnioskować, jak bardzo zakłócać współrzędną tekstury próbkowanie renderowanej geometrii płaskiej, a -15f może być dolną granicą, środkiem bezpieczeństwa.