// -------------------------------------------------------------------- void ReleaseOcclusionTextures() { m_textureHandlingBuffer.ReleaseTemporaryRT(m_directLightOcclusionMapId); m_textureHandlingBuffer.ReleaseTemporaryRT(m_directLightShadowMapId); m_textureHandlingBuffer.ReleaseTemporaryRT(m_directLightDummyTextureId); m_textureHandlingBuffer.ReleaseTemporaryRT(m_directLightDepthTextureId); L2DLRenderHelpers.ExecuteBuffer(m_context, m_textureHandlingBuffer); }
// -------------------------------------------------------------------- public void Render(ScriptableRenderContext context, Camera camera, L2DLDirectLights directLights) { if (!m_directLightData.Enabled) { return; } m_context = context; m_camera = camera; // Encapsulate in frame debugger L2DLRenderHelpers.BeginSample(m_context, m_directLightRenderingBuffer); { CoreUtils.SetRenderTarget(m_clearBuffer, L2DLPipelineData.s_cameraDirectLightResultTextureId, L2DLPipelineData.s_cameraDepthTextureId, ClearFlag.Color); L2DLRenderHelpers.ExecuteBuffer(m_context, m_clearBuffer); // Directional Lights L2DLRenderHelpers.BeginSample(m_context, m_directionalLightsBuffer); foreach (L2DLDirectionalLight directionalLight in directLights.m_directionalLights) { GetOcclusionTextures((int)directionalLight.ShadowMapSize); // Probably don't need to do this every time? RenderOcclusionMapForLight(directionalLight); RunDirectionalLightOcclusionMapTrace(directionalLight); RunDirectionalLightRendering(directionalLight); ReleaseOcclusionTextures(); } L2DLRenderHelpers.EndSample(m_context, m_directionalLightsBuffer); // Point Lights L2DLRenderHelpers.BeginSample(m_context, m_pointLightsBuffer); foreach (L2DLPointLight pointLight in directLights.m_pointLights) { GetOcclusionTextures((int)pointLight.ShadowMapSize); RenderOcclusionMapForLight(pointLight); RunPointLightOcclusionMapTrace(pointLight); RunPointLightRendering(pointLight); ReleaseOcclusionTextures(); } L2DLRenderHelpers.EndSample(m_context, m_pointLightsBuffer); // Spot Lights L2DLRenderHelpers.BeginSample(m_context, m_spotLightsBuffer); foreach (L2DLSpotLight spotLight in directLights.m_spotLights) { GetOcclusionTextures((int)spotLight.ShadowMapSize); RenderOcclusionMapForLight(spotLight); RunSpotLightOcclusionMapTrace(spotLight); RunSpotLightRendering(spotLight); ReleaseOcclusionTextures(); } L2DLRenderHelpers.EndSample(m_context, m_spotLightsBuffer); // Reset m_context.SetupCameraProperties(m_camera); } L2DLRenderHelpers.EndSample(m_context, m_directLightRenderingBuffer); }
public void CalculateShadowMap(ScriptableRenderContext _context, CommandBuffer _buffer, L2DLDirectionalLight _directionalLight, L2DLDirectLightData _data, RenderTargetIdentifier i_occlusionMap, RenderTargetIdentifier o_shadowMap) { // Here we run the code that calculates the shadow map using standard rendering... _buffer.SetGlobalTexture("_OcclusionMap", i_occlusionMap); _buffer.SetGlobalInt("_SamplesPerPixel", m_samplesPerPixel); _buffer.SetGlobalFloat("_WorldDistPerStep", _directionalLight.Height / m_samplesPerPixel); _buffer.Blit(i_occlusionMap, o_shadowMap, DirectionalShadowMapRenderMaterial); L2DLRenderHelpers.ExecuteBuffer(_context, _buffer); }
// -------------------------------------------------------------------- void RunDirectionalLightRendering(L2DLDirectionalLight directionalLight) { SetupCommonLightRenderingProperties(m_directionalLightRenderingBuffer, directionalLight); m_directionalLightRenderingBuffer.SetRenderTarget(new RenderTargetIdentifier[] { L2DLPipelineData.s_cameraDirectLightResultTextureId, L2DLPipelineData.s_cameraEmissionTextureId }, L2DLPipelineData.s_cameraFakeDepthTextureId); m_directionalLightRenderingBuffer.Blit(null, BuiltinRenderTextureType.CurrentActive, DirectionalLightPassMaterial); L2DLRenderHelpers.ExecuteBuffer(m_context, m_directionalLightRenderingBuffer); }
// -------------------------------------------------------------------- void ReleaseTextures() { m_textureHandlerBuffer.ReleaseTemporaryRT(L2DLPipelineData.s_cameraColorTextureId); m_textureHandlerBuffer.ReleaseTemporaryRT(L2DLPipelineData.s_cameraEmissionTextureId); m_textureHandlerBuffer.ReleaseTemporaryRT(L2DLPipelineData.s_cameraOcclusionTextureId); m_textureHandlerBuffer.ReleaseTemporaryRT(L2DLPipelineData.s_cameraAdditionalDataTextureId); m_textureHandlerBuffer.ReleaseTemporaryRT(L2DLPipelineData.s_cameraDepthTextureId); m_textureHandlerBuffer.ReleaseTemporaryRT(L2DLPipelineData.s_cameraFakeDepthTextureId); m_textureHandlerBuffer.ReleaseTemporaryRT(L2DLPipelineData.s_cameraDirectLightResultTextureId); m_textureHandlerBuffer.ReleaseTemporaryRT(L2DLPipelineData.s_cameraIndirectLightResultTextureId); L2DLRenderHelpers.ExecuteBuffer(m_context, m_textureHandlerBuffer); }
// -------------------------------------------------------------------- void RunPointLightRendering(L2DLPointLight pointLight) { SetupCommonLightRenderingProperties(m_pointLightRenderingBuffer, pointLight); m_pointLightRenderingBuffer.SetGlobalFloat("_lightAttenuation", 1f / Mathf.Max(pointLight.Range * pointLight.Range, 0.00001f)); m_pointLightRenderingBuffer.SetGlobalVector("_lightPosition", pointLight.transform.position); m_pointLightRenderingBuffer.SetGlobalFloat("_maxIntensityOutput", pointLight.MaxIntensityOutput); m_pointLightRenderingBuffer.SetRenderTarget(new RenderTargetIdentifier[] { L2DLPipelineData.s_cameraDirectLightResultTextureId, L2DLPipelineData.s_cameraEmissionTextureId }, L2DLPipelineData.s_cameraFakeDepthTextureId); m_pointLightRenderingBuffer.Blit(null, BuiltinRenderTextureType.CurrentActive, PointLightPassMaterial); L2DLRenderHelpers.ExecuteBuffer(m_context, m_pointLightRenderingBuffer); }
// Textures // -------------------------------------------------------------------- void GetOcclusionTextures(int _size) { RenderTextureDescriptor mapDescriptor = new RenderTextureDescriptor(_size, _size, RenderTextureFormat.ARGBHalf) { useMipMap = m_directLightData.ShadowMapCalculator.OcclusionMapGenerateMips, autoGenerateMips = m_directLightData.ShadowMapCalculator.OcclusionMapGenerateMips, enableRandomWrite = m_directLightData.ShadowMapCalculator.OcclusionMapRandomAccess, }; m_textureHandlingBuffer.GetTemporaryRT(m_directLightOcclusionMapId, mapDescriptor, m_directLightData.ShadowMapCalculator.OcclusionMapFilterMode); m_textureHandlingBuffer.GetTemporaryRT(m_directLightShadowMapId, mapDescriptor, m_directLightData.ShadowMapCalculator.OcclusionMapFilterMode); m_textureHandlingBuffer.GetTemporaryRT(m_directLightDummyTextureId, _size, _size, 0, FilterMode.Bilinear, RenderTextureFormat.ARGBHalf); m_textureHandlingBuffer.GetTemporaryRT(m_directLightDepthTextureId, _size, _size, 0, FilterMode.Bilinear, RenderTextureFormat.ARGBHalf); L2DLRenderHelpers.ExecuteBuffer(m_context, m_textureHandlingBuffer); }
// -------------------------------------------------------------------- public void CalculateShadowMap(ScriptableRenderContext _context, CommandBuffer _buffer, L2DLSpotLight _spotLight, L2DLDirectLightData _data, RenderTargetIdentifier i_occlusionMap, RenderTargetIdentifier o_shadowMap) { if (!L2DLRenderHelpers.SupportsComputeShaders()) { return; } ReloadComputeShaders(); int occlusionTraceComputeKernel = m_spotLightOcclusionTraceCompute.FindKernel("SpotLightOcclusionTrace"); SetupCommonComputeShaderProperties(_buffer, m_spotLightOcclusionTraceCompute, occlusionTraceComputeKernel, _spotLight, _data); _buffer.SetComputeFloatParam(m_spotLightOcclusionTraceCompute, "_WorldDistPerStep", _spotLight.Range / (int)_spotLight.ShadowMapSize); _buffer.DispatchCompute(m_spotLightOcclusionTraceCompute, occlusionTraceComputeKernel, (int)_spotLight.ShadowMapSize / 64, 1, 1); L2DLRenderHelpers.ExecuteBuffer(_context, _buffer); }
// -------------------------------------------------------------------- void RenderOcclusionMapForLight(IL2DLDirectLight directLight) { L2DLRenderHelpers.BeginSample(m_context, m_occlusionMapRenderingBuffer); { m_context.SetupCameraProperties(directLight.ShadowCamera); if (!directLight.ShadowCamera.TryGetCullingParameters(out m_cullingParameters)) { return; } m_cullingResults = m_context.Cull(ref m_cullingParameters); CoreUtils.SetRenderTarget(m_clearBuffer, new RenderTargetIdentifier[] { m_directLightDummyTextureId, m_directLightOcclusionMapId }, m_directLightDepthTextureId, ClearFlag.All); L2DLRenderHelpers.ExecuteBuffer(m_context, m_clearBuffer); L2DLRenderHelpers.DrawAllRenderers(m_context, m_cullingResults); } L2DLRenderHelpers.EndSample(m_context, m_occlusionMapRenderingBuffer); }
// -------------------------------------------------------------------- void RenderStep_PresentFinalImage() { // Push the RT we've written on to the camera target switch (TextureToView) { case L2DLBufferTextures.None: m_presentFinalImageBuffer.SetGlobalTexture("_Color", L2DLPipelineData.s_cameraColorTextureId); m_presentFinalImageBuffer.SetGlobalTexture("_DirectLight", L2DLPipelineData.s_cameraDirectLightResultTextureId); m_presentFinalImageBuffer.SetGlobalTexture("_IndirectLight", L2DLPipelineData.s_cameraIndirectLightResultTextureId); List <LPVIterationData> iterationData = m_indirectLightData.IndirectLightCalculator.LPVIterationData; m_presentFinalImageBuffer.SetGlobalInt("_IndirectLightMip", iterationData[iterationData.Count - 1].MipLevel); m_presentFinalImageBuffer.Blit(null, BuiltinRenderTextureType.CameraTarget, L2DLPipelineData.CombineMaterial); break; case L2DLBufferTextures.Colour: m_presentFinalImageBuffer.SetGlobalTexture("_MainTex", L2DLPipelineData.s_cameraColorTextureId); m_presentFinalImageBuffer.Blit(L2DLPipelineData.s_cameraColorTextureId, BuiltinRenderTextureType.CameraTarget, L2DLPipelineData.BlitMaterial); break; case L2DLBufferTextures.Emission: m_presentFinalImageBuffer.SetGlobalTexture("_MainTex", L2DLPipelineData.s_cameraEmissionTextureId); m_presentFinalImageBuffer.Blit(L2DLPipelineData.s_cameraEmissionTextureId, BuiltinRenderTextureType.CameraTarget, L2DLPipelineData.BlitMaterial); break; case L2DLBufferTextures.Occlusion: m_presentFinalImageBuffer.SetGlobalTexture("_MainTex", L2DLPipelineData.s_cameraOcclusionTextureId); m_presentFinalImageBuffer.Blit(L2DLPipelineData.s_cameraOcclusionTextureId, BuiltinRenderTextureType.CameraTarget, L2DLPipelineData.BlitMaterial); break; case L2DLBufferTextures.AdditionalData: m_presentFinalImageBuffer.SetGlobalTexture("_MainTex", L2DLPipelineData.s_cameraAdditionalDataTextureId); m_presentFinalImageBuffer.Blit(L2DLPipelineData.s_cameraAdditionalDataTextureId, BuiltinRenderTextureType.CameraTarget, L2DLPipelineData.BlitMaterial); break; case L2DLBufferTextures.Depth: m_presentFinalImageBuffer.SetGlobalTexture("_MainTex", L2DLPipelineData.s_cameraDepthTextureId); m_presentFinalImageBuffer.Blit(L2DLPipelineData.s_cameraDepthTextureId, BuiltinRenderTextureType.CameraTarget, L2DLPipelineData.BlitMaterial); break; } L2DLRenderHelpers.ExecuteBuffer(m_context, m_presentFinalImageBuffer); }
// -------------------------------------------------------------------- public void Render(ScriptableRenderContext context, Camera camera) { if (!m_indirectLightData.Enabled) { return; } m_context = context; m_camera = camera; // Encapsulate in frame debugger L2DLRenderHelpers.BeginSample(m_context, m_indirectLightRenderingBuffer); { m_indirectLightData.IndirectLightCalculator?.CalculateIndirectLight( m_context, m_indirectLightRenderingBuffer, m_camera, L2DLPipelineData.s_cameraEmissionTextureId, L2DLPipelineData.s_cameraOcclusionTextureId, L2DLPipelineData.s_cameraIndirectLightResultTextureId); } L2DLRenderHelpers.EndSample(m_context, m_indirectLightRenderingBuffer); }
// Textures need to be gotten at the start of the cameras rendering and held on to until the end so that all steps can access them // -------------------------------------------------------------------- void GetTextures() { RenderTextureDescriptor bufferTextureDescriptor = new RenderTextureDescriptor(m_camera.pixelWidth, m_camera.pixelHeight, RenderTextureFormat.ARGBHalf, 0) { enableRandomWrite = true, useMipMap = true, autoGenerateMips = false, }; RenderTextureDescriptor bufferDepthTextureDescriptor = new RenderTextureDescriptor(m_camera.pixelWidth, m_camera.pixelHeight, RenderTextureFormat.Depth, 16); m_textureHandlerBuffer.GetTemporaryRT(L2DLPipelineData.s_cameraColorTextureId, bufferTextureDescriptor, FilterMode.Point); m_textureHandlerBuffer.GetTemporaryRT(L2DLPipelineData.s_cameraEmissionTextureId, bufferTextureDescriptor, FilterMode.Point); m_textureHandlerBuffer.GetTemporaryRT(L2DLPipelineData.s_cameraOcclusionTextureId, bufferTextureDescriptor, FilterMode.Point); m_textureHandlerBuffer.GetTemporaryRT(L2DLPipelineData.s_cameraAdditionalDataTextureId, bufferTextureDescriptor, FilterMode.Point); m_textureHandlerBuffer.GetTemporaryRT(L2DLPipelineData.s_cameraDirectLightResultTextureId, bufferTextureDescriptor, FilterMode.Bilinear); m_textureHandlerBuffer.GetTemporaryRT(L2DLPipelineData.s_cameraIndirectLightResultTextureId, bufferTextureDescriptor, FilterMode.Bilinear); m_textureHandlerBuffer.GetTemporaryRT(L2DLPipelineData.s_cameraDepthTextureId, bufferDepthTextureDescriptor, FilterMode.Point); m_textureHandlerBuffer.GetTemporaryRT(L2DLPipelineData.s_cameraFakeDepthTextureId, bufferDepthTextureDescriptor, FilterMode.Point); L2DLRenderHelpers.ExecuteBuffer(m_context, m_textureHandlerBuffer); }
// -------------------------------------------------------------------- void RunSpotLightRendering(L2DLSpotLight spotLight) { SetupCommonLightRenderingProperties(m_spotLightRenderingBuffer, spotLight); m_spotLightRenderingBuffer.SetGlobalFloat("_lightAttenuation", 1f / Mathf.Max(spotLight.Range * spotLight.Range, 0.00001f)); m_spotLightRenderingBuffer.SetGlobalVector("_lightPosition", spotLight.transform.position + spotLight.transform.up * spotLight.Range / 2f); m_spotLightRenderingBuffer.SetGlobalVector("_lightDirection", -spotLight.transform.up); float outerRad = Mathf.Deg2Rad * 0.5f * spotLight.Angle; float outerCos = Mathf.Cos(outerRad); float outerTan = Mathf.Tan(outerRad); float innerCos = Mathf.Cos(Mathf.Atan((46f / 64f) * outerTan)); float angleRange = Mathf.Max(innerCos - outerCos, 0.00001f); float spotFade = 1f / angleRange; m_spotLightRenderingBuffer.SetGlobalVector("_lightFade", new Vector2(spotFade, -outerCos * spotFade)); m_spotLightRenderingBuffer.SetGlobalFloat("_maxIntensityOutput", spotLight.MaxIntensityOutput); m_spotLightRenderingBuffer.SetGlobalFloat("_startingRange", spotLight.StartingRange); m_spotLightRenderingBuffer.SetRenderTarget(new RenderTargetIdentifier[] { L2DLPipelineData.s_cameraDirectLightResultTextureId, L2DLPipelineData.s_cameraEmissionTextureId }, L2DLPipelineData.s_cameraFakeDepthTextureId); m_spotLightRenderingBuffer.Blit(null, BuiltinRenderTextureType.CurrentActive, SpotLightPassMaterial); L2DLRenderHelpers.ExecuteBuffer(m_context, m_spotLightRenderingBuffer); }
// -------------------------------------------------------------------- public void CalculateIndirectLight( ScriptableRenderContext _context, CommandBuffer _buffer, Camera _camera, RenderTargetIdentifier i_emissiveTexture, RenderTargetIdentifier i_occlusionTexture, RenderTargetIdentifier o_indirectLightTexture ) { if (!L2DLRenderHelpers.SupportsComputeShaders()) { return; } ReloadComputeShaders(); // We'll assume that the emissive texture is all we care about, any reflected direct light can be added in beforehand as part of the general IndirectLight renderer if (m_emissionPolyphaseMipmapComputeShader == null) { m_emissionPolyphaseMipmapComputeShader = (ComputeShader)Resources.Load("Compute Shaders/Indirect Light/Polyphase Mipmap/GenerateEmissionPolyphaseMipmapsCompute"); } if (m_occlusionPolyphaseMipmapComputeShader == null) { m_occlusionPolyphaseMipmapComputeShader = (ComputeShader)Resources.Load("Compute Shaders/Indirect Light/Polyphase Mipmap/GenerateOcclusionPolyphaseMipmapsCompute"); } GeneratePolyphaseTextureMipmaps(_context, m_emissionPolyphaseMipmapComputeShader, i_emissiveTexture, new Vector2(_camera.pixelWidth, _camera.pixelHeight), 4); //TODO: Firgure out max mips from LPV data GeneratePolyphaseTextureMipmaps(_context, m_occlusionPolyphaseMipmapComputeShader, i_occlusionTexture, new Vector2(_camera.pixelWidth, _camera.pixelHeight), 4); // So we can grab some temporary textures that are a power of two above the camera size which generate mips automatically // We'll then render the emissive and occlusion into them // We can then use the mipmapped textures // LPV iterations into the direct light texture ready for final presenting GenerateIndirectLight(_context, i_emissiveTexture, i_occlusionTexture, o_indirectLightTexture, _camera, m_lpvIterationsData, Color.black); }
// -------------------------------------------------------------------- private void GeneratePolyphaseTextureMipmaps( ScriptableRenderContext _context, ComputeShader _shader, RenderTargetIdentifier _textureID, Vector2 _textureSize, int maxMipLevelGenerated = -1 ) { //Polyphase box filter for non-power of two texture mip-mapping int[] previousSize; int[] currentSize; //We need to check if width or height has been rounded bool[] rounded = new bool[2]; //The initial size needs to be recalculated when restarting for each layer so it has to happen within the loop previousSize = new int[] { (int)_textureSize.x, (int)_textureSize.y }; //Calculate the max possible mip levels this texture can have so we know how may iterations to do float mipLevels = (int)Mathf.Floor(Mathf.Log(Mathf.Max(_textureSize.x, _textureSize.y), 2)); if (maxMipLevelGenerated != -1) { mipLevels = Mathf.Min(mipLevels, maxMipLevelGenerated); } //First mip has a special case for occlusion mipmapping m_polyphaseMipmapBuffer.SetComputeFloatParam(_shader, "isFirstMip", 1f); for (var lowerMipLevel = 0; lowerMipLevel < mipLevels; lowerMipLevel++) { //Get the current size of this mipmap currentSize = new int[] { previousSize[0] / 2, previousSize[1] / 2 }; //n for width and height rounded = new bool[] { previousSize[0] / 2f > currentSize[0], previousSize[1] / 2f > currentSize[1] }; //Must be floats for the division //Pick a kernel given the state of the rounded edges (0, 1, 2, 3) int kernelIndex; if (rounded[0] == false) { if (rounded[1] == false) { //Box - box kernelIndex = 0; } else { //Box - poly kernelIndex = 1; } } else { if (rounded[1] == false) { //Poly - box kernelIndex = 2; } else { //Poly - poly kernelIndex = 3; } } // Set shader properties //Bind the lower mip level to read from m_polyphaseMipmapBuffer.SetComputeTextureParam(_shader, kernelIndex, "LowerMipTex", _textureID, lowerMipLevel); //Bind the higher mip level to write to m_polyphaseMipmapBuffer.SetComputeTextureParam(_shader, kernelIndex, "HigherMipTex", _textureID, lowerMipLevel + 1); //Setup additional working variables m_polyphaseMipmapBuffer.SetComputeVectorParam(_shader, "LowerMipTexSize", new Vector2(previousSize[0], previousSize[1])); m_polyphaseMipmapBuffer.SetComputeVectorParam(_shader, "HigherMipTexSize", new Vector2(currentSize[0], currentSize[1])); m_polyphaseMipmapBuffer.SetComputeVectorParam(_shader, "WasTextureSizeRounded", new Vector2(rounded[0] ? 1f : 0f, rounded[1] ? 1f : 0f)); //Calculate these once so doesn't need to be repeated for each pixel m_polyphaseMipmapBuffer.SetComputeVectorParam(_shader, "HigherMipTexelUVSize", new Vector2(1f / currentSize[0], 1f / currentSize[1])); m_polyphaseMipmapBuffer.SetComputeVectorParam(_shader, "LowerMipTexelUVSize", new Vector2(1f / previousSize[0], 1f / previousSize[1])); m_polyphaseMipmapBuffer.DispatchCompute( _shader, kernelIndex, Mathf.CeilToInt(currentSize[0] / 8f), Mathf.CeilToInt(currentSize[1] / 8f), 1 ); //Set previous size for next mip previousSize = currentSize; if (lowerMipLevel == 0) { m_polyphaseMipmapBuffer.SetComputeFloatParam(_shader, "isFirstMip", 0f); } } L2DLRenderHelpers.ExecuteBuffer(_context, m_polyphaseMipmapBuffer); }
// -------------------------------------------------------------------- private void GenerateIndirectLight ( ScriptableRenderContext _context, RenderTargetIdentifier i_emissiveTexture, RenderTargetIdentifier i_occlusionTexture, RenderTargetIdentifier o_indirectLightTexture, Camera _camera, List <LPVIterationData> _lpvIterationsData, Color _ambientLightColour ) { // Get working textures RenderTextureDescriptor bufferTextureDescriptor = new RenderTextureDescriptor(_camera.pixelWidth, _camera.pixelHeight, RenderTextureFormat.ARGBHalf, 0) { useMipMap = true, autoGenerateMips = false, enableRandomWrite = true }; m_lpvIterationsBuffer.GetTemporaryRT(flipTextureId, bufferTextureDescriptor, FilterMode.Point); m_lpvIterationsBuffer.GetTemporaryRT(flopTextureId, bufferTextureDescriptor, FilterMode.Point); // Check shaders if (m_lpvIterationsComputeShader == null) { m_lpvIterationsComputeShader = (ComputeShader)Resources.Load("Compute Shaders/Indirect Light/LPV/LPVIterationCompute"); } m_lpvIterationsFlipKernel = m_lpvIterationsComputeShader.FindKernel("LPVIterationFlip"); m_lpvIterationsFlopKernel = m_lpvIterationsComputeShader.FindKernel("LPVIterationFlop"); m_lpvIterationsBuffer.SetComputeTextureParam(m_lpvIterationsComputeShader, m_lpvIterationsFlipKernel, "OcclusionInput", i_occlusionTexture); m_lpvIterationsBuffer.SetComputeTextureParam(m_lpvIterationsComputeShader, m_lpvIterationsFlopKernel, "OcclusionInput", i_occlusionTexture); m_lpvIterationsBuffer.SetComputeFloatParam(m_lpvIterationsComputeShader, "OcclusionMultiplier", 1f); // TODO if (m_moveLPVDataDownMipLevelsComputeShader == null) { m_moveLPVDataDownMipLevelsComputeShader = (ComputeShader)Resources.Load("Compute Shaders/Indirect Light/LPV/MoveLPVDataDownMipLevels"); } m_moveLPVDataDownMipLevelsKernel = m_moveLPVDataDownMipLevelsComputeShader.FindKernel("MoveLPVDataDownMipLevels"); // LPV Iterations float[] textureWidths = new float[_lpvIterationsData.Count]; float[] textureHeights = new float[_lpvIterationsData.Count]; int totalIterationsSoFar = 0; for (int i = 0; i < _lpvIterationsData.Count; i++) { float lightingOutputResolutionDivisor = Mathf.Pow(2, _lpvIterationsData[i].MipLevel); textureWidths[i] = _camera.pixelWidth / lightingOutputResolutionDivisor; textureHeights[i] = _camera.pixelHeight / lightingOutputResolutionDivisor; int threadGroupsX = Mathf.CeilToInt(_camera.pixelWidth / lightingOutputResolutionDivisor / 8f); int threadGroupsY = Mathf.CeilToInt(_camera.pixelHeight / lightingOutputResolutionDivisor / 8f); if (i == 0) { //Copy m_lpvIterationsBuffer.CopyTexture(i_emissiveTexture, 0, _lpvIterationsData[i].MipLevel, flipTextureId, 0, _lpvIterationsData[i].MipLevel); //We just want to inject the ambient light colour into the specified levels //if (_lpvIterationsData[i].InjectAmbientLight) //{ // m_lpvIterationsBuffer.SetComputeTextureParam(shaders.ambientLightInjectionComputeShader, shaders.ambientLightInjectionComputeKernel, "Texture", flipTextureId, _lpvIterationsData[i].MipLevel); // m_lpvIterationsBuffer.SetComputeVectorParam(shaders.ambientLightInjectionComputeShader, "AmbientLight", _ambientLightColour); // m_lpvIterationsBuffer.DispatchCompute(shaders.ambientLightInjectionComputeShader, shaders.ambientLightInjectionComputeKernel, threadGroupsX, threadGroupsY, 1); //} } else { //Instead of copying across I need to shift all of the data down some mip levels using a compute shader for: // - The lighting flip tex (from whichever one was last used)1 // - The lighting total tex m_lpvIterationsBuffer.SetComputeVectorParam(m_moveLPVDataDownMipLevelsComputeShader, "OutputCellSize", new Vector2(textureWidths[i] / textureWidths[i - 1], textureHeights[i] / textureHeights[i - 1])); m_lpvIterationsBuffer.SetComputeTextureParam(m_moveLPVDataDownMipLevelsComputeShader, m_moveLPVDataDownMipLevelsKernel, "CurrentTotalInput", o_indirectLightTexture, _lpvIterationsData[i - 1].MipLevel); m_lpvIterationsBuffer.SetComputeTextureParam(m_moveLPVDataDownMipLevelsComputeShader, m_moveLPVDataDownMipLevelsKernel, "EmissiveSourcesInput", i_emissiveTexture, _lpvIterationsData[i].MipLevel); m_lpvIterationsBuffer.SetComputeTextureParam(m_moveLPVDataDownMipLevelsComputeShader, m_moveLPVDataDownMipLevelsKernel, "Output1", (totalIterationsSoFar % 2) == 0 ? flipTextureId : flopTextureId, _lpvIterationsData[i].MipLevel); m_lpvIterationsBuffer.SetComputeTextureParam(m_moveLPVDataDownMipLevelsComputeShader, m_moveLPVDataDownMipLevelsKernel, "Output2", o_indirectLightTexture, _lpvIterationsData[i].MipLevel); m_lpvIterationsBuffer.DispatchCompute(m_moveLPVDataDownMipLevelsComputeShader, m_moveLPVDataDownMipLevelsKernel, threadGroupsX, threadGroupsY, 1); //if (_lpvIterationsData[i].InjectAmbientLight) //{ // m_lpvIterationsBuffer.SetComputeTextureParam(shaders.ambientLightInjectionComputeShader, shaders.ambientLightInjectionComputeKernel, "Texture", (totalIterationsSoFar % 2) == 0 ? flipTextureId : flopTextureId, _lpvIterationsData[i].MipLevel); // m_lpvIterationsBuffer.SetComputeVectorParam(shaders.ambientLightInjectionComputeShader, "AmbientLight", _ambientLightColour); // m_lpvIterationsBuffer.DispatchCompute(shaders.ambientLightInjectionComputeShader, shaders.ambientLightInjectionComputeKernel, threadGroupsX, threadGroupsY, 1); //} } //Clear only the FIRST TIME as it's the start of a new total counting if (_lpvIterationsData[i].MipLevel != 0) { m_lpvIterationsBuffer.SetRenderTarget(o_indirectLightTexture, _lpvIterationsData[i].MipLevel); m_lpvIterationsBuffer.ClearRenderTarget(true, true, Color.black); } m_lpvIterationsBuffer.SetComputeIntParam(m_lpvIterationsComputeShader, "WorkingMipLevel", _lpvIterationsData[i].MipLevel); m_lpvIterationsBuffer.SetComputeIntParam(m_lpvIterationsComputeShader, "StartTotalSavingIteration", _lpvIterationsData[i].TotalStartIteration); m_lpvIterationsBuffer.SetComputeFloatParam(m_lpvIterationsComputeShader, "TexelWorldWidth", _camera.orthographicSize / (_camera.pixelHeight / lightingOutputResolutionDivisor / 2f)); m_lpvIterationsBuffer.SetComputeTextureParam(m_lpvIterationsComputeShader, m_lpvIterationsFlipKernel, "LightTotal", o_indirectLightTexture, _lpvIterationsData[i].MipLevel); m_lpvIterationsBuffer.SetComputeTextureParam(m_lpvIterationsComputeShader, m_lpvIterationsFlopKernel, "LightTotal", o_indirectLightTexture, _lpvIterationsData[i].MipLevel); m_lpvIterationsBuffer.SetComputeTextureParam(m_lpvIterationsComputeShader, m_lpvIterationsFlipKernel, "LightFlip", flipTextureId, _lpvIterationsData[i].MipLevel); m_lpvIterationsBuffer.SetComputeTextureParam(m_lpvIterationsComputeShader, m_lpvIterationsFlipKernel, "LightFlop", flopTextureId, _lpvIterationsData[i].MipLevel); m_lpvIterationsBuffer.SetComputeTextureParam(m_lpvIterationsComputeShader, m_lpvIterationsFlopKernel, "LightFlip", flipTextureId, _lpvIterationsData[i].MipLevel); m_lpvIterationsBuffer.SetComputeTextureParam(m_lpvIterationsComputeShader, m_lpvIterationsFlopKernel, "LightFlop", flopTextureId, _lpvIterationsData[i].MipLevel); for (var j = 0; j < _lpvIterationsData[i].Iterations; j++) { m_lpvIterationsBuffer.SetComputeIntParam(m_lpvIterationsComputeShader, "Iteration", j); m_lpvIterationsBuffer.DispatchCompute(m_lpvIterationsComputeShader, (totalIterationsSoFar + j) % 2 == 0 ? m_lpvIterationsFlipKernel : m_lpvIterationsFlopKernel, threadGroupsX, threadGroupsY, 1); } totalIterationsSoFar += _lpvIterationsData[i].Iterations; } //Release textures m_lpvIterationsBuffer.ReleaseTemporaryRT(flipTextureId); m_lpvIterationsBuffer.ReleaseTemporaryRT(flopTextureId); L2DLRenderHelpers.ExecuteBuffer(_context, m_lpvIterationsBuffer); }
// -------------------------------------------------------------------- public void Render(ScriptableRenderContext context, Camera camera) { m_context = context; m_camera = camera; // Sample to encapsulate all used buffers under one heading in the frame debugger L2DLRenderHelpers.BeginSample(m_context, m_sceneDataRenderBuffer); { m_context.SetupCameraProperties(m_camera); // MUST go before culling so that in world UI is setup pre-cull L2DLRenderHelpers.PrepareCameraForSceneWindow(m_camera); if (!m_camera.TryGetCullingParameters(out m_cullingParameters)) { return; } m_cullingResults = m_context.Cull(ref m_cullingParameters); //Clear the main output textures m_clearTexturebuffer.SetRenderTarget(new RenderTargetIdentifier[] { L2DLPipelineData.s_cameraColorTextureId }, L2DLPipelineData.s_cameraDepthTextureId); if (m_camera.cameraType == CameraType.SceneView) { // The scene m_camera's settings aren't always set to clear things, it's quite odd so hard code it to clear m_clearTexturebuffer.ClearRenderTarget(true, true, m_camera.backgroundColor.linear); } else { m_clearTexturebuffer.ClearRenderTarget(m_camera.clearFlags <= CameraClearFlags.Depth, m_camera.clearFlags == CameraClearFlags.Color, m_camera.clearFlags == CameraClearFlags.Color ? m_camera.backgroundColor.linear : Color.clear); } //Clear the buffer textures m_clearTexturebuffer.SetRenderTarget(new RenderTargetIdentifier[] { L2DLPipelineData.s_cameraOcclusionTextureId, L2DLPipelineData.s_cameraEmissionTextureId, L2DLPipelineData.s_cameraAdditionalDataTextureId }, L2DLPipelineData.s_cameraDepthTextureId); m_clearTexturebuffer.ClearRenderTarget(false, true, Color.clear); L2DLRenderHelpers.ExecuteBuffer(m_context, m_clearTexturebuffer); // Set render targets for rendering m_sceneDataRenderBuffer.SetRenderTarget(new RenderTargetIdentifier[] { L2DLPipelineData.s_cameraColorTextureId, L2DLPipelineData.s_cameraOcclusionTextureId, L2DLPipelineData.s_cameraEmissionTextureId, L2DLPipelineData.s_cameraAdditionalDataTextureId }, L2DLPipelineData.s_cameraDepthTextureId); L2DLRenderHelpers.ExecuteBuffer(m_context, m_sceneDataRenderBuffer); L2DLRenderHelpers.DrawAllRenderers(m_context, m_cullingResults); } L2DLRenderHelpers.EndSample(m_context, m_sceneDataRenderBuffer); // Editor Only L2DLRenderHelpers.DrawUnsupportedShaders(m_context, m_cullingResults); }