Counter Strike : Global Offensive Source Code
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
20 KiB

  1. //===== Copyright (c) 1996-2005, 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. #define LIGHT_EFFECTS_FUNCTABLE_SIZE 256
  157. // TODO: cone clipping calc's wont work for boxlight since the player asks for a single point. Not sure what the volume is.
  158. TEMPLATE_FUNCTION_TABLE( void, R_LightEffectsWorldFunctionTable, ( const LightDesc_t* pLightDesc, const lightpos_t *light, const Vector& normal, Vector &dest ), LIGHT_EFFECTS_FUNCTABLE_SIZE )
  159. {
  160. enum
  161. {
  162. LightType1 = ( nArgument & 0xC0 ) >> 6,
  163. LightType2 = ( nArgument & 0x30 ) >> 4,
  164. LightType3 = ( nArgument & 0x0C ) >> 2,
  165. LightType4 = ( nArgument & 0x03 )
  166. };
  167. // VPROF( "R_LightEffectsWorld" );
  168. #ifdef NO_AMBIENT_CUBE
  169. dest[0] = dest[1] = dest[2] = 0.0f;
  170. #endif
  171. // FIXME: lighting effects for normal and position are independent!
  172. // FIXME: these can be pre-calculated per normal
  173. if( (int)LightType1 != (int)MATERIAL_LIGHT_DISABLE )
  174. {
  175. float ratio = light[0].falloff * CWorldLightAngleWrapper<LightType1>::WorldLightAngle( &pLightDesc[0], pLightDesc[0].m_Direction, normal, light[0].delta );
  176. if (ratio > 0)
  177. {
  178. const float* pColor = (float*)&pLightDesc[0].m_Color;
  179. dest[0] += pColor[0] * ratio;
  180. dest[1] += pColor[1] * ratio;
  181. dest[2] += pColor[2] * ratio;
  182. }
  183. }
  184. if( (int)LightType2 != (int)MATERIAL_LIGHT_DISABLE )
  185. {
  186. float ratio = light[1].falloff * CWorldLightAngleWrapper<LightType2>::WorldLightAngle( &pLightDesc[1], pLightDesc[1].m_Direction, normal, light[1].delta );
  187. if (ratio > 0)
  188. {
  189. const float* pColor = (float*)&pLightDesc[1].m_Color;
  190. dest[0] += pColor[0] * ratio;
  191. dest[1] += pColor[1] * ratio;
  192. dest[2] += pColor[2] * ratio;
  193. }
  194. }
  195. if( (int)LightType3 != (int)MATERIAL_LIGHT_DISABLE )
  196. {
  197. float ratio = light[2].falloff * CWorldLightAngleWrapper<LightType3>::WorldLightAngle( &pLightDesc[2], pLightDesc[2].m_Direction, normal, light[2].delta );
  198. if (ratio > 0)
  199. {
  200. const float* pColor = (float*)&pLightDesc[2].m_Color;
  201. dest[0] += pColor[0] * ratio;
  202. dest[1] += pColor[1] * ratio;
  203. dest[2] += pColor[2] * ratio;
  204. }
  205. }
  206. if( (int)LightType4 != (int)MATERIAL_LIGHT_DISABLE )
  207. {
  208. float ratio = light[3].falloff * CWorldLightAngleWrapper<LightType4>::WorldLightAngle( &pLightDesc[3], pLightDesc[3].m_Direction, normal, light[3].delta );
  209. if (ratio > 0)
  210. {
  211. const float* pColor = (float*)&pLightDesc[3].m_Color;
  212. dest[0] += pColor[0] * ratio;
  213. dest[1] += pColor[1] * ratio;
  214. dest[2] += pColor[2] * ratio;
  215. }
  216. }
  217. }
  218. TEMPLATE_FUNCTION_TABLE( void, R_LightEffectsWorldFunctionTableConstDirectional, ( const LightDesc_t* pLightDesc, const lightpos_t *light, const Vector& normal, Vector &dest, float flDirectionalConstant ), LIGHT_EFFECTS_FUNCTABLE_SIZE )
  219. {
  220. enum
  221. {
  222. LightType1 = ( nArgument & 0xC0 ) >> 6,
  223. LightType2 = ( nArgument & 0x30 ) >> 4,
  224. LightType3 = ( nArgument & 0x0C ) >> 2,
  225. LightType4 = ( nArgument & 0x03 )
  226. };
  227. // VPROF( "R_LightEffectsWorld" );
  228. #ifdef NO_AMBIENT_CUBE
  229. dest[0] = dest[1] = dest[2] = 0.0f;
  230. #endif
  231. // FIXME: lighting effects for normal and position are independent!
  232. // FIXME: these can be pre-calculated per normal
  233. if( (int)LightType1 != (int)MATERIAL_LIGHT_DISABLE )
  234. {
  235. float ratio = light[0].falloff *
  236. CWorldLightAngleWrapperConstDirectional<LightType1>::WorldLightAngle( &pLightDesc[0],
  237. pLightDesc[0].m_Direction, normal, light[0].delta, flDirectionalConstant );
  238. if (ratio > 0)
  239. {
  240. const float* pColor = (float*)&pLightDesc[0].m_Color;
  241. dest[0] += pColor[0] * ratio;
  242. dest[1] += pColor[1] * ratio;
  243. dest[2] += pColor[2] * ratio;
  244. }
  245. }
  246. if( (int)LightType2 != (int)MATERIAL_LIGHT_DISABLE )
  247. {
  248. float ratio = light[1].falloff *
  249. CWorldLightAngleWrapperConstDirectional<LightType2>::WorldLightAngle( &pLightDesc[1],
  250. pLightDesc[1].m_Direction, normal, light[1].delta, flDirectionalConstant );
  251. if (ratio > 0)
  252. {
  253. const float* pColor = (float*)&pLightDesc[1].m_Color;
  254. dest[0] += pColor[0] * ratio;
  255. dest[1] += pColor[1] * ratio;
  256. dest[2] += pColor[2] * ratio;
  257. }
  258. }
  259. if( (int)LightType3 != (int)MATERIAL_LIGHT_DISABLE )
  260. {
  261. float ratio = light[2].falloff *
  262. CWorldLightAngleWrapperConstDirectional<LightType3>::WorldLightAngle( &pLightDesc[2],
  263. pLightDesc[2].m_Direction, normal, light[2].delta, flDirectionalConstant );
  264. if (ratio > 0)
  265. {
  266. const float* pColor = (float*)&pLightDesc[2].m_Color;
  267. dest[0] += pColor[0] * ratio;
  268. dest[1] += pColor[1] * ratio;
  269. dest[2] += pColor[2] * ratio;
  270. }
  271. }
  272. if( (int)LightType4 != (int)MATERIAL_LIGHT_DISABLE )
  273. {
  274. float ratio = light[3].falloff *
  275. CWorldLightAngleWrapperConstDirectional<LightType4>::WorldLightAngle( &pLightDesc[3],
  276. pLightDesc[3].m_Direction, normal, light[3].delta, flDirectionalConstant );
  277. if (ratio > 0)
  278. {
  279. const float* pColor = (float*)&pLightDesc[3].m_Color;
  280. dest[0] += pColor[0] * ratio;
  281. dest[1] += pColor[1] * ratio;
  282. dest[2] += pColor[2] * ratio;
  283. }
  284. }
  285. }
  286. //-----------------------------------------------------------------------------
  287. // Get the function table index
  288. //-----------------------------------------------------------------------------
  289. static int s_pLightMask[ 5 ] =
  290. {
  291. 0, // No lights
  292. 0xC0, // 1 light
  293. 0xF0, // 2 lights
  294. 0xFC, // 3 lights
  295. 0xFF, // 4 lights
  296. };
  297. inline int R_LightEffectsWorldIndex(const LightDesc_t* pLightDesc, int nNumLights)
  298. {
  299. if ( nNumLights > 4 )
  300. {
  301. nNumLights = 4;
  302. }
  303. 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);
  304. nIndex &= s_pLightMask[ nNumLights ];
  305. Assert( nIndex >= 0 && nIndex < R_LightEffectsWorldFunctionTable::count );
  306. return nIndex;
  307. }
  308. /*
  309. light_direction (light_pos - vertex_pos)
  310. */
  311. // TODO: move cone calcs to position
  312. // TODO: cone clipping calc's wont work for boxlight since the player asks for a single point. Not sure what the volume is.
  313. TEMPLATE_FUNCTION_TABLE( float, R_WorldLightDistanceFalloffFunctionTable, ( const LightDesc_t *wl, const Vector& delta ), 8)
  314. {
  315. Assert( nArgument != 0 );
  316. float dist2 = DotProduct( delta, delta );
  317. // Cull out light beyond this radius
  318. if (wl->m_Range != 0.f)
  319. {
  320. if (dist2 > wl->m_Range * wl->m_Range)
  321. return 0.0f;
  322. }
  323. // The general purpose equation:
  324. float fTotal = FLT_EPSILON;
  325. if( nArgument & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0 )
  326. {
  327. fTotal = wl->m_Attenuation0;
  328. }
  329. if( nArgument & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1 )
  330. {
  331. fTotal += wl->m_Attenuation1 * FastSqrt( dist2 );
  332. }
  333. if( nArgument & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2 )
  334. {
  335. fTotal += wl->m_Attenuation2 * dist2;
  336. }
  337. return 1.0f / fTotal;
  338. }
  339. //-----------------------------------------------------------------------------
  340. // Calculate the falloff from the world lights
  341. //-----------------------------------------------------------------------------
  342. float FASTCALL R_WorldLightDistanceFalloff( const LightDesc_t *wl, const Vector& delta )
  343. {
  344. // Ensure no invalid flags are set
  345. Assert( ! ( wl->m_Flags & ~(LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0|LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1|LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2|LIGHTTYPE_OPTIMIZATIONFLAGS_DERIVED_VALUES_CALCED) ) );
  346. // calculate falloff
  347. int flags = wl->m_Flags & (LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0|LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1|LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2);
  348. return R_WorldLightDistanceFalloffFunctionTable::functions[flags](wl, delta);
  349. }
  350. #if defined( _WIN32 ) && !defined( _X360 )
  351. fltx4 FASTCALL R_WorldLightDistanceFalloff( const LightDesc_t *wl, const FourVectors &delta )
  352. {
  353. // !!speed!!: lights could store m_Attenuation2,m_Attenuation1, and m_Range^2 copies in replicated SSE format.
  354. // Ensure no invalid flags are set
  355. Assert( ! ( wl->m_Flags & ~(LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0|LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1|LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2|LIGHTTYPE_OPTIMIZATIONFLAGS_DERIVED_VALUES_CALCED) ) );
  356. fltx4 dist2 = delta*delta;
  357. fltx4 fTotal;
  358. if( wl->m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION0 )
  359. {
  360. fTotal = ReplicateX4(wl->m_Attenuation0);
  361. }
  362. else
  363. fTotal= ReplicateX4(FLT_EPSILON); // !!speed!! replicate
  364. if( wl->m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION1 )
  365. {
  366. fTotal=AddSIMD(fTotal,MulSIMD(ReplicateX4(wl->m_Attenuation1),SqrtEstSIMD(dist2)));
  367. }
  368. if( wl->m_Flags & LIGHTTYPE_OPTIMIZATIONFLAGS_HAS_ATTENUATION2 )
  369. {
  370. fTotal=AddSIMD(fTotal,MulSIMD(ReplicateX4(wl->m_Attenuation2),dist2));
  371. }
  372. fTotal=ReciprocalEstSIMD(fTotal);
  373. // Cull out light beyond this radius
  374. // now, zero out elements for which dist2 was > range^2. !!speed!! lights should store dist^2 in sse format
  375. if (wl->m_Range != 0.f)
  376. {
  377. fltx4 RangeSquared = ReplicateX4(wl->m_Range*wl->m_Range); // !!speed!!
  378. fTotal=AndSIMD(fTotal,CmpLtSIMD(dist2,RangeSquared));
  379. }
  380. return fTotal;
  381. }
  382. #endif
  383. int CStudioRender::R_LightGlintPosition( int index, const Vector& org, Vector& delta, Vector& intensity )
  384. {
  385. if (index >= m_pRC->m_NumLocalLights)
  386. return false;
  387. R_WorldLightDelta( &m_pRC->m_LocalLights[index], org, delta );
  388. float falloff = R_WorldLightDistanceFalloff( &m_pRC->m_LocalLights[index], delta );
  389. VectorMultiply( m_pRC->m_LocalLights[index].m_Color, falloff, intensity );
  390. return true;
  391. }
  392. //-----------------------------------------------------------------------------
  393. // Setup up the function table
  394. //-----------------------------------------------------------------------------
  395. void CStudioRender::R_InitLightEffectsWorld3()
  396. {
  397. // set the function pointer
  398. int index = R_LightEffectsWorldIndex( m_pRC->m_LocalLights, m_pRC->m_NumLocalLights );
  399. R_LightEffectsWorld3 = R_LightEffectsWorldFunctionTable::functions[index];
  400. }
  401. //-----------------------------------------------------------------------------
  402. // Performs lighting functions common to the ComputeLighting and ComputeLightingConstantDirectional
  403. // returns the index of the LightEffectsWorldFunction to use
  404. //-----------------------------------------------------------------------------
  405. static int ComputeLightingCommon( const Vector* pAmbient, int lightCount,
  406. LightDesc_t* pLights, const Vector& pt, const Vector& normal, lightpos_t *pLightPos, Vector& lighting )
  407. {
  408. // Set up lightpos[i].dot, lightpos[i].falloff, and lightpos[i].delta for all lights
  409. R_LightStrengthWorld( pt, lightCount, pLights, pLightPos );
  410. // calculate ambient values from the ambient cube given a normal.
  411. R_LightAmbient_3D( normal, pAmbient, lighting );
  412. return R_LightEffectsWorldIndex( pLights, lightCount );
  413. }
  414. //-----------------------------------------------------------------------------
  415. // Compute the lighting at a point and normal
  416. // Final Lighting is in linear space
  417. //-----------------------------------------------------------------------------
  418. void CStudioRenderContext::ComputeLighting( const Vector* pAmbient, int lightCount,
  419. LightDesc_t* pLights, const Vector& pt, const Vector& normal, Vector& lighting )
  420. {
  421. if ( m_RC.m_Config.fullbright )
  422. {
  423. lighting.Init( 1.0f, 1.0f, 1.0f );
  424. return;
  425. }
  426. if ( lightCount > ARRAYSIZE( m_pLightPos ) )
  427. {
  428. AssertMsg( 0, "Light count out of range in ComputeLighting\n" );
  429. lightCount = ARRAYSIZE( m_pLightPos );
  430. }
  431. // Calculate color given lightpos_t lightpos, a normal, and the ambient
  432. // color from the ambient cube calculated in ComputeLightingCommon
  433. int index = ComputeLightingCommon( pAmbient, lightCount, pLights, pt, normal, m_pLightPos, lighting );
  434. R_LightEffectsWorldFunctionTable::functions[index]( pLights, m_pLightPos, normal, lighting );
  435. }
  436. //-----------------------------------------------------------------------------
  437. // Compute the lighting at a point and normal
  438. // Final Lighting is in linear space
  439. // Uses flDirectionalAmount instead of directional components of lights
  440. //-----------------------------------------------------------------------------
  441. void CStudioRenderContext::ComputeLightingConstDirectional( const Vector* pAmbient, int lightCount,
  442. LightDesc_t* pLights, const Vector& pt, const Vector& normal, Vector& lighting, float flDirectionalAmount )
  443. {
  444. if ( m_RC.m_Config.fullbright )
  445. {
  446. lighting.Init( 1.0f, 1.0f, 1.0f );
  447. return;
  448. }
  449. if ( lightCount > ARRAYSIZE( m_pLightPos ) )
  450. {
  451. AssertMsg( 0, "Light count out of range in ComputeLighting\n" );
  452. lightCount = ARRAYSIZE( m_pLightPos );
  453. }
  454. // Calculate color given lightpos_t lightpos, a normal, and the ambient
  455. // color from the ambient cube calculated in ComputeLightingCommon
  456. int index = ComputeLightingCommon( pAmbient, lightCount, pLights, pt, normal, m_pLightPos, lighting );
  457. R_LightEffectsWorldFunctionTableConstDirectional::functions[index]( pLights, m_pLightPos, normal, lighting, flDirectionalAmount );
  458. }