浏览代码

Merge the old volumetrics code (WIP)

/Yibing-Project-2
Evgenii Golubev 7 年前
当前提交
a46c0009
共有 9 个文件被更改,包括 292 次插入115 次删除
  1. 2
      ScriptableRenderPipeline/Core/ShaderLibrary/API/D3D11.hlsl
  2. 2
      ScriptableRenderPipeline/Core/ShaderLibrary/API/PSSL.hlsl
  3. 12
      ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl
  4. 73
      ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl
  5. 15
      ScriptableRenderPipeline/HDRenderPipeline/HDStringConstants.cs
  6. 135
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/Resources/VolumetricLighting.compute
  7. 145
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/VolumetricLighting.cs
  8. 2
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/VolumetricLighting.cs.hlsl
  9. 21
      ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl

2
ScriptableRenderPipeline/Core/ShaderLibrary/API/D3D11.hlsl


#define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName
#define TEXTURE3D(textureName) Texture3D textureName
#define RW_TEXTURE2D(type, textureName) RWTexture2D<type> textureName
#define RW_TEXTURE3D(type, textureName) RWTexture3D<type> textureName
#define SAMPLER2D(samplerName) SamplerState samplerName
#define SAMPLERCUBE(samplerName) SamplerState samplerName

#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias)
#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3)
#define SAMPLE_TEXTURE3D_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod)
#define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) textureName.SampleCmpLevelZero(samplerName, (coord3).xy, (coord3).z)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) textureName.SampleCmpLevelZero(samplerName, (coord3).xyz, (coord3).w)

2
ScriptableRenderPipeline/Core/ShaderLibrary/API/PSSL.hlsl


#define TEXTURECUBE_ARRAY(textureName) TextureCubeArray textureName
#define TEXTURE3D(textureName) Texture3D textureName
#define RW_TEXTURE2D(type, textureName) RW_Texture2D<type> textureName
#define RW_TEXTURE3D(type, textureName) RW_Texture3D<type> textureName
#define SAMPLER2D(samplerName) SamplerState samplerName
#define SAMPLERCUBE(samplerName) SamplerState samplerName

#define SAMPLE_TEXTURECUBE_ARRAY_LOD(textureName, samplerName, coord3, index, lod) textureName.SampleLevel(samplerName, float4(coord3, index), lod)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias)
#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3)
#define SAMPLE_TEXTURE3D_LOD(textureName, samplerName, coord3, lod) textureName.SampleLevel(samplerName, coord3, lod)
#define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) textureName.SampleCmpLevelZero(samplerName, (coord3).xy, (coord3).z)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z)
#define SAMPLE_TEXTURECUBE_SHADOW(textureName, samplerName, coord4) textureName.SampleCmpLevelZero(samplerName, (coord3).xyz, (coord3).w)

12
ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl


return -viewSpaceZ;
}
// The view-space Z position 'z' is assumed to lie between near and far planes.
float EncodeLogarithmicDepth(float z, float4 encodingParams)
{
return saturate(log2(z * encodingParams.z) * encodingParams.w);
}
// The encoded depth 'd' is assumed to lie in the [0, 1] range.
float DecodeLogarithmicDepth(float d, float4 encodingParams)
{
return encodingParams.x * exp2(d * encodingParams.y);
}
struct PositionInputs
{
// Normalize screen position (offset by 0.5)

73
ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl


#ifndef UNITY_VOLUME_RENDERING_INCLUDED
#define UNITY_VOLUME_RENDERING_INCLUDED
// Reminder:
// Optical_Depth(x, y) = Integral{x, y}{Extinction(t) dt}
// Transmittance(x, y) = Exp(-Optical_Depth(x, y))
// Transmittance(x, z) = Transmittance(x, y) * Transmittance(y, z)
// Integral{a, b}{Transmittance(0, x) dx} = Transmittance(0, a) * Integral{0, b - a}{Transmittance(a, a + x) dx}
float Transmittance(float opticalDepth)
float3 OpticalDepthHomogeneous(float3 extinction, float intervalLength)
return exp(-opticalDepth);
return extinction * intervalLength;
float TransmittanceIntegralOverHomogeneousInterval(float extinction, float start, float end)
float Transmittance(float opticalDepth)
return (exp(-extinction * start) - exp(-extinction * end)) / extinction;
return exp(-opticalDepth);
float3 OpticalDepthHomogeneous(float3 extinction, float intervalLength)
float3 Transmittance(float3 opticalDepth)
return extinction * intervalLength;
return exp(-opticalDepth);
float3 Transmittance(float3 opticalDepth)
// Integral{0, b - a}{Transmittance(a, a + x) dx}.
float TransmittanceIntegralHomogeneous(float extinction, float intervalLength)
return exp(-opticalDepth);
return rcp(extinction) - rcp(extinction) * exp(-extinction * intervalLength);
float3 TransmittanceIntegralOverHomogeneousInterval(float3 extinction, float start, float end)
// Integral{0, b - a}{Transmittance(a, a + x) dx}.
float3 TransmittanceIntegralHomogeneous(float3 extinction, float intervalLength)
return (exp(-extinction * start) - exp(-extinction * end)) / extinction;
return rcp(extinction) - rcp(extinction) * exp(-extinction * intervalLength);
}
float IsotropicPhaseFunction()

