浏览代码

Merge pull request #850 from EvgeniiG/master

Factor out VolumetricLightingModule
/main
GitHub 7 年前
当前提交
cc8c318a
共有 4 个文件被更改,包括 149 次插入138 次删除
  1. 15
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Camera/HDCamera.cs
  2. 20
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs
  3. 19
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/HomogeneousFog.cs
  4. 233
      ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/VolumetricLighting.cs

15
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Camera/HDCamera.cs


renderTextureDesc = tempDesc;
}
// Warning: different views can use the same camera!
public int GetViewID()
{
if (camera.cameraType == CameraType.Game)
{
int viewID = camera.GetInstanceID();
Debug.Assert(viewID > 0);
return viewID;
}
else
{
return 0;
}
}
public void Reset()
{
m_LastFrameActive = -1;

20
ScriptableRenderPipeline/HDRenderPipeline/HDRP/HDRenderPipeline.cs


}
public partial class HDRenderPipeline : RenderPipeline
public class HDRenderPipeline : RenderPipeline
{
enum ForwardPass
{

readonly SkyManager m_SkyManager = new SkyManager();
readonly LightLoop m_LightLoop = new LightLoop();
readonly ShadowSettings m_ShadowSettings = new ShadowSettings();
readonly VolumetricLightingModule m_VolumetricLightingModule = new VolumetricLightingModule();
// Debugging
MaterialPropertyBlock m_SharedPropertyBlock = new MaterialPropertyBlock();

m_LightLoop.Build(asset, m_ShadowSettings, m_IBLFilterGGX);
m_SkyManager.Build(asset, m_IBLFilterGGX);
m_VolumetricLightingModule.Build(asset);
m_DebugDisplaySettings.RegisterDebug();
FrameSettings.RegisterDebug("Default Camera", m_Asset.GetFrameSettings());

m_SSSBufferManager.Cleanup();
m_SkyManager.Cleanup();
m_VolumetricLightingModule.Cleanup();
SupportedRenderingFeatures.active = new SupportedRenderingFeatures();
}

}
// Warning: (resolutionChanged == false) if you open a new Editor tab of the same size!
if (m_VolumetricLightingPreset != VolumetricLightingPreset.Off)
{
ResizeVBuffer(GetViewID(hdCamera), texWidth, texHeight);
}
m_VolumetricLightingModule.ResizeVBuffer(hdCamera, texWidth, texHeight);
// update recorded window resolution
m_CurrentWidth = texWidth;

m_DbufferManager.PushGlobalParams(cmd);
if (m_VolumetricLightingPreset != VolumetricLightingPreset.Off)
{
SetVolumetricLightingData(hdCamera, cmd);
}
m_VolumetricLightingModule.PushGlobalParams(hdCamera, cmd);
}
}

// Render the volumetric lighting.
// The pass requires the volume properties, the light list and the shadows, and can run async.
VolumetricLightingPass(hdCamera, cmd);
m_VolumetricLightingModule.VolumetricLightingPass(hdCamera, cmd, m_FrameSettings);
RenderDeferredLighting(hdCamera, cmd);

m_SkyManager.RenderSky(hdCamera, m_LightLoop.GetCurrentSunLight(), m_CameraColorBufferRT, m_CameraDepthStencilBufferRT, cmd);
if (visualEnv.fogType != FogType.None || m_VolumetricLightingPreset != VolumetricLightingPreset.Off)
if (visualEnv.fogType != FogType.None || m_VolumetricLightingModule.preset != VolumetricLightingModule.VolumetricLightingPreset.Off)
m_SkyManager.RenderOpaqueAtmosphericScattering(cmd);
}

19
ScriptableRenderPipeline/HDRenderPipeline/HDRP/Lighting/Volumetrics/HomogeneousFog.cs


