浏览代码

3D texture sampling in homogeneous volumes.

/main
Raymond Graham 7 年前
当前提交
29eb0f1f
共有 10 个文件被更改,包括 338 次插入47 次删除
  1. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs
  2. 75
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/DensityVolumeManager.cs
  3. 63
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/HomogeneousDensityVolume.cs
  4. 33
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumeVoxelization.compute
  5. 44
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.cs
  6. 15
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.cs.hlsl
  7. 4
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLit.cs.hlsl
  8. 2
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Sky/AtmosphericScattering/VolumetricFog.cs
  9. 136
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumeTextureAtlas.cs
  10. 11
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumeTextureAtlas.cs.meta

2
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDStringConstants.cs


public static readonly int _VolumeBounds = Shader.PropertyToID("_VolumeBounds");
public static readonly int _VolumeData = Shader.PropertyToID("_VolumeData");
public static readonly int _NumVisibleDensityVolumes = Shader.PropertyToID("_NumVisibleDensityVolumes");
public static readonly int _VolumeMaskAtlas = Shader.PropertyToID("_VolumeMaskAtlas");
public static readonly int _VolumeMaskDimensions = Shader.PropertyToID("_VolumeMaskDimensions");
}
}

75
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/DensityVolumeManager.cs


using System.Collections.Generic;
using UnityEngine.Rendering;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{

private DensityVolumeManager()
{
volumes = new List<HomogeneousDensityVolume>();
}
public static DensityVolumeManager manager
{

}
}
public VolumeTextureAtlas volumeAtlas = null;
private bool atlasNeedsRefresh = false;
private DensityVolumeManager()
{
volumes = new List<HomogeneousDensityVolume>();
//TODO: hardcoded size....:-(
volumeAtlas = new VolumeTextureAtlas(TextureFormat.RGBA32, 32);
volumeAtlas.OnAtlasUpdated += AtlasUpdated;
}
volume.OnTextureUpdated += TriggerVolumeAtlasRefresh;
if (volume.parameters.volumeMask != null)
{
volumeAtlas.AddTexture(volume.parameters.volumeMask);
}
}
public void DeRegisterVolume(HomogeneousDensityVolume volume)

volumes.Remove(volume);
}
volume.OnTextureUpdated -= TriggerVolumeAtlasRefresh;
if (volume.parameters.volumeMask != null)
{
volumeAtlas.RemoveTexture(volume.parameters.volumeMask);
}
public HomogeneousDensityVolume[] PrepareDensityVolumeData(CommandBuffer cmd)
{
//Update volumes
foreach (HomogeneousDensityVolume volume in volumes )
{
volume.PrepareParameters();
}
public HomogeneousDensityVolume[] GetAllVolumes()
if (atlasNeedsRefresh)
{
atlasNeedsRefresh = false;
VolumeAtlasRefresh();
}
volumeAtlas.GenerateVolumeAtlas(cmd);
return volumes.ToArray();
}
private void VolumeAtlasRefresh()
{
volumeAtlas.ClearTextures();
foreach (HomogeneousDensityVolume volume in volumes )
{
if (volume.parameters.volumeMask != null)
{
volumeAtlas.AddTexture(volume.parameters.volumeMask);
}
}
}
private void TriggerVolumeAtlasRefresh()
return volumes.ToArray();
atlasNeedsRefresh = true;
}
private void AtlasUpdated()
{
foreach(HomogeneousDensityVolume volume in volumes )
{
volume.parameters.textureIndex = volumeAtlas.GetTextureIndex(volume.parameters.volumeMask);
}
}
}
}

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


