/opengles/src/Light.cpp

http://ftk.googlecode.com/ · C++ · 368 lines · 214 code · 92 blank · 62 comment · 36 complexity · 8212d4f1878d570886616afb5b78c9f5 MD5 · raw file

  1. // ==========================================================================
  2. //
  3. // light.cpp Rendering Context Class for 3D Rendering Library
  4. //
  5. // Lightning Related Operations
  6. //
  7. // --------------------------------------------------------------------------
  8. //
  9. // 08-07-2003 Hans-Martin Will initial version
  10. //
  11. // --------------------------------------------------------------------------
  12. //
  13. // Copyright (c) 2004, Hans-Martin Will. All rights reserved.
  14. //
  15. // Redistribution and use in source and binary forms, with or without
  16. // modification, are permitted provided that the following conditions are
  17. // met:
  18. //
  19. // * Redistributions of source code must retain the above copyright
  20. // notice, this list of conditions and the following disclaimer.
  21. // * Redistributions in binary form must reproduce the above copyright
  22. // notice, this list of conditions and the following disclaimer in the
  23. // documentation and/or other materials provided with the distribution.
  24. //
  25. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  26. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  29. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  30. // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  35. // THE POSSIBILITY OF SUCH DAMAGE.
  36. //
  37. // ==========================================================================
  38. #include "stdafx.h"
  39. #include "Light.h"
  40. #include "Material.h"
  41. #include <math.h>
  42. #ifndef M_PI
  43. # define M_PI 3.14159265358979323846
  44. #endif
  45. using namespace EGL;
  46. // ==========================================================================
  47. // class Light
  48. // ==========================================================================
  49. Light :: Light()
  50. : m_AmbientColor(F(0.0f), F(0.0f), F(0.0f), F(1.0f)),
  51. m_DiffuseColor(F(0.0f), F(0.0f), F(0.0f), F(1.0f)),
  52. m_SpecularColor(F(0.0f), F(0.0f), F(0.0f), F(1.0f)),
  53. m_Position(F(0.0f), F(0.0f), F(1.0f), F(0.0f)),
  54. m_SpotDirection(F(0.0f), F(0.0f), F(-1.0f)),
  55. m_NormalizedSpotDirection(F(0.0f), F(0.0f), F(-1.0f)),
  56. m_SpotCutoff(F(180.0f)),
  57. m_ConstantAttenuation(F(1.0f)),
  58. m_LinearAttenuation(0),
  59. m_QuadraticAttenuation(0)
  60. {
  61. }
  62. void Light :: SetAmbientColor(const FractionalColor & color) {
  63. m_AmbientColor = color;
  64. }
  65. void Light :: SetDiffuseColor(const FractionalColor & color) {
  66. m_DiffuseColor = color;
  67. }
  68. void Light :: SetSpecularColor(const FractionalColor & color) {
  69. m_SpecularColor = color;
  70. }
  71. void Light :: SetPosition(const Vec4D & position) {
  72. m_Position = position;
  73. }
  74. void Light :: SetDirection(const Vec3D & direction) {
  75. m_SpotDirection = m_NormalizedSpotDirection = direction;
  76. m_NormalizedSpotDirection.Normalize();
  77. }
  78. void Light :: SetConstantAttenuation(EGL_Fixed attenuation) {
  79. m_ConstantAttenuation = attenuation;
  80. }
  81. void Light :: SetLinearAttenuation(EGL_Fixed attenuation) {
  82. m_LinearAttenuation = attenuation;
  83. }
  84. void Light :: SetQuadraticAttenuation(EGL_Fixed attenuation) {
  85. m_QuadraticAttenuation = attenuation;
  86. }
  87. void Light :: SetSpotExponent(EGL_Fixed exponent) {
  88. m_SpotExponent = exponent;
  89. }
  90. void Light :: SetSpotCutoff(EGL_Fixed cutoff) {
  91. m_SpotCutoff = cutoff;
  92. EGL_Fixed angle = EGL_Mul(cutoff, EGL_FixedFromFloat(static_cast<float>(M_PI) / 180.0f));
  93. m_CosineSpotCutoff = EGL_Cos(angle);
  94. }
  95. void Light :: InitWithMaterial(const Material& material) {
  96. m_EffectiveAmbientColor = material.GetAmbientColor() * m_AmbientColor;
  97. m_EffectiveDiffuseColor = material.GetDiffuseColor() * m_DiffuseColor;
  98. m_EffectiveSpecularColor = material.GetSpecularColor() * m_SpecularColor;
  99. }
  100. // --------------------------------------------------------------------------
  101. // One-sided lightning calculation
  102. // --------------------------------------------------------------------------
  103. #define EGL_Sqrt EGL_FastSqrt
  104. void Light :: AccumulateLight(const Vec4D& vertexCoords, const Vec3D& vertexNormal,
  105. const Material& currMaterial,
  106. FractionalColor& result) {
  107. Vec3D vp_li = EGL_Direction(vertexCoords, m_Position);
  108. EGL_Fixed sqLength = vp_li.LengthSq(); // keep squared length around for later
  109. vp_li.Normalize(); // can optimizer factor this out?
  110. EGL_Fixed att = EGL_ONE;
  111. if (m_SpotCutoff != EGL_FixedFromInt(180)) {
  112. EGL_Fixed cosine = -(vp_li * m_NormalizedSpotDirection);
  113. if (cosine < m_CosineSpotCutoff) {
  114. return;
  115. } else {
  116. att = EGL_Power(cosine, m_SpotExponent);
  117. }
  118. }
  119. if (m_Position.w() != 0) {
  120. EGL_Fixed length = EGL_Sqrt(sqLength);
  121. att = EGL_Mul(att, EGL_Inverse(m_ConstantAttenuation +
  122. EGL_Mul(m_LinearAttenuation, length) +
  123. EGL_Mul(m_QuadraticAttenuation, sqLength)));
  124. }
  125. result.Accumulate(currMaterial.GetAmbientColor() * m_AmbientColor, att);
  126. EGL_Fixed diffuseFactor = vertexNormal * vp_li;
  127. if (diffuseFactor > 0) {
  128. result.Accumulate(currMaterial.GetDiffuseColor() * m_DiffuseColor, EGL_Mul(diffuseFactor, att));
  129. // add specular component
  130. // calculate h^
  131. Vec3D h = vp_li + Vec3D(0, 0, EGL_ONE);
  132. h.Normalize();
  133. EGL_Fixed specularFactor = vertexNormal * h;
  134. if (specularFactor > 0)
  135. result.Accumulate(currMaterial.GetSpecularColor() * m_SpecularColor,
  136. EGL_Mul(att, EGL_Power(specularFactor, currMaterial.GetSpecularExponent())));
  137. }
  138. }
  139. void Light :: AccumulateLight(const Vec4D& vertexCoords, const Vec3D& vertexNormal,
  140. const Material& currMaterial,
  141. const FractionalColor & currentColor,
  142. FractionalColor& result) {
  143. Vec3D vp_li = EGL_Direction(vertexCoords, m_Position);
  144. EGL_Fixed sqLength = vp_li.LengthSq(); // keep squared length around for later
  145. vp_li.Normalize(); // can optimizer factor this out?
  146. EGL_Fixed att = EGL_ONE;
  147. if (m_SpotCutoff != EGL_FixedFromInt(180)) {
  148. EGL_Fixed cosine = -(vp_li * m_NormalizedSpotDirection);
  149. if (cosine < m_CosineSpotCutoff) {
  150. return;
  151. } else {
  152. att = EGL_Power(cosine, m_SpotExponent);
  153. }
  154. }
  155. if (m_Position.w() != 0) {
  156. EGL_Fixed length = EGL_Sqrt(sqLength);
  157. att = EGL_Mul(att, EGL_Inverse(m_ConstantAttenuation +
  158. EGL_Mul(m_LinearAttenuation, length) +
  159. EGL_Mul(m_QuadraticAttenuation, sqLength)));
  160. }
  161. result.Accumulate(currMaterial.GetAmbientColor() * m_AmbientColor, att);
  162. EGL_Fixed diffuseFactor = vertexNormal * vp_li;
  163. if (diffuseFactor > 0) {
  164. result.Accumulate(currentColor * m_DiffuseColor, EGL_Mul(diffuseFactor, att));
  165. // add specular component
  166. // calculate h^
  167. Vec3D h = vp_li + Vec3D(0, 0, EGL_ONE);
  168. h.Normalize();
  169. EGL_Fixed specularFactor = vertexNormal * h;
  170. if (specularFactor > 0)
  171. result.Accumulate(currMaterial.GetSpecularColor() * m_SpecularColor,
  172. EGL_Mul(att, EGL_Power(specularFactor, currMaterial.GetSpecularExponent())));
  173. }
  174. }
  175. // --------------------------------------------------------------------------
  176. // Two-sided lightning calculation
  177. // --------------------------------------------------------------------------
  178. void Light :: AccumulateLight2(const Vec4D& vertexCoords, const Vec3D& vertexNormal,
  179. const Material& currMaterial,
  180. FractionalColor& result,
  181. FractionalColor& result2) {
  182. Vec3D vp_li = EGL_Direction(vertexCoords, m_Position);
  183. EGL_Fixed sqLength = vp_li.LengthSq(); // keep squared length around for later
  184. vp_li.Normalize(); // can optimizer factor this out?
  185. //either front or back color have to be enabled...
  186. // if (diffuseFactor > 0) {
  187. EGL_Fixed att = EGL_ONE;
  188. if (m_SpotCutoff != EGL_FixedFromInt(180)) {
  189. EGL_Fixed cosine = -(vp_li * m_NormalizedSpotDirection);
  190. if (cosine < m_CosineSpotCutoff) {
  191. return;
  192. } else {
  193. att = EGL_Power(cosine, m_SpotExponent);
  194. }
  195. }
  196. if (m_Position.w() != 0) {
  197. EGL_Fixed length = EGL_Sqrt(sqLength);
  198. att = EGL_Mul(att, EGL_Inverse(m_ConstantAttenuation +
  199. EGL_Mul(m_LinearAttenuation, length) +
  200. EGL_Mul(m_QuadraticAttenuation, sqLength)));
  201. }
  202. result.Accumulate(currMaterial.GetAmbientColor() * m_AmbientColor, att);
  203. result2.Accumulate(currMaterial.GetAmbientColor() * m_AmbientColor, att);
  204. EGL_Fixed diffuseFactor = vertexNormal * vp_li;
  205. if (diffuseFactor > 0) {
  206. result.Accumulate(currMaterial.GetDiffuseColor() * m_DiffuseColor, EGL_Mul(diffuseFactor, att));
  207. // add specular component
  208. // calculate h^
  209. Vec3D h = vp_li + Vec3D(0, 0, EGL_ONE);
  210. h.Normalize();
  211. EGL_Fixed specularFactor = vertexNormal * h;
  212. if (specularFactor > 0)
  213. result.Accumulate(currMaterial.GetSpecularColor() * m_SpecularColor,
  214. EGL_Mul(att, EGL_Power(specularFactor, currMaterial.GetSpecularExponent())));
  215. } else {
  216. result2.Accumulate(currMaterial.GetDiffuseColor() * m_DiffuseColor, EGL_Mul(-diffuseFactor, att));
  217. Vec3D h = vp_li + Vec3D(0, 0, EGL_ONE);
  218. h.Normalize();
  219. EGL_Fixed specularFactor = vertexNormal * h;
  220. if (specularFactor < 0)
  221. result2.Accumulate(currMaterial.GetSpecularColor() * m_SpecularColor,
  222. EGL_Mul(att, EGL_Power(-specularFactor, currMaterial.GetSpecularExponent())));
  223. }
  224. // }
  225. }
  226. void Light :: AccumulateLight2(const Vec4D& vertexCoords, const Vec3D& vertexNormal,
  227. const Material& currMaterial,
  228. const FractionalColor& currentColor,
  229. FractionalColor& result,
  230. FractionalColor& result2) {
  231. Vec3D vp_li = EGL_Direction(vertexCoords, m_Position);
  232. EGL_Fixed sqLength = vp_li.LengthSq(); // keep squared length around for later
  233. vp_li.Normalize(); // can optimizer factor this out?
  234. //either front or back color have to be enabled...
  235. // if (diffuseFactor > 0) {
  236. EGL_Fixed att = EGL_ONE;
  237. if (m_SpotCutoff != EGL_FixedFromInt(180)) {
  238. EGL_Fixed cosine = -(vp_li * m_NormalizedSpotDirection);
  239. if (cosine < m_CosineSpotCutoff) {
  240. return;
  241. } else {
  242. att = EGL_Power(cosine, m_SpotExponent);
  243. }
  244. }
  245. if (m_Position.w() != 0) {
  246. EGL_Fixed length = EGL_Sqrt(sqLength);
  247. att = EGL_Mul(att, EGL_Inverse(m_ConstantAttenuation +
  248. EGL_Mul(m_LinearAttenuation, length) +
  249. EGL_Mul(m_QuadraticAttenuation, sqLength)));
  250. }
  251. result.Accumulate(currMaterial.GetAmbientColor() * m_AmbientColor, att);
  252. result2.Accumulate(currMaterial.GetAmbientColor() * m_AmbientColor, att);
  253. EGL_Fixed diffuseFactor = vertexNormal * vp_li;
  254. if (diffuseFactor > 0) {
  255. result.Accumulate(currentColor * m_DiffuseColor, EGL_Mul(diffuseFactor, att));
  256. // add specular component
  257. // calculate h^
  258. Vec3D h = vp_li + Vec3D(0, 0, EGL_ONE);
  259. h.Normalize();
  260. EGL_Fixed specularFactor = vertexNormal * h;
  261. if (specularFactor > 0)
  262. result.Accumulate(currMaterial.GetSpecularColor() * m_SpecularColor,
  263. EGL_Mul(att, EGL_Power(specularFactor, currMaterial.GetSpecularExponent())));
  264. } else {
  265. result2.Accumulate(currentColor * m_DiffuseColor, EGL_Mul(-diffuseFactor, att));
  266. // add specular component
  267. // calculate h^
  268. Vec3D h = vp_li + Vec3D(0, 0, EGL_ONE);
  269. h.Normalize();
  270. EGL_Fixed specularFactor = vertexNormal * h;
  271. if (specularFactor < 0)
  272. result2.Accumulate(currMaterial.GetSpecularColor() * m_SpecularColor,
  273. EGL_Mul(att, EGL_Power(-specularFactor, currMaterial.GetSpecularExponent())));
  274. }
  275. // }
  276. }