133 lines
4.5 KiB
HLSL
133 lines
4.5 KiB
HLSL
// XC_BUILTIN_INFINITE_GRID_D3D12_PS
|
|
cbuffer GridConstants : register(b0) {
|
|
float4x4 gViewProjectionMatrix;
|
|
float4 gCameraPositionAndScale;
|
|
float4 gCameraRightAndFade;
|
|
float4 gCameraUpAndTanHalfFov;
|
|
float4 gCameraForwardAndAspect;
|
|
float4 gViewportNearFar;
|
|
float4 gGridTransition;
|
|
};
|
|
|
|
struct VSOutput {
|
|
float4 position : SV_POSITION;
|
|
};
|
|
|
|
float PristineGridLine(float2 uv) {
|
|
float2 deriv = max(fwidth(uv), float2(1e-6, 1e-6));
|
|
float2 uvMod = frac(uv);
|
|
float2 uvDist = min(uvMod, 1.0 - uvMod);
|
|
float2 distInPixels = uvDist / deriv;
|
|
float2 lineAlpha = 1.0 - smoothstep(0.0, 1.0, distInPixels);
|
|
float density = max(deriv.x, deriv.y);
|
|
float densityFade = 1.0 - smoothstep(0.5, 1.0, density);
|
|
return max(lineAlpha.x, lineAlpha.y) * densityFade;
|
|
}
|
|
|
|
float AxisLineAA(float coord, float deriv) {
|
|
float distInPixels = abs(coord) / max(deriv, 1e-6);
|
|
return 1.0 - smoothstep(0.0, 1.5, distInPixels);
|
|
}
|
|
|
|
struct GridLayer {
|
|
float minor;
|
|
float major;
|
|
};
|
|
|
|
GridLayer SampleGridLayer(float2 worldPos2D, float baseScale) {
|
|
GridLayer layer;
|
|
const float2 gridCoord1 = worldPos2D / baseScale;
|
|
const float2 gridCoord10 = worldPos2D / (baseScale * 10.0);
|
|
const float grid1 = PristineGridLine(gridCoord1);
|
|
const float grid10 = PristineGridLine(gridCoord10);
|
|
const float2 deriv1 = fwidth(gridCoord1);
|
|
const float lodFactor = smoothstep(0.3, 0.6, max(deriv1.x, deriv1.y));
|
|
|
|
layer.major = max(grid10, grid1 * 0.35);
|
|
layer.minor = grid1 * (1.0 - lodFactor);
|
|
return layer;
|
|
}
|
|
|
|
struct PSOutput {
|
|
float4 color : SV_TARGET0;
|
|
float depth : SV_Depth;
|
|
};
|
|
|
|
PSOutput MainPS(VSOutput input) {
|
|
const float2 viewportSize = max(gViewportNearFar.xy, float2(1.0, 1.0));
|
|
const float scale = max(gCameraPositionAndScale.w, 1e-4);
|
|
const float fadeDistance = max(gCameraRightAndFade.w, scale * 10.0);
|
|
const float tanHalfFov = max(gCameraUpAndTanHalfFov.w, 1e-4);
|
|
const float aspect = max(gCameraForwardAndAspect.w, 1e-4);
|
|
const float transitionBlend = saturate(gGridTransition.x);
|
|
const float nearClip = gViewportNearFar.z;
|
|
const float sceneFarClip = gViewportNearFar.w;
|
|
|
|
const float2 ndc = float2(
|
|
(input.position.x / viewportSize.x) * 2.0 - 1.0,
|
|
1.0 - (input.position.y / viewportSize.y) * 2.0);
|
|
|
|
const float3 cameraPosition = gCameraPositionAndScale.xyz;
|
|
const float3 rayDirection = normalize(
|
|
gCameraForwardAndAspect.xyz +
|
|
ndc.x * aspect * tanHalfFov * gCameraRightAndFade.xyz +
|
|
ndc.y * tanHalfFov * gCameraUpAndTanHalfFov.xyz);
|
|
|
|
if (abs(rayDirection.y) < 1e-5) {
|
|
discard;
|
|
}
|
|
|
|
const float t = -cameraPosition.y / rayDirection.y;
|
|
if (t <= nearClip) {
|
|
discard;
|
|
}
|
|
|
|
const float3 worldPosition = cameraPosition + rayDirection * t;
|
|
float depth = 0.999999;
|
|
if (t < sceneFarClip) {
|
|
const float4 clipPosition = mul(gViewProjectionMatrix, float4(worldPosition, 1.0));
|
|
if (clipPosition.w <= 1e-6) {
|
|
discard;
|
|
}
|
|
|
|
depth = clipPosition.z / clipPosition.w;
|
|
if (depth <= 0.0 || depth >= 1.0) {
|
|
discard;
|
|
}
|
|
}
|
|
|
|
const float radialFade =
|
|
1.0 - smoothstep(fadeDistance * 0.3, fadeDistance, length(worldPosition - cameraPosition));
|
|
const float normalFade = smoothstep(0.0, 0.15, abs(rayDirection.y));
|
|
const float fadeFactor = radialFade * normalFade;
|
|
if (fadeFactor < 1e-3) {
|
|
discard;
|
|
}
|
|
|
|
const float2 worldPos2D = worldPosition.xz;
|
|
const GridLayer baseLayer = SampleGridLayer(worldPos2D, scale);
|
|
const GridLayer nextLayer = SampleGridLayer(worldPos2D, scale * 10.0);
|
|
const float minorGridIntensity = lerp(baseLayer.minor, nextLayer.minor, transitionBlend);
|
|
const float majorGridIntensity = lerp(baseLayer.major, nextLayer.major, transitionBlend);
|
|
float3 finalColor = float3(0.56, 0.56, 0.56);
|
|
float finalAlpha = max(
|
|
0.13 * minorGridIntensity * fadeFactor,
|
|
0.28 * majorGridIntensity * fadeFactor);
|
|
|
|
const float2 worldDeriv = max(fwidth(worldPos2D), float2(1e-6, 1e-6));
|
|
const float xAxisAlpha = AxisLineAA(worldPos2D.y, worldDeriv.y) * fadeFactor;
|
|
const float zAxisAlpha = AxisLineAA(worldPos2D.x, worldDeriv.x) * fadeFactor;
|
|
|
|
const float axisAlpha = max(xAxisAlpha, zAxisAlpha);
|
|
finalAlpha = max(finalAlpha, 0.34 * saturate(axisAlpha));
|
|
|
|
if (finalAlpha < 1e-3) {
|
|
discard;
|
|
}
|
|
|
|
PSOutput output;
|
|
output.color = float4(finalColor, finalAlpha);
|
|
output.depth = depth;
|
|
return output;
|
|
}
|