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.

421 lines
13 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Header: $
  6. // $NoKeywords: $
  7. //=============================================================================//
  8. #include "shaderlib/cshader.h"
  9. // memdbgon must be the last include file in a .cpp file!!!
  10. #include "tier0/memdbgon.h"
  11. DEFINE_FALLBACK_SHADER( VertexLitGeneric, VertexLitGeneric_DX6 )
  12. BEGIN_SHADER( VertexLitGeneric_DX6,
  13. "Help for VertexLitGeneric_DX6" )
  14. BEGIN_SHADER_PARAMS
  15. SHADER_PARAM( DETAIL, SHADER_PARAM_TYPE_TEXTURE, "shadertest/detail", "detail texture" )
  16. SHADER_PARAM( DETAILSCALE, SHADER_PARAM_TYPE_FLOAT, "4", "scale of the detail texture" )
  17. SHADER_PARAM( SELFILLUMTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "Self-illumination tint" )
  18. SHADER_PARAM( ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_env", "envmap" )
  19. SHADER_PARAM( ENVMAPFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" )
  20. SHADER_PARAM( ENVMAPMASK, SHADER_PARAM_TYPE_TEXTURE, "shadertest/shadertest_envmask", "envmap mask" )
  21. SHADER_PARAM( ENVMAPMASKFRAME, SHADER_PARAM_TYPE_INTEGER, "", "" )
  22. SHADER_PARAM( ENVMAPMASKSCALE, SHADER_PARAM_TYPE_FLOAT, "1", "envmap mask scale" )
  23. SHADER_PARAM( ENVMAPTINT, SHADER_PARAM_TYPE_COLOR, "[1 1 1]", "envmap tint" )
  24. SHADER_PARAM( ENVMAPOPTIONAL, SHADER_PARAM_TYPE_BOOL, "0", "Make the envmap only apply to dx9 and higher hardware" )
  25. END_SHADER_PARAMS
  26. SHADER_INIT_PARAMS()
  27. {
  28. SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING );
  29. if( !params[ENVMAPMASKSCALE]->IsDefined() )
  30. params[ENVMAPMASKSCALE]->SetFloatValue( 1.0f );
  31. if( !params[ENVMAPTINT]->IsDefined() )
  32. params[ENVMAPTINT]->SetVecValue( 1.0f, 1.0f, 1.0f );
  33. if( !params[SELFILLUMTINT]->IsDefined() )
  34. params[SELFILLUMTINT]->SetVecValue( 1.0f, 1.0f, 1.0f );
  35. if( !params[DETAILSCALE]->IsDefined() )
  36. params[DETAILSCALE]->SetFloatValue( 4.0f );
  37. // No envmap uses mode 0, it's one less pass
  38. // Also, if multipass = 0, then go to mode 0 also
  39. if ( ( !params[ENVMAP]->IsDefined() ) ||
  40. ( !IS_FLAG_SET(MATERIAL_VAR_MULTIPASS) ) )
  41. {
  42. CLEAR_FLAGS( MATERIAL_VAR_ENVMAPMODE );
  43. }
  44. // Vertex color requires mode 1
  45. if ( IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR) )
  46. {
  47. SET_FLAGS( MATERIAL_VAR_ENVMAPMODE );
  48. }
  49. // No texture means no self-illum or env mask in base alpha
  50. if ( !params[BASETEXTURE]->IsDefined() )
  51. {
  52. CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM );
  53. CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK );
  54. }
  55. // If in decal mode, no debug override...
  56. if ( IS_FLAG_SET(MATERIAL_VAR_DECAL) )
  57. {
  58. SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE );
  59. }
  60. SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT );
  61. SET_FLAGS2( MATERIAL_VAR2_NEEDS_SOFTWARE_LIGHTING );
  62. // Get rid of the envmap if it's optional for this dx level.
  63. if( params[ENVMAPOPTIONAL]->IsDefined() && params[ENVMAPOPTIONAL]->GetIntValue() )
  64. {
  65. params[ENVMAP]->SetUndefined();
  66. }
  67. // If mat_specular 0, then get rid of envmap
  68. if( !g_pConfig->UseSpecular() && params[ENVMAP]->IsDefined() && params[BASETEXTURE]->IsDefined() )
  69. {
  70. params[ENVMAP]->SetUndefined();
  71. }
  72. }
  73. SHADER_FALLBACK
  74. {
  75. return 0;
  76. }
  77. SHADER_INIT
  78. {
  79. if (params[BASETEXTURE]->IsDefined())
  80. {
  81. LoadTexture( BASETEXTURE );
  82. if (!params[BASETEXTURE]->GetTextureValue()->IsTranslucent())
  83. {
  84. CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM );
  85. CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK );
  86. }
  87. }
  88. if (params[DETAIL]->IsDefined())
  89. {
  90. LoadTexture( DETAIL );
  91. }
  92. // Don't alpha test if the alpha channel is used for other purposes
  93. if (IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) || IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK) )
  94. CLEAR_FLAGS( MATERIAL_VAR_ALPHATEST );
  95. if (params[ENVMAP]->IsDefined())
  96. {
  97. if( !IS_FLAG_SET(MATERIAL_VAR_ENVMAPSPHERE) )
  98. LoadCubeMap( ENVMAP );
  99. else
  100. LoadTexture( ENVMAP );
  101. if( !g_pHardwareConfig->SupportsCubeMaps() )
  102. {
  103. SET_FLAGS( MATERIAL_VAR_ENVMAPSPHERE );
  104. }
  105. if (params[ENVMAPMASK]->IsDefined())
  106. LoadTexture( ENVMAPMASK );
  107. }
  108. }
  109. int GetDrawFlagsPass1(IMaterialVar** params)
  110. {
  111. int flags = SHADER_DRAW_POSITION | SHADER_DRAW_COLOR;
  112. if (params[BASETEXTURE]->IsTexture())
  113. flags |= SHADER_DRAW_TEXCOORD0;
  114. return flags;
  115. }
  116. void DrawVertexLightingOnly( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow )
  117. {
  118. SHADOW_STATE
  119. {
  120. pShaderShadow->EnableTexture( SHADER_SAMPLER0, false );
  121. SetModulationShadowState();
  122. SetDefaultBlendingShadowState( );
  123. pShaderShadow->DrawFlags( GetDrawFlagsPass1( params ) );
  124. DefaultFog();
  125. }
  126. DYNAMIC_STATE
  127. {
  128. SetModulationDynamicState();
  129. }
  130. Draw();
  131. }
  132. void MultiplyByVertexLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow )
  133. {
  134. SHADOW_STATE
  135. {
  136. // FIXME: How to deal with texture alpha??
  137. pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE0, false );
  138. pShaderShadow->EnableTexGen( SHADER_TEXTURE_STAGE1, false );
  139. pShaderShadow->EnableTexture( SHADER_SAMPLER0, false );
  140. pShaderShadow->EnableTexture( SHADER_SAMPLER1, false );
  141. // NOTE: We're not doing lightmapping here, but we want to use the
  142. // same blend mode as we used for lightmapping
  143. pShaderShadow->EnableBlending( true );
  144. SingleTextureLightmapBlendMode();
  145. pShaderShadow->EnableCustomPixelPipe( true );
  146. pShaderShadow->CustomTextureStages( 1 );
  147. // This here will perform color = vertex light * (cc alpha) + 1 * (1 - cc alpha)
  148. pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0,
  149. SHADER_TEXCHANNEL_COLOR, SHADER_TEXOP_BLEND_CONSTANTALPHA,
  150. SHADER_TEXARG_VERTEXCOLOR, SHADER_TEXARG_CONSTANTCOLOR );
  151. // Alpha isn't used, it doesn't matter what we set it to.
  152. pShaderShadow->CustomTextureOperation( SHADER_TEXTURE_STAGE0,
  153. SHADER_TEXCHANNEL_ALPHA, SHADER_TEXOP_SELECTARG1,
  154. SHADER_TEXARG_NONE, SHADER_TEXARG_NONE );
  155. pShaderShadow->DrawFlags( SHADER_DRAW_POSITION | SHADER_DRAW_COLOR );
  156. FogToOOOverbright();
  157. }
  158. DYNAMIC_STATE
  159. {
  160. // Put the alpha in the color channel to modulate the color down....
  161. float alpha = GetAlpha();
  162. pShaderAPI->Color4f( OO_OVERBRIGHT, OO_OVERBRIGHT, OO_OVERBRIGHT, alpha );
  163. }
  164. Draw();
  165. SHADOW_STATE
  166. {
  167. pShaderShadow->EnableCustomPixelPipe( false );
  168. }
  169. }
  170. //-----------------------------------------------------------------------------
  171. // Used by mode 1
  172. //-----------------------------------------------------------------------------
  173. void DrawBaseTimesVertexLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow )
  174. {
  175. // Base times vertex lighting, no vertex color
  176. SHADOW_STATE
  177. {
  178. // alpha test
  179. pShaderShadow->EnableAlphaTest( IS_FLAG_SET(MATERIAL_VAR_ALPHATEST) );
  180. // base
  181. pShaderShadow->EnableTexture( SHADER_SAMPLER0, true );
  182. pShaderShadow->OverbrightValue( SHADER_TEXTURE_STAGE0, OVERBRIGHT );
  183. // Independenly configure alpha and color
  184. // Color = Color mod * Vertex Light * Tex (x2)
  185. // Alpha = Constant Alpha * Tex Alpha (no tex alpha if self illum == 1)
  186. // Can't have color modulation here
  187. pShaderShadow->EnableConstantColor( IsColorModulating() );
  188. // Independenly configure alpha and color
  189. pShaderShadow->EnableAlphaPipe( true );
  190. pShaderShadow->EnableConstantAlpha( IsAlphaModulating() );
  191. pShaderShadow->EnableVertexAlpha( IS_FLAG_SET(MATERIAL_VAR_VERTEXALPHA) );
  192. if (!IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) && !IS_FLAG_SET(MATERIAL_VAR_BASEALPHAENVMAPMASK))
  193. pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE0, true );
  194. SetDefaultBlendingShadowState( BASETEXTURE, true );
  195. pShaderShadow->DrawFlags( GetDrawFlagsPass1( params ) );
  196. DefaultFog();
  197. }
  198. DYNAMIC_STATE
  199. {
  200. SetFixedFunctionTextureTransform( MATERIAL_TEXTURE0, BASETEXTURETRANSFORM );
  201. BindTexture( SHADER_SAMPLER0, BASETEXTURE, FRAME );
  202. SetModulationDynamicState();
  203. }
  204. Draw();
  205. SHADOW_STATE
  206. {
  207. pShaderShadow->EnableAlphaPipe( false );
  208. }
  209. }
  210. //-----------------------------------------------------------------------------
  211. // Envmap times vertex lighting, no vertex color
  212. //-----------------------------------------------------------------------------
  213. void DrawEnvmapTimesVertexLighting( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow )
  214. {
  215. SHADOW_STATE
  216. {
  217. int materialVarFlags = params[FLAGS]->GetIntValue();
  218. // alpha test
  219. pShaderShadow->EnableAlphaTest( false );
  220. int flags = SetShadowEnvMappingState( ENVMAPMASK ) | SHADER_DRAW_COLOR;
  221. bool hasEnvMapMask = params[ENVMAPMASK]->IsTexture();
  222. pShaderShadow->OverbrightValue( hasEnvMapMask ?
  223. SHADER_TEXTURE_STAGE1 : SHADER_TEXTURE_STAGE0, OVERBRIGHT );
  224. // Independenly configure alpha and color
  225. // Color = Env map * Vertex Light * Envmapmask (x2)
  226. // Alpha = Constant Alpha * Vertex light alpha * Env Map mask Alpha
  227. pShaderShadow->EnableConstantColor( IsColorModulating() );
  228. pShaderShadow->EnableAlphaPipe( true );
  229. pShaderShadow->EnableConstantAlpha( IsAlphaModulating() );
  230. pShaderShadow->EnableVertexAlpha( (materialVarFlags & MATERIAL_VAR_VERTEXALPHA) != 0 );
  231. if (hasEnvMapMask)
  232. pShaderShadow->EnableTextureAlpha( SHADER_TEXTURE_STAGE1, true );
  233. SetDefaultBlendingShadowState( BASETEXTURE, true );
  234. pShaderShadow->DrawFlags( flags );
  235. DefaultFog();
  236. }
  237. DYNAMIC_STATE
  238. {
  239. SetDynamicEnvMappingState( ENVMAP, ENVMAPMASK, BASETEXTURE,
  240. ENVMAPFRAME, ENVMAPMASKFRAME, FRAME,
  241. BASETEXTURETRANSFORM, ENVMAPMASKSCALE );
  242. }
  243. Draw();
  244. SHADOW_STATE
  245. {
  246. pShaderShadow->EnableCustomPixelPipe( false );
  247. pShaderShadow->EnableAlphaPipe( false );
  248. }
  249. }
  250. void DrawMode1( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow )
  251. {
  252. bool texDefined = params[BASETEXTURE]->IsTexture();
  253. bool envDefined = params[ENVMAP]->IsTexture();
  254. // bool maskDefined = params[ENVMAPMASK]->IsTexture();
  255. // Pass 1 : Base + env
  256. // FIXME: Could make it 1 pass for base + env, if it wasn't
  257. // for the envmap tint. So this is 3 passes for now....
  258. // If it's base + mask * env, gotta do that in 2 passes
  259. // Gotta do funky stuff to fade out self-illuminated stuff
  260. bool hasEnvMapTint = !IsWhite(ENVMAPTINT);
  261. // Special case, can do in one pass
  262. if (!hasEnvMapTint && !texDefined && !IS_FLAG_SET(MATERIAL_VAR_VERTEXCOLOR) &&
  263. !IsColorModulating() )
  264. {
  265. DrawEnvmapTimesVertexLighting( params, pShaderAPI, pShaderShadow );
  266. return;
  267. }
  268. if (texDefined)
  269. {
  270. FixedFunctionBaseTimesDetailPass(
  271. BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE );
  272. }
  273. else
  274. {
  275. FixedFunctionMaskedEnvmapPass(
  276. ENVMAP, ENVMAPMASK, BASETEXTURE,
  277. ENVMAPFRAME, ENVMAPMASKFRAME, FRAME,
  278. BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT );
  279. }
  280. // We can get here if multipass isn't set if we specify a vertex color
  281. if ( IS_FLAG_SET(MATERIAL_VAR_MULTIPASS) )
  282. {
  283. if ( texDefined && envDefined )
  284. {
  285. FixedFunctionAdditiveMaskedEnvmapPass(
  286. ENVMAP, ENVMAPMASK, BASETEXTURE,
  287. ENVMAPFRAME, ENVMAPMASKFRAME, FRAME,
  288. BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT );
  289. }
  290. }
  291. // Pass 2 : * vertex lighting
  292. MultiplyByVertexLighting( params, pShaderAPI, pShaderShadow );
  293. // FIXME: We could add it to the lightmap
  294. // Draw the selfillum pass (blows away envmap at self-illum points)
  295. if ( IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) )
  296. {
  297. FixedFunctionSelfIlluminationPass(
  298. SHADER_SAMPLER0, BASETEXTURE, FRAME, BASETEXTURETRANSFORM, SELFILLUMTINT );
  299. }
  300. }
  301. void DrawMode0( IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow )
  302. {
  303. // Pass 1 : Base * lightmap or just lightmap
  304. if ( params[BASETEXTURE]->IsTexture() )
  305. {
  306. DrawBaseTimesVertexLighting( params, pShaderAPI, pShaderShadow );
  307. // Detail map
  308. FixedFunctionMultiplyByDetailPass(
  309. BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE );
  310. // Draw the selfillum pass
  311. if ( IS_FLAG_SET(MATERIAL_VAR_SELFILLUM) )
  312. {
  313. FixedFunctionSelfIlluminationPass(
  314. SHADER_SAMPLER0, BASETEXTURE, FRAME, BASETEXTURETRANSFORM, SELFILLUMTINT );
  315. }
  316. }
  317. else
  318. {
  319. DrawVertexLightingOnly( params, pShaderAPI, pShaderShadow );
  320. // Detail map
  321. FixedFunctionMultiplyByDetailPass(
  322. BASETEXTURE, FRAME, BASETEXTURETRANSFORM, DETAIL, DETAILSCALE );
  323. }
  324. // Pass 2 : Masked environment map
  325. if ( params[ENVMAP]->IsTexture() &&
  326. (IS_FLAG_SET(MATERIAL_VAR_MULTIPASS)) )
  327. {
  328. FixedFunctionAdditiveMaskedEnvmapPass(
  329. ENVMAP, ENVMAPMASK, BASETEXTURE,
  330. ENVMAPFRAME, ENVMAPMASKFRAME, FRAME,
  331. BASETEXTURETRANSFORM, ENVMAPMASKSCALE, ENVMAPTINT );
  332. }
  333. }
  334. SHADER_DRAW
  335. {
  336. bool useMode1 = IS_FLAG_SET(MATERIAL_VAR_ENVMAPMODE);
  337. if (!useMode1)
  338. {
  339. // Base * Vertex Lighting + env
  340. DrawMode0( params, pShaderAPI, pShaderShadow );
  341. }
  342. else
  343. {
  344. // ( Base + env ) * Vertex Lighting
  345. DrawMode1( params, pShaderAPI, pShaderShadow );
  346. }
  347. }
  348. END_SHADER