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 Experimental.Rendering.RayTracingAccelerationStructure(); // We need to define the maximal number of meshes for our geometries int maxNumSubMeshes = 1; // 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) { Renderer currentRenderer = currentLOD.renderers[rendererIdx]; // Add this fella to the renderer list subScene.targetRenderers.Add(currentRenderer); // Also, we need to contribute to the maximal number of sub-meshes MeshFilter currentFilter = currentRenderer.GetComponent <MeshFilter>(); if (currentFilter != null && currentFilter.sharedMesh != null) { maxNumSubMeshes = Mathf.Max(maxNumSubMeshes, currentFilter.sharedMesh.subMeshCount); } } } } // 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); } } } // 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 sub-meshes 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; // We need to build the instance flag for this renderer uint instanceFlag = 0x00; // Incorporate the shadow casting flag instanceFlag |= ((currentRenderer.shadowCastingMode == ShadowCastingMode.On) ? (uint)(1 << 2) : 0x00); 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)(1 << 1) : (uint)(1 << 0); // 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.lights = new HDRayTracingLights(); subScene.lights.hdLightArray = new List <HDAdditionalLightData>(); subScene.lights.hdDirectionalLightArray = new List <HDAdditionalLightData>(); // fetch all the 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.lights.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.lights.hdLightArray.AddRange(pointLights); subScene.lights.hdLightArray.AddRange(lineLights); subScene.lights.hdLightArray.AddRange(rectLights); // Fetch all the reflection probes in the scene subScene.lights.reflectionProbeArray = new List <HDProbe>(); HDAdditionalReflectionData[] reflectionProbeArray = UnityEngine.GameObject.FindObjectsOfType <HDAdditionalReflectionData>(); for (int reflIdx = 0; reflIdx < reflectionProbeArray.Length; ++reflIdx) { HDAdditionalReflectionData reflectionProbe = reflectionProbeArray[reflIdx]; // Add it to the list if enabled if (reflectionProbe.enabled) { subScene.lights.reflectionProbeArray.Add(reflectionProbe); } } // Build the light cluster subScene.lightCluster = new HDRaytracingLightCluster(); subScene.lightCluster.Initialize(m_Resources, m_RTResources, this, m_SharedRTManager, m_RenderPipeline); // Mark this sub-scene as valid subScene.valid = true; } else { subScene.valid = false; } }
internal void BuildRayTracingAccelerationStructure(HDCamera hdCamera) { // Clear all the per frame-data m_RayTracingRendererReference.Clear(); m_RayTracingLights.hdDirectionalLightArray.Clear(); m_RayTracingLights.hdPointLightArray.Clear(); m_RayTracingLights.hdLineLightArray.Clear(); m_RayTracingLights.hdRectLightArray.Clear(); m_RayTracingLights.hdLightArray.Clear(); m_RayTracingLights.reflectionProbeArray.Clear(); m_RayTracingLights.lightCount = 0; m_CurrentRAS.Dispose(); m_CurrentRAS = new RayTracingAccelerationStructure(); m_ValidRayTracingState = false; m_ValidRayTracingCluster = false; m_ValidRayTracingClusterCulling = false; m_RayTracedShadowsRequired = false; m_RayTracedContactShadowsRequired = false; // If the camera does not have a ray tracing frame setting // or it is a preview camera (due to the fact that the sphere does not exist as a game object we can't create the RTAS) // we do not want to build a RTAS if (!hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing) || hdCamera.camera.cameraType == CameraType.Preview) { return; } // We only support ray traced shadows if the camera supports ray traced shadows bool screenSpaceShadowsSupported = hdCamera.frameSettings.IsEnabled(FrameSettingsField.ScreenSpaceShadows); // fetch all the lights in the scene HDAdditionalLightData[] hdLightArray = UnityEngine.GameObject.FindObjectsOfType <HDAdditionalLightData>(); for (int lightIdx = 0; lightIdx < hdLightArray.Length; ++lightIdx) { HDAdditionalLightData hdLight = hdLightArray[lightIdx]; if (hdLight.enabled) { // Check if there is a ray traced shadow in the scene m_RayTracedShadowsRequired |= (hdLight.useRayTracedShadows && screenSpaceShadowsSupported); m_RayTracedContactShadowsRequired |= (hdLight.useContactShadow.@override && hdLight.rayTraceContactShadow); switch (hdLight.type) { case HDLightType.Directional: m_RayTracingLights.hdDirectionalLightArray.Add(hdLight); break; case HDLightType.Point: case HDLightType.Spot: m_RayTracingLights.hdPointLightArray.Add(hdLight); break; case HDLightType.Area: switch (hdLight.areaLightShape) { case AreaLightShape.Rectangle: m_RayTracingLights.hdRectLightArray.Add(hdLight); break; case AreaLightShape.Tube: m_RayTracingLights.hdLineLightArray.Add(hdLight); break; //TODO: case AreaLightShape.Disc: } break; } } } // Aggregate the shadow requirement bool rayTracedShadows = m_RayTracedShadowsRequired || m_RayTracedContactShadowsRequired; m_RayTracingLights.hdLightArray.AddRange(m_RayTracingLights.hdPointLightArray); m_RayTracingLights.hdLightArray.AddRange(m_RayTracingLights.hdLineLightArray); m_RayTracingLights.hdLightArray.AddRange(m_RayTracingLights.hdRectLightArray); HDAdditionalReflectionData[] reflectionProbeArray = UnityEngine.GameObject.FindObjectsOfType <HDAdditionalReflectionData>(); for (int reflIdx = 0; reflIdx < reflectionProbeArray.Length; ++reflIdx) { HDAdditionalReflectionData reflectionProbe = reflectionProbeArray[reflIdx]; // Add it to the list if enabled if (reflectionProbe.enabled) { m_RayTracingLights.reflectionProbeArray.Add(reflectionProbe); } } m_RayTracingLights.lightCount = m_RayTracingLights.hdPointLightArray.Count + m_RayTracingLights.hdLineLightArray.Count + m_RayTracingLights.hdRectLightArray.Count + m_RayTracingLights.reflectionProbeArray.Count; AmbientOcclusion aoSettings = hdCamera.volumeStack.GetComponent <AmbientOcclusion>(); bool rtAOEnabled = aoSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSAO); ScreenSpaceReflection reflSettings = hdCamera.volumeStack.GetComponent <ScreenSpaceReflection>(); bool rtREnabled = reflSettings.enabled.value && reflSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSR); GlobalIllumination giSettings = hdCamera.volumeStack.GetComponent <GlobalIllumination>(); bool rtGIEnabled = giSettings.enable.value && giSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SSGI); RecursiveRendering recursiveSettings = hdCamera.volumeStack.GetComponent <RecursiveRendering>(); bool rrEnabled = recursiveSettings.enable.value; SubSurfaceScattering sssSettings = hdCamera.volumeStack.GetComponent <SubSurfaceScattering>(); bool rtSSSEnabled = sssSettings.rayTracing.value && hdCamera.frameSettings.IsEnabled(FrameSettingsField.SubsurfaceScattering); PathTracing pathTracingSettings = hdCamera.volumeStack.GetComponent <PathTracing>(); bool ptEnabled = pathTracingSettings.enable.value; // We need to check if we should be building the ray tracing acceleration structure (if required by any effect) bool rayTracingRequired = rtAOEnabled || rtREnabled || rtGIEnabled || rrEnabled || rtSSSEnabled || ptEnabled || rayTracedShadows; if (!rayTracingRequired) { return; } // We need to process the emissive meshes of the rectangular area lights for (var i = 0; i < m_RayTracingLights.hdRectLightArray.Count; i++) { // Fetch the current renderer of the rectangular area light (if any) MeshRenderer currentRenderer = m_RayTracingLights.hdRectLightArray[i].emissiveMeshRenderer; // If there is none it means that there is no emissive mesh for this light if (currentRenderer == null) { continue; } // This objects should be included into the RAS AddInstanceToRAS(currentRenderer, rayTracedShadows, rtAOEnabled, aoSettings.layerMask.value, rtREnabled, reflSettings.layerMask.value, rtGIEnabled, giSettings.layerMask.value, rrEnabled, recursiveSettings.layerMask.value, ptEnabled, pathTracingSettings.layerMask.value); } int matCount = m_MaterialCRCs.Count; 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 lod0, we do not have defined way to select the right LOD at the moment if (lodIdx == 0) { for (int rendererIdx = 0; rendererIdx < currentLOD.renderers.Length; ++rendererIdx) { // Fetch the renderer that we are interested in Renderer currentRenderer = currentLOD.renderers[rendererIdx]; // This objects should but included into the RAS AddInstanceToRAS(currentRenderer, rayTracedShadows, aoSettings.rayTracing.value, aoSettings.layerMask.value, reflSettings.rayTracing.value, reflSettings.layerMask.value, giSettings.rayTracing.value, giSettings.layerMask.value, recursiveSettings.enable.value, recursiveSettings.layerMask.value, pathTracingSettings.enable.value, pathTracingSettings.layerMask.value); } } // Add them to the processed set so that they are not taken into account when processing all the renderers for (int rendererIdx = 0; rendererIdx < currentLOD.renderers.Length; ++rendererIdx) { Renderer currentRenderer = currentLOD.renderers[rendererIdx]; // Add this fella to the renderer list // Unfortunately, we need to check that this renderer was not already pushed into the list (happens if the user uses the same mesh renderer // for two LODs) if (!m_RayTracingRendererReference.ContainsKey(currentRenderer.GetInstanceID())) { m_RayTracingRendererReference.Add(currentRenderer.GetInstanceID(), 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, just skip it if (m_RayTracingRendererReference.ContainsKey(currentRenderer.GetInstanceID())) { continue; } // Does this object have a reflection probe component? if yes we do not want to have it in the acceleration structure if (gameObject.TryGetComponent <ReflectionProbe>(out reflectionProbe)) { continue; } // This objects should be included into the RAS AddInstanceToRAS(currentRenderer, rayTracedShadows, aoSettings.rayTracing.value, aoSettings.layerMask.value, reflSettings.rayTracing.value, reflSettings.layerMask.value, giSettings.rayTracing.value, giSettings.layerMask.value, recursiveSettings.enable.value, recursiveSettings.layerMask.value, pathTracingSettings.enable.value, pathTracingSettings.layerMask.value); } // Check if the amount of materials being tracked has changed m_MaterialsDirty |= (matCount != m_MaterialCRCs.Count); // build the acceleration structure m_CurrentRAS.Build(); // tag the structures as valid m_ValidRayTracingState = true; }
public void RenderLightVolumes(RenderGraph renderGraph, LightingDebugSettings lightingDebugSettings, TextureHandle destination, TextureHandle depthBuffer, CullingResults cullResults, HDCamera hdCamera) { using (var builder = renderGraph.AddRenderPass <RenderLightVolumesPassData>("LightVolumes", out var passData)) { bool lightOverlapEnabled = CoreUtils.IsLightOverlapDebugEnabled(hdCamera.camera); bool useColorAndEdge = lightingDebugSettings.lightVolumeDebugByCategory == LightVolumeDebug.ColorAndEdge || lightOverlapEnabled; passData.hdCamera = hdCamera; passData.cullResults = cullResults; passData.debugLightVolumeMaterial = m_DebugLightVolumeMaterial; passData.debugLightVolumeCS = m_DebugLightVolumeCompute; passData.debugLightVolumeKernel = useColorAndEdge ? m_DebugLightVolumeColorsKernel : m_DebugLightVolumeGradientKernel; passData.maxDebugLightCount = (int)lightingDebugSettings.maxDebugLightCount; passData.borderRadius = lightOverlapEnabled ? 0.5f : 1f; passData.colorGradientTexture = m_ColorGradientTexture; passData.lightOverlapEnabled = lightOverlapEnabled; passData.lightCountBuffer = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R32_SFloat, clearBuffer = true, clearColor = Color.black, name = "LightVolumeCount" }); passData.colorAccumulationBuffer = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R16G16B16A16_SFloat, clearBuffer = true, clearColor = Color.black, name = "LightVolumeColorAccumulation" }); passData.debugLightVolumesTexture = builder.CreateTransientTexture(new TextureDesc(Vector2.one, true, true) { colorFormat = GraphicsFormat.R16G16B16A16_SFloat, clearBuffer = true, clearColor = Color.black, enableRandomWrite = true, name = "LightVolumeDebugLightVolumesTexture" }); passData.depthBuffer = builder.UseDepthBuffer(depthBuffer, DepthAccess.ReadWrite); passData.destination = builder.WriteTexture(destination); builder.SetRenderFunc( (RenderLightVolumesPassData data, RenderGraphContext ctx) => { var mpb = ctx.renderGraphPool.GetTempMaterialPropertyBlock(); RenderTargetIdentifier[] mrt = ctx.renderGraphPool.GetTempArray <RenderTargetIdentifier>(2); mrt[0] = data.lightCountBuffer; mrt[1] = data.colorAccumulationBuffer; if (data.lightOverlapEnabled) { // We only need the accumulation buffer, not the color (we only display the outline of the light shape in this mode). CoreUtils.SetRenderTarget(ctx.cmd, mrt[0], depthBuffer); // The cull result doesn't contains overlapping lights so we use a custom list foreach (var overlappingHDLight in HDAdditionalLightData.s_overlappingHDLights) { RenderLightVolume(ctx.cmd, data.debugLightVolumeMaterial, overlappingHDLight, overlappingHDLight.legacyLight, mpb); } } else { // Set the render target array CoreUtils.SetRenderTarget(ctx.cmd, mrt, depthBuffer); // First of all let's do the regions for the light sources (we only support Punctual and Area) int numLights = data.cullResults.visibleLights.Length; for (int lightIdx = 0; lightIdx < numLights; ++lightIdx) { // Let's build the light's bounding sphere matrix Light currentLegacyLight = data.cullResults.visibleLights[lightIdx].light; if (currentLegacyLight == null) { continue; } HDAdditionalLightData currentHDRLight = currentLegacyLight.GetComponent <HDAdditionalLightData>(); if (currentHDRLight == null) { continue; } RenderLightVolume(ctx.cmd, data.debugLightVolumeMaterial, currentHDRLight, currentLegacyLight, mpb); } // When we enable the light overlap mode we hide probes as they can't be baked in shadow masks if (!data.lightOverlapEnabled) { // Now let's do the same but for reflection probes int numProbes = data.cullResults.visibleReflectionProbes.Length; for (int probeIdx = 0; probeIdx < numProbes; ++probeIdx) { // Let's build the light's bounding sphere matrix ReflectionProbe currentLegacyProbe = data.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); ctx.cmd.DrawMesh(targetMesh, positionMat, data.debugLightVolumeMaterial, 0, 0, m_MaterialProperty); } } } // Set the input params for the compute ctx.cmd.SetComputeTextureParam(data.debugLightVolumeCS, data.debugLightVolumeKernel, _DebugLightCountBufferShaderID, data.lightCountBuffer); ctx.cmd.SetComputeTextureParam(data.debugLightVolumeCS, data.debugLightVolumeKernel, _DebugColorAccumulationBufferShaderID, data.colorAccumulationBuffer); ctx.cmd.SetComputeTextureParam(data.debugLightVolumeCS, data.debugLightVolumeKernel, _DebugLightVolumesTextureShaderID, data.debugLightVolumesTexture); ctx.cmd.SetComputeTextureParam(data.debugLightVolumeCS, data.debugLightVolumeKernel, _ColorGradientTextureShaderID, data.colorGradientTexture); ctx.cmd.SetComputeIntParam(data.debugLightVolumeCS, _MaxDebugLightCountShaderID, data.maxDebugLightCount); ctx.cmd.SetComputeFloatParam(data.debugLightVolumeCS, _BorderRadiusShaderID, data.borderRadius); // Texture dimensions int texWidth = data.hdCamera.actualWidth; int texHeight = data.hdCamera.actualHeight; // Dispatch the compute int lightVolumesTileSize = 8; int numTilesX = (texWidth + (lightVolumesTileSize - 1)) / lightVolumesTileSize; int numTilesY = (texHeight + (lightVolumesTileSize - 1)) / lightVolumesTileSize; ctx.cmd.DispatchCompute(data.debugLightVolumeCS, data.debugLightVolumeKernel, numTilesX, numTilesY, data.hdCamera.viewCount); // Blit this into the camera target CoreUtils.SetRenderTarget(ctx.cmd, destination); mpb.SetTexture(HDShaderIDs._BlitTexture, data.debugLightVolumesTexture); ctx.cmd.DrawProcedural(Matrix4x4.identity, data.debugLightVolumeMaterial, 1, MeshTopology.Triangles, 3, 1, mpb); }); } }
internal void BuildRayTracingAccelerationStructure(HDCamera hdCamera) { // Clear all the per frame-data m_RayTracingRendererReference.Clear(); m_RayTracingLights.hdDirectionalLightArray.Clear(); m_RayTracingLights.hdPointLightArray.Clear(); m_RayTracingLights.hdLineLightArray.Clear(); m_RayTracingLights.hdRectLightArray.Clear(); m_RayTracingLights.hdLightArray.Clear(); m_RayTracingLights.reflectionProbeArray.Clear(); m_RayTracingLights.lightCount = 0; m_CurrentRAS.Dispose(); m_CurrentRAS = new RayTracingAccelerationStructure(); m_ValidRayTracingState = false; m_ValidRayTracingCluster = false; bool rayTracedShadow = false; // fetch all the lights in the scene HDAdditionalLightData[] hdLightArray = UnityEngine.GameObject.FindObjectsOfType <HDAdditionalLightData>(); for (int lightIdx = 0; lightIdx < hdLightArray.Length; ++lightIdx) { HDAdditionalLightData hdLight = hdLightArray[lightIdx]; if (hdLight.enabled) { // Check if there is a ray traced shadow in the scene rayTracedShadow |= (hdLight.useRayTracedShadows || (hdLight.useContactShadow.@override && hdLight.rayTraceContactShadow)); switch (hdLight.type) { case HDLightType.Directional: m_RayTracingLights.hdDirectionalLightArray.Add(hdLight); break; case HDLightType.Point: case HDLightType.Spot: m_RayTracingLights.hdPointLightArray.Add(hdLight); break; case HDLightType.Area: switch (hdLight.areaLightShape) { case AreaLightShape.Rectangle: m_RayTracingLights.hdRectLightArray.Add(hdLight); break; case AreaLightShape.Tube: m_RayTracingLights.hdLineLightArray.Add(hdLight); break; //TODO: case AreaLightShape.Disc: } break; } } } m_RayTracingLights.hdLightArray.AddRange(m_RayTracingLights.hdPointLightArray); m_RayTracingLights.hdLightArray.AddRange(m_RayTracingLights.hdLineLightArray); m_RayTracingLights.hdLightArray.AddRange(m_RayTracingLights.hdRectLightArray); HDAdditionalReflectionData[] reflectionProbeArray = UnityEngine.GameObject.FindObjectsOfType <HDAdditionalReflectionData>(); for (int reflIdx = 0; reflIdx < reflectionProbeArray.Length; ++reflIdx) { HDAdditionalReflectionData reflectionProbe = reflectionProbeArray[reflIdx]; // Add it to the list if enabled if (reflectionProbe.enabled) { m_RayTracingLights.reflectionProbeArray.Add(reflectionProbe); } } m_RayTracingLights.lightCount = m_RayTracingLights.hdPointLightArray.Count + m_RayTracingLights.hdLineLightArray.Count + m_RayTracingLights.hdRectLightArray.Count + m_RayTracingLights.reflectionProbeArray.Count; AmbientOcclusion aoSettings = hdCamera.volumeStack.GetComponent <AmbientOcclusion>(); ScreenSpaceReflection reflSettings = hdCamera.volumeStack.GetComponent <ScreenSpaceReflection>(); GlobalIllumination giSettings = hdCamera.volumeStack.GetComponent <GlobalIllumination>(); RecursiveRendering recursiveSettings = hdCamera.volumeStack.GetComponent <RecursiveRendering>(); PathTracing pathTracingSettings = hdCamera.volumeStack.GetComponent <PathTracing>(); 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 lod0, we do not have defined way to select the right LOD at the moment if (lodIdx == 0) { for (int rendererIdx = 0; rendererIdx < currentLOD.renderers.Length; ++rendererIdx) { // Fetch the renderer that we are interested in Renderer currentRenderer = currentLOD.renderers[rendererIdx]; // This objects should but included into the RAS AddInstanceToRAS(currentRenderer, rayTracedShadow, aoSettings.rayTracing.value, aoSettings.layerMask.value, reflSettings.rayTracing.value, reflSettings.layerMask.value, giSettings.rayTracing.value, giSettings.layerMask.value, recursiveSettings.enable.value, recursiveSettings.layerMask.value, pathTracingSettings.enable.value, pathTracingSettings.layerMask.value); } } // Add them to the processed set so that they are not taken into account when processing all the renderers for (int rendererIdx = 0; rendererIdx < currentLOD.renderers.Length; ++rendererIdx) { Renderer currentRenderer = currentLOD.renderers[rendererIdx]; // Add this fella to the renderer list m_RayTracingRendererReference.Add(currentRenderer.GetInstanceID(), 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, just skip it if (m_RayTracingRendererReference.ContainsKey(currentRenderer.GetInstanceID())) { continue; } // Does this object have a reflection probe component? if yes we do not want to have it in the acceleration structure if (gameObject.TryGetComponent <ReflectionProbe>(out reflectionProbe)) { continue; } // This objects should but included into the RAS AddInstanceToRAS(currentRenderer, rayTracedShadow, aoSettings.rayTracing.value, aoSettings.layerMask.value, reflSettings.rayTracing.value, reflSettings.layerMask.value, giSettings.rayTracing.value, giSettings.layerMask.value, recursiveSettings.enable.value, recursiveSettings.layerMask.value, pathTracingSettings.enable.value, pathTracingSettings.layerMask.value); } // build the acceleration structure m_CurrentRAS.Build(); // tag the structures as valid m_ValidRayTracingState = true; }
void CollectLightsForRayTracing(HDCamera hdCamera, ref bool transformDirty) { // fetch all the lights in the scene HDLightRenderDatabase lightEntities = HDLightRenderDatabase.instance; for (int lightIdx = 0; lightIdx < lightEntities.lightCount; ++lightIdx) { HDLightRenderEntity lightRenderEntity = lightEntities.lightEntities[lightIdx]; HDAdditionalLightData hdLight = lightEntities.hdAdditionalLightData[lightIdx]; if (hdLight != null && hdLight.enabled && hdLight != HDUtils.s_DefaultHDAdditionalLightData) { // Flag that needs to be overriden by the light and tells us if the light will need the RTAS bool hasRayTracedShadows = false; // Indicates that a transform has changed in our scene (mesh or light) transformDirty |= hdLight.transform.hasChanged; hdLight.transform.hasChanged = false; switch (hdLight.type) { case HDLightType.Directional: { hasRayTracedShadows = hdLight.ShadowsEnabled() && hdLight.useScreenSpaceShadows && hdLight.useRayTracedShadows; m_RayTracingLights.hdDirectionalLightArray.Add(hdLight); } break; case HDLightType.Point: case HDLightType.Spot: { hasRayTracedShadows = hdLight.ShadowsEnabled() && hdLight.useRayTracedShadows; m_RayTracingLights.hdPointLightArray.Add(lightRenderEntity); } break; case HDLightType.Area: { hasRayTracedShadows = hdLight.ShadowsEnabled() && hdLight.useRayTracedShadows; switch (hdLight.areaLightShape) { case AreaLightShape.Rectangle: m_RayTracingLights.hdRectLightArray.Add(lightRenderEntity); break; case AreaLightShape.Tube: m_RayTracingLights.hdLineLightArray.Add(lightRenderEntity); break; //TODO: case AreaLightShape.Disc: } break; } } // Check if there is a ray traced shadow in the scene m_RayTracedShadowsRequired |= hasRayTracedShadows; m_RayTracedContactShadowsRequired |= (hdLight.useContactShadow.@override && hdLight.rayTraceContactShadow); } } // Add the lights to the structure m_RayTracingLights.hdLightEntityArray.AddRange(m_RayTracingLights.hdPointLightArray); m_RayTracingLights.hdLightEntityArray.AddRange(m_RayTracingLights.hdLineLightArray); m_RayTracingLights.hdLightEntityArray.AddRange(m_RayTracingLights.hdRectLightArray); // Process the lights HDAdditionalReflectionData[] reflectionProbeArray = UnityEngine.GameObject.FindObjectsOfType <HDAdditionalReflectionData>(); for (int reflIdx = 0; reflIdx < reflectionProbeArray.Length; ++reflIdx) { HDAdditionalReflectionData reflectionProbe = reflectionProbeArray[reflIdx]; // Add it to the list if enabled // Skip the probe if the probe has never rendered (in real time cases) or if texture is null if (reflectionProbe != null && reflectionProbe.enabled && reflectionProbe.ReflectionProbeIsEnabled() && reflectionProbe.gameObject.activeSelf && reflectionProbe.HasValidRenderedData()) { m_RayTracingLights.reflectionProbeArray.Add(reflectionProbe); } } m_RayTracingLights.lightCount = m_RayTracingLights.hdPointLightArray.Count + m_RayTracingLights.hdLineLightArray.Count + m_RayTracingLights.hdRectLightArray.Count + m_RayTracingLights.reflectionProbeArray.Count; }