feat(rendering): add volumetric performance coverage

This commit is contained in:
2026-04-19 00:27:13 +08:00
parent d2017b251c
commit f4fef59b2f
7 changed files with 501 additions and 25 deletions

View File

@@ -9,6 +9,9 @@ Shader "Builtin Volumetric"
_AmbientStrength ("Ambient Strength", Float) = 0.005
_LightDirection ("Light Direction", Vector) = (0.5, 0.8, 0.3, 0.0)
_LightSamples ("Light Samples", Float) = 8.0
_EnableEntryHdda ("Enable Entry HDDA", Float) = 1.0
_EnableEmptySpaceSkipping ("Enable Empty Space Skipping", Float) = 1.0
_EnableEarlyTermination ("Enable Early Termination", Float) = 1.0
}
HLSLINCLUDE
#define PNANOVDB_HLSL
@@ -41,6 +44,9 @@ Shader "Builtin Volumetric"
float4 gAmbientStrength;
float4 gLightDirection;
float4 gLightSamples;
float4 gEnableEntryHdda;
float4 gEnableEmptySpaceSkipping;
float4 gEnableEarlyTermination;
};
StructuredBuffer<uint> VolumeData;
@@ -192,6 +198,9 @@ Shader "Builtin Volumetric"
const int maxSteps = max((int)gMaxSteps.x, 1);
const float ambientStrength = max(gAmbientStrength.x, 0.0f);
const float lightSamples = max(gLightSamples.x, 0.0f);
const bool enableEntryHdda = gEnableEntryHdda.x >= 0.5f;
const bool enableEmptySpaceSkipping = gEnableEmptySpaceSkipping.x >= 0.5f;
const bool enableEarlyTermination = gEnableEarlyTermination.x >= 0.5f;
const float3 cameraLocalPosition =
mul(gInverseModelMatrix, float4(gCameraWorldPosition.xyz, 1.0f)).xyz;
@@ -206,7 +215,8 @@ Shader "Builtin Volumetric"
const bool cameraInside = IsPointInsideAabb(cameraLocalPosition, boxMin, boxMax);
const float surfaceT = cameraInside ? tExit : max(tEnter, 0.0f);
const float3 expectedSurfacePosition = cameraLocalPosition + rayDirection * surfaceT;
if (distance(expectedSurfacePosition, input.localPosition) > stepSize * 1.5f + 0.01f) {
const float surfaceTolerance = max(stepSize * 1.5f, 1.0f);
if (distance(expectedSurfacePosition, input.localPosition) > surfaceTolerance + 0.01f) {
discard;
}
@@ -216,14 +226,14 @@ Shader "Builtin Volumetric"
NanoVolume volume;
InitNanoVolume(volume);
if (!GetHddaHit(volume.accessor, t, cameraLocalPosition, rayDirection, marchEnd, hitValue)) {
if (enableEntryHdda &&
!GetHddaHit(volume.accessor, t, cameraLocalPosition, rayDirection, marchEnd, hitValue)) {
discard;
}
float skipDistance = 0.0f;
float3 integratedLight = 0.0f.xxx;
float transmittance = 1.0f;
float accumulatedDensity = 0.0f;
float3 resolvedLightDirectionWS = gLightDirection.xyz;
float3 resolvedLightRadiance = 1.0f.xxx;
@@ -251,21 +261,23 @@ Shader "Builtin Volumetric"
}
float3 localPosition = cameraLocalPosition + rayDirection * t;
const uint dim = GetDimCoord(volume.accessor, localPosition);
if (dim > 1u) {
const uint dim = enableEmptySpaceSkipping
? GetDimCoord(volume.accessor, localPosition)
: 1u;
if (enableEmptySpaceSkipping && dim > 1u) {
skipDistance = 15.0f;
t += skipDistance;
continue;
}
float density = GetValueCoord(volume.accessor, localPosition) * densityScale;
if (density < 0.01f) {
float density = max(GetValueCoord(volume.accessor, localPosition) * densityScale, 0.0f);
if (enableEmptySpaceSkipping && density < 0.01f) {
skipDistance = 5.0f;
t += skipDistance;
continue;
}
if (skipDistance > 0.0f) {
if (enableEmptySpaceSkipping && skipDistance > 0.0f) {
t -= skipDistance * 0.8f;
localPosition = cameraLocalPosition + rayDirection * t;
skipDistance = 0.0f;
@@ -273,7 +285,6 @@ Shader "Builtin Volumetric"
const float sigmaS = density;
const float sigmaE = max(0.000001f, sigmaS);
accumulatedDensity += sigmaS;
const float shadow =
ComputeVolumetricShadow(
@@ -283,15 +294,12 @@ Shader "Builtin Volumetric"
lightSamples,
volume.accessor);
const float3 S = sigmaS * shadow.xxx * resolvedLightRadiance;
const float3 integratedSegment = (S - S * exp(-sigmaE * stepSize)) / sigmaE;
const float segmentTransmittance = exp(-sigmaE * stepSize);
const float3 integratedSegment = (S - S * segmentTransmittance) / sigmaE;
integratedLight += transmittance * integratedSegment;
transmittance *= exp(-sigmaE * stepSize);
transmittance *= segmentTransmittance;
if (accumulatedDensity > 1.0f) {
break;
}
if (transmittance < 0.05f) {
if (enableEarlyTermination && transmittance < 0.05f) {
transmittance = 0.0f;
break;
}
@@ -300,11 +308,12 @@ Shader "Builtin Volumetric"
}
const float3 ambientLight = ambientStrength.xxx;
float3 finalColor = (integratedLight + ambientLight) * accumulatedDensity;
const float opacity = saturate(1.0f - transmittance);
float3 finalColor = integratedLight + ambientLight * opacity;
finalColor *= gVolumeTint.rgb;
finalColor = pow(max(finalColor, 0.0f.xxx), 1.0f / 2.2f);
const float alpha = saturate(accumulatedDensity) * saturate(gVolumeTint.a);
const float alpha = opacity * saturate(gVolumeTint.a);
if (alpha <= 0.001f) {
discard;
}