feat: Main shader LOD detail map

This commit is contained in:
Alexandre Coirier
2026-06-02 07:55:45 +02:00
parent 2f3cd8dc7e
commit 713933b932
16 changed files with 2496 additions and 338 deletions
File diff suppressed because it is too large Load Diff
@@ -33,7 +33,6 @@ float3 GetScale(float3 PivotWS)
float GetShadow(float3 PositionWS)
{
float4 shadowCoord = TransformWorldToShadowCoord(PositionWS);
Light mainLight = GetMainLight(shadowCoord);
float shadow = 1 - mainLight.shadowAttenuation;
@@ -52,6 +51,31 @@ float GetShadow(float3 PositionWS)
return saturate(shadow);
}
void GetDetailLOD
(
float Depth,
float DetailSize,
float LODJitter,
out float DetailSizeA,
out float DetailSizeB,
out float LODBlend
)
{
const float lodRatio = 4;
const float lodSize = DetailSize / lodRatio * 2;
float dist = max(Depth, 1e-5);
float lod = log(dist) / log(lodRatio) + LODJitter; // log2(dist);
float lodFloor = floor(lod);
float lodFrac = lod - lodFloor;
LODBlend = lodFrac * lodFrac * (3 - 2 * lodFrac);
DetailSizeA = lodSize * pow(lodRatio, lodFloor);
DetailSizeB = lodSize * pow(lodRatio, lodFloor + 1);
}
float4 SampleBombedTexture
(
UnityTexture2D Tex,
@@ -116,7 +140,7 @@ ProjectionData GetProjections
(
float3 PositionOS,
float3 NormalOS,
float Blend
float ProjectionBlend
)
{
ProjectionData data;
@@ -134,7 +158,7 @@ ProjectionData GetProjections
float3(0, 0, 1)
};
float sharpness = lerp(2, 32, saturate(Blend));
float sharpness = lerp(2, 32, saturate(ProjectionBlend));
float maskSum = 0;
@@ -171,6 +195,69 @@ ProjectionData GetProjections
return data;
}
float4 SampleProjectedDetailLOD
(
UnityTexture2D DetailTex,
float3 PositionOS,
float3 NormalOS,
float ProjectionBlend,
float DetailSize,
float Depth
)
{
const float lodJitterStrength = .8;
const float lodJitterSize = 1.5;
float4 detail = 0;
float totalMask = 0;
ProjectionData projections = GetProjections
(
PositionOS,
NormalOS,
ProjectionBlend
);
[unroll]
for (int i = 0; i < 7; i++)
{
float mask = projections.mask[i];
float lodJitter = (Hash1From2D(floor(projections.uv[i] * lodJitterSize) + i * 17.13) - .5) * lodJitterStrength;
float detailSizeA;
float detailSizeB;
float lodBlend;
GetDetailLOD
(
Depth,
DetailSize,
lodJitter,
detailSizeA,
detailSizeB,
lodBlend
);
float4 detailA = SampleBombedTexture
(
DetailTex,
projections.uv[i] / detailSizeA
);
float4 detailB = SampleBombedTexture
(
DetailTex,
projections.uv[i] / detailSizeB
);
detail += lerp(detailA, detailB, lodBlend) * mask;
totalMask += mask;
}
return detail / max(totalMask, 1e-5);
}
void EnkiBillal_float
(
float4 Color,
@@ -179,6 +266,10 @@ void EnkiBillal_float
float3 PositionWS,
float3 NormalWS,
float ProjectionsBlend,
float DetailSize,
float4 FogColor,
float FogMin,
float FogMax,
out float3 Output
)
{
@@ -201,38 +292,26 @@ void EnkiBillal_float
// Detail
float4 detail = 0;
ProjectionData projections = GetProjections
float4 detail = SampleProjectedDetailLOD
(
DetailTex,
positionOS,
normalOS,
ProjectionsBlend
ProjectionsBlend,
DetailSize,
depth
);
float totalMask = 0;
[unroll]
for (int i = 0; i < 7; i++)
{
float mask = projections.mask[i];
detail += SampleBombedTexture
(
DetailTex,
projections.uv[i]
) * mask;
totalMask += mask;
}
detail /= max(totalMask, 1e-5);
float detailMask = smoothstep(0, .8, detail.a);
// Fog
// Output
Output = Color.rgb;
Output = lerp(Color.rgb, Color.rgb * detail.rgb, detail.a);
//Output *= shadowAtten;
Output = lerp(Output.rgb, detail.rgb, detailMask);
Output = lerp(Output.rgb, FogColor.rgb, smoothstep(FogMin, FogMax, depth) * FogColor.a);
}
#endif