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.

762 lines
24 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include <stdlib.h>
  7. #include "studiorender.h"
  8. #include "studiorendercontext.h"
  9. #include "materialsystem/imaterialsystem.h"
  10. #include "materialsystem/imaterialsystemhardwareconfig.h"
  11. #include "materialsystem/imaterial.h"
  12. #include "materialsystem/imaterialvar.h"
  13. #include "materialsystem/imesh.h"
  14. #include "optimize.h"
  15. #include "mathlib/vmatrix.h"
  16. #include "tier0/vprof.h"
  17. #include "tier1/strtools.h"
  18. #include "tier1/KeyValues.h"
  19. #include "tier0/memalloc.h"
  20. #include "convar.h"
  21. #include "materialsystem/itexture.h"
  22. #include "tier2/tier2.h"
  23. // memdbgon must be the last include file in a .cpp file!!!
  24. #include "tier0/memdbgon.h"
  25. //-----------------------------------------------------------------------------
  26. // Singleton instance
  27. //-----------------------------------------------------------------------------
  28. CStudioRender g_StudioRender;
  29. CStudioRender *g_pStudioRenderImp = &g_StudioRender;
  30. //-----------------------------------------------------------------------------
  31. // Activate to get stats
  32. //-----------------------------------------------------------------------------
  33. //#define REPORT_FLEX_STATS 1
  34. #ifdef REPORT_FLEX_STATS
  35. static int s_nModelsDrawn = 0;
  36. static int s_nActiveFlexCount = 0;
  37. static ConVar r_flexstats( "r_flexstats", "0", FCVAR_CHEAT );
  38. #endif
  39. //-----------------------------------------------------------------------------
  40. // Constructor
  41. //-----------------------------------------------------------------------------
  42. CStudioRender::CStudioRender()
  43. {
  44. m_pRC = NULL;
  45. m_pBoneToWorld = NULL;
  46. m_pFlexWeights = NULL;
  47. m_pFlexDelayedWeights = NULL;
  48. m_pStudioHdr = NULL;
  49. m_pStudioMeshes = NULL;
  50. m_pSubModel = NULL;
  51. m_pGlintTexture = NULL;
  52. m_GlintWidth = 0;
  53. m_GlintHeight = 0;
  54. // Cache-align our important matrices
  55. MemAlloc_PushAllocDbgInfo( __FILE__, __LINE__ );
  56. m_PoseToWorld = (matrix3x4_t*)MemAlloc_AllocAligned( MAXSTUDIOBONES * sizeof(matrix3x4_t), 32 );
  57. m_PoseToDecal = (matrix3x4_t*)MemAlloc_AllocAligned( MAXSTUDIOBONES * sizeof(matrix3x4_t), 32 );
  58. MemAlloc_PopAllocDbgInfo();
  59. m_nDecalId = 1;
  60. }
  61. CStudioRender::~CStudioRender()
  62. {
  63. MemAlloc_FreeAligned(m_PoseToWorld);
  64. MemAlloc_FreeAligned(m_PoseToDecal);
  65. }
  66. void CStudioRender::InitDebugMaterials( void )
  67. {
  68. m_pMaterialMRMWireframe =
  69. g_pMaterialSystem->FindMaterial( "//platform/materials/debug/debugmrmwireframe", TEXTURE_GROUP_OTHER, true );
  70. m_pMaterialMRMWireframe->IncrementReferenceCount();
  71. m_pMaterialMRMWireframeZBuffer =
  72. g_pMaterialSystem->FindMaterial( "//platform/materials/debug/debugmrmwireframezbuffer", TEXTURE_GROUP_OTHER, true );
  73. m_pMaterialMRMWireframeZBuffer->IncrementReferenceCount();
  74. m_pMaterialMRMNormals =
  75. g_pMaterialSystem->FindMaterial( "//platform/materials/debug/debugmrmnormals", TEXTURE_GROUP_OTHER, true );
  76. m_pMaterialMRMNormals->IncrementReferenceCount();
  77. m_pMaterialTangentFrame =
  78. g_pMaterialSystem->FindMaterial( "//platform/materials/debug/debugvertexcolor", TEXTURE_GROUP_OTHER, true );
  79. m_pMaterialTangentFrame->IncrementReferenceCount();
  80. m_pMaterialTranslucentModelHulls =
  81. g_pMaterialSystem->FindMaterial( "//platform/materials/debug/debugtranslucentmodelhulls", TEXTURE_GROUP_OTHER, true );
  82. m_pMaterialTranslucentModelHulls->IncrementReferenceCount();
  83. m_pMaterialSolidModelHulls =
  84. g_pMaterialSystem->FindMaterial( "//platform/materials/debug/debugsolidmodelhulls", TEXTURE_GROUP_OTHER, true );
  85. m_pMaterialSolidModelHulls->IncrementReferenceCount();
  86. m_pMaterialAdditiveVertexColorVertexAlpha =
  87. g_pMaterialSystem->FindMaterial( "//platform/materials/debug/additivevertexcolorvertexalpha", TEXTURE_GROUP_OTHER, true );
  88. m_pMaterialAdditiveVertexColorVertexAlpha->IncrementReferenceCount();
  89. m_pMaterialModelBones =
  90. g_pMaterialSystem->FindMaterial( "//platform/materials/debug/debugmodelbones", TEXTURE_GROUP_OTHER, true );
  91. m_pMaterialModelBones->IncrementReferenceCount();
  92. m_pMaterialModelEnvCubemap =
  93. g_pMaterialSystem->FindMaterial( "//platform/materials/debug/env_cubemap_model", TEXTURE_GROUP_OTHER, true );
  94. m_pMaterialModelEnvCubemap->IncrementReferenceCount();
  95. m_pMaterialWorldWireframe =
  96. g_pMaterialSystem->FindMaterial( "//platform/materials/debug/debugworldwireframe", TEXTURE_GROUP_OTHER, true );
  97. m_pMaterialWorldWireframe->IncrementReferenceCount();
  98. if( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 90 )
  99. {
  100. KeyValues *pVMTKeyValues = new KeyValues( "DepthWrite" );
  101. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  102. pVMTKeyValues->SetInt( "$alphatest", 0 );
  103. pVMTKeyValues->SetInt( "$nocull", 0 );
  104. m_pDepthWrite[0][0] = g_pMaterialSystem->FindProceduralMaterial( "__DepthWrite00", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  105. m_pDepthWrite[0][0]->IncrementReferenceCount();
  106. pVMTKeyValues = new KeyValues( "DepthWrite" );
  107. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  108. pVMTKeyValues->SetInt( "$alphatest", 0 );
  109. pVMTKeyValues->SetInt( "$nocull", 1 );
  110. m_pDepthWrite[0][1] = g_pMaterialSystem->FindProceduralMaterial( "__DepthWrite01", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  111. m_pDepthWrite[0][1]->IncrementReferenceCount();
  112. pVMTKeyValues = new KeyValues( "DepthWrite" );
  113. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  114. pVMTKeyValues->SetInt( "$alphatest", 1 );
  115. pVMTKeyValues->SetInt( "$nocull", 0 );
  116. m_pDepthWrite[1][0] = g_pMaterialSystem->FindProceduralMaterial( "__DepthWrite10", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  117. m_pDepthWrite[1][0]->IncrementReferenceCount();
  118. pVMTKeyValues = new KeyValues( "DepthWrite" );
  119. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  120. pVMTKeyValues->SetInt( "$alphatest", 1 );
  121. pVMTKeyValues->SetInt( "$nocull", 1 );
  122. m_pDepthWrite[1][1] = g_pMaterialSystem->FindProceduralMaterial( "__DepthWrite11", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  123. m_pDepthWrite[1][1]->IncrementReferenceCount();
  124. pVMTKeyValues = new KeyValues( "DepthWrite" );
  125. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  126. pVMTKeyValues->SetInt( "$alphatest", 0 );
  127. pVMTKeyValues->SetInt( "$nocull", 0 );
  128. pVMTKeyValues->SetInt( "$color_depth", 1 );
  129. m_pSSAODepthWrite[0][0] = g_pMaterialSystem->FindProceduralMaterial( "__ColorDepthWrite00", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  130. m_pSSAODepthWrite[0][0]->IncrementReferenceCount();
  131. pVMTKeyValues = new KeyValues( "DepthWrite" );
  132. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  133. pVMTKeyValues->SetInt( "$alphatest", 0 );
  134. pVMTKeyValues->SetInt( "$nocull", 1 );
  135. pVMTKeyValues->SetInt( "$color_depth", 1 );
  136. m_pSSAODepthWrite[0][1] = g_pMaterialSystem->FindProceduralMaterial( "__ColorDepthWrite01", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  137. m_pSSAODepthWrite[0][1]->IncrementReferenceCount();
  138. pVMTKeyValues = new KeyValues( "DepthWrite" );
  139. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  140. pVMTKeyValues->SetInt( "$alphatest", 1 );
  141. pVMTKeyValues->SetInt( "$nocull", 0 );
  142. pVMTKeyValues->SetInt( "$color_depth", 1 );
  143. m_pSSAODepthWrite[1][0] = g_pMaterialSystem->FindProceduralMaterial( "__ColorDepthWrite10", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  144. m_pSSAODepthWrite[1][0]->IncrementReferenceCount();
  145. pVMTKeyValues = new KeyValues( "DepthWrite" );
  146. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  147. pVMTKeyValues->SetInt( "$alphatest", 1 );
  148. pVMTKeyValues->SetInt( "$nocull", 1 );
  149. pVMTKeyValues->SetInt( "$color_depth", 1 );
  150. m_pSSAODepthWrite[1][1] = g_pMaterialSystem->FindProceduralMaterial( "__ColorDepthWrite11", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  151. m_pSSAODepthWrite[1][1]->IncrementReferenceCount();
  152. pVMTKeyValues = new KeyValues( "EyeGlint" );
  153. m_pGlintBuildMaterial = g_pMaterialSystem->CreateMaterial( "___glintbuildmaterial", pVMTKeyValues );
  154. }
  155. }
  156. void CStudioRender::ShutdownDebugMaterials( void )
  157. {
  158. #ifdef _WIN32
  159. if ( m_pMaterialMRMWireframe )
  160. {
  161. m_pMaterialMRMWireframe->DecrementReferenceCount();
  162. m_pMaterialMRMWireframe = NULL;
  163. }
  164. if ( m_pMaterialMRMWireframeZBuffer )
  165. {
  166. m_pMaterialMRMWireframeZBuffer->DecrementReferenceCount();
  167. m_pMaterialMRMWireframeZBuffer = NULL;
  168. }
  169. if ( m_pMaterialMRMNormals )
  170. {
  171. m_pMaterialMRMNormals->DecrementReferenceCount();
  172. m_pMaterialMRMNormals = NULL;
  173. }
  174. if ( m_pMaterialTangentFrame )
  175. {
  176. m_pMaterialTangentFrame->DecrementReferenceCount();
  177. m_pMaterialTangentFrame = NULL;
  178. }
  179. if ( m_pMaterialTranslucentModelHulls )
  180. {
  181. m_pMaterialTranslucentModelHulls->DecrementReferenceCount();
  182. m_pMaterialTranslucentModelHulls = NULL;
  183. }
  184. if ( m_pMaterialSolidModelHulls )
  185. {
  186. m_pMaterialSolidModelHulls->DecrementReferenceCount();
  187. m_pMaterialSolidModelHulls = NULL;
  188. }
  189. if ( m_pMaterialAdditiveVertexColorVertexAlpha )
  190. {
  191. m_pMaterialAdditiveVertexColorVertexAlpha->DecrementReferenceCount();
  192. m_pMaterialAdditiveVertexColorVertexAlpha = NULL;
  193. }
  194. if ( m_pMaterialModelBones )
  195. {
  196. m_pMaterialModelBones->DecrementReferenceCount();
  197. m_pMaterialModelBones = NULL;
  198. }
  199. if ( m_pMaterialModelEnvCubemap )
  200. {
  201. m_pMaterialModelEnvCubemap->DecrementReferenceCount();
  202. m_pMaterialModelEnvCubemap = NULL;
  203. }
  204. if ( m_pMaterialWorldWireframe )
  205. {
  206. m_pMaterialWorldWireframe->DecrementReferenceCount();
  207. m_pMaterialWorldWireframe = NULL;
  208. }
  209. // DepthWrite materials
  210. for ( int32 i = 0; i < 4; i++ )
  211. {
  212. if ( m_pDepthWrite[ ( i & 0x2 ) >> 1 ][ i & 0x1 ] )
  213. {
  214. m_pDepthWrite[ ( i & 0x2 ) >> 1 ][ i & 0x1 ]->DecrementReferenceCount();
  215. m_pDepthWrite[ ( i & 0x2 ) >> 1 ][ i & 0x1 ] = NULL;
  216. }
  217. if ( m_pSSAODepthWrite[ ( i & 0x2 ) >> 1 ][ i & 0x1 ] )
  218. {
  219. m_pSSAODepthWrite[ ( i & 0x2 ) >> 1 ][ i & 0x1 ]->DecrementReferenceCount();
  220. m_pSSAODepthWrite[ ( i & 0x2 ) >> 1 ][ i & 0x1 ] = NULL;
  221. }
  222. }
  223. if ( m_pGlintBuildMaterial )
  224. {
  225. m_pGlintBuildMaterial->DecrementReferenceCount();
  226. m_pGlintBuildMaterial = NULL;
  227. }
  228. #endif
  229. }
  230. static void ReleaseMaterialSystemObjects()
  231. {
  232. // g_StudioRender.UncacheGlint();
  233. }
  234. static void RestoreMaterialSystemObjects( int nChangeFlags )
  235. {
  236. // g_StudioRender.PrecacheGlint();
  237. }
  238. //-----------------------------------------------------------------------------
  239. // Init, shutdown
  240. //-----------------------------------------------------------------------------
  241. InitReturnVal_t CStudioRender::Init()
  242. {
  243. if ( g_pMaterialSystem && g_pMaterialSystemHardwareConfig )
  244. {
  245. g_pMaterialSystem->AddReleaseFunc( ReleaseMaterialSystemObjects );
  246. g_pMaterialSystem->AddRestoreFunc( RestoreMaterialSystemObjects );
  247. InitDebugMaterials();
  248. return INIT_OK;
  249. }
  250. return INIT_FAILED;
  251. }
  252. void CStudioRender::Shutdown( void )
  253. {
  254. UncacheGlint();
  255. ShutdownDebugMaterials();
  256. if ( g_pMaterialSystem )
  257. {
  258. g_pMaterialSystem->RemoveReleaseFunc( ReleaseMaterialSystemObjects );
  259. g_pMaterialSystem->RemoveRestoreFunc( RestoreMaterialSystemObjects );
  260. }
  261. }
  262. //-----------------------------------------------------------------------------
  263. // Sets the lighting render state
  264. //-----------------------------------------------------------------------------
  265. void CStudioRender::SetLightingRenderState()
  266. {
  267. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  268. // FIXME: What happens when we use the fixed function pipeline but vertex shaders
  269. // are active? For the time being this only works because everything that does
  270. // vertex lighting does, in fact, have a vertex shader which is used to render it.
  271. pRenderContext->SetAmbientLightCube( m_pRC->m_LightBoxColors );
  272. if ( m_pRC->m_Config.bSoftwareLighting || m_pRC->m_NumLocalLights == 0 )
  273. {
  274. pRenderContext->DisableAllLocalLights();
  275. }
  276. else
  277. {
  278. int nMaxLightCount = g_pMaterialSystemHardwareConfig->MaxNumLights();
  279. LightDesc_t desc;
  280. desc.m_Type = MATERIAL_LIGHT_DISABLE;
  281. int i;
  282. int nLightCount = min( m_pRC->m_NumLocalLights, nMaxLightCount );
  283. for( i = 0; i < nLightCount; ++i )
  284. {
  285. pRenderContext->SetLight( i, m_pRC->m_LocalLights[i] );
  286. }
  287. for( ; i < nMaxLightCount; ++i )
  288. {
  289. pRenderContext->SetLight( i, desc );
  290. }
  291. }
  292. }
  293. //-----------------------------------------------------------------------------
  294. // Shadow state (affects the models as they are rendered)
  295. //-----------------------------------------------------------------------------
  296. void CStudioRender::AddShadow( IMaterial* pMaterial, void* pProxyData, FlashlightState_t *pFlashlightState, VMatrix *pWorldToTexture, ITexture *pFlashlightDepthTexture )
  297. {
  298. int i = m_ShadowState.AddToTail();
  299. ShadowState_t& state = m_ShadowState[i];
  300. state.m_pMaterial = pMaterial;
  301. state.m_pProxyData = pProxyData;
  302. state.m_pFlashlightState = pFlashlightState;
  303. state.m_pWorldToTexture = pWorldToTexture;
  304. state.m_pFlashlightDepthTexture = pFlashlightDepthTexture;
  305. }
  306. void CStudioRender::ClearAllShadows()
  307. {
  308. m_ShadowState.RemoveAll();
  309. }
  310. void CStudioRender::GetFlexStats( )
  311. {
  312. #ifdef REPORT_FLEX_STATS
  313. static bool s_bLastFlexStats = false;
  314. bool bDoStats = r_flexstats.GetInt() != 0;
  315. if ( bDoStats )
  316. {
  317. if ( !s_bLastFlexStats )
  318. {
  319. s_nModelsDrawn = 0;
  320. s_nActiveFlexCount = 0;
  321. }
  322. // Count number of active weights
  323. int nActiveFlexCount = 0;
  324. for ( int i = 0; i < MAXSTUDIOFLEXDESC; ++i )
  325. {
  326. if ( fabs( m_FlexWeights[i] ) >= 0.001f || fabs( m_FlexDelayedWeights[i] ) >= 0.001f )
  327. {
  328. ++nActiveFlexCount;
  329. }
  330. }
  331. ++s_nModelsDrawn;
  332. s_nActiveFlexCount += nActiveFlexCount;
  333. }
  334. else
  335. {
  336. if ( s_bLastFlexStats )
  337. {
  338. if ( s_nModelsDrawn )
  339. {
  340. Msg( "Average number of flexes/model: %d\n", s_nActiveFlexCount / s_nModelsDrawn );
  341. }
  342. else
  343. {
  344. Msg( "No models rendered to take stats of\n" );
  345. }
  346. s_nModelsDrawn = 0;
  347. s_nActiveFlexCount = 0;
  348. }
  349. }
  350. s_bLastFlexStats = bDoStats;
  351. #endif
  352. }
  353. //-----------------------------------------------------------------------------
  354. // Main model rendering entry point
  355. //-----------------------------------------------------------------------------
  356. void CStudioRender::DrawModel( const DrawModelInfo_t& info, const StudioRenderContext_t &rc,
  357. matrix3x4_t *pBoneToWorld, const FlexWeights_t &flex, int flags )
  358. {
  359. if ( ( flags & STUDIORENDER_GENERATE_STATS ) != 0 )
  360. {
  361. ModelStats( info, rc, pBoneToWorld, flex, flags );
  362. return;
  363. }
  364. VPROF( "CStudioRender::DrawModel");
  365. m_pRC = const_cast< StudioRenderContext_t* >( &rc );
  366. m_pFlexWeights = flex.m_pFlexWeights;
  367. m_pFlexDelayedWeights = flex.m_pFlexDelayedWeights;
  368. m_pBoneToWorld = pBoneToWorld;
  369. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  370. // Disable flex if we're told to...
  371. bool flexConfig = m_pRC->m_Config.bFlex;
  372. if (flags & STUDIORENDER_DRAW_NO_FLEXES)
  373. {
  374. m_pRC->m_Config.bFlex = false;
  375. }
  376. // Enable wireframe if we're told to...
  377. bool bWireframe = m_pRC->m_Config.bWireframe;
  378. if ( flags & STUDIORENDER_DRAW_WIREFRAME )
  379. {
  380. m_pRC->m_Config.bWireframe = true;
  381. }
  382. int boneMask = BONE_USED_BY_VERTEX_AT_LOD( info.m_Lod );
  383. // Preserve the matrices if we're skinning
  384. pRenderContext->MatrixMode( MATERIAL_MODEL );
  385. pRenderContext->PushMatrix();
  386. pRenderContext->LoadIdentity();
  387. m_VertexCache.StartModel();
  388. m_pStudioHdr = info.m_pStudioHdr;
  389. if ( !info.m_pHardwareData->m_pLODs )
  390. {
  391. // If we are missing LODs then print the model name before returning
  392. // so we can perhaps correct the underlying problem.
  393. Msg( "Missing LODs for %s, lod index is %d.\n", m_pStudioHdr->pszName(), info.m_Lod );
  394. return;
  395. }
  396. m_pStudioMeshes = info.m_pHardwareData->m_pLODs[info.m_Lod].m_pMeshData;
  397. // Bone to world must be set before calling drawmodel; it uses that here
  398. ComputePoseToWorld( m_PoseToWorld, m_pStudioHdr, boneMask, m_pRC->m_ViewOrigin, pBoneToWorld );
  399. R_StudioRenderModel( pRenderContext, info.m_Skin, info.m_Body, info.m_HitboxSet, info.m_pClientEntity,
  400. info.m_pHardwareData->m_pLODs[info.m_Lod].ppMaterials,
  401. info.m_pHardwareData->m_pLODs[info.m_Lod].pMaterialFlags, flags, boneMask, info.m_Lod, info.m_pColorMeshes);
  402. // Draw all the decals on this model
  403. // If the model is not in memory, this code may not function correctly
  404. // This code assumes the model has been rendered!
  405. // So skip if the model hasn't been rendered
  406. // Also, skip if we're rendering to the shadow depth map
  407. if ( ( m_pStudioMeshes != 0 ) && !( flags & ( STUDIORENDER_SHADOWDEPTHTEXTURE | STUDIORENDER_SSAODEPTHTEXTURE )) )
  408. {
  409. if ((flags & STUDIORENDER_DRAW_GROUP_MASK) != STUDIORENDER_DRAW_TRANSLUCENT_ONLY)
  410. {
  411. DrawDecal( info, info.m_Lod, info.m_Body );
  412. }
  413. // Draw shadows
  414. if ( !( flags & STUDIORENDER_DRAW_NO_SHADOWS ) )
  415. {
  416. DrawShadows( info, flags, boneMask );
  417. }
  418. if( (flags & STUDIORENDER_DRAW_GROUP_MASK) != STUDIORENDER_DRAW_TRANSLUCENT_ONLY &&
  419. !( flags & STUDIORENDER_DRAW_NO_SHADOWS ) )
  420. {
  421. DrawFlashlightDecals( info, info.m_Lod );
  422. }
  423. }
  424. // Restore the matrices if we're skinning
  425. pRenderContext->MatrixMode( MATERIAL_MODEL );
  426. pRenderContext->PopMatrix();
  427. // Restore the configs
  428. m_pRC->m_Config.bFlex = flexConfig;
  429. m_pRC->m_Config.bWireframe = bWireframe;
  430. #ifdef REPORT_FLEX_STATS
  431. GetFlexStats();
  432. #endif
  433. pRenderContext->SetNumBoneWeights( 0 );
  434. m_pRC = NULL;
  435. m_pBoneToWorld = NULL;
  436. m_pFlexWeights = NULL;
  437. m_pFlexDelayedWeights = NULL;
  438. }
  439. void CStudioRender::DrawModelStaticProp( const DrawModelInfo_t& info,
  440. const StudioRenderContext_t &rc, const matrix3x4_t& rootToWorld, int flags )
  441. {
  442. VPROF( "CStudioRender::DrawModelStaticProp");
  443. m_pRC = const_cast<StudioRenderContext_t*>( &rc );
  444. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  445. memcpy( &m_StaticPropRootToWorld, &rootToWorld, sizeof(matrix3x4_t) );
  446. memcpy( &m_PoseToWorld[0], &rootToWorld, sizeof(matrix3x4_t) );
  447. m_pBoneToWorld = &m_StaticPropRootToWorld;
  448. bool flexConfig = m_pRC->m_Config.bFlex;
  449. m_pRC->m_Config.bFlex = false;
  450. bool bWireframe = m_pRC->m_Config.bWireframe;
  451. if ( flags & STUDIORENDER_DRAW_WIREFRAME )
  452. {
  453. m_pRC->m_Config.bWireframe = true;
  454. }
  455. int lod = info.m_Lod;
  456. m_pStudioHdr = info.m_pStudioHdr;
  457. m_pStudioMeshes = info.m_pHardwareData->m_pLODs[lod].m_pMeshData;
  458. if ( ( flags & STUDIORENDER_GENERATE_STATS ) != 0 )
  459. {
  460. FlexWeights_t flex;
  461. ModelStats( info, rc, m_pBoneToWorld, flex, flags | STUDIORENDER_DRAW_NO_FLEXES );
  462. return;
  463. }
  464. R_StudioRenderModel( pRenderContext, info.m_Skin, info.m_Body, info.m_HitboxSet, info.m_pClientEntity,
  465. info.m_pHardwareData->m_pLODs[lod].ppMaterials,
  466. info.m_pHardwareData->m_pLODs[lod].pMaterialFlags, flags, BONE_USED_BY_ANYTHING, lod, info.m_pColorMeshes);
  467. // If we're not shadow depth mapping
  468. if ( ( flags & ( STUDIORENDER_SHADOWDEPTHTEXTURE | STUDIORENDER_SSAODEPTHTEXTURE ) ) == 0 )
  469. {
  470. // FIXME: Should this occur in a separate call?
  471. // Draw all the decals on this model
  472. if ((flags & STUDIORENDER_DRAW_GROUP_MASK) != STUDIORENDER_DRAW_TRANSLUCENT_ONLY)
  473. {
  474. DrawDecal( info, lod, info.m_Body );
  475. }
  476. // Draw shadows
  477. if ( !( flags & STUDIORENDER_DRAW_NO_SHADOWS ) )
  478. {
  479. DrawShadows( info, flags, BONE_USED_BY_ANYTHING );
  480. }
  481. if( (flags & STUDIORENDER_DRAW_GROUP_MASK) != STUDIORENDER_DRAW_TRANSLUCENT_ONLY &&
  482. !( flags & STUDIORENDER_DRAW_NO_SHADOWS ) )
  483. {
  484. DrawFlashlightDecals( info, lod );
  485. }
  486. }
  487. // Restore the configs
  488. m_pRC->m_Config.bFlex = flexConfig;
  489. m_pRC->m_Config.bWireframe = bWireframe;
  490. pRenderContext->SetNumBoneWeights( 0 );
  491. m_pBoneToWorld = NULL;
  492. m_pRC = NULL;
  493. }
  494. // UNDONE: Currently no flex supported, no per instance cubemap or other lighting state supported, no eyeballs supported
  495. // NOTE: This is a fast path for simple models with skeletons but not many other features
  496. void CStudioRender::DrawModelArray( const DrawModelInfo_t &drawInfo, const StudioRenderContext_t &rc, int arrayCount, model_array_instance_t *pInstanceData, int instanceStride, int flags )
  497. {
  498. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s %d", __FUNCTION__, arrayCount );
  499. #ifndef SWDS // no drawing on dedicated server
  500. #if 0
  501. FlexWeights_t flex;
  502. memset(&flex, 0, sizeof(flex));
  503. for ( int i = 0; i < arrayCount; i++ )
  504. {
  505. DrawModel( drawInfo, rc, &pInstanceData[i].modelToWorld, flex, flags );
  506. }
  507. return;
  508. #endif
  509. m_pRC = const_cast< StudioRenderContext_t* >( &rc );
  510. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  511. // Preserve the matrices if we're skinning
  512. pRenderContext->MatrixMode( MATERIAL_MODEL );
  513. pRenderContext->PushMatrix();
  514. pRenderContext->LoadIdentity();
  515. pRenderContext->SetNumBoneWeights( 0 );
  516. // get the studio mesh data for this lod
  517. studiomeshdata_t *pMeshDataBase = drawInfo.m_pHardwareData->m_pLODs[drawInfo.m_Lod].m_pMeshData;
  518. IMaterial **ppMaterials = drawInfo.m_pHardwareData->m_pLODs[drawInfo.m_Lod].ppMaterials;
  519. int *pMaterialFlags = drawInfo.m_pHardwareData->m_pLODs[drawInfo.m_Lod].pMaterialFlags;
  520. studiohdr_t *pStudioHdr = drawInfo.m_pStudioHdr;
  521. m_bDrawTranslucentSubModels = false;
  522. int skin = drawInfo.m_Skin;
  523. short *pskinref = pStudioHdr->pSkinref( 0 );
  524. if ( skin > 0 && skin < pStudioHdr->numskinfamilies )
  525. {
  526. pskinref += ( skin * pStudioHdr->numskinref );
  527. }
  528. for ( int body = 0; body < pStudioHdr->numbodyparts; ++body )
  529. {
  530. mstudiobodyparts_t *pbodypart = pStudioHdr->pBodypart( body );
  531. int index = drawInfo.m_Body / pbodypart->base;
  532. index = index % pbodypart->nummodels;
  533. mstudiomodel_t *pSubmodel = pbodypart->pModel( index );
  534. for ( int meshIndex = 0; meshIndex < pSubmodel->nummeshes; ++meshIndex )
  535. {
  536. mstudiomesh_t *pmesh = pSubmodel->pMesh(meshIndex);
  537. studiomeshdata_t *pMeshData = &pMeshDataBase[pmesh->meshid];
  538. Assert( pMeshData );
  539. if ( !pMeshData->m_NumGroup )
  540. continue;
  541. if ( !pMaterialFlags )
  542. continue;
  543. StudioModelLighting_t lighting = LIGHTING_HARDWARE;
  544. int materialFlags = pMaterialFlags[pskinref[pmesh->material]];
  545. IMaterial* pMaterial = R_StudioSetupSkinAndLighting( pRenderContext, pskinref[ pmesh->material ], ppMaterials, materialFlags, drawInfo.m_pClientEntity, NULL, lighting );
  546. if ( !pMaterial )
  547. continue;
  548. // eyeball! can't do those in array mode yet
  549. Assert( pmesh->materialtype != 1 );
  550. //R_StudioDrawMesh( pRenderContext, pmesh, pMeshData, lighting, pMaterial, NULL, drawInfo.m_Lod );
  551. // Draw all the various mesh groups...
  552. for ( int meshGroupIndex = 0; meshGroupIndex < pMeshData->m_NumGroup; ++meshGroupIndex )
  553. {
  554. studiomeshgroup_t* pGroup = &pMeshData->m_pMeshGroup[meshGroupIndex];
  555. // Older models are merely flexed while new ones are also delta flexed
  556. Assert(!(pGroup->m_Flags & MESHGROUP_IS_FLEXED));
  557. Assert(!(pGroup->m_Flags & MESHGROUP_IS_DELTA_FLEXED));
  558. IMesh *pMesh = pGroup->m_pMesh;
  559. // Needed when we switch back and forth between hardware + software lighting
  560. if ( IsPC() && pGroup->m_MeshNeedsRestore )
  561. {
  562. VertexCompressionType_t compressionType = CompressionType( pMesh->GetVertexFormat() );
  563. switch ( compressionType )
  564. {
  565. case VERTEX_COMPRESSION_ON:
  566. R_StudioRestoreMesh<VERTEX_COMPRESSION_ON>( pmesh, pGroup );
  567. case VERTEX_COMPRESSION_NONE:
  568. default:
  569. R_StudioRestoreMesh<VERTEX_COMPRESSION_NONE>( pmesh, pGroup );
  570. break;
  571. }
  572. pGroup->m_MeshNeedsRestore = false;
  573. }
  574. pMesh->SetColorMesh( NULL, 0 );
  575. MaterialPrimitiveType_t stripType = MATERIAL_TRIANGLES;
  576. pMesh->SetPrimitiveType(stripType);
  577. if ( pStudioHdr->numbones > 1 )
  578. {
  579. byte *pData = (byte *)pInstanceData;
  580. for ( int i = 0;i < arrayCount; i++, pData += instanceStride )
  581. {
  582. matrix3x4_t *pBones = &( ((model_array_instance_t *)pData)->modelToWorld );
  583. pRenderContext->LoadMatrix( pBones[0] );
  584. for (int j = 0; j < pGroup->m_NumStrips; ++j)
  585. {
  586. OptimizedModel::StripHeader_t* pStrip = &pGroup->m_pStripData[j];
  587. // Reset bone state if we're hardware skinning
  588. pRenderContext->SetNumBoneWeights( pStrip->numBones );
  589. for (int k = 0; k < pStrip->numBoneStateChanges; ++k)
  590. {
  591. OptimizedModel::BoneStateChangeHeader_t* pStateChange = pStrip->pBoneStateChange(k);
  592. if ( pStateChange->newBoneID < 0 )
  593. break;
  594. pRenderContext->LoadBoneMatrix( pStateChange->hardwareID, pBones[pStateChange->newBoneID] );
  595. }
  596. MaterialPrimitiveType_t localStripType = pStrip->flags & OptimizedModel::STRIP_IS_TRISTRIP ? MATERIAL_TRIANGLE_STRIP : MATERIAL_TRIANGLES;
  597. if ( localStripType != stripType )
  598. {
  599. pMesh->SetPrimitiveType( localStripType );
  600. stripType = localStripType;
  601. }
  602. pMesh->Draw( pStrip->indexOffset, pStrip->numIndices );
  603. }
  604. }
  605. pRenderContext->SetNumBoneWeights( 0 );
  606. }
  607. else
  608. {
  609. byte *pData = (byte *)pInstanceData;
  610. for ( int i = 0;i < arrayCount; i++, pData += instanceStride )
  611. {
  612. matrix3x4_t *pBones = &( ((model_array_instance_t *)pData)->modelToWorld );
  613. pRenderContext->LoadMatrix( pBones[0] );
  614. for (int j = 0; j < pGroup->m_NumStrips; ++j)
  615. {
  616. OptimizedModel::StripHeader_t* pStrip = &pGroup->m_pStripData[j];
  617. MaterialPrimitiveType_t localStripType = pStrip->flags & OptimizedModel::STRIP_IS_TRISTRIP ? MATERIAL_TRIANGLE_STRIP : MATERIAL_TRIANGLES;
  618. if ( localStripType != stripType )
  619. {
  620. pMesh->SetPrimitiveType( localStripType );
  621. stripType = localStripType;
  622. }
  623. pMesh->Draw( pStrip->indexOffset, pStrip->numIndices );
  624. }
  625. }
  626. }
  627. }
  628. }
  629. }
  630. pRenderContext->MatrixMode( MATERIAL_MODEL );
  631. pRenderContext->PopMatrix();
  632. #endif
  633. }