LightingContextNode.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import ContextNode from '../core/ContextNode.js';
  2. import { add } from '../math/OperatorNode.js';
  3. import { mix } from '../math/MathNode.js';
  4. import { addNodeClass } from '../core/Node.js';
  5. import { addNodeElement, nodeProxy, float, vec3 } from '../shadernode/ShaderNode.js';
  6. class LightingContextNode extends ContextNode {
  7. constructor( node, lightingModelNode = null, backdropNode = null, backdropAlphaNode = null ) {
  8. super( node );
  9. this.lightingModelNode = lightingModelNode;
  10. this.backdropNode = backdropNode;
  11. this.backdropAlphaNode = backdropAlphaNode;
  12. }
  13. getNodeType( /*builder*/ ) {
  14. return 'vec3';
  15. }
  16. construct( builder ) {
  17. const { lightingModelNode, backdropNode, backdropAlphaNode } = this;
  18. const context = this.context = {}; // reset context
  19. const properties = builder.getNodeProperties( this );
  20. const directDiffuse = vec3().temp(),
  21. directSpecular = vec3().temp(),
  22. indirectDiffuse = vec3().temp(),
  23. indirectSpecular = vec3().temp();
  24. let totalDiffuse = add( directDiffuse, indirectDiffuse );
  25. if ( backdropNode !== null ) {
  26. totalDiffuse = vec3( backdropAlphaNode !== null ? mix( totalDiffuse, backdropNode, backdropAlphaNode ) : backdropNode );
  27. }
  28. const totalSpecular = add( directSpecular, indirectSpecular );
  29. const total = add( totalDiffuse, totalSpecular ).temp();
  30. const reflectedLight = {
  31. directDiffuse,
  32. directSpecular,
  33. indirectDiffuse,
  34. indirectSpecular,
  35. total
  36. };
  37. const lighting = {
  38. radiance: vec3().temp(),
  39. irradiance: vec3().temp(),
  40. iblIrradiance: vec3().temp(),
  41. ambientOcclusion: float( 1 ).temp()
  42. };
  43. context.reflectedLight = reflectedLight;
  44. context.lightingModelNode = lightingModelNode || context.lightingModelNode;
  45. Object.assign( properties, reflectedLight, lighting );
  46. Object.assign( context, lighting );
  47. // @TODO: Call needed return a new node ( or rename the ShaderNodeInternal.call() function ), it's not moment to run
  48. if ( lightingModelNode && lightingModelNode.init ) lightingModelNode.init( context, builder.stack, builder );
  49. if ( lightingModelNode && lightingModelNode.indirectDiffuse ) lightingModelNode.indirectDiffuse( context, builder.stack, builder );
  50. if ( lightingModelNode && lightingModelNode.indirectSpecular ) lightingModelNode.indirectSpecular( context, builder.stack, builder );
  51. if ( lightingModelNode && lightingModelNode.ambientOcclusion ) lightingModelNode.ambientOcclusion( context, builder.stack, builder );
  52. return super.construct( builder );
  53. }
  54. generate( builder ) {
  55. const { context } = this;
  56. const type = this.getNodeType( builder );
  57. super.generate( builder, type );
  58. return context.reflectedLight.total.build( builder, type );
  59. }
  60. }
  61. export default LightingContextNode;
  62. export const lightingContext = nodeProxy( LightingContextNode );
  63. addNodeElement( 'lightingContext', lightingContext );
  64. addNodeClass( LightingContextNode );