HenyeyGreensteinPhasePartVarying(asymmetry, LdotD);
}
float4 GetInScatteredRadianceAndTransmittance(float2 positionSS, float depthVS,
float globalFogExtinction,
TEXTURE3D(vBuffer), SAMPLER3D(bilinearSampler),
float4 vBufferResolution,
float4 vBufferDepthEncodingParams,
int numSlices = 64)
{
int n = numSlices;
float d = EncodeLogarithmicDepth(depthVS, vBufferDepthEncodingParams);
float slice0 = clamp(floor(d * n - 0.5), 0, n - 1); // TODO: somehow avoid the clamp...
float slice1 = clamp( ceil(d * n - 0.5), 0, n - 1); // TODO: somehow avoid the clamp...
// We cannot simply perform trilinear interpolation since the distance between slices is Z-encoded.
float d0 = slice0 * rcp(n) + (0.5 * rcp(n));
float d1 = slice1 * rcp(n) + (0.5 * rcp(n));
float z0 = DecodeLogarithmicDepth(d0, vBufferDepthEncodingParams);
float z1 = DecodeLogarithmicDepth(d1, vBufferDepthEncodingParams);
float z = depthVS;
// Scale and bias the UVs s.t.
// {0} in the screen space corresponds to {0.5/n} and
// {1} in the screen space corresponds to {1 - 0.5/n}.
// TODO: precompute.
float u = positionSS.x * (vBufferResolution.x - 1) / vBufferResolution.x + 0.5 / vBufferResolution.x;
float v = positionSS.y * (vBufferResolution.y - 1) / vBufferResolution.y + 0.5 / vBufferResolution.y;
// Perform 2 bilinear taps.
float4 v0 = SAMPLE_TEXTURE3D_LOD(vBuffer, bilinearSampler, float3(u, v, d0), 0);
float4 v1 = SAMPLE_TEXTURE3D_LOD(vBuffer, bilinearSampler, float3(u, v, d1), 0);
float4 vt = lerp(v0, v1, saturate((z - z0) / (z1 - z0)));
[flatten] if (z - z1 > 0)
{
// Our sample is beyond the far plane of the V-buffer.
// Apply additional global fog attenuation.
vt.a += OpticalDepthHomogeneous(globalFogExtinction, z - z1);
// TODO: extra in-scattering from directional and ambient lights.
}
return float4(vt.rgb, Transmittance(vt.a));
}
#endif // UNITY_VOLUME_RENDERING_INCLUDED

15
ScriptableRenderPipeline/HDRenderPipeline/HDStringConstants.cs


