public void PushGlobalParams(HDCamera camera, CommandBuffer cmd)
        {
            if (preset == VolumetricLightingPreset.Off)
            {
                return;
            }

            HomogeneousDensityVolume globalVolume = HomogeneousDensityVolume.GetGlobalHomogeneousDensityVolume();

            // TODO: may want to cache these results somewhere.
            VolumeProperties globalVolumeProperties = (globalVolume != null) ? globalVolume.volumeParameters.GetProperties()
                                                                            : VolumeProperties.GetNeutralVolumeProperties();

            float asymmetry = globalVolume != null ? globalVolume.volumeParameters.asymmetry : 0;

            cmd.SetGlobalVector(HDShaderIDs._GlobalScattering, globalVolumeProperties.scattering);
            cmd.SetGlobalFloat(HDShaderIDs._GlobalExtinction, globalVolumeProperties.extinction);
            cmd.SetGlobalFloat(HDShaderIDs._GlobalAsymmetry, asymmetry);

            int w = 0, h = 0, d = 0;

            ComputeVBufferResolutionAndScale(preset, (int)camera.screenSize.x, (int)camera.screenSize.y, ref w, ref h, ref d);

            VBuffer vBuffer = FindVBuffer(camera.GetViewID());

            Debug.Assert(vBuffer != null);

            SetPreconvolvedAmbientLightProbe(cmd, asymmetry);
            cmd.SetGlobalVector(HDShaderIDs._VBufferResolution, new Vector4(w, h, 1.0f / w, 1.0f / h));
            cmd.SetGlobalVector(HDShaderIDs._VBufferSliceCount, new Vector4(d, 1.0f / d));
            cmd.SetGlobalVector(HDShaderIDs._VBufferDepthEncodingParams, ComputeLogarithmicDepthEncodingParams(m_VBufferNearPlane, m_VBufferFarPlane, k_LogScale));
            cmd.SetGlobalVector(HDShaderIDs._VBufferDepthDecodingParams, ComputeLogarithmicDepthDecodingParams(m_VBufferNearPlane, m_VBufferFarPlane, k_LogScale));
            cmd.SetGlobalTexture(HDShaderIDs._VBufferLighting, vBuffer.GetLightingIntegralBuffer());
        }
Beispiel #2
0
 public void DeRegisterVolume(HomogeneousDensityVolume volume)
 {
     if (volumes.Contains(volume))
     {
         volumes.Remove(volume);
     }
 }
