public void VolumeVoxelizationPass(DensityVolumeList densityVolumes, HDCamera camera, CommandBuffer cmd, FrameSettings settings) { if (preset == VolumetricLightingPreset.Off) { return; } using (new ProfilingSample(cmd, "Volume Voxelization")) { int numVisibleVolumes = m_VisibleVolumeBounds.Count; if (numVisibleVolumes == 0) { // Clear the render target instead of running the shader. // CoreUtils.SetRenderTarget(cmd, vBuffer.GetDensityBuffer(), ClearFlag.Color, CoreUtils.clearColorAllBlack); // return; // Clearing 3D textures does not seem to work! // Use the workaround by running the full shader with 0 density. } VBuffer vBuffer = FindVBuffer(camera.GetViewID()); Debug.Assert(vBuffer != null); int w = 0, h = 0, d = 0; vBuffer.GetResolution(ref w, ref h, ref d); bool enableClustered = settings.lightLoopSettings.enableTileAndCluster; int kernel = m_VolumeVoxelizationCS.FindKernel(enableClustered ? "VolumeVoxelizationClustered" : "VolumeVoxelizationBruteforce"); 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_VolumeVoxelizationCS, cmd); cmd.SetComputeTextureParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VBufferDensity, vBuffer.GetDensityBuffer()); cmd.SetComputeBufferParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeBounds, s_VisibleVolumeBoundsBuffer); cmd.SetComputeBufferParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeProperties, s_VisibleVolumePropertiesBuffer); // TODO: set the constant buffer data only once. cmd.SetComputeMatrixParam(m_VolumeVoxelizationCS, HDShaderIDs._VBufferCoordToViewDirWS, transform); cmd.SetComputeIntParam(m_VolumeVoxelizationCS, HDShaderIDs._NumVisibleDensityVolumes, numVisibleVolumes); // The shader defines GROUP_SIZE_1D = 8. cmd.DispatchCompute(m_VolumeVoxelizationCS, kernel, (w + 7) / 8, (h + 7) / 8, 1); } }
public void VolumeVoxelizationPass(HDCamera hdCamera, CommandBuffer cmd, uint frameIndex, DensityVolumeList densityVolumes, LightLoop lightLoop) { if (!hdCamera.frameSettings.IsEnabled(FrameSettingsField.Volumetrics)) { return; } var visualEnvironment = VolumeManager.instance.stack.GetComponent <VisualEnvironment>(); if (visualEnvironment.fogType.value != FogType.Volumetric) { return; } using (new ProfilingSample(cmd, "Volume Voxelization")) { int numVisibleVolumes = m_VisibleVolumeBounds.Count; bool tiledLighting = lightLoop.HasLightToCull() && hdCamera.frameSettings.IsEnabled(FrameSettingsField.BigTilePrepass); bool highQuality = preset == VolumetricLightingPreset.High; int kernel = (tiledLighting ? 1 : 0) | (highQuality ? 2 : 0); var currFrameParams = hdCamera.vBufferParams[0]; var cvp = currFrameParams.viewportSize; Vector4 resolution = new Vector4(cvp.x, cvp.y, 1.0f / cvp.x, 1.0f / cvp.y); #if UNITY_2019_1_OR_NEWER var vFoV = hdCamera.camera.GetGateFittedFieldOfView() * Mathf.Deg2Rad; var lensShift = hdCamera.camera.GetGateFittedLensShift(); #else var vFoV = hdCamera.camera.fieldOfView * Mathf.Deg2Rad; var lensShift = Vector2.zero; #endif // Compose the matrix which allows us to compute the world space view direction. Matrix4x4 transform = HDUtils.ComputePixelCoordToWorldSpaceViewDirectionMatrix(vFoV, lensShift, resolution, hdCamera.mainViewConstants.viewMatrix, false); // Compute texel spacing at the depth of 1 meter. float unitDepthTexelSpacing = HDUtils.ComputZPlaneTexelSpacing(1.0f, vFoV, resolution.y); Texture3D volumeAtlas = DensityVolumeManager.manager.volumeAtlas.GetAtlas(); Vector4 volumeAtlasDimensions = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); if (volumeAtlas != null) { volumeAtlasDimensions.x = (float)volumeAtlas.width / volumeAtlas.depth; // 1 / number of textures volumeAtlasDimensions.y = volumeAtlas.width; volumeAtlasDimensions.z = volumeAtlas.depth; volumeAtlasDimensions.w = Mathf.Log(volumeAtlas.width, 2); // Max LoD } else { volumeAtlas = CoreUtils.blackVolumeTexture; } if (hdCamera.frameSettings.VolumeVoxelizationRunsAsync()) { // We explicitly set the big tile info even though it is set globally, since this could be running async before the PushGlobalParams cmd.SetComputeIntParam(m_VolumeVoxelizationCS, HDShaderIDs._NumTileBigTileX, lightLoop.GetNumTileBigTileX(hdCamera)); cmd.SetComputeIntParam(m_VolumeVoxelizationCS, HDShaderIDs._NumTileBigTileY, lightLoop.GetNumTileBigTileY(hdCamera)); if (tiledLighting) { cmd.SetComputeBufferParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs.g_vBigTileLightList, lightLoop.GetBigTileLightList()); } } cmd.SetComputeTextureParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VBufferDensity, m_DensityBufferHandle); cmd.SetComputeBufferParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeBounds, s_VisibleVolumeBoundsBuffer); cmd.SetComputeBufferParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeData, s_VisibleVolumeDataBuffer); cmd.SetComputeTextureParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeMaskAtlas, volumeAtlas); // TODO: set the constant buffer data only once. cmd.SetComputeMatrixParam(m_VolumeVoxelizationCS, HDShaderIDs._VBufferCoordToViewDirWS, transform); cmd.SetComputeFloatParam(m_VolumeVoxelizationCS, HDShaderIDs._VBufferUnitDepthTexelSpacing, unitDepthTexelSpacing); cmd.SetComputeIntParam(m_VolumeVoxelizationCS, HDShaderIDs._NumVisibleDensityVolumes, numVisibleVolumes); cmd.SetComputeVectorParam(m_VolumeVoxelizationCS, HDShaderIDs._VolumeMaskDimensions, volumeAtlasDimensions); int w = (int)resolution.x; int h = (int)resolution.y; // The shader defines GROUP_SIZE_1D = 8. cmd.DispatchCompute(m_VolumeVoxelizationCS, kernel, (w + 7) / 8, (h + 7) / 8, hdCamera.computePassCount); } }
public DensityVolumeList PrepareVisibleDensityVolumeList(HDCamera hdCamera, CommandBuffer cmd, float time) { DensityVolumeList densityVolumes = new DensityVolumeList(); if (!hdCamera.frameSettings.IsEnabled(FrameSettingsField.Volumetrics)) { return(densityVolumes); } var visualEnvironment = VolumeManager.instance.stack.GetComponent <VisualEnvironment>(); if (visualEnvironment.fogType.value != FogType.Volumetric) { return(densityVolumes); } using (new ProfilingSample(cmd, "Prepare Visible Density Volume List")) { Vector3 camPosition = hdCamera.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. DensityVolume[] volumes = DensityVolumeManager.manager.PrepareDensityVolumeData(cmd, hdCamera.camera, time); for (int i = 0; i < Math.Min(volumes.Length, k_MaxVisibleVolumeCount); i++) { DensityVolume volume = volumes[i]; // TODO: cache these? var obb = new OrientedBBox(Matrix4x4.TRS(volume.transform.position, volume.transform.rotation, volume.parameters.size)); // Handle camera-relative rendering. obb.center -= camOffset; // Frustum cull on the CPU for now. TODO: do it on the GPU. // TODO: account for custom near and far planes of the V-Buffer's frustum. // It's typically much shorter (along the Z axis) than the camera's frustum. // XRTODO: fix combined frustum culling if (GeometryUtils.Overlap(obb, hdCamera.frustum, 6, 8) || hdCamera.camera.stereoEnabled) { // TODO: cache these? var data = volume.parameters.ConvertToEngineData(); 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); } }
public void VolumeVoxelizationPass(HDCamera hdCamera, CommandBuffer cmd, uint frameIndex, DensityVolumeList densityVolumes) { if (!hdCamera.frameSettings.enableVolumetrics) { return; } var visualEnvironment = VolumeManager.instance.stack.GetComponent <VisualEnvironment>(); if (visualEnvironment.fogType.value != FogType.Volumetric) { return; } using (new ProfilingSample(cmd, "Volume Voxelization")) { int numVisibleVolumes = m_VisibleVolumeBounds.Count; bool highQuality = preset == VolumetricLightingPreset.High; bool enableClustered = hdCamera.frameSettings.lightLoopSettings.enableTileAndCluster; int kernel; if (highQuality) { kernel = m_VolumeVoxelizationCS.FindKernel(enableClustered ? "VolumeVoxelizationClusteredHQ" : "VolumeVoxelizationBruteforceHQ"); } else { kernel = m_VolumeVoxelizationCS.FindKernel(enableClustered ? "VolumeVoxelizationClusteredMQ" : "VolumeVoxelizationBruteforceMQ"); } var currFrameParams = hdCamera.vBufferParams[0]; var cvp = currFrameParams.viewportSize; Vector4 resolution = new Vector4(cvp.x, cvp.y, 1.0f / cvp.x, 1.0f / cvp.y); float vFoV = hdCamera.camera.fieldOfView * Mathf.Deg2Rad; // Compose the matrix which allows us to compute the world space view direction. Matrix4x4 transform = HDUtils.ComputePixelCoordToWorldSpaceViewDirectionMatrix(vFoV, resolution, hdCamera.viewMatrix, false); Texture3D volumeAtlas = DensityVolumeManager.manager.volumeAtlas.GetAtlas(); Vector4 volumeAtlasDimensions = new Vector4(0.0f, 0.0f, 0.0f, 0.0f); if (volumeAtlas != null) { volumeAtlasDimensions.x = (float)volumeAtlas.width / volumeAtlas.depth; // 1 / number of textures volumeAtlasDimensions.y = volumeAtlas.width; volumeAtlasDimensions.z = volumeAtlas.depth; volumeAtlasDimensions.w = Mathf.Log(volumeAtlas.width, 2); // Max LoD } else { volumeAtlas = CoreUtils.blackVolumeTexture; } cmd.SetComputeTextureParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VBufferDensity, m_DensityBufferHandle); cmd.SetComputeBufferParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeBounds, s_VisibleVolumeBoundsBuffer); cmd.SetComputeBufferParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeData, s_VisibleVolumeDataBuffer); cmd.SetComputeTextureParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeMaskAtlas, volumeAtlas); // TODO: set the constant buffer data only once. cmd.SetComputeMatrixParam(m_VolumeVoxelizationCS, HDShaderIDs._VBufferCoordToViewDirWS, transform); cmd.SetComputeIntParam(m_VolumeVoxelizationCS, HDShaderIDs._NumVisibleDensityVolumes, numVisibleVolumes); cmd.SetComputeVectorParam(m_VolumeVoxelizationCS, HDShaderIDs._VolumeMaskDimensions, volumeAtlasDimensions); int w = (int)resolution.x; int h = (int)resolution.y; // The shader defines GROUP_SIZE_1D = 8. cmd.DispatchCompute(m_VolumeVoxelizationCS, kernel, (w + 7) / 8, (h + 7) / 8, 1); } }
public void VolumeVoxelizationPass(DensityVolumeList densityVolumes, HDCamera camera, CommandBuffer cmd, FrameSettings settings, uint frameIndex) { if (preset == VolumetricLightingPreset.Off) { return; } var visualEnvironment = VolumeManager.instance.stack.GetComponent <VisualEnvironment>(); if (visualEnvironment.fogType != FogType.Volumetric) { return; } VBuffer vBuffer = FindVBuffer(camera.GetViewID()); if (vBuffer == null) { return; } using (new ProfilingSample(cmd, "Volume Voxelization")) { int numVisibleVolumes = m_VisibleVolumeBounds.Count; if (numVisibleVolumes == 0) { // Clear the render target instead of running the shader. // Note: the clear must take the global fog into account! // CoreUtils.SetRenderTarget(cmd, vBuffer.GetDensityBuffer(), ClearFlag.Color, CoreUtils.clearColorAllBlack); // return; // Clearing 3D textures does not seem to work! // Use the workaround by running the full shader with 0 density } bool enableClustered = settings.lightLoopSettings.enableTileAndCluster; int kernel = m_VolumeVoxelizationCS.FindKernel(enableClustered ? "VolumeVoxelizationClustered" : "VolumeVoxelizationBruteforce"); var frameParams = vBuffer.GetParameters(frameIndex); Vector4 resolution = frameParams.resolution; float vFoV = camera.camera.fieldOfView * Mathf.Deg2Rad; // Compose the matrix which allows us to compute the world space view direction. Matrix4x4 transform = HDUtils.ComputePixelCoordToWorldSpaceViewDirectionMatrix(vFoV, resolution, camera.viewMatrix, false); Texture3D volumeAtlas = DensityVolumeManager.manager.volumeAtlas.volumeAtlas; Vector2 volumeAtlasDimensions = new Vector2(0.0f, 0.0f); if (volumeAtlas != null) { volumeAtlasDimensions.x = volumeAtlas.width / volumeAtlas.depth; // 1 / number of textures volumeAtlasDimensions.y = 1.0f / volumeAtlas.width; } cmd.SetComputeTextureParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VBufferDensity, vBuffer.GetDensityBuffer()); cmd.SetComputeBufferParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeBounds, s_VisibleVolumeBoundsBuffer); cmd.SetComputeBufferParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeData, s_VisibleVolumeDataBuffer); cmd.SetComputeTextureParam(m_VolumeVoxelizationCS, kernel, HDShaderIDs._VolumeMaskAtlas, volumeAtlas); // TODO: set the constant buffer data only once. cmd.SetComputeMatrixParam(m_VolumeVoxelizationCS, HDShaderIDs._VBufferCoordToViewDirWS, transform); cmd.SetComputeIntParam(m_VolumeVoxelizationCS, HDShaderIDs._NumVisibleDensityVolumes, numVisibleVolumes); cmd.SetComputeVectorParam(m_VolumeVoxelizationCS, HDShaderIDs._VolumeMaskDimensions, volumeAtlasDimensions); int w = (int)resolution.x; int h = (int)resolution.y; // The shader defines GROUP_SIZE_1D = 8. cmd.DispatchCompute(m_VolumeVoxelizationCS, kernel, (w + 7) / 8, (h + 7) / 8, 1); } }
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. DensityVolume[] volumes = DensityVolumeManager.manager.PrepareDensityVolumeData(cmd); for (int i = 0; i < Math.Min(volumes.Length, k_MaxVisibleVolumeCount); i++) { DensityVolume 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); } }