VolumetricLighting/Assets/VolumetricFog/Shaders/Scatter.compute

43 lines
1.5 KiB
Plaintext
Raw Normal View History

2016-11-01 13:25:56 +01:00
// Based on 'Volumetric fog: Unified, compute shader based solution to atmospheric scattering, ACM Siggraph 2014'
// https://bartwronski.com/publications/
#pragma kernel CSMain
float3 _FroxelResolution;
2016-11-01 13:25:56 +01:00
Texture3D _VolumeInject;
RWTexture3D<float4> _VolumeScatter;
float4 ScatterStep(float3 accumulatedLight, float accumulatedTransmittance, float3 sliceLight, float sliceDensity)
2016-11-01 13:25:56 +01:00
{
sliceDensity = max(sliceDensity, 0.000001);
float sliceTransmittance = exp(-sliceDensity / _FroxelResolution.z);
2016-11-01 13:25:56 +01:00
// Seb Hillaire's improved transmission by calculating an integral over slice depth instead of
// constant per slice value. Light still constant per slice, but that's acceptable. See slide 28 of
// Physically-based & Unified Volumetric Rendering in Frostbite
// http://www.frostbite.com/2015/08/physically-based-unified-volumetric-rendering-in-frostbite/
float3 sliceLightIntegral = sliceLight * (1.0 - sliceTransmittance) / sliceDensity;
2016-11-01 13:25:56 +01:00
accumulatedLight += sliceLightIntegral * accumulatedTransmittance;
accumulatedTransmittance *= sliceTransmittance;
return float4(accumulatedLight, accumulatedTransmittance);
2016-11-01 13:25:56 +01:00
}
[numthreads(32, 2, 1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
// Store transmission in .a, as opposed to density in _VolumeInject
float4 accum = float4(0, 0, 0, 1);
uint3 pos = uint3(id.xy, 0);
uint steps = _FroxelResolution.z;
2016-11-01 13:25:56 +01:00
for(uint z = 0; z < steps; z++)
2016-11-01 13:25:56 +01:00
{
pos.z = z;
float4 slice = _VolumeInject[pos];
accum = ScatterStep(accum.rgb, accum.a, slice.rgb, slice.a);
_VolumeScatter[pos] = accum;
2016-11-01 13:25:56 +01:00
}
}