|
|
|
|
|
|
|
|
|
|
namespace UnityEngine.Experimental.Rendering.LightweightPipeline |
|
|
|
{ |
|
|
|
public enum RenderPassHandles |
|
|
|
{ |
|
|
|
DepthPrepass, |
|
|
|
DirectionalShadows, |
|
|
|
LocalShadows, |
|
|
|
ScreenSpaceShadowResolve, |
|
|
|
ForwardLit, |
|
|
|
Count, |
|
|
|
} |
|
|
|
|
|
|
|
public enum MaterialHandles |
|
|
|
{ |
|
|
|
Error, |
|
|
|
|
|
|
public static class RenderTargetHandles |
|
|
|
{ |
|
|
|
public static int Color; |
|
|
|
public static int Depth; |
|
|
|
public static int DepthCopy; |
|
|
|
public static int DepthAttachment; |
|
|
|
public static int DepthTexture; |
|
|
|
public static int OpaqueColor; |
|
|
|
public static int DirectionalShadowmap; |
|
|
|
public static int LocalShadowmap; |
|
|
|
|
|
|
public FilterRenderersSettings opaqueFilterSettings { get; private set; } |
|
|
|
public FilterRenderersSettings transparentFilterSettings { get; private set; } |
|
|
|
|
|
|
|
//RenderGraphNode m_RenderGraph;
|
|
|
|
List<ScriptableRenderPass> m_ShadowPassList = new List<ScriptableRenderPass>(); |
|
|
|
List<ScriptableRenderPass> m_RenderPassList = new List<ScriptableRenderPass>(); |
|
|
|
Dictionary<int, Material> m_Materials = new Dictionary<int, Material>(); |
|
|
|
Dictionary<RenderPassHandles, ScriptableRenderPass> m_RenderPassSet = new Dictionary<RenderPassHandles, ScriptableRenderPass>(); |
|
|
|
DepthOnlyPass depthOnlyPass; |
|
|
|
DirectionalShadowsPass directionalShadowPass; |
|
|
|
LocalShadowsPass localShadowsPass; |
|
|
|
ScreenSpaceShadowOcclusionPass screenSpaceShadowOcclusionPass; |
|
|
|
ForwardLitPass forwardLitPass; |
|
|
|
|
|
|
|
Dictionary<int, Material> m_Materials; |
|
|
|
List<RenderPassAttachment> m_AttachmentList; |
|
|
|
|
|
|
|
RenderPass m_RenderPass; |
|
|
|
List<ScriptableRenderPass> m_ActiveShadowQueue = new List<ScriptableRenderPass>(); |
|
|
|
List<ScriptableRenderPass> m_ActiveRenderPassQueue = new List<ScriptableRenderPass>(); |
|
|
|
AddSurface("_CameraColorTexture", out RenderTargetHandles.Color); |
|
|
|
AddSurface("_CameraDepthTexture", out RenderTargetHandles.Depth); |
|
|
|
AddSurface("_CameraDepthTextureCopy", out RenderTargetHandles.DepthCopy); |
|
|
|
AddSurface("_CameraOpaqueTexture", out RenderTargetHandles.OpaqueColor); |
|
|
|
AddSurface("_DirectionalShadowmapTexture", out RenderTargetHandles.DirectionalShadowmap); |
|
|
|
AddSurface("_LocalShadowmapTexture", out RenderTargetHandles.LocalShadowmap); |
|
|
|
AddSurface("_ScreenSpaceShadowMapTexture", out RenderTargetHandles.ScreenSpaceOcclusion); |
|
|
|
RegisterSurface("_CameraColorTexture", out RenderTargetHandles.Color); |
|
|
|
RegisterSurface("_CameraDepthAttachment", out RenderTargetHandles.DepthAttachment); |
|
|
|
RegisterSurface("_CameraDepthTexture", out RenderTargetHandles.DepthTexture); |
|
|
|
RegisterSurface("_CameraOpaqueTexture", out RenderTargetHandles.OpaqueColor); |
|
|
|
RegisterSurface("_DirectionalShadowmapTexture", out RenderTargetHandles.DirectionalShadowmap); |
|
|
|
RegisterSurface("_LocalShadowmapTexture", out RenderTargetHandles.LocalShadowmap); |
|
|
|
RegisterSurface("_ScreenSpaceShadowMapTexture", out RenderTargetHandles.ScreenSpaceOcclusion); |
|
|
|
m_Materials = new Dictionary<int, Material>((int)MaterialHandles.Count); |
|
|
|
m_Materials.Add((int)MaterialHandles.Error, CoreUtils.CreateEngineMaterial("Hidden/InternalErrorShader")); |
|
|
|
m_Materials.Add((int)MaterialHandles.DepthCopy, CoreUtils.CreateEngineMaterial(pipelineAsset.CopyDepthShader)); |
|
|
|
m_Materials.Add((int)MaterialHandles.Sampling, CoreUtils.CreateEngineMaterial(pipelineAsset.SamplingShader)); |
|
|
|
m_Materials.Add((int)MaterialHandles.Blit, CoreUtils.CreateEngineMaterial(pipelineAsset.BlitShader)); |
|
|
|
m_Materials.Add((int)MaterialHandles.ScrenSpaceShadow, CoreUtils.CreateEngineMaterial(pipelineAsset.ScreenSpaceShadowShader)); |
|
|
|
Debug.Assert(m_Materials.Count == (int)MaterialHandles.Count, "All materials in MaterialHandles should be created."); |
|
|
|
RegisterMaterial(MaterialHandles.Error, CoreUtils.CreateEngineMaterial("Hidden/InternalErrorShader")); |
|
|
|
RegisterMaterial(MaterialHandles.DepthCopy, CoreUtils.CreateEngineMaterial(pipelineAsset.CopyDepthShader)); |
|
|
|
RegisterMaterial(MaterialHandles.Sampling, CoreUtils.CreateEngineMaterial(pipelineAsset.SamplingShader)); |
|
|
|
RegisterMaterial(MaterialHandles.Blit, CoreUtils.CreateEngineMaterial(pipelineAsset.BlitShader)); |
|
|
|
RegisterMaterial(MaterialHandles.ScrenSpaceShadow, CoreUtils.CreateEngineMaterial(pipelineAsset.ScreenSpaceShadowShader)); |
|
|
|
Debug.Assert(m_Materials.Count == (int)MaterialHandles.Count, "All materials in MaterialHandles should be registered in the renderer."); |
|
|
|
depthOnlyPass = new DepthOnlyPass(this); |
|
|
|
directionalShadowPass = new DirectionalShadowsPass(this, pipelineAsset.DirectionalShadowAtlasResolution); |
|
|
|
localShadowsPass = new LocalShadowsPass(this, pipelineAsset.LocalShadowAtlasResolution); |
|
|
|
screenSpaceShadowOcclusionPass = new ScreenSpaceShadowOcclusionPass(this); |
|
|
|
forwardLitPass = new ForwardLitPass(this); |
|
|
|
RegisterPass(RenderPassHandles.DepthPrepass, new DepthOnlyPass(this)); |
|
|
|
RegisterPass(RenderPassHandles.DirectionalShadows, new DirectionalShadowsPass(this, pipelineAsset.DirectionalShadowAtlasResolution)); |
|
|
|
RegisterPass(RenderPassHandles.LocalShadows, new LocalShadowsPass(this, pipelineAsset.LocalShadowAtlasResolution)); |
|
|
|
RegisterPass(RenderPassHandles.ScreenSpaceShadowResolve, new ScreenSpaceShadowResolvePass(this)); |
|
|
|
RegisterPass(RenderPassHandles.ForwardLit, new ForwardLitPass(this)); |
|
|
|
Debug.Assert(m_RenderPassSet.Count == (int)RenderPassHandles.Count, "All render passes in Passes should be registered in the renderer"); |
|
|
|
|
|
|
|
postProcessRenderContext = new PostProcessRenderContext(); |
|
|
|
|
|
|
|
|
|
|
return m_Materials[resourceHandleID]; |
|
|
|
} |
|
|
|
|
|
|
|
void AddSurface(string shaderProperty, out int handle) |
|
|
|
{ |
|
|
|
handle = Shader.PropertyToID(shaderProperty); |
|
|
|
m_ResourceMap.Add(handle, new RenderTargetIdentifier(handle)); |
|
|
|
} |
|
|
|
|
|
|
|
public RenderTextureDescriptor CreateRTDesc(ref CameraData cameraData, float scaler = 1.0f) |
|
|
|
{ |
|
|
|
Camera camera = cameraData.camera; |
|
|
|
|
|
|
|
|
|
|
public void Setup(ref ScriptableRenderContext context, ref CullResults cullResults, ref CameraData cameraData, ref LightData lightData) |
|
|
|
{ |
|
|
|
CommandBuffer cmd = CommandBufferPool.Get("Setup Rendering"); |
|
|
|
m_ShadowPassList.Clear(); |
|
|
|
m_RenderPassList.Clear(); |
|
|
|
Clear(); |
|
|
|
bool requiresCameraDepth = cameraData.requiresDepthTexture || cameraData.postProcessEnabled || cameraData.isSceneViewCamera; |
|
|
|
bool shadowsEnabledForCamera = cameraData.maxShadowDistance > 0.0f; |
|
|
|
bool msaaEnabledForCamera = cameraData.msaaSamples > 1; |
|
|
|
bool supportsTexture2DMS = SystemInfo.supportsMultisampledTextures != 0; |
|
|
|
bool supportsTextureCopy = SystemInfo.copyTextureSupport != CopyTextureSupport.None; |
|
|
|
bool copyShaderSupported = GetMaterial(MaterialHandles.DepthCopy).shader.isSupported && (msaaEnabledForCamera == supportsTexture2DMS); |
|
|
|
bool supportsDepthCopy = copyShaderSupported || supportsTextureCopy; |
|
|
|
bool requiresDepthPrepassToResolveMsaa = msaaEnabledForCamera && !supportsTexture2DMS; |
|
|
|
bool renderDirectionalShadows = shadowsEnabledForCamera && lightData.shadowData.supportsDirectionalShadows; |
|
|
|
bool requiresScreenSpaceShadows = renderDirectionalShadows && lightData.shadowData.requiresScreenSpaceOcclusion; |
|
|
|
bool requiresDepthPrepass = requiresScreenSpaceShadows || (requiresCameraDepth && (!supportsDepthCopy || requiresDepthPrepassToResolveMsaa)); |
|
|
|
bool requiresCameraDepth = cameraData.requiresDepthTexture; |
|
|
|
bool depthRenderBuffer = requiresCameraDepth && !requiresDepthPrepass; |
|
|
|
bool intermediateRenderTexture = cameraData.isSceneViewCamera || |
|
|
|
!Mathf.Approximately(cameraData.renderScale, 1.0f) || |
|
|
|
cameraData.isHdrEnabled || |
|
|
|
baseDescriptor.dimension == TextureDimension.Tex2DArray || |
|
|
|
cameraData.postProcessEnabled || |
|
|
|
depthRenderBuffer || |
|
|
|
cameraData.requiresOpaqueTexture; |
|
|
|
ShadowData shadowData = lightData.shadowData; |
|
|
|
bool requiresDepthPrepass = shadowData.requiresScreenSpaceShadowResolve || cameraData.isSceneViewCamera || (requiresCameraDepth && !CanCopyDepth(ref cameraData)); |
|
|
|
CommandBuffer cmd = CommandBufferPool.Get("Setup Rendering"); |
|
|
|
{ |
|
|
|
depthOnlyPass.Setup(cmd, baseDescriptor, null, RenderTargetHandles.Depth); |
|
|
|
m_RenderPassList.Add(depthOnlyPass); |
|
|
|
} |
|
|
|
EnqueuePass(cmd, RenderPassHandles.DepthPrepass, baseDescriptor, null, RenderTargetHandles.DepthTexture); |
|
|
|
if (renderDirectionalShadows) |
|
|
|
if (shadowData.renderDirectionalShadows) |
|
|
|
directionalShadowPass.Setup(cmd, baseDescriptor); |
|
|
|
m_ShadowPassList.Add(directionalShadowPass); |
|
|
|
if (requiresScreenSpaceShadows) |
|
|
|
{ |
|
|
|
screenSpaceShadowOcclusionPass.Setup(cmd, baseDescriptor, new[] {RenderTargetHandles.ScreenSpaceOcclusion}); |
|
|
|
m_RenderPassList.Add(screenSpaceShadowOcclusionPass); |
|
|
|
} |
|
|
|
EnqueuePass(cmd, RenderPassHandles.DirectionalShadows, baseDescriptor); |
|
|
|
if (shadowData.requiresScreenSpaceShadowResolve) |
|
|
|
EnqueuePass(cmd, RenderPassHandles.ScreenSpaceShadowResolve, baseDescriptor, new[] {RenderTargetHandles.ScreenSpaceOcclusion}); |
|
|
|
if (shadowsEnabledForCamera && lightData.shadowData.supportsLocalShadows) |
|
|
|
{ |
|
|
|
localShadowsPass.Setup(cmd, baseDescriptor); |
|
|
|
m_ShadowPassList.Add(localShadowsPass); |
|
|
|
} |
|
|
|
if (shadowData.renderLocalShadows) |
|
|
|
EnqueuePass(cmd, RenderPassHandles.LocalShadows, baseDescriptor); |
|
|
|
int[] colorHandles = (intermediateRenderTexture) ? new[] {RenderTargetHandles.Color} : null; |
|
|
|
int depthHandle = (depthRenderBuffer) ? RenderTargetHandles.Depth : -1; |
|
|
|
forwardLitPass.Setup(cmd, baseDescriptor, colorHandles, depthHandle, cameraData.msaaSamples); |
|
|
|
m_RenderPassList.Add(forwardLitPass); |
|
|
|
bool requiresDepthAttachment = requiresCameraDepth && !requiresDepthPrepass; |
|
|
|
bool requiresColorAttachment = RequiresColorAttachment(ref cameraData, baseDescriptor) || requiresDepthAttachment; |
|
|
|
int[] colorHandles = (requiresColorAttachment) ? new[] {RenderTargetHandles.Color} : null; |
|
|
|
int depthHandle = (requiresColorAttachment) ? RenderTargetHandles.DepthAttachment : -1; |
|
|
|
EnqueuePass(cmd, RenderPassHandles.ForwardLit, baseDescriptor, colorHandles, depthHandle, cameraData.msaaSamples); |
|
|
|
|
|
|
|
context.ExecuteCommandBuffer(cmd); |
|
|
|
CommandBufferPool.Release(cmd); |
|
|
|
|
|
|
ref LightData lightData) |
|
|
|
{ |
|
|
|
for (int i = 0; i < m_ShadowPassList.Count; ++i) |
|
|
|
m_ShadowPassList[i].Execute(ref context, ref cullResults, ref cameraData, ref lightData); |
|
|
|
// TODO: The reason we have to separate passes into two queues is because shadows require different camera
|
|
|
|
// context. We need to take a look at approaches to effectively share shadow between cameras, then we
|
|
|
|
// can move this out
|
|
|
|
for (int i = 0; i < m_ActiveShadowQueue.Count; ++i) |
|
|
|
m_ActiveShadowQueue[i].Execute(ref context, ref cullResults, ref cameraData, ref lightData); |
|
|
|
|
|
|
|
// SetupCameraProperties does the following:
|
|
|
|
// Setup Camera RenderTarget and Viewport
|
|
|
|
|
|
|
// Setup global time properties (_Time, _SinTime, _CosTime)
|
|
|
|
context.SetupCameraProperties(cameraData.camera, cameraData.isStereoEnabled); |
|
|
|
|
|
|
|
for (int i = 0; i < m_RenderPassList.Count; ++i) |
|
|
|
m_RenderPassList[i].Execute(ref context, ref cullResults, ref cameraData, ref lightData); |
|
|
|
for (int i = 0; i < m_ActiveRenderPassQueue.Count; ++i) |
|
|
|
m_ActiveRenderPassQueue[i].Execute(ref context, ref cullResults, ref cameraData, ref lightData); |
|
|
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
if (cameraData.isSceneViewCamera) |
|
|
|
|
|
|
DisposePasses(ref context); |
|
|
|
} |
|
|
|
|
|
|
|
void Clear() |
|
|
|
{ |
|
|
|
m_ActiveShadowQueue.Clear(); |
|
|
|
m_ActiveRenderPassQueue.Clear(); |
|
|
|
} |
|
|
|
|
|
|
|
void RegisterSurface(string shaderProperty, out int handle) |
|
|
|
{ |
|
|
|
handle = Shader.PropertyToID(shaderProperty); |
|
|
|
m_ResourceMap.Add(handle, new RenderTargetIdentifier(handle)); |
|
|
|
} |
|
|
|
|
|
|
|
void RegisterMaterial(MaterialHandles handle, Material material) |
|
|
|
{ |
|
|
|
m_Materials.Add((int)handle, material); |
|
|
|
} |
|
|
|
|
|
|
|
void RegisterPass(RenderPassHandles passHandle, ScriptableRenderPass pass) |
|
|
|
{ |
|
|
|
m_RenderPassSet.Add(passHandle, pass); |
|
|
|
} |
|
|
|
|
|
|
|
void EnqueuePass(CommandBuffer cmd, RenderPassHandles passHandle, RenderTextureDescriptor baseDescriptor, |
|
|
|
int[] colorAttachmentHandles = null, int depthAttachmentHandle = -1, int samples = 1) |
|
|
|
{ |
|
|
|
Debug.Assert((int)passHandle < m_RenderPassSet.Count, "Trying to add an invalid pass to renderer's frame"); |
|
|
|
ScriptableRenderPass pass = m_RenderPassSet[passHandle]; |
|
|
|
pass.Setup(cmd, baseDescriptor, colorAttachmentHandles, depthAttachmentHandle, samples); |
|
|
|
|
|
|
|
if (passHandle == RenderPassHandles.DirectionalShadows || passHandle == RenderPassHandles.LocalShadows) |
|
|
|
m_ActiveShadowQueue.Add(pass); |
|
|
|
else |
|
|
|
m_ActiveRenderPassQueue.Add(pass); |
|
|
|
} |
|
|
|
|
|
|
|
bool RequiresColorAttachment(ref CameraData cameraData, RenderTextureDescriptor baseDescriptor) |
|
|
|
{ |
|
|
|
bool isScaledRender = !Mathf.Approximately(cameraData.renderScale, 1.0f); |
|
|
|
bool isTargetTexture2DArray = baseDescriptor.dimension == TextureDimension.Tex2DArray; |
|
|
|
return cameraData.isSceneViewCamera || isScaledRender || cameraData.isHdrEnabled || |
|
|
|
cameraData.postProcessEnabled || cameraData.requiresOpaqueTexture || isTargetTexture2DArray; |
|
|
|
} |
|
|
|
|
|
|
|
bool CanCopyDepth(ref CameraData cameraData) |
|
|
|
{ |
|
|
|
bool msaaEnabledForCamera = cameraData.msaaSamples > 1; |
|
|
|
bool supportsTextureCopy = SystemInfo.copyTextureSupport != CopyTextureSupport.None; |
|
|
|
bool supportsDepthTarget = SystemInfo.SupportsRenderTextureFormat(RenderTextureFormat.Depth); |
|
|
|
bool supportsDepthCopy = !msaaEnabledForCamera && (supportsDepthTarget || supportsTextureCopy); |
|
|
|
bool msaaDepthResolve = msaaEnabledForCamera && SystemInfo.supportsMultisampledTextures != 0; |
|
|
|
return supportsDepthCopy || msaaDepthResolve; |
|
|
|
} |
|
|
|
|
|
|
|
// Note: Scene view camera always perform depth prepass
|
|
|
|
cmd.Blit(GetSurface(RenderTargetHandles.Depth), BuiltinRenderTextureType.CameraTarget, GetMaterial(MaterialHandles.DepthCopy)); |
|
|
|
cmd.Blit(GetSurface(RenderTargetHandles.DepthTexture), BuiltinRenderTextureType.CameraTarget, GetMaterial(MaterialHandles.DepthCopy)); |
|
|
|
context.ExecuteCommandBuffer(cmd); |
|
|
|
CommandBufferPool.Release(cmd); |
|
|
|
} |
|
|
|
|
|
|
CommandBuffer cmd = CommandBufferPool.Get("Release Resources"); |
|
|
|
for (int i = 0; i < m_ShadowPassList.Count; ++i) |
|
|
|
m_ShadowPassList[i].Dispose(cmd); |
|
|
|
for (int i = 0; i < m_ActiveShadowQueue.Count; ++i) |
|
|
|
m_ActiveShadowQueue[i].Dispose(cmd); |
|
|
|
for (int i = 0; i < m_RenderPassList.Count; ++i) |
|
|
|
m_RenderPassList[i].Dispose(cmd); |
|
|
|
for (int i = 0; i < m_ActiveRenderPassQueue.Count; ++i) |
|
|
|
m_ActiveRenderPassQueue[i].Dispose(cmd); |
|
|
|
|
|
|
|
context.ExecuteCommandBuffer(cmd); |
|
|
|
CommandBufferPool.Release(cmd); |
|
|
|