浏览代码

Factor out EvaluateVoxelLighting()

/Yibing-Project-2
Evgenii Golubev 7 年前
当前提交
9b7488e1
共有 3 个文件被更改,包括 247 次插入204 次删除
  1. 5
      ScriptableRenderPipeline/HDRenderPipeline/HDStringConstants.cs
  2. 403
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/Resources/VolumetricLighting.compute
  3. 43
      ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/VolumetricLighting.cs

5
ScriptableRenderPipeline/HDRenderPipeline/HDStringConstants.cs


public static readonly int _VBufferCoordToViewDirWS = Shader.PropertyToID("_VBufferCoordToViewDirWS");
public static readonly int _VBufferDensity = Shader.PropertyToID("_VBufferDensity");
public static readonly int _VBufferLighting = Shader.PropertyToID("_VBufferLighting");
public static readonly int _VBufferLightingCurr = Shader.PropertyToID("_VBufferLightingCurr");
public static readonly int _VBufferLightingPrev = Shader.PropertyToID("_VBufferLightingPrev");
public static readonly int _VBufferLightingIntegral = Shader.PropertyToID("_VBufferLightingIntegral");
public static readonly int _VBufferLightingHistory = Shader.PropertyToID("_VBufferLightingHistory");
public static readonly int _VBufferLightingFeedback = Shader.PropertyToID("_VBufferLightingFeedback");
}
}

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


// Inputs & outputs
//--------------------------------------------------------------------------------------------------
RW_TEXTURE3D(float4, _VBufferLightingCurr); // RGB = radiance, A = optical depth
TEXTURE3D(_VBufferLightingPrev); // RGB = radiance, A = optical depth
RW_TEXTURE3D(float4, _VBufferLightingIntegral); // RGB = radiance, A = optical depth
TEXTURE3D(_VBufferLightingHistory); // RGB = radiance, A = confidence (similarity)
TEXTURE3D(_VBufferLightingFeedback); // RGB = radiance, A = confidence (similarity)
// TODO: avoid creating another Constant Buffer...
float4x4 _VBufferCoordToViewDirWS; // Actually just 3x3, but Unity can only set 4x4
float4x4 _VBufferCoordToViewDirWS; // Actually just 3x3, but Unity can only set 4x4
CBUFFER_END
//--------------------------------------------------------------------------------------------------

