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.

541 lines
19 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $Date: $
  7. // $NoKeywords: $
  8. //===========================================================================//
  9. #include "r_studiolight.h"
  10. #include "studiorender.h"
  11. #include "studiorendercontext.h"
  12. #include "studio.h"
  13. #include "materialsystem/imaterialsystemhardwareconfig.h"
  14. #include "mathlib/vector.h"
  15. #include "mathlib/mathlib.h"
  16. #include <float.h>
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. void R_WorldLightDelta( const LightDesc_t *wl, const Vector& org, Vector& delta );
  20. //-----------------------------------------------------------------------------
  21. // Copies lighting state
  22. //-----------------------------------------------------------------------------
  23. int CopyLocalLightingState( int nMaxLights, LightDesc_t *pDest, int nLightCount, const LightDesc_t *pSrc )
  24. {
  25. // ensure we write within array bounds
  26. if ( nLightCount > nMaxLights )
  27. {
  28. nLightCount = nMaxLights;
  29. }
  30. for( int i = 0; i < nLightCount; i++ )
  31. {
  32. LightDesc_t *pLight = &pDest[i];
  33. memcpy( pLight, &pSrc[i], sizeof( LightDesc_t ) );
  34. pLight->m_Flags = 0;
  35. if( pLight->m_Attenuation0 != 0.0f )
  36. {
  37. pLight->m_Flags |= LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0;
  38. }
  39. if( pLight->m_Attenuation1 != 0.0f )
  40. {
  41. pLight->m_Flags |= LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1;
  42. }
  43. if( pLight->m_Attenuation2 != 0.0f )
  44. {
  45. pLight->m_Flags |= LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2;
  46. }
  47. }
  48. return nLightCount;
  49. }
  50. //-----------------------------------------------------------------------------
  51. // Computes the ambient term
  52. //-----------------------------------------------------------------------------
  53. void R_LightAmbient_4D( const Vector& normal, Vector4D* pLightBoxColor, Vector &lv )
  54. {
  55. VectorScale( normal[0] > 0.f ? pLightBoxColor[0].AsVector3D() : pLightBoxColor[1].AsVector3D(), normal[0]*normal[0], lv );
  56. VectorMA( lv, normal[1]*normal[1], normal[1] > 0.f ? pLightBoxColor[2].AsVector3D() : pLightBoxColor[3].AsVector3D(), lv );
  57. VectorMA( lv, normal[2]*normal[2], normal[2] > 0.f ? pLightBoxColor[4].AsVector3D() : pLightBoxColor[5].AsVector3D(), lv );
  58. }
  59. #if defined( _WIN32 ) && !defined( _X360 )
  60. void R_LightAmbient_4D( const FourVectors& normal, Vector4D* pLightBoxColor, FourVectors &lv )
  61. {
  62. // VPROF( "R_LightAmbient" );
  63. // !!speed!! compute ambient color cube in sse format
  64. static fltx4 FourZeros={0.,0.,0.,.0};
  65. // find the contributions from each axis
  66. fltx4 NegMask=CmpLtSIMD(normal.x,FourZeros);
  67. fltx4 ColorSelect0=ReplicateX4(pLightBoxColor[0].AsVector3D().x);
  68. fltx4 ColorSelect1=ReplicateX4(pLightBoxColor[1].AsVector3D().x);
  69. fltx4 DirectionalColor=OrSIMD(AndSIMD(ColorSelect1,NegMask),AndNotSIMD(NegMask,ColorSelect0));
  70. fltx4 NormCompSquared=MulSIMD(normal.x,normal.x);
  71. lv.x=MulSIMD(DirectionalColor,NormCompSquared);
  72. ColorSelect0=ReplicateX4(pLightBoxColor[0].AsVector3D().y);
  73. ColorSelect1=ReplicateX4(pLightBoxColor[1].AsVector3D().y);
  74. DirectionalColor=OrSIMD(AndSIMD(ColorSelect1,NegMask),AndNotSIMD(NegMask,ColorSelect0));
  75. lv.y=MulSIMD(DirectionalColor,NormCompSquared);
  76. ColorSelect0=ReplicateX4(pLightBoxColor[0].AsVector3D().z);
  77. ColorSelect1=ReplicateX4(pLightBoxColor[1].AsVector3D().z);
  78. DirectionalColor=OrSIMD(AndSIMD(ColorSelect1,NegMask),AndNotSIMD(NegMask,ColorSelect0));
  79. lv.z=MulSIMD(DirectionalColor,NormCompSquared);
  80. NegMask=CmpLtSIMD(normal.y,FourZeros);
  81. ColorSelect0=ReplicateX4(pLightBoxColor[2].AsVector3D().x);
  82. ColorSelect1=ReplicateX4(pLightBoxColor[3].AsVector3D().x);
  83. DirectionalColor=OrSIMD(AndSIMD(ColorSelect1,NegMask),AndNotSIMD(NegMask,ColorSelect0));
  84. NormCompSquared=MulSIMD(normal.y,normal.y);
  85. lv.x=AddSIMD(lv.x,MulSIMD(DirectionalColor,NormCompSquared));
  86. ColorSelect0=ReplicateX4(pLightBoxColor[2].AsVector3D().y);
  87. ColorSelect1=ReplicateX4(pLightBoxColor[3].AsVector3D().y);
  88. DirectionalColor=OrSIMD(AndSIMD(ColorSelect1,NegMask),AndNotSIMD(NegMask,ColorSelect0));
  89. lv.y=AddSIMD(lv.y,MulSIMD(DirectionalColor,NormCompSquared));
  90. ColorSelect0=ReplicateX4(pLightBoxColor[2].AsVector3D().z);
  91. ColorSelect1=ReplicateX4(pLightBoxColor[3].AsVector3D().z);
  92. DirectionalColor=OrSIMD(AndSIMD(ColorSelect1,NegMask),AndNotSIMD(NegMask,ColorSelect0));
  93. lv.z=AddSIMD(lv.z,MulSIMD(DirectionalColor,NormCompSquared));
  94. NegMask=CmpLtSIMD(normal.z,FourZeros);
  95. ColorSelect0=ReplicateX4(pLightBoxColor[4].AsVector3D().x);
  96. ColorSelect1=ReplicateX4(pLightBoxColor[5].AsVector3D().x);
  97. DirectionalColor=OrSIMD(AndSIMD(ColorSelect1,NegMask),AndNotSIMD(NegMask,ColorSelect0));
  98. NormCompSquared=MulSIMD(normal.z,normal.z);
  99. lv.x=AddSIMD(lv.x,MulSIMD(DirectionalColor,NormCompSquared));
  100. ColorSelect0=ReplicateX4(pLightBoxColor[4].AsVector3D().y);
  101. ColorSelect1=ReplicateX4(pLightBoxColor[5].AsVector3D().y);
  102. DirectionalColor=OrSIMD(AndSIMD(ColorSelect1,NegMask),AndNotSIMD(NegMask,ColorSelect0));
  103. lv.y=AddSIMD(lv.y,MulSIMD(DirectionalColor,NormCompSquared));
  104. ColorSelect0=ReplicateX4(pLightBoxColor[4].AsVector3D().z);
  105. ColorSelect1=ReplicateX4(pLightBoxColor[5].AsVector3D().z);
  106. DirectionalColor=OrSIMD(AndSIMD(ColorSelect1,NegMask),AndNotSIMD(NegMask,ColorSelect0));
  107. lv.z=AddSIMD(lv.z,MulSIMD(DirectionalColor,NormCompSquared));
  108. }
  109. #endif
  110. //-----------------------------------------------------------------------------
  111. // Computes the ambient term, parameters are 3D Vectors for optimization
  112. //-----------------------------------------------------------------------------
  113. void R_LightAmbient_3D( const Vector& normal, const Vector* pLightBoxColor, Vector &lv )
  114. {
  115. VectorScale( normal[0] > 0.f ? pLightBoxColor[0] : pLightBoxColor[1], normal[0]*normal[0], lv );
  116. VectorMA( lv, normal[1]*normal[1], normal[1] > 0.f ? pLightBoxColor[2] : pLightBoxColor[3], lv );
  117. VectorMA( lv, normal[2]*normal[2], normal[2] > 0.f ? pLightBoxColor[4] : pLightBoxColor[5], lv );
  118. }
  119. //-----------------------------------------------------------------------------
  120. // Set up light[i].dot, light[i].falloff, and light[i].delta for all lights given
  121. // a vertex position "vert".
  122. //-----------------------------------------------------------------------------
  123. void R_LightStrengthWorld( const Vector& vert, int lightcount, LightDesc_t* pDesc, lightpos_t *light )
  124. {
  125. // VPROF( "R_LightStrengthWorld" );
  126. // NJS: note to self, maybe switch here based on lightcount, so multiple squareroots can be done simeltaneously?
  127. for ( int i = 0; i < lightcount; i++)
  128. {
  129. R_WorldLightDelta( &pDesc[i], vert, light[i].delta );
  130. light[i].falloff = R_WorldLightDistanceFalloff( &pDesc[i], light[i].delta );
  131. VectorNormalizeFast( light[i].delta );
  132. light[i].dot = DotProduct( light[i].delta, pDesc[i].m_Direction );
  133. }
  134. }
  135. //-----------------------------------------------------------------------------
  136. // Calculate the delta between a light and position
  137. //-----------------------------------------------------------------------------
  138. void R_WorldLightDelta( const LightDesc_t *wl, const Vector& org, Vector& delta )
  139. {
  140. switch (wl->m_Type)
  141. {
  142. case MATERIAL_LIGHT_POINT:
  143. case MATERIAL_LIGHT_SPOT:
  144. VectorSubtract( wl->m_Position, org, delta );
  145. break;
  146. case MATERIAL_LIGHT_DIRECTIONAL:
  147. VectorMultiply( wl->m_Direction, -1, delta );
  148. break;
  149. default:
  150. // Bug: need to return an error
  151. Assert( 0 );
  152. break;
  153. }
  154. }
  155. //#define NO_AMBIENT_CUBE 1
  156. // TODO: cone clipping calc's wont work for boxlight since the player asks for a single point. Not sure what the volume is.
  157. TEMPLATE_FUNCTION_TABLE( void, R_LightEffectsWorldFunctionTable, ( const LightDesc_t* pLightDesc, const lightpos_t *light, const Vector& normal, Vector &dest ), 256 )
  158. {
  159. enum
  160. {
  161. LightType1 = ( nArgument & 0xC0 ) >> 6,
  162. LightType2 = ( nArgument & 0x30 ) >> 4,
  163. LightType3 = ( nArgument & 0x0C ) >> 2,
  164. LightType4 = ( nArgument & 0x03 )
  165. };
  166. // VPROF( "R_LightEffectsWorld" );
  167. #ifdef NO_AMBIENT_CUBE
  168. dest[0] = dest[1] = dest[2] = 0.0f;
  169. #endif
  170. // FIXME: lighting effects for normal and position are independent!
  171. // FIXME: these can be pre-calculated per normal
  172. if( (LightType_t)LightType1 != MATERIAL_LIGHT_DISABLE )
  173. {
  174. float ratio = light[0].falloff * CWorldLightAngleWrapper<LightType1>::WorldLightAngle( &pLightDesc[0], pLightDesc[0].m_Direction, normal, light[0].delta );
  175. if (ratio > 0)
  176. {
  177. const float* pColor = (float*)&pLightDesc[0].m_Color;
  178. dest[0] += pColor[0] * ratio;
  179. dest[1] += pColor[1] * ratio;
  180. dest[2] += pColor[2] * ratio;
  181. }
  182. }
  183. if( (LightType_t)LightType2 != MATERIAL_LIGHT_DISABLE )
  184. {
  185. float ratio = light[1].falloff * CWorldLightAngleWrapper<LightType2>::WorldLightAngle( &pLightDesc[1], pLightDesc[1].m_Direction, normal, light[1].delta );
  186. if (ratio > 0)
  187. {
  188. const float* pColor = (float*)&pLightDesc[1].m_Color;
  189. dest[0] += pColor[0] * ratio;
  190. dest[1] += pColor[1] * ratio;
  191. dest[2] += pColor[2] * ratio;
  192. }
  193. }
  194. if( (LightType_t)LightType3 != MATERIAL_LIGHT_DISABLE )
  195. {
  196. float ratio = light[2].falloff * CWorldLightAngleWrapper<LightType3>::WorldLightAngle( &pLightDesc[2], pLightDesc[2].m_Direction, normal, light[2].delta );
  197. if (ratio > 0)
  198. {
  199. const float* pColor = (float*)&pLightDesc[2].m_Color;
  200. dest[0] += pColor[0] * ratio;
  201. dest[1] += pColor[1] * ratio;
  202. dest[2] += pColor[2] * ratio;
  203. }
  204. }
  205. if( (LightType_t)LightType4 != MATERIAL_LIGHT_DISABLE )
  206. {
  207. float ratio = light[3].falloff * CWorldLightAngleWrapper<LightType4>::WorldLightAngle( &pLightDesc[3], pLightDesc[3].m_Direction, normal, light[3].delta );
  208. if (ratio > 0)
  209. {
  210. const float* pColor = (float*)&pLightDesc[3].m_Color;
  211. dest[0] += pColor[0] * ratio;
  212. dest[1] += pColor[1] * ratio;
  213. dest[2] += pColor[2] * ratio;
  214. }
  215. }
  216. }
  217. TEMPLATE_FUNCTION_TABLE( void, R_LightEffectsWorldFunctionTableConstDirectional, ( const LightDesc_t* pLightDesc, const lightpos_t *light, const Vector& normal, Vector &dest, float flDirectionalConstant ), 256 )
  218. {
  219. enum
  220. {
  221. LightType1 = ( nArgument & 0xC0 ) >> 6,
  222. LightType2 = ( nArgument & 0x30 ) >> 4,
  223. LightType3 = ( nArgument & 0x0C ) >> 2,
  224. LightType4 = ( nArgument & 0x03 )
  225. };
  226. // VPROF( "R_LightEffectsWorld" );
  227. #ifdef NO_AMBIENT_CUBE
  228. dest[0] = dest[1] = dest[2] = 0.0f;
  229. #endif
  230. // FIXME: lighting effects for normal and position are independent!
  231. // FIXME: these can be pre-calculated per normal
  232. if( (LightType_t)LightType1 != MATERIAL_LIGHT_DISABLE )
  233. {
  234. float ratio = light[0].falloff *
  235. CWorldLightAngleWrapperConstDirectional<LightType1>::WorldLightAngle( &pLightDesc[0],
  236. pLightDesc[0].m_Direction, normal, light[0].delta, flDirectionalConstant );
  237. if (ratio > 0)
  238. {
  239. const float* pColor = (float*)&pLightDesc[0].m_Color;
  240. dest[0] += pColor[0] * ratio;
  241. dest[1] += pColor[1] * ratio;
  242. dest[2] += pColor[2] * ratio;
  243. }
  244. }
  245. if( (LightType_t)LightType2 != MATERIAL_LIGHT_DISABLE )
  246. {
  247. float ratio = light[1].falloff *
  248. CWorldLightAngleWrapperConstDirectional<LightType2>::WorldLightAngle( &pLightDesc[1],
  249. pLightDesc[1].m_Direction, normal, light[1].delta, flDirectionalConstant );
  250. if (ratio > 0)
  251. {
  252. const float* pColor = (float*)&pLightDesc[1].m_Color;
  253. dest[0] += pColor[0] * ratio;
  254. dest[1] += pColor[1] * ratio;
  255. dest[2] += pColor[2] * ratio;
  256. }
  257. }
  258. if( (LightType_t)LightType3 != MATERIAL_LIGHT_DISABLE )
  259. {
  260. float ratio = light[2].falloff *
  261. CWorldLightAngleWrapperConstDirectional<LightType3>::WorldLightAngle( &pLightDesc[2],
  262. pLightDesc[2].m_Direction, normal, light[2].delta, flDirectionalConstant );
  263. if (ratio > 0)
  264. {
  265. const float* pColor = (float*)&pLightDesc[2].m_Color;
  266. dest[0] += pColor[0] * ratio;
  267. dest[1] += pColor[1] * ratio;
  268. dest[2] += pColor[2] * ratio;
  269. }
  270. }
  271. if( (LightType_t)LightType4 != MATERIAL_LIGHT_DISABLE )
  272. {
  273. float ratio = light[3].falloff *
  274. CWorldLightAngleWrapperConstDirectional<LightType4>::WorldLightAngle( &pLightDesc[3],
  275. pLightDesc[3].m_Direction, normal, light[3].delta, flDirectionalConstant );
  276. if (ratio > 0)
  277. {
  278. const float* pColor = (float*)&pLightDesc[3].m_Color;
  279. dest[0] += pColor[0] * ratio;
  280. dest[1] += pColor[1] * ratio;
  281. dest[2] += pColor[2] * ratio;
  282. }
  283. }
  284. }
  285. //-----------------------------------------------------------------------------
  286. // Get the function table index
  287. //-----------------------------------------------------------------------------
  288. static int s_pLightMask[ 5 ] =
  289. {
  290. 0, // No lights
  291. 0xC0, // 1 light
  292. 0xF0, // 2 lights
  293. 0xFC, // 3 lights
  294. 0xFF, // 4 lights
  295. };
  296. inline int R_LightEffectsWorldIndex(const LightDesc_t* pLightDesc, int nNumLights)
  297. {
  298. if ( nNumLights > 4 )
  299. {
  300. nNumLights = 4;
  301. }
  302. int nIndex = ((pLightDesc[0].m_Type & 0x3) << 6) | ((pLightDesc[1].m_Type & 0x3) << 4) | ( (pLightDesc[2].m_Type & 0x3) << 2) | (pLightDesc[3].m_Type & 0x3);
  303. nIndex &= s_pLightMask[ nNumLights ];
  304. Assert( nIndex >= 0 && nIndex < R_LightEffectsWorldFunctionTable::count );
  305. return nIndex;
  306. }
  307. /*
  308. light_direction (light_pos - vertex_pos)
  309. */
  310. // TODO: move cone calcs to position
  311. // TODO: cone clipping calc's wont work for boxlight since the player asks for a single point. Not sure what the volume is.
  312. TEMPLATE_FUNCTION_TABLE( float, R_WorldLightDistanceFalloffFunctionTable, ( const LightDesc_t *wl, const Vector& delta ), 8)
  313. {
  314. Assert( nArgument != 0 );
  315. float dist2 = DotProduct( delta, delta );
  316. // Cull out light beyond this radius
  317. if (wl->m_Range != 0.f)
  318. {
  319. if (dist2 > wl->m_Range * wl->m_Range)
  320. return 0.0f;
  321. }
  322. // The general purpose equation:
  323. float fTotal = FLT_EPSILON;
  324. if( nArgument & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0 )
  325. {
  326. fTotal = wl->m_Attenuation0;
  327. }
  328. if( nArgument & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1 )
  329. {
  330. fTotal += wl->m_Attenuation1 * FastSqrt( dist2 );
  331. }
  332. if( nArgument & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2 )
  333. {
  334. fTotal += wl->m_Attenuation2 * dist2;
  335. }
  336. return 1.0f / fTotal;
  337. }
  338. //-----------------------------------------------------------------------------
  339. // Calculate the falloff from the world lights
  340. //-----------------------------------------------------------------------------
  341. float FASTCALL R_WorldLightDistanceFalloff( const LightDesc_t *wl, const Vector& delta )
  342. {
  343. // Ensure no invalid flags are set
  344. Assert( ! ( wl->m_Flags & ~(LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0|LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1|LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2|LIGHTTYPE_OPTIMIZATIONFLAGS_DERIVED_VALUES_CALCED) ) );
  345. // calculate falloff
  346. int flags = wl->m_Flags & (LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0|LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1|LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2);
  347. return R_WorldLightDistanceFalloffFunctionTable::functions[flags](wl, delta);
  348. }
  349. #if defined( _WIN32 ) && !defined( _X360 )
  350. fltx4 FASTCALL R_WorldLightDistanceFalloff( const LightDesc_t *wl, const FourVectors &delta )
  351. {
  352. // !!speed!!: lights could store m_Attenuation2,m_Attenuation1, and m_Range^2 copies in replicated SSE format.
  353. // Ensure no invalid flags are set
  354. Assert( ! ( wl->m_Flags & ~(LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0|LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1|LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2|LIGHTTYPE_OPTIMIZATIONFLAGS_DERIVED_VALUES_CALCED) ) );
  355. fltx4 dist2 = delta*delta;
  356. fltx4 fTotal;
  357. if( wl->m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0 )
  358. {
  359. fTotal = ReplicateX4(wl->m_Attenuation0);
  360. }
  361. else
  362. fTotal= ReplicateX4(FLT_EPSILON); // !!speed!! replicate
  363. if( wl->m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1 )
  364. {
  365. fTotal=AddSIMD(fTotal,MulSIMD(ReplicateX4(wl->m_Attenuation1),SqrtEstSIMD(dist2)));
  366. }
  367. if( wl->m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2 )
  368. {
  369. fTotal=AddSIMD(fTotal,MulSIMD(ReplicateX4(wl->m_Attenuation2),dist2));
  370. }
  371. fTotal=ReciprocalEstSIMD(fTotal);
  372. // Cull out light beyond this radius
  373. // now, zero out elements for which dist2 was > range^2. !!speed!! lights should store dist^2 in sse format
  374. if (wl->m_Range != 0.f)
  375. {
  376. fltx4 RangeSquared = ReplicateX4(wl->m_Range*wl->m_Range); // !!speed!!
  377. fTotal=AndSIMD(fTotal,CmpLtSIMD(dist2,RangeSquared));
  378. }
  379. return fTotal;
  380. }
  381. #endif
  382. int CStudioRender::R_LightGlintPosition( int index, const Vector& org, Vector& delta, Vector& intensity )
  383. {
  384. if (index >= m_pRC->m_NumLocalLights)
  385. return false;
  386. R_WorldLightDelta( &m_pRC->m_LocalLights[index], org, delta );
  387. float falloff = R_WorldLightDistanceFalloff( &m_pRC->m_LocalLights[index], delta );
  388. VectorMultiply( m_pRC->m_LocalLights[index].m_Color, falloff, intensity );
  389. return true;
  390. }
  391. //-----------------------------------------------------------------------------
  392. // Setup up the function table
  393. //-----------------------------------------------------------------------------
  394. void CStudioRender::R_InitLightEffectsWorld3()
  395. {
  396. // set the function pointer
  397. int index = R_LightEffectsWorldIndex( m_pRC->m_LocalLights, m_pRC->m_NumLocalLights );
  398. R_LightEffectsWorld3 = R_LightEffectsWorldFunctionTable::functions[index];
  399. }
  400. //-----------------------------------------------------------------------------
  401. // Performs lighting functions common to the ComputeLighting and ComputeLightingConstantDirectional
  402. // returns the index of the LightEffectsWorldFunction to use
  403. //-----------------------------------------------------------------------------
  404. static int ComputeLightingCommon( const Vector* pAmbient, int lightCount,
  405. LightDesc_t* pLights, const Vector& pt, const Vector& normal, lightpos_t *pLightPos, Vector& lighting )
  406. {
  407. // Set up lightpos[i].dot, lightpos[i].falloff, and lightpos[i].delta for all lights
  408. R_LightStrengthWorld( pt, lightCount, pLights, pLightPos );
  409. // calculate ambient values from the ambient cube given a normal.
  410. R_LightAmbient_3D( normal, pAmbient, lighting );
  411. return R_LightEffectsWorldIndex( pLights, lightCount );
  412. }
  413. //-----------------------------------------------------------------------------
  414. // Compute the lighting at a point and normal
  415. // Final Lighting is in linear space
  416. //-----------------------------------------------------------------------------
  417. void CStudioRenderContext::ComputeLighting( const Vector* pAmbient, int lightCount,
  418. LightDesc_t* pLights, const Vector& pt, const Vector& normal, Vector& lighting )
  419. {
  420. if ( m_RC.m_Config.fullbright )
  421. {
  422. lighting.Init( 1.0f, 1.0f, 1.0f );
  423. return;
  424. }
  425. if ( lightCount > ARRAYSIZE( m_pLightPos ) )
  426. {
  427. AssertMsg( 0, "Light count out of range in ComputeLighting\n" );
  428. lightCount = ARRAYSIZE( m_pLightPos );
  429. }
  430. // Calculate color given lightpos_t lightpos, a normal, and the ambient
  431. // color from the ambient cube calculated in ComputeLightingCommon
  432. int index = ComputeLightingCommon( pAmbient, lightCount, pLights, pt, normal, m_pLightPos, lighting );
  433. R_LightEffectsWorldFunctionTable::functions[index]( pLights, m_pLightPos, normal, lighting );
  434. }
  435. //-----------------------------------------------------------------------------
  436. // Compute the lighting at a point and normal
  437. // Final Lighting is in linear space
  438. // Uses flDirectionalAmount instead of directional components of lights
  439. //-----------------------------------------------------------------------------
  440. void CStudioRenderContext::ComputeLightingConstDirectional( const Vector* pAmbient, int lightCount,
  441. LightDesc_t* pLights, const Vector& pt, const Vector& normal, Vector& lighting, float flDirectionalAmount )
  442. {
  443. if ( m_RC.m_Config.fullbright )
  444. {
  445. lighting.Init( 1.0f, 1.0f, 1.0f );
  446. return;
  447. }
  448. if ( lightCount > ARRAYSIZE( m_pLightPos ) )
  449. {
  450. AssertMsg( 0, "Light count out of range in ComputeLighting\n" );
  451. lightCount = ARRAYSIZE( m_pLightPos );
  452. }
  453. // Calculate color given lightpos_t lightpos, a normal, and the ambient
  454. // color from the ambient cube calculated in ComputeLightingCommon
  455. int index = ComputeLightingCommon( pAmbient, lightCount, pLights, pt, normal, m_pLightPos, lighting );
  456. R_LightEffectsWorldFunctionTableConstDirectional::functions[index]( pLights, m_pLightPos, normal, lighting, flDirectionalAmount );
  457. }