You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
482 lines
24 KiB
482 lines
24 KiB
using Unity.Collections;
|
|
using Unity.Mathematics;
|
|
using UnityEngine.Experimental.Rendering;
|
|
|
|
namespace UnityEngine.Rendering.HighDefinition
|
|
{
|
|
partial class WaterSystem
|
|
{
|
|
const float k_FoamIntensityThreshold = 0.015f;
|
|
|
|
const string k_DeformPassName = nameof(WaterDecal.PassType.Deformation);
|
|
const string k_FoamPassName = nameof(WaterDecal.PassType.Foam);
|
|
const string k_SimulationMaskPassName = nameof(WaterDecal.PassType.SimulationMask);
|
|
const string k_LargeCurrentPassName = nameof(WaterDecal.PassType.LargeCurrent);
|
|
const string k_RipplesCurrentPassName = nameof(WaterDecal.PassType.RipplesCurrent);
|
|
|
|
bool m_ActiveWaterDecals;
|
|
int m_DecalAtlasSize;
|
|
int m_MaxDecalCount;
|
|
|
|
GlobalKeyword horizontalDeformationKeyword;
|
|
|
|
// Buffers used to hold all the water foam generators
|
|
WaterDecalData[] m_WaterDecalDataCPU;
|
|
ComputeBuffer m_WaterDecalData;
|
|
|
|
// CPU culling
|
|
Vector4[] m_WaterRegions;
|
|
VisibleDecalData[] m_VisibleDecals;
|
|
int m_NumActiveWaterDecals = 0;
|
|
float m_MaxWaterDeformation = 0;
|
|
bool m_ActiveFoam;
|
|
internal bool m_ActiveMask, m_ActiveDeformation;
|
|
internal bool m_ActiveLargeCurrent, m_ActiveRipplesCurrent;
|
|
|
|
internal bool HasActiveFoam() => m_ActiveFoam || (m_MaxInjectedFoamIntensity > k_FoamIntensityThreshold);
|
|
|
|
// Deformation
|
|
ComputeShader m_WaterDeformationCS;
|
|
int m_FilterDeformationKernel;
|
|
int m_EvaluateDeformationSurfaceGradientKernel;
|
|
|
|
// Foam
|
|
ComputeShader m_WaterFoamCS;
|
|
int m_ReprojectFoamKernel;
|
|
int m_AttenuateFoamKernel;
|
|
|
|
// Decals
|
|
Material m_DecalMaterial;
|
|
int m_DeformationDecalPass;
|
|
int m_FoamDecalPass;
|
|
int m_MaskDecalPass;
|
|
int m_LargeCurrentDecalPass;
|
|
int m_RipplesCurrentDecalPass;
|
|
int m_AttenuationPass;
|
|
|
|
// Keeps track of maximum possible foam intensity in to estimate when there is no more foam
|
|
float m_MaxInjectedFoamIntensity = 0.0f;
|
|
|
|
// Atlas used to hold the various decal output
|
|
// R: Deformation, G: Surface Foam, B: Deep Foam
|
|
// RGB: Simulation Mask for each band, A: Simulation Foam Mask
|
|
// RG: Large Current Direction, B: Large Current Influence
|
|
// RG: Ripples Current Direction, B: Ripples Current Influence
|
|
// Note: deformation and foam are rendered together cause they often share intermediate computations
|
|
PowerOfTwoTextureAtlas m_DecalAtlas;
|
|
|
|
void InitializeWaterDecals()
|
|
{
|
|
m_ActiveWaterDecals = m_RenderPipeline.asset.currentPlatformRenderPipelineSettings.supportWaterDecals;
|
|
if (!m_ActiveWaterDecals)
|
|
return;
|
|
|
|
horizontalDeformationKeyword = GlobalKeyword.Create("HORIZONTAL_DEFORMATION");
|
|
|
|
m_DecalAtlasSize = (int)m_RenderPipeline.asset.currentPlatformRenderPipelineSettings.waterDecalAtlasSize;
|
|
m_MaxDecalCount = m_RenderPipeline.asset.currentPlatformRenderPipelineSettings.maximumWaterDecalCount;
|
|
|
|
m_WaterRegions = new Vector4[k_MaxNumWaterSurfaceProfiles];
|
|
m_VisibleDecals = new VisibleDecalData[m_MaxDecalCount];
|
|
|
|
m_WaterDecalDataCPU = new WaterDecalData[m_MaxDecalCount];
|
|
m_WaterDecalData = new ComputeBuffer(m_MaxDecalCount, System.Runtime.InteropServices.Marshal.SizeOf<WaterDecalData>());
|
|
|
|
m_DecalAtlas = new PowerOfTwoTextureAtlas(m_DecalAtlasSize, 0, GraphicsFormat.R16G16B16A16_SNorm, name: "Water Decal Atlas", useMipMap: false);
|
|
|
|
// Decals
|
|
m_DecalMaterial = CoreUtils.CreateEngineMaterial(m_RuntimeResources.waterDecalPS);
|
|
m_DeformationDecalPass = m_DecalMaterial.FindPass("DeformationDecal");
|
|
m_FoamDecalPass = m_DecalMaterial.FindPass("FoamDecal");
|
|
m_MaskDecalPass = m_DecalMaterial.FindPass("MaskDecal");
|
|
m_LargeCurrentDecalPass = m_DecalMaterial.FindPass("LargeCurrentDecal");
|
|
m_RipplesCurrentDecalPass = m_DecalMaterial.FindPass("RipplesCurrentDecal");
|
|
m_AttenuationPass = m_DecalMaterial.FindPass("FoamAttenuation");
|
|
|
|
// Deformation
|
|
m_WaterDeformationCS = m_RuntimeResources.waterDeformationCS;
|
|
m_FilterDeformationKernel = m_WaterDeformationCS.FindKernel("FilterDeformation");
|
|
m_EvaluateDeformationSurfaceGradientKernel = m_WaterDeformationCS.FindKernel("EvaluateDeformationSurfaceGradient");
|
|
|
|
// Foam
|
|
m_WaterFoamCS = m_RuntimeResources.waterFoamCS;
|
|
m_ReprojectFoamKernel = m_WaterFoamCS.FindKernel("ReprojectFoam");
|
|
m_AttenuateFoamKernel = m_WaterFoamCS.FindKernel("AttenuateFoam");
|
|
}
|
|
|
|
void ReleaseWaterDecals()
|
|
{
|
|
if (!m_ActiveWaterDecals)
|
|
return;
|
|
|
|
CoreUtils.SafeRelease(m_WaterDecalData);
|
|
CoreUtils.Destroy(m_DecalMaterial);
|
|
m_DecalAtlas.Release();
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
internal void UpdateWaterDecalAtlas(Shader shader)
|
|
{
|
|
// When a water decal shadergraph is saved, update all decals that are affected
|
|
foreach (var decal in WaterDecal.instances)
|
|
{
|
|
if (decal.material != null && decal.material.shader == shader)
|
|
decal.RequestUpdate();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static internal bool IsAffectingProperty(WaterDecal decal, int nameId)
|
|
{
|
|
if (decal.material.HasProperty(nameId))
|
|
return decal.material.GetFloat(nameId) != 0.0f;
|
|
return false;
|
|
}
|
|
|
|
struct VisibleDecalData
|
|
{
|
|
public WaterDecal decal;
|
|
public int materialId;
|
|
|
|
public readonly int resX => decal.resolution.x;
|
|
public readonly int resY => decal.resolution.y;
|
|
public int MaterialId(WaterDecal.PassType passType)
|
|
{
|
|
int hash = 17;
|
|
hash = hash * 23 + (int)passType;
|
|
hash = hash * 23 + materialId;
|
|
return hash;
|
|
}
|
|
}
|
|
|
|
bool CullWaterDecals()
|
|
{
|
|
// Update decal regions based on camera position
|
|
Transform anchor = Camera.main != null ? Camera.main.transform : null;
|
|
#if UNITY_EDITOR
|
|
if (!UnityEditor.EditorApplication.isPlaying)
|
|
anchor = UnityEditor.SceneView.lastActiveSceneView?.camera.transform;
|
|
#endif
|
|
|
|
var waterSurfaces = WaterSurface.instancesAsArray;
|
|
int numWaterSurfaces = Mathf.Min(WaterSurface.instanceCount, k_MaxNumWaterSurfaceProfiles);
|
|
for (int i = 0; i < numWaterSurfaces; ++i)
|
|
{
|
|
waterSurfaces[i].UpdateDecalRegion(anchor);
|
|
waterSurfaces[i].GetDecalRegion(out var decalRegionCenter, out var decalRegionSize);
|
|
m_WaterRegions[i] = new Vector4(decalRegionCenter.x, decalRegionCenter.y, decalRegionSize.x * 0.5f, decalRegionSize.y * 0.5f);
|
|
}
|
|
|
|
// Reset counters
|
|
m_NumActiveWaterDecals = 0;
|
|
m_MaxWaterDeformation = 0.0f;
|
|
m_ActiveMask = m_ActiveDeformation = m_ActiveFoam = false;
|
|
m_ActiveLargeCurrent = m_ActiveRipplesCurrent = false;
|
|
|
|
// Reserve slot in atlas for decals affecting at least one surface
|
|
bool needRelayout = false;
|
|
foreach (var decal in WaterDecal.instances)
|
|
{
|
|
if (!decal.IsValidMaterial())
|
|
continue;
|
|
|
|
float3 scale = decal.effectiveScale;
|
|
Vector3 posWS = decal.transform.position;
|
|
float2 size = (float2)decal.regionSize * 0.5f * scale.xz;
|
|
bool visible = false;
|
|
|
|
bool affectDeformation = IsAffectingProperty(decal, HDShaderIDs._AffectDeformation);
|
|
bool affectFoam = IsAffectingProperty(decal, HDShaderIDs._AffectsFoam);
|
|
bool affectMask = IsAffectingProperty(decal, HDShaderIDs._AffectsSimulationMask);
|
|
bool affectLarge = IsAffectingProperty(decal, HDShaderIDs._AffectsLargeCurrent);
|
|
bool affectRipples = IsAffectingProperty(decal, HDShaderIDs._AffectsRipplesCurrent);
|
|
|
|
// Decals can be rotated, use a bounding circle to simplify computations
|
|
float radiusSquare = size.x * size.x + size.y * size.y;
|
|
for (int i = 0; i < numWaterSurfaces; i++)
|
|
{
|
|
float distX = Mathf.Abs(posWS.x - m_WaterRegions[i].x) - m_WaterRegions[i].z;
|
|
float distY = Mathf.Abs(posWS.z - m_WaterRegions[i].y) - m_WaterRegions[i].w;
|
|
|
|
if (distX > 0.0f && distX*distX > radiusSquare) continue;
|
|
if (distY > 0.0f && distY*distY > radiusSquare) continue;
|
|
|
|
visible |= waterSurfaces[i].deformation && affectDeformation;
|
|
visible |= waterSurfaces[i].foam && affectFoam;
|
|
if (m_EnableDecalWorkflow)
|
|
{
|
|
visible |= (waterSurfaces[i].simulationMask || waterSurfaces[i].supportSimulationFoamMask) && affectMask;
|
|
|
|
if (waterSurfaces[i].surfaceType == WaterSurfaceType.Pool)
|
|
{
|
|
visible |= waterSurfaces[i].supportRipplesCurrent && affectRipples;
|
|
}
|
|
else
|
|
{
|
|
visible |= waterSurfaces[i].supportLargeCurrent && affectLarge;
|
|
visible |= waterSurfaces[i].UsesRipplesCurrent() && affectRipples;
|
|
}
|
|
}
|
|
|
|
if (visible)
|
|
break;
|
|
}
|
|
|
|
// If the decal is visible, prepare GPU data and mark atlas slot as used
|
|
if (visible)
|
|
{
|
|
if (m_NumActiveWaterDecals >= m_MaxDecalCount)
|
|
{
|
|
#if UNITY_EDITOR || DEVELOPMENT_BUILD
|
|
Debug.LogWarning("Maximum amount of visible Water Decals reached. Some of them will be ignored.");
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
ref var cpuData = ref m_VisibleDecals[m_NumActiveWaterDecals];
|
|
cpuData.materialId = decal.GetMaterialAtlasingId();
|
|
cpuData.decal = decal;
|
|
|
|
ref var gpuData = ref m_WaterDecalDataCPU[m_NumActiveWaterDecals];
|
|
|
|
float angle = -decal.transform.eulerAngles.y * Mathf.Deg2Rad;
|
|
gpuData.positionXZ.Set(posWS.x, posWS.z);
|
|
gpuData.forwardXZ.Set(Mathf.Cos(angle), Mathf.Sin(angle));
|
|
gpuData.regionSize = 2.0f * size;
|
|
|
|
gpuData.amplitude = decal.amplitude * scale.y;
|
|
gpuData.surfaceFoamDimmer = decal.surfaceFoamDimmer;
|
|
gpuData.deepFoamDimmer = decal.deepFoamDimmer;
|
|
|
|
if (decal.updateMode == CustomRenderTextureUpdateMode.Realtime)
|
|
decal.updateCount++;
|
|
|
|
bool ReserveAtlasSpace(WaterDecal.PassType passType, in VisibleDecalData cpuData) => m_DecalAtlas.ReserveSpace(cpuData.MaterialId(passType), cpuData.resX, cpuData.resY);
|
|
|
|
if (affectDeformation && !ReserveAtlasSpace(WaterDecal.PassType.Deformation, in cpuData))
|
|
needRelayout = true;
|
|
if (affectFoam && !ReserveAtlasSpace(WaterDecal.PassType.Foam, in cpuData))
|
|
needRelayout = true;
|
|
if (affectMask && !ReserveAtlasSpace(WaterDecal.PassType.SimulationMask, in cpuData))
|
|
needRelayout = true;
|
|
if (affectLarge && !ReserveAtlasSpace(WaterDecal.PassType.LargeCurrent, in cpuData))
|
|
needRelayout = true;
|
|
if (affectRipples && !ReserveAtlasSpace(WaterDecal.PassType.RipplesCurrent, in cpuData))
|
|
needRelayout = true;
|
|
|
|
m_NumActiveWaterDecals++;
|
|
m_ActiveMask |= affectMask;
|
|
m_ActiveDeformation |= affectDeformation;
|
|
m_ActiveFoam |= affectFoam;
|
|
m_ActiveLargeCurrent |= affectLarge;
|
|
m_ActiveRipplesCurrent |= affectRipples;
|
|
if (affectDeformation)
|
|
m_MaxWaterDeformation = Mathf.Max(m_MaxWaterDeformation, Mathf.Abs(decal.amplitude));
|
|
}
|
|
}
|
|
|
|
// Relayout if needed
|
|
if (needRelayout && !m_DecalAtlas.RelayoutEntries())
|
|
{
|
|
Debug.LogError($"No more space in the Water Decal Atlas. To solve this issue, increase the resolution of the atlas in the current HDRP asset.");
|
|
m_NumActiveWaterDecals = 0;
|
|
m_ActiveMask = m_ActiveDeformation = m_ActiveFoam = false;
|
|
m_ActiveLargeCurrent = m_ActiveRipplesCurrent = false;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void ProcessWaterDecals(CommandBuffer cmd)
|
|
{
|
|
// Render decals in atlas if needed
|
|
void FetchCoords(in VisibleDecalData cpuData, WaterDecal.PassType passType, string passName, ref Vector4 scaleBias)
|
|
{
|
|
int id = cpuData.MaterialId(passType);
|
|
if (!m_DecalAtlas.IsCached(out scaleBias, id))
|
|
{
|
|
// Used in WaterDecal.shader to discard decal
|
|
scaleBias.x = -1;
|
|
}
|
|
else if (m_DecalAtlas.NeedsUpdate(id, cpuData.decal.updateCount, false))
|
|
{
|
|
// It would be nice to somehow cache these
|
|
int pass = cpuData.decal.material.FindPass(passName);
|
|
|
|
cmd.SetRenderTarget(m_DecalAtlas.AtlasTexture);
|
|
cmd.SetViewport(new Rect(scaleBias.z * m_DecalAtlasSize, scaleBias.w * m_DecalAtlasSize, scaleBias.x * m_DecalAtlasSize, scaleBias.y * m_DecalAtlasSize));
|
|
cmd.DrawProcedural(Matrix4x4.identity, cpuData.decal.material, pass, MeshTopology.Triangles, 3, 1, cpuData.decal.mpb);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < m_NumActiveWaterDecals; ++i)
|
|
{
|
|
ref var cpuData = ref m_VisibleDecals[i];
|
|
ref var gpuData = ref m_WaterDecalDataCPU[i];
|
|
|
|
// Note: we could have all of these in the same pass like for regular SG decals since they render to the same atlas
|
|
FetchCoords(in cpuData, WaterDecal.PassType.Deformation, k_DeformPassName, ref gpuData.deformScaleOffset);
|
|
FetchCoords(in cpuData, WaterDecal.PassType.Foam, k_FoamPassName, ref gpuData.foamScaleOffset);
|
|
FetchCoords(in cpuData, WaterDecal.PassType.SimulationMask, k_SimulationMaskPassName, ref gpuData.maskScaleOffset);
|
|
FetchCoords(in cpuData, WaterDecal.PassType.LargeCurrent, k_LargeCurrentPassName, ref gpuData.largeCurrentScaleOffset);
|
|
FetchCoords(in cpuData, WaterDecal.PassType.RipplesCurrent, k_RipplesCurrentPassName, ref gpuData.ripplesCurrentScaleOffset);
|
|
}
|
|
|
|
m_DecalAtlas.ResetRequestedTexture();
|
|
}
|
|
|
|
void UpdateWaterDecalData(CommandBuffer cmd)
|
|
{
|
|
if (!m_ActiveWaterDecals)
|
|
return;
|
|
|
|
if (CullWaterDecals())
|
|
ProcessWaterDecals(cmd);
|
|
m_WaterDecalData.SetData(m_WaterDecalDataCPU);
|
|
cmd.SetGlobalBuffer(HDShaderIDs._WaterDecalData, m_WaterDecalData);
|
|
cmd.SetGlobalTexture(HDShaderIDs._WaterDecalAtlas, m_DecalAtlas.AtlasTexture);
|
|
}
|
|
|
|
void UpdateWaterDecals(CommandBuffer cmd, WaterSurface currentWater)
|
|
{
|
|
if (!m_ActiveWaterDecals)
|
|
return;
|
|
|
|
var perSurfaceCB = m_ShaderVariablesWaterPerSurface[currentWater.surfaceIndex];
|
|
currentWater.mpb.SetConstantBuffer(HDShaderIDs._ShaderVariablesWaterPerSurface, perSurfaceCB, 0, perSurfaceCB.stride);
|
|
currentWater.CheckDeformationResources(HDRenderPipeline.currentAsset.currentPlatformRenderPipelineSettings.supportWaterHorizontalDeformation);
|
|
currentWater.CheckFoamResources(cmd);
|
|
currentWater.CheckMaskResources();
|
|
currentWater.CheckCurrentResources();
|
|
|
|
// Needed to see decals in wireframe mode
|
|
bool wireframe = GL.wireframe;
|
|
if (wireframe)
|
|
cmd.SetWireframe(false);
|
|
|
|
if (currentWater.foam)
|
|
{
|
|
ref var cb = ref m_ShaderVariablesPerSurfaceArray[currentWater.surfaceIndex];
|
|
|
|
// Track if reprojected foam is still visible even when no generators are alive
|
|
bool activeFoam = HasActiveFoam();
|
|
if (m_ActiveFoam)
|
|
m_MaxInjectedFoamIntensity = 1.0f;
|
|
else if (activeFoam)
|
|
{
|
|
// Attenuation formula must be in sync with WaterDecal.shader
|
|
m_MaxInjectedFoamIntensity *= Mathf.Exp(-cb._DeltaTime * cb._FoamPersistenceMultiplier * 0.5f);
|
|
}
|
|
|
|
if (activeFoam)
|
|
{
|
|
using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.WaterDecalFoam)))
|
|
{
|
|
RTHandle currentFoamBuffer = currentWater.FoamBuffer();
|
|
|
|
// Check if we need to reproj
|
|
if (currentWater.previousFoamRegionScaleOffset.x != cb._DecalRegionScale.x ||
|
|
currentWater.previousFoamRegionScaleOffset.y != cb._DecalRegionScale.y ||
|
|
currentWater.previousFoamRegionScaleOffset.z != cb._DecalRegionOffset.x ||
|
|
currentWater.previousFoamRegionScaleOffset.w != cb._DecalRegionOffset.y)
|
|
{
|
|
RTHandle tmpFoamBuffer = currentWater.TmpFoamBuffer();
|
|
BindPerSurfaceConstantBuffer(cmd, m_WaterFoamCS, perSurfaceCB);
|
|
|
|
// Reproject the previous frame's foam buffer
|
|
int tileC = HDUtils.DivRoundUp((int)currentWater.foamResolution, 8);
|
|
cmd.SetComputeVectorParam(m_WaterFoamCS, HDShaderIDs._PreviousFoamRegionScaleOffset, currentWater.previousFoamRegionScaleOffset);
|
|
cmd.SetComputeTextureParam(m_WaterFoamCS, m_ReprojectFoamKernel, HDShaderIDs._WaterFoamBuffer, currentFoamBuffer);
|
|
cmd.SetComputeTextureParam(m_WaterFoamCS, m_ReprojectFoamKernel, HDShaderIDs._WaterFoamBufferRW, tmpFoamBuffer);
|
|
cmd.DispatchCompute(m_WaterFoamCS, m_ReprojectFoamKernel, tileC, tileC, 1);
|
|
|
|
// Attenuate the foam buffer
|
|
cmd.SetComputeTextureParam(m_WaterFoamCS, m_AttenuateFoamKernel, HDShaderIDs._WaterFoamBuffer, tmpFoamBuffer);
|
|
cmd.SetComputeTextureParam(m_WaterFoamCS, m_AttenuateFoamKernel, HDShaderIDs._WaterFoamBufferRW, currentFoamBuffer);
|
|
cmd.DispatchCompute(m_WaterFoamCS, m_AttenuateFoamKernel, tileC, tileC, 1);
|
|
|
|
// Update the foam data for the next frame
|
|
currentWater.previousFoamRegionScaleOffset = new float4(cb._DecalRegionScale, cb._DecalRegionOffset);
|
|
}
|
|
else
|
|
{
|
|
// Attenuate the foam buffer
|
|
CoreUtils.SetRenderTarget(cmd, currentFoamBuffer);
|
|
cmd.DrawProcedural(Matrix4x4.identity, m_DecalMaterial, m_AttenuationPass, MeshTopology.Triangles, 3, 1, currentWater.mpb);
|
|
}
|
|
|
|
cmd.DrawProcedural(Matrix4x4.identity, m_DecalMaterial, m_FoamDecalPass, MeshTopology.Quads, 4, m_NumActiveWaterDecals, currentWater.mpb);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (currentWater.deformation && m_ActiveDeformation)
|
|
{
|
|
using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.WaterDecalDeformation)))
|
|
{
|
|
// Bind the constant buffers
|
|
BindPerSurfaceConstantBuffer(cmd, m_WaterDeformationCS, perSurfaceCB);
|
|
|
|
// Clear the render target to black and draw all the deformers to the texture
|
|
// We render in the SG buffer, blur pass will then output to deformation buffer
|
|
CoreUtils.SetRenderTarget(cmd, currentWater.deformationSGBuffer, clearFlag: ClearFlag.Color, Color.clear);
|
|
cmd.DrawProcedural(Matrix4x4.identity, m_DecalMaterial, m_DeformationDecalPass, MeshTopology.Quads, 4, m_NumActiveWaterDecals, currentWater.mpb);
|
|
currentWater.deformationBuffer.rt.IncrementUpdateCount(); // For the CPU Simulation
|
|
|
|
// Evaluate the normals
|
|
int numTiles = HDUtils.DivRoundUp((int)currentWater.deformationRes, 8);
|
|
|
|
cmd.SetKeyword(horizontalDeformationKeyword, HDRenderPipeline.currentAsset.currentPlatformRenderPipelineSettings.supportWaterHorizontalDeformation);
|
|
|
|
// First we need to clear the edge pixel and blur the deformation a bit
|
|
cmd.SetComputeTextureParam(m_WaterDeformationCS, m_FilterDeformationKernel, HDShaderIDs._WaterDeformationBuffer, currentWater.deformationSGBuffer);
|
|
cmd.SetComputeTextureParam(m_WaterDeformationCS, m_FilterDeformationKernel, HDShaderIDs._WaterDeformationBufferRW, currentWater.deformationBuffer);
|
|
cmd.DispatchCompute(m_WaterDeformationCS, m_FilterDeformationKernel, numTiles, numTiles, 1);
|
|
|
|
cmd.SetComputeTextureParam(m_WaterDeformationCS, m_EvaluateDeformationSurfaceGradientKernel, HDShaderIDs._WaterDeformationBuffer, currentWater.deformationBuffer);
|
|
cmd.SetComputeTextureParam(m_WaterDeformationCS, m_EvaluateDeformationSurfaceGradientKernel, HDShaderIDs._WaterDeformationSGBufferRW, currentWater.deformationSGBuffer);
|
|
cmd.DispatchCompute(m_WaterDeformationCS, m_EvaluateDeformationSurfaceGradientKernel, numTiles, numTiles, 1);
|
|
}
|
|
}
|
|
|
|
if (m_EnableDecalWorkflow)
|
|
{
|
|
if ((currentWater.simulationMask || currentWater.supportSimulationFoamMask) && m_ActiveMask)
|
|
{
|
|
using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.WaterDecalMask)))
|
|
{
|
|
CoreUtils.SetRenderTarget(cmd, currentWater.maskBuffer, clearFlag: ClearFlag.Color, Color.white);
|
|
|
|
cmd.DrawProcedural(Matrix4x4.identity, m_DecalMaterial, m_MaskDecalPass, MeshTopology.Quads, 4, m_NumActiveWaterDecals, currentWater.mpb);
|
|
currentWater.maskBuffer.rt.IncrementUpdateCount(); // For the CPU Simulation
|
|
}
|
|
}
|
|
|
|
if (m_ActiveLargeCurrent || m_ActiveRipplesCurrent)
|
|
{
|
|
using (new ProfilingScope(cmd, ProfilingSampler.Get(HDProfileId.WaterDecalCurrent)))
|
|
{
|
|
if (currentWater.supportLargeCurrent && m_ActiveLargeCurrent)
|
|
{
|
|
CoreUtils.SetRenderTarget(cmd, currentWater.largeCurrentBuffer, clearFlag: ClearFlag.Color, Color.black);
|
|
|
|
cmd.DrawProcedural(Matrix4x4.identity, m_DecalMaterial, m_LargeCurrentDecalPass, MeshTopology.Quads, 4, m_NumActiveWaterDecals, currentWater.mpb);
|
|
currentWater.largeCurrentBuffer.rt.IncrementUpdateCount(); // For the CPU Simulation
|
|
}
|
|
if (currentWater.supportRipplesCurrent && m_ActiveRipplesCurrent)
|
|
{
|
|
CoreUtils.SetRenderTarget(cmd, currentWater.ripplesCurrentBuffer, clearFlag: ClearFlag.Color, Color.black);
|
|
|
|
cmd.DrawProcedural(Matrix4x4.identity, m_DecalMaterial, m_RipplesCurrentDecalPass, MeshTopology.Quads, 4, m_NumActiveWaterDecals, currentWater.mpb);
|
|
currentWater.ripplesCurrentBuffer.rt.IncrementUpdateCount(); // For the CPU Simulation
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Reenable wireframe if needed
|
|
if (wireframe)
|
|
cmd.SetWireframe(true);
|
|
}
|
|
}
|
|
}
|