Contabilizando ondas ao fazer reflexões planares

13

Estudei os exemplos da Nvidia a partir do SDK, em particular o projeto Island11 , e descobri algo curioso sobre um pedaço de código HLSL que corrige as reflexões para cima e para baixo, dependendo do estado da altura da onda.

Naturalmente, após examinar o breve parágrafo do código:

// 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);

Meu primeiro palpite foi que ele compensa a reflexão plana quando está sujeito a perturbações verticais (as ondas), deslocando a geometria refletida para um ponto onde não há nada e a água é renderizada como se não houvesse nada lá ou apenas o céu:

insira a descrição da imagem aqui

Agora, esse é o céu refletindo onde deveríamos ver o reflexo verde / cinza / amarelado do terreno marcado com a linha de base da água. Meu problema agora é que não posso realmente identificar qual é a lógica por trás disso. Projetando a posição espacial mundial real de um ponto da geometria das ondas / água e multiplicando por -,5f, apenas para fazer outra projeção do mesmo ponto, desta vez com sua coordenada y alterada para -0,8 (por que -0,8?).

Pistas no código parecem indicar que ele foi derivado com tentativa e erro porque há redundância. Por exemplo, o autor pega a metade negativa da coordenada y projetada (após a divisão w):

float waveheight_correction=-0.5*projected_waveheight.y/projected_waveheight.w;

E então faz o mesmo para o segundo ponto (apenas positivo, para obter uma diferença de algum tipo, presumo) e os combina:

waveheight_correction+=0.5*projected_waveheight.y/projected_waveheight.w;

Ao remover a divisão por 2, não vejo diferença na melhoria da qualidade (se alguém quiser me corrigir, por favor). O ponto crucial disso parece ser a diferença no y projetado, por que isso? Essa redundância e a seleção aparentemente arbitrária de -.8f e -0.15f me levaram a concluir que isso pode ser uma combinação de heurística / trabalho de adivinhação. Existe uma base lógica para isso ou é apenas um hack desesperado?

Aqui está um exagero do problema inicial que o fragmento de código corrige, observe no nível mais baixo de mosaico. Felizmente, isso pode desencadear uma idéia que estou perdendo. O -.8f pode ser uma altura de referência a partir da qual deduzir o quanto perturbar a coordenada da textura amostrando a renderização da geometria refletida planarmente e -.15f pode ser o limite inferior, uma medida de segurança.

insira a descrição da imagem aqui

CloseReflector
fonte

Respostas:

1

Essa técnica deve ter esse artefato, e é por isso que, na maioria das vezes, quando é usado, aplicamos uma mudança vertical na pesquisa para fazer como se o plano de reflexão real estivesse meio metro acima de sua posição real. Sim, tem a desvantagem de não ter um reflexo perfeitamente adequado, mas é preferível aos orifícios.

v.oddou
fonte
2
Você pode elaborar mais?