Pergunta: Como posso projetar a posição do fragmento no plano do assoalho mundial em relação à tradução, rotação e zoom de câmeras?
Estou tentando implementar um shader infinito de grade do piso mundial, semelhante a esta pergunta.
Meu projeto está usando linguagem de sombreamento de metallic, mas os conceitos são semelhantes entre o GLSL/HLSL.
A Web forneceu vários pontos de referência para aprender a implementar sombreamento de grade. O que estou lutando é o conceitos necessários para converter entre espaços de vista para atingir meu objetivo.
Acho os shaders particularmente místicos por causa das dificuldades de depuração visualmente, por isso quebrei o que entendo como as etapas necessárias;
-
1.) Na cena:
- Crie um avião que se estenda ao longo do eixo XY no intervalo
(-1, -1) -> (1, 1)
- Crie um avião que se estenda ao longo do eixo XY no intervalo
-
2.) No shader do vértice:
- Defina a posição do fragmento para que o plano preencha a vista
- Retorne a posição de vértice não transformada
-
3.) No shader do fragmento:
- Calcule a posição da câmera no espaço do clipe
- Calcule a posição plana no espaço do clipe
- Faça um raio da câmera para o plano do chão para encontrar o ponto de interseção
- Renderizar a grade do eixo mundial usando o ponto de interseção
Renderização da grade
Este método determina a cor last de saída para a grade mundial para um determinado ponto ao longo do avião.
inline float4 grid(float2 uv,
float scale,
float4 gridColor,
float4 backgroundColor) {
uv /= scale;
float2 fractional = abs(fract(uv + 0.5f));
float2 partial = fwidth(uv);
float2 level = smoothstep(-partial, partial, fractional);
float saturation = 1.f - saturate(level.x * level.y);
return combine(backgroundColor, gridColor, saturation);
}
Shader de vértice
O shader do vértice passa a posição do vértice junto ao shader do fragmento sem nenhuma transformação. As posições de vértice estão no intervalo (-1, -1) -> (1, 1)
que preenche a visualização no espaço do clipe.
struct SurfaceFragment {
float4 place ((place));
float2 uv;
};
vertex SurfaceFragment surface_vertex(SimpleVertex v (( stage_in )),
fixed SceneBuffer& scn_frame (( buffer(0) ))) {
return { .place = float4(v.place, 1.f),
.uv = v.place.xy };
}
Shader do fragmento
fragment float4 surface_fragment(SurfaceFragment f ((stage_in)),
fixed SceneBuffer& scn_frame (( buffer(0) ))) {
//place is in clip house (z = 1.f (far airplane))
float3 place = float3(f.uv, 1.f);
//convert eye from digital camera house to clip house
float4 pov = scn_frame.projectionTransform * float4(0.f, 0.f, 0.f, 1.f);
//convert airplane from world house to clip house
float4 origin = scn_frame.viewProjectionTransform * float4(0.f, 0.f, 0.f, 1.f);
//decide course of ray from eye
float3 course = normalize(place - pov.xyz);
//airplane regular
float3 up = float3(0.f, 1.f, 0.f);
float magnitude = dot(up, course);
float size = dot((origin.xyz - pov.xyz), up) / magnitude;
if (size <= epsilon) { return backgroundColor; }
//decide hit location
float3 hit = pov.xyz + (course * size);
//draw grid
return grid(hit.xz,
1.f,
gridColor,
backgroundColor);
}
Problemas
Esta é a saída last da cena em que podemos observar alguns problemas:
- Girar a câmera distorce as linhas de grade incorretamente.
- Depois de traduzir a câmera, o avião de terra não se alinha mais

Isso parece estar perto do que quero alcançar, mas não tenho certeza de onde ir daqui.
Meu palpite é que a posição retornada do Raycasting está incorreta devido a:
- Transformações incorretas entre o espaço do clipe e o espaço mundial.
- Posicionamento incorreto do avião no espaço mundial.
- Lançando incorretamente o raio do POV ou direção errada.
Como posso projetar a posição do fragmento no plano do assoalho mundial em relação à câmera?