PMREMNode.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import TempNode from '../core/TempNode.js';
  2. import { addNodeClass } from '../core/Node.js';
  3. import { texture } from '../accessors/TextureNode.js';
  4. import { textureCubeUV } from './PMREMUtils.js';
  5. import { uniform } from '../core/UniformNode.js';
  6. import { NodeUpdateType } from '../core/constants.js';
  7. import { nodeProxy } from '../shadernode/ShaderNode.js';
  8. let _generator = null;
  9. const _cache = new WeakMap();
  10. function _generateCubeUVSize( imageHeight ) {
  11. const maxMip = Math.log2( imageHeight ) - 2;
  12. const texelHeight = 1.0 / imageHeight;
  13. const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) );
  14. return { texelWidth, texelHeight, maxMip };
  15. }
  16. function _getPMREMFromTexture( texture ) {
  17. let cacheTexture = _cache.get( texture );
  18. if ( cacheTexture === undefined ) {
  19. if ( texture.isCubeTexture ) {
  20. cacheTexture = _generator.fromCubemap( texture );
  21. } else {
  22. cacheTexture = _generator.fromEquirectangular( texture );
  23. }
  24. _cache.set( texture, cacheTexture );
  25. }
  26. return cacheTexture.texture;
  27. }
  28. class PMREMNode extends TempNode {
  29. constructor( value, uvNode = null, levelNode = null ) {
  30. super( 'vec3' );
  31. this._value = value;
  32. this._pmrem = null;
  33. this.uvNode = uvNode;
  34. this.levelNode = levelNode;
  35. this._generator = null;
  36. this._texture = texture( null );
  37. this._width = uniform( 0 );
  38. this._height = uniform( 0 );
  39. this._maxMip = uniform( 0 );
  40. this.updateBeforeType = NodeUpdateType.RENDER;
  41. }
  42. set value( value ) {
  43. this._value = value;
  44. this._pmrem = null;
  45. }
  46. get value() {
  47. return this._value;
  48. }
  49. updateFromTexture( texture ) {
  50. const cubeUVSize = _generateCubeUVSize( texture.image.height );
  51. this._texture.value = texture;
  52. this._width.value = cubeUVSize.texelWidth;
  53. this._height.value = cubeUVSize.texelHeight;
  54. this._maxMip.value = cubeUVSize.maxMip;
  55. }
  56. updateBefore( frame ) {
  57. let pmrem = this._pmrem;
  58. if ( pmrem === null ) {
  59. const texture = this._value;
  60. if ( texture.isPMREMTexture === true ) {
  61. pmrem = texture;
  62. } else {
  63. pmrem = _getPMREMFromTexture( texture );
  64. }
  65. this._pmrem = pmrem;
  66. this.updateFromTexture( pmrem );
  67. }
  68. }
  69. setup( builder ) {
  70. if ( _generator === null ) {
  71. _generator = builder.createPMREMGenerator();
  72. }
  73. //
  74. this.updateBefore( builder );
  75. //
  76. let uvNode = this.uvNode;
  77. if ( uvNode === null && builder.context.getUV ) {
  78. uvNode = builder.context.getUV( this );
  79. }
  80. //
  81. let levelNode = this.levelNode;
  82. if ( levelNode === null && builder.context.getTextureLevel ) {
  83. levelNode = builder.context.getTextureLevel( this );
  84. }
  85. //
  86. return textureCubeUV( this._texture, uvNode, levelNode, this._width, this._height, this._maxMip );
  87. }
  88. }
  89. export const pmremTexture = nodeProxy( PMREMNode );
  90. addNodeClass( 'PMREMNode', PMREMNode );
  91. export default PMREMNode;