public static readonly int _SkyParam = Shader.PropertyToID("_SkyParam");
public static readonly int _PixelCoordToViewDirWS = Shader.PropertyToID("_PixelCoordToViewDirWS");
public static readonly int _GlobalFog_Extinction = Shader.PropertyToID("_GlobalFog_Extinction");
public static readonly int _GlobalFog_Asymmetry = Shader.PropertyToID("_GlobalFog_Asymmetry");
public static readonly int _GlobalFog_Scattering = Shader.PropertyToID("_GlobalFog_Scattering");
internal static readonly int _GlobalFog_Extinction = Shader.PropertyToID("_GlobalFog_Extinction");
internal static readonly int _GlobalFog_Asymmetry = Shader.PropertyToID("_GlobalFog_Asymmetry");
internal static readonly int _GlobalFog_Scattering = Shader.PropertyToID("_GlobalFog_Scattering");
internal static readonly int _vBufferResolution = Shader.PropertyToID("_vBufferResolution");
internal static readonly int _vBufferDepthEncodingParams = Shader.PropertyToID("_vBufferDepthEncodingParams");
internal static readonly int _vBufferCoordToViewDirWS = Shader.PropertyToID("_vBufferCoordToViewDirWS");
internal static readonly int _VolumetricLightingBuffer = Shader.PropertyToID("_VolumetricLightingBuffer");
internal static readonly int _VolumetricLightingBufferCurrentFrame = Shader.PropertyToID("_VolumetricLightingBufferCurrentFrame");
internal static readonly int _VolumetricLightingBufferAccumulation = Shader.PropertyToID("_VolumetricLightingBufferAccumulation");
}
}

135
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/Resources/VolumetricLighting.compute


// Inputs & outputs
//--------------------------------------------------------------------------------------------------
TEXTURE2D(_DepthTexture); // Z-buffer
RW_TEXTURE2D(float4, _CameraColorTexture); // Updated texture
RW_TEXTURE3D(float4, _VolumetricLightingBufferCurrentFrame); // RGB = radiance, A = optical depth
TEXTURE3D(_VolumetricLightingBufferAccumulation); // RGB = radiance, A = optical depth
CBUFFER_START(UnityVolumetricLighting)
float4x4 _vBufferCoordToViewDirWS; // Actually just 3x3, but Unity can only set 4x4
CBUFFER_END
//--------------------------------------------------------------------------------------------------
// Implementation

{
float3 originWS;
float3 directionWS; // Normalized
float maxLength; // In meters
float ratioLenToZ; // Ratio of view space length to view space Z
float3 PerformIntegration(PositionInputs posInput, Ray ray, uint numSteps)
void FillVolumetricLightingBuffer(Ray cameraRay, float4 depthParams, uint2 tileCoord, uint2 voxelCoord, uint sliceCount = 64)
{
float3 scattering = _GlobalFog_Scattering;
float extinction = _GlobalFog_Extinction;

LightLoopContext context;
// ZERO_INITIALIZE(LightLoopContext, context);
context.shadowContext = InitShadowContext();
uint featureFlags = 0xFFFFFFFF; // TODO
float maxDepthVS = posInput.depthVS;
// Note: we are already using 'unPositionSS' for randomization of LODDitheringTransition().
float zeta = GenerateHashedRandomFloat(posInput.unPositionSS.yx);
uint featureFlags = 0xFFFFFFFF; // TODO
float du = rcp(numSteps);
float u0 = 0.25 * du + 0.5 * du * zeta;
float dt = du * ray.maxLength;
float t0 = 0;
float n = depthParams.x; // View space Z coordinate of the near plane
float t0 = n * cameraRay.ratioLenToZ; // Distance to the near plane
float du = rcp(sliceCount); // Log-encoded distance between slices
float3 radiance = 0;
float3 totalRadiance = 0;
float opticalDepth = 0;
for (uint s = 0; s < numSteps; s++)
for (uint s = 0; s < sliceCount; s++)
float u = u0 + s * du; // [0, 1]
float t = u * ray.maxLength; // [0, ray.maxLength]
float t1 = t + 0.5 * dt;
float u1 = s * du + du; // (s + 1) / sliceCount
float t1 = DecodeLogarithmicDepth(u1, depthParams) * cameraRay.ratioLenToZ;
float dt = t1 - t0;
float T = TransmittanceIntegralOverHomogeneousInterval(extinction, t0, t1);
// Integral{a, b}{Transmittance(0, x) dx} = Transmittance(0, a) * Integral{0, b - a}{Transmittance(a, a + x) dx}.
float transmittance = Transmittance(opticalDepth) * TransmittanceIntegralHomogeneous(extinction, dt);
[branch] if (T < 0.0001) break;
// TODO: low-discrepancy point set, mirroring around the bounds of the camera frustum.
// Note: using 0.5 here (in the linear space) does not guarantee that we stay within the bounds!
float t = t0 + 0.5 * dt;
float3 positionWS = ray.originWS + t * ray.directionWS;
float3 positionWS = cameraRay.originWS + t * cameraRay.directionWS;
float3 sampleRadiance = 0;

#ifdef USE_HENYEY_GREENSTEIN_PHASE_FUNCTION
// Note: we apply the scattering coefficient and the constant part of the phase function later.
intensity *= HenyeyGreensteinPhasePartVarying(asymmetry, dot(L, ray.directionWS));
intensity *= HenyeyGreensteinPhasePartVarying(asymmetry, dot(L, cameraRay.directionWS));
0, lightData.shadowIndex, L, posInput.unPositionSS);
0, lightData.shadowIndex, L);
intensity *= shadow;
}

