Skip to content

Commit 578bbaf

Browse files
adrien-de-tocquevilleEvergreen
authored andcommitted
[HDRP] Fix missing API to sync clouds over network
Simple API to get animation state to be able to restore it later, or on another machine over network. ```cs var data = VolumetricClouds.animationData; VolumetricClouds.animationData = data; ```
1 parent b6d2c3a commit 578bbaf

File tree

7 files changed

+86
-21
lines changed

7 files changed

+86
-21
lines changed

Packages/com.unity.render-pipelines.high-definition/Documentation~/create-realistic-clouds-volumetric-clouds.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,33 @@ When **Rendering Space** is set to **Camera**, the clouds are always located abo
3333

3434
[!include[](snippets/volume-override-api.md)]
3535

36+
By default, animation data for clouds gets incremented automatically depending on the wind parameters.
37+
In some cases, it can be useful to manually set the animation time, which can be done by using the following script on a Camera:
38+
39+
```cs
40+
using UnityEngine;
41+
using UnityEngine.Rendering;
42+
using UnityEngine.Rendering.HighDefinition;
43+
44+
public class CloudSync : MonoBehaviour
45+
{
46+
VolumetricClouds.AnimationData data;
47+
48+
void Update()
49+
{
50+
// Save animation data
51+
if (Input.GetKeyDown(KeyCode.A))
52+
data = VolumetricClouds.animationData;
53+
54+
// Set animation data
55+
if (Input.GetKeyDown(KeyCode.B))
56+
{
57+
var camera = this.GetComponent<Camera>();
58+
var hdCamera = HDCamera.GetOrCreate(camera);
59+
VolumetricClouds.animationData = data;
60+
// We reset the camera to discard the history buffer manually
61+
hdCamera.Reset();
62+
}
63+
}
64+
}
65+
```

Packages/com.unity.render-pipelines.high-definition/Documentation~/water-scripting-in-the-water-system.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,15 +207,21 @@ public class FitToWaterSurface_Burst : MonoBehaviour
207207

208208
## Synchronizing Water Surfaces
209209

210-
When making a multiplayer game, it can be useful to ensure all clients have a water simulation that is running in sync.
211-
You can achieve this by specifying the absolute time at which the simulation started by using the following API:
210+
When working with multiple water surfaces, it can be useful to synchronize the water simulation of each of the surface.
211+
In a multiplayer game, this can ensure all clients have a water simulation that is running in sync.
212+
You can achieve this by using one of the two following APIs;
212213

213214
```cs
214-
water.simulationStart = new DateTime(2008, 5, 1, 8, 30, 52); // HDRP will compute the water simulation as if the program started at that time
215+
water.simulationStart = DateTime.Now; // HDRP will compute the water simulation as if the game just started
216+
water.simulationTime = 0; // Set the exact simulation time in seconds
215217
```
216218

217-
Alternatively, if you have a reference water surface, you can make sure other existing surfaces are synchronized with this one by copying the start value:
219+
Alternatively, if you have a reference water surface, you can make sure other existing surfaces are synchronized with this one by copying the simulation time value:
218220

219221
```cs
220222
water.simulationStart = referenceSurface.simulationStart;
223+
water.simulationTime = referenceSurface.simulationTime;
221224
```
225+
226+
The `simulationStart` API works with absolute time data, which simplifies synchronization when sending the value over the network, as you don't have to account for the latency.
227+
Using the `simulationTime` gives you direct access to the time value used to compute the result of the water simulation and is useful when synchronizing surfaces locally.

Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricClouds/HDRenderPipeline.VolumetricClouds.cs

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,9 @@ public partial class HDRenderPipeline
4545
Material m_CloudCombinePass;
4646

4747
LocalKeyword m_OutputFogTransmittanceKeyword;
48-
49-
// Animation time is shared for all cameras, but only updated by the main camera
50-
internal struct VolumetricCloudsAnimationData
51-
{
52-
internal float time;
53-
public Vector2 cloudOffset;
54-
public float verticalShapeOffset;
55-
public float verticalErosionOffset;
56-
}
57-
58-
internal VolumetricCloudsAnimationData m_CloudsAnimationData;
48+
49+
float m_CloudsAnimationLastTime;
50+
internal VolumetricClouds.AnimationData m_CloudsAnimationData;
5951

