ComputeSH.hx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package hrt.shader;
  2. class ComputeSH extends h3d.shader.ScreenShader {
  3. static var SRC = {
  4. @param var environment : SamplerCube;
  5. @param var width : Int;
  6. @param var cubeDir : Array<Mat3, 6>;
  7. @const var ORDER : Int;
  8. @param var PI = 3.1416;
  9. var shCoefL00 : Float;
  10. var shCoefL1n1: Float;
  11. var shCoefL10 : Float;
  12. var shCoefL11 : Float;
  13. var shCoefL2n2 : Float;
  14. var shCoefL2n1 : Float;
  15. var shCoefL20 : Float;
  16. var shCoefL21 : Float;
  17. var shCoefL22 : Float;
  18. var coefL00Final : Vec3;
  19. var coefL1n1Final: Vec3;
  20. var coefL10Final : Vec3;
  21. var coefL11Final : Vec3;
  22. var coefL2n2Final : Vec3;
  23. var coefL2n1Final : Vec3;
  24. var coefL20Final : Vec3;
  25. var coefL21Final : Vec3;
  26. var coefL22Final : Vec3;
  27. function vertex() {
  28. var position = vec3(input.position.x, input.position.y * flipY, 0);
  29. output.position = vec4(position, 1.0);
  30. }
  31. function evalSH( dir : Vec3 ) {
  32. if (ORDER >= 1){
  33. shCoefL00 = evalCoefL00(dir);
  34. }
  35. if (ORDER >= 2){
  36. shCoefL1n1 = evalCoefL1n1(dir);
  37. shCoefL10 = evalCoefL10(dir);
  38. shCoefL11 = evalCoefL11(dir);
  39. }
  40. if (ORDER >= 3){
  41. shCoefL2n2 = evalCoefL2n2(dir);
  42. shCoefL2n1 = evalCoefL2n1(dir);
  43. shCoefL20 = evalCoefL20(dir);
  44. shCoefL21 = evalCoefL21(dir);
  45. shCoefL22 = evalCoefL22(dir);
  46. }
  47. }
  48. function getDir( u : Float, v : Float, face : Int ) : Vec3 {
  49. var dir = vec3(u, v, 1) * cubeDir[face];
  50. return dir.normalize();
  51. }
  52. function evalCoefL00(dir: Vec3) : Float { return 0.282095; }
  53. function evalCoefL1n1(dir: Vec3) : Float { return -0.488603 * dir.y; }
  54. function evalCoefL10(dir: Vec3) : Float { return 0.488603 * dir.z; }
  55. function evalCoefL11(dir: Vec3) : Float { return -0.488603 * dir.x; }
  56. function evalCoefL2n2(dir: Vec3) : Float { return 1.092548 * dir.y * dir.x; }
  57. function evalCoefL2n1(dir: Vec3) : Float { return -1.092548 * dir.y * dir.z; }
  58. function evalCoefL20(dir: Vec3) : Float { return 0.315392 * (-dir.x * dir.x - dir.y * dir.y + 2.0 * dir.z * dir.z); }
  59. function evalCoefL21(dir: Vec3) : Float { return -1.092548 * dir.x * dir.z; }
  60. function evalCoefL22(dir: Vec3) : Float { return 0.546274 * (dir.x * dir.x - dir.y * dir.y); }
  61. var out : {
  62. position : Vec4,
  63. coefL00 : Vec3,
  64. coefL1n1: Vec3,
  65. coefL10 : Vec3,
  66. coefL11 : Vec3,
  67. coefL2n2 : Vec3,
  68. coefL2n1 : Vec3,
  69. coefL20 : Vec3,
  70. coefL21 : Vec3,
  71. coefL22 : Vec3,
  72. };
  73. function fragment() {
  74. if( ORDER >= 1 ) {
  75. coefL00Final = vec3(0);
  76. }
  77. if( ORDER >= 2 ) {
  78. coefL1n1Final = vec3(0);
  79. coefL10Final = vec3(0);
  80. coefL11Final = vec3(0);
  81. }
  82. if( ORDER >= 3 ) {
  83. coefL2n2Final = vec3(0);
  84. coefL2n1Final = vec3(0);
  85. coefL20Final = vec3(0);
  86. coefL21Final = vec3(0);
  87. coefL22Final = vec3(0);
  88. }
  89. var weightSum = 0.0;
  90. var fWidth : Float = width;
  91. var invWidth : Float = 1.0 / fWidth;
  92. for( f in 0...6 ) {
  93. for( u in 0...width ) {
  94. var fU : Float = (u / fWidth - 0.5) * 2.0;// Texture coordinate U in range [-1 to 1]
  95. fU *= fU;
  96. var uCoord = 2.0 * u * invWidth + invWidth;
  97. for( v in 0...width ) {
  98. var fV : Float = (v / fWidth - 0.5) * 2.0;// Texture coordinate V in range [-1 to 1]
  99. fV *= fV;
  100. var vCoord = 2.0 * v * invWidth + invWidth;
  101. var dir = getDir(uCoord, vCoord, f);// Get direction from center of cube texture to current texel
  102. var diffSolid = 4.0 / ((1.0 + fU + fV) * sqrt(1.0 + fU + fV)); // Scale factor depending on distance from center of the face
  103. weightSum += diffSolid;
  104. var flippedDir = vec3(dir.x, dir.y, -dir.z);
  105. var color : Vec3 = environment.get(-flippedDir).rgb;// Get color from texture
  106. evalSH(dir);// Calculate coefficients of spherical harmonics for current direction
  107. if( ORDER >= 1 ) {
  108. coefL00Final += shCoefL00 * color * diffSolid;
  109. }
  110. if( ORDER >= 2 ) {
  111. coefL1n1Final += shCoefL1n1 * color * diffSolid;
  112. coefL10Final += shCoefL10 * color * diffSolid;
  113. coefL11Final += shCoefL11 * color * diffSolid;
  114. }
  115. if( ORDER >= 3 ) {
  116. coefL2n2Final += shCoefL2n2 * color * diffSolid;
  117. coefL2n1Final += shCoefL2n1 * color * diffSolid;
  118. coefL20Final += shCoefL20 * color * diffSolid;
  119. coefL21Final += shCoefL21 * color * diffSolid;
  120. coefL22Final += shCoefL22 * color * diffSolid;
  121. }
  122. }
  123. }
  124. }
  125. // Final scale for coefficients
  126. var normProj = (4.0 * PI) / weightSum;
  127. if( ORDER >= 1 ) {
  128. out.coefL00 = coefL00Final * normProj;
  129. }
  130. if( ORDER >= 2 ) {
  131. out.coefL1n1 = coefL1n1Final * normProj;
  132. out.coefL10 = coefL10Final * normProj;
  133. out.coefL11 = coefL11Final * normProj;
  134. }
  135. if( ORDER >= 3 ) {
  136. out.coefL2n2 = coefL2n2Final * normProj;
  137. out.coefL2n1 = coefL2n1Final * normProj;
  138. out.coefL20 = coefL20Final * normProj;
  139. out.coefL21 = coefL21Final * normProj;
  140. out.coefL22 = coefL22Final * normProj;
  141. }
  142. }
  143. }
  144. }