EquirectangularToCubeGenerator.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /**
  2. * @author Richard M. / https://github.com/richardmonette
  3. * @author WestLangley / http://github.com/WestLangley
  4. */
  5. import {
  6. BackSide,
  7. BoxBufferGeometry,
  8. CubeCamera,
  9. Mesh,
  10. NoBlending,
  11. PerspectiveCamera,
  12. Scene,
  13. ShaderMaterial,
  14. UniformsUtils,
  15. WebGLRenderTargetCube
  16. } from "../../../build/three.module.js";
  17. var CubemapGenerator = function ( renderer ) {
  18. this.renderer = renderer;
  19. };
  20. CubemapGenerator.prototype.fromEquirectangular = function ( texture, options ) {
  21. options = options || {};
  22. var scene = new Scene();
  23. var shader = {
  24. uniforms: {
  25. tEquirect: { value: null },
  26. },
  27. vertexShader:
  28. `
  29. varying vec3 vWorldDirection;
  30. //include <common>
  31. vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
  32. return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
  33. }
  34. void main() {
  35. vWorldDirection = transformDirection( position, modelMatrix );
  36. #include <begin_vertex>
  37. #include <project_vertex>
  38. }
  39. `,
  40. fragmentShader:
  41. `
  42. uniform sampler2D tEquirect;
  43. varying vec3 vWorldDirection;
  44. //include <common>
  45. #define RECIPROCAL_PI 0.31830988618
  46. #define RECIPROCAL_PI2 0.15915494
  47. void main() {
  48. vec3 direction = normalize( vWorldDirection );
  49. vec2 sampleUV;
  50. sampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;
  51. sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;
  52. gl_FragColor = texture2D( tEquirect, sampleUV );
  53. }
  54. `
  55. };
  56. var material = new ShaderMaterial( {
  57. type: 'CubemapFromEquirect',
  58. uniforms: UniformsUtils.clone( shader.uniforms ),
  59. vertexShader: shader.vertexShader,
  60. fragmentShader: shader.fragmentShader,
  61. side: BackSide,
  62. blending: NoBlending
  63. } );
  64. material.uniforms.tEquirect.value = texture;
  65. var mesh = new Mesh( new BoxBufferGeometry( 5, 5, 5 ), material );
  66. scene.add( mesh );
  67. var resolution = options.resolution || 512;
  68. var params = {
  69. type: texture.type,
  70. format: texture.format,
  71. encoding: texture.encoding,
  72. generateMipmaps: ( options.generateMipmaps !== undefined ) ? options.generateMipmaps : texture.generateMipmaps,
  73. minFilter: ( options.minFilter !== undefined ) ? options.minFilter : texture.minFilter,
  74. magFilter: ( options.magFilter !== undefined ) ? options.magFilter : texture.magFilter
  75. };
  76. var camera = new CubeCamera( 1, 10, resolution, params );
  77. camera.update( this.renderer, scene );
  78. mesh.geometry.dispose();
  79. mesh.material.dispose();
  80. return camera.renderTarget;
  81. };
  82. //
  83. var EquirectangularToCubeGenerator = ( function () {
  84. var camera = new PerspectiveCamera( 90, 1, 0.1, 10 );
  85. var scene = new Scene();
  86. var boxMesh = new Mesh( new BoxBufferGeometry( 1, 1, 1 ), getShader() );
  87. boxMesh.material.side = BackSide;
  88. scene.add( boxMesh );
  89. var EquirectangularToCubeGenerator = function ( sourceTexture, options ) {
  90. options = options || {};
  91. this.sourceTexture = sourceTexture;
  92. this.resolution = options.resolution || 512;
  93. this.views = [
  94. { t: [ 1, 0, 0 ], u: [ 0, - 1, 0 ] },
  95. { t: [ - 1, 0, 0 ], u: [ 0, - 1, 0 ] },
  96. { t: [ 0, 1, 0 ], u: [ 0, 0, 1 ] },
  97. { t: [ 0, - 1, 0 ], u: [ 0, 0, - 1 ] },
  98. { t: [ 0, 0, 1 ], u: [ 0, - 1, 0 ] },
  99. { t: [ 0, 0, - 1 ], u: [ 0, - 1, 0 ] },
  100. ];
  101. var params = {
  102. format: options.format || this.sourceTexture.format,
  103. magFilter: this.sourceTexture.magFilter,
  104. minFilter: this.sourceTexture.minFilter,
  105. type: options.type || this.sourceTexture.type,
  106. generateMipmaps: this.sourceTexture.generateMipmaps,
  107. anisotropy: this.sourceTexture.anisotropy,
  108. encoding: this.sourceTexture.encoding
  109. };
  110. this.renderTarget = new WebGLRenderTargetCube( this.resolution, this.resolution, params );
  111. };
  112. EquirectangularToCubeGenerator.prototype = {
  113. constructor: EquirectangularToCubeGenerator,
  114. update: function ( renderer ) {
  115. var currentRenderTarget = renderer.getRenderTarget();
  116. boxMesh.material.uniforms.equirectangularMap.value = this.sourceTexture;
  117. for ( var i = 0; i < 6; i ++ ) {
  118. var v = this.views[ i ];
  119. camera.position.set( 0, 0, 0 );
  120. camera.up.set( v.u[ 0 ], v.u[ 1 ], v.u[ 2 ] );
  121. camera.lookAt( v.t[ 0 ], v.t[ 1 ], v.t[ 2 ] );
  122. renderer.setRenderTarget( this.renderTarget, i );
  123. renderer.clear();
  124. renderer.render( scene, camera );
  125. }
  126. renderer.setRenderTarget( currentRenderTarget );
  127. return this.renderTarget.texture;
  128. },
  129. dispose: function () {
  130. this.renderTarget.dispose();
  131. }
  132. };
  133. function getShader() {
  134. var shaderMaterial = new ShaderMaterial( {
  135. uniforms: {
  136. "equirectangularMap": { value: null },
  137. },
  138. vertexShader:
  139. "varying vec3 localPosition;\n\
  140. \n\
  141. void main() {\n\
  142. localPosition = position;\n\
  143. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
  144. }",
  145. fragmentShader:
  146. "#include <common>\n\
  147. varying vec3 localPosition;\n\
  148. uniform sampler2D equirectangularMap;\n\
  149. \n\
  150. vec2 EquirectangularSampleUV(vec3 v) {\n\
  151. vec2 uv = vec2(atan(v.z, v.x), asin(v.y));\n\
  152. uv *= vec2(0.1591, 0.3183); // inverse atan\n\
  153. uv += 0.5;\n\
  154. return uv;\n\
  155. }\n\
  156. \n\
  157. void main() {\n\
  158. vec2 uv = EquirectangularSampleUV(normalize(localPosition));\n\
  159. gl_FragColor = texture2D(equirectangularMap, uv);\n\
  160. }",
  161. blending: NoBlending
  162. } );
  163. shaderMaterial.type = 'EquirectangularToCubeGenerator';
  164. return shaderMaterial;
  165. }
  166. return EquirectangularToCubeGenerator;
  167. } )();
  168. export { CubemapGenerator, EquirectangularToCubeGenerator };