浏览代码

Port global density volumes to the interpolation volume system

/main
Evgenii Golubev 7 年前
当前提交
e788c519
共有 10 个文件被更改,包括 184 次插入127 次删除
  1. 2
      ScriptableRenderPipeline/Core/CoreRP/Volume/VolumeComponent.cs
  2. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Sky/AtmosphericScattering/ExponentialFogEditor.cs
  3. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs
  4. 37
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/HomogeneousDensityVolume.cs
  5. 6
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumeVoxelization.compute
  6. 151
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.cs
  7. 8
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/AtmosphericScattering/AtmosphericScattering.cs
  8. 56
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/AtmosphericScattering/VolumetricFog.cs
  9. 34
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Sky/AtmosphericScattering/VolumetricFogEditor.cs
  10. 11
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Sky/AtmosphericScattering/VolumetricFogEditor.cs.meta

2
ScriptableRenderPipeline/Core/CoreRP/Volume/VolumeComponent.cs


// or reference direct fields (you'll need to cast `state` to your custom type and don't
// forget to use `SetValue` on parameters, do not assign directly to the state object - and
// of course you'll need to check for the `overrideState` manually).
protected internal virtual void Override(VolumeComponent state, float interpFactor)
public virtual void Override(VolumeComponent state, float interpFactor)
{
int count = parameters.Count;

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Sky/AtmosphericScattering/ExponentialFogEditor.cs


using System.Collections;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

PropertyField(m_FogHeightAttenuation);
}
}
}
}

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs


public static readonly int _VBufferLightingFeedback = Shader.PropertyToID("_VBufferLightingFeedback");
public static readonly int _VBufferSampleOffset = Shader.PropertyToID("_VBufferSampleOffset");
public static readonly int _VolumeBounds = Shader.PropertyToID("_VolumeBounds");
public static readonly int _VolumeProperties = Shader.PropertyToID("_VolumeProperties");
public static readonly int _VolumeData = Shader.PropertyToID("_VolumeData");
public static readonly int _NumVisibleDensityVolumes = Shader.PropertyToID("_NumVisibleDensityVolumes");
}
}

37
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/HomogeneousDensityVolume.cs


[AddComponentMenu("Rendering/Homogeneous Density Volume", 1100)]
public class HomogeneousDensityVolume : MonoBehaviour
{
public DensityVolumeParameters parameters = new DensityVolumeParameters();
public DensityVolumeParameters parameters;
public HomogeneousDensityVolume()
{
parameters.albedo = new Color(0.5f, 0.5f, 0.5f);
parameters.meanFreePath = 10.0f;
parameters.asymmetry = 0.0f;
}
private void Awake()
{

void OnDrawGizmos()
{
if (parameters.IsLocalVolume())
{
Gizmos.color = parameters.albedo;
Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.DrawWireCube(Vector3.zero, Vector3.one);
}
}
// Returns NULL if a global fog component does not exist, or is not enabled.
public static HomogeneousDensityVolume GetGlobalHomogeneousDensityVolume()
{
HomogeneousDensityVolume globalVolume = null;
HomogeneousDensityVolume[] volumes = FindObjectsOfType(typeof(HomogeneousDensityVolume)) as HomogeneousDensityVolume[];
foreach (HomogeneousDensityVolume volume in volumes)
{
if (volume.enabled && !volume.parameters.IsLocalVolume())
{
globalVolume = volume;
break;
}
}
return globalVolume;
Gizmos.color = parameters.albedo;
Gizmos.matrix = transform.localToWorldMatrix;
Gizmos.DrawWireCube(Vector3.zero, Vector3.one);
}
}
} // UnityEngine.Experimental.Rendering.HDPipeline

6
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumeVoxelization.compute


//--------------------------------------------------------------------------------------------------
StructuredBuffer<OrientedBBox> _VolumeBounds;
StructuredBuffer<DensityVolumeProperties> _VolumeProperties;
StructuredBuffer<DensityVolumeProperties> _VolumeData;
RW_TEXTURE3D(float4, _VBufferDensity); // RGB = sqrt(scattering), A = sqrt(extinction)

if (overlapFraction > 0)
{
// There is an overlap. Sample the 3D texture, or load the constant value.
voxelScattering += overlapFraction * _VolumeProperties[volumeIndex].scattering;
voxelExtinction += overlapFraction * _VolumeProperties[volumeIndex].extinction;
voxelScattering += overlapFraction * _VolumeData[volumeIndex].scattering;
voxelExtinction += overlapFraction * _VolumeData[volumeIndex].extinction;
}
#ifndef USE_CLUSTERED_LIGHTLIST

