CubeMapNode.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. import TempNode from '../core/TempNode.js';
  2. import { addNodeClass } from '../core/Node.js';
  3. import { NodeUpdateType } from '../core/constants.js';
  4. import { nodeProxy } from '../shadernode/ShaderNode.js';
  5. import { CubeTexture } from '../../textures/CubeTexture.js';
  6. import { cubeTexture } from '../accessors/CubeTextureNode.js';
  7. import CubeRenderTarget from '../../renderers/common/CubeRenderTarget.js';
  8. import { CubeReflectionMapping, CubeRefractionMapping, EquirectangularReflectionMapping, EquirectangularRefractionMapping } from '../../constants.js';
  9. const _cache = new WeakMap();
  10. class CubeMapNode extends TempNode {
  11. constructor( envNode ) {
  12. super( 'vec3' );
  13. this.envNode = envNode;
  14. this._cubeTexture = null;
  15. this._cubeTextureNode = cubeTexture();
  16. const defaultTexture = new CubeTexture();
  17. defaultTexture.isRenderTargetTexture = true;
  18. this._defaultTexture = defaultTexture;
  19. this.updateBeforeType = NodeUpdateType.RENDER;
  20. }
  21. updateBefore( frame ) {
  22. const { renderer, material } = frame;
  23. const envNode = this.envNode;
  24. if ( envNode.isTextureNode || envNode.isMaterialReferenceNode ) {
  25. const texture = ( envNode.isTextureNode ) ? envNode.value : material[ envNode.property ];
  26. if ( texture && texture.isTexture ) {
  27. const mapping = texture.mapping;
  28. if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) {
  29. // check for converted cubemap map
  30. if ( _cache.has( texture ) ) {
  31. const cubeMap = _cache.get( texture );
  32. mapTextureMapping( cubeMap, texture.mapping );
  33. this._cubeTexture = cubeMap;
  34. } else {
  35. // create cube map from equirectangular map
  36. const image = texture.image;
  37. if ( isEquirectangularMapReady( image ) ) {
  38. const renderTarget = new CubeRenderTarget( image.height );
  39. renderTarget.fromEquirectangularTexture( renderer, texture );
  40. mapTextureMapping( renderTarget.texture, texture.mapping );
  41. this._cubeTexture = renderTarget.texture;
  42. _cache.set( texture, renderTarget.texture );
  43. texture.addEventListener( 'dispose', onTextureDispose );
  44. } else {
  45. // default cube texture as fallback when equirectangular texture is not yet loaded
  46. this._cubeTexture = this._defaultTexture;
  47. }
  48. }
  49. //
  50. this._cubeTextureNode.value = this._cubeTexture;
  51. } else {
  52. // envNode already refers to a cube map
  53. this._cubeTextureNode = this.envNode;
  54. }
  55. }
  56. }
  57. }
  58. setup( builder ) {
  59. this.updateBefore( builder );
  60. return this._cubeTextureNode;
  61. }
  62. }
  63. function isEquirectangularMapReady( image ) {
  64. if ( image === null || image === undefined ) return false;
  65. return image.height > 0;
  66. }
  67. function onTextureDispose( event ) {
  68. const texture = event.target;
  69. texture.removeEventListener( 'dispose', onTextureDispose );
  70. const renderTarget = _cache.get( texture );
  71. if ( renderTarget !== undefined ) {
  72. _cache.delete( texture );
  73. renderTarget.dispose();
  74. }
  75. }
  76. function mapTextureMapping( texture, mapping ) {
  77. if ( mapping === EquirectangularReflectionMapping ) {
  78. texture.mapping = CubeReflectionMapping;
  79. } else if ( mapping === EquirectangularRefractionMapping ) {
  80. texture.mapping = CubeRefractionMapping;
  81. }
  82. }
  83. export const cubeMapNode = nodeProxy( CubeMapNode );
  84. addNodeClass( 'CubeMapNode', CubeMapNode );
  85. export default CubeMapNode;
粤ICP备19079148号