private void InitRaytracingAccelerationStructure() { RayTracingAccelerationStructure.RASSettings settings = new RayTracingAccelerationStructure.RASSettings(); // include default layer, not lights settings.layerMask = -1; // enable automatic updates settings.managementMode = RayTracingAccelerationStructure.ManagementMode.Manual; // include all renderer types settings.rayTracingModeMask = RayTracingAccelerationStructure.RayTracingModeMask.Everything; _accelerationStructure = new RayTracingAccelerationStructure(settings); // collect all objects in scene and add them to raytracing scene Renderer[] renderers = FindObjectsOfType <Renderer>(); foreach (Renderer r in renderers) { if (r.CompareTag("Light")) { // mask for lights is 0x10 (for shadow rays - dont want to check for intersection in some cases) _accelerationStructure.AddInstance(r, null, null, true, false, 0x10); } else { _accelerationStructure.AddInstance(r, null, null, true, false, 0x01); } } // build raytracing AS _accelerationStructure.Build(); }
void Start() { if (!SystemInfo.supportsRayTracing) { Debug.Log("Ray Tracing not supported !"); } _Camera = GetComponent <Camera>(); _RenderTarget0 = new RenderTexture(_Camera.pixelWidth, _Camera.pixelHeight, 0, RenderTextureFormat.ARGBFloat); _RenderTarget0.enableRandomWrite = true; _RenderTarget0.Create(); _RenderTarget1 = new RenderTexture(_RenderTarget0); _RenderTarget2 = new RenderTexture(_RenderTarget0); RayTracingAccelerationStructure.RASSettings settings = new RayTracingAccelerationStructure.RASSettings(); settings.layerMask = ~0; settings.managementMode = RayTracingAccelerationStructure.ManagementMode.Automatic; settings.rayTracingModeMask = RayTracingAccelerationStructure.RayTracingModeMask.Everything; _AccelerationStructure = new RayTracingAccelerationStructure(settings); Renderer[] renderers = FindObjectsOfType <Renderer>(); for (int i = 0; i < renderers.Length; i++) { Material[] materials = renderers[i].sharedMaterials; for (int j = 0; j < materials.Length; j++) { materials[j] = new Material(IndirectDiffuseShader); } renderers[i].sharedMaterials = materials; _AccelerationStructure.AddInstance(renderers[i]); } _AccelerationStructure.Build(); PathTracingShader.SetAccelerationStructure("_AccelerationStructure", _AccelerationStructure); PathTracingShader.SetTexture("_RenderTarget", _RenderTarget0); PathTracingShader.SetShaderPass("PathTracingRTX"); _Material = new Material(ProgressiveShader); Reset(); }
private void InitRaytracingAccelerationStructure() { RayTracingAccelerationStructure.RASSettings settings = new RayTracingAccelerationStructure.RASSettings(); // include all layers settings.layerMask = ~0; // enable automatic updates settings.managementMode = RayTracingAccelerationStructure.ManagementMode.Automatic; // include all renderer types settings.rayTracingModeMask = RayTracingAccelerationStructure.RayTracingModeMask.Everything; _rtas = new RayTracingAccelerationStructure(settings); // collect all objects in scene and add them to raytracing scene Renderer[] renderers = FindObjectsOfType <Renderer>(); foreach (Renderer r in renderers) { _rtas.AddInstance(r); } // build raytracing scene _rtas.Build(); // RTAS could also be the one from (internal) // HDRenderPipeline.RequestAccelerationStructure(); // reset with // HDRenderPipeline.ResetPathTracing(); }
public void FillAccelerationStructure(ref RayTracingAccelerationStructure vRayTracingAccelerationStructure) { foreach (var r in _renderers) { if (r) { vRayTracingAccelerationStructure.AddInstance(r, _subMeshFlagArray, _subMeshCutoffArray); } } }
protected override void Setup(ScriptableRenderContext ctx, CommandBuffer cmd) { if (!enableRayTracingOutline) return; _outlineRAS = new RayTracingAccelerationStructure(); if (outlineRenderers != null) foreach (var renderer in outlineRenderers) if (renderer != null) _outlineRAS.AddInstance(renderer); _outlineMask = RTHandles.Alloc(Vector2.one, TextureXR.slices, colorFormat: GraphicsFormat.R8_SNorm, dimension: TextureXR.dimension, enableRandomWrite: true, useDynamicScale: true, useMipMap: false, name: "JTRP Ray Tracing Outline Mask"); }
private void InitRaytracingAccelerationStructure() { _rtas = new RayTracingAccelerationStructure(); // collect all objects in scene and add them to raytracing scene Renderer[] renderers = FindObjectsOfType <Renderer>(); foreach (Renderer r in renderers) { _rtas.AddInstance(r); } // build raytrasing scene _rtas.Build(); }
/// <summary> /// build acceleration structure. /// </summary> public void BuildAccelerationStructure() { accelerationStructure?.Dispose(); accelerationStructure = new RayTracingAccelerationStructure(); var subMeshFlagArray = new bool[32]; var subMeshCutoffArray = new bool[32]; for (var i = 0; i < 32; ++i) { subMeshFlagArray[i] = true; subMeshCutoffArray[i] = false; } foreach (var r in colliders) { accelerationStructure.AddInstance(r, subMeshFlagArray, subMeshCutoffArray); } accelerationStructure.Build(); }
void CreateRTAS() { RayTracingAccelerationStructure.RASSettings settings = new RayTracingAccelerationStructure.RASSettings(); settings.layerMask = ~0; settings.managementMode = RayTracingAccelerationStructure.ManagementMode.Automatic; settings.rayTracingModeMask = RayTracingAccelerationStructure.RayTracingModeMask.Everything; _RTAS = new RayTracingAccelerationStructure(settings); renderers = FindObjectsOfType <Renderer>(); for (int i = 0; i < renderers.Length; i++) { _RTAS.AddInstance(renderers[i]); } _RTAS.Build(); }
private void InitRaytracingAccelerationStructure() { RayTracingAccelerationStructure.RASSettings settings = new RayTracingAccelerationStructure.RASSettings(); // include all layers settings.layerMask = ~0; // enable automatic updates settings.managementMode = RayTracingAccelerationStructure.ManagementMode.Automatic; // include all renderer types settings.rayTracingModeMask = RayTracingAccelerationStructure.RayTracingModeMask.Everything; _rtas = new RayTracingAccelerationStructure(settings); // collect all objects in scene and add them to raytracing scene Renderer[] renderers = FindObjectsOfType <Renderer>(); foreach (Renderer r in renderers) { _rtas.AddInstance(r); } // build raytrasing scene _rtas.Build(); }
public void Update() { // if loading world is not enabled, build AS and return if (!Settings.Instance.loadWorld) { if (_accelerationStructure != null) { _accelerationStructure.UpdateInstanceTransform(sun.GetComponent <Renderer>()); _accelerationStructure.Build(); } return; } _radius = Settings.Instance.WorldRadius; if (runningJobs > 0) { runningJobs = 0; JobHandle.CompleteAll(_jobHandles); } if (_jobHandlesAlocated) { _jobHandles.Dispose(); } _jobHandles = new NativeList <JobHandle>(Allocator.Persistent); _jobHandlesAlocated = true; // If camera moved to another chunk, generate new chunks in multiple phases Vector3Int chunkWherePlayerStands = ChunkWherePlayerStands(); if ((!chunkWherePlayerStands.Equals(_chunkWherePlayerStood) || _prevRadius != _radius) && phase == Phase.Resting) { _chunkWherePlayerStood = chunkWherePlayerStands; int radiusInChunks = _chunkSize * _radius; FindMissingChunks(chunkWherePlayerStands, radiusInChunks); if (_toGenerate.Count > 0) { _iter = _toGenerate.Count - 1; phase = Phase.GeneratingBlocks; } else if (_prevRadius != _radius) { phase = Phase.RemovingChunks; } else { phase = Phase.Resting; } _prevRadius = _radius; } else if (phase == Phase.GeneratingBlocks) { for (; _iter >= 0 && runningJobs < _maxJobsAtOnce * 5; _iter--) { _jobHandles.Add(_toGenerate[_iter].GenerateBlocks(centroids)); runningJobs++; } if (_iter < 0) { phase = Phase.GeneratingMeshData; _iter = _toGenerate.Count - 1; } } else if (phase == Phase.GeneratingMeshData) { for (; _iter >= 0 && runningJobs <= _maxJobsAtOnce * 4; _iter--) { if (!_toGenerate[_iter].IsEmpty()) { _jobHandles.Add(_toGenerate[_iter].GenerateMeshData()); _toGenerate[_iter].PrepareMesh(); runningJobs++; } } if (_iter < 0) { phase = Phase.GeneratingFlora; _iter = _toGenerate.Count - 1; } } else if (phase == Phase.GeneratingFlora) { for (; _iter >= 0 && runningJobs <= _maxJobsAtOnce * 4; _iter--) { if (_toGenerate[_iter].AreTrees()) { _jobHandles.Add(_toGenerate[_iter].GenerateTrees()); runningJobs++; } } if (_iter < 0) { phase = Phase.FillingMeshes; _iter = _toGenerate.Count - 1; } } else if (phase == Phase.FillingMeshes) { int runningFinishes = 0; for (; _iter >= 0 && runningFinishes < 2; _iter--) { if (!_toGenerate[_iter].IsEmpty()) { runningFinishes += _toGenerate[_iter].FinishCreatingChunk(); _accelerationStructure.AddInstance(_toGenerate[_iter].chunk.GetComponent <Renderer>(), null, null, true, false, 0x01); } } if (_iter < 0) { phase = Phase.RemovingChunks; _toGenerate.Clear(); } } else if (phase == Phase.RemovingChunks) { int radiusInChunks = _chunkSize * _radius; RemoveChunks(chunkWherePlayerStands, radiusInChunks); phase = Phase.Resting; } else { phase = Phase.Resting; } // Update sun transform and build AS if (_accelerationStructure != null) { _accelerationStructure.UpdateInstanceTransform(sun.GetComponent <Renderer>()); _accelerationStructure.Build(); } if (phase == Phase.Resting) { Settings.Instance.reprojectWithIDs = true; } else { Settings.Instance.reprojectWithIDs = false; } }
AccelerationStructureStatus AddInstanceToRAS(Renderer currentRenderer, bool rayTracedShadow, bool aoEnabled, int aoLayerValue, bool reflEnabled, int reflLayerValue, bool giEnabled, int giLayerValue, bool recursiveEnabled, int rrLayerValue, bool pathTracingEnabled, int ptLayerValue) { // Get all the materials of the mesh renderer currentRenderer.GetSharedMaterials(materialArray); // If the array is null, we are done if (materialArray == null) { return(AccelerationStructureStatus.NullMaterial); } // For every sub-mesh/sub-material let's build the right flags int numSubMeshes = 1; if (!(currentRenderer.GetType() == typeof(SkinnedMeshRenderer))) { currentRenderer.TryGetComponent(out MeshFilter meshFilter); if (meshFilter == null || meshFilter.sharedMesh == null) { return(AccelerationStructureStatus.MissingMesh); } numSubMeshes = meshFilter.sharedMesh.subMeshCount; } else { SkinnedMeshRenderer skinnedMesh = (SkinnedMeshRenderer)currentRenderer; if (skinnedMesh.sharedMesh == null) { return(AccelerationStructureStatus.MissingMesh); } numSubMeshes = skinnedMesh.sharedMesh.subMeshCount; } // Get the layer of this object int objectLayerValue = 1 << currentRenderer.gameObject.layer; // We need to build the instance flag for this renderer uint instanceFlag = 0x00; bool singleSided = false; bool materialIsOnlyTransparent = true; bool hasTransparentSubMaterial = false; for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx) { // Initially we consider the potential mesh as invalid bool validMesh = false; if (materialArray.Count > meshIdx) { // Grab the material for the current sub-mesh Material currentMaterial = materialArray[meshIdx]; // The material is transparent if either it has the requested keyword or is in the transparent queue range if (currentMaterial != null) { // Mesh is valid given that all requirements are ok validMesh = true; subMeshFlagArray[meshIdx] = true; // Is the sub material transparent? subMeshTransparentArray[meshIdx] = currentMaterial.IsKeywordEnabled("_SURFACE_TYPE_TRANSPARENT") || (HDRenderQueue.k_RenderQueue_Transparent.lowerBound <= currentMaterial.renderQueue && HDRenderQueue.k_RenderQueue_Transparent.upperBound >= currentMaterial.renderQueue); // aggregate the transparency info materialIsOnlyTransparent &= subMeshTransparentArray[meshIdx]; hasTransparentSubMaterial |= subMeshTransparentArray[meshIdx]; // 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; // Check if the material has changed since last time we were here if (!m_MaterialsDirty) { int matId = currentMaterial.GetInstanceID(); int matPrevCRC, matCurCRC = currentMaterial.ComputeCRC(); if (m_MaterialCRCs.TryGetValue(matId, out matPrevCRC)) { m_MaterialCRCs[matId] = matCurCRC; m_MaterialsDirty |= (matCurCRC != matPrevCRC); } else { m_MaterialCRCs.Add(matId, matCurCRC); } } } } // If the mesh was not valid, exclude it if (!validMesh) { subMeshFlagArray[meshIdx] = false; subMeshCutoffArray[meshIdx] = false; singleSided = true; } } // If the material is considered opaque, but has some transparent sub-materials if (!materialIsOnlyTransparent && hasTransparentSubMaterial) { for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx) { subMeshCutoffArray[meshIdx] = subMeshTransparentArray[meshIdx] ? true : subMeshCutoffArray[meshIdx]; } } // Propagate the opacity mask only if all sub materials are opaque bool isOpaque = !hasTransparentSubMaterial; if (isOpaque) { instanceFlag |= (uint)(RayTracingRendererFlag.Opaque); } if (rayTracedShadow || pathTracingEnabled) { if (hasTransparentSubMaterial) { // Raise the shadow casting flag if needed instanceFlag |= ((currentRenderer.shadowCastingMode != ShadowCastingMode.Off) ? (uint)(RayTracingRendererFlag.CastShadowTransparent) : 0x00); } else { // Raise the shadow casting flag if needed instanceFlag |= ((currentRenderer.shadowCastingMode != ShadowCastingMode.Off) ? (uint)(RayTracingRendererFlag.CastShadowOpaque) : 0x00); } } // We consider a mesh visible by reflection, gi, etc if it is not in the shadow only mode. bool meshIsVisible = currentRenderer.shadowCastingMode != ShadowCastingMode.ShadowsOnly; if (aoEnabled && !materialIsOnlyTransparent && meshIsVisible) { // Raise the Ambient Occlusion flag if needed instanceFlag |= ((aoLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.AmbientOcclusion) : 0x00; } if (reflEnabled && !materialIsOnlyTransparent && meshIsVisible) { // Raise the Screen Space Reflection if needed instanceFlag |= ((reflLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.Reflection) : 0x00; } if (giEnabled && !materialIsOnlyTransparent && meshIsVisible) { // Raise the Global Illumination if needed instanceFlag |= ((giLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.GlobalIllumination) : 0x00; } if (recursiveEnabled && meshIsVisible) { // Raise the Global Illumination if needed instanceFlag |= ((rrLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.RecursiveRendering) : 0x00; } if (pathTracingEnabled && meshIsVisible) { // Raise the Global Illumination if needed instanceFlag |= ((ptLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.PathTracing) : 0x00; } // If the object was not referenced if (instanceFlag == 0) { return(AccelerationStructureStatus.Added); } // Add it to the acceleration structure m_CurrentRAS.AddInstance(currentRenderer, subMeshMask: subMeshFlagArray, subMeshTransparencyFlags: subMeshCutoffArray, enableTriangleCulling: singleSided, mask: instanceFlag); // return the status return((!materialIsOnlyTransparent && hasTransparentSubMaterial) ? AccelerationStructureStatus.TransparencyIssue : AccelerationStructureStatus.Added); }
AccelerationStructureStatus AddInstanceToRAS(Renderer currentRenderer, bool rayTracedShadow, bool aoEnabled, int aoLayerValue, bool reflEnabled, int reflLayerValue, bool giEnabled, int giLayerValue, bool recursiveEnabled, int rrLayerValue, bool pathTracingEnabled, int ptLayerValue) { // Get all the materials of the mesh renderer currentRenderer.GetSharedMaterials(materialArray); // If the array is null, we are done if (materialArray == null) { return(AccelerationStructureStatus.NullMaterial); } // For every sub-mesh/sub-material let's build the right flags int numSubMeshes = 1; if (!(currentRenderer.GetType() == typeof(SkinnedMeshRenderer))) { currentRenderer.TryGetComponent(out MeshFilter meshFilter); if (meshFilter == null || meshFilter.sharedMesh == null) { return(AccelerationStructureStatus.MissingMesh); } numSubMeshes = meshFilter.sharedMesh.subMeshCount; } else { SkinnedMeshRenderer skinnedMesh = (SkinnedMeshRenderer)currentRenderer; if (skinnedMesh.sharedMesh == null) { return(AccelerationStructureStatus.MissingMesh); } numSubMeshes = skinnedMesh.sharedMesh.subMeshCount; } // Let's clamp the number of sub-meshes to avoid throwing an unwated error numSubMeshes = Mathf.Min(numSubMeshes, maxNumSubMeshes); // Get the layer of this object int objectLayerValue = 1 << currentRenderer.gameObject.layer; // We need to build the instance flag for this renderer uint instanceFlag = 0x00; bool doubleSided = false; bool materialIsOnlyTransparent = true; bool hasTransparentSubMaterial = false; // We disregard the ray traced shadows option when in Path Tracing rayTracedShadow &= !pathTracingEnabled; // Deactivate Path Tracing if the object does not belong to the path traced layer(s) pathTracingEnabled &= (bool)((ptLayerValue & objectLayerValue) != 0); for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx) { // Initially we consider the potential mesh as invalid bool validMesh = false; if (materialArray.Count > meshIdx) { // Grab the material for the current sub-mesh Material currentMaterial = materialArray[meshIdx]; // Make sure that the material is HDRP's and non-decal if (IsValidRayTracedMaterial(currentMaterial)) { // Mesh is valid given that all requirements are ok validMesh = true; // First mark the thing as valid subMeshFlagArray[meshIdx] = RayTracingSubMeshFlags.Enabled; // Evaluate what kind of materials we are dealing with bool alphaTested = IsAlphaTestedMaterial(currentMaterial); bool transparentMaterial = IsTransparentMaterial(currentMaterial); // Aggregate the transparency info materialIsOnlyTransparent &= transparentMaterial; hasTransparentSubMaterial |= transparentMaterial; // Append the additional flags depending on what kind of sub mesh this is if (!transparentMaterial && !alphaTested) { subMeshFlagArray[meshIdx] |= RayTracingSubMeshFlags.ClosestHitOnly; } else if (transparentMaterial) { subMeshFlagArray[meshIdx] |= RayTracingSubMeshFlags.UniqueAnyHitCalls; } // Check if we want to enable double-sidedness for the mesh // (note that a mix of single and double-sided materials will result in a double-sided mesh in the AS) doubleSided |= currentMaterial.doubleSidedGI || currentMaterial.IsKeywordEnabled("_DOUBLESIDED_ON"); // Check if the material has changed since last time we were here if (!m_MaterialsDirty) { int matId = currentMaterial.GetInstanceID(); int matPrevCRC, matCurCRC = currentMaterial.ComputeCRC(); if (m_MaterialCRCs.TryGetValue(matId, out matPrevCRC)) { m_MaterialCRCs[matId] = matCurCRC; m_MaterialsDirty |= (matCurCRC != matPrevCRC); } else { m_MaterialCRCs.Add(matId, matCurCRC); } } } } // If the mesh was not valid, exclude it (without affecting sidedness) if (!validMesh) { subMeshFlagArray[meshIdx] = RayTracingSubMeshFlags.Disabled; } } // If the material is considered opaque, every sub-mesh has to be enabled and with unique any hit calls if (!materialIsOnlyTransparent && hasTransparentSubMaterial) { for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx) { subMeshFlagArray[meshIdx] = RayTracingSubMeshFlags.Enabled | RayTracingSubMeshFlags.UniqueAnyHitCalls; } } // Propagate the opacity mask only if all sub materials are opaque bool isOpaque = !hasTransparentSubMaterial; if (isOpaque) { instanceFlag |= (uint)(RayTracingRendererFlag.Opaque); } if (rayTracedShadow || pathTracingEnabled) { if (hasTransparentSubMaterial) { // Raise the shadow casting flag if needed instanceFlag |= ((currentRenderer.shadowCastingMode != ShadowCastingMode.Off) ? (uint)(RayTracingRendererFlag.CastShadowTransparent) : 0x00); } else { // Raise the shadow casting flag if needed instanceFlag |= ((currentRenderer.shadowCastingMode != ShadowCastingMode.Off) ? (uint)(RayTracingRendererFlag.CastShadowOpaque) : 0x00); } } // We consider a mesh visible by reflection, gi, etc if it is not in the shadow only mode. bool meshIsVisible = currentRenderer.shadowCastingMode != ShadowCastingMode.ShadowsOnly; if (aoEnabled && !materialIsOnlyTransparent && meshIsVisible) { // Raise the Ambient Occlusion flag if needed instanceFlag |= ((aoLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.AmbientOcclusion) : 0x00; } if (reflEnabled && !materialIsOnlyTransparent && meshIsVisible) { // Raise the Screen Space Reflection flag if needed instanceFlag |= ((reflLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.Reflection) : 0x00; } if (giEnabled && !materialIsOnlyTransparent && meshIsVisible) { // Raise the Global Illumination flag if needed instanceFlag |= ((giLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.GlobalIllumination) : 0x00; } if (recursiveEnabled && meshIsVisible) { // Raise the Recursive Rendering flag if needed instanceFlag |= ((rrLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.RecursiveRendering) : 0x00; } if (pathTracingEnabled && meshIsVisible) { // Raise the Path Tracing flag if needed instanceFlag |= (uint)(RayTracingRendererFlag.PathTracing); } // If the object was not referenced if (instanceFlag == 0) { return(AccelerationStructureStatus.Added); } // Add it to the acceleration structure m_CurrentRAS.AddInstance(currentRenderer, subMeshFlags: subMeshFlagArray, enableTriangleCulling: !doubleSided, mask: instanceFlag); // Indicates that a transform has changed in our scene (mesh or light) m_TransformDirty |= currentRenderer.transform.hasChanged; currentRenderer.transform.hasChanged = false; // return the status return((!materialIsOnlyTransparent && hasTransparentSubMaterial) ? AccelerationStructureStatus.TransparencyIssue : AccelerationStructureStatus.Added); }
void AddInstanceToRAS(Renderer currentRenderer, bool rayTracedShadow, bool aoEnabled, int aoLayerValue, bool reflEnabled, int reflLayerValue, bool giEnabled, int giLayerValue, bool recursiveEnabled, int rrLayerValue, bool pathTracingEnabled, int ptLayerValue) { currentRenderer.GetSharedMaterials(materialArray); if (materialArray != null) { // For every sub-mesh/sub-material let's build the right flags int numSubMeshes = materialArray.Count; // Get the layer of this object int objectLayerValue = 1 << currentRenderer.gameObject.layer; // We need to build the instance flag for this renderer uint instanceFlag = 0x00; bool singleSided = false; bool materialIsTransparent = false; for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx) { Material currentMaterial = materialArray[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? 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); // 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; } } // Propagate the right mask instanceFlag |= materialIsTransparent ? (uint)(1 << 1) : (uint)(1 << 0); if (rayTracedShadow) { // Raise the shadow casting flag if needed instanceFlag |= ((currentRenderer.shadowCastingMode == ShadowCastingMode.On) ? (uint)(RayTracingRendererFlag.CastShadow) : 0x00); } if (aoEnabled && !materialIsTransparent) { // Raise the Ambient Occlusion flag if needed instanceFlag |= ((aoLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.AmbientOcclusion) : 0x00; } if (reflEnabled && !materialIsTransparent) { // Raise the Screen Space Reflection if needed instanceFlag |= ((reflLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.Reflection) : 0x00; } if (giEnabled && !materialIsTransparent) { // Raise the Global Illumination if needed instanceFlag |= ((giLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.GlobalIllumination) : 0x00; } if (recursiveEnabled) { // Raise the Global Illumination if needed instanceFlag |= ((rrLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.RecursiveRendering) : 0x00; } if (pathTracingEnabled) { // Raise the Global Illumination if needed instanceFlag |= ((ptLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.PathTracing) : 0x00; } if (instanceFlag == 0) { return; } // Add it to the acceleration structure m_CurrentRAS.AddInstance(currentRenderer, subMeshMask: subMeshFlagArray, subMeshTransparencyFlags: subMeshCutoffArray, enableTriangleCulling: singleSided, mask: instanceFlag); } }
AccelerationStructureStatus AddInstanceToRAS(Renderer currentRenderer, bool rayTracedShadow, bool aoEnabled, int aoLayerValue, bool reflEnabled, int reflLayerValue, bool giEnabled, int giLayerValue, bool recursiveEnabled, int rrLayerValue, bool pathTracingEnabled, int ptLayerValue) { // Get all the materials of the mesh renderer currentRenderer.GetSharedMaterials(materialArray); // If the array is null, we are done if (materialArray == null) { return(AccelerationStructureStatus.NullMaterial); } // For every sub-mesh/sub-material let's build the right flags currentRenderer.TryGetComponent(out MeshFilter meshFilter); if (meshFilter == null || meshFilter.sharedMesh == null) { return(AccelerationStructureStatus.MissingMesh); } int numSubMeshes = meshFilter.sharedMesh.subMeshCount; // Get the layer of this object int objectLayerValue = 1 << currentRenderer.gameObject.layer; // We need to build the instance flag for this renderer uint instanceFlag = 0x00; bool singleSided = false; bool materialIsOnlyTransparent = true; bool hasTransparentSubMaterial = false; for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx) { // Intially we consider the potential mesh as invalid bool validMesh = false; if (materialArray.Count > meshIdx) { // Grab the material for the current sub-mesh Material currentMaterial = materialArray[meshIdx]; // The material is transparent if either it has the requested keyword or is in the transparent queue range if (currentMaterial != null) { // Mesh is valid given that all requirements are ok validMesh = true; subMeshFlagArray[meshIdx] = true; // Is the sub material transparent? subMeshTransparentArray[meshIdx] = 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); // aggregate the transparency info materialIsOnlyTransparent &= subMeshTransparentArray[meshIdx]; hasTransparentSubMaterial |= subMeshTransparentArray[meshIdx]; // 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; } } // If the mesh was not valid, exclude it if (!validMesh) { subMeshFlagArray[meshIdx] = false; subMeshCutoffArray[meshIdx] = false; singleSided = true; } } // If the material is considered opaque, but has some transparent sub-materials if (!materialIsOnlyTransparent && hasTransparentSubMaterial) { for (int meshIdx = 0; meshIdx < numSubMeshes; ++meshIdx) { subMeshCutoffArray[meshIdx] = subMeshTransparentArray[meshIdx] ? true : subMeshCutoffArray[meshIdx]; } } // Propagate the right mask instanceFlag |= materialIsOnlyTransparent ? (uint)(1 << 1) : (uint)(1 << 0); if (rayTracedShadow) { // Raise the shadow casting flag if needed instanceFlag |= ((currentRenderer.shadowCastingMode == ShadowCastingMode.On) ? (uint)(RayTracingRendererFlag.CastShadow) : 0x00); } if (aoEnabled && !materialIsOnlyTransparent) { // Raise the Ambient Occlusion flag if needed instanceFlag |= ((aoLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.AmbientOcclusion) : 0x00; } if (reflEnabled && !materialIsOnlyTransparent) { // Raise the Screen Space Reflection if needed instanceFlag |= ((reflLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.Reflection) : 0x00; } if (giEnabled && !materialIsOnlyTransparent) { // Raise the Global Illumination if needed instanceFlag |= ((giLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.GlobalIllumination) : 0x00; } if (recursiveEnabled) { // Raise the Global Illumination if needed instanceFlag |= ((rrLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.RecursiveRendering) : 0x00; } if (pathTracingEnabled) { // Raise the Global Illumination if needed instanceFlag |= ((ptLayerValue & objectLayerValue) != 0) ? (uint)(RayTracingRendererFlag.PathTracing) : 0x00; } // If the object was not referenced if (instanceFlag == 0) { return(AccelerationStructureStatus.Added); } // Add it to the acceleration structure m_CurrentRAS.AddInstance(currentRenderer, subMeshMask: subMeshFlagArray, subMeshTransparencyFlags: subMeshCutoffArray, enableTriangleCulling: singleSided, mask: instanceFlag); // return the status return((!materialIsOnlyTransparent && hasTransparentSubMaterial) ? AccelerationStructureStatus.TransparencyIssue : AccelerationStructureStatus.Added); }