151
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.cs


namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[GenerateHLSL]
public struct DensityVolumeProperties
public struct DensityVolumeData
public float asymmetry; // [-1, 1], linear, global parameter
public static DensityVolumeProperties GetNeutralProperties()
public static DensityVolumeData GetNeutralValues()
DensityVolumeProperties properties = new DensityVolumeProperties();
DensityVolumeData data;
properties.scattering = Vector3.zero;
properties.extinction = 0;
properties.asymmetry = 0;
data.scattering = Vector3.zero;
data.extinction = 0;
return properties;
return data;
[Serializable]
public class DensityVolumeParameters
public class VolumeRenderingUtils
public bool isLocal; // Enables voxelization
public Color albedo; // Single scattering albedo [0, 1]
public float meanFreePath; // In meters [1, inf]. Should be chromatic - this is an optimization!
public float asymmetry; // Only used if (isLocal == false)
public DensityVolumeParameters()
public static float MeanFreePathFromExtinction(float extinction)
isLocal = true;
albedo = new Color(0.5f, 0.5f, 0.5f);
meanFreePath = 10.0f;
asymmetry = 0.0f;
return 1.0f / extinction;
public bool IsLocalVolume()
public static float ExtinctionFromMeanFreePath(float meanFreePath)
return isLocal;
return 1.0f / meanFreePath;
public Vector3 GetAbsorptionCoefficient()
public static Vector3 AbsorptionFromExtinctionAndScattering(float extinction, Vector3 scattering)
float extinction = GetExtinctionCoefficient();
Vector3 scattering = GetScatteringCoefficient();
return Vector3.Max(new Vector3(extinction, extinction, extinction) - scattering, Vector3.zero);
return new Vector3(extinction, extinction, extinction) - scattering;
public Vector3 GetScatteringCoefficient()
public static Vector3 ScatteringFromExtinctionAndAlbedo(float extinction, Vector3 albedo)
float extinction = GetExtinctionCoefficient();
return new Vector3(albedo.r * extinction, albedo.g * extinction, albedo.b * extinction);
return extinction * albedo;
public float GetExtinctionCoefficient()
public static Vector3 AlbedoFromMeanFreePathAndScattering(float meanFreePath, Vector3 scattering)
return 1.0f / meanFreePath;
return meanFreePath * scattering;
}
[Serializable]
public struct DensityVolumeParameters
{
public Color albedo; // Single scattering albedo [0, 1]. Alpha is ignored
public float meanFreePath; // In meters [1, inf]. Should be chromatic - this is an optimization!
public float asymmetry; // Only used if (isLocal == false)
public void Constrain()
{

albedo.a = 1.0f;
meanFreePath = Mathf.Max(meanFreePath, 1.0f);
meanFreePath = Mathf.Clamp(meanFreePath, 1.0f, float.MaxValue);
public DensityVolumeProperties GetProperties()
public DensityVolumeData GetData()
DensityVolumeProperties properties = new DensityVolumeProperties();
DensityVolumeData data = new DensityVolumeData();
properties.scattering = GetScatteringCoefficient();
properties.extinction = GetExtinctionCoefficient();
data.extinction = VolumeRenderingUtils.ExtinctionFromMeanFreePath(meanFreePath);
data.scattering = VolumeRenderingUtils.ScatteringFromExtinctionAndAlbedo(data.extinction, (Vector3)(Vector4)albedo);
return properties;
return data;
public List<OrientedBBox> bounds;
public List<DensityVolumeProperties> properties;
public List<OrientedBBox> bounds;
public List<DensityVolumeData> density;
}
public class VolumetricLightingSystem

ComputeShader m_VolumeVoxelizationCS = null;
ComputeShader m_VolumetricLightingCS = null;
List<VBuffer> m_VBuffers = null;
List<OrientedBBox> m_VisibleVolumeBounds = null;
List<DensityVolumeProperties> m_VisibleVolumeProperties = null;
public const int k_MaxVisibleVolumeCount = 512;
List<VBuffer> m_VBuffers = null;
List<OrientedBBox> m_VisibleVolumeBounds = null;
List<DensityVolumeData> m_VisibleVolumeData = null;
public const int k_MaxVisibleVolumeCount = 512;
static ComputeBuffer s_VisibleVolumePropertiesBuffer = null;
static ComputeBuffer s_VisibleVolumeDataBuffer = null;
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

m_VolumetricLightingCS = asset.renderPipelineResources.volumetricLightingCS;
m_VBuffers = new List<VBuffer>();
m_VisibleVolumeBounds = new List<OrientedBBox>();
m_VisibleVolumeProperties = new List<DensityVolumeProperties>();
m_VisibleVolumeData = new List<DensityVolumeData>();
s_VisibleVolumePropertiesBuffer = new ComputeBuffer(k_MaxVisibleVolumeCount, System.Runtime.InteropServices.Marshal.SizeOf(typeof(DensityVolumeProperties)));
s_VisibleVolumeDataBuffer = new ComputeBuffer(k_MaxVisibleVolumeCount, System.Runtime.InteropServices.Marshal.SizeOf(typeof(DensityVolumeData)));
}
public void Cleanup()

