EnvironmentNode.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import LightingNode from './LightingNode.js';
  2. import ContextNode from '../core/ContextNode.js';
  3. import CacheNode from '../core/CacheNode.js';
  4. import SpecularMIPLevelNode from '../utils/SpecularMIPLevelNode.js';
  5. import { float, mul, roughness, positionViewDirection, transformedNormalView, transformedNormalWorld, cameraViewMatrix, equirectUV, vec2 } from '../shadernode/ShaderNodeElements.js';
  6. class EnvironmentNode extends LightingNode {
  7. constructor( envNode = null ) {
  8. super();
  9. this.envNode = envNode;
  10. }
  11. construct( builder ) {
  12. const envNode = this.envNode;
  13. const properties = builder.getNodeProperties( this );
  14. let reflectVec;
  15. let radianceTextureUVNode;
  16. let irradianceTextureUVNode;
  17. const radianceContext = new ContextNode( envNode, {
  18. getUVNode: ( textureNode ) => {
  19. let node = null;
  20. if ( reflectVec === undefined ) {
  21. reflectVec = positionViewDirection.negate().reflect( transformedNormalView );
  22. reflectVec = reflectVec.mix( transformedNormalView, roughness.mul( roughness ) ).normalize();
  23. reflectVec = reflectVec.transformDirection( cameraViewMatrix );
  24. }
  25. if ( textureNode.isCubeTextureNode ) {
  26. node = reflectVec;
  27. } else if ( textureNode.isTextureNode ) {
  28. if ( radianceTextureUVNode === undefined ) {
  29. // @TODO: Needed PMREM
  30. radianceTextureUVNode = equirectUV( reflectVec );
  31. radianceTextureUVNode = vec2( radianceTextureUVNode.x, radianceTextureUVNode.y.invert() );
  32. }
  33. node = radianceTextureUVNode;
  34. }
  35. return node;
  36. },
  37. getSamplerLevelNode: () => {
  38. return roughness;
  39. },
  40. getMIPLevelAlgorithmNode: ( textureNode, levelNode ) => {
  41. return new SpecularMIPLevelNode( textureNode, levelNode );
  42. }
  43. } );
  44. const irradianceContext = new ContextNode( envNode, {
  45. getUVNode: ( textureNode ) => {
  46. let node = null;
  47. if ( textureNode.isCubeTextureNode ) {
  48. node = transformedNormalWorld;
  49. } else if ( textureNode.isTextureNode ) {
  50. if ( irradianceTextureUVNode === undefined ) {
  51. // @TODO: Needed PMREM
  52. irradianceTextureUVNode = equirectUV( transformedNormalWorld );
  53. irradianceTextureUVNode = vec2( irradianceTextureUVNode.x, irradianceTextureUVNode.y.invert() );
  54. }
  55. node = irradianceTextureUVNode;
  56. }
  57. return node;
  58. },
  59. getSamplerLevelNode: () => {
  60. return float( 1 );
  61. },
  62. getMIPLevelAlgorithmNode: ( textureNode, levelNode ) => {
  63. return new SpecularMIPLevelNode( textureNode, levelNode );
  64. }
  65. } );
  66. //
  67. const isolateRadianceFlowContext = new CacheNode( radianceContext );
  68. //
  69. builder.context.radiance.add( isolateRadianceFlowContext );
  70. builder.context.iblIrradiance.add( mul( Math.PI, irradianceContext ) );
  71. properties.radianceContext = isolateRadianceFlowContext;
  72. properties.irradianceContext = irradianceContext;
  73. }
  74. }
  75. export default EnvironmentNode;