using System;
using UnityEngine.Rendering;
[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 Texture3D volumeMask;
public int textureIndex;
public void Constrain()
{
albedo.r = Mathf.Clamp01(albedo.r);
albedo.g = Mathf.Clamp01(albedo.g);
albedo.b = Mathf.Clamp01(albedo.b);
albedo.a = 1.0f;
meanFreePath = Mathf.Clamp(meanFreePath, 1.0f, float.MaxValue);
asymmetry = Mathf.Clamp(asymmetry, -1.0f, 1.0f);
}
public DensityVolumeData GetData()
{
DensityVolumeData data = new DensityVolumeData();
data.extinction = VolumeRenderingUtils.ExtinctionFromMeanFreePath(meanFreePath);
data.scattering = VolumeRenderingUtils.ScatteringFromExtinctionAndAlbedo(data.extinction, (Vector3)(Vector4)albedo);
data.textureIndex = textureIndex;
return data;
}
} // class DensityVolumeParameters
[ExecuteInEditMode]
[AddComponentMenu("Rendering/Homogeneous Density Volume", 1100)]
public class HomogeneousDensityVolume : MonoBehaviour

private Texture3D previousVolumeMask = null;
public Action OnTextureUpdated;
parameters.volumeMask = null;
parameters.textureIndex = -1;
}
//Gather and Update any parameters that may have changed
public void PrepareParameters()
{
//Texture has been updated notify the manager
if (previousVolumeMask != parameters.volumeMask)
{
NotifyUpdatedTexure();
previousVolumeMask = parameters.volumeMask;
}
}
private void NotifyUpdatedTexure()
{
if (OnTextureUpdated != null)
{
OnTextureUpdated();
}
}
private void Awake()

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


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

float4 _VBufferSampleOffset; // Not used by this shader
float _CornetteShanksConstant; // Not used by this shader
uint _NumVisibleDensityVolumes;
float2 _VolumeMaskDimensions; //x = width , y = depth
float4 SampleVolumeMask(DensityVolumeData volumeData, float3 voxelCenterUV)
{
//TODO: transform voxelCenterUV based on volume texture transform
float totalTextures = _VolumeMaskDimensions.y / _VolumeMaskDimensions.x;
float offset = volumeData.textureIndex / totalTextures;
float clampBorder = 0.5f / _VolumeMaskDimensions.x;
voxelCenterUV.z /= totalTextures;
voxelCenterUV.z += offset;
voxelCenterUV.z = clamp(voxelCenterUV.z, offset + clampBorder, offset + (1.0f / totalTextures) - clampBorder);
float4 maskValue = SAMPLE_TEXTURE3D_LOD(_VolumeMaskAtlas, s_linear_clamp_sampler, voxelCenterUV, 0);
return maskValue;
}
void FillVolumetricDensityBuffer(PositionInputs posInput, float3 rayOriginWS, float3 rayUnDirWS,
float3 voxelAxisRight, float3 voxelAxisUp, float3 voxelAxisForward)

if (overlapFraction > 0)
{
float4 scatteringAndExtinctionMask = float4(1.0f, 1.0f, 1.0f, 1.0f);
//Sample the volumeMask
if (_VolumeData[volumeIndex].textureIndex != -1)
{
scatteringAndExtinctionMask = SampleVolumeMask(_VolumeData[volumeIndex], voxelCenterUV);
}
voxelScattering += overlapFraction * _VolumeData[volumeIndex].scattering;
voxelExtinction += overlapFraction * _VolumeData[volumeIndex].extinction;
voxelScattering += overlapFraction * _VolumeData[volumeIndex].scattering * scatteringAndExtinctionMask.rgb;
voxelExtinction += overlapFraction * _VolumeData[volumeIndex].extinction * scatteringAndExtinctionMask.a;
}
#ifndef USE_CLUSTERED_LIGHTLIST

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