6052
struct VolumetricCloudsCameraData
6153
{
@@ -108,9 +100,9 @@ void InitializeVolumetricClouds()
108100
AllocatePresetTextures();
109101

110102
// Initialize cloud animation
103+
m_CloudsAnimationLastTime = -1.0f;
111104
m_CloudsAnimationData = new()
112105
{
113-
time = -1.0f,
114106
cloudOffset = new Vector2(0.0f, 0.0f),
115107
verticalShapeOffset = 0.0f,
116108
verticalErosionOffset = 0.0f,
@@ -515,8 +507,8 @@ void UpdateVolumetricClouds(HDCamera hdCamera, in VolumetricClouds settings)
515507
if (EvaluateVolumetricCloudsHistoryValidity(hdCamera))
516508
{
517509
float totalTime = Application.isPlaying ? Time.time : Time.realtimeSinceStartup;
518-
float deltaTime = totalTime - m_CloudsAnimationData.time;
519-
if (m_CloudsAnimationData.time == -1.0f)
510+
float deltaTime = totalTime - m_CloudsAnimationLastTime;
511+
if (m_CloudsAnimationLastTime == -1.0f)
520512
deltaTime = 0.0f;
521513

522514
#if UNITY_EDITOR
@@ -533,7 +525,7 @@ void UpdateVolumetricClouds(HDCamera hdCamera, in VolumetricClouds settings)
533525
Vector2 windDirection = new Vector2(Mathf.Cos(theta), Mathf.Sin(theta));
534526

535527
// Animate the offsets
536-
m_CloudsAnimationData.time = totalTime;
528+
m_CloudsAnimationLastTime = totalTime;
537529
m_CloudsAnimationData.cloudOffset += deltaTime * settings.globalWindSpeed.GetValue(hdCamera) * windDirection;
538530
m_CloudsAnimationData.verticalShapeOffset += deltaTime * settings.verticalShapeWindSpeed.value;
539531
m_CloudsAnimationData.verticalErosionOffset += deltaTime * settings.verticalErosionWindSpeed.value;

Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/VolumetricClouds/VolumetricClouds.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,26 @@ namespace UnityEngine.Rendering.HighDefinition
1111
[HDRPHelpURL("Override-Volumetric-Clouds")]
1212
public sealed partial class VolumetricClouds : VolumeComponent
1313
{
14+
/// <summary>
15+
/// Struct holding animation data for volumetric clouds.
16+
/// Animation data is shared for all cameras, but only updated by the main camera.
17+
/// </summary>
18+
public struct AnimationData
19+
{
20+
internal Vector2 cloudOffset;
21+
internal float verticalShapeOffset;
22+
internal float verticalErosionOffset;
23+
}
24+
25+
/// <summary>
26+
/// Override current clouds animation data. Can be used to synchronize clouds over the network.
27+
/// </summary>
28+
public static AnimationData animationData
29+
{
30+
get => HDRenderPipeline.currentPipeline.m_CloudsAnimationData;
31+
set { HDRenderPipeline.currentPipeline.m_CloudsAnimationData = value; }
32+
}
33+
1434
/// <summary>
1535
/// Control mode for the volumetric clouds.
1636
/// </summary>

Packages/com.unity.render-pipelines.high-definition/Runtime/Water/HDRenderPipeline.WaterSystem.Foam.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ void UpdateWaterFoamSimulation(CommandBuffer cmd, WaterSurface currentWater)
193193
return;
194194

195195
// First we must ensure, that the texture is there (if it should be) and at the right resolution
196-
currentWater.CheckFoamResources();
196+
currentWater.CheckFoamResources(cmd);
197197

198198
// Skip if there are is foam to render
199199
if (!currentWater.foam)

Packages/com.unity.render-pipelines.high-definition/Runtime/Water/WaterSurface/WaterSurface.Foam.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public enum WaterFoamResolution
123123
internal RTHandle[] foamBuffers = new RTHandle[2];
124124
internal float4 previousFoamRegionScaleOffset;
125125

126-
internal void CheckFoamResources()
126+
internal void CheckFoamResources(CommandBuffer cmd)
127127
{
128128
if (foam)
129129
{
@@ -137,6 +137,9 @@ internal void CheckFoamResources()
137137
{
138138
foamBuffers[0] = RTHandles.Alloc(resolution, resolution, 1, dimension: TextureDimension.Tex2D, colorFormat: GraphicsFormat.R16G16_SFloat, enableRandomWrite: true, wrapMode: TextureWrapMode.Clamp);
139139
foamBuffers[1] = RTHandles.Alloc(resolution, resolution, 1, dimension: TextureDimension.Tex2D, colorFormat: GraphicsFormat.R16G16_SFloat, enableRandomWrite: true, wrapMode: TextureWrapMode.Clamp);
140+
141+
// Clear buffer 0 only
142+
CoreUtils.SetRenderTarget(cmd, foamBuffers[0], ClearFlag.Color, Color.black);
140143
}
141144
}
142145
else

Packages/com.unity.render-pipelines.high-definition/Runtime/Water/WaterSurface/WaterSurface.Simulation.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,20 @@ public DateTime simulationStart
148148
}
149149
}
150150

151+
/// <summary>Current simulation time in seconds.</summary>
152+
public float simulationTime
153+
{
154+
get
155+
{
156+
return simulation?.simulationTime ?? 0.0f;
157+
}
158+
set
159+
{
160+
if (simulation != null)
161+
simulation.simulationTime = value;
162+
}
163+
}
164+
151165
internal int numActiveBands => HDRenderPipeline.EvaluateBandCount(surfaceType, ripples);
152166

153167
// Optional CPU simulation data

0 commit comments

Comments
 (0)