// As we have our own default value, we need to initialize the light intensity correctly public static void InitDefaultHDAdditionalLightData(HDAdditionalLightData lightData) { // At first init we need to initialize correctly the default value lightData.ConvertPhysicalLightIntensityToLightIntensity(); // Special treatment for Unity builtin area light. Change it to our rectangle light var light = lightData.gameObject.GetComponent <Light>(); if (light.type == LightType.Area) { lightData.lightTypeExtent = LightTypeExtent.Rectangle; } }
// As we have our own default value, we need to initialize the light intensity correctly public static void InitDefaultHDAdditionalLightData(HDAdditionalLightData lightData) { // At first init we need to initialize correctly the default value lightData.ConvertPhysicalLightIntensityToLightIntensity(); // Special treatment for Unity builtin area light. Change it to our rectangle light var light = lightData.gameObject.GetComponent <Light>(); // Sanity check: lightData.lightTypeExtent is init to LightTypeExtent.Punctual (in case for unknow reasons we recreate additional data on an existing line) if (light.type == LightType.Area && lightData.lightTypeExtent == LightTypeExtent.Punctual) { lightData.lightTypeExtent = LightTypeExtent.Rectangle; light.type = LightType.Point; // Same as in HDLightEditor } }
// We do our own hash here because Unity does not provide correct hash for builtin types // Moreover, we don't want to test every single parameters of the light so we filter them here in this specific function. int GetSunLightHashCode(Light light) { HDAdditionalLightData ald = light.GetComponent <HDAdditionalLightData>(); unchecked { // Sun could influence the sky (like for procedural sky). We need to handle this possibility. If sun property change, then we need to update the sky int hash = 13; hash = hash * 23 + (light.GetHashCode() * 23 + light.transform.position.GetHashCode()) * 23 + light.transform.rotation.GetHashCode(); hash = hash * 23 + light.color.GetHashCode(); hash = hash * 23 + light.colorTemperature.GetHashCode(); hash = hash * 23 + light.intensity.GetHashCode(); // Note: We don't take into account cookie as it doesn't influence GI if (ald != null) { hash = hash * 23 + ald.lightDimmer.GetHashCode(); } return(hash); } }
public void CopyTo(HDAdditionalLightData data) { #pragma warning disable 618 data.directionalIntensity = directionalIntensity; data.punctualIntensity = punctualIntensity; data.areaIntensity = areaIntensity; #pragma warning restore 618 data.enableSpotReflector = enableSpotReflector; data.luxAtDistance = luxAtDistance; data.m_InnerSpotPercent = m_InnerSpotPercent; data.lightDimmer = lightDimmer; data.volumetricDimmer = volumetricDimmer; data.lightUnit = lightUnit; data.fadeDistance = fadeDistance; data.affectDiffuse = affectDiffuse; data.affectSpecular = affectSpecular; data.nonLightmappedOnly = nonLightmappedOnly; data.lightTypeExtent = lightTypeExtent; data.spotLightShape = spotLightShape; data.shapeWidth = shapeWidth; data.shapeHeight = shapeHeight; data.aspectRatio = aspectRatio; data.shapeRadius = shapeRadius; data.maxSmoothness = maxSmoothness; data.applyRangeAttenuation = applyRangeAttenuation; data.useOldInspector = useOldInspector; data.featuresFoldout = featuresFoldout; data.showAdditionalSettings = showAdditionalSettings; data.displayLightIntensity = displayLightIntensity; data.displayAreaLightEmissiveMesh = displayAreaLightEmissiveMesh; data.needsIntensityUpdate_1_0 = needsIntensityUpdate_1_0; #if UNITY_EDITOR data.timelineWorkaround = timelineWorkaround; #endif }
public void RenderLightVolumes(CommandBuffer cmd, HDCamera hdCamera, CullingResults cullResults, LightingDebugSettings lightDebugSettings, RTHandleSystem.RTHandle finalRT) { using (new ProfilingSample(cmd, "Display Light Volumes")) { // Clear the buffers HDUtils.SetRenderTarget(cmd, hdCamera, m_ColorAccumulationBuffer, ClearFlag.Color, Color.black); HDUtils.SetRenderTarget(cmd, hdCamera, m_LightCountBuffer, ClearFlag.Color, Color.black); HDUtils.SetRenderTarget(cmd, hdCamera, m_DebugLightVolumesTexture, ClearFlag.Color, Color.black); // Set the render target array HDUtils.SetRenderTarget(cmd, hdCamera, m_RTIDs, m_DepthBuffer); // First of all let's do the regions for the light sources (we only support Punctual and Area) int numLights = cullResults.visibleLights.Length; for (int lightIdx = 0; lightIdx < numLights; ++lightIdx) { // Let's build the light's bounding sphere matrix Light currentLegacyLight = cullResults.visibleLights[lightIdx].light; if (currentLegacyLight == null) { continue; } HDAdditionalLightData currentHDRLight = currentLegacyLight.GetComponent <HDAdditionalLightData>(); if (currentHDRLight == null) { continue; } Matrix4x4 positionMat = Matrix4x4.Translate(currentLegacyLight.transform.position); if (currentLegacyLight.type == LightType.Point || currentLegacyLight.type == LightType.Area) { m_MaterialProperty.SetVector(_RangeShaderID, new Vector3(currentLegacyLight.range, currentLegacyLight.range, currentLegacyLight.range)); switch (currentHDRLight.lightTypeExtent) { case LightTypeExtent.Punctual: { m_MaterialProperty.SetColor(_ColorShaderID, new Color(0.0f, 0.5f, 0.0f, 1.0f)); m_MaterialProperty.SetVector(_OffsetShaderID, new Vector3(0, 0, 0)); cmd.DrawMesh(DebugShapes.instance.RequestSphereMesh(), positionMat, m_DebugLightVolumeMaterial, 0, 0, m_MaterialProperty); } break; case LightTypeExtent.Rectangle: { m_MaterialProperty.SetColor(_ColorShaderID, new Color(0.0f, 1.0f, 1.0f, 1.0f)); m_MaterialProperty.SetVector(_OffsetShaderID, new Vector3(0, 0, 0)); cmd.DrawMesh(DebugShapes.instance.RequestSphereMesh(), positionMat, m_DebugLightVolumeMaterial, 0, 0, m_MaterialProperty); } break; case LightTypeExtent.Tube: { m_MaterialProperty.SetColor(_ColorShaderID, new Color(1.0f, 0.0f, 0.5f, 1.0f)); m_MaterialProperty.SetVector(_OffsetShaderID, new Vector3(0, 0, 0)); cmd.DrawMesh(DebugShapes.instance.RequestSphereMesh(), positionMat, m_DebugLightVolumeMaterial, 0, 0, m_MaterialProperty); } break; default: break; } } else if (currentLegacyLight.type == LightType.Spot) { if (currentHDRLight.spotLightShape == SpotLightShape.Cone) { float bottomRadius = Mathf.Tan(currentLegacyLight.spotAngle * Mathf.PI / 360.0f) * currentLegacyLight.range; m_MaterialProperty.SetColor(_ColorShaderID, new Color(1.0f, 0.5f, 0.0f, 1.0f)); m_MaterialProperty.SetVector(_RangeShaderID, new Vector3(bottomRadius, bottomRadius, currentLegacyLight.range)); m_MaterialProperty.SetVector(_OffsetShaderID, new Vector3(0, 0, 0)); cmd.DrawMesh(DebugShapes.instance.RequestConeMesh(), currentLegacyLight.gameObject.transform.localToWorldMatrix, m_DebugLightVolumeMaterial, 0, 0, m_MaterialProperty); } else if (currentHDRLight.spotLightShape == SpotLightShape.Box) { m_MaterialProperty.SetColor(_ColorShaderID, new Color(1.0f, 0.5f, 0.0f, 1.0f)); m_MaterialProperty.SetVector(_RangeShaderID, new Vector3(currentHDRLight.shapeWidth, currentHDRLight.shapeHeight, currentLegacyLight.range)); m_MaterialProperty.SetVector(_OffsetShaderID, new Vector3(0, 0, currentLegacyLight.range / 2.0f)); cmd.DrawMesh(DebugShapes.instance.RequestBoxMesh(), currentLegacyLight.gameObject.transform.localToWorldMatrix, m_DebugLightVolumeMaterial, 0, 0, m_MaterialProperty); } else if (currentHDRLight.spotLightShape == SpotLightShape.Pyramid) { float bottomWidth = Mathf.Tan(currentLegacyLight.spotAngle * Mathf.PI / 360.0f) * currentLegacyLight.range; m_MaterialProperty.SetColor(_ColorShaderID, new Color(1.0f, 0.5f, 0.0f, 1.0f)); m_MaterialProperty.SetVector(_RangeShaderID, new Vector3(currentHDRLight.aspectRatio * bottomWidth * 2, bottomWidth * 2, currentLegacyLight.range)); m_MaterialProperty.SetVector(_OffsetShaderID, new Vector3(0, 0, 0)); cmd.DrawMesh(DebugShapes.instance.RequestPyramidMesh(), currentLegacyLight.gameObject.transform.localToWorldMatrix, m_DebugLightVolumeMaterial, 0, 0, m_MaterialProperty); } } } // Now let's do the same but for reflection probes int numProbes = cullResults.visibleReflectionProbes.Length; for (int probeIdx = 0; probeIdx < numProbes; ++probeIdx) { // Let's build the light's bounding sphere matrix ReflectionProbe currentLegacyProbe = cullResults.visibleReflectionProbes[probeIdx].reflectionProbe; HDAdditionalReflectionData currentHDProbe = currentLegacyProbe.GetComponent <HDAdditionalReflectionData>(); if (!currentHDProbe) { continue; } MaterialPropertyBlock m_MaterialProperty = new MaterialPropertyBlock(); Mesh targetMesh = null; if (currentHDProbe.influenceVolume.shape == InfluenceShape.Sphere) { m_MaterialProperty.SetVector(_RangeShaderID, new Vector3(currentHDProbe.influenceVolume.sphereRadius, currentHDProbe.influenceVolume.sphereRadius, currentHDProbe.influenceVolume.sphereRadius)); targetMesh = DebugShapes.instance.RequestSphereMesh(); } else { m_MaterialProperty.SetVector(_RangeShaderID, new Vector3(currentHDProbe.influenceVolume.boxSize.x, currentHDProbe.influenceVolume.boxSize.y, currentHDProbe.influenceVolume.boxSize.z)); targetMesh = DebugShapes.instance.RequestBoxMesh(); } m_MaterialProperty.SetColor(_ColorShaderID, new Color(1.0f, 1.0f, 0.0f, 1.0f)); m_MaterialProperty.SetVector(_OffsetShaderID, new Vector3(0, 0, 0)); Matrix4x4 positionMat = Matrix4x4.Translate(currentLegacyProbe.transform.position); cmd.DrawMesh(targetMesh, positionMat, m_DebugLightVolumeMaterial, 0, 0, m_MaterialProperty); } // Define which kernel to use based on the lightloop options int targetKernel = lightDebugSettings.lightVolumeDebugByCategory == LightLoop.LightVolumeDebug.ColorAndEdge ? m_DebugLightVolumeColorsKernel : m_DebugLightVolumeGradientKernel; // Set the input params for the compute cmd.SetComputeTextureParam(m_DebugLightVolumeCompute, targetKernel, _DebugLightCountBufferShaderID, m_LightCountBuffer); cmd.SetComputeTextureParam(m_DebugLightVolumeCompute, targetKernel, _DebugColorAccumulationBufferShaderID, m_ColorAccumulationBuffer); cmd.SetComputeTextureParam(m_DebugLightVolumeCompute, targetKernel, _DebugLightVolumesTextureShaderID, m_DebugLightVolumesTexture); cmd.SetComputeTextureParam(m_DebugLightVolumeCompute, targetKernel, _ColorGradientTextureShaderID, m_ColorGradientTexture); cmd.SetComputeIntParam(m_DebugLightVolumeCompute, _MaxDebugLightCountShaderID, (int)lightDebugSettings.maxDebugLightCount); // Texture dimensions int texWidth = hdCamera.actualWidth; // m_ColorAccumulationBuffer.rt.width; int texHeight = hdCamera.actualHeight; // m_ColorAccumulationBuffer.rt.width; // Dispatch the compute int lightVolumesTileSize = 8; int numTilesX = (texWidth + (lightVolumesTileSize - 1)) / lightVolumesTileSize; int numTilesY = (texHeight + (lightVolumesTileSize - 1)) / lightVolumesTileSize; cmd.DispatchCompute(m_DebugLightVolumeCompute, targetKernel, numTilesX, numTilesY, hdCamera.computePassCount); // Blit this into the camera target HDUtils.SetRenderTarget(cmd, hdCamera, finalRT); m_MaterialProperty.SetTexture(HDShaderIDs._BlitTexture, m_DebugLightVolumesTexture); cmd.DrawProcedural(Matrix4x4.identity, m_DebugLightVolumeMaterial, 1, MeshTopology.Triangles, 3, 1, m_MaterialProperty); } }
public void BuildSubSceneStructure(ref HDRayTracingSubScene subScene) { // If there is no render environments, then we should not generate acceleration structure if (m_Environments.Count > 0) { // This structure references all the renderers that are considered to be processed Dictionary <int, int> rendererReference = new Dictionary <int, int>(); // Destroy the acceleration structure subScene.targetRenderers = new List <Renderer>(); // Create the acceleration structure subScene.accelerationStructure = new RaytracingAccelerationStructure(); // First of all let's process all the LOD groups LODGroup[] lodGroupArray = UnityEngine.GameObject.FindObjectsOfType <LODGroup>(); for (var i = 0; i < lodGroupArray.Length; i++) { // Grab the current LOD group LODGroup lodGroup = lodGroupArray[i]; // Get the set of LODs LOD[] lodArray = lodGroup.GetLODs(); for (int lodIdx = 0; lodIdx < lodArray.Length; ++lodIdx) { LOD currentLOD = lodArray[lodIdx]; // We only want to push to the acceleration structure the first fella if (lodIdx == 0) { for (int rendererIdx = 0; rendererIdx < currentLOD.renderers.Length; ++rendererIdx) { // Convert the object's layer to an int int objectLayerValue = 1 << currentLOD.renderers[rendererIdx].gameObject.layer; // Is this object in one of the allowed layers ? if ((objectLayerValue & subScene.mask.value) != 0) { // Add this fella to the renderer list subScene.targetRenderers.Add(currentLOD.renderers[rendererIdx]); } } } // Add them to the processed set for (int rendererIdx = 0; rendererIdx < currentLOD.renderers.Length; ++rendererIdx) { Renderer currentRenderer = currentLOD.renderers[rendererIdx]; // Add this fella to the renderer list rendererReference.Add(currentRenderer.GetInstanceID(), 1); } } } int maxNumSubMeshes = 1; // Grab all the renderers from the scene var rendererArray = UnityEngine.GameObject.FindObjectsOfType <Renderer>(); for (var i = 0; i < rendererArray.Length; i++) { // Fetch the current renderer Renderer currentRenderer = rendererArray[i]; // If it is not active skip it if (currentRenderer.enabled == false) { continue; } // Grab the current game object GameObject gameObject = currentRenderer.gameObject; // Has this object already been processed, jsut skip if (rendererReference.ContainsKey(currentRenderer.GetInstanceID())) { continue; } // Does this object have a reflection probe component? if yes we do not want to see it in the raytracing environment ReflectionProbe targetProbe = gameObject.GetComponent <ReflectionProbe>(); if (targetProbe != null) { continue; } // Convert the object's layer to an int int objectLayerValue = 1 << currentRenderer.gameObject.layer; // Is this object in one of the allowed layers ? if ((objectLayerValue & subScene.mask.value) != 0) { // Add this fella to the renderer list subScene.targetRenderers.Add(currentRenderer); } // Also, we need to contribute to the maximal number of submeshes MeshFilter currentFilter = currentRenderer.GetComponent <MeshFilter>(); if (currentFilter != null && currentFilter.sharedMesh != null) { maxNumSubMeshes = Mathf.Max(maxNumSubMeshes, currentFilter.sharedMesh.subMeshCount); } } bool[] subMeshFlagArray = new bool[maxNumSubMeshes]; bool[] subMeshCutoffArray = new bool[maxNumSubMeshes]; // If any object build the acceleration structure if (subScene.targetRenderers.Count != 0) { // For all the renderers that we need to push in the acceleration structure for (var i = 0; i < subScene.targetRenderers.Count; i++) { // Grab the current renderer Renderer currentRenderer = subScene.targetRenderers[i]; bool singleSided = false; if (currentRenderer.sharedMaterials != null) { // For every sub-mesh/sub-material let's build the right flags int numSubMeshes = currentRenderer.sharedMaterials.Length; uint instanceFlag = 0xff; for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx) { Material currentMaterial = currentRenderer.sharedMaterials[meshIdx]; // The material is transparent if either it has the requested keyword or is in the transparent queue range if (currentMaterial != null) { subMeshFlagArray[meshIdx] = true; // Is the material transparent? bool materialIsTransparent = currentMaterial.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT") || (HDRenderQueue.k_RenderQueue_Transparent.lowerBound <= currentMaterial.renderQueue && HDRenderQueue.k_RenderQueue_Transparent.upperBound >= currentMaterial.renderQueue) || (HDRenderQueue.k_RenderQueue_AllTransparentRaytracing.lowerBound <= currentMaterial.renderQueue && HDRenderQueue.k_RenderQueue_AllTransparentRaytracing.upperBound >= currentMaterial.renderQueue); // Propagate the right mask instanceFlag = materialIsTransparent ? (uint)0xf0 : (uint)0x0f; // Is the material alpha tested? subMeshCutoffArray[meshIdx] = currentMaterial.IsKeywordEnabled("_ALPHATEST_ON") || (HDRenderQueue.k_RenderQueue_OpaqueAlphaTest.lowerBound <= currentMaterial.renderQueue && HDRenderQueue.k_RenderQueue_OpaqueAlphaTest.upperBound >= currentMaterial.renderQueue); // Force it to be non single sided if it has the keyword if there is a reason bool doubleSided = currentMaterial.doubleSidedGI || currentMaterial.IsKeywordEnabled("_DOUBLESIDED_ON"); singleSided |= !doubleSided; } else { subMeshFlagArray[meshIdx] = false; subMeshCutoffArray[meshIdx] = false; singleSided = true; } } // Add it to the acceleration structure subScene.accelerationStructure.AddInstance(currentRenderer, subMeshMask: subMeshFlagArray, subMeshTransparencyFlags: subMeshCutoffArray, enableTriangleCulling: singleSided, mask: instanceFlag); } } } // build the acceleration structure subScene.accelerationStructure.Build(); // Allocate the array for the lights subScene.hdLightArray = new List <HDAdditionalLightData>(); subScene.hdDirectionalLightArray = new List <HDAdditionalLightData>(); // fetch all the hdrp lights HDAdditionalLightData[] hdLightArray = UnityEngine.GameObject.FindObjectsOfType <HDAdditionalLightData>(); // Here an important thing is to make sure that the point lights are first in the list then line then area List <HDAdditionalLightData> pointLights = new List <HDAdditionalLightData>(); List <HDAdditionalLightData> lineLights = new List <HDAdditionalLightData>(); List <HDAdditionalLightData> rectLights = new List <HDAdditionalLightData>(); for (int lightIdx = 0; lightIdx < hdLightArray.Length; ++lightIdx) { HDAdditionalLightData hdLight = hdLightArray[lightIdx]; if (hdLight.enabled) { // Convert the object's layer to an int int lightayerValue = 1 << hdLight.gameObject.layer; if ((lightayerValue & subScene.mask.value) != 0) { if (hdLight.GetComponent <Light>().type == LightType.Directional) { subScene.hdDirectionalLightArray.Add(hdLight); } else { if (hdLight.lightTypeExtent == LightTypeExtent.Punctual) { pointLights.Add(hdLight); } else if (hdLight.lightTypeExtent == LightTypeExtent.Tube) { lineLights.Add(hdLight); } else { rectLights.Add(hdLight); } } } } } subScene.hdLightArray.AddRange(pointLights); subScene.hdLightArray.AddRange(lineLights); subScene.hdLightArray.AddRange(rectLights); // Build the light cluster subScene.lightCluster = new HDRaytracingLightCluster(); subScene.lightCluster.Initialize(m_Resources, this, m_SharedRTManager, m_LightLoop); // Mark this sub-scene as valid subScene.valid = true; } else { subScene.valid = false; } }
public bool RenderAreaShadows(HDCamera hdCamera, CommandBuffer cmd, ScriptableRenderContext renderContext, int frameCount) { // NOTE: Here we cannot clear the area shadow texture because it is a texture array. So we need to bind it and make sure no material will try to read it in the shaders BindShadowTexture(cmd); // Let's check all the resources and states to see if we should render the effect HDRaytracingEnvironment rtEnvironment = m_RaytracingManager.CurrentEnvironment(); RaytracingShader shadowRaytrace = m_PipelineAsset.renderPipelineRayTracingResources.areaShadowsRaytracingRT; ComputeShader shadowsCompute = m_PipelineAsset.renderPipelineRayTracingResources.areaShadowRaytracingCS; ComputeShader shadowFilter = m_PipelineAsset.renderPipelineRayTracingResources.areaShadowFilterCS; // Make sure everything is valid bool invalidState = rtEnvironment == null || hdCamera.frameSettings.litShaderMode != LitShaderMode.Deferred || shadowRaytrace == null || shadowsCompute == null || shadowFilter == null || m_PipelineResources.textures.owenScrambledTex == null || m_PipelineResources.textures.scramblingTex == null; // If invalid state or ray-tracing acceleration structure, we stop right away if (invalidState) { return(false); } // Grab the TAA history buffers (SN/UN and Analytic value) RTHandleSystem.RTHandle areaShadowHistoryArray = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.RaytracedAreaShadow) ?? hdCamera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.RaytracedAreaShadow, AreaShadowHistoryBufferAllocatorFunction, 1); RTHandleSystem.RTHandle areaAnalyticHistoryArray = hdCamera.GetCurrentFrameRT((int)HDCameraFrameHistoryType.RaytracedAreaAnalytic) ?? hdCamera.AllocHistoryFrameRT((int)HDCameraFrameHistoryType.RaytracedAreaAnalytic, AreaAnalyticHistoryBufferAllocatorFunction, 1); // Grab the acceleration structure for the target camera RaytracingAccelerationStructure accelerationStructure = m_RaytracingManager.RequestAccelerationStructure(rtEnvironment.shadowLayerMask); // Define the shader pass to use for the reflection pass cmd.SetRaytracingShaderPass(shadowRaytrace, "VisibilityDXR"); // Set the acceleration structure for the pass cmd.SetRaytracingAccelerationStructure(shadowRaytrace, HDShaderIDs._RaytracingAccelerationStructureName, accelerationStructure); // Inject the ray-tracing sampling data cmd.SetGlobalTexture(HDShaderIDs._OwenScrambledTexture, m_PipelineResources.textures.owenScrambledTex); cmd.SetGlobalTexture(HDShaderIDs._ScramblingTexture, m_PipelineResources.textures.scramblingTex); int frameIndex = hdCamera.IsTAAEnabled() ? hdCamera.taaFrameIndex : (int)frameCount % 8; cmd.SetGlobalInt(HDShaderIDs._RaytracingFrameIndex, frameIndex); // Temporal Filtering kernels int applyTAAKernel = shadowFilter.FindKernel("AreaShadowApplyTAA"); int updateAnalyticHistory = shadowFilter.FindKernel("AreaAnalyticHistoryCopy"); int updateShadowHistory = shadowFilter.FindKernel("AreaShadowHistoryCopy"); // Spatial Filtering kernels int estimateNoiseKernel = shadowFilter.FindKernel("AreaShadowEstimateNoise"); int firstDenoiseKernel = shadowFilter.FindKernel("AreaShadowDenoiseFirstPass"); int secondDenoiseKernel = shadowFilter.FindKernel("AreaShadowDenoiseSecondPass"); // Texture dimensions int texWidth = hdCamera.actualWidth; int texHeight = hdCamera.actualHeight; // Evaluate the dispatch parameters int areaTileSize = 8; int numTilesX = (texWidth + (areaTileSize - 1)) / areaTileSize; int numTilesY = (texHeight + (areaTileSize - 1)) / areaTileSize; // Inject the ray generation data cmd.SetGlobalFloat(HDShaderIDs._RaytracingRayBias, rtEnvironment.rayBias); int numLights = m_RenderPipeline.m_lightList.lights.Count; for (int lightIdx = 0; lightIdx < numLights; ++lightIdx) { // If this is not a rectangular area light or it won't have shadows, skip it if (m_RenderPipeline.m_lightList.lights[lightIdx].lightType != GPULightType.Rectangle || m_RenderPipeline.m_lightList.lights[lightIdx].rayTracedAreaShadowIndex == -1) { continue; } LightData currentLight = m_RenderPipeline.m_lightList.lights[lightIdx]; HDAdditionalLightData currentAdditionalLightData = m_RenderPipeline.GetCurrentRayTracedShadow(currentLight.rayTracedAreaShadowIndex); using (new ProfilingSample(cmd, "Ray Traced Area Shadow", CustomSamplerId.RaytracingShadowIntegration.GetSampler())) { // We need to build the world to area light matrix worldToLocalArea.SetColumn(0, currentLight.right); worldToLocalArea.SetColumn(1, currentLight.up); worldToLocalArea.SetColumn(2, currentLight.forward); // Compensate the relative rendering if active Vector3 lightPositionWS = currentLight.positionRWS; if (ShaderConfig.s_CameraRelativeRendering != 0) { lightPositionWS += hdCamera.camera.transform.position; } worldToLocalArea.SetColumn(3, lightPositionWS); worldToLocalArea.m33 = 1.0f; worldToLocalArea = worldToLocalArea.inverse; // We have noticed from extensive profiling that ray-trace shaders are not as effective for running per-pixel computation. In order to reduce that, // we do a first prepass that compute the analytic term and probability and generates the first integration sample if (true) { int shadowComputeKernel = shadowsCompute.FindKernel("RaytracingAreaShadowPrepass"); // This pass evaluates the analytic value and the generates and outputs the first sample cmd.SetComputeBufferParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._LightDatas, m_RenderPipeline.lightDatas); cmd.SetComputeIntParam(shadowsCompute, HDShaderIDs._RaytracingTargetAreaLight, lightIdx); cmd.SetComputeIntParam(shadowsCompute, HDShaderIDs._RaytracingNumSamples, currentAdditionalLightData.numRayTracingSamples); cmd.SetComputeMatrixParam(shadowsCompute, HDShaderIDs._RaytracingAreaWorldToLocal, worldToLocalArea); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._NormalBufferTexture, m_SharedRTManager.GetNormalBuffer()); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._GBufferTexture[0], m_GbufferManager.GetBuffer(0)); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._GBufferTexture[1], m_GbufferManager.GetBuffer(1)); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._GBufferTexture[2], m_GbufferManager.GetBuffer(2)); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._GBufferTexture[3], m_GbufferManager.GetBuffer(3)); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._AreaCookieTextures, m_RenderPipeline.areaLightCookieManager.GetTexCache()); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._RaytracedAreaShadowIntegration, m_DenoiseBuffer0); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._RaytracedAreaShadowSample, m_DenoiseBuffer1); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._RaytracingDirectionBuffer, m_RaytracingDirectionBuffer); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._RaytracingDistanceBuffer, m_RaytracingDistanceBuffer); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._AnalyticProbBuffer, m_AnalyticProbBuffer); cmd.DispatchCompute(shadowsCompute, shadowComputeKernel, numTilesX, numTilesY, 1); // This pass will use the previously generated sample and add it to the integration buffer cmd.SetRaytracingBufferParam(shadowRaytrace, HDShaderIDs._LightDatas, m_RenderPipeline.lightDatas); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._RaytracedAreaShadowSample, m_DenoiseBuffer1); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._RaytracedAreaShadowIntegration, m_DenoiseBuffer0); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._RaytracingDirectionBuffer, m_RaytracingDirectionBuffer); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._RaytracingDistanceBuffer, m_RaytracingDistanceBuffer); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._AnalyticProbBuffer, m_AnalyticProbBuffer); cmd.DispatchRays(shadowRaytrace, m_RayGenShadowSingleName, (uint)hdCamera.actualWidth, (uint)hdCamera.actualHeight, 1); // Let's do the following samples (if any) for (int sampleIndex = 1; sampleIndex < currentAdditionalLightData.numRayTracingSamples; ++sampleIndex) { shadowComputeKernel = shadowsCompute.FindKernel("RaytracingAreaShadowNewSample"); // This pass generates a new sample based on the initial pre-pass cmd.SetComputeBufferParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._LightDatas, m_RenderPipeline.lightDatas); cmd.SetComputeIntParam(shadowsCompute, HDShaderIDs._RaytracingTargetAreaLight, lightIdx); cmd.SetComputeIntParam(shadowsCompute, HDShaderIDs._RaytracingNumSamples, currentAdditionalLightData.numRayTracingSamples); cmd.SetComputeIntParam(shadowsCompute, HDShaderIDs._RaytracingSampleIndex, sampleIndex); cmd.SetComputeMatrixParam(shadowsCompute, HDShaderIDs._RaytracingAreaWorldToLocal, worldToLocalArea); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._NormalBufferTexture, m_SharedRTManager.GetNormalBuffer()); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._GBufferTexture[0], m_GbufferManager.GetBuffer(0)); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._GBufferTexture[1], m_GbufferManager.GetBuffer(1)); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._GBufferTexture[2], m_GbufferManager.GetBuffer(2)); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._GBufferTexture[3], m_GbufferManager.GetBuffer(3)); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._AreaCookieTextures, m_RenderPipeline.areaLightCookieManager.GetTexCache()); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._RaytracedAreaShadowIntegration, m_DenoiseBuffer0); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._RaytracedAreaShadowSample, m_DenoiseBuffer1); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._RaytracingDirectionBuffer, m_RaytracingDirectionBuffer); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._RaytracingDistanceBuffer, m_RaytracingDistanceBuffer); cmd.SetComputeTextureParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._AnalyticProbBuffer, m_AnalyticProbBuffer); cmd.DispatchCompute(shadowsCompute, shadowComputeKernel, numTilesX, numTilesY, 1); // This pass will use the previously generated sample and add it to the integration buffer cmd.SetRaytracingBufferParam(shadowRaytrace, HDShaderIDs._LightDatas, m_RenderPipeline.lightDatas); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._RaytracedAreaShadowSample, m_DenoiseBuffer1); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._RaytracedAreaShadowIntegration, m_DenoiseBuffer0); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._RaytracingDirectionBuffer, m_RaytracingDirectionBuffer); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._RaytracingDistanceBuffer, m_RaytracingDistanceBuffer); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._AnalyticProbBuffer, m_AnalyticProbBuffer); cmd.DispatchRays(shadowRaytrace, m_RayGenShadowSingleName, (uint)hdCamera.actualWidth, (uint)hdCamera.actualHeight, 1); } } else { // This pass generates the analytic value and will do the full integration cmd.SetRaytracingBufferParam(shadowRaytrace, HDShaderIDs._LightDatas, m_RenderPipeline.lightDatas); cmd.SetRaytracingIntParam(shadowRaytrace, HDShaderIDs._RaytracingTargetAreaLight, lightIdx); cmd.SetRaytracingIntParam(shadowRaytrace, HDShaderIDs._RaytracingNumSamples, currentAdditionalLightData.numRayTracingSamples); cmd.SetRaytracingMatrixParam(shadowRaytrace, HDShaderIDs._RaytracingAreaWorldToLocal, worldToLocalArea); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._NormalBufferTexture, m_SharedRTManager.GetNormalBuffer()); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._GBufferTexture[0], m_GbufferManager.GetBuffer(0)); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._GBufferTexture[1], m_GbufferManager.GetBuffer(1)); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._GBufferTexture[2], m_GbufferManager.GetBuffer(2)); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._GBufferTexture[3], m_GbufferManager.GetBuffer(3)); cmd.SetRaytracingIntParam(shadowRaytrace, HDShaderIDs._RayCountEnabled, m_RaytracingManager.rayCountManager.RayCountIsEnabled()); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._RayCountTexture, m_RaytracingManager.rayCountManager.rayCountTexture); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._AreaCookieTextures, m_RenderPipeline.areaLightCookieManager.GetTexCache()); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._AnalyticProbBuffer, m_AnalyticProbBuffer); cmd.SetRaytracingTextureParam(shadowRaytrace, HDShaderIDs._RaytracedAreaShadowIntegration, m_DenoiseBuffer0); cmd.DispatchRays(shadowRaytrace, m_RayGenShaderName, (uint)hdCamera.actualWidth, (uint)hdCamera.actualHeight, 1); } } using (new ProfilingSample(cmd, "Combine Area Shadow", CustomSamplerId.RaytracingShadowCombination.GetSampler())) { // Global parameters cmd.SetComputeIntParam(shadowFilter, HDShaderIDs._RaytracingDenoiseRadius, currentAdditionalLightData.filterSizeTraced); cmd.SetComputeIntParam(shadowFilter, HDShaderIDs._RaytracingShadowSlot, m_RenderPipeline.m_lightList.lights[lightIdx].rayTracedAreaShadowIndex); // Apply a vectorized temporal filtering pass and store it back in the denoisebuffer0 with the analytic value in the third channel var historyScale = new Vector2(hdCamera.actualWidth / (float)areaShadowHistoryArray.rt.width, hdCamera.actualHeight / (float)areaShadowHistoryArray.rt.height); cmd.SetComputeVectorParam(shadowFilter, HDShaderIDs._RTHandleScaleHistory, historyScale); cmd.SetComputeTextureParam(shadowFilter, applyTAAKernel, HDShaderIDs._AnalyticProbBuffer, m_AnalyticProbBuffer); cmd.SetComputeTextureParam(shadowFilter, applyTAAKernel, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetComputeTextureParam(shadowFilter, applyTAAKernel, HDShaderIDs._AreaShadowHistory, areaShadowHistoryArray); cmd.SetComputeTextureParam(shadowFilter, applyTAAKernel, HDShaderIDs._AnalyticHistoryBuffer, areaAnalyticHistoryArray); cmd.SetComputeTextureParam(shadowFilter, applyTAAKernel, HDShaderIDs._DenoiseInputTexture, m_DenoiseBuffer0); cmd.SetComputeTextureParam(shadowFilter, applyTAAKernel, HDShaderIDs._DenoiseOutputTextureRW, m_DenoiseBuffer1); cmd.DispatchCompute(shadowFilter, applyTAAKernel, numTilesX, numTilesY, 1); // Update the shadow history buffer cmd.SetComputeTextureParam(shadowFilter, updateAnalyticHistory, HDShaderIDs._AnalyticProbBuffer, m_AnalyticProbBuffer); cmd.SetComputeTextureParam(shadowFilter, updateAnalyticHistory, HDShaderIDs._AnalyticHistoryBuffer, areaAnalyticHistoryArray); cmd.DispatchCompute(shadowFilter, updateAnalyticHistory, numTilesX, numTilesY, 1); // Update the analytic history buffer cmd.SetComputeTextureParam(shadowFilter, updateShadowHistory, HDShaderIDs._DenoiseInputTexture, m_DenoiseBuffer1); cmd.SetComputeTextureParam(shadowFilter, updateShadowHistory, HDShaderIDs._AreaShadowHistoryRW, areaShadowHistoryArray); cmd.DispatchCompute(shadowFilter, updateShadowHistory, numTilesX, numTilesY, 1); if (currentAdditionalLightData.filterSizeTraced > 0) { // Inject parameters for noise estimation cmd.SetComputeTextureParam(shadowFilter, estimateNoiseKernel, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetComputeTextureParam(shadowFilter, estimateNoiseKernel, HDShaderIDs._NormalBufferTexture, m_SharedRTManager.GetNormalBuffer()); cmd.SetComputeTextureParam(shadowFilter, estimateNoiseKernel, HDShaderIDs._ScramblingTexture, m_PipelineResources.textures.scramblingTex); // Noise estimation pre-pass cmd.SetComputeTextureParam(shadowFilter, estimateNoiseKernel, HDShaderIDs._DenoiseInputTexture, m_DenoiseBuffer1); cmd.SetComputeTextureParam(shadowFilter, estimateNoiseKernel, HDShaderIDs._DenoiseOutputTextureRW, m_DenoiseBuffer0); cmd.DispatchCompute(shadowFilter, estimateNoiseKernel, numTilesX, numTilesY, 1); // Reinject parameters for denoising cmd.SetComputeTextureParam(shadowFilter, firstDenoiseKernel, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetComputeTextureParam(shadowFilter, firstDenoiseKernel, HDShaderIDs._NormalBufferTexture, m_SharedRTManager.GetNormalBuffer()); cmd.SetComputeTextureParam(shadowFilter, firstDenoiseKernel, HDShaderIDs._AreaShadowTextureRW, m_AreaShadowTextureArray); // First denoising pass cmd.SetComputeTextureParam(shadowFilter, firstDenoiseKernel, HDShaderIDs._DenoiseInputTexture, m_DenoiseBuffer0); cmd.SetComputeTextureParam(shadowFilter, firstDenoiseKernel, HDShaderIDs._DenoiseOutputTextureRW, m_DenoiseBuffer1); cmd.DispatchCompute(shadowFilter, firstDenoiseKernel, numTilesX, numTilesY, 1); } // Re-inject parameters for denoising cmd.SetComputeTextureParam(shadowFilter, secondDenoiseKernel, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetComputeTextureParam(shadowFilter, secondDenoiseKernel, HDShaderIDs._NormalBufferTexture, m_SharedRTManager.GetNormalBuffer()); cmd.SetComputeTextureParam(shadowFilter, secondDenoiseKernel, HDShaderIDs._AreaShadowTextureRW, m_AreaShadowTextureArray); // Second (and final) denoising pass cmd.SetComputeTextureParam(shadowFilter, secondDenoiseKernel, HDShaderIDs._DenoiseInputTexture, m_DenoiseBuffer1); cmd.DispatchCompute(shadowFilter, secondDenoiseKernel, numTilesX, numTilesY, 1); } } // If this is the right debug mode and we have at least one light, write the first shadow to the denoise texture HDRenderPipeline hdrp = (RenderPipelineManager.currentPipeline as HDRenderPipeline); if (FullScreenDebugMode.RaytracedAreaShadow == hdrp.m_CurrentDebugDisplaySettings.data.fullScreenDebugMode && numLights > 0) { int targetKernel = shadowFilter.FindKernel("WriteShadowTextureDebug"); cmd.SetComputeIntParam(shadowFilter, HDShaderIDs._RaytracingShadowSlot, 0); cmd.SetComputeTextureParam(shadowFilter, targetKernel, HDShaderIDs._AreaShadowTextureRW, m_AreaShadowTextureArray); cmd.SetComputeTextureParam(shadowFilter, targetKernel, HDShaderIDs._DenoiseOutputTextureRW, m_DenoiseBuffer0); cmd.DispatchCompute(shadowFilter, targetKernel, numTilesX, numTilesY, 1); hdrp.PushFullScreenDebugTexture(hdCamera, cmd, m_DenoiseBuffer0, FullScreenDebugMode.RaytracedAreaShadow); } return(true); }
// As we have our own default value, we need to initialize the light intensity correctly public static void InitDefaultHDAdditionalLightData(HDAdditionalLightData lightData) { // At first init we need to initialize correctly the default value lightData.ConvertPhysicalLightIntensityToLightIntensity(); }