Gizmos.DrawWireCube(volumeParameters.bounds.center, volumeParameters.bounds.size);
}
}
// Returns NULL if a global fog component does not exist, or is not enabled.
public static HomogeneousFog GetGlobalFogComponent()
{
HomogeneousFog globalFogComponent = null;
HomogeneousFog[] fogComponents = FindObjectsOfType(typeof(HomogeneousFog)) as HomogeneousFog[];
foreach (HomogeneousFog fogComponent in fogComponents)
{
if (fogComponent.enabled && fogComponent.volumeParameters.IsVolumeUnbounded())
{
globalFogComponent = fogComponent;
break;
}
}
return globalFogComponent;
}
}
} // UnityEngine.Experimental.Rendering.HDPipeline

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


}
} // class VolumeParameters
public partial class HDRenderPipeline : RenderPipeline
public class VolumetricLightingModule
{
public enum VolumetricLightingPreset
{

Count
};
VolumetricLightingPreset m_VolumetricLightingPreset
{ get { return (VolumetricLightingPreset)Math.Min(ShaderConfig.s_VolumetricLightingPreset, (int)VolumetricLightingPreset.Count); } }
ComputeShader m_VolumetricLightingCS { get { return m_Asset.renderPipelineResources.volumetricLightingCS; } }
}
class VBuffer
{
public int viewID = -1; // -1 is invalid; positive for Game Views, 0 otherwise

Debug.Assert(viewID > 0); // Game View only
return lightingRTID[1 + ((Time.renderedFrameCount + 1) & 1)];
}
};
List<VBuffer> m_VBuffers = 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
public void Create(int viewID, int w, int h, int d)
{
Debug.Assert(viewID >= 0);
Debug.Assert(w > 0 && h > 0 && d > 0);
// Warning: different views can use the same camera!
int GetViewID(HDCamera camera)
{
Debug.Assert(camera != null);
// Clean up first.
Destroy();
// The required number of buffers depends on the view type.
bool isGameView = viewID > 0;
int n = isGameView ? 3 : 1;
this.viewID = viewID;
this.lightingRTEX = new RenderTexture[n];
this.lightingRTID = new RenderTargetIdentifier[n];
for (int i = 0; i < n; i++)
{
this.lightingRTEX[i] = new RenderTexture(w, h, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
this.lightingRTEX[i].filterMode = FilterMode.Trilinear; // Custom
this.lightingRTEX[i].dimension = TextureDimension.Tex3D; // TODO: request the thick 3D tiling layout
this.lightingRTEX[i].volumeDepth = d;
this.lightingRTEX[i].enableRandomWrite = true;
this.lightingRTEX[i].Create();
if (camera.camera.cameraType == CameraType.Game)
{
int viewID = camera.camera.GetInstanceID();
Debug.Assert(viewID > 0);
return viewID;
this.lightingRTID[i] = new RenderTargetIdentifier(this.lightingRTEX[i]);
}
else
public void Destroy()
return 0;
if (this.lightingRTEX != null)
{
for (int i = 0, n = this.lightingRTEX.Length; i < n; i++)
{
this.lightingRTEX[i].Release();
}
}
this.viewID = -1;
this.lightingRTEX = null;
this.lightingRTID = null;
} // class VBuffer
public VolumetricLightingPreset preset { get { return (VolumetricLightingPreset)Math.Min(ShaderConfig.s_VolumetricLightingPreset, (int)VolumetricLightingPreset.Count); } }
ComputeShader m_VolumetricLightingCS = null;
List<VBuffer> m_VBuffers = 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
public void Build(HDRenderPipelineAsset asset)
{
if (preset == VolumetricLightingPreset.Off) return;
m_VolumetricLightingCS = asset.renderPipelineResources.volumetricLightingCS;
m_VBuffers = new List<VBuffer>(1);
VBuffer FindVBuffer(int viewID)
public void Cleanup()
Debug.Assert(viewID >= 0);
if (preset == VolumetricLightingPreset.Off) return;
VBuffer vBuffer = null;
m_VolumetricLightingCS = null;
if (m_VBuffers != null)
for (int i = 0, n = m_VBuffers.Count; i < n; i++)
int n = m_VBuffers.Count;
for (int i = 0; i < n; i++)
{
if (viewID == m_VBuffers[i].viewID)
{
vBuffer = m_VBuffers[i];
}
}
m_VBuffers[i].Destroy();
return vBuffer;
m_VBuffers = null;
void ResizeVBuffer(int viewID, int screenWidth, int screenHeight)
public void ResizeVBuffer(HDCamera camera, int screenWidth, int screenHeight)
int viewID = camera.GetViewID();
if (preset == VolumetricLightingPreset.Off) return;
ComputeVBufferResolutionAndScale(screenWidth, screenHeight, ref w, ref h, ref d);
ComputeVBufferResolutionAndScale(preset, screenWidth, screenHeight, ref w, ref h, ref d);
VBuffer vBuffer = FindVBuffer(viewID);

return;
}
}
// Otherwise, we have to (re)create the VBuffer.
CreateVBuffer(viewID, w, h, d, vBuffer);
}
void CreateVBuffer(int viewID, int w, int h, int d, VBuffer vBuffer)
{
Debug.Assert(viewID >= 0);
if (vBuffer != null)
{
// Clean up first.
DestroyVBuffer(vBuffer);
}
// Grow the array.
// Not found - grow the array.
if (m_VBuffers == null)
{
m_VBuffers = new List<VBuffer>(1);
}
bool isGameView = viewID > 0;
int numBuffers = isGameView ? 3 : 1;
vBuffer.viewID = viewID;
vBuffer.lightingRTEX = new RenderTexture[numBuffers];
vBuffer.lightingRTID = new RenderTargetIdentifier[numBuffers];
for (int i = 0; i < numBuffers; i++)
{
vBuffer.lightingRTEX[i] = new RenderTexture(w, h, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
vBuffer.lightingRTEX[i].filterMode = FilterMode.Trilinear; // Custom
vBuffer.lightingRTEX[i].dimension = TextureDimension.Tex3D; // TODO: request the thick 3D tiling layout
vBuffer.lightingRTEX[i].volumeDepth = d;
vBuffer.lightingRTEX[i].enableRandomWrite = true;
vBuffer.lightingRTEX[i].Create();
vBuffer.lightingRTID[i] = new RenderTargetIdentifier(vBuffer.lightingRTEX[i]);
}
vBuffer.Create(viewID, w, h, d);
void DestroyVBuffer(VBuffer vBuffer)
VBuffer FindVBuffer(int viewID)
if (vBuffer == null) return;
Debug.Assert(viewID >= 0);
VBuffer vBuffer = null;
if (vBuffer.lightingRTEX != null)
if (m_VBuffers != null)
int n = vBuffer.lightingRTEX.Length;
int n = m_VBuffers.Count;
vBuffer.lightingRTEX[i].Release();
if (viewID == m_VBuffers[i].viewID)
{
vBuffer = m_VBuffers[i];
}
vBuffer.viewID = -1;
vBuffer.lightingRTEX = null;
vBuffer.lightingRTID = null;
return vBuffer;
public static int ComputeVBufferTileSize(VolumetricLightingPreset preset)
static int ComputeVBufferTileSize(VolumetricLightingPreset preset)
{
switch (preset)
{

}
}
public static int ComputeVBufferSliceCount(VolumetricLightingPreset preset)
static int ComputeVBufferSliceCount(VolumetricLightingPreset preset)
{
switch (preset)
{

// Since a single voxel corresponds to a tile (e.g. 8x8) of pixels,
// the VBuffer can potentially extend past the boundaries of the viewport.
// The function returns the fraction of the {width, height} of the VBuffer visible on screen.
Vector2 ComputeVBufferResolutionAndScale(float screenWidth, float screenHeight,
ref int w, ref int h, ref int d)
static Vector2 ComputeVBufferResolutionAndScale(VolumetricLightingPreset preset,
int screenWidth, int screenHeight,
ref int w, ref int h, ref int d)
int t = ComputeVBufferTileSize(m_VolumetricLightingPreset);
int t = ComputeVBufferTileSize(preset);
w = ((int)screenWidth + t - 1) / t;
h = ((int)screenHeight + t - 1) / t;
d = ComputeVBufferSliceCount(m_VolumetricLightingPreset);
w = (screenWidth + t - 1) / t;
h = (screenHeight + t - 1) / t;
d = ComputeVBufferSliceCount(preset);
return new Vector2(screenWidth / (w * t), screenHeight / (h * t));
return new Vector2((float)screenWidth / (float)(w * t), (float)screenHeight / (float)(h * t));
public static Vector4 ComputeLogarithmicDepthEncodingParams(float nearPlane, float farPlane)
static Vector4 ComputeLogarithmicDepthEncodingParams(float nearPlane, float farPlane)
{
Vector4 depthParams = new Vector4();

return depthParams;
}
// Returns NULL if a global fog component does not exist, or is not enabled.
public static HomogeneousFog GetGlobalFogComponent()
{
HomogeneousFog globalFogComponent = null;
HomogeneousFog[] fogComponents = Object.FindObjectsOfType(typeof(HomogeneousFog)) as HomogeneousFog[];
foreach (HomogeneousFog fogComponent in fogComponents)
{
if (fogComponent.enabled && fogComponent.volumeParameters.IsVolumeUnbounded())
{
globalFogComponent = fogComponent;
break;
}
}
return globalFogComponent;
}
public void SetVolumetricLightingData(HDCamera camera, CommandBuffer cmd)
public void PushGlobalParams(HDCamera camera, CommandBuffer cmd)
HomogeneousFog globalFogComponent = GetGlobalFogComponent();
if (preset == VolumetricLightingPreset.Off) return;
HomogeneousFog globalFogComponent = HomogeneousFog.GetGlobalFogComponent();
// TODO: may want to cache these results somewhere.
VolumeProperties globalFogProperties = (globalFogComponent != null) ? globalFogComponent.volumeParameters.GetProperties()

cmd.SetGlobalFloat( HDShaderIDs._GlobalFog_Extinction, globalFogProperties.extinction);
int w = 0, h = 0, d = 0;
Vector2 scale = ComputeVBufferResolutionAndScale(camera.screenSize.x, camera.screenSize.y, ref w, ref h, ref d);
Vector2 scale = ComputeVBufferResolutionAndScale(preset, (int)camera.screenSize.x, (int)camera.screenSize.y, ref w, ref h, ref d);
VBuffer vBuffer = FindVBuffer(GetViewID(camera));
VBuffer vBuffer = FindVBuffer(camera.GetViewID());
Debug.Assert(vBuffer != null);
cmd.SetGlobalVector( HDShaderIDs._VBufferResolution, new Vector4(w, h, 1.0f / w, 1.0f / h));

// The returned {x, y} coordinates (and all spheres) are all within the (-0.5, 0.5)^2 range.
// The pattern has been rotated by 15 degrees to maximize the resolution along X and Y:
// https://www.desmos.com/calculator/kcpfvltz7c
Vector2[] GetHexagonalClosePackedSpheres7()
static Vector2[] GetHexagonalClosePackedSpheres7()
{
Vector2[] coords = new Vector2[7];

return coords;
}
void VolumetricLightingPass(HDCamera camera, CommandBuffer cmd)
public void VolumetricLightingPass(HDCamera camera, CommandBuffer cmd, FrameSettings frameSettings)
if (m_VolumetricLightingPreset == VolumetricLightingPreset.Off) return;
if (preset == VolumetricLightingPreset.Off) return;
VBuffer vBuffer = FindVBuffer(GetViewID(camera));
VBuffer vBuffer = FindVBuffer(camera.GetViewID());
if (GetGlobalFogComponent() == null)
if (HomogeneousFog.GetGlobalFogComponent() == null)
{
// Clear the render target instead of running the shader.
// CoreUtils.SetRenderTarget(cmd, GetVBufferLightingIntegral(viewOffset), ClearFlag.Color, CoreUtils.clearColorAllBlack);

// Use the workaround by running the full shader with no volume.
}
bool enableClustered = m_FrameSettings.lightLoopSettings.enableTileAndCluster;
bool enableClustered = frameSettings.lightLoopSettings.enableTileAndCluster;
bool enableReprojection = Application.isPlaying && camera.camera.cameraType == CameraType.Game;
int kernel;

}
int w = 0, h = 0, d = 0;
Vector2 scale = ComputeVBufferResolutionAndScale(camera.screenSize.x, camera.screenSize.y, ref w, ref h, ref d);
Vector2 scale = ComputeVBufferResolutionAndScale(preset, (int)camera.screenSize.x, (int)camera.screenSize.y, ref w, ref h, ref d);
float vFoV = camera.camera.fieldOfView * Mathf.Deg2Rad;
// Compose the matrix which allows us to compute the world space view direction.

cmd.DispatchCompute(m_VolumetricLightingCS, kernel, (w + 15) / 16, (h + 15) / 16, 1);
}
}
} // class HDRenderPipeline
} // class VolumetricLightingModule
} // namespace UnityEngine.Experimental.Rendering.HDPipeline
正在加载...
取消
保存