m_VBuffers = null;
m_VisibleVolumeBounds = null;
m_VisibleVolumeProperties = null;
m_VisibleVolumeData = null;
CoreUtils.SafeRelease(s_VisibleVolumePropertiesBuffer);
CoreUtils.SafeRelease(s_VisibleVolumeDataBuffer);
}
public void ResizeVBuffer(HDCamera camera, int screenWidth, int screenHeight)

// Warning: it can screw up the reprojection. However, we have to do it in order for clustered lighting to work correctly.
m_VBufferNearPlane = camera.camera.nearClipPlane;
HomogeneousDensityVolume globalVolume = HomogeneousDensityVolume.GetGlobalHomogeneousDensityVolume();
// TODO: may want to cache these results somewhere.
DensityVolumeProperties globalVolumeProperties = (globalVolume != null) ? globalVolume.parameters.GetProperties()
: DensityVolumeProperties.GetNeutralProperties();
cmd.SetGlobalVector(HDShaderIDs._GlobalScattering, globalVolumeProperties.scattering);
cmd.SetGlobalFloat( HDShaderIDs._GlobalExtinction, globalVolumeProperties.extinction);
cmd.SetGlobalFloat( HDShaderIDs._GlobalAsymmetry, globalVolumeProperties.asymmetry);
VBuffer vBuffer = FindVBuffer(camera.GetViewID());
Debug.Assert(vBuffer != null);

SetPreconvolvedAmbientLightProbe(cmd, globalVolumeProperties.asymmetry);
// Get the interpolated asymmetry value.
var fog = VolumeManager.instance.stack.GetComponent<VolumetricFog>();
SetPreconvolvedAmbientLightProbe(cmd, fog.asymmetry);
cmd.SetGlobalVector( HDShaderIDs._VBufferResolution, new Vector4(w, h, 1.0f / w, 1.0f / h));
cmd.SetGlobalVector( HDShaderIDs._VBufferSliceCount, new Vector4(d, 1.0f / d));

if (preset == VolumetricLightingPreset.Off) return densityVolumes;
var visualEnvironment = VolumeManager.instance.stack.GetComponent<VisualEnvironment>();
if (visualEnvironment.fogType != FogType.Volumetric) return densityVolumes;
using (new ProfilingSample(cmd, "Prepare Visible Density Volume List"))
{
Vector3 camPosition = camera.camera.transform.position;

}
m_VisibleVolumeBounds.Clear();
m_VisibleVolumeProperties.Clear();
m_VisibleVolumeData.Clear();
// Collect all visible finite volume data, and upload it to the GPU.
HomogeneousDensityVolume[] volumes = Object.FindObjectsOfType(typeof(HomogeneousDensityVolume)) as HomogeneousDensityVolume[];

