public static string GetBakedTextureFilePath(HDProbe probe)
 {
     return(GetBakedTextureFilePath(
                probe.settings.type,
                SceneObjectIDMap.GetOrCreateSceneObjectID(
                    probe.gameObject, SceneObjectCategory.ReflectionProbe
                    ),
                probe.gameObject.scene
                ));
 }
        static ProbeCapturePositionSettings ComputeFrom(
            HDProbe probe,
            Vector3 referencePosition, Quaternion referenceRotation
            )
        {
            var result       = new ProbeCapturePositionSettings();
            var proxyToWorld = probe.proxyToWorld;

            result.proxyPosition     = proxyToWorld.GetColumn(3);
            result.proxyRotation     = proxyToWorld.rotation;
            result.referencePosition = referencePosition;
            result.referenceRotation = referenceRotation;
            result.influenceToWorld  = probe.influenceToWorld;
            return(result);
        }
        void BuildEnvLightData(CommandBuffer cmd, HDCamera hdCamera, HDRayTracingLights lights)
        {
            int totalReflectionProbes = lights.reflectionProbeArray.Count;

            if (totalReflectionProbes == 0)
            {
                ResizeEnvLightDataBuffer(1);
                return;
            }

            // Also we need to build the light list data
            if (m_EnvLightDataCPUArray == null || m_EnvLightDataGPUArray == null || m_EnvLightDataGPUArray.count != totalReflectionProbes)
            {
                ResizeEnvLightDataBuffer(totalReflectionProbes);
            }

            // Make sure the Cpu list is empty
            m_EnvLightDataCPUArray.Clear();
            ProcessedProbeData processedProbe = new ProcessedProbeData();

            // Build the data for every light
            for (int lightIdx = 0; lightIdx < lights.reflectionProbeArray.Count; ++lightIdx)
            {
                HDProbe probeData = lights.reflectionProbeArray[lightIdx];

                // Skip the probe if the probe has never rendered (in realtime cases) or if texture is null
                if (!probeData.HasValidRenderedData())
                {
                    continue;
                }

                HDRenderPipeline.PreprocessProbeData(ref processedProbe, probeData, hdCamera);

                var envLightData = new EnvLightData();
                m_RenderPipeline.GetEnvLightData(cmd, hdCamera, processedProbe, ref envLightData);

                // We make the light position camera-relative as late as possible in order
                // to allow the preceding code to work with the absolute world space coordinates.
                Vector3 camPosWS = hdCamera.mainViewConstants.worldSpaceCameraPos;
                HDRenderPipeline.UpdateEnvLighCameraRelativetData(ref envLightData, camPosWS);

                m_EnvLightDataCPUArray.Add(envLightData);
            }

            // Push the data to the GPU
            m_EnvLightDataGPUArray.SetData(m_EnvLightDataCPUArray);
        }
        /// <summary>
        /// Compute the probe capture settings from an HDProbe and a reference position.
        /// The position will be mirrored based on the mirror position of the probe.
        /// </summary>
        /// <param name="probe">The probe to extract settings from.</param>
        /// <param name="referencePosition">The reference position to use.</param>
        /// <returns>The probe capture position setting.</returns>
        public static ProbeCapturePositionSettings ComputeFromMirroredReference(
            HDProbe probe, Vector3 referencePosition
            )
        {
            var positionSettings = ComputeFrom(
                probe,
                referencePosition, Quaternion.identity
                );
            // Set proper orientation for the reference rotation
            var proxyMatrix = Matrix4x4.TRS(
                positionSettings.proxyPosition,
                positionSettings.proxyRotation,
                Vector3.one
                );
            var mirrorPosition = proxyMatrix.MultiplyPoint(probe.settings.proxySettings.mirrorPositionProxySpace);

            positionSettings.referenceRotation = Quaternion.LookRotation(mirrorPosition - positionSettings.referencePosition);
            return(positionSettings);
        }
        /// <summary>
        /// Compute the probe capture settings from an HDProbe and a reference transform.
        /// </summary>
        /// <param name="probe">The probe to extract settings from.</param>
        /// <param name="reference">The reference transform. Use <c>null</c> when no reference is available.</param>
        /// <returns>The probe capture position settings.</returns>
        public static ProbeCapturePositionSettings ComputeFrom(HDProbe probe, Transform reference)
        {
            var referencePosition = Vector3.zero;
            var referenceRotation = Quaternion.identity;

            if (reference != null)
            {
                referencePosition = reference.position;
                referenceRotation = reference.rotation;
            }
            else
            {
                if (probe.type == ProbeSettings.ProbeType.PlanarProbe)
                {
                    var planar = (PlanarReflectionProbe)probe;
                    return(ComputeFromMirroredReference(planar, planar.referencePosition));
                }
            }

            var result = ComputeFrom(probe, referencePosition, referenceRotation);

            return(result);
        }