Beispiel #3
0
        public DensityVolumeList PrepareVisibleDensityVolumeList(HDCamera camera, CommandBuffer cmd)
        {
            DensityVolumeList densityVolumes = new DensityVolumeList();

            if (preset == VolumetricLightingPreset.Off)
            {
                return(densityVolumes);
            }

            using (new ProfilingSample(cmd, "Prepare Visible Density Volume List"))
            {
                Vector3 camPosition = camera.camera.transform.position;
                Vector3 camOffset   = Vector3.zero; // World-origin-relative

                if (ShaderConfig.s_CameraRelativeRendering != 0)
                {
                    camOffset = camPosition; // Camera-relative
                }

                m_VisibleVolumeBounds.Clear();
                m_VisibleVolumeProperties.Clear();

                // Collect all visible finite volume data, and upload it to the GPU.
                HomogeneousDensityVolume[] volumes = Object.FindObjectsOfType(typeof(HomogeneousDensityVolume)) as HomogeneousDensityVolume[];

                for (int i = 0; i < Math.Min(volumes.Length, k_MaxVisibleVolumeCount); i++)
                {
                    HomogeneousDensityVolume volume = volumes[i];

                    // Only test active finite volumes.
                    if (volume.enabled && volume.parameters.IsLocalVolume())
                    {
                        // TODO: cache these?
                        var obb = OrientedBBox.Create(volume.transform);

                        // Handle camera-relative rendering.
                        obb.center -= camOffset;

                        // Frustum cull on the CPU for now. TODO: do it on the GPU.
                        if (GeometryUtils.Overlap(obb, camera.frustum, 6, 8))
                        {
                            // TODO: cache these?
                            var properties = volume.parameters.GetProperties();

                            m_VisibleVolumeBounds.Add(obb);
                            m_VisibleVolumeProperties.Add(properties);
                        }
                    }
                }

                s_VisibleVolumeBoundsBuffer.SetData(m_VisibleVolumeBounds);
                s_VisibleVolumePropertiesBuffer.SetData(m_VisibleVolumeProperties);

                // Fill the struct with pointers in order to share the data with the light loop.
                densityVolumes.bounds     = m_VisibleVolumeBounds;
                densityVolumes.properties = m_VisibleVolumeProperties;

                return(densityVolumes);
            }
        }
        public void VolumetricLightingPass(HDCamera camera, CommandBuffer cmd, FrameSettings frameSettings)
        {
            if (preset == VolumetricLightingPreset.Off)
            {
                return;
            }

            using (new ProfilingSample(cmd, "Volumetric Lighting"))
            {
                VBuffer vBuffer = FindVBuffer(camera.GetViewID());
                Debug.Assert(vBuffer != null);

                HomogeneousDensityVolume globalVolume = HomogeneousDensityVolume.GetGlobalHomogeneousDensityVolume();
                float asymmetry = globalVolume != null ? globalVolume.volumeParameters.asymmetry : 0;

                if (globalVolume == null)
                {
                    // Clear the render target instead of running the shader.
                    // CoreUtils.SetRenderTarget(cmd, GetVBufferLightingIntegral(viewOffset), ClearFlag.Color, CoreUtils.clearColorAllBlack);
                    // return;

                    // Clearing 3D textures does not seem to work!
                    // Use the workaround by running the full shader with no volume.
                }

                bool enableClustered    = frameSettings.lightLoopSettings.enableTileAndCluster;
                bool enableReprojection = Application.isPlaying && camera.camera.cameraType == CameraType.Game;

                int kernel;

                if (enableReprojection)
                {
                    // Only available in the Play Mode because all the frame counters in the Edit Mode are broken.
                    kernel = m_VolumetricLightingCS.FindKernel(enableClustered ? "VolumetricLightingClusteredReproj"
                                                                           : "VolumetricLightingAllLightsReproj");
                }
                else
                {
                    kernel = m_VolumetricLightingCS.FindKernel(enableClustered ? "VolumetricLightingClustered"
                                                                           : "VolumetricLightingAllLights");
                }

                int w = 0, h = 0, d = 0;
                ComputeVBufferResolutionAndScale(preset, (int)camera.screenSize.x, (int)camera.screenSize.y, ref w, ref h, ref d);

                // Compose the matrix which allows us to compute the world space view direction.
                float     vFoV       = camera.camera.fieldOfView * Mathf.Deg2Rad;
                Vector4   resolution = new Vector4(w, h, 1.0f / w, 1.0f / h);
                Matrix4x4 transform  = HDUtils.ComputePixelCoordToWorldSpaceViewDirectionMatrix(vFoV, resolution, camera.viewMatrix, false);

                camera.SetupComputeShader(m_VolumetricLightingCS, cmd);

                Vector2[] xySeq = GetHexagonalClosePackedSpheres7();

                // This is a sequence of 7 equidistant numbers from 1/14 to 13/14.
                // Each of them is the centroid of the interval of length 2/14.
                // They've been rearranged in a sequence of pairs {small, large}, s.t. (small + large) = 1.
                // That way, the running average position is close to 0.5.
                // | 6 | 2 | 4 | 1 | 5 | 3 | 7 |
                // |   |   |   | o |   |   |   |
                // |   | o |   | x |   |   |   |
                // |   | x |   | x |   | o |   |
                // |   | x | o | x |   | x |   |
                // |   | x | x | x | o | x |   |
                // | o | x | x | x | x | x |   |
                // | x | x | x | x | x | x | o |
                // | x | x | x | x | x | x | x |
                float[] zSeq = { 7.0f / 14.0f, 3.0f / 14.0f, 11.0f / 14.0f, 5.0f / 14.0f, 9.0f / 14.0f, 1.0f / 14.0f, 13.0f / 14.0f };

                int     rfc         = Time.renderedFrameCount;
                int     sampleIndex = rfc % 7;
                Vector4 offset      = new Vector4(xySeq[sampleIndex].x, xySeq[sampleIndex].y, zSeq[sampleIndex], rfc);

                // TODO: set 'm_VolumetricLightingPreset'.
                cmd.SetComputeFloatParam(m_VolumetricLightingCS, HDShaderIDs._CornetteShanksConstant, CornetteShanksPhasePartConstant(asymmetry));
                cmd.SetComputeVectorParam(m_VolumetricLightingCS, HDShaderIDs._VBufferSampleOffset, offset);
                cmd.SetComputeMatrixParam(m_VolumetricLightingCS, HDShaderIDs._VBufferCoordToViewDirWS, transform);
                cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingIntegral, vBuffer.GetLightingIntegralBuffer()); // Write
                if (enableReprojection)
                {
                    cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingFeedback, vBuffer.GetLightingFeedbackBuffer()); // Write
                    cmd.SetComputeTextureParam(m_VolumetricLightingCS, kernel, HDShaderIDs._VBufferLightingHistory, vBuffer.GetLightingHistoryBuffer());   // Read
                }

                // The shader defines GROUP_SIZE_1D = 16.
                cmd.DispatchCompute(m_VolumetricLightingCS, kernel, (w + 15) / 16, (h + 15) / 16, 1);
            }
        }
