public static PackedLightData ToPackedLightData(LightData data) { PackedLightData outData = default(PackedLightData); outData.packedData1 = data.positionRWS; outData.packedData1.w = (float)data.lightLayers + Epsilon; //防止1,转换为float变成0.999999999998; outData.packedData2 = data.forward; outData.packedData2.w = data.lightDimmer; outData.packedData3 = data.right; outData.packedData3.w = data.volumetricLightDimmer; outData.packedData4 = data.up; outData.packedData4.w = data.angleScale; outData.packedData5 = data.color; outData.packedData5.w = data.angleOffset; outData.packedData6 = data.shadowMaskSelector; outData.packedData7.x = (float)(int)data.lightType + Epsilon; //防止1,转换为float变成0.999999999998; outData.packedData7.y = data.range; outData.packedData7.z = data.rangeAttenuationScale; outData.packedData7.w = data.rangeAttenuationBias; outData.packedData8.x = (float)data.cookieIndex + Epsilon; //防止1,转换为float变成0.999999999998; outData.packedData8.y = (float)data.tileCookie + Epsilon; //防止1,转换为float变成0.999999999998; outData.packedData8.z = (float)data.shadowIndex + Epsilon; //防止1,转换为float变成0.999999999998; outData.packedData8.w = (float)data.contactShadowIndex + Epsilon; //防止1,转换为float变成0.999999999998; outData.packedData9.x = data.shadowDimmer; outData.packedData9.y = data.volumetricShadowDimmer; outData.packedData9.z = (float)data.nonLightMappedOnly + Epsilon; //防止1,转换为float变成0.999999999998; outData.packedData9.w = data.minRoughness; outData.packedData10 = data.size; outData.packedData10.z = data.diffuseDimmer; outData.packedData10.w = data.specularDimmer; //not use outData.packedData11 = Vector4.zero; outData.packedData12 = Vector4.zero; outData.packedData13 = Vector4.zero; outData.packedData14 = Vector4.zero; return(outData); }
public static LightData UnPackedLightDataToLightData(PackedLightData data) { LightData outData = default(LightData); outData.positionRWS = data.packedData1; outData.lightLayers = (uint)data.packedData1.w; outData.forward = data.packedData2; outData.lightDimmer = data.packedData2.w; outData.right = data.packedData3; outData.volumetricLightDimmer = data.packedData3.w; outData.up = data.packedData4; outData.angleScale = data.packedData4.w; outData.color = data.packedData5; outData.angleOffset = data.packedData5.w; outData.shadowMaskSelector = data.packedData6; outData.lightType = (GPULightType)(int)data.packedData7.x; outData.range = data.packedData7.y; outData.rangeAttenuationScale = data.packedData7.z; outData.rangeAttenuationBias = data.packedData7.w; outData.cookieIndex = (int)data.packedData8.x; outData.tileCookie = (int)data.packedData8.y; outData.shadowIndex = (int)data.packedData8.z; outData.contactShadowIndex = (int)data.packedData8.w; outData.shadowDimmer = data.packedData9.x; outData.volumetricShadowDimmer = data.packedData9.y; outData.nonLightMappedOnly = (int)data.packedData9.z; outData.minRoughness = data.packedData9.w; outData.size = data.packedData10; outData.diffuseDimmer = data.packedData10.z; outData.specularDimmer = data.packedData10.w; return(outData); }
void BuildLightData(CommandBuffer cmd, HDCamera hdCamera, List <HDAdditionalLightData> lightArray) { // Also we need to build the light list data if (m_LightDataGPUArray == null || m_LightDataGPUArray.count != lightArray.Count) { ResizeLightDataBuffer(lightArray.Count); } // Build the data for every light for (int lightIdx = 0; lightIdx < lightArray.Count; ++lightIdx) { var lightData = new LightData(); HDAdditionalLightData additionalLightData = lightArray[lightIdx]; // When the user deletes a light source in the editor, there is a single frame where the light is null before the collection of light in the scene is triggered // the workaround for this is simply to add an invalid light for that frame if (additionalLightData == null) { m_LightDataCPUArray[lightIdx] = lightData; continue; } Light light = additionalLightData.gameObject.GetComponent <Light>(); // Both of these positions are non-camera-relative. float distanceToCamera = (light.gameObject.transform.position - hdCamera.camera.transform.position).magnitude; float lightDistanceFade = HDUtils.ComputeLinearDistanceFade(distanceToCamera, additionalLightData.fadeDistance); bool contributesToLighting = ((additionalLightData.lightDimmer > 0) && (additionalLightData.affectDiffuse || additionalLightData.affectSpecular)) || (additionalLightData.volumetricDimmer > 0); contributesToLighting = contributesToLighting && (lightDistanceFade > 0); if (!contributesToLighting) { continue; } lightData.lightLayers = additionalLightData.GetLightLayers(); LightCategory lightCategory = LightCategory.Count; GPULightType gpuLightType = GPULightType.Point; GetLightGPUType(additionalLightData, light, ref gpuLightType, ref lightCategory); lightData.lightType = gpuLightType; lightData.positionRWS = light.gameObject.transform.position - hdCamera.camera.transform.position; bool applyRangeAttenuation = additionalLightData.applyRangeAttenuation && (gpuLightType != GPULightType.ProjectorBox); lightData.range = light.range; if (applyRangeAttenuation) { lightData.rangeAttenuationScale = 1.0f / (light.range * light.range); lightData.rangeAttenuationBias = 1.0f; if (lightData.lightType == GPULightType.Rectangle) { // Rect lights are currently a special case because they use the normalized // [0, 1] attenuation range rather than the regular [0, r] one. lightData.rangeAttenuationScale = 1.0f; } } else // Don't apply any attenuation but do a 'step' at range { // Solve f(x) = b - (a * x)^2 where x = (d/r)^2. // f(0) = huge -> b = huge. // f(1) = 0 -> huge - a^2 = 0 -> a = sqrt(huge). const float hugeValue = 16777216.0f; const float sqrtHuge = 4096.0f; lightData.rangeAttenuationScale = sqrtHuge / (light.range * light.range); lightData.rangeAttenuationBias = hugeValue; if (lightData.lightType == GPULightType.Rectangle) { // Rect lights are currently a special case because they use the normalized // [0, 1] attenuation range rather than the regular [0, r] one. lightData.rangeAttenuationScale = sqrtHuge; } } Color value = light.color.linear * light.intensity; if (additionalLightData.useColorTemperature) { value *= Mathf.CorrelatedColorTemperatureToRGB(light.colorTemperature); } lightData.color = new Vector3(value.r, value.g, value.b); lightData.forward = light.transform.forward; lightData.up = light.transform.up; lightData.right = light.transform.right; if (lightData.lightType == GPULightType.ProjectorBox) { // Rescale for cookies and windowing. lightData.right *= 2.0f / Mathf.Max(additionalLightData.shapeWidth, 0.001f); lightData.up *= 2.0f / Mathf.Max(additionalLightData.shapeHeight, 0.001f); } else if (lightData.lightType == GPULightType.ProjectorPyramid) { // Get width and height for the current frustum var spotAngle = light.spotAngle; float frustumWidth, frustumHeight; if (additionalLightData.aspectRatio >= 1.0f) { frustumHeight = 2.0f * Mathf.Tan(spotAngle * 0.5f * Mathf.Deg2Rad); frustumWidth = frustumHeight * additionalLightData.aspectRatio; } else { frustumWidth = 2.0f * Mathf.Tan(spotAngle * 0.5f * Mathf.Deg2Rad); frustumHeight = frustumWidth / additionalLightData.aspectRatio; } // Rescale for cookies and windowing. lightData.right *= 2.0f / frustumWidth; lightData.up *= 2.0f / frustumHeight; } if (lightData.lightType == GPULightType.Spot) { var spotAngle = light.spotAngle; var innerConePercent = additionalLightData.GetInnerSpotPercent01(); var cosSpotOuterHalfAngle = Mathf.Clamp(Mathf.Cos(spotAngle * 0.5f * Mathf.Deg2Rad), 0.0f, 1.0f); var sinSpotOuterHalfAngle = Mathf.Sqrt(1.0f - cosSpotOuterHalfAngle * cosSpotOuterHalfAngle); var cosSpotInnerHalfAngle = Mathf.Clamp(Mathf.Cos(spotAngle * 0.5f * innerConePercent * Mathf.Deg2Rad), 0.0f, 1.0f); // inner cone var val = Mathf.Max(0.0001f, (cosSpotInnerHalfAngle - cosSpotOuterHalfAngle)); lightData.angleScale = 1.0f / val; lightData.angleOffset = -cosSpotOuterHalfAngle * lightData.angleScale; // Rescale for cookies and windowing. float cotOuterHalfAngle = cosSpotOuterHalfAngle / sinSpotOuterHalfAngle; lightData.up *= cotOuterHalfAngle; lightData.right *= cotOuterHalfAngle; } else { // These are the neutral values allowing GetAngleAnttenuation in shader code to return 1.0 lightData.angleScale = 0.0f; lightData.angleOffset = 1.0f; } if (lightData.lightType != GPULightType.Directional && lightData.lightType != GPULightType.ProjectorBox) { // Store the squared radius of the light to simulate a fill light. lightData.size = new Vector2(additionalLightData.shapeRadius * additionalLightData.shapeRadius, 0); } if (lightData.lightType == GPULightType.Rectangle || lightData.lightType == GPULightType.Tube) { lightData.size = new Vector2(additionalLightData.shapeWidth, additionalLightData.shapeHeight); } lightData.lightDimmer = lightDistanceFade * (additionalLightData.lightDimmer); lightData.diffuseDimmer = lightDistanceFade * (additionalLightData.affectDiffuse ? additionalLightData.lightDimmer : 0); lightData.specularDimmer = lightDistanceFade * (additionalLightData.affectSpecular ? additionalLightData.lightDimmer * hdCamera.frameSettings.specularGlobalDimmer : 0); lightData.volumetricLightDimmer = lightDistanceFade * (additionalLightData.volumetricDimmer); lightData.contactShadowIndex = -1; lightData.cookieIndex = -1; lightData.shadowIndex = -1; lightData.rayTracedAreaShadowIndex = -1; if (light != null && light.cookie != null) { // TODO: add texture atlas support for cookie textures. switch (light.type) { case LightType.Spot: lightData.cookieIndex = m_LightLoop.cookieTexArray.FetchSlice(cmd, light.cookie); break; case LightType.Point: lightData.cookieIndex = m_LightLoop.cubeCookieTexArray.FetchSlice(cmd, light.cookie); break; } } else if (light.type == LightType.Spot && additionalLightData.spotLightShape != SpotLightShape.Cone) { // Projectors lights must always have a cookie texture. // As long as the cache is a texture array and not an atlas, the 4x4 white texture will be rescaled to 128 lightData.cookieIndex = m_LightLoop.cookieTexArray.FetchSlice(cmd, Texture2D.whiteTexture); } else if (lightData.lightType == GPULightType.Rectangle && additionalLightData.areaLightCookie != null) { lightData.cookieIndex = m_LightLoop.areaLightCookieManager.FetchSlice(cmd, additionalLightData.areaLightCookie); } { lightData.shadowDimmer = 1.0f; lightData.volumetricShadowDimmer = 1.0f; } { // fix up shadow information lightData.shadowIndex = additionalLightData.shadowIndex; } // Value of max smoothness is from artists point of view, need to convert from perceptual smoothness to roughness lightData.minRoughness = (1.0f - additionalLightData.maxSmoothness) * (1.0f - additionalLightData.maxSmoothness); // No usage for the shadow masks lightData.shadowMaskSelector = Vector4.zero; { // use -1 to say that we don't use shadow mask lightData.shadowMaskSelector.x = -1.0f; lightData.nonLightMappedOnly = 0; } // Set the data for this light m_LightDataCPUArray[lightIdx] = lightData; } //Push the data to the GPU m_LightDataGPUArray.SetData(m_LightDataCPUArray); }
public bool RenderAreaShadows(HDCamera hdCamera, CommandBuffer cmd, ScriptableRenderContext renderContext, uint 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 rtEnvironement = m_RaytracingManager.CurrentEnvironment(); RaytracingShader shadowRaytrace = m_PipelineAsset.renderPipelineResources.shaders.areaShadowsRaytracingRT; ComputeShader shadowsCompute = m_PipelineAsset.renderPipelineResources.shaders.areaShadowRaytracingCS; ComputeShader shadowFilter = m_PipelineAsset.renderPipelineResources.shaders.areaShadowFilterCS; // Make sure everything is valid bool invalidState = rtEnvironement == null || rtEnvironement.raytracedShadows == false || 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(rtEnvironement.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); // Grab the Filtering Kernels int copyTAAHistoryKernel = shadowFilter.FindKernel("AreaShadowCopyTAAHistory"); int applyTAAKernel = shadowFilter.FindKernel("AreaShadowApplyTAA"); int updateAnalyticHistory = shadowFilter.FindKernel("AreaAnalyticHistoryUpdate"); 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, rtEnvironement.rayBias); int numLights = m_LightLoop.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_LightLoop.m_lightList.lights[lightIdx].lightType != GPULightType.Rectangle || m_LightLoop.m_lightList.lights[lightIdx].rayTracedAreaShadowIndex == -1) { continue; } using (new ProfilingSample(cmd, "Raytrace Area Shadow", CustomSamplerId.RaytracingShadowIntegration.GetSampler())) { LightData currentLight = m_LightLoop.m_lightList.lights[lightIdx]; // 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 (rtEnvironement.splitIntegration) { 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_LightLoop.lightDatas); cmd.SetComputeIntParam(shadowsCompute, HDShaderIDs._RaytracingTargetAreaLight, lightIdx); cmd.SetComputeIntParam(shadowsCompute, HDShaderIDs._RaytracingNumSamples, rtEnvironement.shadowNumSamples); 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_LightLoop.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, m_RayGenShadowSingleName, HDShaderIDs._LightDatas, m_LightLoop.lightDatas); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShadowSingleName, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShadowSingleName, HDShaderIDs._RaytracedAreaShadowSample, m_DenoiseBuffer1); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShadowSingleName, HDShaderIDs._RaytracedAreaShadowIntegration, m_DenoiseBuffer0); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShadowSingleName, HDShaderIDs._RaytracingDirectionBuffer, m_RaytracingDirectionBuffer); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShadowSingleName, HDShaderIDs._RaytracingDistanceBuffer, m_RaytracingDistanceBuffer); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShadowSingleName, 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 < rtEnvironement.shadowNumSamples; ++sampleIndex) { shadowComputeKernel = shadowsCompute.FindKernel("RaytracingAreaShadowNewSample"); // This pass generates a new sample based on the initial pre-pass cmd.SetComputeBufferParam(shadowsCompute, shadowComputeKernel, HDShaderIDs._LightDatas, m_LightLoop.lightDatas); cmd.SetComputeIntParam(shadowsCompute, HDShaderIDs._RaytracingTargetAreaLight, lightIdx); cmd.SetComputeIntParam(shadowsCompute, HDShaderIDs._RaytracingNumSamples, rtEnvironement.shadowNumSamples); 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_LightLoop.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, m_RayGenShadowSingleName, HDShaderIDs._LightDatas, m_LightLoop.lightDatas); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShadowSingleName, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShadowSingleName, HDShaderIDs._RaytracedAreaShadowSample, m_DenoiseBuffer1); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShadowSingleName, HDShaderIDs._RaytracedAreaShadowIntegration, m_DenoiseBuffer0); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShadowSingleName, HDShaderIDs._RaytracingDirectionBuffer, m_RaytracingDirectionBuffer); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShadowSingleName, HDShaderIDs._RaytracingDistanceBuffer, m_RaytracingDistanceBuffer); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShadowSingleName, 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, m_RayGenShaderName, HDShaderIDs._LightDatas, m_LightLoop.lightDatas); cmd.SetRaytracingIntParam(shadowRaytrace, HDShaderIDs._RaytracingTargetAreaLight, lightIdx); cmd.SetRaytracingIntParam(shadowRaytrace, HDShaderIDs._RaytracingNumSamples, rtEnvironement.shadowNumSamples); cmd.SetRaytracingMatrixParam(shadowRaytrace, HDShaderIDs._RaytracingAreaWorldToLocal, worldToLocalArea); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShaderName, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShaderName, HDShaderIDs._NormalBufferTexture, m_SharedRTManager.GetNormalBuffer()); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShaderName, HDShaderIDs._GBufferTexture[0], m_GbufferManager.GetBuffer(0)); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShaderName, HDShaderIDs._GBufferTexture[1], m_GbufferManager.GetBuffer(1)); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShaderName, HDShaderIDs._GBufferTexture[2], m_GbufferManager.GetBuffer(2)); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShaderName, HDShaderIDs._GBufferTexture[3], m_GbufferManager.GetBuffer(3)); cmd.SetRaytracingIntParam(shadowRaytrace, HDShaderIDs._RayCountEnabled, m_RaytracingManager.rayCountManager.RayCountIsEnabled()); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShaderName, HDShaderIDs._RayCountTexture, m_RaytracingManager.rayCountManager.rayCountTexture); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShaderName, HDShaderIDs._AreaCookieTextures, m_LightLoop.areaLightCookieManager.GetTexCache()); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShaderName, HDShaderIDs._AnalyticProbBuffer, m_AnalyticProbBuffer); cmd.SetRaytracingTextureParam(shadowRaytrace, m_RayGenShaderName, 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, rtEnvironement.shadowFilterRadius); cmd.SetComputeIntParam(shadowFilter, HDShaderIDs._RaytracingShadowSlot, m_LightLoop.m_lightList.lights[lightIdx].rayTracedAreaShadowIndex); // Given that we can't read and write into the same buffer, we store the current frame value and the history in the denoisebuffer1 cmd.SetComputeTextureParam(shadowFilter, copyTAAHistoryKernel, HDShaderIDs._AreaShadowHistoryRW, areaShadowHistoryArray); cmd.SetComputeTextureParam(shadowFilter, copyTAAHistoryKernel, HDShaderIDs._DenoiseInputTexture, m_DenoiseBuffer0); cmd.SetComputeTextureParam(shadowFilter, copyTAAHistoryKernel, HDShaderIDs._DenoiseOutputTextureRW, m_DenoiseBuffer1); cmd.DispatchCompute(shadowFilter, copyTAAHistoryKernel, numTilesX, numTilesY, 1); // 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._ScreenToTargetScaleHistory, historyScale); cmd.SetComputeTextureParam(shadowFilter, applyTAAKernel, HDShaderIDs._AnalyticProbBuffer, m_AnalyticProbBuffer); cmd.SetComputeTextureParam(shadowFilter, applyTAAKernel, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetComputeTextureParam(shadowFilter, applyTAAKernel, HDShaderIDs._AnalyticHistoryBuffer, areaAnalyticHistoryArray); cmd.SetComputeTextureParam(shadowFilter, applyTAAKernel, HDShaderIDs._DenoiseInputTexture, m_DenoiseBuffer1); cmd.SetComputeTextureParam(shadowFilter, applyTAAKernel, HDShaderIDs._DenoiseOutputTextureRW, m_DenoiseBuffer0); cmd.SetComputeTextureParam(shadowFilter, applyTAAKernel, HDShaderIDs._AreaShadowHistoryRW, areaShadowHistoryArray); cmd.DispatchCompute(shadowFilter, applyTAAKernel, numTilesX, numTilesY, 1); // Now that we do not need it anymore, update the anyltic history cmd.SetComputeTextureParam(shadowFilter, updateAnalyticHistory, HDShaderIDs._AnalyticHistoryBuffer, areaAnalyticHistoryArray); cmd.SetComputeTextureParam(shadowFilter, updateAnalyticHistory, HDShaderIDs._AnalyticProbBuffer, m_AnalyticProbBuffer); cmd.DispatchCompute(shadowFilter, updateAnalyticHistory, numTilesX, numTilesY, 1); if (rtEnvironement.shadowFilterRadius > 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_DenoiseBuffer0); cmd.SetComputeTextureParam(shadowFilter, estimateNoiseKernel, HDShaderIDs._DenoiseOutputTextureRW, m_DenoiseBuffer1); 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_DenoiseBuffer1); cmd.SetComputeTextureParam(shadowFilter, firstDenoiseKernel, HDShaderIDs._DenoiseOutputTextureRW, m_DenoiseBuffer0); cmd.DispatchCompute(shadowFilter, firstDenoiseKernel, numTilesX, numTilesY, 1); } // Reinject 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_DenoiseBuffer0); 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); }
public bool RenderAreaShadows(HDCamera hdCamera, CommandBuffer cmd, ScriptableRenderContext renderContext, uint 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 rtEnvironement = m_RaytracingManager.CurrentEnvironment(); RaytracingShader shadowsShader = m_PipelineAsset.renderPipelineResources.shaders.shadowsRaytracing; ComputeShader bilateralFilter = m_PipelineAsset.renderPipelineResources.shaders.areaBillateralFilterCS; bool invalidState = rtEnvironement == null || !rtEnvironement.raytracedShadows || hdCamera.frameSettings.litShaderMode != LitShaderMode.Deferred || shadowsShader == null || bilateralFilter == 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 acceleration structure for the target camera RaytracingAccelerationStructure accelerationStructure = m_RaytracingManager.RequestAccelerationStructure(rtEnvironement.shadowLayerMask); // Define the shader pass to use for the reflection pass cmd.SetRaytracingShaderPass(shadowsShader, "VisibilityDXR"); // Set the acceleration structure for the pass cmd.SetRaytracingAccelerationStructure(shadowsShader, HDShaderIDs._RaytracingAccelerationStructureName, accelerationStructure); // Inject the ray-tracing sampling data cmd.SetRaytracingTextureParam(shadowsShader, m_RayGenShaderName, HDShaderIDs._OwenScrambledTexture, m_PipelineResources.textures.owenScrambledTex); cmd.SetRaytracingTextureParam(shadowsShader, m_RayGenShaderName, HDShaderIDs._ScramblingTexture, m_PipelineResources.textures.scramblingTex); int frameIndex = hdCamera.IsTAAEnabled() ? hdCamera.taaFrameIndex : (int)frameCount % 8; cmd.SetGlobalInt(HDShaderIDs._RaytracingFrameIndex, frameIndex); // Inject the ray generation data cmd.SetGlobalFloat(HDShaderIDs._RaytracingRayBias, rtEnvironement.rayBias); int numLights = m_LightLoop.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_LightLoop.m_lightList.lights[lightIdx].lightType != GPULightType.Rectangle || m_LightLoop.m_lightList.lights[lightIdx].rayTracedAreaShadowIndex == -1) { continue; } using (new ProfilingSample(cmd, "Raytrace Area Shadow", CustomSamplerId.RaytracingShadowIntegration.GetSampler())) { LightData currentLight = m_LightLoop.m_lightList.lights[lightIdx]; // 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; // Inject the light data cmd.SetRaytracingBufferParam(shadowsShader, m_RayGenShaderName, HDShaderIDs._LightDatas, m_LightLoop.lightDatas); cmd.SetRaytracingIntParam(shadowsShader, HDShaderIDs._RaytracingTargetAreaLight, lightIdx); cmd.SetRaytracingIntParam(shadowsShader, HDShaderIDs._RaytracingNumSamples, rtEnvironement.shadowNumSamples); cmd.SetRaytracingMatrixParam(shadowsShader, HDShaderIDs._RaytracingAreaWorldToLocal, worldToLocalArea); // Set the data for the ray generation cmd.SetRaytracingTextureParam(shadowsShader, m_RayGenShaderName, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetRaytracingTextureParam(shadowsShader, m_RayGenShaderName, HDShaderIDs._NormalBufferTexture, m_SharedRTManager.GetNormalBuffer()); cmd.SetRaytracingTextureParam(shadowsShader, m_RayGenShaderName, HDShaderIDs._GBufferTexture[0], m_GbufferManager.GetBuffer(0)); cmd.SetRaytracingTextureParam(shadowsShader, m_RayGenShaderName, HDShaderIDs._GBufferTexture[1], m_GbufferManager.GetBuffer(1)); cmd.SetRaytracingTextureParam(shadowsShader, m_RayGenShaderName, HDShaderIDs._GBufferTexture[2], m_GbufferManager.GetBuffer(2)); cmd.SetRaytracingTextureParam(shadowsShader, m_RayGenShaderName, HDShaderIDs._GBufferTexture[3], m_GbufferManager.GetBuffer(3)); cmd.SetRaytracingIntParam(shadowsShader, HDShaderIDs._RayCountEnabled, m_RaytracingManager.rayCountManager.RayCountIsEnabled()); cmd.SetRaytracingTextureParam(shadowsShader, m_RayGenShaderName, HDShaderIDs._RayCountTexture, m_RaytracingManager.rayCountManager.rayCountTexture); // Set the output textures cmd.SetRaytracingTextureParam(shadowsShader, m_RayGenShaderName, _SNBuffer, m_SNBuffer); cmd.SetRaytracingTextureParam(shadowsShader, m_RayGenShaderName, _UNBuffer, m_UNBuffer); cmd.SetRaytracingTextureParam(shadowsShader, m_RayGenShaderName, _UBuffer, m_UBuffer); // Bind the area cookie textures to the raytracing shader cmd.SetRaytracingTextureParam(shadowsShader, m_RayGenShaderName, HDShaderIDs._AreaCookieTextures, m_LightLoop.areaLightCookieManager.GetTexCache()); // Run the shadow evaluation cmd.DispatchRays(shadowsShader, m_RayGenShaderName, (uint)hdCamera.actualWidth, (uint)hdCamera.actualHeight, 1); } using (new ProfilingSample(cmd, "Combine Area Shadow", CustomSamplerId.RaytracingShadowCombination.GetSampler())) { // Fetch the filter kernel m_KernelFilter = bilateralFilter.FindKernel("AreaBilateralShadow"); // Inject all the parameters for the compute cmd.SetComputeTextureParam(bilateralFilter, m_KernelFilter, _SNBuffer, m_SNBuffer); cmd.SetComputeTextureParam(bilateralFilter, m_KernelFilter, _UNBuffer, m_UNBuffer); cmd.SetComputeTextureParam(bilateralFilter, m_KernelFilter, HDShaderIDs._DepthTexture, m_SharedRTManager.GetDepthStencilBuffer()); cmd.SetComputeTextureParam(bilateralFilter, m_KernelFilter, HDShaderIDs._NormalBufferTexture, m_SharedRTManager.GetNormalBuffer()); cmd.SetComputeIntParam(bilateralFilter, _DenoiseRadius, rtEnvironement.shadowFilterRadius); cmd.SetComputeFloatParam(bilateralFilter, _GaussianSigma, rtEnvironement.shadowFilterSigma); cmd.SetComputeIntParam(bilateralFilter, HDShaderIDs._RaytracingShadowSlot, m_LightLoop.m_lightList.lights[lightIdx].rayTracedAreaShadowIndex); // Set the output slot cmd.SetComputeTextureParam(bilateralFilter, m_KernelFilter, HDShaderIDs._AreaShadowTextureRW, m_AreaShadowTextureArray); // Texture dimensions int texWidth = m_AreaShadowTextureArray.rt.width; int texHeight = m_AreaShadowTextureArray.rt.width; // Evaluate the dispatch parameters int areaTileSize = 8; int numTilesX = (texWidth + (areaTileSize - 1)) / areaTileSize; int numTilesY = (texHeight + (areaTileSize - 1)) / areaTileSize; // Compute the texture cmd.DispatchCompute(bilateralFilter, m_KernelFilter, numTilesX, numTilesY, 1); } } return(true); }