147 lines
4.1 KiB
GLSL
147 lines
4.1 KiB
GLSL
// Implementation based on:
|
|
// "The Best Darn Grid Shader (Yet)", Medium, Oct 2023
|
|
// Ben Golus
|
|
// https://bgolus.medium.com/the-best-darn-grid-shader-yet-727f9278b9d8#3e73
|
|
|
|
#define MIN_DERIV 0.00001f
|
|
|
|
#include "./Flax/Common.hlsl"
|
|
|
|
META_CB_BEGIN(0, Data)
|
|
float4x4 ViewProjectionMatrix;
|
|
float4 GridColor;
|
|
float3 ViewPos;
|
|
float Far;
|
|
float3 ViewOrigin;
|
|
float GridSize;
|
|
META_CB_END
|
|
|
|
// Geometry data passed to the vertex shader
|
|
struct ModelInput
|
|
{
|
|
float3 Position : POSITION;
|
|
};
|
|
|
|
// Interpolants passed from the vertex shader
|
|
struct VertexOutput
|
|
{
|
|
float4 Position : SV_Position;
|
|
float2 TexCoord : TEXCOORD0;
|
|
float3 WorldPosition : TEXCOORD1;
|
|
};
|
|
|
|
// Interpolants passed to the pixel shader
|
|
struct PixelInput
|
|
{
|
|
float4 Position : SV_Position;
|
|
noperspective float2 TexCoord : TEXCOORD0;
|
|
float3 WorldPosition : TEXCOORD1;
|
|
};
|
|
|
|
// Vertex shader function for grid rendering
|
|
META_VS(true, FEATURE_LEVEL_ES2)
|
|
META_VS_IN_ELEMENT(POSITION, 0, R32G32B32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
|
|
VertexOutput VS_Grid(ModelInput input)
|
|
{
|
|
VertexOutput output;
|
|
output.WorldPosition = input.Position.xyz + ViewOrigin;
|
|
float3 geoPosition = input.Position.xyz - float3(0, ViewOrigin.y, 0);
|
|
output.Position = mul(float4(geoPosition, 1), ViewProjectionMatrix);
|
|
return output;
|
|
}
|
|
|
|
float invLerp(float from, float to, float value)
|
|
{
|
|
return (value - from) / (to - from);
|
|
}
|
|
|
|
float remap(float origFrom, float origTo, float targetFrom, float targetTo, float value)
|
|
{
|
|
float rel = invLerp(origFrom, origTo, value);
|
|
return lerp(targetFrom, targetTo, rel);
|
|
}
|
|
|
|
float GetLine(float pos, float scale, float thickness)
|
|
{
|
|
float lineWidth = thickness;
|
|
float coord = (pos * 0.01) * scale;
|
|
|
|
float2 uvDDXY = float2(ddx(coord), ddy(coord));
|
|
|
|
float deriv = max(float(length(uvDDXY.xy)), MIN_DERIV);
|
|
float drawWidth = clamp(lineWidth, deriv, 0.5);
|
|
float lineAA = deriv * 1.5;
|
|
float gridUV = abs(coord);
|
|
float grid2 = smoothstep(drawWidth + lineAA, drawWidth - lineAA, gridUV);
|
|
grid2 *= saturate(lineWidth / drawWidth);
|
|
grid2 = lerp(grid2, lineWidth, saturate(deriv * 2.0 - 1.0));
|
|
|
|
float grid = lerp(grid2, 1.0, grid2);
|
|
return grid;
|
|
}
|
|
|
|
float GetGrid(float3 pos, float scale, float thickness)
|
|
{
|
|
float lineWidth = thickness;
|
|
float2 coord = (pos.xz * 0.01) * scale;
|
|
|
|
float4 uvDDXY = float4(ddx(coord), ddy(coord));
|
|
|
|
float2 deriv = max(float2(length(uvDDXY.xz), length(uvDDXY.yw)), float2(MIN_DERIV, MIN_DERIV));
|
|
float2 drawWidth = clamp(lineWidth, deriv, 0.5);
|
|
float2 lineAA = deriv * 1.5;
|
|
float2 gridUV = 1.0 - abs(frac(coord) * 2.0 - 1.0);
|
|
float2 grid2 = smoothstep(drawWidth + lineAA, drawWidth - lineAA, gridUV);
|
|
grid2 *= saturate(lineWidth / drawWidth);
|
|
grid2 = lerp(grid2, lineWidth, saturate(deriv * 2.0 - 1.0));
|
|
|
|
float grid = lerp(grid2.x, 1.0, grid2.y);
|
|
return grid;
|
|
}
|
|
|
|
float4 GetColor(float3 pos, float scale)
|
|
{
|
|
float dist = 1 - saturate(distance(float3(ViewPos.x, 0, ViewPos.z), pos) / GridSize);
|
|
|
|
// Line width
|
|
float g1LW = 0.01;
|
|
// Major line Z
|
|
float l1 = GetLine(pos.x, 1, g1LW * 2);
|
|
// Major line X
|
|
float l2 = GetLine(pos.z, 1, g1LW);
|
|
|
|
// Main grid
|
|
float g1 = GetGrid(pos, 1, g1LW * 0.8);
|
|
float g2 = GetGrid(pos, 2, g1LW * 0.4);
|
|
float g3 = GetGrid(pos, 0.1, g1LW * 2);
|
|
|
|
float camFadeLarge = clamp(invLerp(2500, 4000, abs(ViewPos.y)),0, g3);
|
|
g3 *= camFadeLarge;
|
|
|
|
float g4 = GetGrid(pos, 10, g1LW);
|
|
float camFadeTiny = clamp(invLerp(150, 100, abs(ViewPos.y)), 0, g4);
|
|
g4 *= camFadeTiny;
|
|
|
|
float grid = 0;
|
|
grid = max(l1, l2);
|
|
grid = max(grid, g1);
|
|
grid = max(grid, g2);
|
|
grid = max(grid, g3);
|
|
grid = max(grid, g4);
|
|
|
|
float4 color = grid * GridColor;
|
|
color = lerp(color, float4(1,0,0,1), l2);
|
|
color = lerp(color, float4(0,0,1,1), l1);
|
|
color *= dist;
|
|
color *= 1 - saturate(length(pos) - 600000); // Fade out when far from origin (60km)
|
|
return color;
|
|
}
|
|
|
|
// Pixel shader function for grid rendering
|
|
META_PS(true, FEATURE_LEVEL_ES2)
|
|
float4 PS_Grid(PixelInput input) : SV_Target
|
|
{
|
|
float4 color = GetColor(input.WorldPosition, 1);
|
|
return color;
|
|
}
|