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.

612 lines
26 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #ifndef IMATERIAL_H
  9. #define IMATERIAL_H
  10. #ifdef _WIN32
  11. #pragma once
  12. #endif
  13. #include "bitmap/imageformat.h"
  14. #include "materialsystem/imaterialsystem.h"
  15. //-----------------------------------------------------------------------------
  16. // forward declaraions
  17. //-----------------------------------------------------------------------------
  18. class IMaterialVar;
  19. class ITexture;
  20. class IMaterialProxy;
  21. class Vector;
  22. //-----------------------------------------------------------------------------
  23. // Flags for GetVertexFormat
  24. //-----------------------------------------------------------------------------
  25. #define VERTEX_POSITION 0x0001
  26. #define VERTEX_NORMAL 0x0002
  27. #define VERTEX_COLOR 0x0004
  28. #define VERTEX_SPECULAR 0x0008
  29. #define VERTEX_TANGENT_S 0x0010
  30. #define VERTEX_TANGENT_T 0x0020
  31. #define VERTEX_TANGENT_SPACE ( VERTEX_TANGENT_S | VERTEX_TANGENT_T )
  32. // Indicates we're using wrinkle
  33. #define VERTEX_WRINKLE 0x0040
  34. // Indicates we're using bone indices
  35. #define VERTEX_BONE_INDEX 0x0080
  36. // Indicates this is a vertex shader
  37. #define VERTEX_FORMAT_VERTEX_SHADER 0x0100
  38. // Indicates this format shouldn't be bloated to cache align it
  39. // (only used for VertexUsage)
  40. #define VERTEX_FORMAT_USE_EXACT_FORMAT 0x0200
  41. // Indicates that compressed vertex elements are to be used (see also VertexCompressionType_t)
  42. #define VERTEX_FORMAT_COMPRESSED 0x400
  43. // Update this if you add or remove bits...
  44. #define VERTEX_LAST_BIT 10
  45. #define VERTEX_BONE_WEIGHT_BIT (VERTEX_LAST_BIT + 1)
  46. #define USER_DATA_SIZE_BIT (VERTEX_LAST_BIT + 4)
  47. #define TEX_COORD_SIZE_BIT (VERTEX_LAST_BIT + 7)
  48. #define VERTEX_BONE_WEIGHT_MASK ( 0x7 << VERTEX_BONE_WEIGHT_BIT )
  49. #define USER_DATA_SIZE_MASK ( 0x7 << USER_DATA_SIZE_BIT )
  50. #define VERTEX_FORMAT_FIELD_MASK 0x0FF
  51. // If everything is off, it's an unknown vertex format
  52. #define VERTEX_FORMAT_UNKNOWN 0
  53. //-----------------------------------------------------------------------------
  54. // Macros for construction..
  55. //-----------------------------------------------------------------------------
  56. #define VERTEX_BONEWEIGHT( _n ) ((_n) << VERTEX_BONE_WEIGHT_BIT)
  57. #define VERTEX_USERDATA_SIZE( _n ) ((_n) << USER_DATA_SIZE_BIT)
  58. #define VERTEX_TEXCOORD_MASK( _coord ) (( 0x7ULL ) << ( TEX_COORD_SIZE_BIT + 3 * (_coord) ))
  59. inline VertexFormat_t VERTEX_TEXCOORD_SIZE( int nIndex, int nNumCoords )
  60. {
  61. uint64 n64=nNumCoords;
  62. uint64 nShift=TEX_COORD_SIZE_BIT + (3*nIndex);
  63. return n64 << nShift;
  64. }
  65. //-----------------------------------------------------------------------------
  66. // Gets at various vertex format info...
  67. //-----------------------------------------------------------------------------
  68. inline int VertexFlags( VertexFormat_t vertexFormat )
  69. {
  70. return static_cast<int> ( vertexFormat & ( (1 << (VERTEX_LAST_BIT+1)) - 1 ) );
  71. }
  72. inline int NumBoneWeights( VertexFormat_t vertexFormat )
  73. {
  74. return static_cast<int> ( (vertexFormat >> VERTEX_BONE_WEIGHT_BIT) & 0x7 );
  75. }
  76. inline int UserDataSize( VertexFormat_t vertexFormat )
  77. {
  78. return static_cast<int> ( (vertexFormat >> USER_DATA_SIZE_BIT) & 0x7 );
  79. }
  80. inline int TexCoordSize( int nTexCoordIndex, VertexFormat_t vertexFormat )
  81. {
  82. return static_cast<int> ( (vertexFormat >> (TEX_COORD_SIZE_BIT + 3*nTexCoordIndex) ) & 0x7 );
  83. }
  84. inline bool UsesVertexShader( VertexFormat_t vertexFormat )
  85. {
  86. return (vertexFormat & VERTEX_FORMAT_VERTEX_SHADER) != 0;
  87. }
  88. inline VertexCompressionType_t CompressionType( VertexFormat_t vertexFormat )
  89. {
  90. // This is trivial now, but we may add multiple flavours of compressed vertex later on
  91. if ( vertexFormat & VERTEX_FORMAT_COMPRESSED )
  92. return VERTEX_COMPRESSION_ON;
  93. else
  94. return VERTEX_COMPRESSION_NONE;
  95. }
  96. //-----------------------------------------------------------------------------
  97. // VertexElement_t (enumerates all usable vertex elements)
  98. //-----------------------------------------------------------------------------
  99. // FIXME: unify this with VertexFormat_t (i.e. construct the lower bits of VertexFormat_t with "1 << (VertexElement_t)element")
  100. enum VertexElement_t
  101. {
  102. VERTEX_ELEMENT_NONE = -1,
  103. // Deliberately explicitly numbered so it's a pain in the ass to change, so you read this:
  104. // #!#!#NOTE#!#!# update GetVertexElementSize, VertexElementToDeclType and
  105. // CVBAllocTracker (elementTable) when you update this!
  106. VERTEX_ELEMENT_POSITION = 0,
  107. VERTEX_ELEMENT_NORMAL = 1,
  108. VERTEX_ELEMENT_COLOR = 2,
  109. VERTEX_ELEMENT_SPECULAR = 3,
  110. VERTEX_ELEMENT_TANGENT_S = 4,
  111. VERTEX_ELEMENT_TANGENT_T = 5,
  112. VERTEX_ELEMENT_WRINKLE = 6,
  113. VERTEX_ELEMENT_BONEINDEX = 7,
  114. VERTEX_ELEMENT_BONEWEIGHTS1 = 8,
  115. VERTEX_ELEMENT_BONEWEIGHTS2 = 9,
  116. VERTEX_ELEMENT_BONEWEIGHTS3 = 10,
  117. VERTEX_ELEMENT_BONEWEIGHTS4 = 11,
  118. VERTEX_ELEMENT_USERDATA1 = 12,
  119. VERTEX_ELEMENT_USERDATA2 = 13,
  120. VERTEX_ELEMENT_USERDATA3 = 14,
  121. VERTEX_ELEMENT_USERDATA4 = 15,
  122. VERTEX_ELEMENT_TEXCOORD1D_0 = 16,
  123. VERTEX_ELEMENT_TEXCOORD1D_1 = 17,
  124. VERTEX_ELEMENT_TEXCOORD1D_2 = 18,
  125. VERTEX_ELEMENT_TEXCOORD1D_3 = 19,
  126. VERTEX_ELEMENT_TEXCOORD1D_4 = 20,
  127. VERTEX_ELEMENT_TEXCOORD1D_5 = 21,
  128. VERTEX_ELEMENT_TEXCOORD1D_6 = 22,
  129. VERTEX_ELEMENT_TEXCOORD1D_7 = 23,
  130. VERTEX_ELEMENT_TEXCOORD2D_0 = 24,
  131. VERTEX_ELEMENT_TEXCOORD2D_1 = 25,
  132. VERTEX_ELEMENT_TEXCOORD2D_2 = 26,
  133. VERTEX_ELEMENT_TEXCOORD2D_3 = 27,
  134. VERTEX_ELEMENT_TEXCOORD2D_4 = 28,
  135. VERTEX_ELEMENT_TEXCOORD2D_5 = 29,
  136. VERTEX_ELEMENT_TEXCOORD2D_6 = 30,
  137. VERTEX_ELEMENT_TEXCOORD2D_7 = 31,
  138. VERTEX_ELEMENT_TEXCOORD3D_0 = 32,
  139. VERTEX_ELEMENT_TEXCOORD3D_1 = 33,
  140. VERTEX_ELEMENT_TEXCOORD3D_2 = 34,
  141. VERTEX_ELEMENT_TEXCOORD3D_3 = 35,
  142. VERTEX_ELEMENT_TEXCOORD3D_4 = 36,
  143. VERTEX_ELEMENT_TEXCOORD3D_5 = 37,
  144. VERTEX_ELEMENT_TEXCOORD3D_6 = 38,
  145. VERTEX_ELEMENT_TEXCOORD3D_7 = 39,
  146. VERTEX_ELEMENT_TEXCOORD4D_0 = 40,
  147. VERTEX_ELEMENT_TEXCOORD4D_1 = 41,
  148. VERTEX_ELEMENT_TEXCOORD4D_2 = 42,
  149. VERTEX_ELEMENT_TEXCOORD4D_3 = 43,
  150. VERTEX_ELEMENT_TEXCOORD4D_4 = 44,
  151. VERTEX_ELEMENT_TEXCOORD4D_5 = 45,
  152. VERTEX_ELEMENT_TEXCOORD4D_6 = 46,
  153. VERTEX_ELEMENT_TEXCOORD4D_7 = 47,
  154. VERTEX_ELEMENT_NUMELEMENTS = 48
  155. };
  156. inline void Detect_VertexElement_t_Changes( VertexElement_t element ) // GREPs for VertexElement_t will hit this
  157. {
  158. // Make it harder for someone to change VertexElement_t without noticing that dependent code
  159. // (GetVertexElementSize, VertexElementToDeclType, CVBAllocTracker) needs updating
  160. Assert( VERTEX_ELEMENT_NUMELEMENTS == 48 );
  161. switch ( element )
  162. {
  163. case VERTEX_ELEMENT_POSITION: Assert( VERTEX_ELEMENT_POSITION == 0 ); break;
  164. case VERTEX_ELEMENT_NORMAL: Assert( VERTEX_ELEMENT_NORMAL == 1 ); break;
  165. case VERTEX_ELEMENT_COLOR: Assert( VERTEX_ELEMENT_COLOR == 2 ); break;
  166. case VERTEX_ELEMENT_SPECULAR: Assert( VERTEX_ELEMENT_SPECULAR == 3 ); break;
  167. case VERTEX_ELEMENT_TANGENT_S: Assert( VERTEX_ELEMENT_TANGENT_S == 4 ); break;
  168. case VERTEX_ELEMENT_TANGENT_T: Assert( VERTEX_ELEMENT_TANGENT_T == 5 ); break;
  169. case VERTEX_ELEMENT_WRINKLE: Assert( VERTEX_ELEMENT_WRINKLE == 6 ); break;
  170. case VERTEX_ELEMENT_BONEINDEX: Assert( VERTEX_ELEMENT_BONEINDEX == 7 ); break;
  171. case VERTEX_ELEMENT_BONEWEIGHTS1: Assert( VERTEX_ELEMENT_BONEWEIGHTS1 == 8 ); break;
  172. case VERTEX_ELEMENT_BONEWEIGHTS2: Assert( VERTEX_ELEMENT_BONEWEIGHTS2 == 9 ); break;
  173. case VERTEX_ELEMENT_BONEWEIGHTS3: Assert( VERTEX_ELEMENT_BONEWEIGHTS3 == 10 ); break;
  174. case VERTEX_ELEMENT_BONEWEIGHTS4: Assert( VERTEX_ELEMENT_BONEWEIGHTS4 == 11 ); break;
  175. case VERTEX_ELEMENT_USERDATA1: Assert( VERTEX_ELEMENT_USERDATA1 == 12 ); break;
  176. case VERTEX_ELEMENT_USERDATA2: Assert( VERTEX_ELEMENT_USERDATA2 == 13 ); break;
  177. case VERTEX_ELEMENT_USERDATA3: Assert( VERTEX_ELEMENT_USERDATA3 == 14 ); break;
  178. case VERTEX_ELEMENT_USERDATA4: Assert( VERTEX_ELEMENT_USERDATA4 == 15 ); break;
  179. case VERTEX_ELEMENT_TEXCOORD1D_0: Assert( VERTEX_ELEMENT_TEXCOORD1D_0 == 16 ); break;
  180. case VERTEX_ELEMENT_TEXCOORD1D_1: Assert( VERTEX_ELEMENT_TEXCOORD1D_1 == 17 ); break;
  181. case VERTEX_ELEMENT_TEXCOORD1D_2: Assert( VERTEX_ELEMENT_TEXCOORD1D_2 == 18 ); break;
  182. case VERTEX_ELEMENT_TEXCOORD1D_3: Assert( VERTEX_ELEMENT_TEXCOORD1D_3 == 19 ); break;
  183. case VERTEX_ELEMENT_TEXCOORD1D_4: Assert( VERTEX_ELEMENT_TEXCOORD1D_4 == 20 ); break;
  184. case VERTEX_ELEMENT_TEXCOORD1D_5: Assert( VERTEX_ELEMENT_TEXCOORD1D_5 == 21 ); break;
  185. case VERTEX_ELEMENT_TEXCOORD1D_6: Assert( VERTEX_ELEMENT_TEXCOORD1D_6 == 22 ); break;
  186. case VERTEX_ELEMENT_TEXCOORD1D_7: Assert( VERTEX_ELEMENT_TEXCOORD1D_7 == 23 ); break;
  187. case VERTEX_ELEMENT_TEXCOORD2D_0: Assert( VERTEX_ELEMENT_TEXCOORD2D_0 == 24 ); break;
  188. case VERTEX_ELEMENT_TEXCOORD2D_1: Assert( VERTEX_ELEMENT_TEXCOORD2D_1 == 25 ); break;
  189. case VERTEX_ELEMENT_TEXCOORD2D_2: Assert( VERTEX_ELEMENT_TEXCOORD2D_2 == 26 ); break;
  190. case VERTEX_ELEMENT_TEXCOORD2D_3: Assert( VERTEX_ELEMENT_TEXCOORD2D_3 == 27 ); break;
  191. case VERTEX_ELEMENT_TEXCOORD2D_4: Assert( VERTEX_ELEMENT_TEXCOORD2D_4 == 28 ); break;
  192. case VERTEX_ELEMENT_TEXCOORD2D_5: Assert( VERTEX_ELEMENT_TEXCOORD2D_5 == 29 ); break;
  193. case VERTEX_ELEMENT_TEXCOORD2D_6: Assert( VERTEX_ELEMENT_TEXCOORD2D_6 == 30 ); break;
  194. case VERTEX_ELEMENT_TEXCOORD2D_7: Assert( VERTEX_ELEMENT_TEXCOORD2D_7 == 31 ); break;
  195. case VERTEX_ELEMENT_TEXCOORD3D_0: Assert( VERTEX_ELEMENT_TEXCOORD3D_0 == 32 ); break;
  196. case VERTEX_ELEMENT_TEXCOORD3D_1: Assert( VERTEX_ELEMENT_TEXCOORD3D_1 == 33 ); break;
  197. case VERTEX_ELEMENT_TEXCOORD3D_2: Assert( VERTEX_ELEMENT_TEXCOORD3D_2 == 34 ); break;
  198. case VERTEX_ELEMENT_TEXCOORD3D_3: Assert( VERTEX_ELEMENT_TEXCOORD3D_3 == 35 ); break;
  199. case VERTEX_ELEMENT_TEXCOORD3D_4: Assert( VERTEX_ELEMENT_TEXCOORD3D_4 == 36 ); break;
  200. case VERTEX_ELEMENT_TEXCOORD3D_5: Assert( VERTEX_ELEMENT_TEXCOORD3D_5 == 37 ); break;
  201. case VERTEX_ELEMENT_TEXCOORD3D_6: Assert( VERTEX_ELEMENT_TEXCOORD3D_6 == 38 ); break;
  202. case VERTEX_ELEMENT_TEXCOORD3D_7: Assert( VERTEX_ELEMENT_TEXCOORD3D_7 == 39 ); break;
  203. case VERTEX_ELEMENT_TEXCOORD4D_0: Assert( VERTEX_ELEMENT_TEXCOORD4D_0 == 40 ); break;
  204. case VERTEX_ELEMENT_TEXCOORD4D_1: Assert( VERTEX_ELEMENT_TEXCOORD4D_1 == 41 ); break;
  205. case VERTEX_ELEMENT_TEXCOORD4D_2: Assert( VERTEX_ELEMENT_TEXCOORD4D_2 == 42 ); break;
  206. case VERTEX_ELEMENT_TEXCOORD4D_3: Assert( VERTEX_ELEMENT_TEXCOORD4D_3 == 43 ); break;
  207. case VERTEX_ELEMENT_TEXCOORD4D_4: Assert( VERTEX_ELEMENT_TEXCOORD4D_4 == 44 ); break;
  208. case VERTEX_ELEMENT_TEXCOORD4D_5: Assert( VERTEX_ELEMENT_TEXCOORD4D_5 == 45 ); break;
  209. case VERTEX_ELEMENT_TEXCOORD4D_6: Assert( VERTEX_ELEMENT_TEXCOORD4D_6 == 46 ); break;
  210. case VERTEX_ELEMENT_TEXCOORD4D_7: Assert( VERTEX_ELEMENT_TEXCOORD4D_7 == 47 ); break;
  211. default:
  212. Assert( 0 ); // Invalid input or VertexElement_t has definitely changed
  213. break;
  214. }
  215. }
  216. // We're testing 2 normal compression methods
  217. // One compressed normals+tangents into a SHORT2 each (8 bytes total)
  218. // The other compresses them together, into a single UBYTE4 (4 bytes total)
  219. // FIXME: pick one or the other, compare lighting quality in important cases
  220. #define COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 0
  221. #define COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 1
  222. //#define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2
  223. #define COMPRESSED_NORMALS_TYPE COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4
  224. inline int GetVertexElementSize( VertexElement_t element, VertexCompressionType_t compressionType )
  225. {
  226. Detect_VertexElement_t_Changes( element );
  227. if ( compressionType == VERTEX_COMPRESSION_ON )
  228. {
  229. // Compressed-vertex element sizes
  230. switch ( element )
  231. {
  232. #if ( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_SEPARATETANGENTS_SHORT2 )
  233. case VERTEX_ELEMENT_NORMAL:
  234. return ( 2 * sizeof( short ) );
  235. case VERTEX_ELEMENT_USERDATA4:
  236. return ( 2 * sizeof( short ) );
  237. #else //( COMPRESSED_NORMALS_TYPE == COMPRESSED_NORMALS_COMBINEDTANGENTS_UBYTE4 )
  238. // Normals and tangents (userdata4) are combined into a single UBYTE4 vertex element
  239. case VERTEX_ELEMENT_NORMAL:
  240. return ( 4 * sizeof( unsigned char ) );
  241. case VERTEX_ELEMENT_USERDATA4:
  242. return ( 0 );
  243. #endif
  244. // Compressed bone weights use a SHORT2 vertex element:
  245. case VERTEX_ELEMENT_BONEWEIGHTS1:
  246. case VERTEX_ELEMENT_BONEWEIGHTS2:
  247. return ( 2 * sizeof( short ) );
  248. default:
  249. break;
  250. }
  251. }
  252. // Uncompressed-vertex element sizes
  253. switch ( element )
  254. {
  255. case VERTEX_ELEMENT_POSITION: return ( 3 * sizeof( float ) );
  256. case VERTEX_ELEMENT_NORMAL: return ( 3 * sizeof( float ) );
  257. case VERTEX_ELEMENT_COLOR: return ( 4 * sizeof( unsigned char ) );
  258. case VERTEX_ELEMENT_SPECULAR: return ( 4 * sizeof( unsigned char ) );
  259. case VERTEX_ELEMENT_TANGENT_S: return ( 3 * sizeof( float ) );
  260. case VERTEX_ELEMENT_TANGENT_T: return ( 3 * sizeof( float ) );
  261. case VERTEX_ELEMENT_WRINKLE: return ( 1 * sizeof( float ) ); // Packed into Position.W
  262. case VERTEX_ELEMENT_BONEINDEX: return ( 4 * sizeof( unsigned char ) );
  263. case VERTEX_ELEMENT_BONEWEIGHTS1: return ( 1 * sizeof( float ) );
  264. case VERTEX_ELEMENT_BONEWEIGHTS2: return ( 2 * sizeof( float ) );
  265. case VERTEX_ELEMENT_BONEWEIGHTS3: return ( 3 * sizeof( float ) );
  266. case VERTEX_ELEMENT_BONEWEIGHTS4: return ( 4 * sizeof( float ) );
  267. case VERTEX_ELEMENT_USERDATA1: return ( 1 * sizeof( float ) );
  268. case VERTEX_ELEMENT_USERDATA2: return ( 2 * sizeof( float ) );
  269. case VERTEX_ELEMENT_USERDATA3: return ( 3 * sizeof( float ) );
  270. case VERTEX_ELEMENT_USERDATA4: return ( 4 * sizeof( float ) );
  271. case VERTEX_ELEMENT_TEXCOORD1D_0: return ( 1 * sizeof( float ) );
  272. case VERTEX_ELEMENT_TEXCOORD1D_1: return ( 1 * sizeof( float ) );
  273. case VERTEX_ELEMENT_TEXCOORD1D_2: return ( 1 * sizeof( float ) );
  274. case VERTEX_ELEMENT_TEXCOORD1D_3: return ( 1 * sizeof( float ) );
  275. case VERTEX_ELEMENT_TEXCOORD1D_4: return ( 1 * sizeof( float ) );
  276. case VERTEX_ELEMENT_TEXCOORD1D_5: return ( 1 * sizeof( float ) );
  277. case VERTEX_ELEMENT_TEXCOORD1D_6: return ( 1 * sizeof( float ) );
  278. case VERTEX_ELEMENT_TEXCOORD1D_7: return ( 1 * sizeof( float ) );
  279. case VERTEX_ELEMENT_TEXCOORD2D_0: return ( 2 * sizeof( float ) );
  280. case VERTEX_ELEMENT_TEXCOORD2D_1: return ( 2 * sizeof( float ) );
  281. case VERTEX_ELEMENT_TEXCOORD2D_2: return ( 2 * sizeof( float ) );
  282. case VERTEX_ELEMENT_TEXCOORD2D_3: return ( 2 * sizeof( float ) );
  283. case VERTEX_ELEMENT_TEXCOORD2D_4: return ( 2 * sizeof( float ) );
  284. case VERTEX_ELEMENT_TEXCOORD2D_5: return ( 2 * sizeof( float ) );
  285. case VERTEX_ELEMENT_TEXCOORD2D_6: return ( 2 * sizeof( float ) );
  286. case VERTEX_ELEMENT_TEXCOORD2D_7: return ( 2 * sizeof( float ) );
  287. case VERTEX_ELEMENT_TEXCOORD3D_0: return ( 3 * sizeof( float ) );
  288. case VERTEX_ELEMENT_TEXCOORD3D_1: return ( 3 * sizeof( float ) );
  289. case VERTEX_ELEMENT_TEXCOORD3D_2: return ( 3 * sizeof( float ) );
  290. case VERTEX_ELEMENT_TEXCOORD3D_3: return ( 3 * sizeof( float ) );
  291. case VERTEX_ELEMENT_TEXCOORD3D_4: return ( 3 * sizeof( float ) );
  292. case VERTEX_ELEMENT_TEXCOORD3D_5: return ( 3 * sizeof( float ) );
  293. case VERTEX_ELEMENT_TEXCOORD3D_6: return ( 3 * sizeof( float ) );
  294. case VERTEX_ELEMENT_TEXCOORD3D_7: return ( 3 * sizeof( float ) );
  295. case VERTEX_ELEMENT_TEXCOORD4D_0: return ( 4 * sizeof( float ) );
  296. case VERTEX_ELEMENT_TEXCOORD4D_1: return ( 4 * sizeof( float ) );
  297. case VERTEX_ELEMENT_TEXCOORD4D_2: return ( 4 * sizeof( float ) );
  298. case VERTEX_ELEMENT_TEXCOORD4D_3: return ( 4 * sizeof( float ) );
  299. case VERTEX_ELEMENT_TEXCOORD4D_4: return ( 4 * sizeof( float ) );
  300. case VERTEX_ELEMENT_TEXCOORD4D_5: return ( 4 * sizeof( float ) );
  301. case VERTEX_ELEMENT_TEXCOORD4D_6: return ( 4 * sizeof( float ) );
  302. case VERTEX_ELEMENT_TEXCOORD4D_7: return ( 4 * sizeof( float ) );
  303. default:
  304. Assert(0);
  305. return 0;
  306. };
  307. }
  308. //-----------------------------------------------------------------------------
  309. // Shader state flags can be read from the FLAGS materialvar
  310. // Also can be read or written to with the Set/GetMaterialVarFlags() call
  311. // Also make sure you add/remove a string associated with each flag below to CShaderSystem::ShaderStateString in ShaderSystem.cpp
  312. //-----------------------------------------------------------------------------
  313. enum MaterialVarFlags_t
  314. {
  315. MATERIAL_VAR_DEBUG = (1 << 0),
  316. MATERIAL_VAR_NO_DEBUG_OVERRIDE = (1 << 1),
  317. MATERIAL_VAR_NO_DRAW = (1 << 2),
  318. MATERIAL_VAR_USE_IN_FILLRATE_MODE = (1 << 3),
  319. MATERIAL_VAR_VERTEXCOLOR = (1 << 4),
  320. MATERIAL_VAR_VERTEXALPHA = (1 << 5),
  321. MATERIAL_VAR_SELFILLUM = (1 << 6),
  322. MATERIAL_VAR_ADDITIVE = (1 << 7),
  323. MATERIAL_VAR_ALPHATEST = (1 << 8),
  324. MATERIAL_VAR_MULTIPASS = (1 << 9),
  325. MATERIAL_VAR_ZNEARER = (1 << 10),
  326. MATERIAL_VAR_MODEL = (1 << 11),
  327. MATERIAL_VAR_FLAT = (1 << 12),
  328. MATERIAL_VAR_NOCULL = (1 << 13),
  329. MATERIAL_VAR_NOFOG = (1 << 14),
  330. MATERIAL_VAR_IGNOREZ = (1 << 15),
  331. MATERIAL_VAR_DECAL = (1 << 16),
  332. MATERIAL_VAR_ENVMAPSPHERE = (1 << 17),
  333. MATERIAL_VAR_NOALPHAMOD = (1 << 18),
  334. MATERIAL_VAR_ENVMAPCAMERASPACE = (1 << 19),
  335. MATERIAL_VAR_BASEALPHAENVMAPMASK = (1 << 20),
  336. MATERIAL_VAR_TRANSLUCENT = (1 << 21),
  337. MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK = (1 << 22),
  338. MATERIAL_VAR_NEEDS_SOFTWARE_SKINNING = (1 << 23),
  339. MATERIAL_VAR_OPAQUETEXTURE = (1 << 24),
  340. MATERIAL_VAR_ENVMAPMODE = (1 << 25),
  341. MATERIAL_VAR_SUPPRESS_DECALS = (1 << 26),
  342. MATERIAL_VAR_HALFLAMBERT = (1 << 27),
  343. MATERIAL_VAR_WIREFRAME = (1 << 28),
  344. MATERIAL_VAR_ALLOWALPHATOCOVERAGE = (1 << 29),
  345. MATERIAL_VAR_IGNORE_ALPHA_MODULATION = (1 << 30),
  346. // NOTE: Only add flags here that either should be read from
  347. // .vmts or can be set directly from client code. Other, internal
  348. // flags should to into the flag enum in imaterialinternal.h
  349. };
  350. //-----------------------------------------------------------------------------
  351. // Internal flags not accessible from outside the material system. Stored in Flags2
  352. //-----------------------------------------------------------------------------
  353. enum MaterialVarFlags2_t
  354. {
  355. // NOTE: These are for $flags2!!!!!
  356. // UNUSED = (1 << 0),
  357. MATERIAL_VAR2_LIGHTING_UNLIT = 0,
  358. MATERIAL_VAR2_LIGHTING_VERTEX_LIT = (1 << 1),
  359. MATERIAL_VAR2_LIGHTING_LIGHTMAP = (1 << 2),
  360. MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP = (1 << 3),
  361. MATERIAL_VAR2_LIGHTING_MASK =
  362. ( MATERIAL_VAR2_LIGHTING_VERTEX_LIT |
  363. MATERIAL_VAR2_LIGHTING_LIGHTMAP |
  364. MATERIAL_VAR2_LIGHTING_BUMPED_LIGHTMAP ),
  365. // FIXME: Should this be a part of the above lighting enums?
  366. MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL = (1 << 4),
  367. MATERIAL_VAR2_USES_ENV_CUBEMAP = (1 << 5),
  368. MATERIAL_VAR2_NEEDS_TANGENT_SPACES = (1 << 6),
  369. MATERIAL_VAR2_NEEDS_SOFTWARE_LIGHTING = (1 << 7),
  370. // GR - HDR path puts lightmap alpha in separate texture...
  371. MATERIAL_VAR2_BLEND_WITH_LIGHTMAP_ALPHA = (1 << 8),
  372. MATERIAL_VAR2_NEEDS_BAKED_LIGHTING_SNAPSHOTS = (1 << 9),
  373. MATERIAL_VAR2_USE_FLASHLIGHT = (1 << 10),
  374. MATERIAL_VAR2_USE_FIXED_FUNCTION_BAKED_LIGHTING = (1 << 11),
  375. MATERIAL_VAR2_NEEDS_FIXED_FUNCTION_FLASHLIGHT = (1 << 12),
  376. MATERIAL_VAR2_USE_EDITOR = (1 << 13),
  377. MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE = (1 << 14),
  378. MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE = (1 << 15),
  379. MATERIAL_VAR2_IS_SPRITECARD = (1 << 16),
  380. MATERIAL_VAR2_USES_VERTEXID = (1 << 17),
  381. MATERIAL_VAR2_SUPPORTS_HW_SKINNING = (1 << 18),
  382. MATERIAL_VAR2_SUPPORTS_FLASHLIGHT = (1 << 19),
  383. };
  384. //-----------------------------------------------------------------------------
  385. // Preview image return values
  386. //-----------------------------------------------------------------------------
  387. enum PreviewImageRetVal_t
  388. {
  389. MATERIAL_PREVIEW_IMAGE_BAD = 0,
  390. MATERIAL_PREVIEW_IMAGE_OK,
  391. MATERIAL_NO_PREVIEW_IMAGE,
  392. };
  393. //-----------------------------------------------------------------------------
  394. // material interface
  395. //-----------------------------------------------------------------------------
  396. abstract_class IMaterial
  397. {
  398. public:
  399. // Get the name of the material. This is a full path to
  400. // the vmt file starting from "hl2/materials" (or equivalent) without
  401. // a file extension.
  402. virtual const char * GetName() const = 0;
  403. virtual const char * GetTextureGroupName() const = 0;
  404. // Get the preferred size/bitDepth of a preview image of a material.
  405. // This is the sort of image that you would use for a thumbnail view
  406. // of a material, or in WorldCraft until it uses materials to render.
  407. // separate this for the tools maybe
  408. virtual PreviewImageRetVal_t GetPreviewImageProperties( int *width, int *height,
  409. ImageFormat *imageFormat, bool* isTranslucent ) const = 0;
  410. // Get a preview image at the specified width/height and bitDepth.
  411. // Will do resampling if necessary.(not yet!!! :) )
  412. // Will do color format conversion. (works now.)
  413. virtual PreviewImageRetVal_t GetPreviewImage( unsigned char *data,
  414. int width, int height,
  415. ImageFormat imageFormat ) const = 0;
  416. //
  417. virtual int GetMappingWidth( ) = 0;
  418. virtual int GetMappingHeight( ) = 0;
  419. virtual int GetNumAnimationFrames( ) = 0;
  420. // For material subrects (material pages). Offset(u,v) and scale(u,v) are normalized to texture.
  421. virtual bool InMaterialPage( void ) = 0;
  422. virtual void GetMaterialOffset( float *pOffset ) = 0;
  423. virtual void GetMaterialScale( float *pScale ) = 0;
  424. virtual IMaterial *GetMaterialPage( void ) = 0;
  425. // find a vmt variable.
  426. // This is how game code affects how a material is rendered.
  427. // The game code must know about the params that are used by
  428. // the shader for the material that it is trying to affect.
  429. virtual IMaterialVar * FindVar( const char *varName, bool *found, bool complain = true ) = 0;
  430. // The user never allocates or deallocates materials. Reference counting is
  431. // used instead. Garbage collection is done upon a call to
  432. // IMaterialSystem::UncacheUnusedMaterials.
  433. virtual void IncrementReferenceCount( void ) = 0;
  434. virtual void DecrementReferenceCount( void ) = 0;
  435. inline void AddRef() { IncrementReferenceCount(); }
  436. inline void Release() { DecrementReferenceCount(); }
  437. // Each material is assigned a number that groups it with like materials
  438. // for sorting in the application.
  439. virtual int GetEnumerationID( void ) const = 0;
  440. virtual void GetLowResColorSample( float s, float t, float *color ) const = 0;
  441. // This computes the state snapshots for this material
  442. virtual void RecomputeStateSnapshots() = 0;
  443. // Are we translucent?
  444. virtual bool IsTranslucent() = 0;
  445. // Are we alphatested?
  446. virtual bool IsAlphaTested() = 0;
  447. // Are we vertex lit?
  448. virtual bool IsVertexLit() = 0;
  449. // Gets the vertex format
  450. virtual VertexFormat_t GetVertexFormat() const = 0;
  451. // returns true if this material uses a material proxy
  452. virtual bool HasProxy( void ) const = 0;
  453. virtual bool UsesEnvCubemap( void ) = 0;
  454. virtual bool NeedsTangentSpace( void ) = 0;
  455. virtual bool NeedsPowerOfTwoFrameBufferTexture( bool bCheckSpecificToThisFrame = true ) = 0;
  456. virtual bool NeedsFullFrameBufferTexture( bool bCheckSpecificToThisFrame = true ) = 0;
  457. // returns true if the shader doesn't do skinning itself and requires
  458. // the data that is sent to it to be preskinned.
  459. virtual bool NeedsSoftwareSkinning( void ) = 0;
  460. // Apply constant color or alpha modulation
  461. virtual void AlphaModulate( float alpha ) = 0;
  462. virtual void ColorModulate( float r, float g, float b ) = 0;
  463. // Material Var flags...
  464. virtual void SetMaterialVarFlag( MaterialVarFlags_t flag, bool on ) = 0;
  465. virtual bool GetMaterialVarFlag( MaterialVarFlags_t flag ) const = 0;
  466. // Gets material reflectivity
  467. virtual void GetReflectivity( Vector& reflect ) = 0;
  468. // Gets material property flags
  469. virtual bool GetPropertyFlag( MaterialPropertyTypes_t type ) = 0;
  470. // Is the material visible from both sides?
  471. virtual bool IsTwoSided() = 0;
  472. // Sets the shader associated with the material
  473. virtual void SetShader( const char *pShaderName ) = 0;
  474. // Can't be const because the material might have to precache itself.
  475. virtual int GetNumPasses( void ) = 0;
  476. // Can't be const because the material might have to precache itself.
  477. virtual int GetTextureMemoryBytes( void ) = 0;
  478. // Meant to be used with materials created using CreateMaterial
  479. // It updates the materials to reflect the current values stored in the material vars
  480. virtual void Refresh() = 0;
  481. // GR - returns true is material uses lightmap alpha for blending
  482. virtual bool NeedsLightmapBlendAlpha( void ) = 0;
  483. // returns true if the shader doesn't do lighting itself and requires
  484. // the data that is sent to it to be prelighted
  485. virtual bool NeedsSoftwareLighting( void ) = 0;
  486. // Gets at the shader parameters
  487. virtual int ShaderParamCount() const = 0;
  488. virtual IMaterialVar **GetShaderParams( void ) = 0;
  489. // Returns true if this is the error material you get back from IMaterialSystem::FindMaterial if
  490. // the material can't be found.
  491. virtual bool IsErrorMaterial() const = 0;
  492. virtual void SetUseFixedFunctionBakedLighting( bool bEnable ) = 0;
  493. // Gets the current alpha modulation
  494. virtual float GetAlphaModulation() = 0;
  495. virtual void GetColorModulation( float *r, float *g, float *b ) = 0;
  496. // Gets the morph format
  497. virtual MorphFormat_t GetMorphFormat() const = 0;
  498. // fast find that stores the index of the found var in the string table in local cache
  499. virtual IMaterialVar * FindVarFast( char const *pVarName, unsigned int *pToken ) = 0;
  500. // Sets new VMT shader parameters for the material
  501. virtual void SetShaderAndParams( KeyValues *pKeyValues ) = 0;
  502. virtual const char * GetShaderName() const = 0;
  503. virtual void DeleteIfUnreferenced() = 0;
  504. virtual bool IsSpriteCard() = 0;
  505. virtual void CallBindProxy( void *proxyData ) = 0;
  506. virtual IMaterial *CheckProxyReplacement( void *proxyData ) = 0;
  507. virtual void RefreshPreservingMaterialVars() = 0;
  508. virtual bool WasReloadedFromWhitelist() = 0;
  509. virtual bool IsPrecached() const = 0;
  510. };
  511. inline bool IsErrorMaterial( IMaterial *pMat )
  512. {
  513. return !pMat || pMat->IsErrorMaterial();
  514. }
  515. #endif // IMATERIAL_H