Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions com.unity.render-pipelines.high-definition/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Fixed unexpectedly strong contribution from directional lights in path-traced volumetric scattering (case 1304688).
- Fixed memory leak with XR combined occlusion meshes (case 1366173).
- Fixed diffusion profile being reset to default on SpeedTree8 materials with subsurface scattering enabled during import.
- Fixed support for light/shadow dimmers (volumetric or not) in path tracing.

### Changed
- Visual Environment ambient mode is now Dynamic by default.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ void UpdateShaderVariablesGlobalCBFogParameters(ref ShaderVariablesGlobal cb, HD
cb._HeightFogBaseHeight = crBaseHeight;
cb._GlobalFogAnisotropy = anisotropy.value;
cb._VolumetricFilteringEnabled = ((int)denoisingMode.value & (int)FogDenoisingMode.Gaussian) != 0 ? 1 : 0;
cb._FogDirectionalOnly = directionalLightsOnly.value ? 1 : 0;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/ShaderVariablesRaytracingLightLoop.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Shadows/SphericalQuad.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/Raytracing/Shaders/Common/AtmosphericScatteringRayTracing.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingSampling.hlsl"

// How many lights (at most) do we support at one given shading point
// FIXME: hardcoded limits are evil, this LightList should instead be put together in C#
Expand Down Expand Up @@ -327,6 +328,11 @@ float3 GetAreaEmission(LightData lightData, float centerU, float centerV, float
return emission;
}

float3 GetLightTransmission(float3 transmission, float shadowOpacity)
{
return lerp(float3(1.0, 1.0, 1.0), transmission, shadowOpacity);
}

bool SampleLights(LightList lightList,
float3 inputSample,
float3 position,
Expand All @@ -335,7 +341,8 @@ bool SampleLights(LightList lightList,
out float3 outgoingDir,
out float3 value,
out float pdf,
out float dist)
out float dist,
out float shadowOpacity)
{
if (!GetLightCount(lightList))
return false;
Expand Down Expand Up @@ -404,7 +411,15 @@ bool SampleLights(LightList lightList,
}

if (isVolume)
{
value *= lightData.volumetricLightDimmer;
shadowOpacity = lightData.volumetricShadowDimmer;
}
else
{
value *= lightData.lightDimmer;
shadowOpacity = lightData.shadowDimmer;
}

#ifndef LIGHT_EVALUATION_NO_HEIGHT_FOG
ApplyFogAttenuation(position, outgoingDir, dist, value);
Expand Down Expand Up @@ -435,7 +450,15 @@ bool SampleLights(LightList lightList,
dist = FLT_INF;

if (isVolume)
{
value *= lightData.volumetricLightDimmer;
shadowOpacity = lightData.volumetricShadowDimmer;
}
else
{
value *= lightData.lightDimmer;
shadowOpacity = lightData.shadowDimmer;
}

#ifndef LIGHT_EVALUATION_NO_HEIGHT_FOG
ApplyFogAttenuation(position, outgoingDir, value);
Expand Down Expand Up @@ -759,13 +782,13 @@ float PickLocalLightInterval(float3 rayOrigin, float3 rayDirection, inout float
tMin = tLightMin;
tMax = tLightMax;

inputSample /= wLight;
inputSample = RescaleSampleUnder(inputSample, wLight);
}
else
{
lightWeight *= 1.0 - wLight;

inputSample = (inputSample - wLight) / (1.0 - wLight);
inputSample = RescaleSampleOver(inputSample, wLight);
}

localCount++;
Expand Down Expand Up @@ -793,13 +816,13 @@ float PickLocalLightInterval(float3 rayOrigin, float3 rayDirection, inout float
tMin = tLightMin;
tMax = tLightMax;

inputSample /= wLight;
inputSample = RescaleSampleUnder(inputSample, wLight);
}
else
{
lightWeight *= 1.0 - wLight;

inputSample = (inputSample - wLight) / (1.0 - wLight);
inputSample = RescaleSampleOver(inputSample, wLight);
}

localCount++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,15 @@ bool RussianRouletteTest(float threshold, float value, float rand, out float fac
return true;
}

float RescaleSampleUnder(float inputSample, float threshold)
{
return inputSample / threshold;
}

float RescaleSampleOver(float inputSample, float threshold)
{
// Make sure we never reach 1.0 due to numerical imprecision
return min((inputSample - threshold) / (1.0 - threshold), 0.99999);
}

#endif // UNITY_PATH_TRACING_SAMPLING_INCLUDED
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
#ifndef UNITY_PATH_TRACING_VOLUME_INCLUDED
#define UNITY_PATH_TRACING_VOLUME_INCLUDED

#ifdef HAS_LIGHTLOOP
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingLight.hlsl"
#endif

float ComputeHeightFogMultiplier(float height)
{
Expand All @@ -17,42 +15,46 @@ bool SampleVolumeScatteringPosition(uint2 pixelCoord, inout float inputSample, i
if (!_FogEnabled || !_EnableVolumetricFog)
return false;

// This will determin the interval in which volumetric scattering can occur
// This will determine the interval in which volumetric scattering can occur
float tMin, tMax;
float pdfVol = 1.0;
float tFog = min(t, _MaxFogDistance);

#ifdef HAS_LIGHTLOOP

float pickedLightWeight;
float localWeight = PickLocalLightInterval(WorldRayOrigin(), WorldRayDirection(), inputSample, lightPosition, pickedLightWeight, tMin, tMax);

if (localWeight < 0.0)
return false;

sampleLocalLights = inputSample < localWeight;
if (sampleLocalLights)
if (_FogDirectionalOnly)
{
tMax = min(tMax, tFog);
if (tMin >= tMax)
if (!_DirectionalLightCount)
return false;

inputSample /= localWeight;
pdfVol *= localWeight * pickedLightWeight;
}
else
{
tMin = 0.0;
tMax = tFog;
}
else // Directional and local lights
{
float pickedLightWeight;
float localWeight = PickLocalLightInterval(WorldRayOrigin(), WorldRayDirection(), inputSample, lightPosition, pickedLightWeight, tMin, tMax);

if (localWeight < 0.0)
return false;

inputSample -= localWeight;
inputSample /= 1.0 - localWeight;
pdfVol *= 1.0 - localWeight;
sampleLocalLights = inputSample < localWeight;
if (sampleLocalLights)
{
tMax = min(tMax, tFog);
if (tMin >= tMax)
return false;

inputSample = RescaleSampleUnder(inputSample, localWeight);
pdfVol *= localWeight * pickedLightWeight;
}
else
{
tMin = 0.0;
tMax = tFog;

inputSample = RescaleSampleOver(inputSample, localWeight);
pdfVol *= 1.0 - localWeight;
}
}
#else
tMin = 0.0;
tMax = tFog;
#endif

// FIXME: not quite sure what the sigmaT value is supposed to be...
const float sigmaT = _HeightFogBaseExtinction;
Expand All @@ -62,27 +64,18 @@ bool SampleVolumeScatteringPosition(uint2 pixelCoord, inout float inputSample, i

if (inputSample >= transmittanceThreshold)
{
// Re-scale the sample
inputSample -= transmittanceThreshold;
inputSample /= 1.0 - transmittanceThreshold;

// Adjust the pdf
inputSample = RescaleSampleOver(inputSample, transmittanceThreshold);
pdf *= 1.0 - transmittanceThreshold;

return false;
}

// Re-scale the sample
inputSample /= transmittanceThreshold;

// Adjust the pdf
inputSample = RescaleSampleUnder(inputSample, transmittanceThreshold);
pdf *= pdfVol * transmittanceThreshold;

// Exponential sampling
float transmittance = transmittanceTMax + inputSample * (transmittanceTMin - transmittanceTMax);
t = -log(transmittance) / sigmaT;

// Adjust the pdf
pdf *= sigmaT * transmittance / (transmittanceTMin - transmittanceTMax);

return true;
Expand All @@ -94,8 +87,6 @@ void ComputeVolumeScattering(inout PathIntersection pathIntersection : SV_RayPay
// Reset the ray intersection color, which will store our final result
pathIntersection.value = 0.0;

#ifdef HAS_LIGHTLOOP

// Grab depth information
uint currentDepth = _RaytracingMaxRecursion - pathIntersection.remainingDepth;

Expand All @@ -108,8 +99,7 @@ void ComputeVolumeScattering(inout PathIntersection pathIntersection : SV_RayPay
// Create the list of active lights (a local light can be forced by providing its position)
LightList lightList = CreateLightList(scatteringPosition, sampleLocalLights, lightPosition);

// Bunch of variables common to material and light sampling
float pdf;
float pdf, shadowOpacity;
float3 value;

RayDesc ray;
Expand All @@ -121,7 +111,7 @@ void ComputeVolumeScattering(inout PathIntersection pathIntersection : SV_RayPay
// Light sampling
if (computeDirect)
{
if (SampleLights(lightList, inputSample, scatteringPosition, 0.0, true, ray.Direction, value, pdf, ray.TMax))
if (SampleLights(lightList, inputSample, scatteringPosition, 0.0, true, ray.Direction, value, pdf, ray.TMax, shadowOpacity))
{
// FIXME: Apply phase function and divide by pdf (only isotropic for now, and not sure about sigmaS value)
value *= _HeightFogBaseScattering.xyz * ComputeHeightFogMultiplier(scatteringPosition.y) * INV_FOUR_PI / pdf;
Expand All @@ -137,12 +127,11 @@ void ComputeVolumeScattering(inout PathIntersection pathIntersection : SV_RayPay
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | RAY_FLAG_FORCE_NON_OPAQUE | RAY_FLAG_SKIP_CLOSEST_HIT_SHADER,
RAYTRACINGRENDERERFLAG_CAST_SHADOW, 0, 1, 1, ray, nextPathIntersection);

pathIntersection.value += value * nextPathIntersection.value;
pathIntersection.value += value * GetLightTransmission(nextPathIntersection.value, shadowOpacity);
}
}
}

#endif // HAS_LIGHTLOOP
}

#endif // UNITY_PATH_TRACING_VOLUME_INCLUDED
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@

// Path tracing includes
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingIntersection.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingVolume.hlsl"
#ifdef HAS_LIGHTLOOP
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingLight.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingSampling.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/PathTracing/Shaders/PathTracingVolume.hlsl"
#endif

float PowerHeuristic(float f, float b)
Expand Down Expand Up @@ -36,9 +34,9 @@ float ComputeVisibility(float3 position, float3 normal, float3 inputSample)

// We will ignore value and pdf here, as we only want to catch occluders (no distance falloffs, cosines, etc.)
float3 value;
float pdf;
float pdf, shadowOpacity;

if (SampleLights(lightList, inputSample, rayDescriptor.Origin, normal, false, rayDescriptor.Direction, value, pdf, rayDescriptor.TMax))
if (SampleLights(lightList, inputSample, rayDescriptor.Origin, normal, false, rayDescriptor.Direction, value, pdf, rayDescriptor.TMax, shadowOpacity))
{
// Shoot a transmission ray (to mark it as such, purposedly set remaining depth to an invalid value)
PathIntersection intersection;
Expand All @@ -50,7 +48,7 @@ float ComputeVisibility(float3 position, float3 normal, float3 inputSample)
TraceRay(_RaytracingAccelerationStructure, RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | RAY_FLAG_FORCE_NON_OPAQUE | RAY_FLAG_SKIP_CLOSEST_HIT_SHADER,
RAYTRACINGRENDERERFLAG_CAST_SHADOW, 0, 1, 1, rayDescriptor, intersection);

visibility = Luminance(intersection.value);
visibility = Luminance(GetLightTransmission(intersection.value, shadowOpacity));
}

return visibility;
Expand Down Expand Up @@ -143,8 +141,7 @@ void ComputeSurfaceScattering(inout PathIntersection pathIntersection : SV_RayPa
#endif
LightList lightList = CreateLightList(shadingPosition, lightNormal, builtinData.renderingLayers);

// Bunch of variables common to material and light sampling
float pdf;
float pdf, shadowOpacity;
float3 value;
MaterialResult mtlResult;

Expand All @@ -157,7 +154,7 @@ void ComputeSurfaceScattering(inout PathIntersection pathIntersection : SV_RayPa
// Light sampling
if (computeDirect)
{
if (SampleLights(lightList, inputSample.xyz, rayDescriptor.Origin, lightNormal, false, rayDescriptor.Direction, value, pdf, rayDescriptor.TMax))
if (SampleLights(lightList, inputSample.xyz, rayDescriptor.Origin, lightNormal, false, rayDescriptor.Direction, value, pdf, rayDescriptor.TMax, shadowOpacity))
{
EvaluateMaterial(mtlData, rayDescriptor.Direction, mtlResult);

Expand All @@ -174,7 +171,7 @@ void ComputeSurfaceScattering(inout PathIntersection pathIntersection : SV_RayPa
RAYTRACINGRENDERERFLAG_CAST_SHADOW, 0, 1, 1, rayDescriptor, nextPathIntersection);

float misWeight = PowerHeuristic(pdf, mtlResult.diffPdf + mtlResult.specPdf);
pathIntersection.value += value * nextPathIntersection.value * misWeight;
pathIntersection.value += value * GetLightTransmission(nextPathIntersection.value, shadowOpacity) * misWeight;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,16 @@ unsafe struct ShaderVariablesGlobal
public float _FogColorMode;
public float _GlobalMipBias;
public float _GlobalMipBiasPow2;
public float _Pad2;
public float _Pad0;
public Vector4 _MipFogParameters;
public Vector4 _HeightFogBaseScattering;
public float _HeightFogBaseExtinction;
public float _HeightFogBaseHeight;
public float _GlobalFogAnisotropy;
public int _VolumetricFilteringEnabled;
public Vector2 _HeightFogExponents; // { 1/H, H }
public float _Pad4;
public float _Pad5;
public int _FogDirectionalOnly;
public float _Pad1;

// VBuffer
public Vector4 _VBufferViewportSize; // { w, h, 1/w, 1/h }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,16 @@ GLOBAL_CBUFFER_START(ShaderVariablesGlobal, b0)
float _FogColorMode;
float _GlobalMipBias;
float _GlobalMipBiasPow2;
float _Pad2;
float _Pad0;
float4 _MipFogParameters;
float4 _HeightFogBaseScattering;
float _HeightFogBaseExtinction;
float _HeightFogBaseHeight;
float _GlobalFogAnisotropy;
int _VolumetricFilteringEnabled;
float2 _HeightFogExponents;
float _Pad4;
float _Pad5;
int _FogDirectionalOnly;
float _Pad1;
float4 _VBufferViewportSize;
float4 _VBufferLightingViewportScale;
float4 _VBufferLightingViewportLimit;
Expand Down