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:
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.