lightenvironment.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWPhys *
  23. * *
  24. * $Archive:: /Commando/Code/ww3d2/lightenvironment.cpp $*
  25. * *
  26. * Original Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Greg_h $*
  29. * *
  30. * $Modtime:: 3/01/02 3:43p $*
  31. * *
  32. * $Revision:: 4 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  37. #include "lightenvironment.h"
  38. #include "matrix3d.h"
  39. #include "camera.h"
  40. #include "light.h"
  41. /*
  42. ** Constants
  43. */
  44. const float DIFFUSE_TO_AMBIENT_FRACTION = 1.0f;
  45. /*
  46. ** Static variables
  47. */
  48. static _LightingLODCutoff = 0.5f;
  49. static _LightingLODCutoff2 = 0.5f * 0.5f;
  50. /************************************************************************************************
  51. **
  52. ** LightEnvironmentClass::InputLightStruct Implementation
  53. **
  54. ************************************************************************************************/
  55. void LightEnvironmentClass::InputLightStruct::Init
  56. (
  57. const LightClass & light,
  58. const Vector3 & object_center
  59. )
  60. {
  61. switch(light.Get_Type())
  62. {
  63. case LightClass::POINT:
  64. case LightClass::SPOT:
  65. Init_From_Point_Or_Spot_Light(light,object_center);
  66. break;
  67. case LightClass::DIRECTIONAL:
  68. Init_From_Directional_Light(light,object_center);
  69. break;
  70. };
  71. }
  72. void LightEnvironmentClass::InputLightStruct::Init_From_Point_Or_Spot_Light
  73. (
  74. const LightClass & light,
  75. const Vector3 & object_center
  76. )
  77. {
  78. /*
  79. ** Compute the direction vector and the distance to the light
  80. */
  81. Direction = light.Get_Position() - object_center;
  82. float dist = Direction.Length();
  83. if (dist > 0.0f) {
  84. Direction /= dist;
  85. }
  86. /*
  87. ** Compute the attenuation factor
  88. */
  89. double atten_start,atten_end;
  90. light.Get_Far_Attenuation_Range(atten_start,atten_end);
  91. float atten = 1.0f - (dist - atten_start) / (atten_end - atten_start);
  92. atten = WWMath::Clamp(atten,0.0f,1.0f);
  93. if (light.Get_Type() == LightClass::SPOT) {
  94. Vector3 spot_dir;
  95. light.Get_Spot_Direction(spot_dir);
  96. Matrix3D::Rotate_Vector(light.Get_Transform(),spot_dir,&spot_dir);
  97. float spot_angle_cos = light.Get_Spot_Angle_Cos();
  98. atten *= (Vector3::Dot_Product(-spot_dir,Direction) - spot_angle_cos) / (1.0f - spot_angle_cos);
  99. atten = WWMath::Clamp(atten,0.0f,1.0f);
  100. }
  101. /*
  102. ** Compute the ambient and diffuse values. Rejecting the diffuse
  103. ** component and folding it into the ambient component if it is below
  104. ** the LOD cutoff
  105. */
  106. light.Get_Ambient(&Ambient);
  107. light.Get_Diffuse(&Diffuse);
  108. if (Diffuse.Length2() > _LightingLODCutoff2) {
  109. DiffuseRejected = false;
  110. Ambient *= atten;
  111. Diffuse *= atten;
  112. } else {
  113. DiffuseRejected = true;
  114. Ambient *= atten;
  115. Ambient += atten * DIFFUSE_TO_AMBIENT_FRACTION * Diffuse;
  116. Diffuse.Set(0,0,0);
  117. }
  118. }
  119. void LightEnvironmentClass::InputLightStruct::Init_From_Directional_Light
  120. (
  121. const LightClass & light,
  122. const Vector3 & object_center
  123. )
  124. {
  125. Direction = -light.Get_Transform().Get_Z_Vector();
  126. DiffuseRejected = false;
  127. light.Get_Ambient(&Ambient);
  128. light.Get_Diffuse(&Diffuse);
  129. }
  130. float LightEnvironmentClass::InputLightStruct::Contribution(void)
  131. {
  132. return Diffuse.Length2();
  133. }
  134. /************************************************************************************************
  135. **
  136. ** LightEnvironmentClass::OutputLightStruct Implementation
  137. **
  138. ************************************************************************************************/
  139. void LightEnvironmentClass::OutputLightStruct::Init
  140. (
  141. const InputLightStruct & input,
  142. const Matrix3D & camera_tm
  143. )
  144. {
  145. Diffuse = input.Diffuse;
  146. Matrix3D::Inverse_Rotate_Vector(camera_tm,input.Direction,&Direction);
  147. }
  148. /************************************************************************************************
  149. **
  150. ** LightEnvironmentClass Implementation
  151. **
  152. ************************************************************************************************/
  153. LightEnvironmentClass::LightEnvironmentClass(void) :
  154. LightCount(0),
  155. ObjectCenter(0,0,0),
  156. OutputAmbient(0,0,0)
  157. {
  158. }
  159. LightEnvironmentClass::~LightEnvironmentClass(void)
  160. {
  161. }
  162. void LightEnvironmentClass::Reset(const Vector3 & object_center,const Vector3 & ambient)
  163. {
  164. LightCount = 0;
  165. ObjectCenter = object_center;
  166. OutputAmbient = ambient;
  167. }
  168. void LightEnvironmentClass::Add_Light(const LightClass & light)
  169. {
  170. /*
  171. ** Compute the equivalent directional + ambient light
  172. */
  173. InputLightStruct new_light;
  174. new_light.Init(light,ObjectCenter);
  175. /*
  176. ** Add in the ambient component
  177. */
  178. OutputAmbient += new_light.Ambient;
  179. /*
  180. ** If not rejected, add the directional component to the active lights
  181. */
  182. if (new_light.DiffuseRejected == false) {
  183. if (LightCount < MAX_LIGHTS) {
  184. InputLights[LightCount] = new_light;
  185. LightCount++;
  186. } else {
  187. for (int light_index=0; light_index<LightCount; light_index++) {
  188. if (new_light.Contribution() > InputLights[light_index].Contribution()) {
  189. InputLights[light_index] = new_light;
  190. light_index = MAX_LIGHTS;
  191. }
  192. }
  193. }
  194. }
  195. }
  196. void LightEnvironmentClass::Pre_Render_Update(const Matrix3D & camera_tm)
  197. {
  198. /*
  199. ** Transform each light into camera space
  200. ** and add up the ambient effect of each light
  201. */
  202. for (int light_index=0; light_index<LightCount; light_index++) {
  203. OutputLights[light_index].Init(InputLights[light_index],camera_tm);
  204. }
  205. OutputAmbient.X = WWMath::Clamp(OutputAmbient.X);
  206. OutputAmbient.Y = WWMath::Clamp(OutputAmbient.Y);
  207. OutputAmbient.Z = WWMath::Clamp(OutputAmbient.Z);
  208. }
  209. void LightEnvironmentClass::Set_Lighting_LOD_Cutoff(float inten)
  210. {
  211. _LightingLODCutoff = inten;
  212. _LightingLODCutoff2 = _LightingLODCutoff * _LightingLODCutoff;
  213. }
  214. float LightEnvironmentClass::Get_Lighting_LOD_Cutoff(void)
  215. {
  216. return _LightingLODCutoff;
  217. }