Query: How can I mission the fragment place onto the world flooring airplane with respect to the cameras present translation, rotation and zoom?
I’m making an attempt to implement an infinite world flooring grid shader, much like this query.
My mission is utilizing Metallic Shading Language however the ideas are related between GLSL/HLSL.
The web has supplied a number of factors of reference for studying the best way to implement grid shading. What I’m combating is the ideas required to convert between view areas to realize my objective.
I discover shaders notably mystical due to the difficulties in debugging visually so I’ve damaged up what I perceive to be the required steps;
-
1.) Within the scene:
- Create a airplane that extends alongside the xy axis within the vary
[-1, -1] -> [1, 1]
- Create a airplane that extends alongside the xy axis within the vary
-
2.) Within the vertex shader:
- Set the fragment place so the airplane fills the view
- Return the untransformed vertex place
-
3.) Within the fragment shader:
- Calculate the digital camera place in clip area
- Calculate the airplane place in clip area
- Forged a ray from the digital camera to the ground airplane to search out the purpose of intersection
- Render the world axis grid utilizing the purpose of intersection
Grid Rendering
This methodology determines the ultimate output coloration for the world grid for a given level alongside the airplane.
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);
}
Vertex Shader
The vertex shader passes the vertex place alongside to the fragment shader with none transformations. The vertex positions are within the vary [-1, -1] -> [1, 1]
which fills the viewport in clip area.
struct SurfaceFragment {
float4 place [[position]];
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 };
}
Fragment Shader
fragment float4 surface_fragment(SurfaceFragment f [[stage_in]],
fixed SceneBuffer& scn_frame [[ buffer(0) ]]) {
//place is in clip area (z = 1.f (far airplane))
float3 place = float3(f.uv, 1.f);
//convert eye from digital camera area to clip area
float4 pov = scn_frame.projectionTransform * float4(0.f, 0.f, 0.f, 1.f);
//convert airplane from world area to clip area
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);
}
Points
That is the ultimate output for the scene the place we will observe just a few issues:
- Rotating the digital camera skews the grid strains incorrectly.
- After translating the digital camera the bottom airplane not aligns
This appears to be like to be near what I need to obtain however I’m uncertain the place to go from right here.
My guess is that the place returned from raycasting is inaccurate as a result of both:
- Incorrect transformations between clip area and world area.
- Incorrect placement of the airplane in world area.
- Incorrectly casting the ray from the flawed pov or course.
How can I mission the fragment place onto the world flooring airplane in respect to the digital camera?