{
public Vector3 scattering; // [0, 1], prefer sRGB
public float extinction; // [0, 1], prefer sRGB
public int textureIndex; //
public static DensityVolumeData GetNeutralValues()
{

data.extinction = 0;
data.textureIndex = -1;
return data;
}

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.r = Mathf.Clamp01(albedo.r);
albedo.g = Mathf.Clamp01(albedo.g);
albedo.b = Mathf.Clamp01(albedo.b);
albedo.a = 1.0f;
meanFreePath = Mathf.Clamp(meanFreePath, 1.0f, float.MaxValue);
asymmetry = Mathf.Clamp(asymmetry, -1.0f, 1.0f);
}
public DensityVolumeData GetData()
{
DensityVolumeData data = new DensityVolumeData();
data.extinction = VolumeRenderingUtils.ExtinctionFromMeanFreePath(meanFreePath);
data.scattering = VolumeRenderingUtils.ScatteringFromExtinctionAndAlbedo(data.extinction, (Vector3)(Vector4)albedo);
return data;
}
} // class VolumeParameters
public struct DensityVolumeList
{

m_VisibleVolumeData.Clear();
// Collect all visible finite volume data, and upload it to the GPU.
HomogeneousDensityVolume[] volumes = DensityVolumeManager.manager.GetAllVolumes();
HomogeneousDensityVolume[] volumes = DensityVolumeManager.manager.PrepareDensityVolumeData(cmd);
for (int i = 0; i < Math.Min(volumes.Length, k_MaxVisibleVolumeCount); i++)
{

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);
Texture3D volumeAtlas = DensityVolumeManager.manager.volumeAtlas.volumeAtlas;
Vector2 volumeAtlasDimensions = new Vector2(0.0f, 0.0f);
if (volumeAtlas != null)
{
volumeAtlasDimensions.x = volumeAtlas.width;
volumeAtlasDimensions.y = volumeAtlas.depth;
}
cmd.SetComputeTextureParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeMaskAtlas, volumeAtlas);
cmd.SetComputeVectorParam(m_VolumeVoxelizationCS, HDShaderIDs._VolumeMaskDimensions, volumeAtlasDimensions);
// The shader defines GROUP_SIZE_1D = 8.
cmd.DispatchCompute(m_VolumeVoxelizationCS, kernel, (w + 7) / 8, (h + 7) / 8, 1);

15
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.cs.hlsl


#ifndef VOLUMETRICLIGHTING_CS_HLSL
#define VOLUMETRICLIGHTING_CS_HLSL
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.DensityVolumeProperties
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.DensityVolumeData
struct DensityVolumeProperties
struct DensityVolumeData
int textureIndex;
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.DensityVolumeProperties
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.DensityVolumeData
float3 GetScattering(DensityVolumeProperties value)
float3 GetScattering(DensityVolumeData value)
float GetExtinction(DensityVolumeProperties value)
float GetExtinction(DensityVolumeData value)
}
int GetTextureIndex(DensityVolumeData value)
{
return value.textureIndex;
}

4
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Material/StackLit/StackLit.cs.hlsl


#define DEBUGVIEW_STACKLIT_BSDFDATA_NORMAL_VIEW_SPACE (1404)
#define DEBUGVIEW_STACKLIT_BSDFDATA_PERCEPTUAL_ROUGHNESS_A (1405)
#define DEBUGVIEW_STACKLIT_BSDFDATA_PERCEPTUAL_ROUGHNESS_B (1406)
#define DEBUGVIEW_STACKLIT_BSDFDATA_LOBE_MIXING (1407)
#define DEBUGVIEW_STACKLIT_BSDFDATA_LOBE_MIX (1407)
#define DEBUGVIEW_STACKLIT_BSDFDATA_ROUGHNESS_AT (1408)
#define DEBUGVIEW_STACKLIT_BSDFDATA_ROUGHNESS_AB (1409)
#define DEBUGVIEW_STACKLIT_BSDFDATA_ROUGHNESS_BT (1410)