Example #6
0
        void BuildEnvLightData(CommandBuffer cmd, HDCamera hdCamera, HDRayTracingLights lights)
        {
            int totalReflectionProbes = lights.reflectionProbeArray.Count;

            if (totalReflectionProbes == 0)
            {
                ResizeEnvLightDataBuffer(1);
                return;
            }

            // Also we need to build the light list data
            if (m_EnvLightDataCPUArray == null || m_EnvLightDataGPUArray == null || m_EnvLightDataGPUArray.count != totalReflectionProbes)
            {
                ResizeEnvLightDataBuffer(totalReflectionProbes);
            }

            // Make sure the Cpu list is empty
            m_EnvLightDataCPUArray.Clear();

            // Build the data for every light
            for (int lightIdx = 0; lightIdx < lights.reflectionProbeArray.Count; ++lightIdx)
            {
                HDProbe probeData    = lights.reflectionProbeArray[lightIdx];
                var     envLightData = new EnvLightData();
                m_RenderPipeline.GetEnvLightData(cmd, hdCamera, probeData, m_RenderPipeline.m_CurrentDebugDisplaySettings, ref envLightData);

                // We make the light position camera-relative as late as possible in order
                // to allow the preceding code to work with the absolute world space coordinates.
                Vector3 camPosWS = hdCamera.mainViewConstants.worldSpaceCameraPos;
                m_RenderPipeline.UpdateEnvLighCameraRelativetData(ref envLightData, camPosWS);

                m_EnvLightDataCPUArray.Add(envLightData);
            }

            // Push the data to the GPU
            m_EnvLightDataGPUArray.SetData(m_EnvLightDataCPUArray);
        }
        static ProbeCapturePositionSettings ComputeFrom(
            HDProbe probe,
            Vector3 referencePosition, Quaternion referenceRotation
            )
        {
            var result       = new ProbeCapturePositionSettings();
            var proxyToWorld = probe.proxyToWorld;

            result.proxyPosition = proxyToWorld.GetColumn(3);

            // If reference position and proxy position is exactly the same, we end up in some degeneracies triggered
            // by engine code when computing culling parameters. This is an extremely rare case, but can happen
            // in editor when focusing on the planar probe. So if that happens, we offset them 0.1 mm apart.
            if (Vector3.Distance(result.proxyPosition, referencePosition) < 1e-4f)
            {
                referencePosition += new Vector3(1e-4f, 1e-4f, 1e-4f);
            }

            result.proxyRotation     = proxyToWorld.rotation;
            result.referencePosition = referencePosition;
            result.referenceRotation = referenceRotation;
            result.influenceToWorld  = probe.influenceToWorld;
            return(result);
        }
        void BuildGPULightVolumes(HDCamera hdCamera, HDRayTracingLights rayTracingLights)
        {
            int totalNumLights = rayTracingLights.lightCount;

            // Make sure the light volume buffer has the right size
            if (m_LightVolumesCPUArray == null || totalNumLights != m_LightVolumesCPUArray.Length)
            {
                ResizeVolumeBuffer(totalNumLights);
            }

            // Set Light volume data to the CPU buffer
            punctualLightCount = 0;
            areaLightCount     = 0;
            envLightCount      = 0;
            totalLightCount    = 0;

            int realIndex = 0;

            for (int lightIdx = 0; lightIdx < rayTracingLights.hdLightArray.Count; ++lightIdx)
            {
                HDAdditionalLightData currentLight = rayTracingLights.hdLightArray[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 not add it if it is null for that invalid frame
                if (currentLight != null)
                {
                    Light light = currentLight.gameObject.GetComponent <Light>();
                    if (light == null || !light.enabled)
                    {
                        continue;
                    }

                    if (hdCamera.frameSettings.IsEnabled(FrameSettingsField.RayTracing) && !currentLight.includeForRayTracing)
                    {
                        continue;
                    }

                    // Reserve space in the cookie atlas
                    m_RenderPipeline.ReserveCookieAtlasTexture(currentLight, light, currentLight.type);

                    // Compute the camera relative position
                    Vector3 lightPositionRWS = currentLight.gameObject.transform.position;
                    if (ShaderConfig.s_CameraRelativeRendering != 0)
                    {
                        lightPositionRWS -= hdCamera.camera.transform.position;
                    }

                    // Grab the light range
                    float lightRange = light.range;

                    if (currentLight.type != HDLightType.Area)
                    {
                        m_LightVolumesCPUArray[realIndex].range      = new Vector3(lightRange, lightRange, lightRange);
                        m_LightVolumesCPUArray[realIndex].position   = lightPositionRWS;
                        m_LightVolumesCPUArray[realIndex].active     = (currentLight.gameObject.activeInHierarchy ? 1 : 0);
                        m_LightVolumesCPUArray[realIndex].lightIndex = (uint)lightIdx;
                        m_LightVolumesCPUArray[realIndex].shape      = 0;
                        m_LightVolumesCPUArray[realIndex].lightType  = 0;
                        punctualLightCount++;
                    }
                    else
                    {
                        // let's compute the oobb of the light influence volume first
                        Vector3 oobbDimensions = new Vector3(currentLight.shapeWidth + 2 * lightRange, currentLight.shapeHeight + 2 * lightRange, lightRange); // One-sided
                        Vector3 extents        = 0.5f * oobbDimensions;
                        Vector3 oobbCenter     = lightPositionRWS + extents.z * currentLight.gameObject.transform.forward;

                        // Let's now compute an AABB that matches the previously defined OOBB
                        OOBBToAABBBounds(oobbCenter, extents, currentLight.gameObject.transform.up, currentLight.gameObject.transform.right, currentLight.gameObject.transform.forward, ref bounds);

                        // Fill the volume data
                        m_LightVolumesCPUArray[realIndex].range      = bounds.extents;
                        m_LightVolumesCPUArray[realIndex].position   = bounds.center;
                        m_LightVolumesCPUArray[realIndex].active     = (currentLight.gameObject.activeInHierarchy ? 1 : 0);
                        m_LightVolumesCPUArray[realIndex].lightIndex = (uint)lightIdx;
                        m_LightVolumesCPUArray[realIndex].shape      = 1;
                        m_LightVolumesCPUArray[realIndex].lightType  = 1;
                        areaLightCount++;
                    }
                    realIndex++;
                }
            }

            int indexOffset = realIndex;

            // Set Env Light volume data to the CPU buffer
            for (int lightIdx = 0; lightIdx < rayTracingLights.reflectionProbeArray.Count; ++lightIdx)
            {
                HDProbe currentEnvLight = rayTracingLights.reflectionProbeArray[lightIdx];

                // Compute the camera relative position
                Vector3 probePositionRWS = currentEnvLight.influenceToWorld.GetColumn(3);
                if (ShaderConfig.s_CameraRelativeRendering != 0)
                {
                    probePositionRWS -= hdCamera.camera.transform.position;
                }

                if (currentEnvLight != null)
                {
                    if (currentEnvLight.influenceVolume.shape == InfluenceShape.Sphere)
                    {
                        m_LightVolumesCPUArray[lightIdx + indexOffset].shape    = 0;
                        m_LightVolumesCPUArray[lightIdx + indexOffset].range    = new Vector3(currentEnvLight.influenceVolume.sphereRadius, currentEnvLight.influenceVolume.sphereRadius, currentEnvLight.influenceVolume.sphereRadius);
                        m_LightVolumesCPUArray[lightIdx + indexOffset].position = probePositionRWS;
                    }
                    else
                    {
                        m_LightVolumesCPUArray[lightIdx + indexOffset].shape    = 1;
                        m_LightVolumesCPUArray[lightIdx + indexOffset].range    = new Vector3(currentEnvLight.influenceVolume.boxSize.x / 2.0f, currentEnvLight.influenceVolume.boxSize.y / 2.0f, currentEnvLight.influenceVolume.boxSize.z / 2.0f);
                        m_LightVolumesCPUArray[lightIdx + indexOffset].position = probePositionRWS;
                    }
                    m_LightVolumesCPUArray[lightIdx + indexOffset].active     = (currentEnvLight.gameObject.activeInHierarchy ? 1 : 0);
                    m_LightVolumesCPUArray[lightIdx + indexOffset].lightIndex = (uint)lightIdx;
                    m_LightVolumesCPUArray[lightIdx + indexOffset].lightType  = 2;
                    envLightCount++;
                }
            }

            totalLightCount = punctualLightCount + areaLightCount + envLightCount;

            // Push the light volumes to the GPU
            m_LightVolumeGPUArray.SetData(m_LightVolumesCPUArray);
        }
Example #9
0
        void BuildGPULightVolumes(HDRayTracingLights lightArray)
        {
            int totalNumLights = lightArray.hdLightArray.Count + lightArray.reflectionProbeArray.Count;

            // Make sure the light volume buffer has the right size
            if (m_LightVolumesCPUArray == null || totalNumLights != m_LightVolumesCPUArray.Length)
            {
                ResizeVolumeBuffer(totalNumLights);
            }

            // Set Light volume data to the CPU buffer
            punctualLightCount = 0;
            areaLightCount     = 0;
            envLightCount      = 0;
            totalLightCount    = 0;

            int realIndex = 0;

            for (int lightIdx = 0; lightIdx < lightArray.hdLightArray.Count; ++lightIdx)
            {
                HDAdditionalLightData currentLight = lightArray.hdLightArray[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 not add it if it is null for that invalid frame
                if (currentLight != null)
                {
                    Light light = currentLight.gameObject.GetComponent <Light>();
                    if (light == null || !light.enabled)
                    {
                        continue;
                    }

                    float lightRange = light.range;
                    m_LightVolumesCPUArray[realIndex].range      = new Vector3(lightRange, lightRange, lightRange);
                    m_LightVolumesCPUArray[realIndex].position   = currentLight.gameObject.transform.position;
                    m_LightVolumesCPUArray[realIndex].active     = (currentLight.gameObject.activeInHierarchy ? 1 : 0);
                    m_LightVolumesCPUArray[realIndex].lightIndex = (uint)lightIdx;

                    if (currentLight.lightTypeExtent == LightTypeExtent.Punctual)
                    {
                        m_LightVolumesCPUArray[realIndex].lightType = 0;
                        punctualLightCount++;
                    }
                    else
                    {
                        m_LightVolumesCPUArray[realIndex].lightType = 1;
                        areaLightCount++;
                    }
                    realIndex++;
                }
            }

            int indexOffset = realIndex;

            // Set Env Light volume data to the CPU buffer
            for (int lightIdx = 0; lightIdx < lightArray.reflectionProbeArray.Count; ++lightIdx)
            {
                HDProbe currentEnvLight = lightArray.reflectionProbeArray[lightIdx];
                if (currentEnvLight != null)
                {
                    if (currentEnvLight.influenceVolume.shape == InfluenceShape.Sphere)
                    {
                        m_LightVolumesCPUArray[lightIdx + indexOffset].shape    = 0;
                        m_LightVolumesCPUArray[lightIdx + indexOffset].range    = new Vector3(currentEnvLight.influenceVolume.sphereRadius, currentEnvLight.influenceVolume.sphereRadius, currentEnvLight.influenceVolume.sphereRadius);
                        m_LightVolumesCPUArray[lightIdx + indexOffset].position = currentEnvLight.influenceToWorld.GetColumn(3);
                    }
                    else
                    {
                        m_LightVolumesCPUArray[lightIdx + indexOffset].shape    = 1;
                        m_LightVolumesCPUArray[lightIdx + indexOffset].range    = new Vector3(currentEnvLight.influenceVolume.boxSize.x / 2.0f, currentEnvLight.influenceVolume.boxSize.y / 2.0f, currentEnvLight.influenceVolume.boxSize.z / 2.0f);
                        m_LightVolumesCPUArray[lightIdx + indexOffset].position = currentEnvLight.influenceToWorld.GetColumn(3);
                    }
                    m_LightVolumesCPUArray[lightIdx + indexOffset].active     = (currentEnvLight.gameObject.activeInHierarchy ? 1 : 0);
                    m_LightVolumesCPUArray[lightIdx + indexOffset].lightIndex = (uint)lightIdx;
                    m_LightVolumesCPUArray[lightIdx + indexOffset].lightType  = 2;
                    envLightCount++;
                }
            }

            totalLightCount = punctualLightCount + areaLightCount + envLightCount;

            // Push the light volumes to the GPU
            m_LightVolumeGPUArray.SetData(m_LightVolumesCPUArray);
        }
        internal void AddProbe(HDProbe visibleProbes)
        {
            Assert.IsNotNull(m_VisibleProbes);

            m_VisibleProbes.Add(visibleProbes);
        }