Team Fortress 2 Source Code as on 22/4/2020
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.

130 lines
4.1 KiB

  1. // DYNAMIC: "FOGTYPE" "0..1"
  2. #include "common_vs_fxc.h"
  3. static const int g_FogType = FOGTYPE;
  4. const float4 cCustomConstants[6] : register( SHADER_SPECIFIC_CONST_0 );
  5. const float4 g_vLightPosition : register( SHADER_SPECIFIC_CONST_0 );
  6. const float4 g_vLightColor : register( SHADER_SPECIFIC_CONST_1 ); // range 0-1
  7. const float g_flLightIntensity : register( SHADER_SPECIFIC_CONST_2 ); // scales g_vLightColor
  8. struct VS_INPUT
  9. {
  10. // If this is float4, and the input is float3, the w component default to one.
  11. float4 vPos : POSITION;
  12. float2 vBumpTexCoord : TEXCOORD0;
  13. float4 vAmbientColor : COLOR0;
  14. };
  15. struct VS_OUTPUT
  16. {
  17. float4 projPos : POSITION;
  18. #if !defined( _X360 )
  19. float fog : FOG;
  20. #endif
  21. float2 vBumpTexCoord : TEXCOORD0;
  22. float3 vTangentSpaceLightDir : TEXCOORD1;
  23. float3 vAmbientColor : TEXCOORD2;
  24. #if defined( _X360 )
  25. float4 vScreenPos_ReverseZ : TEXCOORD3;
  26. #else
  27. float4 vScreenPos : TEXCOORD3;
  28. #endif
  29. float4 vDirLightScale : COLOR0;
  30. float4 worldPos_projPosZ : TEXCOORD7; // Necessary for pixel fog
  31. };
  32. VS_OUTPUT main( const VS_INPUT v )
  33. {
  34. VS_OUTPUT o;
  35. // Transform the input position.
  36. float4 projPos = mul( v.vPos, cModelViewProj );
  37. o.projPos = projPos;
  38. projPos.z = dot( v.vPos, cModelViewProjZ );
  39. #if defined( _X360 )
  40. o.vScreenPos_ReverseZ.x = projPos.x;
  41. o.vScreenPos_ReverseZ.y = -projPos.y; // invert Y
  42. o.vScreenPos_ReverseZ.xy = (o.vScreenPos_ReverseZ.xy + projPos.w) * 0.5f;
  43. o.vScreenPos_ReverseZ.z = projPos.w - projPos.z;
  44. o.vScreenPos_ReverseZ.w = projPos.w;
  45. #else
  46. o.vScreenPos.x = projPos.x;
  47. o.vScreenPos.y = -projPos.y; // invert Y
  48. o.vScreenPos.xy = (o.vScreenPos.xy + projPos.w) * 0.5f;
  49. o.vScreenPos.z = projPos.z;
  50. o.vScreenPos.w = projPos.w;
  51. #endif
  52. o.worldPos_projPosZ = float4( v.vPos.xyz, projPos.z );
  53. #if !defined( _X360 )
  54. // Setup fog.
  55. o.fog = CalcFog( mul( v.vPos, cModel[0] ), projPos, g_FogType );
  56. #endif
  57. // Copy texcoords over.
  58. o.vBumpTexCoord = v.vBumpTexCoord;
  59. // Copy the vertex color over.
  60. o.vAmbientColor = v.vAmbientColor;
  61. // ------------------------------------------------------------------------------
  62. // Generate a tangent space and rotate L.
  63. // This can be thought of as rotating the normal map to face the viewer.
  64. //
  65. // This is useful when a particle is way off to the side of the screen.
  66. // You should be looking at the half-sphere with a normal pointing from the
  67. // particle to the viewer. Instead, you're looking at the half-sphere with
  68. // a normal along Z. This tangent space builder code fixes the problem.
  69. //
  70. // Note that since the model and view matrices are identity, the coordinate
  71. // system has X=right, Y=up, and Z=behind you (negative Z goes into the screen).
  72. // ------------------------------------------------------------------------------
  73. // This basis wants Z positive going into the screen so flip it here.
  74. float4 vForward = normalize( float4( v.vPos.x, v.vPos.y, -v.vPos.z, 1 ) );
  75. // This is the same as CrossProduct( vForward, Vector( 1, 0, 0 ) )
  76. float4 vUp = normalize( float4( 0, vForward.z, -vForward.y, vForward.w ) );
  77. // vRight = CrossProduct( vUp, vForward )
  78. float4 vRight = vUp.yzxw * vForward.zxyw;
  79. vRight += -vUp.zxyw * vForward.yzxw;
  80. // Put the light in tangent space.
  81. float4 vToLight = g_vLightPosition - v.vPos;
  82. float4 vTangentSpaceLight = vRight*vToLight.x + vUp*vToLight.y + vForward*vToLight.z;
  83. // Output texcoord 1 holds the normalized transformed light direction.
  84. o.vTangentSpaceLightDir = normalize( vTangentSpaceLight ) * 0.5 + 0.5; // make it 0-1 for the pixel shader
  85. // Handle oversaturation here. The shader code already scaled the light color so its max value is 1,
  86. // so if our intensity/distance scale is > 1, then all we need to do is use the light color.
  87. float flTransposedLenSqr = dot( vTangentSpaceLight, vTangentSpaceLight );
  88. float flScaledIntensity = g_flLightIntensity / flTransposedLenSqr;
  89. if ( flScaledIntensity > 1 )
  90. {
  91. o.vDirLightScale.xyz = g_vLightColor;
  92. }
  93. else
  94. {
  95. o.vDirLightScale.xyz = g_vLightColor * flScaledIntensity;
  96. }
  97. // Alpha comes right from the vertex color.
  98. o.vDirLightScale.a = v.vAmbientColor.a;
  99. return o;
  100. }