HomogeneousDensityVolume volume = volumes[i];
// Only test active finite volumes.
if (volume.enabled && volume.parameters.IsLocalVolume())
if (volume.enabled)
{
// TODO: cache these?
var obb = OrientedBBox.Create(volume.transform);

if (GeometryUtils.Overlap(obb, camera.frustum, 6, 8))
{
// TODO: cache these?
var properties = volume.parameters.GetProperties();
var data = volume.parameters.GetData();
m_VisibleVolumeProperties.Add(properties);
m_VisibleVolumeData.Add(data);
s_VisibleVolumePropertiesBuffer.SetData(m_VisibleVolumeProperties);
s_VisibleVolumeDataBuffer.SetData(m_VisibleVolumeData);
densityVolumes.properties = m_VisibleVolumeProperties;
densityVolumes.density = m_VisibleVolumeData;
return densityVolumes;
}

float vFoV = camera.camera.fieldOfView * Mathf.Deg2Rad;
Vector4 resolution = new Vector4(w, h, 1.0f / w, 1.0f / h);
Matrix4x4 transform = HDUtils.ComputePixelCoordToWorldSpaceViewDirectionMatrix(vFoV, resolution, camera.viewMatrix, false);
cmd.SetComputeTextureParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VBufferDensity, vBuffer.GetDensityBuffer());
cmd.SetComputeBufferParam( m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeBounds, s_VisibleVolumeBoundsBuffer);
cmd.SetComputeBufferParam( m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeProperties, s_VisibleVolumePropertiesBuffer);
cmd.SetComputeTextureParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VBufferDensity, vBuffer.GetDensityBuffer());
cmd.SetComputeBufferParam( m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeBounds, s_VisibleVolumeBoundsBuffer);
cmd.SetComputeBufferParam( m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeData, s_VisibleVolumeDataBuffer);
// TODO: set the constant buffer data only once.
cmd.SetComputeMatrixParam( m_VolumeVoxelizationCS, HDShaderIDs._VBufferCoordToViewDirWS, transform);

using (new ProfilingSample(cmd, "Volumetric Lighting"))
{
VBuffer vBuffer = FindVBuffer(camera.GetViewID());
Debug.Assert(vBuffer != null);
var visualEnvironment = VolumeManager.instance.stack.GetComponent<VisualEnvironment>();
HomogeneousDensityVolume globalVolume = HomogeneousDensityVolume.GetGlobalHomogeneousDensityVolume();
float asymmetry = globalVolume != null ? globalVolume.parameters.asymmetry : 0;
if (globalVolume == null)
if (visualEnvironment.fogType != FogType.Volumetric)
// CoreUtils.SetRenderTarget(cmd, vBuffer.GetLightingIntegralBuffer(), ClearFlag.Color, CoreUtils.clearColorAllBlack);
// CoreUtils.SetRenderTarget(cmd, vBuffer.GetLightingFeedbackBuffer(), ClearFlag.Color, CoreUtils.clearColorAllBlack);
// CoreUtils.SetRenderTarget(cmd, vBuffer.GetDensityBuffer(), ClearFlag.Color, CoreUtils.clearColorAllBlack);
VBuffer vBuffer = FindVBuffer(camera.GetViewID());
Debug.Assert(vBuffer != null);
// Only available in the Play Mode because all the frame counters in the Edit Mode are broken.
bool enableClustered = settings.lightLoopSettings.enableTileAndCluster;

int sampleIndex = rfc % 7;
Vector4 offset = new Vector4(xySeq[sampleIndex].x, xySeq[sampleIndex].y, zSeq[sampleIndex], rfc);
// Get the interpolated asymmetry value.
var fog = VolumeManager.instance.stack.GetComponent<VolumetricFog>();
cmd.SetComputeFloatParam( m_VolumetricLightingCS, HDShaderIDs._CornetteShanksConstant, CornetteShanksPhasePartConstant(asymmetry));
cmd.SetComputeFloatParam( m_VolumetricLightingCS, HDShaderIDs._CornetteShanksConstant, CornetteShanksPhasePartConstant(fog.asymmetry));
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferDensity, vBuffer.GetDensityBuffer()); // Read
cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingIntegral, vBuffer.GetLightingIntegralBuffer()); // Write
if (enableReprojection)

8
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/AtmosphericScattering/AtmosphericScattering.cs


// (not just the atmospheric scattering one) receive neutral parameters.
if (ShaderConfig.s_VolumetricLightingPreset != 0)
{
var properties = DensityVolumeProperties.GetNeutralProperties();
var data = DensityVolumeData.GetNeutralValues();
cmd.SetGlobalVector(HDShaderIDs._GlobalScattering, properties.scattering);
cmd.SetGlobalFloat( HDShaderIDs._GlobalExtinction, properties.extinction);
cmd.SetGlobalFloat( HDShaderIDs._GlobalAsymmetry, properties.asymmetry);
cmd.SetGlobalVector(HDShaderIDs._GlobalScattering, data.scattering);
cmd.SetGlobalFloat( HDShaderIDs._GlobalExtinction, data.extinction);
cmd.SetGlobalFloat( HDShaderIDs._GlobalAsymmetry, 0.0f);
}
}