return ray.originWS + t * ray.directionWS;
}
// Computes the in-scattered radiance along the ray.
void FillVolumetricLightingBuffer(LightLoopContext context, uint featureFlags,
PositionInputs posInput, Ray ray)
BakeLightingData unused; // Unused, so define once
// Computes the light integral (in-scattered radiance) within the voxel.
// Multiplication by the scattering coefficient and the phase function is performed outside.
float3 EvaluateVoxelLighting(LightLoopContext context, uint featureFlags, PositionInputs posInput,
Ray ray, float t0, float t1, float dt, float rndVal, float extinction
#ifdef LIGHTLOOP_TILE_PASS
, uint clusterIndices[2], float clusterDepths[2])
#else
)
#endif
BakeLightingData unused; // Unused, so define once
float3 voxelRadiance = 0;
float z0 = _VBufferDepthEncodingParams.x; // Start integration from the near plane
float t0 = ray.ratioLenToZ * z0;
float de = rcp(VBUFFER_SLICE_COUNT); // Log-encoded distance between slices
float3 totalRadiance = 0;
float opticalDepth = 0;
uint sliceCountHack = max(VBUFFER_SLICE_COUNT, (uint)_VBufferDepthEncodingParams.x); // Prevent unrolling...
#ifdef LIGHTLOOP_TILE_PASS
// Our voxel is not necessarily completely inside a single light cluster.
// Note that Z-binning can solve this problem, as we can iterate over all Z-bins
// to compute min/max light indices, and then use this range for the entire slice.
uint clusterIndices[2];
float clusterDepths[2];
clusterIndices[0] = GetLightClusterIndex(posInput.tileCoord, z0);
clusterDepths[0] = GetLightClusterMinLinearDepth(posInput.tileCoord, clusterIndices[0]);
#endif // LIGHTLOOP_TILE_PASS
// TODO: replace 'sliceCountHack' with VBUFFER_SLICE_COUNT when the shader compiler bug is fixed.
for (uint slice = 0; slice < sliceCountHack; slice++)
if (featureFlags & LIGHTFEATUREFLAGS_DIRECTIONAL)
float e1 = slice * de + de; // (slice + 1) / sliceCount
float z1 = DecodeLogarithmicDepth(e1, _VBufferDepthEncodingParams);
float t1 = ray.ratioLenToZ * z1;
float dt = t1 - t0;
float tOffset, weight;
ImportanceSampleHomogeneousMedium(rndVal, extinction, dt, tOffset, weight);
// Compute the position of the center of the voxel.
// We will use it for participating media sampling and reprojection.
float tc = t0 + 0.5 * dt;
float3 centerWS = GetPointAtDistance(ray, tc);
// Reproject 'centerWS'. It performs a point sample.
float2 reprojPosNDC = ComputeNormalizedDeviceCoordinates(centerWS, _PrevViewProjMatrix);
float reprojZ = mul(_PrevViewProjMatrix, float4(centerWS, 1)).w;
float4 reprojValue = LoadInScatteredRadianceAndTransmittance(reprojPosNDC, reprojZ,
_VBufferLightingPrev,
_VBufferResolutionAndScale,
_VBufferDepthEncodingParams);
// Sample the participating medium at 'tc' (or 'centerWS').
// We consider it to be constant along the interval [t0, t1] (within the voxel).
float3 scattering = _GlobalFog_Scattering;
float extinction = _GlobalFog_Extinction;
// TODO: use a low-discrepancy point set.
float rndVal = 0.5;
float3 sampleRadiance = 0;
float t = t0 + tOffset;
posInput.positionWS = GetPointAtDistance(ray, t);
if (featureFlags & LIGHTFEATUREFLAGS_DIRECTIONAL)
for (uint i = 0; i < _DirectionalLightCount; ++i)
float tOffset, weight;
ImportanceSampleHomogeneousMedium(rndVal, extinction, dt, tOffset, weight);
// Fetch the light.
DirectionalLightData light = _DirectionalLightDatas[i];
float3 L = -light.forward; // Lights point backwards in Unity
float t = t0 + tOffset;
posInput.positionWS = GetPointAtDistance(ray, t);
float3 color; float attenuation;
EvaluateLight_Directional(context, posInput, light, unused, 0, L,
color, attenuation);
for (uint i = 0; i < _DirectionalLightCount; ++i)
{
// Fetch the light.
DirectionalLightData light = _DirectionalLightDatas[i];
float3 L = -light.forward; // Lights point backwards in Unity
// Note: the 'weight' accounts for transmittance from 't0' to 't'.
float intensity = attenuation * weight;
float3 color; float attenuation;
EvaluateLight_Directional(context, posInput, light, unused, 0, L,
color, attenuation);
// Compute the amount of in-scattered radiance.
voxelRadiance += intensity * color;
}
}
// Note: the 'weight' accounts for transmittance from 't0' to 't'.
float intensity = attenuation * weight;
#ifdef LIGHTLOOP_TILE_PASS
// Loop over 1 or 2 light clusters.
int cluster = 0;
do
{
float tMin = max(t0, ray.ratioLenToZ * clusterDepths[cluster]);
float tMax = t1;
// Compute the amount of in-scattered radiance.
sampleRadiance += intensity * color;
}
if (cluster == 0 && (clusterIndices[0] != clusterIndices[1]))
{
tMax = min(t1, ray.ratioLenToZ * clusterDepths[1]);
#else
float tMin = t0;
float tMax = t1;
#endif // LIGHTLOOP_TILE_PASS
#ifdef LIGHTLOOP_TILE_PASS
clusterIndices[1] = GetLightClusterIndex(posInput.tileCoord, z1);
clusterDepths[1] = GetLightClusterMinLinearDepth(posInput.tileCoord, clusterIndices[1]);
// Loop over 1 or 2 light clusters.
for (int cluster = 0; cluster < 2; cluster++)
if (featureFlags & LIGHTFEATUREFLAGS_PUNCTUAL)
float tMin = max(t0, ray.ratioLenToZ * clusterDepths[cluster]);
float tMax = t1;
uint lightCount, lightStart;
if (cluster == 0 && (clusterIndices[0] != clusterIndices[1]))
{
tMax = min(t1, ray.ratioLenToZ * clusterDepths[1]);
}
#else
float tMin = t0;
float tMax = t1;
#endif // LIGHTLOOP_TILE_PASS
#ifdef LIGHTLOOP_TILE_PASS
GetCountAndStartCluster(posInput.tileCoord, clusterIndices[cluster], LIGHTCATEGORY_PUNCTUAL,
lightStart, lightCount);
#else
lightCount = _PunctualLightCount;
lightStart = 0;
#endif // LIGHTLOOP_TILE_PASS
if (featureFlags & LIGHTFEATUREFLAGS_PUNCTUAL)
if (lightCount > 0)
uint lightCount, lightStart;
LightData light = FetchLight(lightStart, 0);
#ifdef LIGHTLOOP_TILE_PASS
GetCountAndStartCluster(posInput.tileCoord, clusterIndices[cluster], LIGHTCATEGORY_PUNCTUAL,
lightStart, lightCount);
#else
lightCount = _PunctualLightCount;
lightStart = 0;
#endif // LIGHTLOOP_TILE_PASS
uint i = 0, last = lightCount - 1;
if (lightCount > 0)
// Box lights require special handling (see the next while loop).
while (i <= last && light.lightType != GPULIGHTTYPE_PROJECTOR_BOX)
LightData light = FetchLight(lightStart, 0);
float tEntr = tMin;
float tExit = tMax;
uint i = 0, last = lightCount - 1;
bool sampleLight = true;
// Box lights require special handling (see the next while loop).
while (i <= last && light.lightType != GPULIGHTTYPE_PROJECTOR_BOX)
// Perform ray-cone intersection for pyramid and spot lights.
if (light.lightType != GPULIGHTTYPE_POINT)
float tEntr = tMin;
float tExit = tMax;
bool sampleLight = true;
float lenMul = 1;
// Perform ray-cone intersection for pyramid and spot lights.
if (light.lightType != GPULIGHTTYPE_POINT)
if (light.lightType == GPULIGHTTYPE_PROJECTOR_PYRAMID)
float lenMul = 1;
// 'light.right' and 'light.up' vectors are pre-scaled on the CPU
// s.t. if you were to place them at the distance of 1 directly in front
// of the light, they would give you the "footprint" of the light.
// For spot lights, the cone fit is exact.
// For pyramid lights, however, this is the "inscribed" cone
// (contained within the pyramid), and we want to intersect
// the "escribed" cone (which contains the pyramid).
// Therefore, we have to scale the radii by the sqrt(2).
lenMul = rsqrt(2);
}
if (light.lightType == GPULIGHTTYPE_PROJECTOR_PYRAMID)
{
// 'light.right' and 'light.up' vectors are pre-scaled on the CPU
// s.t. if you were to place them at the distance of 1 directly in front
// of the light, they would give you the "footprint" of the light.
// For spot lights, the cone fit is exact.
// For pyramid lights, however, this is the "inscribed" cone
// (contained within the pyramid), and we want to intersect
// the "escribed" cone (which contains the pyramid).
// Therefore, we have to scale the radii by the sqrt(2).
lenMul = rsqrt(2);
}
float3 coneAxisX = lenMul * light.right;
float3 coneAxisY = lenMul * light.up;
float3 coneAxisX = lenMul * light.right;
float3 coneAxisY = lenMul * light.up;
sampleLight = IntersectRayCone(ray.originWS, ray.directionWS,
light.positionWS, light.forward,
coneAxisX, coneAxisY,
tMin, tMax, tEntr, tExit);
}
sampleLight = IntersectRayCone(ray.originWS, ray.directionWS,
light.positionWS, light.forward,
coneAxisX, coneAxisY,
tMin, tMax, tEntr, tExit);
}
if (sampleLight)
{
float t, distSq, rcpPdf;
ImportanceSamplePunctualLight(rndVal, light.positionWS,
ray.originWS, ray.directionWS,
tEntr, tExit, t, distSq, rcpPdf);
if (sampleLight)
{
float t, distSq, rcpPdf;
ImportanceSamplePunctualLight(rndVal, light.positionWS,
ray.originWS, ray.directionWS,
tEntr, tExit, t, distSq, rcpPdf);
posInput.positionWS = GetPointAtDistance(ray, t);
posInput.positionWS = GetPointAtDistance(ray, t);
float3 lightToSample = posInput.positionWS - light.positionWS;
float dist = sqrt(distSq);
float3 L = -lightToSample * rsqrt(distSq);
float3 lightToSample = posInput.positionWS - light.positionWS;
float dist = sqrt(distSq);
float3 L = -lightToSample * rsqrt(distSq);
float3 color; float attenuation;
EvaluateLight_Punctual(context, posInput, light, unused, 0, L, dist, distSq,
color, attenuation);
float3 color; float attenuation;
EvaluateLight_Punctual(context, posInput, light, unused, 0, L, dist, distSq,
color, attenuation);
float intensity = attenuation * rcpPdf;
float intensity = attenuation * rcpPdf;
// Compute transmittance from 't0' to 't'.
intensity *= TransmittanceHomogeneousMedium(extinction, t - t0);
// Compute transmittance from 't0' to 't'.
intensity *= TransmittanceHomogeneousMedium(extinction, t - t0);
// Compute the amount of in-scattered radiance.
voxelRadiance += color * intensity;
}
// Compute the amount of in-scattered radiance.
sampleRadiance += color * intensity;
}
light = FetchLight(lightStart, min(++i, last));
}
light = FetchLight(lightStart, min(++i, last));
}
while (i <= last) // GPULIGHTTYPE_PROJECTOR_BOX
{
light = FetchLight(lightStart, min(++i, last));
light.lightType = GPULIGHTTYPE_PROJECTOR_BOX;
while (i <= last) // GPULIGHTTYPE_PROJECTOR_BOX
{
light = FetchLight(lightStart, min(++i, last));
light.lightType = GPULIGHTTYPE_PROJECTOR_BOX;
// Convert the box light from OBB to AABB.
// 'light.right' and 'light.up' vectors are pre-scaled on the CPU by (2/w) and (2/h).
float3x3 rotMat = float3x3(light.right, light.up, light.forward);
// Convert the box light from OBB to AABB.
// 'light.right' and 'light.up' vectors are pre-scaled on the CPU by (2/w) and (2/h).
float3x3 rotMat = float3x3(light.right, light.up, light.forward);
float3 o = mul(rotMat, ray.originWS - light.positionWS);
float3 d = mul(rotMat, ray.directionWS);
float3 o = mul(rotMat, ray.originWS - light.positionWS);
float3 d = mul(rotMat, ray.directionWS);
float range = light.size.x;
float3 boxPt0 = float3(-1, -1, 0);
float3 boxPt1 = float3( 1, 1, range);
float range = light.size.x;
float3 boxPt0 = float3(-1, -1, 0);
float3 boxPt1 = float3( 1, 1, range);
float tEntr, tExit;
float tEntr, tExit;
if (IntersectRayAABB(o, d, boxPt0, boxPt1, tMin, tMax, tEntr, tExit))
{
float tOffset, weight;
ImportanceSampleHomogeneousMedium(rndVal, extinction, tExit - tEntr, tOffset, weight);
if (IntersectRayAABB(o, d, boxPt0, boxPt1, tMin, tMax, tEntr, tExit))
{
float tOffset, weight;
ImportanceSampleHomogeneousMedium(rndVal, extinction, tExit - tEntr, tOffset, weight);
float t = tEntr + tOffset;
posInput.positionWS = GetPointAtDistance(ray, t);
float t = tEntr + tOffset;
posInput.positionWS = GetPointAtDistance(ray, t);
float3 L = -light.forward;
float3 L = -light.forward;
float3 color; float attenuation;
EvaluateLight_Punctual(context, posInput, light, unused, 0, L, 1, 1,
color, attenuation);
float3 color; float attenuation;
EvaluateLight_Punctual(context, posInput, light, unused, 0, L, 1, 1,
color, attenuation);
// Note: the 'weight' accounts for transmittance from 'tEntr' to 't'.
float intensity = attenuation * weight;
// Note: the 'weight' accounts for transmittance from 'tEntr' to 't'.
float intensity = attenuation * weight;
// Compute transmittance from 't0' to 'tEntr'.
intensity *= TransmittanceHomogeneousMedium(extinction, tEntr - t0);
// Compute transmittance from 't0' to 'tEntr'.
intensity *= TransmittanceHomogeneousMedium(extinction, tEntr - t0);
// Compute the amount of in-scattered radiance.
sampleRadiance += intensity * color;
}
// Compute the amount of in-scattered radiance.
voxelRadiance += intensity * color;
#ifdef LIGHTLOOP_TILE_PASS
// Check whether the voxel is completely inside the light cluster.
if (clusterIndices[0] == clusterIndices[1]) break;
#ifdef LIGHTLOOP_TILE_PASS
cluster++;
// Check whether the voxel is completely inside the light cluster.
} while ((cluster < 2) && (clusterIndices[0] != clusterIndices[1]));
#endif // LIGHTLOOP_TILE_PASS
clusterIndices[0] = clusterIndices[1];
clusterDepths[0] = clusterDepths[1];
#endif // LIGHTLOOP_TILE_PASS
return voxelRadiance;
}
// Computes the in-scattered radiance along the ray.
void FillVolumetricLightingBuffer(LightLoopContext context, uint featureFlags,
PositionInputs posInput, Ray ray)
{
float z0 = _VBufferDepthEncodingParams.x; // Start integration from the near plane
float t0 = ray.ratioLenToZ * z0;
float de = rcp(VBUFFER_SLICE_COUNT); // Log-encoded distance between slices
float3 totalRadiance = 0;
float opticalDepth = 0;
uint sliceCountHack = max(VBUFFER_SLICE_COUNT, (uint)_VBufferDepthEncodingParams.x); // Prevent unrolling...
#ifdef LIGHTLOOP_TILE_PASS
// Our voxel is not necessarily completely inside a single light cluster.
// Note that Z-binning can solve this problem, as we can iterate over all Z-bins
// to compute min/max light indices, and then use this range for the entire slice.
uint clusterIndices[2];
float clusterDepths[2];
clusterIndices[0] = GetLightClusterIndex(posInput.tileCoord, z0);
clusterDepths[0] = GetLightClusterMinLinearDepth(posInput.tileCoord, clusterIndices[0]);
#endif // LIGHTLOOP_TILE_PASS
// TODO: replace 'sliceCountHack' with VBUFFER_SLICE_COUNT when the shader compiler bug is fixed.
for (uint slice = 0; slice < sliceCountHack; slice++)
{
float e1 = slice * de + de; // (slice + 1) / sliceCount
float z1 = DecodeLogarithmicDepth(e1, _VBufferDepthEncodingParams);
float t1 = ray.ratioLenToZ * z1;
float dt = t1 - t0;
#ifdef LIGHTLOOP_TILE_PASS
clusterIndices[1] = GetLightClusterIndex(posInput.tileCoord, z1);
clusterDepths[1] = GetLightClusterMinLinearDepth(posInput.tileCoord, clusterIndices[1]);
#endif
// Compute the position of the center of the voxel.
// We will use it for participating media sampling and reprojection.
float tc = t0 + 0.5 * dt;
float3 centerWS = GetPointAtDistance(ray, tc);
// Sample the participating medium at 'tc' (or 'centerWS').
// We consider it to be constant along the interval [t0, t1] (within the voxel).
float3 scattering = _GlobalFog_Scattering;
float extinction = _GlobalFog_Extinction;
// TODO: use a low-discrepancy point set.
float rndVal = 0.5;
float3 voxelRadiance = EvaluateVoxelLighting(context, featureFlags, posInput,
ray, t0, t1, dt, rndVal, extinction
#ifdef LIGHTLOOP_TILE_PASS
, clusterIndices, clusterDepths);
#else
);
#endif
totalRadiance += (transmittance * IsotropicPhaseFunction()) * scattering * sampleRadiance;
totalRadiance += (transmittance * IsotropicPhaseFunction()) * scattering * voxelRadiance;
// Reproject 'centerWS'. It performs a point sample.
float2 reprojPosNDC = ComputeNormalizedDeviceCoordinates(centerWS, _PrevViewProjMatrix);
float reprojZ = mul(_PrevViewProjMatrix, float4(centerWS, 1)).w;
float4 reprojValue = LoadInScatteredRadianceAndTransmittance(reprojPosNDC, reprojZ,
_VBufferLightingHistory,
_VBufferResolutionAndScale,
_VBufferDepthEncodingParams);
_VBufferLightingCurr[uint3(posInput.positionSS, slice)] = blendedValue;
_VBufferLightingIntegral[uint3(posInput.positionSS, slice)] = blendedValue;
#ifdef LIGHTLOOP_TILE_PASS
clusterIndices[0] = clusterIndices[1];
clusterDepths[0] = clusterDepths[1];
#endif // LIGHTLOOP_TILE_PASS
}
}

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


