lightenvironment.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*
  2. ** Command & Conquer Generals(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:: 2/01/01 5:40p $*
  31. * *
  32. * $Revision:: 3 $*
  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. m_point = false;
  62. switch(light.Get_Type())
  63. {
  64. case LightClass::POINT:
  65. case LightClass::SPOT:
  66. Init_From_Point_Or_Spot_Light(light,object_center);
  67. break;
  68. case LightClass::DIRECTIONAL:
  69. Init_From_Directional_Light(light,object_center);
  70. break;
  71. };
  72. }
  73. void LightEnvironmentClass::InputLightStruct::Init_From_Point_Or_Spot_Light
  74. (
  75. const LightClass & light,
  76. const Vector3 & object_center
  77. )
  78. {
  79. /*
  80. ** Compute the direction vector and the distance to the light
  81. */
  82. Direction = light.Get_Position() - object_center;
  83. float dist = Direction.Length();
  84. if (dist > 0.0f) {
  85. Direction /= dist;
  86. }
  87. /*
  88. ** Compute the attenuation factor
  89. */
  90. double atten_start,atten_end;
  91. light.Get_Far_Attenuation_Range(atten_start,atten_end);
  92. float atten = 1.0f - (dist - atten_start) / (atten_end - atten_start);
  93. atten = WWMath::Clamp(atten,0.0f,1.0f);
  94. if (light.Get_Type() == LightClass::SPOT) {
  95. Vector3 spot_dir;
  96. light.Get_Spot_Direction(spot_dir);
  97. Matrix3D::Rotate_Vector(light.Get_Transform(),spot_dir,&spot_dir);
  98. float spot_angle_cos = light.Get_Spot_Angle_Cos();
  99. atten *= (Vector3::Dot_Product(-spot_dir,Direction) - spot_angle_cos) / (1.0f - spot_angle_cos);
  100. atten = WWMath::Clamp(atten,0.0f,1.0f);
  101. }
  102. /*
  103. ** Compute the ambient and diffuse values. Rejecting the diffuse
  104. ** component and folding it into the ambient component if it is below
  105. ** the LOD cutoff
  106. */
  107. light.Get_Ambient(&Ambient);
  108. light.Get_Diffuse(&Diffuse);
  109. m_point = (light.Get_Type() == LightClass::POINT);
  110. m_center = light.Get_Position();
  111. m_innerRadius = atten_start;
  112. m_outerRadius = atten_end;
  113. m_ambient = Ambient;
  114. m_diffuse = Diffuse;
  115. if (Diffuse.Length2() > _LightingLODCutoff2) {
  116. DiffuseRejected = false;
  117. Ambient *= atten;
  118. Diffuse *= atten;
  119. } else {
  120. DiffuseRejected = true;
  121. Ambient *= atten;
  122. Ambient += atten * DIFFUSE_TO_AMBIENT_FRACTION * Diffuse;
  123. Diffuse.Set(0,0,0);
  124. }
  125. }
  126. void LightEnvironmentClass::InputLightStruct::Init_From_Directional_Light
  127. (
  128. const LightClass & light,
  129. const Vector3 & object_center
  130. )
  131. {
  132. Direction = -light.Get_Transform().Get_Z_Vector();
  133. DiffuseRejected = false;
  134. light.Get_Ambient(&Ambient);
  135. light.Get_Diffuse(&Diffuse);
  136. }
  137. float LightEnvironmentClass::InputLightStruct::Contribution(void)
  138. {
  139. return Diffuse.Length2();
  140. }
  141. /************************************************************************************************
  142. **
  143. ** LightEnvironmentClass::OutputLightStruct Implementation
  144. **
  145. ************************************************************************************************/
  146. void LightEnvironmentClass::OutputLightStruct::Init
  147. (
  148. const InputLightStruct & input,
  149. const Matrix3D & camera_tm
  150. )
  151. {
  152. Diffuse = input.Diffuse;
  153. Matrix3D::Inverse_Rotate_Vector(camera_tm,input.Direction,&Direction);
  154. }
  155. /************************************************************************************************
  156. **
  157. ** LightEnvironmentClass Implementation
  158. **
  159. ************************************************************************************************/
  160. LightEnvironmentClass::LightEnvironmentClass(void) :
  161. LightCount(0),
  162. ObjectCenter(0,0,0),
  163. OutputAmbient(0,0,0)
  164. {
  165. }
  166. LightEnvironmentClass::~LightEnvironmentClass(void)
  167. {
  168. }
  169. void LightEnvironmentClass::Reset(const Vector3 & object_center,const Vector3 & ambient)
  170. {
  171. LightCount = 0;
  172. ObjectCenter = object_center;
  173. OutputAmbient = ambient;
  174. }
  175. void LightEnvironmentClass::Add_Light(const LightClass & light)
  176. {
  177. /*
  178. ** Compute the equivalent directional + ambient light
  179. */
  180. InputLightStruct new_light;
  181. new_light.Init(light,ObjectCenter);
  182. /*
  183. ** Add in the ambient component
  184. */
  185. OutputAmbient += new_light.Ambient;
  186. /*
  187. ** If not rejected, add the directional component to the active lights
  188. */
  189. if (new_light.DiffuseRejected == false || new_light.m_point) {
  190. if (LightCount < MAX_LIGHTS) {
  191. InputLights[LightCount] = new_light;
  192. LightCount++;
  193. } else {
  194. for (int light_index=0; light_index<LightCount; light_index++) {
  195. if (new_light.Contribution() > InputLights[light_index].Contribution()) {
  196. InputLights[light_index] = new_light;
  197. light_index = MAX_LIGHTS;
  198. }
  199. }
  200. }
  201. }
  202. }
  203. void LightEnvironmentClass::Pre_Render_Update(const Matrix3D & camera_tm)
  204. {
  205. /*
  206. ** Transform each light into camera space
  207. ** and add up the ambient effect of each light
  208. */
  209. for (int light_index=0; light_index<LightCount; light_index++) {
  210. OutputLights[light_index].Init(InputLights[light_index],camera_tm);
  211. }
  212. // Clamp ambient.
  213. OutputAmbient.X = WWMath::Clamp(OutputAmbient.X,0.0f,1.0f);
  214. OutputAmbient.Y = WWMath::Clamp(OutputAmbient.Y,0.0f,1.0f);
  215. OutputAmbient.Z = WWMath::Clamp(OutputAmbient.Z,0.0f,1.0f);
  216. }
  217. void LightEnvironmentClass::Set_Lighting_LOD_Cutoff(float inten)
  218. {
  219. _LightingLODCutoff = inten;
  220. _LightingLODCutoff2 = _LightingLODCutoff * _LightingLODCutoff;
  221. }
  222. float LightEnvironmentClass::Get_Lighting_LOD_Cutoff(void)
  223. {
  224. return _LightingLODCutoff;
  225. }