/// <summary> /// Creates a single Reflection Probe in the given position /// </summary> /// <param name="position"></param> /// <param name="terrain"></param> /// <param name="reflectionProbeData"></param> /// <param name="seaLevelActive"></param> /// <param name="seaLevel"></param> /// <param name="parentTransform"></param> /// <param name="isHDRP"></param> /// <returns></returns> public static ReflectionProbe CreateReflectionProbe(Vector3 position, Vector3 size, Terrain terrain, ReflectionProbeData reflectionProbeData, bool seaLevelActive, float seaLevel, Transform parentTransform, bool isHDRP, bool probeCulling = false) { GameObject probeObject = new GameObject("Global Generated Reflection Probe"); float sampledHeight = terrain.SampleHeight(position); ReflectionProbe reflectionProbe = probeObject.AddComponent <ReflectionProbe>(); reflectionProbe.enabled = false; reflectionProbe.blendDistance = 0f; reflectionProbe.cullingMask = reflectionProbeData.reflectionprobeCullingMask; reflectionProbe.farClipPlane = reflectionProbeData.reflectionProbeClipPlaneDistance; reflectionProbe.mode = reflectionProbeData.reflectionProbeMode; switch (reflectionProbeData.reflectionProbeRefresh) { case GaiaConstants.ReflectionProbeRefreshModePW.OnAwake: reflectionProbe.refreshMode = ReflectionProbeRefreshMode.OnAwake; break; case GaiaConstants.ReflectionProbeRefreshModePW.EveryFrame: reflectionProbe.refreshMode = ReflectionProbeRefreshMode.EveryFrame; break; case GaiaConstants.ReflectionProbeRefreshModePW.ViaScripting: reflectionProbe.refreshMode = ReflectionProbeRefreshMode.ViaScripting; break; case GaiaConstants.ReflectionProbeRefreshModePW.ProbeManager: reflectionProbe.refreshMode = ReflectionProbeRefreshMode.ViaScripting; break; } if (!seaLevelActive) { position.y = 500f + seaLevel + 0.2f; } else { position.y = sampledHeight + reflectionProbeData.reflectionProbeOffset; reflectionProbe.center = new Vector3(0f, 0f - reflectionProbeData.reflectionProbeOffset - sampledHeight, 0f); } if (position.y < seaLevel) { position.y = seaLevel + reflectionProbeData.reflectionProbeOffset; } probeObject.transform.position = position; probeObject.transform.SetParent(parentTransform); switch (reflectionProbeData.reflectionProbeResolution) { case GaiaConstants.ReflectionProbeResolution.Resolution16: reflectionProbe.resolution = 16; break; case GaiaConstants.ReflectionProbeResolution.Resolution32: reflectionProbe.resolution = 32; break; case GaiaConstants.ReflectionProbeResolution.Resolution64: reflectionProbe.resolution = 64; break; case GaiaConstants.ReflectionProbeResolution.Resolution128: reflectionProbe.resolution = 128; break; case GaiaConstants.ReflectionProbeResolution.Resolution256: reflectionProbe.resolution = 256; break; case GaiaConstants.ReflectionProbeResolution.Resolution512: reflectionProbe.resolution = 512; break; case GaiaConstants.ReflectionProbeResolution.Resolution1024: reflectionProbe.resolution = 1024; break; case GaiaConstants.ReflectionProbeResolution.Resolution2048: reflectionProbe.resolution = 2048; break; } reflectionProbe.shadowDistance = 80f; reflectionProbe.size = size; reflectionProbe.timeSlicingMode = reflectionProbeData.reflectionProbeTimeSlicingMode; reflectionProbe.hdr = true; reflectionProbe.shadowDistance = reflectionProbeData.reflectionProbeShadowDistance; //If HDRP if (isHDRP) { #if HDPipeline HDAdditionalReflectionData reflectionData = probeObject.GetComponent <HDAdditionalReflectionData>(); if (reflectionData == null) { reflectionData = probeObject.AddComponent <HDAdditionalReflectionData>(); } reflectionData.multiplier = 1f; reflectionData.realtimeMode = ProbeSettings.RealtimeMode.OnEnable; #endif } #if GAIA_PRO_PRESENT ReflectionProbeCuller culler = reflectionProbe.GetComponent <ReflectionProbeCuller>(); if (probeCulling) { if (culler == null) { culler = reflectionProbe.gameObject.AddComponent <ReflectionProbeCuller>(); culler.m_probe = reflectionProbe; culler.Initialize(); } } else { if (culler != null) { GameObject.DestroyImmediate(culler); } } #endif return(reflectionProbe); }
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); }); } }