Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
4.5 KiB

  1. //============ Copyright (c) Valve Corporation, All rights reserved. ============
  2. #ifndef _TREE_SWAY_H
  3. #define _TREE_SWAY_H
  4. // Tree sway vertex animation function. Requires a number of global variables to be defined. See vertexlit_and_unlit_generic_vs20.fxc or depthwrite_vs20.fxc for details.
  5. // Tree sway mode 2:
  6. // Hacks to use tree sway code on rectangular sheets of plastic/tarp attached at the four corners.
  7. // Inverts the sway scale radius to be 1 at (0,0,0) in model space and fall off radially towards the edges of the model.
  8. // The model is expected to be build lying in the xy plane in model space, with its center at the origin.
  9. // Treeswaystrength should be 0 in the vmt.
  10. #if ( TREESWAY )
  11. float3 ComputeTreeSway( float3 vPositionOS, float flTime )
  12. {
  13. static const float g_flWindOffsetScale = 19;
  14. float flWindIntensity = length( g_vWindDir );
  15. // Model root position is the translation component of the model to world matrix
  16. float3 vModelRoot = float3( hlsl_float4x3_element( cModel[0],3,0 ), hlsl_float4x3_element( cModel[0],3,1 ), hlsl_float4x3_element( cModel[0],3,2 ) );
  17. // Transform the wind direction into model space
  18. #ifdef _PS3
  19. float3 vWindDirAndIntensityOS = mul( float3( g_vWindDir, 0 ), ( float3x3 )cModel[0] );
  20. #else
  21. float3 vWindDirAndIntensityOS = mul( ( float3x3 )cModel[0], float3( g_vWindDir, 0 ) );
  22. #endif // !_PS3
  23. float flSwayScaleHeight = saturate( ( vPositionOS.z - g_flHeight * g_flStartHeight ) /
  24. ( ( 1.0 - g_flStartHeight ) * g_flHeight ) );
  25. float flSwayScaleRadius = saturate( length( ( vPositionOS.xy ) - g_flRadius * g_flStartRadius ) /
  26. ( ( 1.0 - g_flStartRadius ) * g_flRadius ) );
  27. // Used to turn off branch sway and scrumble below the minimum sway height
  28. float flHeightThreshold = step( 0, vPositionOS.z - g_flHeight * g_flStartHeight );
  29. #if ( TREESWAY == 2 )
  30. {
  31. // Works better for hanging vines
  32. flHeightThreshold = step( vPositionOS.z - g_flHeight * g_flStartHeight, 0 );
  33. }
  34. #endif
  35. #ifdef _X360
  36. // Scale branch motion based on how orthogonal they are
  37. float flOrthoBranchScale = 1.0 - abs( dot( normalize( vWindDirAndIntensityOS.xyz ), float3( normalize( vPositionOS.xy ), 0 ) ) );
  38. #else
  39. // Scale branch motion based on how orthogonal they are
  40. // This is what I want to compute:
  41. // float flOrthoBranchScale = 1.0 - abs( dot( normalize( vWindDirAndIntensityOS.xyz ), float3( normalize( vPositionOS.xy ), 0 ) ) );
  42. // Some NV hardware (7800) will do bad things when normalizing a 0 length vector. Instead, I'm doing the dot product unnormalized
  43. // and divide by the length of the vectors, making sure to avoid divide by 0.
  44. float flOrthoBranchScale = abs( dot( vWindDirAndIntensityOS.xyz, float3( vPositionOS.xy, 0 ) ) );
  45. flOrthoBranchScale = 1.0 - saturate( flOrthoBranchScale / ( max( length( vWindDirAndIntensityOS.xyz ), 0.0001 ) * max( length( vPositionOS.xy ), 0.0001 ) ) );
  46. #endif
  47. float flSwayScaleTrunk = g_flSwayIntensity * pow( flSwayScaleHeight, g_flSwayFalloffCurve );
  48. float flSwayScaleBranches = g_flSwayIntensity * flOrthoBranchScale * flSwayScaleRadius * flHeightThreshold;
  49. #if ( TREESWAY == 2 )
  50. {
  51. // Looks stupid on vines
  52. flSwayScaleBranches = 0.0;
  53. }
  54. #endif
  55. float flWindTimeOffset = dot( vModelRoot.xyz, float3( 1, 1, 1 ) ) * g_flWindOffsetScale;
  56. float flSlowSwayTime = ( flTime + flWindTimeOffset ) * g_flSwaySpeed;
  57. float3 vSwayPosOS = normalize( vPositionOS.xyz );
  58. float3 vScrumblePosOS = vSwayPosOS * g_flScrumbleWaveCount;
  59. float flScrumbleScale = pow( flSwayScaleRadius, g_flScrumbleFalloffCurve ) * g_flScrumbleIntensity * flHeightThreshold;
  60. float3 vPositionOffset = float3( 0, 0, 0 );
  61. // lerp between slow and fast sines based on wind speed
  62. float flSpeedLerp = smoothstep( g_flWindSpeedLerpStart, g_flWindSpeedLerpEnd, flWindIntensity );
  63. float4 vABunchOfSines = sin( float4( 1.0, 2.31, g_flFastSwaySpeedScale, 2.14 * g_flFastSwaySpeedScale ) * flSlowSwayTime.xxxx );
  64. vABunchOfSines.xy = lerp( vABunchOfSines.xy, vABunchOfSines.zw, flSpeedLerp );
  65. vPositionOffset.xyz = vWindDirAndIntensityOS * flSwayScaleTrunk * ( vABunchOfSines.x + 0.1 );
  66. vPositionOffset.xyz += vWindDirAndIntensityOS * flSwayScaleBranches * ( vABunchOfSines.y + 0.4 );
  67. float3 vScrumbleScale = flScrumbleScale.xxx;
  68. #if ( TREESWAY == 2 )
  69. {
  70. vScrumbleScale *= float3( 0.5, 0.5, 1.0 );
  71. }
  72. #endif
  73. vPositionOffset.xyz += flWindIntensity * ( vScrumbleScale.xyz * sin( g_flScrumbleSpeed * flTime.xxx + vScrumblePosOS.yzx + flWindTimeOffset.xxx ) );
  74. return vPositionOS.xyz + vPositionOffset.xyz;
  75. }
  76. #endif
  77. #endif // _TREE_SWAY_H