A game about forced loneliness, made by TACStudios
1// Unity built-in shader source. Copyright (c) 2024 Unity Technologies. MIT license (see license.txt)
2
3#ifndef SPEEDTREE_WIND_9_INCLUDED
4#define SPEEDTREE_WIND_9_INCLUDED
5
6#define SPEEDTREE_VERSION_9
7#include "SpeedTreeCommon.hlsl"
8
9//
10// DATA DEFINITIONS
11//
12struct WindBranchState // 8 floats | 32B
13{
14 float3 m_vNoisePosTurbulence;
15 float m_fIndependence;
16 float m_fBend;
17 float m_fOscillation;
18 float m_fTurbulence;
19 float m_fFlexibility;
20};
21struct WindRippleState // 8 floats | 32B
22{
23 float3 m_vNoisePosTurbulence;
24 float m_fIndependence;
25 float m_fPlanar;
26 float m_fDirectional;
27 float m_fFlexibility;
28 float m_fShimmer;
29};
30struct CBufferSpeedTree9 // 44 floats | 176B
31{
32 float3 m_vWindDirection;
33 float m_fWindStrength;
34
35 float3 m_vTreeExtents;
36 float m_fSharedHeightStart;
37
38 float m_fBranch1StretchLimit;
39 float m_fBranch2StretchLimit;
40 float m_fWindIndependence;
41 float m_fImportScaling;
42
43 WindBranchState m_sShared;
44 WindBranchState m_sBranch1;
45 WindBranchState m_sBranch2;
46 WindRippleState m_sRipple;
47};
48
49CBUFFER_START(SpeedTreeWind)
50float4 _ST_WindVector;
51float4 _ST_TreeExtents_SharedHeightStart;
52float4 _ST_BranchStretchLimits;
53float4 _ST_Shared_NoisePosTurbulence_Independence;
54float4 _ST_Shared_Bend_Oscillation_Turbulence_Flexibility;
55float4 _ST_Branch1_NoisePosTurbulence_Independence;
56float4 _ST_Branch1_Bend_Oscillation_Turbulence_Flexibility;
57float4 _ST_Branch2_NoisePosTurbulence_Independence;
58float4 _ST_Branch2_Bend_Oscillation_Turbulence_Flexibility;
59float4 _ST_Ripple_NoisePosTurbulence_Independence;
60float4 _ST_Ripple_Planar_Directional_Flexibility_Shimmer;
61CBUFFER_END
62
63CBUFFER_START(SpeedTreeWindHistory)
64float4 _ST_HistoryWindVector;
65float4 _ST_HistoryTreeExtents_SharedHeightStart;
66float4 _ST_HistoryBranchStretchLimits;
67float4 _ST_HistoryShared_NoisePosTurbulence_Independence;
68float4 _ST_HistoryShared_Bend_Oscillation_Turbulence_Flexibility;
69float4 _ST_HistoryBranch1_NoisePosTurbulence_Independence;
70float4 _ST_HistoryBranch1_Bend_Oscillation_Turbulence_Flexibility;
71float4 _ST_HistoryBranch2_NoisePosTurbulence_Independence;
72float4 _ST_HistoryBranch2_Bend_Oscillation_Turbulence_Flexibility;
73float4 _ST_HistoryRipple_NoisePosTurbulence_Independence;
74float4 _ST_HistoryRipple_Planar_Directional_Flexibility_Shimmer;
75CBUFFER_END
76
77#ifdef UNITY_DOTS_INSTANCING_ENABLED
78
79#define DOTS_ST_WindVector DOTS_ST_WindParam0
80#define DOTS_ST_TreeExtents_SharedHeightStart DOTS_ST_WindParam1
81#define DOTS_ST_BranchStretchLimits DOTS_ST_WindParam2
82#define DOTS_ST_Shared_NoisePosTurbulence_Independence DOTS_ST_WindParam3
83#define DOTS_ST_Shared_Bend_Oscillation_Turbulence_Flexibility DOTS_ST_WindParam4
84#define DOTS_ST_Branch1_NoisePosTurbulence_Independence DOTS_ST_WindParam5
85#define DOTS_ST_Branch1_Bend_Oscillation_Turbulence_Flexibility DOTS_ST_WindParam6
86#define DOTS_ST_Branch2_NoisePosTurbulence_Independence DOTS_ST_WindParam7
87#define DOTS_ST_Branch2_Bend_Oscillation_Turbulence_Flexibility DOTS_ST_WindParam8
88#define DOTS_ST_Ripple_NoisePosTurbulence_Independence DOTS_ST_WindParam9
89#define DOTS_ST_Ripple_Planar_Directional_Flexibility_Shimmer DOTS_ST_WindParam10
90
91#define DOTS_ST_HistoryWindVector DOTS_ST_WindHistoryParam0
92#define DOTS_ST_HistoryTreeExtents_SharedHeightStart DOTS_ST_WindHistoryParam1
93#define DOTS_ST_HistoryBranchStretchLimits DOTS_ST_WindHistoryParam2
94#define DOTS_ST_HistoryShared_NoisePosTurbulence_Independence DOTS_ST_WindHistoryParam3
95#define DOTS_ST_HistoryShared_Bend_Oscillation_Turbulence_Flexibility DOTS_ST_WindHistoryParam4
96#define DOTS_ST_HistoryBranch1_NoisePosTurbulence_Independence DOTS_ST_WindHistoryParam5
97#define DOTS_ST_HistoryBranch1_Bend_Oscillation_Turbulence_Flexibility DOTS_ST_WindHistoryParam6
98#define DOTS_ST_HistoryBranch2_NoisePosTurbulence_Independence DOTS_ST_WindHistoryParam7
99#define DOTS_ST_HistoryBranch2_Bend_Oscillation_Turbulence_Flexibility DOTS_ST_WindHistoryParam8
100#define DOTS_ST_HistoryRipple_NoisePosTurbulence_Independence DOTS_ST_WindHistoryParam9
101#define DOTS_ST_HistoryRipple_Planar_Directional_Flexibility_Shimmer DOTS_ST_WindHistoryParam10
102
103UNITY_DOTS_INSTANCING_START(UserPropertyMetadata)
104 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindVector)
105 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_TreeExtents_SharedHeightStart)
106 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_BranchStretchLimits)
107 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_Shared_NoisePosTurbulence_Independence)
108 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_Shared_Bend_Oscillation_Turbulence_Flexibility)
109 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_Branch1_NoisePosTurbulence_Independence)
110 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_Branch1_Bend_Oscillation_Turbulence_Flexibility)
111 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_Branch2_NoisePosTurbulence_Independence)
112 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_Branch2_Bend_Oscillation_Turbulence_Flexibility)
113 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_Ripple_NoisePosTurbulence_Independence)
114 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_Ripple_Planar_Directional_Flexibility_Shimmer)
115
116 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryWindVector)
117 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryTreeExtents_SharedHeightStart)
118 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryBranchStretchLimits)
119 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryShared_NoisePosTurbulence_Independence)
120 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryShared_Bend_Oscillation_Turbulence_Flexibility)
121 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryBranch1_NoisePosTurbulence_Independence)
122 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryBranch1_Bend_Oscillation_Turbulence_Flexibility)
123 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryBranch2_NoisePosTurbulence_Independence)
124 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryBranch2_Bend_Oscillation_Turbulence_Flexibility)
125 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryRipple_NoisePosTurbulence_Independence)
126 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryRipple_Planar_Directional_Flexibility_Shimmer)
127UNITY_DOTS_INSTANCING_END(UserPropertyMetadata)
128
129#define _ST_WindVector UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindVector)
130#define _ST_TreeExtents_SharedHeightStart UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_TreeExtents_SharedHeightStart)
131#define _ST_BranchStretchLimits UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_BranchStretchLimits)
132#define _ST_Shared_NoisePosTurbulence_Independence UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_Shared_NoisePosTurbulence_Independence)
133#define _ST_Shared_Bend_Oscillation_Turbulence_Flexibility UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_Shared_Bend_Oscillation_Turbulence_Flexibility)
134#define _ST_Branch1_NoisePosTurbulence_Independence UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_Branch1_NoisePosTurbulence_Independence)
135#define _ST_Branch1_Bend_Oscillation_Turbulence_Flexibility UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_Branch1_Bend_Oscillation_Turbulence_Flexibility)
136#define _ST_Branch2_NoisePosTurbulence_Independence UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_Branch2_NoisePosTurbulence_Independence)
137#define _ST_Branch2_Bend_Oscillation_Turbulence_Flexibility UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_Branch2_Bend_Oscillation_Turbulence_Flexibility)
138#define _ST_Ripple_NoisePosTurbulence_Independence UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_Ripple_NoisePosTurbulence_Independence)
139#define _ST_Ripple_Planar_Directional_Flexibility_Shimmer UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_Ripple_Planar_Directional_Flexibility_Shimmer)
140
141#define _ST_HistoryWindVector UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryWindVector)
142#define _ST_HistoryTreeExtents_SharedHeightStart UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryTreeExtents_SharedHeightStart)
143#define _ST_HistoryBranchStretchLimits UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryBranchStretchLimits)
144#define _ST_HistoryShared_NoisePosTurbulence_Independence UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryShared_NoisePosTurbulence_Independence)
145#define _ST_HistoryShared_Bend_Oscillation_Turbulence_Flexibility UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryShared_Bend_Oscillation_Turbulence_Flexibility)
146#define _ST_HistoryBranch1_NoisePosTurbulence_Independence UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryBranch1_NoisePosTurbulence_Independence)
147#define _ST_HistoryBranch1_Bend_Oscillation_Turbulence_Flexibility UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryBranch1_Bend_Oscillation_Turbulence_Flexibility)
148#define _ST_HistoryBranch2_NoisePosTurbulence_Independence UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryBranch2_NoisePosTurbulence_Independence)
149#define _ST_HistoryBranch2_Bend_Oscillation_Turbulence_Flexibility UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryBranch2_Bend_Oscillation_Turbulence_Flexibility)
150#define _ST_HistoryRipple_NoisePosTurbulence_Independence UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryRipple_NoisePosTurbulence_Independence)
151#define _ST_HistoryRipple_Planar_Directional_Flexibility_Shimmer UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_HistoryRipple_Planar_Directional_Flexibility_Shimmer)
152
153#endif
154
155CBufferSpeedTree9 ReadCBuffer(bool bHistory /*must be known compile-time*/)
156{
157 CBufferSpeedTree9 cb;
158 cb.m_vWindDirection = bHistory ? _ST_HistoryWindVector.xyz : _ST_WindVector.xyz;
159 cb.m_fWindStrength = bHistory ? _ST_HistoryWindVector.w : _ST_WindVector.w;
160 cb.m_vTreeExtents = bHistory ? _ST_HistoryTreeExtents_SharedHeightStart.xyz : _ST_TreeExtents_SharedHeightStart.xyz;
161 cb.m_fSharedHeightStart = bHistory ? _ST_HistoryTreeExtents_SharedHeightStart.w : _ST_TreeExtents_SharedHeightStart.w;
162 cb.m_fBranch1StretchLimit = bHistory ? _ST_HistoryBranchStretchLimits.x : _ST_BranchStretchLimits.x;
163 cb.m_fBranch2StretchLimit = bHistory ? _ST_HistoryBranchStretchLimits.y : _ST_BranchStretchLimits.y;
164 cb.m_fWindIndependence = bHistory ? _ST_HistoryBranchStretchLimits.z : _ST_BranchStretchLimits.z;
165 cb.m_fImportScaling = bHistory ? _ST_HistoryBranchStretchLimits.w : _ST_BranchStretchLimits.w;
166
167 // Shared Wind State
168 cb.m_sShared.m_vNoisePosTurbulence = bHistory ? _ST_HistoryShared_NoisePosTurbulence_Independence.xyz : _ST_Shared_NoisePosTurbulence_Independence.xyz;
169 cb.m_sShared.m_fIndependence = bHistory ? _ST_HistoryShared_NoisePosTurbulence_Independence.w : _ST_Shared_NoisePosTurbulence_Independence.w;
170 cb.m_sShared.m_fBend = bHistory ? _ST_HistoryShared_Bend_Oscillation_Turbulence_Flexibility.x : _ST_Shared_Bend_Oscillation_Turbulence_Flexibility.x;
171 cb.m_sShared.m_fOscillation = bHistory ? _ST_HistoryShared_Bend_Oscillation_Turbulence_Flexibility.y : _ST_Shared_Bend_Oscillation_Turbulence_Flexibility.y;
172 cb.m_sShared.m_fTurbulence = bHistory ? _ST_HistoryShared_Bend_Oscillation_Turbulence_Flexibility.z : _ST_Shared_Bend_Oscillation_Turbulence_Flexibility.z;
173 cb.m_sShared.m_fFlexibility = bHistory ? _ST_HistoryShared_Bend_Oscillation_Turbulence_Flexibility.w : _ST_Shared_Bend_Oscillation_Turbulence_Flexibility.w;
174
175 // Branch1 Wind State
176 cb.m_sBranch1.m_vNoisePosTurbulence = bHistory ? _ST_HistoryBranch1_NoisePosTurbulence_Independence.xyz : _ST_Branch1_NoisePosTurbulence_Independence.xyz;
177 cb.m_sBranch1.m_fIndependence = bHistory ? _ST_HistoryBranch1_NoisePosTurbulence_Independence.w : _ST_Branch1_NoisePosTurbulence_Independence.w;
178 cb.m_sBranch1.m_fBend = bHistory ? _ST_HistoryBranch1_Bend_Oscillation_Turbulence_Flexibility.x : _ST_Branch1_Bend_Oscillation_Turbulence_Flexibility.x;
179 cb.m_sBranch1.m_fOscillation = bHistory ? _ST_HistoryBranch1_Bend_Oscillation_Turbulence_Flexibility.y : _ST_Branch1_Bend_Oscillation_Turbulence_Flexibility.y;
180 cb.m_sBranch1.m_fTurbulence = bHistory ? _ST_HistoryBranch1_Bend_Oscillation_Turbulence_Flexibility.z : _ST_Branch1_Bend_Oscillation_Turbulence_Flexibility.z;
181 cb.m_sBranch1.m_fFlexibility = bHistory ? _ST_HistoryBranch1_Bend_Oscillation_Turbulence_Flexibility.w : _ST_Branch1_Bend_Oscillation_Turbulence_Flexibility.w;
182
183 // Branch2 Wind State
184 cb.m_sBranch2.m_vNoisePosTurbulence = bHistory ? _ST_HistoryBranch2_NoisePosTurbulence_Independence.xyz : _ST_Branch2_NoisePosTurbulence_Independence.xyz;
185 cb.m_sBranch2.m_fIndependence = bHistory ? _ST_HistoryBranch2_NoisePosTurbulence_Independence.w : _ST_Branch2_NoisePosTurbulence_Independence.w;
186 cb.m_sBranch2.m_fBend = bHistory ? _ST_HistoryBranch2_Bend_Oscillation_Turbulence_Flexibility.x : _ST_Branch2_Bend_Oscillation_Turbulence_Flexibility.x;
187 cb.m_sBranch2.m_fOscillation = bHistory ? _ST_HistoryBranch2_Bend_Oscillation_Turbulence_Flexibility.y : _ST_Branch2_Bend_Oscillation_Turbulence_Flexibility.y;
188 cb.m_sBranch2.m_fTurbulence = bHistory ? _ST_HistoryBranch2_Bend_Oscillation_Turbulence_Flexibility.z : _ST_Branch2_Bend_Oscillation_Turbulence_Flexibility.z;
189 cb.m_sBranch2.m_fFlexibility = bHistory ? _ST_HistoryBranch2_Bend_Oscillation_Turbulence_Flexibility.w : _ST_Branch2_Bend_Oscillation_Turbulence_Flexibility.w;
190
191 // Ripple Wind State
192 cb.m_sRipple.m_vNoisePosTurbulence = bHistory ? _ST_HistoryRipple_NoisePosTurbulence_Independence.xyz : _ST_Ripple_NoisePosTurbulence_Independence.xyz;
193 cb.m_sRipple.m_fIndependence = bHistory ? _ST_HistoryRipple_NoisePosTurbulence_Independence.w : _ST_Ripple_NoisePosTurbulence_Independence.w;
194 cb.m_sRipple.m_fPlanar = bHistory ? _ST_HistoryRipple_Planar_Directional_Flexibility_Shimmer.x : _ST_Ripple_Planar_Directional_Flexibility_Shimmer.x;
195 cb.m_sRipple.m_fDirectional = bHistory ? _ST_HistoryRipple_Planar_Directional_Flexibility_Shimmer.y : _ST_Ripple_Planar_Directional_Flexibility_Shimmer.y;
196 cb.m_sRipple.m_fFlexibility = bHistory ? _ST_HistoryRipple_Planar_Directional_Flexibility_Shimmer.z : _ST_Ripple_Planar_Directional_Flexibility_Shimmer.z;
197 cb.m_sRipple.m_fShimmer = bHistory ? _ST_HistoryRipple_Planar_Directional_Flexibility_Shimmer.w : _ST_Ripple_Planar_Directional_Flexibility_Shimmer.w;
198
199 cb.m_vWindDirection = TransformWindVectorFromWorldToLocalSpace(cb.m_vWindDirection);
200 return cb;
201}
202
203
204//
205// UTILS
206//
207float NoiseHash(float n) { return frac(sin(n) * 1e4); }
208float NoiseHash(float2 p){ return frac(1e4 * sin(17.0f * p.x + p.y * 0.1f) * (0.1f + abs(sin(p.y * 13.0f + p.x)))); }
209float QNoise(float2 x)
210{
211 float2 i = floor(x);
212 float2 f = frac(x);
213
214 // four corners in 2D of a tile
215 float a = NoiseHash(i);
216 float b = NoiseHash(i + float2(1.0, 0.0));
217 float c = NoiseHash(i + float2(0.0, 1.0));
218 float d = NoiseHash(i + float2(1.0, 1.0));
219
220 // same code, with the clamps in smoothstep and common subexpressions optimized away.
221 float2 u = f * f * (float2(3.0, 3.0) - float2(2.0, 2.0) * f);
222
223 return lerp(a, b, u.x) + (c - a) * u.y * (1.0f - u.x) + (d - b) * u.x * u.y;
224}
225float4 RuntimeSdkNoise2DFlat(float3 vNoisePos3d)
226{
227 float2 vNoisePos = vNoisePos3d.xz;
228
229#ifdef USE_ST_NOISE_TEXTURE // test this toggle during shader perf tuning
230 return texture2D(g_samNoiseKernel, vNoisePos.xy) - float4(0.5f, 0.5f, 0.5f, 0.5f);
231#else
232 // fallback, slower noise lookup method
233 const float c_fFrequecyScale = 20.0f;
234 const float c_fAmplitudeScale = 1.0f;
235 const float c_fAmplitueShift = 0.0f;
236
237 float fNoiseX = (QNoise(vNoisePos * c_fFrequecyScale) + c_fAmplitueShift) * c_fAmplitudeScale;
238 float fNoiseY = (QNoise(vNoisePos.yx * 0.5f * c_fFrequecyScale) + c_fAmplitueShift) * c_fAmplitudeScale;
239 return float4(fNoiseX, fNoiseY, fNoiseX+fNoiseY, 0.0f) - 0.5f.xxxx;
240#endif
241}
242float WindUtil_Square(float fValue) { return fValue * fValue; }
243float2 WindUtil_Square(float2 fValue) { return fValue * fValue; }
244float3 WindUtil_Square(float3 fValue) { return fValue * fValue; }
245float4 WindUtil_Square(float4 fValue) { return fValue * fValue; }
246
247float3 WindUtil_UnpackNormalizedFloat(float fValue)
248{
249 float3 vReturn = frac(float3(fValue * 0.01f, fValue, fValue * 100.0f));
250
251 vReturn -= 0.5f;
252 vReturn *= 2.0f;
253 vReturn = normalize(vReturn);
254 return vReturn;
255}
256
257
258
259//
260// SPEEDTREE WIND 9 FUNCTIONS
261//
262
263// returns position offset (caller must apply to the vertex position)
264float3 RippleWindMotion(
265 float3 vUp,
266 float3 vWindDirection,
267 float3 vVertexPositionIn,
268 float3 vGlobalNoisePosition,
269
270 float fRippleWeight,
271 float3 vRippleNoisePosTurbulence,
272 float fRippleIndependence,
273 float fRippleFlexibility,
274 float fRippleDirectional,
275 float fRipplePlanar,
276 float fTreeHeight,
277 float fImportScaling
278)
279{
280 float fImportScalingInv = (1.0f / fImportScaling);
281
282 float3 vNoisePosition = vGlobalNoisePosition
283 + vRippleNoisePosTurbulence
284 + (vVertexPositionIn * fImportScalingInv) * fRippleIndependence
285 + vWindDirection * fRippleFlexibility * fRippleWeight;
286
287 float2 vNoise = RuntimeSdkNoise2DFlat(vNoisePosition);
288 vNoise.r += 0.25f;
289
290 float3 vMotion = vWindDirection * vNoise.r * fRippleDirectional
291 + vUp * (vNoise.g * fRipplePlanar)
292 ;
293 vMotion *= fRippleWeight;
294
295 return vMotion;
296}
297
298float3 RippleWindMotion_cb(
299 float3 vUpVector,
300 float3 vVertexPositionIn,
301 float3 vGlobalNoisePosition,
302 float fRippleWeight,
303 in CBufferSpeedTree9 cb
304)
305{
306 return RippleWindMotion(
307 vUpVector,
308 cb.m_vWindDirection,
309 vVertexPositionIn,
310 vGlobalNoisePosition,
311 fRippleWeight,
312 cb.m_sRipple.m_vNoisePosTurbulence,
313 cb.m_sRipple.m_fIndependence,
314 cb.m_sRipple.m_fFlexibility,
315 cb.m_sRipple.m_fDirectional,
316 cb.m_sRipple.m_fPlanar,
317 cb.m_vTreeExtents.y, // y-up = height
318 cb.m_fImportScaling
319 );
320}
321
322
323// returns updated position
324float3 BranchWindPosition(
325 float3 vUp,
326 float3 vWindDirection,
327 float3 vVertexPositionIn,
328 float3 vGlobalNoisePosition,
329 float fPackedBranchDir,
330 float fPackedBranchNoiseOffset,
331 float fBranchWeight,
332 float fBranchStretchLimit,
333 float3 vBranchNoisePosTurbulence,
334 float fBranchIndependence,
335 float fBranchTurbulence,
336 float fBranchOscillation,
337 float fBranchBend,
338 float fBranchFlexibility,
339 float fTreeHeight,
340 float fImportScaling
341)
342{
343 float fImportScalingInv = (1.0f / fImportScaling);
344 float fLength = fBranchWeight * fBranchStretchLimit;
345 if (fBranchWeight * fBranchStretchLimit <= 0.0f)
346 {
347 return vVertexPositionIn;
348 }
349
350 float3 vBranchDir = WindUtil_UnpackNormalizedFloat(fPackedBranchDir);
351 float3 vBranchNoiseOffset = WindUtil_UnpackNormalizedFloat(fPackedBranchNoiseOffset);
352
353 // SpeedTree Modeler packs Z up, rotate around X for -90deg
354 vBranchDir = float3(vBranchDir.x, -vBranchDir.z, vBranchDir.y);
355 vBranchNoiseOffset = float3(vBranchNoiseOffset.x, -vBranchNoiseOffset.z, vBranchNoiseOffset.y);
356
357 float3 vAnchor = vVertexPositionIn - vBranchDir * fLength;
358 vVertexPositionIn -= vAnchor;
359
360 float fBranchDotWindSq = WindUtil_Square(dot(vBranchDir, vWindDirection));
361 float3 vWind = normalize(vWindDirection + vUp * fBranchDotWindSq);
362
363 // Undo modifications to fBranchIndependence:
364 // (1) Modeler divides fBranchIndependence by fTreeHeight before export
365 // (2) Importer scales fTreeHeight by fImportScaling during import
366 fBranchIndependence *= (fTreeHeight * fImportScalingInv);
367
368 float3 vNoisePosition = vGlobalNoisePosition
369 + vBranchNoisePosTurbulence
370 + vBranchNoiseOffset * fBranchIndependence
371 + vWind * (fBranchFlexibility * fBranchWeight);
372
373 float4 vNoise = RuntimeSdkNoise2DFlat(vNoisePosition);
374 vNoise.r *= 0.65; // tune down the 'flexy' branches
375 vNoise.g *= 0.50; // tune down the 'flexy' branches
376
377 float3 vOscillationTurbulent = vUp * fBranchTurbulence;
378
379 float3 vMotion = (vWind * vNoise.r + vOscillationTurbulent * vNoise.g) * fBranchOscillation;
380 vMotion += vWind * (fBranchBend * (1.0f - vNoise.b));
381 vMotion *= fBranchWeight;
382
383 return normalize(vVertexPositionIn + vMotion) * fLength + vAnchor;
384}
385float3 BranchWindPosition_cb(
386 float3 vUp,
387 float3 vGlobalNoisePosition,
388 float3 vVertexPositionIn,
389
390 float fBranchWeight,
391 float fPackedBranchDir,
392 float fPackedBranchNoiseOffset,
393 in CBufferSpeedTree9 cb,
394 const int iBranch // 1 or 2, compile time constants
395)
396{
397 if (iBranch == 1)
398 {
399 return BranchWindPosition(
400 vUp,
401 cb.m_vWindDirection,
402 vVertexPositionIn,
403 vGlobalNoisePosition,
404 fPackedBranchDir,
405 fPackedBranchNoiseOffset,
406 fBranchWeight,
407 cb.m_fBranch1StretchLimit,
408 cb.m_sBranch1.m_vNoisePosTurbulence,
409 cb.m_sBranch1.m_fIndependence,
410 cb.m_sBranch1.m_fTurbulence,
411 cb.m_sBranch1.m_fOscillation,
412 cb.m_sBranch1.m_fBend,
413 cb.m_sBranch1.m_fFlexibility,
414 cb.m_vTreeExtents.y, // y-up = height
415 cb.m_fImportScaling
416 );
417 }
418
419 return BranchWindPosition(
420 vUp,
421 cb.m_vWindDirection,
422 vVertexPositionIn,
423 vGlobalNoisePosition,
424 fPackedBranchDir,
425 fPackedBranchNoiseOffset,
426 fBranchWeight,
427 cb.m_fBranch2StretchLimit,
428 cb.m_sBranch2.m_vNoisePosTurbulence,
429 cb.m_sBranch2.m_fIndependence,
430 cb.m_sBranch2.m_fTurbulence,
431 cb.m_sBranch2.m_fOscillation,
432 cb.m_sBranch2.m_fBend,
433 cb.m_sBranch2.m_fFlexibility,
434 cb.m_vTreeExtents.y, // y-up = height
435 cb.m_fImportScaling
436 );
437}
438
439
440// returns updated position
441float3 SharedWindPosition(
442 float3 vUp,
443 float3 vWindDirection,
444 float3 vVertexPositionIn,
445 float3 vGlobalNoisePosition,
446
447 float fTreeHeight,
448 float fSharedHeightStart,
449 float3 vSharedNoisePosTurbulence,
450 float fSharedTurbulence,
451 float fSharedOscillation,
452 float fSharedBend,
453 float fSharedFlexibility,
454 float fImportScaling
455)
456{
457 float fImportScalingInv = (1.0f / fImportScaling);
458 float fLengthSq = dot(vVertexPositionIn, vVertexPositionIn);
459 if (fLengthSq == 0.0f)
460 {
461 return vVertexPositionIn;
462 }
463 float fLength = sqrt(fLengthSq);
464
465 float fHeight = vVertexPositionIn.y; // y-up
466 float fMaxHeight = fTreeHeight;
467
468 float fWeight = WindUtil_Square(max(fHeight - (fMaxHeight * fSharedHeightStart), 0.0f) / fMaxHeight);
469
470 float3 vNoisePosition = vGlobalNoisePosition
471 + vSharedNoisePosTurbulence;
472 + vWindDirection * (fSharedFlexibility * fWeight);
473
474 float4 vNoise = RuntimeSdkNoise2DFlat(vNoisePosition);
475
476 float3 vOscillationTurbulent = cross(vWindDirection, vUp) * fSharedTurbulence;
477
478 float3 vMotion = (vWindDirection * vNoise.r + vOscillationTurbulent * vNoise.g) * fSharedOscillation
479 + vWindDirection * (fSharedBend * (1.0f - vNoise.b));
480 ;
481 vMotion *= fWeight;
482
483 return normalize(vVertexPositionIn + vMotion) * fLength;
484}
485
486
487float3 SharedWindPosition_cb(
488 float3 vUp,
489 float3 vVertexPositionIn,
490 float3 vGlobalNoisePosition,
491
492 in CBufferSpeedTree9 cb
493)
494{
495 return SharedWindPosition(
496 vUp,
497 cb.m_vWindDirection,
498 vVertexPositionIn,
499 vGlobalNoisePosition,
500 cb.m_vTreeExtents.y, // y-up = height
501 cb.m_fSharedHeightStart,
502 cb.m_sShared.m_vNoisePosTurbulence,
503 cb.m_sShared.m_fTurbulence,
504 cb.m_sShared.m_fOscillation,
505 cb.m_sShared.m_fBend,
506 cb.m_sShared.m_fFlexibility,
507 cb.m_fImportScaling
508 );
509}
510
511
512
513//====================================================================================================
514
515//
516// SPEEDTREE WIND 9 ENTRY
517//
518float3 SpeedTree9Wind(
519 float3 vPos,
520 float3 vNormal,
521 float4 vTexcoord ,
522 float4 vTexcoord1,
523 float4 vTexcoord2,
524 float4 vTexcoord3,
525 bool bHistory
526)
527{
528 CBufferSpeedTree9 cb = ReadCBuffer(bHistory);
529 const float fWindDirectionLengthSq = dot(cb.m_vWindDirection, cb.m_vWindDirection);
530 if (fWindDirectionLengthSq == 0.0f) // check if we have valid wind vector
531 {
532 return vPos;
533 }
534
535 float3 vUp = float3(0.0, 1.0, 0.0);
536 float3 vWindyPosition = vPos;
537
538 // get world space sposition from the model matrix
539 float3 vWorldPosition = float3(UNITY_MATRIX_M[0].w, UNITY_MATRIX_M[1].w, UNITY_MATRIX_M[2].w);
540#if SHADEROPTIONS_CAMERA_RELATIVE_RENDERING // HDRP has camera translation encoded in the matrix
541 vWorldPosition += _WorldSpaceCameraPos;
542#endif
543
544 // global noise applied to animation instances to break off synchronized
545 // movement among multiple instances under wind effect.
546 float3 vGlobalNoisePosition = vWorldPosition * cb.m_fWindIndependence;
547
548 #if defined(_WIND_RIPPLE)
549 {
550 float fRippleWeight = vTexcoord1.w;
551 float3 vMotion = RippleWindMotion_cb(
552 vUp,
553 vWindyPosition,
554 vGlobalNoisePosition,
555 fRippleWeight,
556 cb
557 );
558 vWindyPosition += vMotion;
559
560 #if defined(_WIND_SHIMMER)
561 {
562 vNormal = normalize(vNormal - (vMotion * cb.m_sRipple.m_fShimmer));
563 }
564 #endif
565 }
566 #endif
567
568 #if defined(_WIND_BRANCH2)
569 {
570 const int BRANCH2 = 2;
571 float fBranch2Weight = vTexcoord2.z;
572 float fPackedBranch2Dir = vTexcoord2.y;
573 float fPackedBranch2NoiseOffset = vTexcoord2.x;
574 vWindyPosition = BranchWindPosition_cb(
575 vUp,
576 vGlobalNoisePosition,
577 vWindyPosition,
578
579 fBranch2Weight,
580 fPackedBranch2Dir,
581 fPackedBranch2NoiseOffset,
582 cb,
583 BRANCH2
584 );
585 }
586 #endif
587
588 #if defined(_WIND_BRANCH1)
589 {
590 const int BRANCH1 = 1;
591 float fBranch1Weight = vTexcoord1.z;
592 float fPackedBranch1Dir = vTexcoord.w;
593 float fPackedBranch1NoiseOffset = vTexcoord.z;
594 vWindyPosition = BranchWindPosition_cb(
595 vUp,
596 vGlobalNoisePosition,
597 vWindyPosition,
598
599 fBranch1Weight,
600 fPackedBranch1Dir,
601 fPackedBranch1NoiseOffset,
602 cb,
603 BRANCH1
604 );
605 }
606 #endif
607
608 #if defined(_WIND_SHARED)
609 {
610 vWindyPosition = SharedWindPosition_cb(
611 vUp,
612 vWindyPosition,
613 vGlobalNoisePosition,
614 cb
615 );
616 }
617 #endif
618
619 return vWindyPosition;
620}
621
622// This version is used by ShaderGraph
623void SpeedTree9Wind_float(
624 // in
625 float3 vPos,
626 float3 vNormal,
627 float4 vTexcoord0,
628 float4 vTexcoord1,
629 float4 vTexcoord2,
630 float4 vTexcoord3,
631 bool bHistory,
632
633 // out
634 out float3 outPos
635)
636{
637 outPos = SpeedTree9Wind(
638 vPos,
639 vNormal,
640 vTexcoord0,
641 vTexcoord1,
642 vTexcoord2,
643 vTexcoord3,
644 bHistory
645 );
646}
647
648#endif // SPEEDTREE_WIND_9_INCLUDED