float m_VBufferNearPlane = 0.5f; // Distance in meters; dynamic modifications not handled by reprojection
float m_VBufferFarPlane = 64.0f; // Distance in meters; dynamic modifications not handled by reprojection
const uint m_VBufferCount = 3; // 0 and 1 - history (prev) and feedback (next), 2 - integral (curr)
RenderTexture[] m_VBufferLighting = null; // Used for even / odd frames
RenderTexture[] m_VBufferLighting = null;
RenderTargetIdentifier[] m_VBufferLightingRT = null;
public static int ComputeVBufferTileSize(VolumetricLightingPreset preset)

{
DestroyVBuffer();
m_VBufferLighting = new RenderTexture[2];
m_VBufferLightingRT = new RenderTargetIdentifier[2];
m_VBufferLighting = new RenderTexture[m_VBufferCount];
m_VBufferLightingRT = new RenderTargetIdentifier[m_VBufferCount];
for (int i = 0; i < 2; i++)
for (uint i = 0; i < m_VBufferCount; i++)
{
m_VBufferLighting[i] = new RenderTexture(w, h, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear); // UAV with ARGBHalf appears to be broken...
m_VBufferLighting[i].filterMode = FilterMode.Bilinear; // Custom trilinear

m_VBufferLighting[i].Create();
m_VBufferLightingRT[i] = new RenderTargetIdentifier(m_VBufferLighting[i]);
// No clean way to clear a RenderTexture without a CommandBuffer? Ridiculous.
RenderTexture saveRT = UnityEngine.RenderTexture.active;
RenderTexture.active = m_VBufferLighting[i];
GL.Clear(false, true, CoreUtils.clearColorAllBlack);
RenderTexture.active = saveRT;
}
}