uint punctualLightCount;
#ifdef LIGHTLOOP_TILE_PASS
uint punctualLightStart;
PositionInputs posInput;
posInput.depthVS = t;
posInput.unTileCoord = tileCoord;
posInput.depthVS = u * maxDepthVS;
uint punctualLightStart;
GetCountAndStart(posInput, LIGHTCATEGORY_PUNCTUAL, punctualLightStart, punctualLightCount);
#else
punctualLightCount = _PunctualLightCount;

float distSq = dot(lightToSample, lightToSample);
float dist = sqrt(distSq);
float3 L = lightToSample * -rsqrt(distSq);
float intensity = GetPunctualShapeAttenuation(lightData, L, distSq);
float clampedDistSq = max(distSq, 0.25); // Reduce undersampling
float intensity = GetPunctualShapeAttenuation(lightData, L, clampedDistSq);
intensity *= HenyeyGreensteinPhasePartVarying(asymmetry, dot(L, ray.directionWS));
intensity *= HenyeyGreensteinPhasePartVarying(asymmetry, dot(L, cameraRay.directionWS));
#endif
intensity *= Transmittance(OpticalDepthHomogeneous(extinction, dist));

float3 offset = 0; // GetShadowPosOffset(nDotL, normal);
float shadow = GetPunctualShadowAttenuation(context.shadowContext, positionWS + offset,
0, lightData.shadowIndex, float4(L, dist), posInput.unPositionSS);
0, lightData.shadowIndex, float4(L, dist));
intensity *= lerp(1, shadow, lightData.shadowDimmer);
}

}
}
radiance += sampleRadiance * T;
#ifdef USE_HENYEY_GREENSTEIN_PHASE_FUNCTION
float3 phaseConstant = scattering * HenyeyGreensteinPhasePartConstant(asymmetry);
#else
float3 phaseConstant = scattering * IsotropicPhaseFunction();
#endif
// Compute optical depth up to the center of the interval.
opticalDepth += extinction * (0.5 * dt);
totalRadiance += transmittance * phaseConstant * sampleRadiance;
// Store the voxel data. TODO: reprojection using camera motion vectors.
_VolumetricLightingBufferCurrentFrame[uint3(voxelCoord, s)] = float4(totalRadiance, opticalDepth);
// Compute optical depth up to the end of the interval.
opticalDepth += extinction * (0.5 * dt);
#ifdef USE_HENYEY_GREENSTEIN_PHASE_FUNCTION
float3 phaseConstant = scattering * HenyeyGreensteinPhasePartConstant(asymmetry);
#else
float3 phaseConstant = scattering * IsotropicPhaseFunction();
#endif
return radiance * phaseConstant;
}
int GetLog2NumVoxelsPerLightTile()
{
// Assume that the light tile size is an base-2 multiple of the voxel tile size.
return (int)log2(GetTileSize()) - (int)_vBufferResolution.w;
}
[numthreads(GROUP_SIZE_2D, 1, 1)]