case DEBUGVIEW_STACKLIT_BSDFDATA_PERCEPTUAL_ROUGHNESS_B:
result = bsdfdata.perceptualRoughnessB.xxx;
break;
case DEBUGVIEW_STACKLIT_BSDFDATA_LOBE_MIXING:
case DEBUGVIEW_STACKLIT_BSDFDATA_LOBE_MIX:
result = bsdfdata.lobeMix.xxx;
break;
case DEBUGVIEW_STACKLIT_BSDFDATA_ROUGHNESS_AT:

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


param.albedo = albedo;
param.meanFreePath = meanFreePath;
param.asymmetry = asymmetry;
param.textureIndex = -1;
param.volumeMask = null;
DensityVolumeData data = param.GetData();

136
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumeTextureAtlas.cs


using System;
using System.Collections.Generic;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
public class VolumeTextureAtlas
{
private List<Texture3D> textures = null;
//Assuming every volume texture is square and number of depth slices equal to 2D dimensions
private int requiredTextureSize;
private TextureFormat requiredTextureFormat;
public bool needTextureUpdate
{
get;
private set;
}
public Texture3D volumeAtlas
{
get;
private set;
}
public event Action OnAtlasUpdated;
private void NotifyAtlasUpdated()
{
if (OnAtlasUpdated != null)
{
OnAtlasUpdated();
}
}
public VolumeTextureAtlas(TextureFormat atlasFormat, int atlasSize )
{
requiredTextureSize = atlasSize;
requiredTextureFormat = atlasFormat;
textures = new List<Texture3D>();
needTextureUpdate = false;
}
public void ClearTextures()
{
textures.Clear();
needTextureUpdate = true;
}
public void AddTexture(Texture3D volumeTexture)
{
//TODO: we should really just convert the texture to the right size and format...HOWEVER, we dont' support 3D textures at the moment in the ConvertTexture call
if (volumeTexture.width != requiredTextureSize || volumeTexture.height != requiredTextureSize || volumeTexture.depth != requiredTextureSize)
{
Debug.LogError(string.Format("VolumeTextureAtlas: Dimensions of texture {0} does not match expected dimensions of {1}", volumeTexture, requiredTextureSize));
return;
}
if (volumeTexture.format != requiredTextureFormat)
{
Debug.LogError(string.Format("VolumeTextureAtlas: Texture format of texture {0} : {1} does not match expected format of {2}", volumeTexture, volumeTexture.format, requiredTextureSize));
return;
}
if (!textures.Contains(volumeTexture))
{
textures.Add(volumeTexture);
needTextureUpdate = true;
}
}
public void RemoveTexture(Texture3D volumeTexture)
{
if (textures.Contains(volumeTexture))
{
textures.Add(volumeTexture);
needTextureUpdate = true;
}
}
//Generates the volume atlas by converting (if needed) and then copying the textures into one big volume texture.
public void GenerateVolumeAtlas(CommandBuffer cmd)
{
if (needTextureUpdate)
{
if (textures.Count > 0)
{
Color[] colorArray = new Color[0];
volumeAtlas = new Texture3D(requiredTextureSize, requiredTextureSize, requiredTextureSize * textures.Count, requiredTextureFormat, false);
// int volumeDepthOffset = 0;
foreach (Texture3D tex in textures)
{
//UGGG this is awful...why you no working CopyTexture???
Color[] texColor = tex.GetPixels();
Array.Resize(ref colorArray, texColor.Length + colorArray.Length);
Array.Copy(texColor, 0, colorArray, colorArray.Length - texColor.Length, texColor.Length);
for (int i = 0; i < requiredTextureSize; i++)
{
/*
cmd.CopyTexture(tex, i, volumeAtlas, volumeDepthOffset);
volumeDepthOffset++;*/
}
}
volumeAtlas.SetPixels(colorArray);
volumeAtlas.Apply();
}
else
{
volumeAtlas = null;
}
needTextureUpdate = false;
NotifyAtlasUpdated();
}
}
public int GetTextureIndex(Texture3D tex)
{
return textures.IndexOf(tex);
}
}
}

11
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumeTextureAtlas.cs.meta


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