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.

419 lines
15 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "BaseVSShader.h"
  8. #include "mathlib/vmatrix.h"
  9. #include "water_vs11.inc"
  10. #include "watercheappervertexfresnel_vs11.inc"
  11. #include "watercheap_vs11.inc"
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. BEGIN_VS_SHADER( Water_DX80,
  15. "Help for Water_DX80" )
  16. BEGIN_SHADER_PARAMS
  17. SHADER_PARAM( REFRACTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "", "" )
  18. SHADER_PARAM( REFLECTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "_rt_WaterReflection", "" )
  19. SHADER_PARAM( REFRACTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" )
  20. SHADER_PARAM( REFRACTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "refraction tint" )
  21. SHADER_PARAM( REFLECTAMOUNT, SHADER_PARAM_TYPE_FLOAT, "0", "" )
  22. SHADER_PARAM( REFLECTTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "reflection tint" )
  23. SHADER_PARAM( BUMPMAP, SHADER_PARAM_TYPE_TEXTURE, "", "dudv bump map" )
  24. SHADER_PARAM( NORMALMAP, SHADER_PARAM_TYPE_TEXTURE, "", "normal map" )
  25. SHADER_PARAM( BUMPFRAME, SHADER_PARAM_TYPE_INTEGER, "0", "frame number for $bumpmap" )
  26. SHADER_PARAM( BUMPTRANSFORM, SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", "$bumpmap texcoord transform" )
  27. SHADER_PARAM( SCALE, SHADER_PARAM_TYPE_VEC2, "[1 1]", "" )
  28. SHADER_PARAM( TIME, SHADER_PARAM_TYPE_FLOAT, "", "" )
  29. SHADER_PARAM( WATERDEPTH, SHADER_PARAM_TYPE_FLOAT, "", "" )
  30. SHADER_PARAM( CHEAPWATERSTARTDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should start transitioning to a cheaper water shader." )
  31. SHADER_PARAM( CHEAPWATERENDDISTANCE, SHADER_PARAM_TYPE_FLOAT, "", "This is the distance from the eye in inches that the shader should finish transitioning to a cheaper water shader." )
  32. SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "env_cubemap", "envmap" )
  33. SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" )
  34. SHADER_PARAM( FOGCOLOR, SHADER_PARAM_TYPE_COLOR, "", "" )
  35. SHADER_PARAM( FORCECHEAP, SHADER_PARAM_TYPE_INTEGER, "", "" )
  36. SHADER_PARAM( FORCEEXPENSIVE, SHADER_PARAM_TYPE_BOOL, "", "" )
  37. SHADER_PARAM( REFLECTENTITIES, SHADER_PARAM_TYPE_BOOL, "", "" )
  38. SHADER_PARAM( REFLECTBLENDFACTOR, SHADER_PARAM_TYPE_FLOAT, "1.0", "" )
  39. SHADER_PARAM( NOFRESNEL, SHADER_PARAM_TYPE_BOOL, "0", "" )
  40. END_SHADER_PARAMS
  41. SHADER_INIT_PARAMS()
  42. {
  43. SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES );
  44. if( !params[CHEAPWATERSTARTDISTANCE]->IsDefined() )
  45. {
  46. params[CHEAPWATERSTARTDISTANCE]->SetFloatValue( 500.0f );
  47. }
  48. if( !params[CHEAPWATERENDDISTANCE]->IsDefined() )
  49. {
  50. params[CHEAPWATERENDDISTANCE]->SetFloatValue( 1000.0f );
  51. }
  52. if( !params[SCALE]->IsDefined() )
  53. {
  54. params[SCALE]->SetVecValue( 1.0f, 1.0f );
  55. }
  56. if( !params[FOGCOLOR]->IsDefined() )
  57. {
  58. params[FOGCOLOR]->SetVecValue( 1.0f, 0.0f, 0.0f );
  59. Warning( "material %s needs to have a $fogcolor.\n", pMaterialName );
  60. }
  61. if( !params[REFLECTENTITIES]->IsDefined() )
  62. {
  63. params[REFLECTENTITIES]->SetIntValue( 0 );
  64. }
  65. if( !params[FORCEEXPENSIVE]->IsDefined() )
  66. {
  67. params[FORCEEXPENSIVE]->SetIntValue( 0 );
  68. }
  69. if( !params[REFLECTBLENDFACTOR]->IsDefined() )
  70. {
  71. params[REFLECTBLENDFACTOR]->SetFloatValue( 1.0f );
  72. }
  73. if( params[FORCEEXPENSIVE]->GetIntValue() && params[FORCECHEAP]->GetIntValue() )
  74. {
  75. params[FORCEEXPENSIVE]->SetIntValue( 0 );
  76. }
  77. }
  78. SHADER_FALLBACK
  79. {
  80. if ( IsPC() && ( g_pHardwareConfig->GetDXSupportLevel() < 80 || !g_pHardwareConfig->HasProjectedBumpEnv() ) )
  81. {
  82. return "Water_DX60";
  83. }
  84. return 0;
  85. }
  86. SHADER_INIT
  87. {
  88. Assert( params[WATERDEPTH]->IsDefined() );
  89. if( params[REFRACTTEXTURE]->IsDefined() )
  90. {
  91. LoadTexture( REFRACTTEXTURE );
  92. }
  93. if( params[REFLECTTEXTURE]->IsDefined() )
  94. {
  95. LoadTexture( REFLECTTEXTURE );
  96. }
  97. if (params[BUMPMAP]->IsDefined() )
  98. {
  99. LoadTexture( BUMPMAP );
  100. }
  101. if (params[ENVMAP]->IsDefined() )
  102. {
  103. LoadCubeMap( ENVMAP );
  104. }
  105. if (params[NORMALMAP]->IsDefined() )
  106. {
  107. LoadBumpMap( NORMALMAP );
  108. }
  109. }
  110. inline void SetCheapWaterFactors( IMaterialVar **params, IShaderDynamicAPI* pShaderAPI, int nConstantReg )
  111. {
  112. float flCheapWaterStartDistance = params[CHEAPWATERSTARTDISTANCE]->GetFloatValue();
  113. float flCheapWaterEndDistance = params[CHEAPWATERENDDISTANCE]->GetFloatValue();
  114. float flCheapWaterConstants[4] =
  115. {
  116. flCheapWaterStartDistance,
  117. 1.0f / ( flCheapWaterEndDistance - flCheapWaterStartDistance ),
  118. 0.0f,
  119. 0.0f
  120. };
  121. pShaderAPI->SetVertexShaderConstant( nConstantReg, flCheapWaterConstants );
  122. }
  123. inline void DrawReflection( IMaterialVar **params, IShaderShadow* pShaderShadow,
  124. IShaderDynamicAPI* pShaderAPI, bool bBlendReflection )
  125. {
  126. SHADOW_STATE
  127. {
  128. SetInitialShadowState( );
  129. pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
  130. pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
  131. pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
  132. pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
  133. int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T;
  134. pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 );
  135. if( bBlendReflection )
  136. {
  137. EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA );
  138. }
  139. water_vs11_Static_Index vshIndex;
  140. pShaderShadow->SetVertexShader( "Water_vs11", vshIndex.GetIndex() );
  141. pShaderShadow->SetPixelShader( "WaterReflect_ps11", 0 );
  142. FogToFogColor();
  143. }
  144. DYNAMIC_STATE
  145. {
  146. pShaderAPI->SetDefaultState();
  147. // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders.
  148. pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE1, 0, true );
  149. float fReflectionAmount = params[REFLECTAMOUNT]->GetFloatValue();
  150. pShaderAPI->SetBumpEnvMatrix( SHADER_TEXTURE_STAGE1, fReflectionAmount, 0.0f, 0.0f, fReflectionAmount );
  151. BindTexture( SHADER_SAMPLER0, BUMPMAP, BUMPFRAME );
  152. BindTexture( SHADER_SAMPLER1, REFLECTTEXTURE, -1 );
  153. BindTexture( SHADER_SAMPLER2, NORMALMAP, BUMPFRAME );
  154. pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALIZATION_CUBEMAP );
  155. pShaderAPI->SetVertexShaderIndex( 0 );
  156. SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM );
  157. // used to invert y
  158. float c[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
  159. pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, c, 1 );
  160. SetPixelShaderConstant( 0, REFLECTTINT );
  161. water_vs11_Dynamic_Index vshIndex;
  162. vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
  163. pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() );
  164. }
  165. Draw();
  166. }
  167. inline void DrawRefraction( IMaterialVar **params, IShaderShadow* pShaderShadow,
  168. IShaderDynamicAPI* pShaderAPI )
  169. {
  170. SHADOW_STATE
  171. {
  172. pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
  173. pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
  174. int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T;
  175. pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 );
  176. water_vs11_Static_Index vshIndex;
  177. pShaderShadow->SetVertexShader( "Water_vs11", vshIndex.GetIndex() );
  178. pShaderShadow->SetPixelShader( "WaterRefract_ps11", 0 );
  179. FogToFogColor();
  180. }
  181. DYNAMIC_STATE
  182. {
  183. // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders.
  184. pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE1, 0, true );
  185. float fRefractionAmount = params[REFRACTAMOUNT]->GetFloatValue();
  186. pShaderAPI->SetBumpEnvMatrix( SHADER_TEXTURE_STAGE1, fRefractionAmount, 0.0f, 0.0f, fRefractionAmount );
  187. BindTexture( SHADER_SAMPLER0, BUMPMAP, BUMPFRAME );
  188. BindTexture( SHADER_SAMPLER1, REFRACTTEXTURE );
  189. SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM );
  190. // used to invert y
  191. float c[4] = { 0.0f, 0.0f, 0.0f, -1.0f };
  192. pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, c, 1 );
  193. SetPixelShaderConstant( 0, REFRACTTINT );
  194. water_vs11_Dynamic_Index vshIndex;
  195. vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
  196. pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() );
  197. }
  198. Draw();
  199. }
  200. inline void DrawRefractionForFresnel( IMaterialVar **params, IShaderShadow* pShaderShadow,
  201. IShaderDynamicAPI* pShaderAPI )
  202. {
  203. SHADOW_STATE
  204. {
  205. pShaderShadow->EnableAlphaWrites( true );
  206. pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
  207. pShaderShadow->EnableTexture( SHADER_SAMPLER1, true );
  208. pShaderShadow->EnableTexture( SHADER_SAMPLER2, true );
  209. pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
  210. int fmt = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S | VERTEX_TANGENT_T;
  211. pShaderShadow->VertexShaderVertexFormat( fmt, 1, 0, 0 );
  212. water_vs11_Static_Index vshIndex;
  213. pShaderShadow->SetVertexShader( "Water_vs11", vshIndex.GetIndex() );
  214. pShaderShadow->SetPixelShader( "WaterRefractFresnel_ps11", 0 );
  215. FogToFogColor();
  216. }
  217. DYNAMIC_STATE
  218. {
  219. // The dx9.0c runtime says that we shouldn't have a non-zero dimension when using vertex and pixel shaders.
  220. pShaderAPI->SetTextureTransformDimension( SHADER_TEXTURE_STAGE1, 0, true );
  221. float fRefractionAmount = params[REFRACTAMOUNT]->GetFloatValue();
  222. pShaderAPI->SetBumpEnvMatrix( SHADER_TEXTURE_STAGE1, fRefractionAmount, 0.0f, 0.0f, fRefractionAmount );
  223. BindTexture( SHADER_SAMPLER0, BUMPMAP, BUMPFRAME );
  224. BindTexture( SHADER_SAMPLER1, REFRACTTEXTURE );
  225. BindTexture( SHADER_SAMPLER2, NORMALMAP, BUMPFRAME );
  226. s_pShaderAPI->BindStandardTexture( SHADER_SAMPLER3, TEXTURE_NORMALIZATION_CUBEMAP );
  227. SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_1, BUMPTRANSFORM );
  228. SetCheapWaterFactors( params, pShaderAPI, VERTEX_SHADER_SHADER_SPECIFIC_CONST_3 );
  229. // used to invert y
  230. float c[4] = { 0.0f, 0.0f, 0.0f, -1.0f };
  231. pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4, c, 1 );
  232. SetPixelShaderConstant( 0, REFRACTTINT );
  233. water_vs11_Dynamic_Index vshIndex;
  234. vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
  235. pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() );
  236. }
  237. Draw();
  238. }
  239. inline void DrawCheapWater( IMaterialVar **params, IShaderShadow* pShaderShadow,
  240. IShaderDynamicAPI* pShaderAPI, bool bBlend, bool bBlendFresnel, bool bNoPerVertexFresnel )
  241. {
  242. SHADOW_STATE
  243. {
  244. SetInitialShadowState( );
  245. // In edit mode, use nocull
  246. if ( UsingEditor( params ) )
  247. {
  248. s_pShaderShadow->EnableCulling( false );
  249. }
  250. pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
  251. pShaderShadow->EnableTexture( SHADER_SAMPLER3, true );
  252. if( bBlend )
  253. {
  254. if ( bBlendFresnel )
  255. {
  256. EnableAlphaBlending( SHADER_BLEND_DST_ALPHA, SHADER_BLEND_ONE_MINUS_DST_ALPHA );
  257. }
  258. else
  259. {
  260. EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA );
  261. }
  262. }
  263. pShaderShadow->VertexShaderVertexFormat(
  264. VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TANGENT_S |
  265. VERTEX_TANGENT_T, 1, 0, 0 );
  266. if( bNoPerVertexFresnel )
  267. {
  268. watercheap_vs11_Static_Index vshIndex;
  269. pShaderShadow->SetVertexShader( "WaterCheap_vs11", vshIndex.GetIndex() );
  270. }
  271. else
  272. {
  273. watercheappervertexfresnel_vs11_Static_Index vshIndex;
  274. pShaderShadow->SetVertexShader( "WaterCheapPerVertexFresnel_vs11", vshIndex.GetIndex() );
  275. }
  276. static const char *s_pPixelShaderName[] =
  277. {
  278. "WaterCheapOpaque_ps11",
  279. "WaterCheap_ps11",
  280. "WaterCheapNoFresnelOpaque_ps11",
  281. "WaterCheapNoFresnel_ps11",
  282. };
  283. int nPshIndex = 0;
  284. if ( bBlend ) nPshIndex |= 0x1;
  285. if ( bNoPerVertexFresnel ) nPshIndex |= 0x2;
  286. pShaderShadow->SetPixelShader( s_pPixelShaderName[nPshIndex] );
  287. FogToFogColor();
  288. }
  289. DYNAMIC_STATE
  290. {
  291. pShaderAPI->SetDefaultState();
  292. BindTexture( SHADER_SAMPLER0, NORMALMAP, BUMPFRAME );
  293. BindTexture( SHADER_SAMPLER3, ENVMAP, ENVMAPFRAME );
  294. if( bBlend && !bBlendFresnel )
  295. {
  296. SetCheapWaterFactors( params, pShaderAPI, VERTEX_SHADER_SHADER_SPECIFIC_CONST_2 );
  297. }
  298. else
  299. {
  300. float flCheapWaterConstants[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  301. pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, flCheapWaterConstants );
  302. }
  303. SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, BUMPTRANSFORM );
  304. SetPixelShaderConstant( 0, FOGCOLOR );
  305. SetPixelShaderConstant( 1, REFLECTTINT, REFLECTBLENDFACTOR );
  306. if( bNoPerVertexFresnel )
  307. {
  308. watercheap_vs11_Dynamic_Index vshIndex;
  309. vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
  310. pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() );
  311. }
  312. else
  313. {
  314. watercheappervertexfresnel_vs11_Dynamic_Index vshIndex;
  315. vshIndex.SetDOWATERFOG( pShaderAPI->GetSceneFogMode() == MATERIAL_FOG_LINEAR_BELOW_FOG_Z );
  316. pShaderAPI->SetVertexShaderIndex( vshIndex.GetIndex() );
  317. }
  318. }
  319. Draw();
  320. }
  321. SHADER_DRAW
  322. {
  323. // NOTE: Here's what all this means.
  324. // 1) ForceCheap means use env_cubemap only
  325. // 2) ForceExpensive means do real reflection instead of env_cubemap.
  326. // By default, it will do refraction and use env_cubemap for the reflection.
  327. // If dest alpha is available, it will also use dest alpha for a fresnel term.
  328. // otherwise there will be no fresnel term as it looks bizzare.
  329. bool bBlendReflection = false;
  330. bool bForceCheap = params[FORCECHEAP]->GetIntValue() != 0 || UsingEditor( params );
  331. bool bForceExpensive = !bForceCheap && (params[FORCEEXPENSIVE]->GetIntValue() != 0);
  332. bool bRefraction = params[REFRACTTEXTURE]->IsTexture();
  333. bool bReflection = bForceExpensive && params[REFLECTTEXTURE]->IsTexture();
  334. bool bReflectionUseFresnel = false;
  335. // Can't do fresnel when forcing cheap or if there's no refraction
  336. if( !bForceCheap )
  337. {
  338. if( bRefraction )
  339. {
  340. // NOTE: Expensive reflection does the fresnel correctly per-pixel
  341. if ( g_pHardwareConfig->HasDestAlphaBuffer() && !bReflection && !params[NOFRESNEL]->GetIntValue() )
  342. {
  343. DrawRefractionForFresnel( params, pShaderShadow, pShaderAPI );
  344. bReflectionUseFresnel = true;
  345. }
  346. else
  347. {
  348. DrawRefraction( params, pShaderShadow, pShaderAPI );
  349. }
  350. bBlendReflection = true;
  351. }
  352. if( bReflection )
  353. {
  354. DrawReflection( params, pShaderShadow, pShaderAPI, bBlendReflection );
  355. }
  356. }
  357. // Use $decal to see if we are a decal or not. . if we are, then don't bother
  358. // drawing the cheap version for now since we don't have access to env_cubemap
  359. if( !bReflection && params[ENVMAP]->IsTexture() && !IS_FLAG_SET( MATERIAL_VAR_DECAL ) )
  360. {
  361. bool bNoPerVertexFresnel = ( params[NOFRESNEL]->GetIntValue() || bReflectionUseFresnel || bForceCheap || !bRefraction );
  362. DrawCheapWater( params, pShaderShadow, pShaderAPI, bBlendReflection, bReflectionUseFresnel, bNoPerVertexFresnel );
  363. }
  364. }
  365. END_SHADER