{
if (m_VBufferLighting[0] != null) m_VBufferLighting[0].Release();
if (m_VBufferLighting[1] != null) m_VBufferLighting[1].Release();
for (uint i = 0; i < m_VBufferCount; i++)
{
if (m_VBufferLighting[i] != null) m_VBufferLighting[i].Release();
}
m_VBufferLighting = null;
m_VBufferLightingRT = null;

return globalFogComponent;
}
RenderTargetIdentifier GetVBufferCurrFrame()
RenderTargetIdentifier GetVBufferLightingHistory() // From the previous frame
bool evenFrame = (Time.renderedFrameCount & 1) == 0;
bool evenFrame = (Time.renderedFrameCount & 1) == 0; // Does not work in the Scene view
RenderTargetIdentifier GetVBufferPrevFrame()
RenderTargetIdentifier GetVBufferLightingFeedback() // For the next frame
bool evenFrame = (Time.renderedFrameCount & 1) == 0;
bool evenFrame = (Time.renderedFrameCount & 1) == 0; // Does not work in the Scene view
RenderTargetIdentifier GetVBufferLightingIntegral() // Of the current frame
{
return m_VBufferLightingRT[2];
}
public void SetVolumetricLightingData(HDCamera camera, CommandBuffer cmd)
{
HomogeneousFog globalFogComponent = GetGlobalFogComponent();

cmd.SetGlobalVector( HDShaderIDs._VBufferResolutionAndScale, resAndScale);
cmd.SetGlobalVector( HDShaderIDs._VBufferDepthEncodingParams, depthParams);
cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, GetVBufferCurrFrame());
cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, GetVBufferLightingIntegral());
}
void VolumetricLightingPass(HDCamera camera, CommandBuffer cmd)

if (GetGlobalFogComponent() == null)
{
// Clear the render target instead of running the shader.
CoreUtils.SetRenderTarget(cmd, GetVBufferCurrFrame(), ClearFlag.Color, CoreUtils.clearColorAllBlack);
CoreUtils.SetRenderTarget(cmd, GetVBufferLightingHistory(), ClearFlag.Color, CoreUtils.clearColorAllBlack);
return;
}

// TODO: set 'm_VolumetricLightingPreset'.
cmd.SetComputeMatrixParam( m_VolumetricLightingCS, HDShaderIDs._VBufferCoordToViewDirWS, transform);
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingCurr, GetVBufferCurrFrame());
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingPrev, GetVBufferPrevFrame());
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingHistory, GetVBufferLightingHistory()); // Read
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingFeedback, GetVBufferLightingFeedback()); // Write
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingIntegral, GetVBufferLightingIntegral()); // Write
// The shader defines GROUP_SIZE_1D = 16.
cmd.DispatchCompute(m_VolumetricLightingCS, kernel, (w + 15) / 16, (h + 15) / 16, 1);

正在加载...
取消
保存