uint mortonCode = groupThreadId;
uint2 localCoord = DecodeMorton2D(mortonCode);
uint2 tileAnchor = groupId * GROUP_SIZE_1D;
uint2 pixelCoord = tileAnchor + localCoord;
uint2 tileCoord = pixelCoord / GetTileSize();
uint2 voxelCoord = tileAnchor + localCoord;
uint2 tileCoord = tileAnchor >> GetLog2NumVoxelsPerLightTile();
if (pixelCoord.x >= (uint)_ScreenSize.x || pixelCoord.y >= (uint)_ScreenSize.y) { return; }
[branch] if (voxelCoord.x >= (uint)_vBufferResolution.x ||
voxelCoord.y >= (uint)_vBufferResolution.y)
{
return;
}
// Idea: zenith angle based distance limiting to simulate aerial perspective?
// TODO: read the HiZ texture in order to skip evaluation of lighting in occluded voxels.
float z = max(LOAD_TEXTURE2D(_DepthTexture, pixelCoord).r, 0 + 0.001);
// float tileMaxZ = ...
float z = min(LOAD_TEXTURE2D(_DepthTexture, pixelCoord).r, 1 - 0.001);
// float tileMaxZ = ...
// Determine the farthest unoccluded voxel...
PositionInputs posInput = GetPositionInput(pixelCoord, _ScreenSize.zw, tileCoord);
UpdatePositionInput(z, _InvViewProjMatrix, _ViewProjMatrix, posInput);
// TODO: low-discrepancy point set, mirroring around the bounds of the camera frustum.
float2 sampleCoord = voxelCoord + 0.5;
Ray cameraRay;
// Compute the unnormalized ray direction s.t. its Z coordinate in the view space is equal to 1.
float3 dir = -mul(float3(sampleCoord, 1), (float3x3)_vBufferCoordToViewDirWS);
// Note: the camera ray does not start on the the near (camera sensor) plane.
// While this is not correct (strictly speaking), the introduced error is small.
cameraRay.originWS = GetCurrentViewPosition();
cameraRay.directionWS = posInput.positionWS - cameraRay.originWS;
cameraRay.maxLength = sqrt(dot(cameraRay.directionWS, cameraRay.directionWS));
cameraRay.directionWS *= rsqrt(dot(cameraRay.directionWS, cameraRay.directionWS)); // Normalize
// Compute the ratio of the length of the vector to its view space Z coordinate.
float len = length(dir);
float rayT = Transmittance(OpticalDepthHomogeneous(_GlobalFog_Extinction, cameraRay.maxLength));
const int numSamples = 64;
float3 inL = PerformIntegration(posInput, cameraRay, numSamples);
Ray cameraRay;
cameraRay.originWS = GetCurrentViewPosition();
cameraRay.directionWS = normalize(dir);
cameraRay.ratioLenToZ = len;
// In-place UAV updates do not work on Intel GPUs.
_CameraColorTexture[pixelCoord] = float4(rayT * _CameraColorTexture[pixelCoord].rgb + inL, _CameraColorTexture[pixelCoord].a);
FillVolumetricLightingBuffer(cameraRay, _vBufferDepthEncodingParams, tileCoord, voxelCoord);
}

145
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/VolumetricLighting.cs


return properties;
}
}
} // struct VolumeProperties
[Serializable]
public class VolumeParameters

