Fix code style

This commit is contained in:
Wojtek Figat
2020-12-22 13:45:02 +01:00
parent 760d586923
commit 4fe91d57b7
12 changed files with 151 additions and 182 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -25,9 +25,9 @@ float D_GGX(float roughness, float NoH)
float Vis_Schlick(float roughness, float NoV, float NoL)
{
float k = Square(roughness) * 0.5;
float vis_SchlickV = NoV * (1 - k) + k;
float vis_SchlickL = NoL * (1 - k) + k;
return 0.25 / (vis_SchlickV * vis_SchlickL);
float visSchlickV = NoV * (1 - k) + k;
float visSchlickL = NoL * (1 - k) + k;
return 0.25 / (visSchlickV * visSchlickL);
}
// Smith term for GGX
@@ -36,9 +36,9 @@ float Vis_Smith(float roughness, float NoV, float NoL)
{
float a = Square(roughness);
float a2 = a * a;
float vis_SmithV = NoV + sqrt(NoV * (NoV - NoV * a2) + a2);
float vis_SmithL = NoL + sqrt(NoL * (NoL - NoL * a2) + a2);
return rcp(vis_SmithV * vis_SmithL);
float visSmithV = NoV + sqrt(NoV * (NoV - NoV * a2) + a2);
float visSmithL = NoL + sqrt(NoL * (NoL - NoL * a2) + a2);
return rcp(visSmithV * visSmithL);
}
// Appoximation of joint Smith term for GGX
@@ -74,7 +74,7 @@ half SSRMipFromRoughness(half roughness)
return max(1, 10 - mip1px);
}
float ComputeReflectionCaptureRoughnessFromMip(float mip)
float ProbeRoughnessFromMip(float mip)
{
float mip1px = REFLECTION_CAPTURE_NUM_MIPS - 1 - mip;
return exp2((REFLECTION_CAPTURE_ROUGHEST_MIP - mip1px) / REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE);
@@ -99,8 +99,6 @@ float3 EnvBRDF(Texture2D preIntegratedGF, float3 specularColor, float roughness,
return specularColor * ab.x + saturate(50.0 * specularColor.g) * ab.y;
}
#define MAX_SPECULAR_POWER 10000000000.0f
float RoughnessToSpecularPower(float roughness)
{
return pow(2, 13 * (1 - roughness));

View File

@@ -264,37 +264,33 @@ META_VS(true, FEATURE_LEVEL_SM4)
META_FLAG(VertexToGeometryShader)
META_VS_IN_ELEMENT(POSITION, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
META_VS_IN_ELEMENT(TEXCOORD, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
Quad_VS2GS VS_WriteToSlice(float2 Position : POSITION0, float2 TexCoord : TEXCOORD0, uint LayerIndex : SV_InstanceID)
Quad_VS2GS VS_WriteToSlice(float2 position : POSITION0, float2 texCoord : TEXCOORD0, uint layerIndex : SV_InstanceID)
{
Quad_VS2GS output;
output.Vertex.Position = float4(Position, 0, 1);
output.Vertex.TexCoord = TexCoord;
output.LayerIndex = LayerIndex;
output.Vertex.Position = float4(position, 0, 1);
output.Vertex.TexCoord = texCoord;
output.LayerIndex = layerIndex;
return output;
}
// Geometry shader that writes to a range of slices of a volume texture
META_GS(true, FEATURE_LEVEL_SM4)
[maxvertexcount(3)]
void GS_WriteToSlice(triangle Quad_VS2GS input[3], inout TriangleStream<Quad_GS2PS> OutStream)
void GS_WriteToSlice(triangle Quad_VS2GS input[3], inout TriangleStream<Quad_GS2PS> stream)
{
Quad_GS2PS vertex0;
vertex0.Vertex = input[0].Vertex;
vertex0.LayerIndex = input[0].LayerIndex;
Quad_GS2PS vertex;
Quad_GS2PS vertex1;
vertex1.Vertex = input[1].Vertex;
vertex1.LayerIndex = input[1].LayerIndex;
vertex.Vertex = input[0].Vertex;
vertex.LayerIndex = input[0].LayerIndex;
stream.Append(vertex);
Quad_GS2PS vertex2;
vertex2.Vertex = input[2].Vertex;
vertex2.LayerIndex = input[2].LayerIndex;
vertex.Vertex = input[1].Vertex;
vertex.LayerIndex = input[1].LayerIndex;
stream.Append(vertex);
OutStream.Append(vertex0);
OutStream.Append(vertex1);
OutStream.Append(vertex2);
vertex.Vertex = input[2].Vertex;
vertex.LayerIndex = input[2].LayerIndex;
stream.Append(vertex);
}
META_PS(true, FEATURE_LEVEL_ES2)

View File

@@ -571,9 +571,9 @@ StructuredBuffer<BokehPoint> BokehPointBuffer : register(t2);
// Vertex Shader, positions and scales the bokeh point
META_VS(true, FEATURE_LEVEL_SM5)
META_FLAG(VertexToGeometryShader)
BokehVSOutput VS_Bokeh(in uint VertexID : SV_VertexID)
BokehVSOutput VS_Bokeh(in uint vertexID : SV_VertexID)
{
BokehPoint bPoint = BokehPointBuffer[VertexID];
BokehPoint bPoint = BokehPointBuffer[vertexID];
BokehVSOutput output;
// Position the vertex in normalized device coordinate space [-1, 1]
@@ -599,7 +599,7 @@ BokehVSOutput VS_Bokeh(in uint VertexID : SV_VertexID)
// Geometry Shader, expands a vertex into a quad with two triangles
META_GS(true, FEATURE_LEVEL_SM5)
[maxvertexcount(4)]
void GS_Bokeh(point BokehVSOutput input[1], inout TriangleStream<BokehGSOutput> SpriteStream)
void GS_Bokeh(point BokehVSOutput input[1], inout TriangleStream<BokehGSOutput> stream)
{
BokehGSOutput output;
@@ -613,9 +613,9 @@ void GS_Bokeh(point BokehVSOutput input[1], inout TriangleStream<BokehGSOutput>
output.Color = input[0].Color;
output.Depth = input[0].Depth;
SpriteStream.Append(output);
stream.Append(output);
}
SpriteStream.RestartStrip();
stream.RestartStrip();
}
// Pixel Shader, applies the bokeh shape texture

View File

@@ -29,29 +29,29 @@ struct ExponentialHeightFogData
float StartDistance;
};
half4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, float3 worldPosition, float3 cameraPosition, float excludeDistance)
float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, float3 posWS, float3 camWS, float skipDistance)
{
float3 cameraToReceiver = worldPosition - cameraPosition;
float cameraToReceiverLengthSqr = dot(cameraToReceiver, cameraToReceiver);
float cameraToReceiverLengthInv = rsqrt(cameraToReceiverLengthSqr);
float cameraToReceiverLength = cameraToReceiverLengthSqr * cameraToReceiverLengthInv;
half3 cameraToReceiverNormalized = cameraToReceiver * cameraToReceiverLengthInv;
float3 cameraToPos = posWS - camWS;
float cameraToPosSqr = dot(cameraToPos, cameraToPos);
float cameraToPosLenInv = rsqrt(cameraToPosSqr);
float cameraToPosLen = cameraToPosSqr * cameraToPosLenInv;
float3 cameraToReceiverNorm = cameraToPos * cameraToPosLenInv;
float rayOriginTerms = exponentialHeightFog.FogAtViewPosition;
float rayLength = cameraToReceiverLength;
float rayDirectionY = cameraToReceiver.y;
float rayLength = cameraToPosLen;
float rayDirectionY = cameraToPos.y;
// Apply start distance offset
excludeDistance = max(excludeDistance, exponentialHeightFog.StartDistance);
if (excludeDistance > 0)
skipDistance = max(skipDistance, exponentialHeightFog.StartDistance);
if (skipDistance > 0)
{
float excludeIntersectionTime = excludeDistance * cameraToReceiverLengthInv;
float cameraToExclusionIntersectionY = excludeIntersectionTime * cameraToReceiver.y;
float exclusionIntersectionY = cameraPosition.y + cameraToExclusionIntersectionY;
float exclusionIntersectionToReceiverY = cameraToReceiver.y - cameraToExclusionIntersectionY;
float excludeIntersectionTime = skipDistance * cameraToPosLenInv;
float cameraToExclusionIntersectionY = excludeIntersectionTime * cameraToPos.y;
float exclusionIntersectionY = camWS.y + cameraToExclusionIntersectionY;
float exclusionIntersectionToReceiverY = cameraToPos.y - cameraToExclusionIntersectionY;
// Calculate fog off of the ray starting from the exclusion distance, instead of starting from the camera
rayLength = (1.0f - excludeIntersectionTime) * cameraToReceiverLength;
rayLength = (1.0f - excludeIntersectionTime) * cameraToPosLen;
rayDirectionY = exclusionIntersectionToReceiverY;
// Move off the viewer
@@ -67,22 +67,22 @@ half4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, flo
float exponentialHeightLineIntegral = exponentialHeightLineIntegralCalc * rayLength;
// Calculate the amount of light that made it through the fog using the transmission equation
half expFogFactor = max(saturate(exp2(-exponentialHeightLineIntegral)), exponentialHeightFog.FogMinOpacity);
float expFogFactor = max(saturate(exp2(-exponentialHeightLineIntegral)), exponentialHeightFog.FogMinOpacity);
// Calculate the directional light inscattering
half3 inscatteringColor = exponentialHeightFog.FogInscatteringColor;
half3 directionalInscattering = 0;
float3 inscatteringColor = exponentialHeightFog.FogInscatteringColor;
float3 directionalInscattering = 0;
BRANCH
if (exponentialHeightFog.ApplyDirectionalInscattering > 0)
{
// Setup a cosine lobe around the light direction to approximate inscattering from the directional light off of the ambient haze
half3 directionalLightInscattering = exponentialHeightFog.DirectionalInscatteringColor * pow(saturate(dot(cameraToReceiverNormalized, exponentialHeightFog.InscatteringLightDirection)), exponentialHeightFog.DirectionalInscatteringExponent);
float3 directionalLightInscattering = exponentialHeightFog.DirectionalInscatteringColor * pow(saturate(dot(cameraToReceiverNorm, exponentialHeightFog.InscatteringLightDirection)), exponentialHeightFog.DirectionalInscatteringExponent);
// Calculate the line integral of the eye ray through the haze, using a special starting distance to limit the inscattering to the distance
float dirExponentialHeightLineIntegral = exponentialHeightLineIntegralCalc * max(rayLength - exponentialHeightFog.DirectionalInscatteringStartDistance, 0.0f);
// Calculate the amount of light that made it through the fog using the transmission equation
half directionalInscatteringFogFactor = saturate(exp2(-dirExponentialHeightLineIntegral));
float directionalInscatteringFogFactor = saturate(exp2(-dirExponentialHeightLineIntegral));
// Final inscattering from the light
directionalInscattering = directionalLightInscattering * (1 - directionalInscatteringFogFactor);
@@ -90,13 +90,13 @@ half4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, flo
// Disable fog after a certain distance
FLATTEN
if (exponentialHeightFog.FogCutoffDistance > 0 && cameraToReceiverLength > exponentialHeightFog.FogCutoffDistance)
if (exponentialHeightFog.FogCutoffDistance > 0 && cameraToPosLen > exponentialHeightFog.FogCutoffDistance)
{
expFogFactor = 1;
directionalInscattering = 0;
}
return half4((inscatteringColor) * (1 - expFogFactor) + directionalInscattering, expFogFactor);
return float4(inscatteringColor * (1.0f - expFogFactor) + directionalInscattering, expFogFactor);
}
#endif

View File

@@ -33,15 +33,15 @@ float3 GetWorldPos(float2 uv)
return mul(float4(viewPos, 1), gBufferData.InvViewMatrix).xyz;
}
float4 CalculateCombinedFog(float3 worldPosition, float sceneDepth, float3 volumeUV)
float4 CalculateCombinedFog(float3 posWS, float sceneDepth, float3 volumeUV)
{
float excludeDistance = 0;
float skipDistance = 0;
#if VOLUMETRIC_FOG
excludeDistance = max(ExponentialHeightFog.VolumetricFogMaxDistance - 100, 0);
skipDistance = max(ExponentialHeightFog.VolumetricFogMaxDistance - 100, 0);
#endif
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, worldPosition, GBuffer.ViewPos, excludeDistance);
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, posWS, GBuffer.ViewPos, skipDistance);
#if VOLUMETRIC_FOG
float4 volumetricFog = IntegratedLightScattering.SampleLevel(SamplerLinearClamp, volumeUV, 0);
@@ -57,8 +57,8 @@ META_PERMUTATION_1(VOLUMETRIC_FOG=1)
float4 PS_Fog(Quad_VS2PS input) : SV_Target0
{
// Calculate pixel world space position
float3 worldPosition = GetWorldPos(input.TexCoord);
float3 viewVector = worldPosition - GBuffer.ViewPos;
float3 posWS = GetWorldPos(input.TexCoord);
float3 viewVector = posWS - GBuffer.ViewPos;
float sceneDepth = length(viewVector);
// Calculate volumetric fog coordinates
@@ -67,17 +67,17 @@ float4 PS_Fog(Quad_VS2PS input) : SV_Target0
// Debug code
#if VOLUMETRIC_FOG && 0
volumeUV = worldPosition / 1000;
volumeUV = posWS / 1000;
if (!all(volumeUV >= 0 && volumeUV <= 1))
return 0;
return float4(IntegratedLightScattering.SampleLevel(SamplerLinearClamp, volumeUV, 0).rgb, 1);
//return float4(volumeUV, 1);
//return float4(worldPosition / 100, 1);
//return float4(posWS / 100, 1);
#endif
// Calculate fog color
float4 fog = CalculateCombinedFog(worldPosition, sceneDepth, volumeUV);
float4 fog = CalculateCombinedFog(posWS, sceneDepth, volumeUV);
return fog;
}

View File

@@ -65,7 +65,7 @@ float4 PS_FilterFace(Quad_VS2PS input) : SV_Target
#define NUM_FILTER_SAMPLES 512
float3 N = normalize(cubeCoordinates);
float roughness = ComputeReflectionCaptureRoughnessFromMip(SourceMipIndex);
float roughness = ProbeRoughnessFromMip(SourceMipIndex);
float4 filteredColor = 0;
float weight = 0;

View File

@@ -61,7 +61,7 @@ META_CB_END
META_CB_BEGIN(1, PerLight)
float2 Dummy1;
int MinZ; // Z index of the minimum slice in the range
int MinZ;
float LocalLightScatteringIntensity;
float4 ViewSpaceBoundingSphere;
@@ -72,48 +72,44 @@ LightShadowData LocalLightShadow;
META_CB_END
float ComputeDepthFromZSlice(float zSlice)
{
return (zSlice / GridSize.z) * VolumetricFogMaxDistance;
}
float3 ComputeCellWorldPosition(uint3 gridCoordinate, float3 cellOffset, out float sceneDepth)
{
float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy;
sceneDepth = ComputeDepthFromZSlice(gridCoordinate.z + cellOffset.z) / GBuffer.ViewFar;
float deviceDepth = LinearZ2DeviceDepth(GBuffer, sceneDepth);
return GetWorldPos(GBuffer, volumeUV, deviceDepth);
}
float3 ComputeCellWorldPosition(uint3 gridCoordinate, float3 cellOffset)
{
float unused;
return ComputeCellWorldPosition(gridCoordinate, cellOffset, unused);
}
float ComputeNormalizedZSliceFromDepth(float sceneDepth)
{
return sceneDepth / VolumetricFogMaxDistance;
}
float3 ComputeVolumeUV(float3 worldPosition, float4x4 worldToClip)
{
float4 ndcPosition = mul(float4(worldPosition, 1), worldToClip);
ndcPosition.xy /= ndcPosition.w;
return float3(ndcPosition.xy * float2(0.5f, -0.5f) + 0.5f, ComputeNormalizedZSliceFromDepth(ndcPosition.w));
}
// The Henyey-Greenstein phase function
// [Henyey and Greenstein 1941, https://www.astro.umd.edu/~jph/HG_note.pdf]
float HenyeyGreensteinPhase(float g, float cosTheta)
{
return (1 - g * g) / (4 * PI * pow(1 + g * g + 2 * g * cosTheta, 1.5f));
}
// +g = forward scattering, 0=g = isotropic, -g = backward scattering
float PhaseFunction(float g, float cosTheta)
float GetPhase(float g, float cosTheta)
{
return HenyeyGreensteinPhase(g, cosTheta);
}
float GetSliceDepth(float zSlice)
{
return (zSlice / GridSize.z) * VolumetricFogMaxDistance;
}
float3 GetCellPositionWS(uint3 gridCoordinate, float3 cellOffset, out float sceneDepth)
{
float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy;
sceneDepth = GetSliceDepth(gridCoordinate.z + cellOffset.z) / GBuffer.ViewFar;
float deviceDepth = LinearZ2DeviceDepth(GBuffer, sceneDepth);
return GetWorldPos(GBuffer, volumeUV, deviceDepth);
}
float3 GetCellPositionWS(uint3 gridCoordinate, float3 cellOffset)
{
float temp;
return GetCellPositionWS(gridCoordinate, cellOffset, temp);
}
float3 GetVolumeUV(float3 worldPosition, float4x4 worldToClip)
{
float4 ndcPosition = mul(float4(worldPosition, 1), worldToClip);
ndcPosition.xy /= ndcPosition.w;
return float3(ndcPosition.xy * float2(0.5f, -0.5f) + 0.5f, ndcPosition.w / VolumetricFogMaxDistance);
}
// Vertex shader that writes to a range of slices of a volume texture
META_VS(true, FEATURE_LEVEL_SM5)
META_FLAG(VertexToGeometryShader)
@@ -123,22 +119,18 @@ Quad_VS2GS VS_WriteToSlice(float2 TexCoord : TEXCOORD0, uint LayerIndex : SV_Ins
Quad_VS2GS output;
uint slice = LayerIndex + MinZ;
float sliceDepth = ComputeDepthFromZSlice(slice);
float sliceDepthOffset = abs(sliceDepth - ViewSpaceBoundingSphere.z);
float depth = GetSliceDepth(slice);
float depthOffset = abs(depth - ViewSpaceBoundingSphere.z);
if (sliceDepthOffset < ViewSpaceBoundingSphere.w)
if (depthOffset < ViewSpaceBoundingSphere.w)
{
// Compute the radius of the circle formed by the intersection of the bounding sphere and the current depth slice
float sliceRadius = sqrt(ViewSpaceBoundingSphere.w * ViewSpaceBoundingSphere.w - sliceDepthOffset * sliceDepthOffset);
// Place the quad vertex to tightly bound the circle
float3 viewSpaceVertexPosition = float3(ViewSpaceBoundingSphere.xy + (TexCoord * 2 - 1) * sliceRadius, sliceDepth);
output.Vertex.Position = mul(float4(viewSpaceVertexPosition, 1), ViewToVolumeClip);
float radius = sqrt(ViewSpaceBoundingSphere.w * ViewSpaceBoundingSphere.w - depthOffset * depthOffset);
float3 positionVS = float3(ViewSpaceBoundingSphere.xy + (TexCoord * 2 - 1) * radius, depth);
output.Vertex.Position = mul(float4(positionVS, 1), ViewToVolumeClip);
}
else
{
// Slice does not intersect bounding sphere, emit degenerate triangle
output.Vertex.Position = 0;
output.Vertex.Position = float4(0, 0, 0, 0);
}
output.Vertex.TexCoord = 0;
@@ -150,23 +142,21 @@ Quad_VS2GS VS_WriteToSlice(float2 TexCoord : TEXCOORD0, uint LayerIndex : SV_Ins
// Geometry shader that writes to a range of slices of a volume texture
META_GS(true, FEATURE_LEVEL_SM5)
[maxvertexcount(3)]
void GS_WriteToSlice(triangle Quad_VS2GS input[3], inout TriangleStream<Quad_GS2PS> OutStream)
void GS_WriteToSlice(triangle Quad_VS2GS input[3], inout TriangleStream<Quad_GS2PS> stream)
{
Quad_GS2PS vertex0;
vertex0.Vertex = input[0].Vertex;
vertex0.LayerIndex = input[0].LayerIndex;
Quad_GS2PS vertex;
Quad_GS2PS vertex1;
vertex1.Vertex = input[1].Vertex;
vertex1.LayerIndex = input[1].LayerIndex;
vertex.Vertex = input[0].Vertex;
vertex.LayerIndex = input[0].LayerIndex;
stream.Append(vertex);
Quad_GS2PS vertex2;
vertex2.Vertex = input[2].Vertex;
vertex2.LayerIndex = input[2].LayerIndex;
vertex.Vertex = input[1].Vertex;
vertex.LayerIndex = input[1].LayerIndex;
stream.Append(vertex);
OutStream.Append(vertex0);
OutStream.Append(vertex1);
OutStream.Append(vertex2);
vertex.Vertex = input[2].Vertex;
vertex.LayerIndex = input[2].LayerIndex;
stream.Append(vertex);
}
#if USE_SHADOW
@@ -208,18 +198,16 @@ float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0
return 0;
#if USE_TEMPORAL_REPROJECTION
float3 historyUV = ComputeVolumeUV(ComputeCellWorldPosition(gridCoordinate, 0.5f), PrevWorldToClip);
float3 historyUV = GetVolumeUV(GetCellPositionWS(gridCoordinate, 0.5f), PrevWorldToClip);
float historyAlpha = HistoryWeight;
FLATTEN
if (any(historyUV < 0) || any(historyUV > 1))
{
historyAlpha = 0;
}
uint numSuperSamples = historyAlpha < .001f ? HistoryMissSuperSampleCount : 1;
uint samplesCount = historyAlpha < 0.001f ? HistoryMissSuperSampleCount : 1;
#else
uint numSuperSamples = 1;
uint samplesCount = 1;
#endif
float3 L = 0;
@@ -229,22 +217,19 @@ float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0
float lightRadiusMask = 1;
float spotAttenuation = 1;
bool isSpotLight = LocalLight.SpotAngles.x > -2.0f;
float4 scattering = 0;
for (uint sampleIndex = 0; sampleIndex < numSuperSamples; sampleIndex++)
for (uint sampleIndex = 0; sampleIndex < samplesCount; sampleIndex++)
{
float3 cellOffset = FrameJitterOffsets[sampleIndex].xyz;
//float cellOffset = 0.5f;
float3 worldPosition = ComputeCellWorldPosition(gridCoordinate, cellOffset);
float3 cameraVector = normalize(worldPosition - GBuffer.ViewPos);
float cellRadius = length(worldPosition - ComputeCellWorldPosition(gridCoordinate + uint3(1, 1, 1), cellOffset));
// Bias the inverse squared light falloff based on voxel size to prevent aliasing near the light source
float3 positionWS = GetCellPositionWS(gridCoordinate, cellOffset);
float3 cameraVector = normalize(positionWS - GBuffer.ViewPos);
float cellRadius = length(positionWS - GetCellPositionWS(gridCoordinate + uint3(1, 1, 1), cellOffset));
float distanceBias = max(cellRadius * InverseSquaredLightDistanceBiasScale, 1);
// Get the light attenuation
GetRadialLightAttenuation(LocalLight, isSpotLight, worldPosition, float3(0, 0, 1), distanceBias * distanceBias, toLight, L, NoL, distanceAttenuation, lightRadiusMask, spotAttenuation);
// Calculate the light attenuation
GetRadialLightAttenuation(LocalLight, isSpotLight, positionWS, float3(0, 0, 1), distanceBias * distanceBias, toLight, L, NoL, distanceAttenuation, lightRadiusMask, spotAttenuation);
float combinedAttenuation = distanceAttenuation * lightRadiusMask * spotAttenuation;
// Peek the shadow
@@ -252,16 +237,14 @@ float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0
#if USE_SHADOW
if (combinedAttenuation > 0)
{
shadowFactor = ComputeVolumeShadowing(worldPosition, isSpotLight);
shadowFactor = ComputeVolumeShadowing(positionWS, isSpotLight);
}
#endif
scattering.rgb += LocalLight.Color * (PhaseFunction(PhaseG, dot(L, -cameraVector)) * combinedAttenuation * shadowFactor * LocalLightScatteringIntensity);
scattering.rgb += LocalLight.Color * (GetPhase(PhaseG, dot(L, -cameraVector)) * combinedAttenuation * shadowFactor * LocalLightScatteringIntensity);
}
// Normalize
scattering.rgb /= (float)numSuperSamples;
scattering.rgb /= (float)samplesCount;
return scattering;
}
@@ -280,7 +263,7 @@ void CS_Initialize(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_Dispa
// Center of the voxel
float voxelOffset = 0.5f;
float3 worldPosition = ComputeCellWorldPosition(gridCoordinate, voxelOffset);
float3 positionWS = GetCellPositionWS(gridCoordinate, voxelOffset);
// Unpack the fog parameters (packing done in C++ ExponentialHeightFog::GetVolumetricFogOptions)
float fogDensity = FogParameters.x;
@@ -288,7 +271,7 @@ void CS_Initialize(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_Dispa
float fogHeightFalloff = FogParameters.z;
// Calculate the global fog density that matches the exponential height fog density
float globalDensity = fogDensity * exp2(-fogHeightFalloff * (worldPosition.y - fogHeight));
float globalDensity = fogDensity * exp2(-fogHeightFalloff * (positionWS.y - fogHeight));
float matchFactor = 0.24f;
float extinction = max(globalDensity * GlobalExtinctionScale * matchFactor, 0);
@@ -326,7 +309,7 @@ void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_
uint numSuperSamples = 1;
#if USE_TEMPORAL_REPROJECTION
float3 historyUV = ComputeVolumeUV(ComputeCellWorldPosition(gridCoordinate, 0.5f), PrevWorldToClip);
float3 historyUV = GetVolumeUV(GetCellPositionWS(gridCoordinate, 0.5f), PrevWorldToClip);
float historyAlpha = HistoryWeight;
// Discard history if it lays outside the current view
@@ -347,8 +330,8 @@ void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_
//float3 cellOffset = 0.5f;
float sceneDepth;
float3 worldPosition = ComputeCellWorldPosition(gridCoordinate, cellOffset, sceneDepth);
float3 cameraVector = worldPosition - GBuffer.ViewPos;
float3 positionWS = GetCellPositionWS(gridCoordinate, cellOffset, sceneDepth);
float3 cameraVector = positionWS - GBuffer.ViewPos;
float cameraVectorLength = length(cameraVector);
float3 cameraVectorNormalized = cameraVector / cameraVectorLength;
@@ -360,10 +343,10 @@ void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_
float shadow = 1;
if (DirectionalLightShadow.NumCascades > 0)
{
shadow = SampleShadow(DirectionalLight, DirectionalLightShadow, ShadowMapCSM, worldPosition, cameraVectorLength);
shadow = SampleShadow(DirectionalLight, DirectionalLightShadow, ShadowMapCSM, positionWS, cameraVectorLength);
}
lightScattering += DirectionalLight.Color * (8 * shadow * PhaseFunction(PhaseG, dot(DirectionalLight.Direction, cameraVectorNormalized)));
lightScattering += DirectionalLight.Color * (8 * shadow * GetPhase(PhaseG, dot(DirectionalLight.Direction, cameraVectorNormalized)));
}
// Sky light
@@ -414,38 +397,30 @@ META_CS(true, FEATURE_LEVEL_SM5)
void CS_FinalIntegration(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_DispatchThreadID, uint3 GroupThreadId : SV_GroupThreadID)
{
uint3 gridCoordinate = DispatchThreadId;
float4 accumulatedLightingAndTransmittance = float4(0, 0, 0, 1);
float3 previousSliceWorldPosition = GBuffer.ViewPos;
float4 acc = float4(0, 0, 0, 1);
float3 prevPositionWS = GBuffer.ViewPos;
for (uint layerIndex = 0; layerIndex < GridSizeInt.z; layerIndex++)
{
uint3 layerCoordinate = uint3(gridCoordinate.xy, layerIndex);
float4 scatteringAndExtinction = LightScattering[layerCoordinate];
float3 layerWorldPosition = ComputeCellWorldPosition(layerCoordinate, 0.5f);
float stepLength = length(layerWorldPosition - previousSliceWorldPosition);
previousSliceWorldPosition = layerWorldPosition;
float transmittance = exp(-scatteringAndExtinction.w * stepLength);
uint3 coords = uint3(gridCoordinate.xy, layerIndex);
float4 scatteringExtinction = LightScattering[coords];
float3 positionWS = GetCellPositionWS(coords, 0.5f);
// Ref: "Physically Based and Unified Volumetric Rendering in Frostbite"
#define ENERGY_CONSERVING_INTEGRATION 1
#if ENERGY_CONSERVING_INTEGRATION
float3 scatteringIntegratedOverSlice = (scatteringAndExtinction.rgb - scatteringAndExtinction.rgb * transmittance) / max(scatteringAndExtinction.w, .00001f);
accumulatedLightingAndTransmittance.rgb += scatteringIntegratedOverSlice * accumulatedLightingAndTransmittance.a;
#else
accumulatedLightingAndTransmittance.rgb += scatteringAndExtinction.rgb * accumulatedLightingAndTransmittance.a;
#endif
accumulatedLightingAndTransmittance.a *= transmittance;
float transmittance = exp(-scatteringExtinction.w * length(positionWS - prevPositionWS));
float3 scatteringIntegratedOverSlice = (scatteringExtinction.rgb - scatteringExtinction.rgb * transmittance) / max(scatteringExtinction.w, 0.00001f);
acc.rgb += scatteringIntegratedOverSlice * acc.a;
acc.a *= transmittance;
#if DEBUG_VOXELS
RWIntegratedLightScattering[layerCoordinate] = float4(scatteringAndExtinction.rgb, 1.0f);
RWIntegratedLightScattering[coords] = float4(scatteringExtinction.rgb, 1.0f);
#elif DEBUG_VOXEL_WS_POS
RWIntegratedLightScattering[layerCoordinate] = float4(layerWorldPosition.rgb, 1.0f);
RWIntegratedLightScattering[coords] = float4(positionWS.rgb, 1.0f);
#else
RWIntegratedLightScattering[layerCoordinate] = accumulatedLightingAndTransmittance;
RWIntegratedLightScattering[coords] = acc;
#endif
prevPositionWS = positionWS;
}
}