LightProbeGenerator.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /**
  2. * @author WestLangley / http://github.com/WestLangley
  3. */
  4. THREE.LightProbeGenerator = {
  5. fromAmbientLight: function ( light ) {
  6. var color = light.color;
  7. var intensity = light.intensity;
  8. var sh = new THREE.SphericalHarmonics3();
  9. // without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );
  10. sh.coefficients[ 0 ].set( color.r, color.g, color.b ).multiplyScalar( 2 * Math.sqrt( Math.PI ) );
  11. return new THREE.LightProbe( sh, intensity );
  12. },
  13. fromHemisphereLight: function ( light ) {
  14. // up-direction hardwired
  15. // up-direction hardwired
  16. var color1 = light.color;
  17. var color2 = light.groundColor;
  18. var sky = new THREE.Vector3( color1.r, color1.g, color1.b );
  19. var ground = new THREE.Vector3( color2.r, color2.g, color2.b );
  20. var intensity = light.intensity;
  21. // without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );
  22. var c0 = Math.sqrt( Math.PI );
  23. var c1 = c0 * Math.sqrt( 0.75 );
  24. var sh = new THREE.SphericalHarmonics3();
  25. sh.coefficients[ 0 ].copy( sky ).add( ground ).multiplyScalar( c0 );
  26. sh.coefficients[ 1 ].copy( sky ).sub( ground ).multiplyScalar( c1 );
  27. return new THREE.LightProbe( sh, intensity );
  28. },
  29. // https://www.ppsloan.org/publications/StupidSH36.pdf
  30. fromCubeTexture: function ( cubeTexture ) {
  31. var norm, lengthSq, weight, totalWeight = 0;
  32. var coord = new THREE.Vector3();
  33. var dir = new THREE.Vector3();
  34. var color = new THREE.Color();
  35. var shBasis = [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
  36. var sh = new THREE.SphericalHarmonics3();
  37. var shCoefficients = sh.coefficients;
  38. for ( var faceIndex = 0; faceIndex < 6; faceIndex ++ ) {
  39. var image = cubeTexture.image[ faceIndex ];
  40. var width = image.width;
  41. var height = image.height;
  42. var canvas = document.createElement( 'canvas' );
  43. canvas.width = width;
  44. canvas.height = height;
  45. var context = canvas.getContext( '2d' );
  46. context.drawImage( image, 0, 0, width, height );
  47. var imageData = context.getImageData( 0, 0, width, height );
  48. var data = imageData.data;
  49. var imageWidth = imageData.width; // assumed to be square
  50. var pixelSize = 2 / imageWidth;
  51. for ( var i = 0, il = data.length; i < il; i += 4 ) { // RGBA assumed
  52. // pixel color
  53. color.setRGB( data[ i ] / 255, data[ i + 1 ] / 255, data[ i + 2 ] / 255 );
  54. // convert to linear color space
  55. color.copySRGBToLinear( color );
  56. // pixel coordinate on unit cube
  57. var pixelIndex = i / 4;
  58. var col = - 1 + ( pixelIndex % imageWidth + 0.5 ) * pixelSize;
  59. var row = 1 - ( Math.floor( pixelIndex / imageWidth ) + 0.5 ) * pixelSize;
  60. switch ( faceIndex ) {
  61. case 0: coord.set( - 1, row, - col ); break;
  62. case 1: coord.set( 1, row, col ); break;
  63. case 2: coord.set( - col, 1, - row ); break;
  64. case 3: coord.set( - col, - 1, row ); break;
  65. case 4: coord.set( - col, row, 1 ); break;
  66. case 5: coord.set( col, row, - 1 ); break;
  67. }
  68. // weight assigned to this pixel
  69. lengthSq = coord.lengthSq();
  70. weight = 4 / ( Math.sqrt( lengthSq ) * lengthSq );
  71. totalWeight += weight;
  72. // direction vector to this pixel
  73. dir.copy( coord ).normalize();
  74. // evaluate SH basis functions in direction dir
  75. THREE.SphericalHarmonics3.getBasisAt( dir, shBasis );
  76. // accummuulate
  77. for ( var j = 0; j < 9; j ++ ) {
  78. shCoefficients[ j ].x += shBasis[ j ] * color.r * weight;
  79. shCoefficients[ j ].y += shBasis[ j ] * color.g * weight;
  80. shCoefficients[ j ].z += shBasis[ j ] * color.b * weight;
  81. }
  82. }
  83. }
  84. // normalize
  85. norm = ( 4 * Math.PI ) / totalWeight;
  86. for ( var j = 0; j < 9; j ++ ) {
  87. shCoefficients[ j ].x *= norm;
  88. shCoefficients[ j ].y *= norm;
  89. shCoefficients[ j ].z *= norm;
  90. }
  91. return new THREE.LightProbe( sh );
  92. }
  93. };