VarNode.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. import Node from './Node.js';
  2. import { addMethodChaining, nodeProxy } from '../tsl/TSLCore.js';
  3. /** @module VarNode **/
  4. /**
  5. * Class for representing shader variables as nodes. Variables are created from
  6. * existing nodes like the following:
  7. *
  8. * ```js
  9. * const depth = sampleDepth( uvNode ).toVar( 'depth' );
  10. * ```
  11. *
  12. * @augments Node
  13. */
  14. class VarNode extends Node {
  15. static get type() {
  16. return 'VarNode';
  17. }
  18. /**
  19. * Constructs a new variable node.
  20. *
  21. * @param {Node} node - The node for which a variable should be created.
  22. * @param {String?} name - The name of the variable in the shader.
  23. * @param {Boolean?} readOnly - The read-only flag.
  24. */
  25. constructor( node, name = null, readOnly = false ) {
  26. super();
  27. /**
  28. * The node for which a variable should be created.
  29. *
  30. * @type {Node}
  31. */
  32. this.node = node;
  33. /**
  34. * The name of the variable in the shader. If no name is defined,
  35. * the node system auto-generates one.
  36. *
  37. * @type {String?}
  38. * @default null
  39. */
  40. this.name = name;
  41. /**
  42. * `VarNode` sets this property to `true` by default.
  43. *
  44. * @type {Boolean}
  45. * @default true
  46. */
  47. this.global = true;
  48. /**
  49. * This flag can be used for type testing.
  50. *
  51. * @type {Boolean}
  52. * @readonly
  53. * @default true
  54. */
  55. this.isVarNode = true;
  56. /**
  57. *
  58. * The read-only flag.
  59. *
  60. * @type {Boolean}
  61. * @default false
  62. */
  63. this.readOnly = readOnly;
  64. }
  65. getHash( builder ) {
  66. return this.name || super.getHash( builder );
  67. }
  68. getElementType( builder ) {
  69. return this.node.getElementType( builder );
  70. }
  71. getNodeType( builder ) {
  72. return this.node.getNodeType( builder );
  73. }
  74. generate( builder ) {
  75. const { node, name, readOnly } = this;
  76. const { renderer } = builder;
  77. const isWebGPUBackend = renderer.backend.isWebGPUBackend === true;
  78. let isDeterministic = false;
  79. let shouldTreatAsReadOnly = false;
  80. if ( readOnly ) {
  81. isDeterministic = builder.isDeterministic( node );
  82. shouldTreatAsReadOnly = isWebGPUBackend ? readOnly : isDeterministic;
  83. }
  84. const vectorType = builder.getVectorType( this.getNodeType( builder ) );
  85. const snippet = node.build( builder, vectorType );
  86. const nodeVar = builder.getVarFromNode( this, name, vectorType, undefined, shouldTreatAsReadOnly );
  87. const propertyName = builder.getPropertyName( nodeVar );
  88. let declarationPrefix = propertyName;
  89. if ( shouldTreatAsReadOnly ) {
  90. if ( isWebGPUBackend ) {
  91. declarationPrefix = isDeterministic
  92. ? `const ${ propertyName }`
  93. : `let ${ propertyName }`;
  94. } else {
  95. const count = builder.getArrayCount( node );
  96. declarationPrefix = `const ${ builder.getVar( nodeVar.type, propertyName, count ) }`;
  97. }
  98. }
  99. builder.addLineFlowCode( `${ declarationPrefix } = ${ snippet }`, this );
  100. return propertyName;
  101. }
  102. }
  103. export default VarNode;
  104. /**
  105. * TSL function for creating a var node.
  106. *
  107. * @function
  108. * @param {Node} node - The node for which a variable should be created.
  109. * @param {String?} name - The name of the variable in the shader.
  110. * @returns {VarNode}
  111. */
  112. const createVar = /*@__PURE__*/ nodeProxy( VarNode );
  113. /**
  114. * TSL function for creating a var node.
  115. *
  116. * @function
  117. * @param {Node} node - The node for which a variable should be created.
  118. * @param {String?} name - The name of the variable in the shader.
  119. * @returns {VarNode}
  120. */
  121. export const Var = ( node, name = null ) => createVar( node, name ).append();
  122. /**
  123. * TSL function for creating a const node.
  124. *
  125. * @function
  126. * @param {Node} node - The node for which a constant should be created.
  127. * @param {String?} name - The name of the constant in the shader.
  128. * @returns {VarNode}
  129. */
  130. export const Const = ( node, name = null ) => createVar( node, name, true ).append();
  131. // Method chaining
  132. addMethodChaining( 'toVar', Var );
  133. addMethodChaining( 'toConst', Const );
  134. // Deprecated
  135. /**
  136. * @function
  137. * @deprecated since r170. Use `Var( node )` or `node.toVar()` instead.
  138. *
  139. * @param {Any} node
  140. * @returns {VarNode}
  141. */
  142. export const temp = ( node ) => { // @deprecated, r170
  143. console.warn( 'TSL: "temp( node )" is deprecated. Use "Var( node )" or "node.toVar()" instead.' );
  144. return createVar( node );
  145. };
  146. addMethodChaining( 'temp', temp );
粤ICP备19079148号