Beispiel #5
0
 public void RegisterVolume(HomogeneousDensityVolume volume)
 {
     volumes.Add(volume);
 }
Beispiel #6
0
        public DensityVolumeList PrepareVisibleDensityVolumeList(HDCamera camera, CommandBuffer cmd)
        {
            DensityVolumeList densityVolumes = new DensityVolumeList();

            if (preset == VolumetricLightingPreset.Off)
            {
                return(densityVolumes);
            }

            var visualEnvironment = VolumeManager.instance.stack.GetComponent <VisualEnvironment>();

            if (visualEnvironment.fogType != FogType.Volumetric)
            {
                return(densityVolumes);
            }

            VBuffer vBuffer = FindVBuffer(camera.GetViewID());

            if (vBuffer == null)
            {
                return(densityVolumes);
            }

            using (new ProfilingSample(cmd, "Prepare Visible Density Volume List"))
            {
                Vector3 camPosition = camera.camera.transform.position;
                Vector3 camOffset   = Vector3.zero; // World-origin-relative

                if (ShaderConfig.s_CameraRelativeRendering != 0)
                {
                    camOffset = camPosition; // Camera-relative
                }

                m_VisibleVolumeBounds.Clear();
                m_VisibleVolumeData.Clear();

                // Collect all visible finite volume data, and upload it to the GPU.
                HomogeneousDensityVolume[] volumes = DensityVolumeManager.manager.GetAllVolumes();

                for (int i = 0; i < Math.Min(volumes.Length, k_MaxVisibleVolumeCount); i++)
                {
                    HomogeneousDensityVolume volume = volumes[i];

                    // TODO: cache these?
                    var obb = OrientedBBox.Create(volume.transform);

                    // Handle camera-relative rendering.
                    obb.center -= camOffset;

                    // Frustum cull on the CPU for now. TODO: do it on the GPU.
                    if (GeometryUtils.Overlap(obb, camera.frustum, 6, 8))
                    {
                        // TODO: cache these?
                        var data = volume.parameters.GetData();

                        m_VisibleVolumeBounds.Add(obb);
                        m_VisibleVolumeData.Add(data);
                    }
                }

                s_VisibleVolumeBoundsBuffer.SetData(m_VisibleVolumeBounds);
                s_VisibleVolumeDataBuffer.SetData(m_VisibleVolumeData);

                // Fill the struct with pointers in order to share the data with the light loop.
                densityVolumes.bounds  = m_VisibleVolumeBounds;
                densityVolumes.density = m_VisibleVolumeData;

                return(densityVolumes);
            }
        }