return properties;
}
}
} // class VolumeParameters
bool m_VolumetricLightingEnabled = false; // Must be able to change this dynamically
int m_VolumetricBufferTileSize = 4; // In pixels, must be a power of 2
bool m_VolumetricLightingEnabled = false;
int m_VolumetricBufferTileSize = 4; // In pixels, must be a power of 2
float m_VolumetricBufferMaxFarPlane = 32.0f; // Distance in meters
RenderTexture m_VolumetricLightingBufferAccumulated = null;
RenderTexture m_VolumetricLightingBufferAccumulation = null;
// RenderTargetIdentifier m_VolumetricLightingBufferAccumulatedRT;
RenderTargetIdentifier m_VolumetricLightingBufferAccumulationRT;
void ComputeVolumetricBufferResolution(int screenWidth, int screenHeight, ref int w, ref int h, ref int d)
{
int t = m_VolumetricBufferTileSize;
Debug.Assert((t & (t - 1)) == 0, "m_VolumetricBufferTileSize must be a power of 2.");
// Ceil(ScreenSize / TileSize).
w = (screenWidth + t - 1) / t;
h = (screenHeight + t - 1) / t;
d = 64;
// Cell-centered -> node-centered.
w += 1;
h += 1;
}
// Uses a logarithmic depth encoding.
// Near plane: depth = 0; far plane: depth = 1.
// x = n, y = log2(f/n), z = 1/n, w = 1/log2(f/n).
Vector4 ComputeVolumetricBufferDepthEncodingParams(float cameraNearPlane, float cameraFarPlane, float sliceCount)
{
float n = cameraNearPlane;
float f = Math.Min(cameraFarPlane, m_VolumetricBufferMaxFarPlane);
float s = sliceCount;
// Cell-centered -> node-centered.
// Remap near and far planes s.t. Depth(n) = 0.5/s and Depth(f) = 1-0.5/s.
float x = Mathf.Pow(n, (s - 0.5f) / (s - 1)) * Mathf.Pow(f, -0.5f / (s - 1));
f = n * f / x;
n = x;
Vector4 depthParams = new Vector4();
depthParams.x = n;
depthParams.y = Mathf.Log(f / n, 2);
depthParams.z = 1 / depthParams.x;
depthParams.w = 1 / depthParams.y;
return depthParams;
}
if (m_VolumetricLightingBufferAccumulated != null)
if (m_VolumetricLightingBufferAccumulation != null)
m_VolumetricLightingBufferAccumulated.Release();
m_VolumetricLightingBufferAccumulation.Release();
int s = m_VolumetricBufferTileSize;
Debug.Assert((s & (s - 1)) == 0, "m_VolumetricBufferTileSize must be a power of 2.");
int w = (width + s - 1) / s;
int h = (height + s - 1) / s;
int d = 64;
int w = 0, h = 0, d = 0;
ComputeVolumetricBufferResolution(width, height, ref w, ref h, ref d);
m_VolumetricLightingBufferCurrentFrame = new RenderTexture(w, h, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
m_VolumetricLightingBufferCurrentFrame = new RenderTexture(w, h, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear); // UAV with ARGBHalf appears to be broken...
m_VolumetricLightingBufferCurrentFrame.filterMode = FilterMode.Bilinear; // Custom trilinear
m_VolumetricLightingBufferCurrentFrame.dimension = TextureDimension.Tex3D; // Prefer 3D Thick tiling layout
m_VolumetricLightingBufferCurrentFrame.volumeDepth = d;

m_VolumetricLightingBufferAccumulated = new RenderTexture(w, h, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
m_VolumetricLightingBufferAccumulated.filterMode = FilterMode.Bilinear; // Custom trilinear
m_VolumetricLightingBufferAccumulated.dimension = TextureDimension.Tex3D; // Prefer 3D Thick tiling layout
m_VolumetricLightingBufferAccumulated.volumeDepth = d;
m_VolumetricLightingBufferAccumulated.enableRandomWrite = true;
m_VolumetricLightingBufferAccumulated.Create();
// m_VolumetricLightingBufferAccumulatedRT = new RenderTargetIdentifier(m_VolumetricLightingBufferAccumulated);
m_VolumetricLightingBufferAccumulation = new RenderTexture(w, h, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear); // UAV with ARGBHalf appears to be broken...
m_VolumetricLightingBufferAccumulation.filterMode = FilterMode.Bilinear; // Custom trilinear
m_VolumetricLightingBufferAccumulation.dimension = TextureDimension.Tex3D; // Prefer 3D Thick tiling layout
m_VolumetricLightingBufferAccumulation.volumeDepth = d;
m_VolumetricLightingBufferAccumulation.enableRandomWrite = true;
m_VolumetricLightingBufferAccumulation.Create();
m_VolumetricLightingBufferAccumulationRT = new RenderTargetIdentifier(m_VolumetricLightingBufferAccumulation);
}
void ClearVolumetricLightingBuffers(CommandBuffer cmd, bool isFirstFrame)

if (isFirstFrame)
{
CoreUtils.SetRenderTarget(cmd, m_VolumetricLightingBufferAccumulated, ClearFlag.Color, Color.black);
CoreUtils.SetRenderTarget(cmd, m_VolumetricLightingBufferAccumulation, ClearFlag.Color, Color.black);
}
}
}

