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