A game about forced loneliness, made by TACStudios
1// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
2
3#ifndef SPEEDTREE_WIND_8_INCLUDED
4#define SPEEDTREE_WIND_8_INCLUDED
5
6#define SPEEDTREE_VERSION_8 1
7#include "SpeedTreeCommon.hlsl"
8
9///////////////////////////////////////////////////////////////////////
10// Wind Info
11
12CBUFFER_START(SpeedTreeWind)
13float4 _ST_WindVector;
14float4 _ST_WindGlobal;
15float4 _ST_WindBranch;
16float4 _ST_WindBranchTwitch;
17float4 _ST_WindBranchWhip;
18float4 _ST_WindBranchAnchor;
19float4 _ST_WindBranchAdherences;
20float4 _ST_WindTurbulences;
21float4 _ST_WindLeaf1Ripple;
22float4 _ST_WindLeaf1Tumble;
23float4 _ST_WindLeaf1Twitch;
24float4 _ST_WindLeaf2Ripple;
25float4 _ST_WindLeaf2Tumble;
26float4 _ST_WindLeaf2Twitch;
27float4 _ST_WindFrondRipple;
28float4 _ST_WindAnimation;
29CBUFFER_END
30
31CBUFFER_START(SpeedTreeWindHistory)
32float4 _ST_WindVectorHistory;
33float4 _ST_WindGlobalHistory;
34float4 _ST_WindBranchHistory;
35float4 _ST_WindBranchTwitchHistory;
36float4 _ST_WindBranchWhipHistory;
37float4 _ST_WindBranchAnchorHistory;
38float4 _ST_WindBranchAdherencesHistory;
39float4 _ST_WindTurbulencesHistory;
40float4 _ST_WindLeaf1RippleHistory;
41float4 _ST_WindLeaf1TumbleHistory;
42float4 _ST_WindLeaf1TwitchHistory;
43float4 _ST_WindLeaf2RippleHistory;
44float4 _ST_WindLeaf2TumbleHistory;
45float4 _ST_WindLeaf2TwitchHistory;
46float4 _ST_WindFrondRippleHistory;
47float4 _ST_WindAnimationHistory;
48CBUFFER_END
49
50#ifdef UNITY_DOTS_INSTANCING_ENABLED
51
52#define DOTS_ST_WindVector DOTS_ST_WindParam0
53#define DOTS_ST_WindGlobal DOTS_ST_WindParam1
54#define DOTS_ST_WindBranch DOTS_ST_WindParam2
55#define DOTS_ST_WindBranchTwitch DOTS_ST_WindParam3
56#define DOTS_ST_WindBranchWhip DOTS_ST_WindParam4
57#define DOTS_ST_WindBranchAnchor DOTS_ST_WindParam5
58#define DOTS_ST_WindBranchAdherences DOTS_ST_WindParam6
59#define DOTS_ST_WindTurbulences DOTS_ST_WindParam7
60#define DOTS_ST_WindLeaf1Ripple DOTS_ST_WindParam8
61#define DOTS_ST_WindLeaf1Tumble DOTS_ST_WindParam9
62#define DOTS_ST_WindLeaf1Twitch DOTS_ST_WindParam10
63#define DOTS_ST_WindLeaf2Ripple DOTS_ST_WindParam11
64#define DOTS_ST_WindLeaf2Tumble DOTS_ST_WindParam12
65#define DOTS_ST_WindLeaf2Twitch DOTS_ST_WindParam13
66#define DOTS_ST_WindFrondRipple DOTS_ST_WindParam14
67#define DOTS_ST_WindAnimation DOTS_ST_WindParam15
68
69#define DOTS_ST_WindVectorHistory DOTS_ST_WindHistoryParam0
70#define DOTS_ST_WindGlobalHistory DOTS_ST_WindHistoryParam1
71#define DOTS_ST_WindBranchHistory DOTS_ST_WindHistoryParam2
72#define DOTS_ST_WindBranchTwitchHistory DOTS_ST_WindHistoryParam3
73#define DOTS_ST_WindBranchWhipHistory DOTS_ST_WindHistoryParam4
74#define DOTS_ST_WindBranchAnchorHistory DOTS_ST_WindHistoryParam5
75#define DOTS_ST_WindBranchAdherencesHistory DOTS_ST_WindHistoryParam6
76#define DOTS_ST_WindTurbulencesHistory DOTS_ST_WindHistoryParam7
77#define DOTS_ST_WindLeaf1RippleHistory DOTS_ST_WindHistoryParam8
78#define DOTS_ST_WindLeaf1TumbleHistory DOTS_ST_WindHistoryParam9
79#define DOTS_ST_WindLeaf1TwitchHistory DOTS_ST_WindHistoryParam10
80#define DOTS_ST_WindLeaf2RippleHistory DOTS_ST_WindHistoryParam11
81#define DOTS_ST_WindLeaf2TumbleHistory DOTS_ST_WindHistoryParam12
82#define DOTS_ST_WindLeaf2TwitchHistory DOTS_ST_WindHistoryParam13
83#define DOTS_ST_WindFrondRippleHistory DOTS_ST_WindHistoryParam14
84#define DOTS_ST_WindAnimationHistory DOTS_ST_WindHistoryParam15
85
86UNITY_DOTS_INSTANCING_START(UserPropertyMetadata)
87 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindVector)
88 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindGlobal)
89 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranch)
90 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchTwitch)
91 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchWhip)
92 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchAnchor)
93 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchAdherences)
94 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindTurbulences)
95 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf1Ripple)
96 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf1Tumble)
97 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf1Twitch)
98 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf2Ripple)
99 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf2Tumble)
100 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf2Twitch)
101 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindFrondRipple)
102 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindAnimation)
103
104 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindVectorHistory)
105 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindGlobalHistory)
106 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchHistory)
107 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchTwitchHistory)
108 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchWhipHistory)
109 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchAnchorHistory)
110 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchAdherencesHistory)
111 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindTurbulencesHistory)
112 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf1RippleHistory)
113 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf1TumbleHistory)
114 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf1TwitchHistory)
115 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf2RippleHistory)
116 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf2TumbleHistory)
117 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf2TwitchHistory)
118 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindFrondRippleHistory)
119 UNITY_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindAnimationHistory)
120UNITY_DOTS_INSTANCING_END(UserPropertyMetadata)
121
122#define _ST_WindVector UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindVector)
123#define _ST_WindGlobal UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindGlobal)
124#define _ST_WindBranch UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranch)
125#define _ST_WindBranchTwitch UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchTwitch)
126#define _ST_WindBranchWhip UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchWhip)
127#define _ST_WindBranchAnchor UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchAnchor)
128#define _ST_WindBranchAdherences UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchAdherences)
129#define _ST_WindTurbulences UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindTurbulences)
130#define _ST_WindLeaf1Ripple UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf1Ripple)
131#define _ST_WindLeaf1Tumble UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf1Tumble)
132#define _ST_WindLeaf1Twitch UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf1Twitch)
133#define _ST_WindLeaf2Ripple UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf2Ripple)
134#define _ST_WindLeaf2Tumble UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf2Tumble)
135#define _ST_WindLeaf2Twitch UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf2Twitch)
136#define _ST_WindFrondRipple UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindFrondRipple)
137#define _ST_WindAnimation UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindAnimation)
138
139#define _ST_WindVectorHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindVectorHistory)
140#define _ST_WindGlobalHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindGlobalHistory)
141#define _ST_WindBranchHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchHistory)
142#define _ST_WindBranchTwitchHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchTwitchHistory)
143#define _ST_WindBranchWhipHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchWhipHistory)
144#define _ST_WindBranchAnchorHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchAnchorHistory)
145#define _ST_WindBranchAdherencesHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindBranchAdherencesHistory)
146#define _ST_WindTurbulencesHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindTurbulencesHistory)
147#define _ST_WindLeaf1RippleHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf1RippleHistory)
148#define _ST_WindLeaf1TumbleHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf1TumbleHistory)
149#define _ST_WindLeaf1TwitchHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf1TwitchHistory)
150#define _ST_WindLeaf2RippleHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf2RippleHistory)
151#define _ST_WindLeaf2TumbleHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf2TumbleHistory)
152#define _ST_WindLeaf2TwitchHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindLeaf2TwitchHistory)
153#define _ST_WindFrondRippleHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindFrondRippleHistory)
154#define _ST_WindAnimationHistory UNITY_ACCESS_DOTS_INSTANCED_PROP(float4, DOTS_ST_WindAnimationHistory)
155
156#endif
157
158#define ST_WIND_QUALITY_NONE 0
159#define ST_WIND_QUALITY_FASTEST 1
160#define ST_WIND_QUALITY_FAST 2
161#define ST_WIND_QUALITY_BETTER 3
162#define ST_WIND_QUALITY_BEST 4
163#define ST_WIND_QUALITY_PALM 5
164
165///////////////////////////////////////////////////////////////////////
166// Get_Wind*() functions
167
168float4 Get_WindVector(bool bHistory) { return bHistory ? _ST_WindVectorHistory : _ST_WindVector; }
169float4 Get_WindGlobal(bool bHistory) { return bHistory ? _ST_WindGlobalHistory : _ST_WindGlobal; }
170float4 Get_WindBranch(bool bHistory) { return bHistory ? _ST_WindBranchHistory : _ST_WindBranch; }
171float4 Get_WindBranchTwitch(bool bHistory) { return bHistory ? _ST_WindBranchTwitchHistory : _ST_WindBranchTwitch; }
172float4 Get_WindBranchWhip(bool bHistory) { return bHistory ? _ST_WindBranchWhipHistory : _ST_WindBranchWhip; }
173float4 Get_WindBranchAnchor(bool bHistory) { return bHistory ? _ST_WindBranchAnchorHistory : _ST_WindBranchAnchor; }
174float4 Get_WindBranchAdherences(bool bHistory) { return bHistory ? _ST_WindBranchAdherencesHistory : _ST_WindBranchAdherences; }
175float4 Get_WindTurbulences(bool bHistory) { return bHistory ? _ST_WindTurbulencesHistory : _ST_WindTurbulences; }
176float4 Get_WindLeaf1Ripple(bool bHistory) { return bHistory ? _ST_WindLeaf1RippleHistory : _ST_WindLeaf1Ripple; }
177float4 Get_WindLeaf1Tumble(bool bHistory) { return bHistory ? _ST_WindLeaf1TumbleHistory : _ST_WindLeaf1Tumble; }
178float4 Get_WindLeaf1Twitch(bool bHistory) { return bHistory ? _ST_WindLeaf1TwitchHistory : _ST_WindLeaf1Twitch; }
179float4 Get_WindLeaf2Ripple(bool bHistory) { return bHistory ? _ST_WindLeaf2RippleHistory : _ST_WindLeaf2Ripple; }
180float4 Get_WindLeaf2Tumble(bool bHistory) { return bHistory ? _ST_WindLeaf2TumbleHistory : _ST_WindLeaf2Tumble; }
181float4 Get_WindLeaf2Twitch(bool bHistory) { return bHistory ? _ST_WindLeaf2TwitchHistory : _ST_WindLeaf2Twitch; }
182float4 Get_WindFrondRipple(bool bHistory) { return bHistory ? _ST_WindFrondRippleHistory : _ST_WindFrondRipple; }
183float4 Get_WindAnimation(bool bHistory) { return bHistory ? _ST_WindAnimationHistory : _ST_WindAnimation; }
184
185///////////////////////////////////////////////////////////////////////
186// UnpackNormalFromFloat
187
188float3 UnpackNormalFromFloat(float fValue)
189{
190 float3 vDecodeKey = float3(16.0, 1.0, 0.0625);
191
192 // decode into [0,1] range
193 float3 vDecodedValue = frac(fValue / vDecodeKey);
194
195 // move back into [-1,1] range & normalize
196 return (vDecodedValue * 2.0 - 1.0);
197}
198
199
200///////////////////////////////////////////////////////////////////////
201// CubicSmooth
202
203float4 CubicSmooth(float4 vData)
204{
205 return vData * vData * (3.0 - 2.0 * vData);
206}
207
208
209///////////////////////////////////////////////////////////////////////
210// TriangleWave
211
212float4 TriangleWave(float4 vData)
213{
214 return abs((frac(vData + 0.5) * 2.0) - 1.0);
215}
216
217
218///////////////////////////////////////////////////////////////////////
219// TrigApproximate
220
221float4 TrigApproximate(float4 vData)
222{
223 return (CubicSmooth(TriangleWave(vData)) - 0.5) * 2.0;
224}
225
226
227///////////////////////////////////////////////////////////////////////
228// RotationMatrix
229//
230// Constructs an arbitrary axis rotation matrix
231
232float3x3 RotationMatrix(float3 vAxis, float fAngle)
233{
234 // compute sin/cos of fAngle
235 float2 vSinCos;
236#ifdef OPENGL
237 vSinCos.x = sin(fAngle);
238 vSinCos.y = cos(fAngle);
239#else
240 sincos(fAngle, vSinCos.x, vSinCos.y);
241#endif
242
243 const float c = vSinCos.y;
244 const float s = vSinCos.x;
245 const float t = 1.0 - c;
246 const float x = vAxis.x;
247 const float y = vAxis.y;
248 const float z = vAxis.z;
249
250 return float3x3(t * x * x + c, t * x * y - s * z, t * x * z + s * y,
251 t * x * y + s * z, t * y * y + c, t * y * z - s * x,
252 t * x * z - s * y, t * y * z + s * x, t * z * z + c);
253}
254
255
256///////////////////////////////////////////////////////////////////////
257// mul_float3x3_float3x3
258
259float3x3 mul_float3x3_float3x3(float3x3 mMatrixA, float3x3 mMatrixB)
260{
261 return mul(mMatrixA, mMatrixB);
262}
263
264
265///////////////////////////////////////////////////////////////////////
266// mul_float3x3_float3
267
268float3 mul_float3x3_float3(float3x3 mMatrix, float3 vVector)
269{
270 return mul(mMatrix, vVector);
271}
272
273
274///////////////////////////////////////////////////////////////////////
275// cross()'s parameters are backwards in GLSL
276
277#define wind_cross(a, b) cross((a), (b))
278
279
280///////////////////////////////////////////////////////////////////////
281// Roll
282
283float Roll(float fCurrent,
284 float fMaxScale,
285 float fMinScale,
286 float fSpeed,
287 float fRipple,
288 float3 vPos,
289 float fTime,
290 float3 vRotatedWindVector)
291{
292 float fWindAngle = dot(vPos, -vRotatedWindVector) * fRipple;
293 float fAdjust = TrigApproximate(float4(fWindAngle + fTime * fSpeed, 0.0, 0.0, 0.0)).x;
294 fAdjust = (fAdjust + 1.0) * 0.5;
295
296 return lerp(fCurrent * fMinScale, fCurrent * fMaxScale, fAdjust);
297}
298
299
300///////////////////////////////////////////////////////////////////////
301// Twitch
302
303float Twitch(float3 vPos, float fAmount, float fSharpness, float fTime)
304{
305 const float c_fTwitchFudge = 0.87;
306 float4 vOscillations = TrigApproximate(float4(fTime + (vPos.x + vPos.z), c_fTwitchFudge * fTime + vPos.y, 0.0, 0.0));
307
308 //float fTwitch = sin(fFreq1 * fTime + (vPos.x + vPos.z)) * cos(fFreq2 * fTime + vPos.y);
309 float fTwitch = vOscillations.x * vOscillations.y * vOscillations.y;
310 fTwitch = (fTwitch + 1.0) * 0.5;
311
312 return fAmount * pow(saturate(fTwitch), fSharpness);
313}
314
315
316///////////////////////////////////////////////////////////////////////
317// Oscillate
318//
319// This function computes an oscillation value and whip value if necessary.
320// Whip and oscillation are combined like this to minimize calls to
321// TrigApproximate( ) when possible.
322
323float Oscillate(float3 vPos,
324 float fTime,
325 float fOffset,
326 float fWeight,
327 float fWhip,
328 bool bWhip,
329 bool bRoll,
330 bool bComplex,
331 float fTwitch,
332 float fTwitchFreqScale,
333 inout float4 vOscillations,
334 float3 vRotatedWindVector,
335 bool bHistory)
336{
337 float fOscillation = 1.0;
338 if (bComplex)
339 {
340 if (bWhip)
341 vOscillations = TrigApproximate(float4(fTime + fOffset, fTime * fTwitchFreqScale + fOffset, fTwitchFreqScale * 0.5 * (fTime + fOffset), fTime + fOffset + (1.0 - fWeight)));
342 else
343 vOscillations = TrigApproximate(float4(fTime + fOffset, fTime * fTwitchFreqScale + fOffset, fTwitchFreqScale * 0.5 * (fTime + fOffset), 0.0));
344
345 float fFineDetail = vOscillations.x;
346 float fBroadDetail = vOscillations.y * vOscillations.z;
347
348 float fTarget = 1.0;
349 float fAmount = fBroadDetail;
350 if (fBroadDetail < 0.0)
351 {
352 fTarget = -fTarget;
353 fAmount = -fAmount;
354 }
355
356 fBroadDetail = lerp(fBroadDetail, fTarget, fAmount);
357 fBroadDetail = lerp(fBroadDetail, fTarget, fAmount);
358
359 fOscillation = fBroadDetail * fTwitch * (1.0 - Get_WindVector(bHistory).w) + fFineDetail * (1.0 - fTwitch);
360
361 if (bWhip)
362 fOscillation *= 1.0 + (vOscillations.w * fWhip);
363 }
364 else
365 {
366 if (bWhip)
367 vOscillations = TrigApproximate(float4(fTime + fOffset, fTime * 0.689 + fOffset, 0.0, fTime + fOffset + (1.0 - fWeight)));
368 else
369 vOscillations = TrigApproximate(float4(fTime + fOffset, fTime * 0.689 + fOffset, 0.0, 0.0));
370
371 fOscillation = vOscillations.x + vOscillations.y * vOscillations.x;
372
373 if (bWhip)
374 fOscillation *= 1.0 + (vOscillations.w * fWhip);
375 }
376
377 //if (bRoll)
378 //{
379 // fOscillation = Roll(fOscillation, _ST_WindRollingBranches.x, _ST_WindRollingBranches.y, _ST_WindRollingBranches.z, _ST_WindRollingBranches.w, vPos.xyz, fTime + fOffset, vRotatedWindVector);
380 //}
381
382 return fOscillation;
383}
384
385
386///////////////////////////////////////////////////////////////////////
387// Turbulence
388
389float Turbulence(float fTime, float fOffset, float fGlobalTime, float fTurbulence)
390{
391 const float c_fTurbulenceFactor = 0.1;
392
393 float4 vOscillations = TrigApproximate(float4(fTime * c_fTurbulenceFactor + fOffset, fGlobalTime * fTurbulence * c_fTurbulenceFactor + fOffset, 0.0, 0.0));
394
395 return 1.0 - (vOscillations.x * vOscillations.y * vOscillations.x * vOscillations.y * fTurbulence);
396}
397
398
399///////////////////////////////////////////////////////////////////////
400// GlobalWind
401//
402// This function positions any tree geometry based on their untransformed
403// position and 4 wind floats.
404
405float3 GlobalWind(float3 vPos, float3 vInstancePos, bool bPreserveShape, float3 vRotatedWindVector, float time, bool bHistory)
406{
407 // WIND_LOD_GLOBAL may be on, but if the global wind effect (WIND_EFFECT_GLOBAL_ST_Wind)
408 // was disabled for the tree in the Modeler, we should skip it
409 const float4 windGlobal = Get_WindGlobal(bHistory);
410 const float4 windBranchAdherences = Get_WindBranchAdherences(bHistory);
411
412 float fLength = 1.0;
413 if (bPreserveShape)
414 fLength = length(vPos.xyz);
415
416 // compute how much the height contributes
417#ifdef SPEEDTREE_Z_UP
418 float fAdjust = max(vPos.z - (1.0 / windGlobal.z) * 0.25, 0.0) * windGlobal.z;
419#else
420 float fAdjust = max(vPos.y - (1.0 / windGlobal.z) * 0.25, 0.0) * windGlobal.z;
421#endif
422 if (fAdjust != 0.0)
423 fAdjust = pow(abs(fAdjust), windGlobal.w);
424
425 // primary oscillation
426 float4 vOscillations = TrigApproximate(float4(vInstancePos.x + time, vInstancePos.y + time * 0.8, 0.0, 0.0));
427 float fOsc = vOscillations.x + (vOscillations.y * vOscillations.y);
428 float fMoveAmount = windGlobal.y * fOsc;
429
430 // move a minimum amount based on direction adherence
431 fMoveAmount += windBranchAdherences.x / windGlobal.z;
432
433 // adjust based on how high up the tree this vertex is
434 fMoveAmount *= fAdjust;
435
436 // xy component
437#ifdef SPEEDTREE_Z_UP
438 vPos.xy += vRotatedWindVector.xy * fMoveAmount;
439#else
440 vPos.xz += vRotatedWindVector.xz * fMoveAmount;
441#endif
442
443 if (bPreserveShape)
444 vPos.xyz = normalize(vPos.xyz) * fLength;
445
446 return vPos;
447}
448
449
450///////////////////////////////////////////////////////////////////////
451// SimpleBranchWind
452
453float3 SimpleBranchWind(float3 vPos,
454 float3 vInstancePos,
455 float fWeight,
456 float fOffset,
457 float fTime,
458 float fDistance,
459 float fTwitch,
460 float fTwitchScale,
461 float fWhip,
462 bool bWhip,
463 bool bRoll,
464 bool bComplex,
465 float3 vRotatedWindVector,
466 bool bHistory)
467{
468 // turn the offset back into a nearly normalized vector
469 float3 vWindVector = UnpackNormalFromFloat(fOffset);
470 vWindVector = vWindVector * fWeight;
471
472 // try to fudge time a bit so that instances aren't in sync
473 fTime += vInstancePos.x + vInstancePos.y;
474
475 // oscillate
476 float4 vOscillations;
477 float fOsc = Oscillate(vPos, fTime, fOffset, fWeight, fWhip, bWhip, bRoll, bComplex, fTwitch, fTwitchScale, vOscillations, vRotatedWindVector, bHistory);
478
479 vPos.xyz += vWindVector * fOsc * fDistance;
480
481 return vPos;
482}
483
484
485///////////////////////////////////////////////////////////////////////
486// DirectionalBranchWind
487
488float3 DirectionalBranchWind(float3 vPos,
489 float3 vInstancePos,
490 float fWeight,
491 float fOffset,
492 float fTime,
493 float fDistance,
494 float fTurbulence,
495 float fAdherence,
496 float fTwitch,
497 float fTwitchScale,
498 float fWhip,
499 bool bWhip,
500 bool bRoll,
501 bool bComplex,
502 bool bTurbulence,
503 float3 vRotatedWindVector,
504 bool bHistory)
505{
506 // turn the offset back into a nearly normalized vector
507 float3 vWindVector = UnpackNormalFromFloat(fOffset);
508 vWindVector = vWindVector * fWeight;
509
510 // try to fudge time a bit so that instances aren't in sync
511 fTime += vInstancePos.x + vInstancePos.y;
512
513 // oscillate
514 float4 vOscillations;
515 float fOsc = Oscillate(vPos, fTime, fOffset, fWeight, fWhip, bWhip, false, bComplex, fTwitch, fTwitchScale, vOscillations, vRotatedWindVector, bHistory);
516
517 vPos.xyz += vWindVector * fOsc * fDistance;
518
519 // add in the direction, accounting for turbulence
520 float fAdherenceScale = 1.0;
521 if (bTurbulence)
522 fAdherenceScale = Turbulence(fTime, fOffset, Get_WindAnimation(bHistory).x, fTurbulence);
523
524 if (bWhip)
525 fAdherenceScale += vOscillations.w * Get_WindVector(bHistory).w * fWhip;
526
527 //if (bRoll)
528 // fAdherenceScale = Roll(fAdherenceScale, _ST_WindRollingBranches.x, _ST_WindRollingBranches.y, _ST_WindRollingBranches.z, _ST_WindRollingBranches.w, vPos.xyz, fTime + fOffset, vRotatedWindVector);
529
530 vPos.xyz += vRotatedWindVector * fAdherence * fAdherenceScale * fWeight;
531
532 return vPos;
533}
534
535
536///////////////////////////////////////////////////////////////////////
537// DirectionalBranchWindFrondStyle
538
539float3 DirectionalBranchWindFrondStyle(float3 vPos,
540 float3 vInstancePos,
541 float fWeight,
542 float fOffset,
543 float fTime,
544 float fDistance,
545 float fTurbulence,
546 float fAdherence,
547 float fTwitch,
548 float fTwitchScale,
549 float fWhip,
550 bool bWhip,
551 bool bRoll,
552 bool bComplex,
553 bool bTurbulence,
554 float3 vRotatedWindVector,
555 float3 vRotatedBranchAnchor,
556 bool bHistory)
557{
558 // turn the offset back into a nearly normalized vector
559 float3 vWindVector = UnpackNormalFromFloat(fOffset);
560 vWindVector = vWindVector * fWeight;
561
562 // try to fudge time a bit so that instances aren't in sync
563 fTime += vInstancePos.x + vInstancePos.y;
564
565 // oscillate
566 float4 vOscillations;
567 float fOsc = Oscillate(vPos, fTime, fOffset, fWeight, fWhip, bWhip, false, bComplex, fTwitch, fTwitchScale, vOscillations, vRotatedWindVector, bHistory);
568
569 vPos.xyz += vWindVector * fOsc * fDistance;
570
571 // add in the direction, accounting for turbulence
572 float fAdherenceScale = 1.0;
573 if (bTurbulence)
574 fAdherenceScale = Turbulence(fTime, fOffset, Get_WindAnimation(bHistory).x, fTurbulence);
575
576 //if (bRoll)
577 // fAdherenceScale = Roll(fAdherenceScale, _ST_WindRollingBranches.x, _ST_WindRollingBranches.y, _ST_WindRollingBranches.z, _ST_WindRollingBranches.w, vPos.xyz, fTime + fOffset, vRotatedWindVector);
578
579 if (bWhip)
580 fAdherenceScale += vOscillations.w * Get_WindVector(bHistory).w * fWhip;
581
582 float3 vWindAdherenceVector = vRotatedBranchAnchor - vPos.xyz;
583 vPos.xyz += vWindAdherenceVector * fAdherence * fAdherenceScale * fWeight;
584
585 return vPos;
586}
587
588
589///////////////////////////////////////////////////////////////////////
590// BranchWind
591
592// Apply only to better, best, palm winds
593float3 BranchWind(bool isPalmWind, float3 vPos, float3 vInstancePos, float4 vWindData, float3 vRotatedWindVector, float3 vRotatedBranchAnchor, bool bHistory)
594{
595 const float4 windBranch = Get_WindBranch(bHistory);
596 const float4 windBranchTwitch = Get_WindBranchTwitch(bHistory);
597 const float4 windBranchAdherences = Get_WindBranchAdherences(bHistory);
598 const float4 windBarnchWhip = Get_WindBranchWhip(bHistory);
599 const float4 windTurbulences = Get_WindTurbulences(bHistory);
600 const bool bWhip = isPalmWind;
601 const bool bRoll = false;
602 const bool bComplex = true;
603
604 if (isPalmWind)
605 {
606 const bool bTurbulence = true;
607 vPos = DirectionalBranchWindFrondStyle(
608 vPos,
609 vInstancePos,
610 vWindData.x, vWindData.y,
611 windBranch.x, windBranch.y,
612 windTurbulences.x, windBranchAdherences.y,
613 windBranchTwitch.x, windBranchTwitch.y,
614 windBarnchWhip.x,
615 bWhip,
616 bRoll,
617 bComplex,
618 bTurbulence,
619 vRotatedWindVector,
620 vRotatedBranchAnchor,
621 bHistory
622 );
623 }
624 else
625 {
626 vPos = SimpleBranchWind(
627 vPos,
628 vInstancePos,
629 vWindData.x, vWindData.y,
630 windBranch.x, windBranch.y,
631 windBranchTwitch.x, windBranchTwitch.y,
632 windBarnchWhip.x,
633 bWhip,
634 bRoll,
635 bComplex,
636 vRotatedWindVector,
637 bHistory
638 );
639 }
640
641 return vPos;
642}
643
644
645///////////////////////////////////////////////////////////////////////
646// LeafRipple
647
648float3 LeafRipple(float3 vPos,
649 inout float3 vDirection,
650 float fScale,
651 float fPackedRippleDir,
652 float fTime,
653 float fAmount,
654 bool bDirectional,
655 float fTrigOffset)
656{
657 // compute how much to move
658 float4 vInput = float4(fTime + fTrigOffset, 0.0, 0.0, 0.0);
659 float fMoveAmount = fAmount * TrigApproximate(vInput).x;
660
661 if (bDirectional)
662 {
663 vPos.xyz += vDirection.xyz * fMoveAmount * fScale;
664 }
665 else
666 {
667 float3 vRippleDir = UnpackNormalFromFloat(fPackedRippleDir);
668 vPos.xyz += vRippleDir * fMoveAmount * fScale;
669 }
670
671 return vPos;
672}
673
674
675///////////////////////////////////////////////////////////////////////
676// LeafTumble
677
678float3 LeafTumble(float3 vPos,
679 inout float3 vDirection,
680 float fScale,
681 float3 vAnchor,
682 float3 vGrowthDir,
683 float fTrigOffset,
684 float fTime,
685 float fFlip,
686 float fTwist,
687 float fAdherence,
688 float3 vTwitch,
689 float4 vRoll,
690 bool bTwitch,
691 bool bRoll,
692 float3 vRotatedWindVector)
693{
694 // compute all oscillations up front
695 float3 vFracs = frac((vAnchor + fTrigOffset) * 30.3);
696 float fOffset = vFracs.x + vFracs.y + vFracs.z;
697 float4 vOscillations = TrigApproximate(float4(fTime + fOffset, fTime * 0.75 - fOffset, fTime * 0.01 + fOffset, fTime * 1.0 + fOffset));
698
699 // move to the origin and get the growth direction
700 float3 vOriginPos = vPos.xyz - vAnchor;
701 float fLength = length(vOriginPos);
702
703 // twist
704 float fOsc = vOscillations.x + vOscillations.y * vOscillations.y;
705 float3x3 matTumble = RotationMatrix(vGrowthDir, fScale * fTwist * fOsc);
706
707 // with wind
708 float3 vAxis = wind_cross(vGrowthDir.xyz, vRotatedWindVector.xyz);
709 float fDot = clamp(dot(vRotatedWindVector, vGrowthDir), -1.0, 1.0);
710#ifdef SPEEDTREE_Z_UP
711 vAxis.z += fDot;
712#else
713 vAxis.y += fDot;
714#endif
715 vAxis = normalize(vAxis);
716
717 float fAngle = acos(fDot);
718
719 float fAdherenceScale = 1.0;
720 //if (bRoll)
721 //{
722 // fAdherenceScale = Roll(fAdherenceScale, vRoll.x, vRoll.y, vRoll.z, vRoll.w, vAnchor.xyz, fTime, vRotatedWindVector);
723 //}
724
725 fOsc = vOscillations.y - vOscillations.x * vOscillations.x;
726
727 float fTwitch = 0.0;
728 if (bTwitch)
729 fTwitch = Twitch(vAnchor.xyz, vTwitch.x, vTwitch.y, vTwitch.z + fOffset);
730
731 matTumble = mul_float3x3_float3x3(matTumble, RotationMatrix(vAxis, fScale * (fAngle * fAdherence * fAdherenceScale + fOsc * fFlip + fTwitch)));
732
733 vDirection = mul_float3x3_float3(matTumble, vDirection);
734 vOriginPos = mul_float3x3_float3(matTumble, vOriginPos);
735
736 vOriginPos = normalize(vOriginPos) * fLength;
737
738 return (vOriginPos + vAnchor);
739}
740
741
742///////////////////////////////////////////////////////////////////////
743// LeafWind
744// Optimized (for instruction count) version. Assumes leaf 1 and 2 have the same options
745
746float3 LeafWind(bool isBestWind,
747 bool bLeaf2,
748 float3 vPos,
749 inout float3 vDirection,
750 float fScale,
751 float3 vAnchor,
752 float fPackedGrowthDir,
753 float fPackedRippleDir,
754 float fRippleTrigOffset,
755 float3 vRotatedWindVector,
756 bool bHistory)
757{
758 const float4 windLeaf2Ripple = Get_WindLeaf2Ripple(bHistory);
759 const float4 windLeaf1Ripple = Get_WindLeaf1Ripple(bHistory);
760 const float4 windLeaf1Tumble = Get_WindLeaf1Tumble(bHistory);
761 const float4 windLeaf2Tumble = Get_WindLeaf2Tumble(bHistory);
762 const float4 windLeaf1Twitch = Get_WindLeaf2Twitch(bHistory);
763 const float4 windLeaf2Twitch = Get_WindLeaf2Twitch(bHistory);
764
765 vPos = LeafRipple(vPos, vDirection, fScale, fPackedRippleDir,
766 (bLeaf2 ? windLeaf2Ripple.x : windLeaf1Ripple.x),
767 (bLeaf2 ? windLeaf2Ripple.y : windLeaf1Ripple.y),
768 false, fRippleTrigOffset);
769
770 if (isBestWind)
771 {
772 float3 vGrowthDir = UnpackNormalFromFloat(fPackedGrowthDir);
773 vPos = LeafTumble(vPos, vDirection, fScale, vAnchor, vGrowthDir, fPackedGrowthDir,
774 (bLeaf2 ? windLeaf2Tumble.x : windLeaf1Tumble.x),
775 (bLeaf2 ? windLeaf2Tumble.y : windLeaf1Tumble.y),
776 (bLeaf2 ? windLeaf2Tumble.z : windLeaf1Tumble.z),
777 (bLeaf2 ? windLeaf2Tumble.w : windLeaf1Tumble.w),
778 (bLeaf2 ? windLeaf2Twitch.xyz : windLeaf1Twitch.xyz),
779 0.0f,
780 true,
781 true,
782 vRotatedWindVector);
783 }
784
785 return vPos;
786}
787
788
789///////////////////////////////////////////////////////////////////////
790// RippleFrondOneSided
791
792float3 RippleFrondOneSided(float3 vPos,
793 inout float3 vDirection,
794 float fU,
795 float fV,
796 float fRippleScale,
797 bool bHistory
798#ifdef WIND_EFFECT_FROND_RIPPLE_ADJUST_LIGHTING
799 , float3 vBinormal
800 , float3 vTangent
801#endif
802)
803{
804 float fOffset = 0.0;
805 if (fU < 0.5)
806 fOffset = 0.75;
807
808 const float4 windFrondRipple = Get_WindFrondRipple(bHistory);
809
810 float4 vOscillations = TrigApproximate(float4((windFrondRipple.x + fV) * windFrondRipple.z + fOffset, 0.0, 0.0, 0.0));
811
812 float fAmount = fRippleScale * vOscillations.x * windFrondRipple.y;
813 float3 vOffset = fAmount * vDirection;
814 vPos.xyz += vOffset;
815
816#ifdef WIND_EFFECT_FROND_RIPPLE_ADJUST_LIGHTING
817 vTangent.xyz = normalize(vTangent.xyz + vOffset * windFrondRipple.w);
818 float3 vNewNormal = normalize(wind_cross(vBinormal.xyz, vTangent.xyz));
819 if (dot(vNewNormal, vDirection.xyz) < 0.0)
820 vNewNormal = -vNewNormal;
821 vDirection.xyz = vNewNormal;
822#endif
823
824 return vPos;
825}
826
827///////////////////////////////////////////////////////////////////////
828// RippleFrondTwoSided
829
830float3 RippleFrondTwoSided(float3 vPos,
831 inout float3 vDirection,
832 float fU,
833 float fLengthPercent,
834 float fPackedRippleDir,
835 float fRippleScale,
836 bool bHistory
837#ifdef WIND_EFFECT_FROND_RIPPLE_ADJUST_LIGHTING
838 , float3 vBinormal
839 , float3 vTangent
840#endif
841)
842{
843 const float4 windFrondRipple = Get_WindFrondRipple(bHistory);
844 float4 vOscillations = TrigApproximate(float4(windFrondRipple.x * fLengthPercent * windFrondRipple.z, 0.0, 0.0, 0.0));
845
846 float3 vRippleDir = UnpackNormalFromFloat(fPackedRippleDir);
847
848 float fAmount = fRippleScale * vOscillations.x * windFrondRipple.y;
849 float3 vOffset = fAmount * vRippleDir;
850
851 vPos.xyz += vOffset;
852
853#ifdef WIND_EFFECT_FROND_RIPPLE_ADJUST_LIGHTING
854 vTangent.xyz = normalize(vTangent.xyz + vOffset * windFrondRipple.w);
855 float3 vNewNormal = normalize(wind_cross(vBinormal.xyz, vTangent.xyz));
856 if (dot(vNewNormal, vDirection.xyz) < 0.0)
857 vNewNormal = -vNewNormal;
858 vDirection.xyz = vNewNormal;
859#endif
860
861 return vPos;
862}
863
864
865///////////////////////////////////////////////////////////////////////
866// RippleFrond
867
868float3 RippleFrond(float3 vPos,
869 inout float3 vDirection,
870 float fU,
871 float fV,
872 float fPackedRippleDir,
873 float fRippleScale,
874 float fLenghtPercent,
875 bool bHistory
876#ifdef WIND_EFFECT_FROND_RIPPLE_ADJUST_LIGHTING
877 , float3 vBinormal
878 , float3 vTangent
879#endif
880)
881{
882 return RippleFrondOneSided(vPos,
883 vDirection,
884 fU,
885 fV,
886 fRippleScale,
887 bHistory
888#ifdef WIND_EFFECT_FROND_RIPPLE_ADJUST_LIGHTING
889 , vBinormal
890 , vTangent
891#endif
892 );
893}
894
895///////////////////////////////////////////////////////////////////////
896// SpeedTreeWind
897
898
899float3 SpeedTreeWind(
900 float3 vPos,
901 float3 vNormal,
902 float4 vTexcoord0,
903 float4 vTexcoord1,
904 float4 vTexcoord2,
905 float4 vTexcoord3,
906 int iWindQuality,
907 bool bBillboard,
908 bool bHistory
909)
910{
911 float3 vReturnPos = vPos;
912
913 // check wind enabled & data available
914 float3 windVector = Get_WindVector(bHistory).xyz;
915 float3 rotatedWindVector = TransformWindVectorFromWorldToLocalSpace(windVector);
916
917 if (iWindQuality == 0 || (length(rotatedWindVector) < 1.0e-5) )
918 {
919 return vReturnPos; // sanity check that wind data is available
920 }
921
922 // do wind
923 float4x4 matObjectToWorld = GetObjectToWorldMatrix();
924 float3 treePos = GetAbsolutePositionWS(float3(matObjectToWorld[0].w, matObjectToWorld[1].w, matObjectToWorld[2].w));
925 float globalWindTime = Get_WindGlobal(bHistory).x;
926
927 // BILLBOARD WIND =======================================================================================================================
928 if(bBillboard)
929 {
930 vReturnPos = GlobalWind(vReturnPos, treePos, true, rotatedWindVector, globalWindTime, bHistory);
931 return vReturnPos;
932 }
933
934 // 3D GEOMETRY WIND =====================================================================================================================
935 // leaf
936 bool leafTwo = false;
937 const int geometryType = GetGeometryType(vTexcoord3, leafTwo);
938 const bool bDoLeafWind = ((iWindQuality == ST_WIND_QUALITY_FAST) || (iWindQuality == ST_WIND_QUALITY_BETTER) || (iWindQuality == ST_WIND_QUALITY_BEST))
939 && geometryType > ST_GEOM_TYPE_FROND;
940 if (bDoLeafWind)
941 {
942 const float3 anchor = float3(vTexcoord1.zw, vTexcoord2.w);
943 const float leafWindTrigOffset = anchor.x + anchor.y;
944 const bool bBestWind = (iWindQuality == ST_WIND_QUALITY_BEST);
945
946 vReturnPos -= anchor; // remove anchor position
947 vReturnPos = LeafWind(bBestWind, leafTwo, vReturnPos, vNormal, vTexcoord3.x, float3(0, 0, 0), vTexcoord3.y, vTexcoord3.z, leafWindTrigOffset, rotatedWindVector, bHistory);
948 vReturnPos += anchor; // move back out to anchor
949 }
950
951 // frond wind (palm-only)
952 const bool bDoPalmWind = iWindQuality == ST_WIND_QUALITY_PALM && geometryType == ST_GEOM_TYPE_FROND;
953 if (bDoPalmWind)
954 {
955 vReturnPos = RippleFrond(vReturnPos, vNormal, vTexcoord0.x, vTexcoord0.y, vTexcoord3.x, vTexcoord3.y, vTexcoord3.z, bHistory);
956 }
957
958 // branch wind (applies to all 3D geometry)
959 const bool bDoBranchWind = (iWindQuality == ST_WIND_QUALITY_BETTER) || (iWindQuality == ST_WIND_QUALITY_BEST) || (iWindQuality == ST_WIND_QUALITY_PALM);
960 if (bDoBranchWind)
961 {
962 const float4 windBranchAnchorHistory = Get_WindBranchAnchor(bHistory);
963 const float3 rotatedBranchAnchor = TransformWorldToObjectDir(windBranchAnchorHistory.xyz) * windBranchAnchorHistory.w;
964 vReturnPos = BranchWind(bDoPalmWind, vReturnPos, treePos, float4(vTexcoord0.zw, 0, 0), rotatedWindVector, rotatedBranchAnchor, bHistory);
965 }
966
967 // global wind
968 vReturnPos = GlobalWind(vReturnPos, treePos, true, rotatedWindVector, globalWindTime, bHistory);
969 return vReturnPos;
970}
971
972// ShaderGraph stub
973void SpeedTreeWind_float(float3 vPos, float3 vNormal, float4 vTexcoord0, float4 vTexcoord1, float4 vTexcoord2, float4 vTexcoord3, int iWindQuality, bool bBillboard, bool bHistory, out float3 outPos)
974{
975 outPos = SpeedTreeWind(vPos, vNormal, vTexcoord0, vTexcoord1, vTexcoord2, vTexcoord3, iWindQuality, bBillboard, bHistory);
976}
977#endif // SPEEDTREE_WIND_8_INCLUDED