public static void Render(ScriptableRenderContext context, IEnumerable <Camera> cameras, SimpleRenderPipeline.Mode mode) { foreach (var camera in cameras) { // Culling ScriptableCullingParameters cullingParams; if (!camera.TryGetCullingParameters(out cullingParams)) { continue; } CullingResults cull = context.Cull(ref cullingParams); context.SetupCameraProperties(camera); AttachmentDescriptor color = new AttachmentDescriptor(RenderTextureFormat.ARGB32); AttachmentDescriptor depth = new AttachmentDescriptor(RenderTextureFormat.Depth); bool needsFinalBlit = camera.cameraType == CameraType.SceneView; RenderTargetIdentifier tmpBuf = new RenderTargetIdentifier("TempSurface"); if (needsFinalBlit) { using (var cmd = new CommandBuffer()) { cmd.GetTemporaryRT(Shader.PropertyToID("TempSurface"), camera.pixelWidth, camera.pixelHeight, 24, FilterMode.Bilinear, RenderTextureFormat.ARGB32); context.ExecuteCommandBuffer(cmd); } color.ConfigureTarget(tmpBuf, false, true); } else { color.ConfigureTarget(BuiltinRenderTextureType.CameraTarget, false, true); } // No configure target for depth means depth will be memoryless color.ConfigureClear(Color.blue / 3 + Color.red / 2); depth.ConfigureClear(Color.black, 1.0f, 0); using (var attachmentsDisposable = new NativeArray <AttachmentDescriptor>(2, Allocator.Temp)) { var attachments = attachmentsDisposable; const int depthIndex = 0, colorIndex = 1; attachments[depthIndex] = depth; attachments[colorIndex] = color; using (context.BeginScopedRenderPass(camera.pixelWidth, camera.pixelHeight, 1, attachments, depthIndex)) { var fs = new FilteringSettings(RenderQueueRange.opaque); if (mode == SimpleRenderPipeline.Mode.DepthPrepass) { var depthPrePasssettings = new DrawingSettings(new ShaderTagId("DepthPrepass"), new SortingSettings(camera)); using (var depthOnlyDisposable = new NativeArray <int>(0, Allocator.Temp)) { var depthArray = depthOnlyDisposable; using (context.BeginScopedSubPass(depthArray)) { context.DrawRenderers(cull, ref depthPrePasssettings, ref fs); } } var mainPasssettings = new DrawingSettings(new ShaderTagId("AfterZPrepass"), new SortingSettings(camera)); using (var colorsDisposable = new NativeArray <int>(1, Allocator.Temp)) { var colors = colorsDisposable; colors[0] = colorIndex; using (context.BeginScopedSubPass(colors)) { context.DrawRenderers(cull, ref mainPasssettings, ref fs); } } } else if (mode == SimpleRenderPipeline.Mode.OnePassAlphaTest) { var mainPasssettings = new DrawingSettings(new ShaderTagId("OnePassAlphaClip"), new SortingSettings(camera)); using (var colorsDisposable = new NativeArray <int>(1, Allocator.Temp)) { var colors = colorsDisposable; colors[0] = colorIndex; using (context.BeginScopedSubPass(colors)) { context.DrawRenderers(cull, ref mainPasssettings, ref fs); } } } else if (mode == SimpleRenderPipeline.Mode.OnePassAlphaBlend) { var sortingSettings = new SortingSettings(camera); sortingSettings.criteria = SortingCriteria.BackToFront; var mainPasssettings = new DrawingSettings(new ShaderTagId("OnePassAlphaBlend"), sortingSettings); using (var colorsDisposable = new NativeArray <int>(1, Allocator.Temp)) { var colors = colorsDisposable; colors[0] = colorIndex; using (context.BeginScopedSubPass(colors)) { context.DrawRenderers(cull, ref mainPasssettings, ref fs); } } } } } if (needsFinalBlit) { using (var cmd = new CommandBuffer()) { cmd.Blit(tmpBuf, new RenderTargetIdentifier(BuiltinRenderTextureType.CameraTarget)); context.ExecuteCommandBuffer(cmd); } } context.Submit(); } }
void DrawDeferred(Camera camera, CullingResults cullingResults, ScriptableRenderContext context) { var albedo = new AttachmentDescriptor(RenderTextureFormat.ARGB32); var specRough = new AttachmentDescriptor(RenderTextureFormat.ARGB32); var normal = new AttachmentDescriptor(RenderTextureFormat.ARGB2101010); var emission = new AttachmentDescriptor(RenderTextureFormat.ARGBHalf); var depth = new AttachmentDescriptor(RenderTextureFormat.Depth); var depthSRV = new AttachmentDescriptor(RenderTextureFormat.ARGBHalf); // At the beginning of the render pass, clear the emission buffer to all black, and the depth buffer to 1.0f emission.ConfigureClear(new Color(0.0f, 0.0f, 0.0f, 0.0f), 1.0f, 0); depth.ConfigureClear(new Color(), 1.0f, 0); //depthSRV.ConfigureClear(new Color(), 1.0f, 0); albedo.ConfigureTarget(BuiltinRenderTextureType.CameraTarget, false, true); var attachments = new NativeArray <AttachmentDescriptor>(5, Allocator.Temp); const int depthIndex = 0, albedoIndex = 1, specRoughIndex = 2, normalIndex = 3, emissionIndex = 4, depthSRVIndex = 5; attachments[depthIndex] = depth; attachments[albedoIndex] = albedo; attachments[specRoughIndex] = specRough; attachments[normalIndex] = normal; attachments[emissionIndex] = emission; //attachments[depthSRVIndex] = depthSRV; using (context.BeginScopedRenderPass(camera.pixelWidth, camera.pixelHeight, 1, attachments, depthIndex)) { attachments.Dispose(); // Start the first subpass, GBuffer creation: render to albedo, specRough, normal and emission, no need to read any input attachments var gbufferColors = new NativeArray <int>(4, Allocator.Temp); gbufferColors[0] = albedoIndex; gbufferColors[1] = specRoughIndex; gbufferColors[2] = normalIndex; gbufferColors[3] = emissionIndex; //gbufferColors[4] = depthSRVIndex; using (context.BeginScopedSubPass(gbufferColors)) { gbufferColors.Dispose(); // Render the deferred G-Buffer RenderGBuffer(camera, cullingResults, context); } // Second subpass, lighting: Render to the emission buffer, read from albedo, specRough, normal and depth. // The last parameter indicates whether the depth buffer can be bound as read-only. // Note that some renderers (notably iOS Metal) won't allow reading from the depth buffer while it's bound as Z-buffer, // so those renderers should write the Z into an additional FP32 render target manually in the pixel shader and read from it instead var lightingColors = new NativeArray <int>(1, Allocator.Temp); lightingColors[0] = albedoIndex; var lightingInputs = new NativeArray <int>(1, Allocator.Temp); lightingInputs[0] = albedoIndex; // lightingInputs[1] = specRoughIndex; // lightingInputs[2] = normalIndex; // //lightingInputs[3] = depthSRVIndex; using (context.BeginScopedSubPass(lightingColors, lightingInputs, true)) { lightingColors.Dispose(); lightingInputs.Dispose(); // PushGlobalShadowParams(context); RenderDeferredLighting(camera, cullingResults, context); } // Third subpass, tonemapping: Render to albedo (which is bound to the camera target), read from emission. var tonemappingColors = new NativeArray <int>(1, Allocator.Temp); tonemappingColors[0] = albedoIndex; var tonemappingInputs = new NativeArray <int>(1, Allocator.Temp); tonemappingInputs[0] = albedoIndex; using (context.BeginScopedSubPass(tonemappingColors, tonemappingInputs, true)) { tonemappingColors.Dispose(); tonemappingInputs.Dispose(); // present frame buffer. RenderDeferredFinalPass(context); } } }
protected override void Render(ScriptableRenderContext context, Camera[] cameras) { BeginFrameRendering(cameras); foreach (Camera camera in cameras) { BeginCameraRendering(camera); //Culling ScriptableCullingParameters cullingParams; if (!camera.TryGetCullingParameters(out cullingParams)) { continue; } CullingResults cull = context.Cull(ref cullingParams); //Camera setup some builtin variables e.g. camera projection matrices etc context.SetupCameraProperties(camera); //Get the setting from camera component bool drawSkyBox = camera.clearFlags == CameraClearFlags.Skybox? true : false; bool clearDepth = camera.clearFlags == CameraClearFlags.Nothing? false : true; bool clearColor = camera.clearFlags == CameraClearFlags.Color? true : false; //Color Texture Descriptor RenderTextureDescriptor colorRTDesc = new RenderTextureDescriptor(camera.pixelWidth, camera.pixelHeight); colorRTDesc.colorFormat = m_ColorFormat; colorRTDesc.depthBufferBits = depthBufferBits; colorRTDesc.sRGB = (QualitySettings.activeColorSpace == ColorSpace.Linear); colorRTDesc.msaaSamples = 1; colorRTDesc.enableRandomWrite = false; //Get Temp Texture for Color Texture CommandBuffer cmdTempId = new CommandBuffer(); cmdTempId.name = "(" + camera.name + ")" + "Setup TempRT"; cmdTempId.GetTemporaryRT(m_ColorRTid, colorRTDesc, FilterMode.Bilinear); cmdTempId.SetRenderTarget(m_ColorRT); //so that result won't flip context.ExecuteCommandBuffer(cmdTempId); cmdTempId.Release(); //Setup DrawSettings and FilterSettings var sortingSettings = new SortingSettings(camera); DrawingSettings drawSettings1 = new DrawingSettings(m_PassName1, sortingSettings); DrawingSettings drawSettings2 = new DrawingSettings(m_PassName2, sortingSettings); FilteringSettings filterSettings = new FilteringSettings(RenderQueueRange.all); //Native Arrays for Attachaments NativeArray <AttachmentDescriptor> renderPassAttachments = new NativeArray <AttachmentDescriptor>(4, Allocator.Temp); renderPassAttachments[0] = m_Albedo; renderPassAttachments[1] = m_Emission; renderPassAttachments[2] = m_Output; renderPassAttachments[3] = m_Depth; NativeArray <int> renderPassColorAttachments = new NativeArray <int>(2, Allocator.Temp); renderPassColorAttachments[0] = 0; renderPassColorAttachments[1] = 1; NativeArray <int> renderPassOutputAttachments = new NativeArray <int>(1, Allocator.Temp); renderPassOutputAttachments[0] = 2; //Clear Attachements m_Output.ConfigureTarget(m_ColorRT, false, true); m_Output.ConfigureClear(new Color(0.0f, 0.0f, 0.0f, 0.0f), 1, 0); m_Albedo.ConfigureClear(camera.backgroundColor, 1, 0); m_Emission.ConfigureClear(new Color(0.0f, 0.0f, 0.0f, 0.0f), 1, 0); m_Depth.ConfigureClear(new Color(), 1, 0); //More clean to use ScopedRenderPass instead of BeginRenderPass+EndRenderPass using (context.BeginScopedRenderPass(camera.pixelWidth, camera.pixelHeight, 1, renderPassAttachments, 3)) { //Output to Albedo & Emission using (context.BeginScopedSubPass(renderPassColorAttachments, false)) { //Opaque objects sortingSettings.criteria = SortingCriteria.CommonOpaque; drawSettings1.sortingSettings = sortingSettings; filterSettings.renderQueueRange = RenderQueueRange.opaque; context.DrawRenderers(cull, ref drawSettings1, ref filterSettings); //Transparent objects sortingSettings.criteria = SortingCriteria.CommonTransparent; drawSettings1.sortingSettings = sortingSettings; filterSettings.renderQueueRange = RenderQueueRange.transparent; context.DrawRenderers(cull, ref drawSettings1, ref filterSettings); } //Read from Albedo & Emission, then output to Output using (context.BeginScopedSubPass(renderPassOutputAttachments, renderPassColorAttachments)) { //Skybox if (drawSkyBox) { context.DrawSkybox(camera); } //Opaque objects sortingSettings.criteria = SortingCriteria.CommonOpaque; drawSettings2.sortingSettings = sortingSettings; filterSettings.renderQueueRange = RenderQueueRange.opaque; context.DrawRenderers(cull, ref drawSettings2, ref filterSettings); //Transparent objects sortingSettings.criteria = SortingCriteria.CommonTransparent; drawSettings2.sortingSettings = sortingSettings; filterSettings.renderQueueRange = RenderQueueRange.transparent; context.DrawRenderers(cull, ref drawSettings2, ref filterSettings); } } //Blit To Camera so that the CameraTarget has content and make sceneview works CommandBuffer cmd = new CommandBuffer(); cmd.name = "Cam:" + camera.name + " BlitToCamera"; cmd.Blit(m_ColorRT, BuiltinRenderTextureType.CameraTarget); context.ExecuteCommandBuffer(cmd); cmd.Release(); //CleanUp Texture CommandBuffer cmdclean = new CommandBuffer(); cmdclean.name = "(" + camera.name + ")" + "Clean Up"; cmdclean.ReleaseTemporaryRT(m_ColorRTid); context.ExecuteCommandBuffer(cmdclean); cmdclean.Release(); //Submit the CommandBuffers context.Submit(); //CleanUp NativeArrays renderPassAttachments.Dispose(); renderPassColorAttachments.Dispose(); renderPassOutputAttachments.Dispose(); } }
void DeferredLightPass(ScriptableRenderContext context, CullingResults cullingResults, Camera camera) { var cmd = CommandBufferPool.Get("SetupGlobalLights"); SortingSettings opaqueSortingSettings = new SortingSettings(camera); opaqueSortingSettings.criteria = SortingCriteria.CommonOpaque; FilteringSettings opaqueFilteringSettings = new FilteringSettings(RenderQueueRange.opaque); if (cullingResults.visibleLights.Length > 0) { VisibleLight lightData = cullingResults.visibleLights[0]; Vector4 dir = -lightData.localToWorldMatrix.GetColumn(2); Vector4 lightPos = new Vector4(dir.x, dir.y, dir.z, 0.0f); cmd.SetGlobalVector("_MainLightPosition", lightPos); cmd.SetGlobalVector("_MainLightColor", lightData.finalColor); } if (cullingResults.visibleReflectionProbes.Length > 0) { cmd.SetGlobalTexture("unity_SpecCube0", cullingResults.visibleReflectionProbes[0].texture); } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); bool useRenderPass = false; if (!useRenderPass) { bool enableDynamicBatching = false; bool enableInstancing = false; PerObjectData perObjectData = PerObjectData.None; // DrawGBuffers DrawingSettings gBufferDrawingSettings = new DrawingSettings(ShaderPassTag.GBuffer, opaqueSortingSettings); gBufferDrawingSettings.enableDynamicBatching = enableDynamicBatching; gBufferDrawingSettings.enableInstancing = enableInstancing; gBufferDrawingSettings.perObjectData = perObjectData; cmd = CommandBufferPool.Get("Gbuffer"); cmd.SetRenderTarget(m_GBufferRTIDs, m_DepthBufferRTID); cmd.ClearRenderTarget(true, true, camera.backgroundColor); //CoreUtils.SetRenderTarget(cmd, m_GBufferRTIDs, m_DepthBufferRTID, ClearFlag.All); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); context.DrawRenderers(cullingResults, ref gBufferDrawingSettings, ref opaqueFilteringSettings); cmd = CommandBufferPool.Get("DeferredLightingPass"); cmd.SetGlobalVector("unity_SpecCube0_HDR", new Vector4(1, 1, 0, 0)); // Bind buffers cmd.SetGlobalTexture("_GBufferAlbedo", m_GBufferRTIDs[0]); cmd.SetGlobalTexture("_GBufferNormal", m_GBufferRTIDs[1]); cmd.SetGlobalTexture("_GBufferMetallicOcclusionSmoothness", m_GBufferRTIDs[2]); cmd.SetGlobalTexture("_GBufferDepth", m_DepthBufferRTID); cmd.SetGlobalInt("_TileCountX", (camera.scaledPixelWidth + 64 - 1) / 64); cmd.SetGlobalInt("_TileCountY", (camera.scaledPixelHeight + 64 - 1) / 64); cmd.SetGlobalVector("unity_LightData", new Vector4(6, 0, 1, 0)); //Set RenderTarget cmd.SetRenderTarget(m_ColorBuffer, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store); cmd.ClearRenderTarget(true, true, Color.black, 0.0f); //cmd.SetViewProjectionMatrices(Matrix4x4.identity, Matrix4x4.identity); //cmd.SetViewport(camera.pixelRect); cmd.DrawMesh(CustomRenderPipeline.fullscreenMesh, Matrix4x4.identity, m_DeferredLightingMat, 0, 0); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); //cmd.SetViewport(new Rect(0,0,camera.scaledPixelWidth, camera.scaledPixelHeight)); } else { // var colorBuffer = new AttachmentDescriptor(RenderTextureFormat.ARGBHalf); // 64 bit // var depthBuffer = new AttachmentDescriptor(RenderTextureFormat.Depth); // 32 bit // var albedoGBuffer = new AttachmentDescriptor(RenderTextureFormat.ARGB32); // 32 bit // var normalGBuffer = new AttachmentDescriptor(RenderTextureFormat.ARGBHalf); // 64 bit // var pbrGBuffer = new AttachmentDescriptor(RenderTextureFormat.ARGB32); // 32 // var depthGBuffer = new AttachmentDescriptor(RenderTextureFormat.RFloat); // 32 bit // // colorBuffer.ConfigureClear(new Color(0.0f, 0.0f, 0.0f, 0.0f), 1.0f, 0); // depthBuffer.ConfigureClear(new Color(), 1.0f, 0); // colorBuffer.ConfigureTarget(BuiltinRenderTextureType.CameraTarget, true, true); // // var attachments = new NativeArray<AttachmentDescriptor>(6, Allocator.Temp); // const int colorBufferId = 0, depthBufferId = 1, albedoGBufferId = 2, normalGBufferId = 3, pbrGbufferId = 4, depthGBufferId = 5; // //const int colorBufferId = 0, albedoGBufferId = 2, normalGBufferId = 3, pbrGbufferId = 4, depthGBufferId = 5; // attachments[colorBufferId] = colorBuffer; // attachments[depthBufferId] = depthBuffer; // attachments[albedoGBufferId] = albedoGBuffer; // attachments[normalGBufferId] = normalGBuffer; // attachments[pbrGbufferId] = pbrGBuffer; // attachments[depthGBufferId] = depthGBuffer; // // using (context.BeginScopedRenderPass(camera.scaledPixelWidth, camera.scaledPixelHeight, 1, attachments, depthBufferId)) // { // attachments.Dispose(); // var gBuffers = new NativeArray<int>(4, Allocator.Temp); // // //gBuffers[0] = colorBufferId; // gBuffers[0] = albedoGBufferId; // gBuffers[1] = normalGBufferId; // gBuffers[2] = pbrGbufferId; // gBuffers[3] = depthGBufferId; // using (context.BeginScopedSubPass(gBuffers)) // { // RenderGbufferSubPass(context, cullingResults, camera); // } // var lightingColors = new NativeArray<int>(1, Allocator.Temp); // lightingColors[0] = colorBufferId; // var lightingInputs = new NativeArray<int>(4, Allocator.Temp); // lightingInputs[0] = albedoGBufferId; // //lightingInputs[1] = albedoGBufferId; // lightingInputs[1] = normalGBufferId; // lightingInputs[2] = pbrGbufferId; // lightingInputs[3] = depthGBufferId; // using (context.BeginScopedSubPass(lightingColors, lightingInputs, true)) // { // lightingColors.Dispose(); // lightingInputs.Dispose(); // // // RenderLighting(camera, cullResults, context); // RenderDeferredLightingSubPass(context, cullingResults, camera); // } // // // } var albedo = new AttachmentDescriptor(RenderTextureFormat.ARGB32); var specRough = new AttachmentDescriptor(RenderTextureFormat.ARGB32); var normal = new AttachmentDescriptor(RenderTextureFormat.ARGB2101010); var emission = new AttachmentDescriptor(RenderTextureFormat.ARGBHalf); var depth = new AttachmentDescriptor(RenderTextureFormat.Depth); emission.ConfigureClear(new Color(0.0f, 0.0f, 0.0f, 0.0f), 1.0f, 0); depth.ConfigureClear(new Color(), 1.0f, 0); albedo.ConfigureTarget(BuiltinRenderTextureType.CameraTarget, false, true); var attachments = new NativeArray <AttachmentDescriptor>(5, Allocator.Temp); const int depthIndex = 0, albedoIndex = 1, specRoughIndex = 2, normalIndex = 3, emissionIndex = 4; attachments[depthIndex] = depth; attachments[albedoIndex] = albedo; attachments[specRoughIndex] = specRough; attachments[normalIndex] = normal; attachments[emissionIndex] = emission; using (context.BeginScopedRenderPass(camera.pixelWidth, camera.pixelHeight, 1, attachments, depthIndex)) { attachments.Dispose(); // Start the first subpass, GBuffer creation: render to albedo, specRough, normal and emission, no need to read any input attachments var gbufferColors = new NativeArray <int>(4, Allocator.Temp); gbufferColors[0] = albedoIndex; gbufferColors[1] = specRoughIndex; gbufferColors[2] = normalIndex; gbufferColors[3] = emissionIndex; using (context.BeginScopedSubPass(gbufferColors)) { gbufferColors.Dispose(); // Render the deferred G-Buffer RenderGbufferSubPass(context, cullingResults, camera); } // Second subpass, lighting: Render to the emission buffer, read from albedo, specRough, normal and depth. // The last parameter indicates whether the depth buffer can be bound as read-only. // Note that some renderers (notably iOS Metal) won't allow reading from the depth buffer while it's bound as Z-buffer, // so those renderers should write the Z into an additional FP32 render target manually in the pixel shader and read from it instead var lightingColors = new NativeArray <int>(1, Allocator.Temp); lightingColors[0] = emissionIndex; var lightingInputs = new NativeArray <int>(4, Allocator.Temp); lightingInputs[0] = albedoIndex; lightingInputs[1] = specRoughIndex; lightingInputs[2] = normalIndex; lightingInputs[3] = depthIndex; using (context.BeginScopedSubPass(lightingColors, lightingInputs, true)) { lightingColors.Dispose(); lightingInputs.Dispose(); // PushGlobalShadowParams(context); RenderDeferredLightingSubPass(context, cullingResults, camera); } // Third subpass, tonemapping: Render to albedo (which is bound to the camera target), read from emission. // var tonemappingColors = new NativeArray<int>(1, Allocator.Temp); // tonemappingColors[0] = albedoIndex; // var tonemappingInputs = new NativeArray<int>(1, Allocator.Temp); // tonemappingInputs[0] = emissionIndex; // using (context.BeginScopedSubPass(tonemappingColors, tonemappingInputs, true)) // { // tonemappingColors.Dispose(); // tonemappingInputs.Dispose(); // // // present frame buffer. // // FinalPass(context); // } } } }