return (globalFogComponent != null);
}
void VolumetricLightingPass(HDCamera hdCamera, CommandBuffer cmd)
public void SetVolumetricLightingData(bool volumetricLightingEnabled, CommandBuffer cmd, HDCamera camera, ComputeShader cs = null, int kernel = 0)
{
SetGlobalVolumeProperties(volumetricLightingEnabled, cmd, cs);
// Compute dimensions of the buffer.
int w = 0, h = 0, d = 0;
ComputeVolumetricBufferResolution((int)camera.screenSize.x, (int)camera.screenSize.y, ref w, ref h, ref d);
Vector4 resolution = new Vector4(w, h, d, Mathf.Log(m_VolumetricBufferTileSize, 2));
// Compute custom near and far flipping planes of the volumetric lighting buffer.
Vector4 depthParams = ComputeVolumetricBufferDepthEncodingParams(camera.camera.nearClipPlane, camera.camera.farClipPlane, d);
if (cs)
{
cmd.SetComputeVectorParam( cs, HDShaderIDs._vBufferResolution, resolution);
cmd.SetComputeVectorParam( cs, HDShaderIDs._vBufferDepthEncodingParams, depthParams);
cmd.SetComputeTextureParam(cs, kernel, HDShaderIDs._VolumetricLightingBuffer, m_VolumetricLightingBufferCurrentFrameRT);
}
else
{
cmd.SetGlobalVector( HDShaderIDs._vBufferResolution, resolution);
cmd.SetGlobalVector( HDShaderIDs._vBufferDepthEncodingParams, depthParams);
cmd.SetGlobalTexture(HDShaderIDs._VolumetricLightingBuffer, m_VolumetricLightingBufferCurrentFrameRT);
}
}
void VolumetricLightingPass(HDCamera camera, CommandBuffer cmd)
{
if (!SetGlobalVolumeProperties(m_VolumetricLightingEnabled, cmd, m_VolumetricLightingCS)) { return; }

int volumetricLightingKernel = m_VolumetricLightingCS.FindKernel(enableClustered ? "VolumetricLightingClustered"
: "VolumetricLightingAllLights");
hdCamera.SetupComputeShader(m_VolumetricLightingCS, cmd);
camera.SetupComputeShader(m_VolumetricLightingCS, cmd);
cmd.SetComputeTextureParam(m_VolumetricLightingCS, volumetricLightingKernel, HDShaderIDs._CameraColorTexture, m_CameraColorBufferRT);
cmd.SetComputeTextureParam(m_VolumetricLightingCS, volumetricLightingKernel, HDShaderIDs._DepthTexture, GetDepthTexture());
cmd.SetComputeVectorParam( m_VolumetricLightingCS, HDShaderIDs._Time, Shader.GetGlobalVector(HDShaderIDs._Time));
// Compute dimensions of the buffer.
int w = 0, h = 0, d = 0;
ComputeVolumetricBufferResolution((int)camera.screenSize.x, (int)camera.screenSize.y, ref w, ref h, ref d);
Vector4 resolution = new Vector4(w, h, d, Mathf.Log(m_VolumetricBufferTileSize, 2));
// Pass clustered light data (if present) into the compute shader.
m_LightLoop.PushGlobalParams(hdCamera.camera, cmd, m_VolumetricLightingCS, volumetricLightingKernel, true);
// Compute custom near and far flipping planes of the volumetric lighting buffer.
Vector4 depthParams = ComputeVolumetricBufferDepthEncodingParams(camera.camera.nearClipPlane, camera.camera.farClipPlane, d);
// Cell-centered -> node-centered.
float vFoV = camera.camera.fieldOfView * Mathf.Deg2Rad;
vFoV = 2 * Mathf.Atan(Mathf.Tan(0.5f * vFoV) * h / (h - 1));
// Compose the matrix which allows us to compute the world space view direction.
Matrix4x4 transform = SkyManager.ComputePixelCoordToWorldSpaceViewDirectionMatrix(vFoV, new Vector4(w, h, 1.0f / w, 1.0f / h), camera.viewMatrix, false);
cmd.SetComputeVectorParam( m_VolumetricLightingCS, HDShaderIDs._vBufferResolution, resolution);
cmd.SetComputeVectorParam( m_VolumetricLightingCS, HDShaderIDs._vBufferDepthEncodingParams, depthParams);
cmd.SetComputeMatrixParam( m_VolumetricLightingCS, HDShaderIDs._vBufferCoordToViewDirWS, transform);
cmd.SetComputeVectorParam( m_VolumetricLightingCS, HDShaderIDs._Time, Shader.GetGlobalVector(HDShaderIDs._Time));
cmd.SetComputeTextureParam(m_VolumetricLightingCS, volumetricLightingKernel, HDShaderIDs._VolumetricLightingBufferCurrentFrame, m_VolumetricLightingBufferCurrentFrameRT);
cmd.SetComputeTextureParam(m_VolumetricLightingCS, volumetricLightingKernel, HDShaderIDs._VolumetricLightingBufferAccumulation, m_VolumetricLightingBufferAccumulationRT);
// Pass clustered light data (if present) to the compute shader.
m_LightLoop.PushGlobalParams(camera.camera, cmd, m_VolumetricLightingCS, volumetricLightingKernel, true);
cmd.DispatchCompute(m_VolumetricLightingCS, volumetricLightingKernel, ((int)hdCamera.screenSize.x + 15) / 16, ((int)hdCamera.screenSize.y + 15) / 16, 1);
cmd.DispatchCompute(m_VolumetricLightingCS, volumetricLightingKernel, (w + 15) / 16, (h + 15) / 16, 1);
} // namespace UnityEngine.Experimental.Rendering.HDPipeline

