babylon.sphericalPolynomial.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. module BABYLON {
  2. /**
  3. * Class representing spherical polynomial coefficients to the 3rd degree
  4. */
  5. export class SphericalPolynomial {
  6. /**
  7. * The x coefficients of the spherical polynomial
  8. */
  9. public x: Vector3 = Vector3.Zero();
  10. /**
  11. * The y coefficients of the spherical polynomial
  12. */
  13. public y: Vector3 = Vector3.Zero();
  14. /**
  15. * The z coefficients of the spherical polynomial
  16. */
  17. public z: Vector3 = Vector3.Zero();
  18. /**
  19. * The xx coefficients of the spherical polynomial
  20. */
  21. public xx: Vector3 = Vector3.Zero();
  22. /**
  23. * The yy coefficients of the spherical polynomial
  24. */
  25. public yy: Vector3 = Vector3.Zero();
  26. /**
  27. * The zz coefficients of the spherical polynomial
  28. */
  29. public zz: Vector3 = Vector3.Zero();
  30. /**
  31. * The xy coefficients of the spherical polynomial
  32. */
  33. public xy: Vector3 = Vector3.Zero();
  34. /**
  35. * The yz coefficients of the spherical polynomial
  36. */
  37. public yz: Vector3 = Vector3.Zero();
  38. /**
  39. * The zx coefficients of the spherical polynomial
  40. */
  41. public zx: Vector3 = Vector3.Zero();
  42. /**
  43. * Adds an ambient color to the spherical polynomial
  44. * @param color the color to add
  45. */
  46. public addAmbient(color: Color3): void {
  47. var colorVector = new Vector3(color.r, color.g, color.b);
  48. this.xx = this.xx.add(colorVector);
  49. this.yy = this.yy.add(colorVector);
  50. this.zz = this.zz.add(colorVector);
  51. }
  52. /**
  53. * Scales the spherical polynomial by the given amount
  54. * @param scale the amount to scale
  55. */
  56. public scale(scale: number)
  57. {
  58. this.x = this.x.scale(scale);
  59. this.y = this.y.scale(scale);
  60. this.z = this.z.scale(scale);
  61. this.xx = this.xx.scale(scale);
  62. this.yy = this.yy.scale(scale);
  63. this.zz = this.zz.scale(scale);
  64. this.yz = this.yz.scale(scale);
  65. this.zx = this.zx.scale(scale);
  66. this.xy = this.xy.scale(scale);
  67. }
  68. /**
  69. * Gets the spherical polynomial from harmonics
  70. * @param harmonics the spherical harmonics
  71. * @returns the spherical polynomial
  72. */
  73. public static FromHarmonics(harmonics: SphericalHarmonics): SphericalPolynomial {
  74. var result = new SphericalPolynomial();
  75. result.x = harmonics.l11.scale(1.02333);
  76. result.y = harmonics.l1_1.scale(1.02333);
  77. result.z = harmonics.l10.scale(1.02333);
  78. result.xx = harmonics.l00.scale(0.886277).subtract(harmonics.l20.scale(0.247708)).add(harmonics.lL22.scale(0.429043));
  79. result.yy = harmonics.l00.scale(0.886277).subtract(harmonics.l20.scale(0.247708)).subtract(harmonics.lL22.scale(0.429043));
  80. result.zz = harmonics.l00.scale(0.886277).add(harmonics.l20.scale(0.495417));
  81. result.yz = harmonics.l2_1.scale(0.858086);
  82. result.zx = harmonics.l21.scale(0.858086);
  83. result.xy = harmonics.l2_2.scale(0.858086);
  84. result.scale(1.0 / Math.PI);
  85. return result;
  86. }
  87. /**
  88. * Constructs a spherical polynomial from an array.
  89. * @param data defines the 9x3 coefficients (x, y, z, xx, yy, zz, yz, zx, xy)
  90. * @returns the spherical polynomial
  91. */
  92. public static FromArray(data: ArrayLike<ArrayLike<number>>): SphericalPolynomial {
  93. const sp = new SphericalPolynomial();
  94. Vector3.FromArrayToRef(data[0], 0, sp.x);
  95. Vector3.FromArrayToRef(data[1], 0, sp.y);
  96. Vector3.FromArrayToRef(data[2], 0, sp.z);
  97. Vector3.FromArrayToRef(data[3], 0, sp.xx);
  98. Vector3.FromArrayToRef(data[4], 0, sp.yy);
  99. Vector3.FromArrayToRef(data[5], 0, sp.zz);
  100. Vector3.FromArrayToRef(data[6], 0, sp.yz);
  101. Vector3.FromArrayToRef(data[7], 0, sp.zx);
  102. Vector3.FromArrayToRef(data[8], 0, sp.xy);
  103. return sp;
  104. }
  105. }
  106. /**
  107. * Class representing spherical harmonics coefficients to the 3rd degree
  108. */
  109. export class SphericalHarmonics {
  110. /**
  111. * The l0,0 coefficients of the spherical harmonics
  112. */
  113. public l00: Vector3 = Vector3.Zero();
  114. /**
  115. * The l1,-1 coefficients of the spherical harmonics
  116. */
  117. public l1_1: Vector3 = Vector3.Zero();
  118. /**
  119. * The l1,0 coefficients of the spherical harmonics
  120. */
  121. public l10: Vector3 = Vector3.Zero();
  122. /**
  123. * The l1,1 coefficients of the spherical harmonics
  124. */
  125. public l11: Vector3 = Vector3.Zero();
  126. /**
  127. * The l2,-2 coefficients of the spherical harmonics
  128. */
  129. public l2_2: Vector3 = Vector3.Zero();
  130. /**
  131. * The l2,-1 coefficients of the spherical harmonics
  132. */
  133. public l2_1: Vector3 = Vector3.Zero();
  134. /**
  135. * The l2,0 coefficients of the spherical harmonics
  136. */
  137. public l20: Vector3 = Vector3.Zero();
  138. /**
  139. * The l2,1 coefficients of the spherical harmonics
  140. */
  141. public l21: Vector3 = Vector3.Zero();
  142. /**
  143. * The l2,2 coefficients of the spherical harmonics
  144. */
  145. public lL22: Vector3 = Vector3.Zero();
  146. /**
  147. * Adds a light to the spherical harmonics
  148. * @param direction the direction of the light
  149. * @param color the color of the light
  150. * @param deltaSolidAngle the delta solid angle of the light
  151. */
  152. public addLight(direction: Vector3, color: Color3, deltaSolidAngle: number): void {
  153. var colorVector = new Vector3(color.r, color.g, color.b);
  154. var c = colorVector.scale(deltaSolidAngle);
  155. this.l00 = this.l00.add(c.scale(0.282095));
  156. this.l1_1 = this.l1_1.add(c.scale(0.488603 * direction.y));
  157. this.l10 = this.l10.add(c.scale(0.488603 * direction.z));
  158. this.l11 = this.l11.add(c.scale(0.488603 * direction.x));
  159. this.l2_2 = this.l2_2.add(c.scale(1.092548 * direction.x * direction.y));
  160. this.l2_1 = this.l2_1.add(c.scale(1.092548 * direction.y * direction.z));
  161. this.l21 = this.l21.add(c.scale(1.092548 * direction.x * direction.z));
  162. this.l20 = this.l20.add(c.scale(0.315392 * (3.0 * direction.z * direction.z - 1.0)));
  163. this.lL22 = this.lL22.add(c.scale(0.546274 * (direction.x * direction.x - direction.y * direction.y)));
  164. }
  165. /**
  166. * Scales the spherical harmonics by the given amount
  167. * @param scale the amount to scale
  168. */
  169. public scale(scale: number): void {
  170. this.l00 = this.l00.scale(scale);
  171. this.l1_1 = this.l1_1.scale(scale);
  172. this.l10 = this.l10.scale(scale);
  173. this.l11 = this.l11.scale(scale);
  174. this.l2_2 = this.l2_2.scale(scale);
  175. this.l2_1 = this.l2_1.scale(scale);
  176. this.l20 = this.l20.scale(scale);
  177. this.l21 = this.l21.scale(scale);
  178. this.lL22 = this.lL22.scale(scale);
  179. }
  180. /**
  181. * Convert from incident radiance (Li) to irradiance (E) by applying convolution with the cosine-weighted hemisphere.
  182. *
  183. * ```
  184. * E_lm = A_l * L_lm
  185. * ```
  186. *
  187. * In spherical harmonics this convolution amounts to scaling factors for each frequency band.
  188. * This corresponds to equation 5 in "An Efficient Representation for Irradiance Environment Maps", where
  189. * the scaling factors are given in equation 9.
  190. */
  191. public convertIncidentRadianceToIrradiance(): void
  192. {
  193. // Constant (Band 0)
  194. this.l00 = this.l00.scale(3.141593);
  195. // Linear (Band 1)
  196. this.l1_1 = this.l1_1.scale(2.094395);
  197. this.l10 = this.l10.scale(2.094395);
  198. this.l11 = this.l11.scale(2.094395);
  199. // Quadratic (Band 2)
  200. this.l2_2 = this.l2_2.scale(0.785398);
  201. this.l2_1 = this.l2_1.scale(0.785398);
  202. this.l20 = this.l20.scale(0.785398);
  203. this.l21 = this.l21.scale(0.785398);
  204. this.lL22 = this.lL22.scale(0.785398);
  205. }
  206. /**
  207. * Convert from irradiance to outgoing radiance for Lambertian BDRF, suitable for efficient shader evaluation.
  208. *
  209. * ```
  210. * L = (1/pi) * E * rho
  211. * ```
  212. *
  213. * This is done by an additional scale by 1/pi, so is a fairly trivial operation but important conceptually.
  214. */
  215. public convertIrradianceToLambertianRadiance(): void
  216. {
  217. this.scale(1.0 / Math.PI);
  218. // The resultant SH now represents outgoing radiance, so includes the Lambert 1/pi normalisation factor but without albedo (rho) applied
  219. // (The pixel shader must apply albedo after texture fetches, etc).
  220. }
  221. /**
  222. * Gets the spherical harmonics from polynomial
  223. * @param polynomial the spherical polynomial
  224. * @returns the spherical harmonics
  225. */
  226. public static FromPolynomial(polynomial: SphericalPolynomial): SphericalHarmonics
  227. {
  228. var result = new SphericalHarmonics();
  229. result.l00 = polynomial.xx.scale(0.376127).add(polynomial.yy.scale(0.376127)).add(polynomial.zz.scale(0.376126));
  230. result.l1_1 = polynomial.y.scale(0.977204);
  231. result.l10 = polynomial.z.scale(0.977204);
  232. result.l11 = polynomial.x.scale(0.977204);
  233. result.l2_2 = polynomial.xy.scale(1.16538);
  234. result.l2_1 = polynomial.yz.scale(1.16538);
  235. result.l20 = polynomial.zz.scale(1.34567).subtract(polynomial.xx.scale(0.672834)).subtract(polynomial.yy.scale(0.672834));
  236. result.l21 = polynomial.zx.scale(1.16538);
  237. result.lL22 = polynomial.xx.scale(1.16538).subtract(polynomial.yy.scale(1.16538));
  238. result.scale(Math.PI);
  239. return result;
  240. }
  241. /**
  242. * Constructs a spherical harmonics from an array.
  243. * @param data defines the 9x3 coefficients (l00, l1-1, l10, l11, l2-2, l2-1, l20, l21, l22)
  244. * @returns the spherical harmonics
  245. */
  246. public static FromArray(data: ArrayLike<ArrayLike<number>>): SphericalHarmonics {
  247. const sh = new SphericalHarmonics();
  248. Vector3.FromArrayToRef(data[0], 0, sh.l00);
  249. Vector3.FromArrayToRef(data[1], 0, sh.l1_1);
  250. Vector3.FromArrayToRef(data[2], 0, sh.l10);
  251. Vector3.FromArrayToRef(data[3], 0, sh.l11);
  252. Vector3.FromArrayToRef(data[4], 0, sh.l2_2);
  253. Vector3.FromArrayToRef(data[5], 0, sh.l2_1);
  254. Vector3.FromArrayToRef(data[6], 0, sh.l20);
  255. Vector3.FromArrayToRef(data[7], 0, sh.l21);
  256. Vector3.FromArrayToRef(data[8], 0, sh.lL22);
  257. return sh;
  258. }
  259. }
  260. }