56
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/AtmosphericScattering/VolumetricFog.cs


{
public class VolumetricFog : AtmosphericScattering
{
private readonly static int m_ExpFogParam = Shader.PropertyToID("_ExpFogParameters");
public MinFloatParameter meanFreePath = new MinFloatParameter(float.MaxValue, 1.0f);
public ClampedFloatParameter asymmetry = new ClampedFloatParameter(0.0f, -1.0f, 1.0f);
// Note: mean free path is a non-linear function of density.
// You want to interpolate the ExtinctionCoefficient = 1 / MeanFreePath.
public ClampedFloatParameter meanFreePath = new ClampedFloatParameter(10.0f, 0, 1000000);
// Override the volume blending function.
public override void Override(VolumeComponent state, float interpFactor)
{
VolumetricFog other = state as VolumetricFog;
public ClampedFloatParameter asymmetry = new ClampedFloatParameter(0.0f, -1, 1);
float thisExtinction = VolumeRenderingUtils.ExtinctionFromMeanFreePath(meanFreePath);
Vector3 thisScattering = VolumeRenderingUtils.ScatteringFromExtinctionAndAlbedo(thisExtinction, (Vector3)(Vector4)albedo.value);
float otherExtinction = VolumeRenderingUtils.ExtinctionFromMeanFreePath(other.meanFreePath);
Vector3 otherScattering = VolumeRenderingUtils.ScatteringFromExtinctionAndAlbedo(otherExtinction, (Vector3)(Vector4)other.albedo.value);
float blendExtinction = Mathf.Lerp(otherExtinction, thisExtinction, interpFactor);
Vector3 blendScattering = Vector3.Lerp(otherScattering, thisScattering, interpFactor);
float blendAsymmetry = Mathf.Lerp(other.asymmetry, asymmetry, interpFactor);
float blendMeanFreePath = VolumeRenderingUtils.MeanFreePathFromExtinction(blendExtinction);
Color blendAlbedo = (Color)(Vector4)VolumeRenderingUtils.AlbedoFromMeanFreePathAndScattering(blendMeanFreePath, blendScattering);
blendAlbedo.a = 1.0f;
if (meanFreePath.overrideState)
{
other.meanFreePath.value = blendMeanFreePath;
}
if (albedo.overrideState)
{
other.albedo.value = blendAlbedo;
}
if (asymmetry.overrideState)
{
other.asymmetry.value = blendAsymmetry;
}
}
DensityVolumeParameters param;
param.albedo = albedo;
param.meanFreePath = meanFreePath;
param.asymmetry = asymmetry;
DensityVolumeData data = param.GetData();
// cmd.SetGlobalVector(HDShaderIDs._GlobalScattering, properties.scattering);
// cmd.SetGlobalFloat( HDShaderIDs._GlobalExtinction, properties.extinction);
// cmd.SetGlobalFloat( HDShaderIDs._GlobalAsymmetry, properties.asymmetry);
cmd.SetGlobalVector(HDShaderIDs._GlobalScattering, data.scattering);
cmd.SetGlobalFloat( HDShaderIDs._GlobalExtinction, data.extinction);
cmd.SetGlobalFloat( HDShaderIDs._GlobalAsymmetry, asymmetry);
}

34
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Sky/AtmosphericScattering/VolumetricFogEditor.cs


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.Experimental.Rendering.HDPipeline;
using UnityEditor.Experimental.Rendering;
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
[VolumeComponentEditor(typeof(VolumetricFog))]
public class VolumetricFogEditor : AtmosphericScatteringEditor
{
private SerializedDataParameter m_Albedo;
private SerializedDataParameter m_MeanFreePath;
private SerializedDataParameter m_Asymmetry;
public override void OnEnable()
{
base.OnEnable();
var o = new PropertyFetcher<VolumetricFog>(serializedObject);
m_Albedo = Unpack(o.Find(x => x.albedo));
m_MeanFreePath = Unpack(o.Find(x => x.meanFreePath));
m_Asymmetry = Unpack(o.Find(x => x.asymmetry));
}
public override void OnInspectorGUI()
{
PropertyField(m_Albedo);
PropertyField(m_MeanFreePath);
PropertyField(m_Asymmetry);
}
}
}

11
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Editor/Sky/AtmosphericScattering/VolumetricFogEditor.cs.meta


fileFormatVersion: 2
guid: a530ef8d0c07494409d34294d8e04a89
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存