2
ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/VolumetricLighting.cs.hlsl


//
// This file was automatically generated. Please don't edit by hand.
// This file was automatically generated from Assets/SRP/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/VolumetricLighting.cs. Please don't edit by hand.
//
#ifndef VOLUMETRICLIGHTING_CS_HLSL

21
ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl


#endif
float4 unity_ShadowColor;
// Volumetric lighting. Should be a struct in 'UnityPerFrame'.
// Unfortunately, structures inside constant buffers are not supported by Unity.
float4 _vBufferDepthEncodingParams; // { n, log2(f/n), 1/n, 1/log2(f/n) }
float4 _vBufferResolution; // { w, h, sliceCount = 64, log2(vBufferTileSize) }
float3 _GlobalFog_Scattering;
float _GlobalFog_Extinction;
float _GlobalFog_Asymmetry;
float _GlobalFog_Align16_0;
float _GlobalFog_Align16_1;
float _GlobalFog_Align16_2;
CBUFFER_END
// ----------------------------------------------------------------------------

float4 _InvProjParam;
float4 _ScreenSize; // (w, h, 1/w, 1/h)
float4 _FrustumPlanes[6]; // (N, -dot(N, P))
// Volumetric lighting. Should be a struct in 'UnityPerFrame'.
// Unfortunately, we cannot modify the layout of 'UnityPerFrame',
// and structures inside constant buffers are not supported by Unity.
float3 _GlobalFog_Scattering;
float _GlobalFog_Extinction;
float _GlobalFog_Asymmetry;
float _GlobalFog_Align16_0;
float _GlobalFog_Align16_1;
float _GlobalFog_Align16_2;
CBUFFER_END
#ifdef USE_LEGACY_UNITY_MATRIX_VARIABLES

正在加载...
取消
保存