NodeBuilder.js 75 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381
  1. import NodeUniform from './NodeUniform.js';
  2. import NodeAttribute from './NodeAttribute.js';
  3. import NodeVarying from './NodeVarying.js';
  4. import NodeVar from './NodeVar.js';
  5. import NodeCode from './NodeCode.js';
  6. import NodeCache from './NodeCache.js';
  7. import ParameterNode from './ParameterNode.js';
  8. import StructType from './StructType.js';
  9. import FunctionNode from '../code/FunctionNode.js';
  10. import NodeMaterial from '../../materials/nodes/NodeMaterial.js';
  11. import { getDataFromObject, getTypeFromLength, hashString } from './NodeUtils.js';
  12. import { NodeUpdateType, defaultBuildStages, shaderStages } from './constants.js';
  13. import {
  14. NumberNodeUniform, Vector2NodeUniform, Vector3NodeUniform, Vector4NodeUniform,
  15. ColorNodeUniform, Matrix2NodeUniform, Matrix3NodeUniform, Matrix4NodeUniform
  16. } from '../../renderers/common/nodes/NodeUniform.js';
  17. import { stack } from './StackNode.js';
  18. import { getCurrentStack, setCurrentStack } from '../tsl/TSLBase.js';
  19. import CubeRenderTarget from '../../renderers/common/CubeRenderTarget.js';
  20. import BindGroup from '../../renderers/common/BindGroup.js';
  21. import { REVISION, IntType, UnsignedIntType, LinearFilter, LinearMipmapNearestFilter, NearestMipmapLinearFilter, LinearMipmapLinearFilter, NormalBlending, RedFormat, RGFormat, RGBFormat, RedIntegerFormat, RGIntegerFormat, RGBIntegerFormat } from '../../constants.js';
  22. import { RenderTarget } from '../../core/RenderTarget.js';
  23. import { Color } from '../../math/Color.js';
  24. import { Vector2 } from '../../math/Vector2.js';
  25. import { Vector3 } from '../../math/Vector3.js';
  26. import { Vector4 } from '../../math/Vector4.js';
  27. import { Float16BufferAttribute } from '../../core/BufferAttribute.js';
  28. import { warn, error, yieldToMain } from '../../utils.js';
  29. let _id = 0;
  30. const _bindingGroupsCache = new WeakMap();
  31. const _functionNodeCache = new WeakMap();
  32. const sharedNodeData = new WeakMap();
  33. const typeFromArray = new Map( [
  34. [ Int8Array, 'int' ],
  35. [ Int16Array, 'int' ],
  36. [ Int32Array, 'int' ],
  37. [ Uint8Array, 'uint' ],
  38. [ Uint16Array, 'uint' ],
  39. [ Uint32Array, 'uint' ],
  40. [ Float32Array, 'float' ]
  41. ] );
  42. const toFloat = ( value ) => {
  43. if ( /e/g.test( value ) ) {
  44. return String( value ).replace( /\+/g, '' );
  45. } else {
  46. value = Number( value );
  47. return value + ( value % 1 ? '' : '.0' );
  48. }
  49. };
  50. /**
  51. * Base class for builders which generate a shader program based
  52. * on a 3D object and its node material definition.
  53. */
  54. class NodeBuilder {
  55. /**
  56. * Constructs a new node builder.
  57. *
  58. * @param {Object3D} object - The 3D object.
  59. * @param {Renderer} renderer - The current renderer.
  60. * @param {NodeParser} parser - A reference to a node parser.
  61. */
  62. constructor( object, renderer, parser ) {
  63. /**
  64. * The 3D object.
  65. *
  66. * @type {Object3D}
  67. */
  68. this.object = object;
  69. /**
  70. * The material of the 3D object.
  71. *
  72. * @type {?Material}
  73. */
  74. this.material = ( object && object.material ) || null;
  75. /**
  76. * The geometry of the 3D object.
  77. *
  78. * @type {?BufferGeometry}
  79. */
  80. this.geometry = ( object && object.geometry ) || null;
  81. /**
  82. * The current renderer.
  83. *
  84. * @type {Renderer}
  85. */
  86. this.renderer = renderer;
  87. /**
  88. * A reference to a node parser.
  89. *
  90. * @type {NodeParser}
  91. */
  92. this.parser = parser;
  93. /**
  94. * The scene the 3D object belongs to.
  95. *
  96. * @type {?Scene}
  97. * @default null
  98. */
  99. this.scene = null;
  100. /**
  101. * The camera the 3D object is rendered with.
  102. *
  103. * @type {?Camera}
  104. * @default null
  105. */
  106. this.camera = null;
  107. /**
  108. * A list of all nodes the builder is processing
  109. * for this 3D object.
  110. *
  111. * @type {Array<Node>}
  112. */
  113. this.nodes = [];
  114. /**
  115. * A list of all nodes the builder is processing in sequential order.
  116. *
  117. * This is used to determine the update order of nodes, which is important for
  118. * {@link NodeUpdateType#UPDATE_BEFORE} and {@link NodeUpdateType#UPDATE_AFTER}.
  119. *
  120. * @type {Array<Node>}
  121. */
  122. this.sequentialNodes = [];
  123. /**
  124. * A list of all nodes which {@link Node#update} method should be executed.
  125. *
  126. * @type {Array<Node>}
  127. */
  128. this.updateNodes = [];
  129. /**
  130. * A list of all nodes which {@link Node#updateBefore} method should be executed.
  131. *
  132. * @type {Array<Node>}
  133. */
  134. this.updateBeforeNodes = [];
  135. /**
  136. * A list of all nodes which {@link Node#updateAfter} method should be executed.
  137. *
  138. * @type {Array<Node>}
  139. */
  140. this.updateAfterNodes = [];
  141. /**
  142. * A dictionary that assigns each node to a unique hash.
  143. *
  144. * @type {Object<number,Node>}
  145. */
  146. this.hashNodes = {};
  147. /**
  148. * A reference to a node material observer.
  149. *
  150. * @type {?NodeMaterialObserver}
  151. * @default null
  152. */
  153. this.observer = null;
  154. /**
  155. * A reference to the current lights node.
  156. *
  157. * @type {?LightsNode}
  158. * @default null
  159. */
  160. this.lightsNode = null;
  161. /**
  162. * A reference to the current environment node.
  163. *
  164. * @type {?Node}
  165. * @default null
  166. */
  167. this.environmentNode = null;
  168. /**
  169. * A reference to the current fog node.
  170. *
  171. * @type {?Node}
  172. * @default null
  173. */
  174. this.fogNode = null;
  175. /**
  176. * The current clipping context.
  177. *
  178. * @type {?ClippingContext}
  179. */
  180. this.clippingContext = null;
  181. /**
  182. * The generated vertex shader.
  183. *
  184. * @type {?string}
  185. */
  186. this.vertexShader = null;
  187. /**
  188. * The generated fragment shader.
  189. *
  190. * @type {?string}
  191. */
  192. this.fragmentShader = null;
  193. /**
  194. * The generated compute shader.
  195. *
  196. * @type {?string}
  197. */
  198. this.computeShader = null;
  199. /**
  200. * Nodes used in the primary flow of code generation.
  201. *
  202. * @type {Object<string,Array<Node>>}
  203. */
  204. this.flowNodes = { vertex: [], fragment: [], compute: [] };
  205. /**
  206. * Nodes code from `.flowNodes`.
  207. *
  208. * @type {Object<string,string>}
  209. */
  210. this.flowCode = { vertex: '', fragment: '', compute: '' };
  211. /**
  212. * This dictionary holds the node uniforms of the builder.
  213. * The uniforms are maintained in an array for each shader stage.
  214. *
  215. * @type {Object}
  216. */
  217. this.uniforms = { vertex: [], fragment: [], compute: [], index: 0 };
  218. /**
  219. * This dictionary holds the output structs of the builder.
  220. * The structs are maintained in an array for each shader stage.
  221. *
  222. * @type {Object}
  223. */
  224. this.structs = { vertex: [], fragment: [], compute: [], index: 0 };
  225. /**
  226. * This dictionary holds the types of the builder.
  227. *
  228. * @type {Object}
  229. */
  230. this.types = { vertex: [], fragment: [], compute: [], index: 0 };
  231. /**
  232. * This dictionary holds the bindings for each shader stage.
  233. *
  234. * @type {Object}
  235. */
  236. this.bindings = { vertex: {}, fragment: {}, compute: {} };
  237. /**
  238. * This dictionary maintains the binding indices per bind group.
  239. *
  240. * @type {Object}
  241. */
  242. this.bindingsIndexes = {};
  243. /**
  244. * Reference to the array of bind groups.
  245. *
  246. * @type {?Array<BindGroup>}
  247. */
  248. this.bindGroups = null;
  249. /**
  250. * This array holds the node attributes of this builder
  251. * created via {@link AttributeNode}.
  252. *
  253. * @type {Array<NodeAttribute>}
  254. */
  255. this.attributes = [];
  256. /**
  257. * This array holds the node attributes of this builder
  258. * created via {@link BufferAttributeNode}.
  259. *
  260. * @type {Array<NodeAttribute>}
  261. */
  262. this.bufferAttributes = [];
  263. /**
  264. * This array holds the node varyings of this builder.
  265. *
  266. * @type {Array<NodeVarying>}
  267. */
  268. this.varyings = [];
  269. /**
  270. * This dictionary holds the (native) node codes of this builder.
  271. * The codes are maintained in an array for each shader stage.
  272. *
  273. * @type {Object<string,Array<NodeCode>>}
  274. */
  275. this.codes = {};
  276. /**
  277. * This dictionary holds the node variables of this builder.
  278. * The variables are maintained in an array for each shader stage.
  279. * This dictionary is also used to count the number of variables
  280. * according to their type (const, vars).
  281. *
  282. * @type {Object<string,Array<NodeVar>|number>}
  283. */
  284. this.vars = {};
  285. /**
  286. * This dictionary holds the declarations for each shader stage.
  287. *
  288. * @type {Object}
  289. */
  290. this.declarations = {};
  291. /**
  292. * Current code flow.
  293. * All code generated in this stack will be stored in `.flow`.
  294. *
  295. * @type {{code: string}}
  296. */
  297. this.flow = { code: '' };
  298. /**
  299. * A chain of nodes.
  300. * Used to check recursive calls in node-graph.
  301. *
  302. * @type {Array<Node>}
  303. */
  304. this.chaining = [];
  305. /**
  306. * The current stack.
  307. * This reflects the current process in the code block hierarchy,
  308. * it is useful to know if the current process is inside a conditional for example.
  309. *
  310. * @type {StackNode}
  311. */
  312. this.stack = stack();
  313. /**
  314. * List of stack nodes.
  315. * The current stack hierarchy is stored in an array.
  316. *
  317. * @type {Array<StackNode>}
  318. */
  319. this.stacks = [];
  320. /**
  321. * A tab value. Used for shader string generation.
  322. *
  323. * @type {string}
  324. * @default '\t'
  325. */
  326. this.tab = '\t';
  327. /**
  328. * Reference to the current function node.
  329. *
  330. * @type {?FunctionNode}
  331. * @default null
  332. */
  333. this.currentFunctionNode = null;
  334. /**
  335. * The builder's context.
  336. *
  337. * @type {Object}
  338. */
  339. this.context = {
  340. material: this.material
  341. };
  342. /**
  343. * The builder's cache.
  344. *
  345. * @type {NodeCache}
  346. */
  347. this.cache = new NodeCache();
  348. /**
  349. * Since the {@link NodeBuilder#cache} might be temporarily
  350. * overwritten by other caches, this member retains the reference
  351. * to the builder's own cache.
  352. *
  353. * @type {NodeCache}
  354. * @default this.cache
  355. */
  356. this.globalCache = this.cache;
  357. this.flowsData = new WeakMap();
  358. /**
  359. * The current shader stage.
  360. *
  361. * @type {?('vertex'|'fragment'|'compute'|'any')}
  362. */
  363. this.shaderStage = null;
  364. /**
  365. * The current build stage.
  366. *
  367. * @type {?('setup'|'analyze'|'generate')}
  368. */
  369. this.buildStage = null;
  370. /**
  371. * The sub-build layers.
  372. *
  373. * @type {Array<SubBuildNode>}
  374. * @default []
  375. */
  376. this.subBuildLayers = [];
  377. /**
  378. * The active stack nodes.
  379. *
  380. * @type {Array<StackNode>}
  381. */
  382. this.activeStacks = [];
  383. /**
  384. * The current sub-build TSL function(Fn).
  385. *
  386. * @type {?string}
  387. * @default null
  388. */
  389. this.subBuildFn = null;
  390. /**
  391. * The current TSL function(Fn) call node.
  392. *
  393. * @type {?Node}
  394. * @default null
  395. */
  396. this.fnCall = null;
  397. Object.defineProperty( this, 'id', { value: _id ++ } );
  398. }
  399. /**
  400. * Whether the material is using flat shading or not.
  401. *
  402. * @returns {boolean} Whether the material is using flat shading or not.
  403. */
  404. isFlatShading() {
  405. return this.material.flatShading === true || this.geometry.hasAttribute( 'normal' ) === false;
  406. }
  407. /**
  408. * Whether the material is opaque or not.
  409. *
  410. * @return {boolean} Whether the material is opaque or not.
  411. */
  412. isOpaque() {
  413. const material = this.material;
  414. return material.transparent === false && material.blending === NormalBlending && material.alphaToCoverage === false;
  415. }
  416. /**
  417. * Factory method for creating an instance of {@link RenderTarget} with the given
  418. * dimensions and options.
  419. *
  420. * @param {number} width - The width of the render target.
  421. * @param {number} height - The height of the render target.
  422. * @param {Object} options - The options of the render target.
  423. * @return {RenderTarget} The render target.
  424. */
  425. createRenderTarget( width, height, options ) {
  426. return new RenderTarget( width, height, options );
  427. }
  428. /**
  429. * Factory method for creating an instance of {@link CubeRenderTarget} with the given
  430. * dimensions and options.
  431. *
  432. * @param {number} size - The size of the cube render target.
  433. * @param {Object} options - The options of the cube render target.
  434. * @return {CubeRenderTarget} The cube render target.
  435. */
  436. createCubeRenderTarget( size, options ) {
  437. return new CubeRenderTarget( size, options );
  438. }
  439. /**
  440. * Whether the given node is included in the internal array of nodes or not.
  441. *
  442. * @param {Node} node - The node to test.
  443. * @return {boolean} Whether the given node is included in the internal array of nodes or not.
  444. */
  445. includes( node ) {
  446. return this.nodes.includes( node );
  447. }
  448. /**
  449. * Returns the type of the color output based on the renderer's render target.
  450. *
  451. * @param {number} [index=0] - The index of the render target texture.
  452. * @return {string} The type.
  453. */
  454. getOutputType( index = 0 ) {
  455. let type = 'vec4';
  456. const renderTarget = this.renderer.getRenderTarget();
  457. if ( renderTarget !== null ) {
  458. const renderTargetType = renderTarget.textures[ index ].type;
  459. const renderTargetFormat = renderTarget.textures[ index ].format;
  460. let typeStr = 'vec';
  461. if ( renderTargetType === IntType ) {
  462. typeStr = 'ivec';
  463. } else if ( renderTargetType === UnsignedIntType ) {
  464. typeStr = 'uvec';
  465. }
  466. if ( renderTargetFormat === RedFormat || renderTargetFormat === RedIntegerFormat ) {
  467. if ( renderTargetType === IntType ) type = 'int';
  468. else if ( renderTargetType === UnsignedIntType ) type = 'uint';
  469. else type = 'float';
  470. } else if ( renderTargetFormat === RGFormat || renderTargetFormat === RGIntegerFormat ) {
  471. type = `${ typeStr }2`;
  472. } else if ( renderTargetFormat === RGBFormat || renderTargetFormat === RGBIntegerFormat ) {
  473. type = `${ typeStr }3`;
  474. } else {
  475. type = `${ typeStr }4`;
  476. }
  477. }
  478. return type;
  479. }
  480. /**
  481. * Returns the output struct name which is required by
  482. * {@link OutputStructNode}.
  483. *
  484. * @abstract
  485. * @return {string} The name of the output struct.
  486. */
  487. getOutputStructName() {}
  488. /**
  489. * Returns a bind group for the given group name and binding.
  490. *
  491. * @private
  492. * @param {string} groupName - The group name.
  493. * @param {Array<NodeUniformsGroup>} bindings - List of bindings.
  494. * @return {BindGroup} The bind group
  495. */
  496. _getBindGroup( groupName, bindings ) {
  497. const groupNode = bindings[ 0 ].groupNode;
  498. let sharedGroup = groupNode.shared;
  499. if ( sharedGroup ) {
  500. for ( let i = 1; i < bindings.length; i ++ ) {
  501. if ( groupNode !== bindings[ i ].groupNode ) {
  502. sharedGroup = false;
  503. }
  504. }
  505. }
  506. //
  507. let bindGroup;
  508. if ( sharedGroup ) {
  509. let cacheKeyString = '';
  510. for ( const binding of bindings ) {
  511. if ( binding.isNodeUniformsGroup ) {
  512. binding.uniforms.sort( ( a, b ) => a.nodeUniform.node.id - b.nodeUniform.node.id );
  513. for ( const uniform of binding.uniforms ) {
  514. cacheKeyString += uniform.nodeUniform.node.id;
  515. }
  516. } else {
  517. cacheKeyString += binding.nodeUniform.id;
  518. }
  519. }
  520. // TODO: Remove this hack ._currentRenderContext
  521. const currentContext = this.renderer._currentRenderContext || this.renderer; // use renderer as fallback until we have a compute context
  522. let bindingGroupsCache = _bindingGroupsCache.get( currentContext );
  523. if ( bindingGroupsCache === undefined ) {
  524. bindingGroupsCache = new Map();
  525. _bindingGroupsCache.set( currentContext, bindingGroupsCache );
  526. }
  527. //
  528. const cacheKey = hashString( cacheKeyString );
  529. bindGroup = bindingGroupsCache.get( cacheKey );
  530. if ( bindGroup === undefined ) {
  531. bindGroup = new BindGroup( groupName, bindings );
  532. bindingGroupsCache.set( cacheKey, bindGroup );
  533. }
  534. } else {
  535. bindGroup = new BindGroup( groupName, bindings );
  536. }
  537. return bindGroup;
  538. }
  539. /**
  540. * Returns an array of node uniform groups for the given group name and shader stage.
  541. *
  542. * @param {string} groupName - The group name.
  543. * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
  544. * @return {Array<NodeUniformsGroup>} The array of node uniform groups.
  545. */
  546. getBindGroupArray( groupName, shaderStage ) {
  547. const bindings = this.bindings[ shaderStage ];
  548. let bindGroup = bindings[ groupName ];
  549. if ( bindGroup === undefined ) {
  550. if ( this.bindingsIndexes[ groupName ] === undefined ) {
  551. this.bindingsIndexes[ groupName ] = { binding: 0, group: Object.keys( this.bindingsIndexes ).length };
  552. }
  553. bindings[ groupName ] = bindGroup = [];
  554. }
  555. return bindGroup;
  556. }
  557. /**
  558. * Returns a list bindings of all shader stages separated by groups.
  559. *
  560. * @return {Array<BindGroup>} The list of bindings.
  561. */
  562. getBindings() {
  563. let bindingsGroups = this.bindGroups;
  564. if ( bindingsGroups === null ) {
  565. const groups = {};
  566. const bindings = this.bindings;
  567. for ( const shaderStage of shaderStages ) {
  568. for ( const groupName in bindings[ shaderStage ] ) {
  569. const uniforms = bindings[ shaderStage ][ groupName ];
  570. const groupUniforms = groups[ groupName ] || ( groups[ groupName ] = [] );
  571. for ( const uniform of uniforms ) {
  572. if ( groupUniforms.includes( uniform ) === false ) {
  573. groupUniforms.push( uniform );
  574. }
  575. }
  576. }
  577. }
  578. bindingsGroups = [];
  579. for ( const groupName in groups ) {
  580. const group = groups[ groupName ];
  581. const bindingsGroup = this._getBindGroup( groupName, group );
  582. bindingsGroups.push( bindingsGroup );
  583. }
  584. this.bindGroups = bindingsGroups;
  585. }
  586. return bindingsGroups;
  587. }
  588. /**
  589. * Sorts the bind groups and updates {@link NodeBuilder#bindingsIndexes}.
  590. */
  591. sortBindingGroups() {
  592. const bindingsGroups = this.getBindings();
  593. bindingsGroups.sort( ( a, b ) => ( a.bindings[ 0 ].groupNode.order - b.bindings[ 0 ].groupNode.order ) );
  594. for ( let i = 0; i < bindingsGroups.length; i ++ ) {
  595. const bindingGroup = bindingsGroups[ i ];
  596. this.bindingsIndexes[ bindingGroup.name ].group = i;
  597. }
  598. }
  599. /**
  600. * The builder maintains each node in a hash-based dictionary.
  601. * This method sets the given node (value) with the given hash (key) into this dictionary.
  602. *
  603. * @param {Node} node - The node to add.
  604. * @param {number} hash - The hash of the node.
  605. */
  606. setHashNode( node, hash ) {
  607. this.hashNodes[ hash ] = node;
  608. }
  609. /**
  610. * Adds a node to this builder.
  611. *
  612. * @param {Node} node - The node to add.
  613. */
  614. addNode( node ) {
  615. if ( this.nodes.includes( node ) === false ) {
  616. this.nodes.push( node );
  617. this.setHashNode( node, node.getHash( this ) );
  618. }
  619. }
  620. /**
  621. * It is used to add Nodes that will be used as FRAME and RENDER events,
  622. * and need to follow a certain sequence in the calls to work correctly.
  623. * This function should be called after 'setup()' in the 'build()' process to ensure that the child nodes are processed first.
  624. *
  625. * @param {Node} node - The node to add.
  626. */
  627. addSequentialNode( node ) {
  628. const updateBeforeType = node.getUpdateBeforeType();
  629. const updateAfterType = node.getUpdateAfterType();
  630. if ( updateBeforeType !== NodeUpdateType.NONE || updateAfterType !== NodeUpdateType.NONE ) {
  631. if ( this.sequentialNodes.includes( node ) === false ) {
  632. this.sequentialNodes.push( node );
  633. }
  634. }
  635. }
  636. /**
  637. * Checks the update types of nodes
  638. */
  639. buildUpdateNodes() {
  640. for ( const node of this.nodes ) {
  641. const updateType = node.getUpdateType();
  642. if ( updateType !== NodeUpdateType.NONE ) {
  643. this.updateNodes.push( node );
  644. }
  645. }
  646. for ( const node of this.sequentialNodes ) {
  647. const updateBeforeType = node.getUpdateBeforeType();
  648. const updateAfterType = node.getUpdateAfterType();
  649. if ( updateBeforeType !== NodeUpdateType.NONE ) {
  650. this.updateBeforeNodes.push( node );
  651. }
  652. if ( updateAfterType !== NodeUpdateType.NONE ) {
  653. this.updateAfterNodes.push( node );
  654. }
  655. }
  656. }
  657. /**
  658. * A reference the current node which is the
  659. * last node in the chain of nodes.
  660. *
  661. * @type {Node}
  662. */
  663. get currentNode() {
  664. return this.chaining[ this.chaining.length - 1 ];
  665. }
  666. /**
  667. * Whether the given texture is filtered or not.
  668. *
  669. * @param {Texture} texture - The texture to check.
  670. * @return {boolean} Whether the given texture is filtered or not.
  671. */
  672. isFilteredTexture( texture ) {
  673. return ( texture.magFilter === LinearFilter || texture.magFilter === LinearMipmapNearestFilter || texture.magFilter === NearestMipmapLinearFilter || texture.magFilter === LinearMipmapLinearFilter ||
  674. texture.minFilter === LinearFilter || texture.minFilter === LinearMipmapNearestFilter || texture.minFilter === NearestMipmapLinearFilter || texture.minFilter === LinearMipmapLinearFilter );
  675. }
  676. /**
  677. * Returns the maximum number of bytes available for uniform buffers.
  678. *
  679. * @return {number} The maximum number of bytes available for uniform buffers.
  680. */
  681. getUniformBufferLimit() {
  682. return this.renderer.backend.capabilities.getUniformBufferLimit();
  683. }
  684. /**
  685. * Adds the given node to the internal node chain.
  686. * This is used to check recursive calls in node-graph.
  687. *
  688. * @param {Node} node - The node to add.
  689. */
  690. addChain( node ) {
  691. /*
  692. if ( this.chaining.indexOf( node ) !== - 1 ) {
  693. warn( 'Recursive node: ', node );
  694. }
  695. */
  696. this.chaining.push( node );
  697. }
  698. /**
  699. * Removes the given node from the internal node chain.
  700. *
  701. * @param {Node} node - The node to remove.
  702. */
  703. removeChain( node ) {
  704. const lastChain = this.chaining.pop();
  705. if ( lastChain !== node ) {
  706. throw new Error( 'THREE.NodeBuilder: Invalid node chaining!' );
  707. }
  708. }
  709. /**
  710. * Returns the native shader method name for a given generic name. E.g.
  711. * the method name `textureDimensions` matches the WGSL name but must be
  712. * resolved to `textureSize` in GLSL.
  713. *
  714. * @abstract
  715. * @param {string} method - The method name to resolve.
  716. * @return {string} The resolved method name.
  717. */
  718. getMethod( method ) {
  719. return method;
  720. }
  721. /**
  722. * Returns the native snippet for a ternary operation. E.g. GLSL would output
  723. * a ternary op as `cond ? x : y` whereas WGSL would output it as `select(y, x, cond)`
  724. *
  725. * @abstract
  726. * @param {string} condSnippet - The condition determining which expression gets resolved.
  727. * @param {string} ifSnippet - The expression to resolve to if the condition is true.
  728. * @param {string} elseSnippet - The expression to resolve to if the condition is false.
  729. * @return {string} The resolved method name.
  730. */
  731. getTernary( /* condSnippet, ifSnippet, elseSnippet*/ ) {
  732. return null;
  733. }
  734. /**
  735. * Returns a node for the given hash, see {@link NodeBuilder#setHashNode}.
  736. *
  737. * @param {number} hash - The hash of the node.
  738. * @return {Node} The found node.
  739. */
  740. getNodeFromHash( hash ) {
  741. return this.hashNodes[ hash ];
  742. }
  743. /**
  744. * Adds the Node to a target flow so that it can generate code in the 'generate' process.
  745. *
  746. * @param {('vertex'|'fragment'|'compute')} shaderStage - The shader stage.
  747. * @param {Node} node - The node to add.
  748. * @return {Node} The node.
  749. */
  750. addFlow( shaderStage, node ) {
  751. this.flowNodes[ shaderStage ].push( node );
  752. return node;
  753. }
  754. /**
  755. * Sets builder's context.
  756. *
  757. * @param {Object} context - The context to set.
  758. */
  759. setContext( context ) {
  760. this.context = context;
  761. }
  762. /**
  763. * Returns the builder's current context.
  764. *
  765. * @return {Object} The builder's current context.
  766. */
  767. getContext() {
  768. return this.context;
  769. }
  770. /**
  771. * Adds context data to the builder's current context.
  772. *
  773. * @param {Object} context - The context to add.
  774. * @return {Object} The previous context.
  775. */
  776. addContext( context ) {
  777. const previousContext = this.getContext();
  778. this.setContext( { ...this.context, ...context } );
  779. return previousContext;
  780. }
  781. /**
  782. * Gets a context used in shader construction that can be shared across different materials.
  783. * This is necessary since the renderer cache can reuse shaders generated in one material and use them in another.
  784. *
  785. * @return {Object} The builder's current context without material.
  786. */
  787. getSharedContext() {
  788. const context = { ...this.context };
  789. delete context.material;
  790. delete context.getUV;
  791. delete context.getOutput;
  792. delete context.getTextureLevel;
  793. delete context.getAO;
  794. delete context.getShadow;
  795. return context;
  796. }
  797. /**
  798. * Sets builder's cache.
  799. *
  800. * @param {NodeCache} cache - The cache to set.
  801. */
  802. setCache( cache ) {
  803. this.cache = cache;
  804. }
  805. /**
  806. * Returns the builder's current cache.
  807. *
  808. * @return {NodeCache} The builder's current cache.
  809. */
  810. getCache() {
  811. return this.cache;
  812. }
  813. /**
  814. * Returns a cache for the given node.
  815. *
  816. * @param {Node} node - The node.
  817. * @param {boolean} [parent=true] - Whether this node refers to a shared parent cache or not.
  818. * @return {NodeCache} The cache.
  819. */
  820. getCacheFromNode( node, parent = true ) {
  821. const data = this.getDataFromNode( node );
  822. if ( data.cache === undefined ) data.cache = new NodeCache( parent ? this.getCache() : null );
  823. return data.cache;
  824. }
  825. /**
  826. * Whether the requested feature is available or not.
  827. *
  828. * @abstract
  829. * @param {string} name - The requested feature.
  830. * @return {boolean} Whether the requested feature is supported or not.
  831. */
  832. isAvailable( /*name*/ ) {
  833. return false;
  834. }
  835. /**
  836. * Returns the vertexIndex input variable as a native shader string.
  837. *
  838. * @abstract
  839. * @return {string} The instanceIndex shader string.
  840. */
  841. getVertexIndex() {
  842. warn( 'Abstract function.' );
  843. }
  844. /**
  845. * Contextually returns either the vertex stage instance index builtin
  846. * or the linearized index of an compute invocation within a grid of workgroups.
  847. *
  848. * @abstract
  849. * @return {string} The instanceIndex shader string.
  850. */
  851. getInstanceIndex() {
  852. warn( 'Abstract function.' );
  853. }
  854. /**
  855. * Returns the drawIndex input variable as a native shader string.
  856. * Only relevant for WebGL and its `WEBGL_multi_draw` extension.
  857. *
  858. * @abstract
  859. * @return {?string} The drawIndex shader string.
  860. */
  861. getDrawIndex() {
  862. warn( 'Abstract function.' );
  863. }
  864. /**
  865. * Returns the frontFacing input variable as a native shader string.
  866. *
  867. * @abstract
  868. * @return {string} The frontFacing shader string.
  869. */
  870. getFrontFacing() {
  871. warn( 'Abstract function.' );
  872. }
  873. /**
  874. * Returns the fragCoord input variable as a native shader string.
  875. *
  876. * @abstract
  877. * @return {string} The fragCoord shader string.
  878. */
  879. getFragCoord() {
  880. warn( 'Abstract function.' );
  881. }
  882. /**
  883. * Whether to flip texture data along its vertical axis or not. WebGL needs
  884. * this method evaluate to `true`, WebGPU to `false`.
  885. *
  886. * @abstract
  887. * @return {boolean} Whether to flip texture data along its vertical axis or not.
  888. */
  889. isFlipY() {
  890. return false;
  891. }
  892. /**
  893. * Calling this method increases the usage count for the given node by one.
  894. *
  895. * @param {Node} node - The node to increase the usage count for.
  896. * @return {number} The updated usage count.
  897. */
  898. increaseUsage( node ) {
  899. const nodeData = this.getDataFromNode( node );
  900. nodeData.usageCount = nodeData.usageCount === undefined ? 1 : nodeData.usageCount + 1;
  901. return nodeData.usageCount;
  902. }
  903. /**
  904. * Generates a texture sample shader string for the given texture data.
  905. *
  906. * @abstract
  907. * @param {Texture} texture - The texture.
  908. * @param {string} textureProperty - The texture property name.
  909. * @param {string} uvSnippet - Snippet defining the texture coordinates.
  910. * @return {string} The generated shader string.
  911. */
  912. generateTexture( /* texture, textureProperty, uvSnippet */ ) {
  913. warn( 'Abstract function.' );
  914. }
  915. /**
  916. * Generates a texture LOD shader string for the given texture data.
  917. *
  918. * @abstract
  919. * @param {Texture} texture - The texture.
  920. * @param {string} textureProperty - The texture property name.
  921. * @param {string} uvSnippet - Snippet defining the texture coordinates.
  922. * @param {?string} depthSnippet - Snippet defining the 0-based texture array index to sample.
  923. * @param {string} levelSnippet - Snippet defining the mip level.
  924. * @return {string} The generated shader string.
  925. */
  926. generateTextureLod( /* texture, textureProperty, uvSnippet, depthSnippet, levelSnippet */ ) {
  927. warn( 'Abstract function.' );
  928. }
  929. /**
  930. * Generates the array declaration string.
  931. *
  932. * @param {string} type - The type.
  933. * @param {?number} [count] - The count.
  934. * @return {string} The generated value as a shader string.
  935. */
  936. generateArrayDeclaration( type, count ) {
  937. return this.getType( type ) + '[ ' + count + ' ]';
  938. }
  939. /**
  940. * Generates the array shader string for the given type and value.
  941. *
  942. * @param {string} type - The type.
  943. * @param {?number} [count] - The count.
  944. * @param {?Array<Node>} [values=null] - The default values.
  945. * @return {string} The generated value as a shader string.
  946. */
  947. generateArray( type, count, values = null ) {
  948. let snippet = this.generateArrayDeclaration( type, count ) + '( ';
  949. for ( let i = 0; i < count; i ++ ) {
  950. const value = values ? values[ i ] : null;
  951. if ( value !== null ) {
  952. snippet += value.build( this, type );
  953. } else {
  954. snippet += this.generateConst( type );
  955. }
  956. if ( i < count - 1 ) snippet += ', ';
  957. }
  958. snippet += ' )';
  959. return snippet;
  960. }
  961. /**
  962. * Generates the struct shader string.
  963. *
  964. * @param {string} type - The type.
  965. * @param {Array<Object>} [membersLayout] - The count.
  966. * @param {?Array<Node>} [values=null] - The default values.
  967. * @return {string} The generated value as a shader string.
  968. */
  969. generateStruct( type, membersLayout, values = null ) {
  970. const snippets = [];
  971. for ( const member of membersLayout ) {
  972. const { name, type } = member;
  973. if ( values && values[ name ] && values[ name ].isNode ) {
  974. snippets.push( values[ name ].build( this, type ) );
  975. } else {
  976. snippets.push( this.generateConst( type ) );
  977. }
  978. }
  979. return type + '( ' + snippets.join( ', ' ) + ' )';
  980. }
  981. /**
  982. * Generates the shader string for the given type and value.
  983. *
  984. * @param {string} type - The type.
  985. * @param {?any} [value=null] - The value.
  986. * @return {string} The generated value as a shader string.
  987. */
  988. generateConst( type, value = null ) {
  989. if ( value === null ) {
  990. if ( type === 'float' || type === 'int' || type === 'uint' ) value = 0;
  991. else if ( type === 'bool' ) value = false;
  992. else if ( type === 'color' ) value = new Color();
  993. else if ( type === 'vec2' || type === 'uvec2' || type === 'ivec2' ) value = new Vector2();
  994. else if ( type === 'vec3' || type === 'uvec3' || type === 'ivec3' ) value = new Vector3();
  995. else if ( type === 'vec4' || type === 'uvec4' || type === 'ivec4' ) value = new Vector4();
  996. }
  997. if ( type === 'float' ) return toFloat( value );
  998. if ( type === 'int' ) return `${ Math.round( value ) }`;
  999. if ( type === 'uint' ) return value >= 0 ? `${ Math.round( value ) }u` : '0u';
  1000. if ( type === 'bool' ) return value ? 'true' : 'false';
  1001. if ( type === 'color' ) return `${ this.getType( 'vec3' ) }( ${ toFloat( value.r ) }, ${ toFloat( value.g ) }, ${ toFloat( value.b ) } )`;
  1002. const typeLength = this.getTypeLength( type );
  1003. const componentType = this.getComponentType( type );
  1004. const generateConst = value => this.generateConst( componentType, value );
  1005. if ( typeLength === 2 ) {
  1006. return `${ this.getType( type ) }( ${ generateConst( value.x ) }, ${ generateConst( value.y ) } )`;
  1007. } else if ( typeLength === 3 ) {
  1008. return `${ this.getType( type ) }( ${ generateConst( value.x ) }, ${ generateConst( value.y ) }, ${ generateConst( value.z ) } )`;
  1009. } else if ( typeLength === 4 && type !== 'mat2' ) {
  1010. return `${ this.getType( type ) }( ${ generateConst( value.x ) }, ${ generateConst( value.y ) }, ${ generateConst( value.z ) }, ${ generateConst( value.w ) } )`;
  1011. } else if ( typeLength >= 4 && value && ( value.isMatrix2 || value.isMatrix3 || value.isMatrix4 ) ) {
  1012. return `${ this.getType( type ) }( ${ value.elements.map( generateConst ).join( ', ' ) } )`;
  1013. } else if ( typeLength > 4 ) {
  1014. return `${ this.getType( type ) }()`;
  1015. }
  1016. throw new Error( `THREE.NodeBuilder: Type '${type}' not found in generate constant attempt.` );
  1017. }
  1018. /**
  1019. * It might be necessary to convert certain data types to different ones
  1020. * so this method can be used to hide the conversion.
  1021. *
  1022. * @param {string} type - The type.
  1023. * @return {string} The updated type.
  1024. */
  1025. getType( type ) {
  1026. if ( type === 'color' ) return 'vec3';
  1027. return type;
  1028. }
  1029. /**
  1030. * Whether the given attribute name is defined in the geometry or not.
  1031. *
  1032. * @param {string} name - The attribute name.
  1033. * @return {boolean} Whether the given attribute name is defined in the geometry.
  1034. */
  1035. hasGeometryAttribute( name ) {
  1036. return this.geometry && this.geometry.getAttribute( name ) !== undefined;
  1037. }
  1038. /**
  1039. * Returns a node attribute for the given name and type.
  1040. *
  1041. * @param {string} name - The attribute's name.
  1042. * @param {string} type - The attribute's type.
  1043. * @return {NodeAttribute} The node attribute.
  1044. */
  1045. getAttribute( name, type ) {
  1046. const attributes = this.attributes;
  1047. // find attribute
  1048. for ( const attribute of attributes ) {
  1049. if ( attribute.name === name ) {
  1050. return attribute;
  1051. }
  1052. }
  1053. // create a new if no exist
  1054. const attribute = new NodeAttribute( name, type );
  1055. this.registerDeclaration( attribute );
  1056. attributes.push( attribute );
  1057. return attribute;
  1058. }
  1059. /**
  1060. * Returns for the given node and shader stage the property name for the shader.
  1061. *
  1062. * @param {Node} node - The node.
  1063. * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
  1064. * @return {string} The property name.
  1065. */
  1066. getPropertyName( node/*, shaderStage*/ ) {
  1067. return node.name;
  1068. }
  1069. /**
  1070. * Whether the given type is a vector type or not.
  1071. *
  1072. * @param {string} type - The type to check.
  1073. * @return {boolean} Whether the given type is a vector type or not.
  1074. */
  1075. isVector( type ) {
  1076. return /vec\d/.test( type );
  1077. }
  1078. /**
  1079. * Whether the given type is a matrix type or not.
  1080. *
  1081. * @param {string} type - The type to check.
  1082. * @return {boolean} Whether the given type is a matrix type or not.
  1083. */
  1084. isMatrix( type ) {
  1085. return /mat\d/.test( type );
  1086. }
  1087. /**
  1088. * Whether the given type is a reference type or not.
  1089. *
  1090. * @param {string} type - The type to check.
  1091. * @return {boolean} Whether the given type is a reference type or not.
  1092. */
  1093. isReference( type ) {
  1094. return type === 'void' || type === 'property' || type === 'sampler' || type === 'samplerComparison' || type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'depthTexture' || type === 'texture3D';
  1095. }
  1096. /**
  1097. * Checks if the given texture requires a manual conversion to the working color space.
  1098. *
  1099. * @abstract
  1100. * @param {Texture} texture - The texture to check.
  1101. * @return {boolean} Whether the given texture requires a conversion to working color space or not.
  1102. */
  1103. needsToWorkingColorSpace( /*texture*/ ) {
  1104. return false;
  1105. }
  1106. /**
  1107. * Returns the component type of a given texture.
  1108. *
  1109. * @param {Texture} texture - The texture.
  1110. * @return {string} The component type.
  1111. */
  1112. getComponentTypeFromTexture( texture ) {
  1113. const type = texture.type;
  1114. if ( texture.isDepthTexture === true ) return 'float';
  1115. if ( type === IntType ) return 'int';
  1116. if ( type === UnsignedIntType ) return 'uint';
  1117. return 'float';
  1118. }
  1119. /**
  1120. * Returns the element type for a given type.
  1121. *
  1122. * @param {string} type - The type.
  1123. * @return {string} The element type.
  1124. */
  1125. getElementType( type ) {
  1126. if ( type === 'mat2' ) return 'vec2';
  1127. if ( type === 'mat3' ) return 'vec3';
  1128. if ( type === 'mat4' ) return 'vec4';
  1129. return this.getComponentType( type );
  1130. }
  1131. /**
  1132. * Returns the component type for a given type.
  1133. *
  1134. * @param {string} type - The type.
  1135. * @return {string} The component type.
  1136. */
  1137. getComponentType( type ) {
  1138. type = this.getVectorType( type );
  1139. if ( type === 'float' || type === 'bool' || type === 'int' || type === 'uint' ) return type;
  1140. const componentType = /(b|i|u|)(vec|mat)([2-4])/.exec( type );
  1141. if ( componentType === null ) return null;
  1142. if ( componentType[ 1 ] === 'b' ) return 'bool';
  1143. if ( componentType[ 1 ] === 'i' ) return 'int';
  1144. if ( componentType[ 1 ] === 'u' ) return 'uint';
  1145. return 'float';
  1146. }
  1147. /**
  1148. * Returns the vector type for a given type.
  1149. *
  1150. * @param {string} type - The type.
  1151. * @return {string} The vector type.
  1152. */
  1153. getVectorType( type ) {
  1154. if ( type === 'color' ) return 'vec3';
  1155. if ( type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'texture3D' ) return 'vec4';
  1156. return type;
  1157. }
  1158. /**
  1159. * Returns the data type for the given the length and component type.
  1160. *
  1161. * @param {number} length - The length.
  1162. * @param {string} [componentType='float'] - The component type.
  1163. * @return {string} The type.
  1164. */
  1165. getTypeFromLength( length, componentType = 'float' ) {
  1166. if ( length === 1 ) return componentType;
  1167. let baseType = getTypeFromLength( length );
  1168. const prefix = componentType === 'float' ? '' : componentType[ 0 ];
  1169. // fix edge case for mat2x2 being same size as vec4
  1170. if ( /mat2/.test( componentType ) === true ) {
  1171. baseType = baseType.replace( 'vec', 'mat' );
  1172. }
  1173. return prefix + baseType;
  1174. }
  1175. /**
  1176. * Returns the type for a given typed array.
  1177. *
  1178. * @param {TypedArray} array - The typed array.
  1179. * @return {string} The type.
  1180. */
  1181. getTypeFromArray( array ) {
  1182. return typeFromArray.get( array.constructor );
  1183. }
  1184. /**
  1185. * Returns the type is an integer type.
  1186. *
  1187. * @param {string} type - The type.
  1188. * @return {boolean} Whether the type is an integer type or not.
  1189. */
  1190. isInteger( type ) {
  1191. return /int|uint|(i|u)vec/.test( type );
  1192. }
  1193. /**
  1194. * Returns the type for a given buffer attribute.
  1195. *
  1196. * @param {BufferAttribute} attribute - The buffer attribute.
  1197. * @return {string} The type.
  1198. */
  1199. getTypeFromAttribute( attribute ) {
  1200. let dataAttribute = attribute;
  1201. if ( attribute.isInterleavedBufferAttribute ) dataAttribute = attribute.data;
  1202. const array = dataAttribute.array;
  1203. const itemSize = attribute.itemSize;
  1204. const normalized = attribute.normalized;
  1205. let arrayType;
  1206. if ( ! ( attribute instanceof Float16BufferAttribute ) && normalized !== true ) {
  1207. arrayType = this.getTypeFromArray( array );
  1208. }
  1209. return this.getTypeFromLength( itemSize, arrayType );
  1210. }
  1211. /**
  1212. * Returns the length for the given data type.
  1213. *
  1214. * @param {string} type - The data type.
  1215. * @return {number} The length.
  1216. */
  1217. getTypeLength( type ) {
  1218. const vecType = this.getVectorType( type );
  1219. const vecNum = /vec([2-4])/.exec( vecType );
  1220. if ( vecNum !== null ) return Number( vecNum[ 1 ] );
  1221. if ( vecType === 'float' || vecType === 'bool' || vecType === 'int' || vecType === 'uint' ) return 1;
  1222. if ( /mat2/.test( type ) === true ) return 4;
  1223. if ( /mat3/.test( type ) === true ) return 9;
  1224. if ( /mat4/.test( type ) === true ) return 16;
  1225. return 0;
  1226. }
  1227. /**
  1228. * Returns the vector type for a given matrix type.
  1229. *
  1230. * @param {string} type - The matrix type.
  1231. * @return {string} The vector type.
  1232. */
  1233. getVectorFromMatrix( type ) {
  1234. return type.replace( 'mat', 'vec' );
  1235. }
  1236. /**
  1237. * For a given type this method changes the component type to the
  1238. * given value. E.g. `vec4` should be changed to the new component type
  1239. * `uint` which results in `uvec4`.
  1240. *
  1241. * @param {string} type - The type.
  1242. * @param {string} newComponentType - The new component type.
  1243. * @return {string} The new type.
  1244. */
  1245. changeComponentType( type, newComponentType ) {
  1246. return this.getTypeFromLength( this.getTypeLength( type ), newComponentType );
  1247. }
  1248. /**
  1249. * Returns the integer type pendant for the given type.
  1250. *
  1251. * @param {string} type - The type.
  1252. * @return {string} The integer type.
  1253. */
  1254. getIntegerType( type ) {
  1255. const componentType = this.getComponentType( type );
  1256. if ( componentType === 'int' || componentType === 'uint' ) return type;
  1257. return this.changeComponentType( type, 'int' );
  1258. }
  1259. /**
  1260. * Adds an active stack to the internal stack.
  1261. *
  1262. * @param {StackNode} stack - The stack node to add.
  1263. */
  1264. setActiveStack( stack ) {
  1265. this.activeStacks.push( stack );
  1266. }
  1267. /**
  1268. * Removes the active stack from the internal stack.
  1269. *
  1270. * @param {StackNode} stack - The stack node to remove.
  1271. */
  1272. removeActiveStack( stack ) {
  1273. if ( this.activeStacks[ this.activeStacks.length - 1 ] === stack ) {
  1274. this.activeStacks.pop();
  1275. } else {
  1276. throw new Error( 'THREE.NodeBuilder: Invalid active stack removal.' );
  1277. }
  1278. }
  1279. /**
  1280. * Returns the active stack.
  1281. *
  1282. * @return {StackNode} The active stack.
  1283. */
  1284. getActiveStack() {
  1285. return this.activeStacks[ this.activeStacks.length - 1 ];
  1286. }
  1287. /**
  1288. * Returns the base stack.
  1289. *
  1290. * @return {StackNode} The base stack.
  1291. */
  1292. getBaseStack() {
  1293. return this.activeStacks[ 0 ];
  1294. }
  1295. /**
  1296. * Adds a stack node to the internal stack.
  1297. *
  1298. * @return {StackNode} The added stack node.
  1299. */
  1300. addStack() {
  1301. this.stack = stack( this.stack );
  1302. const previousStack = getCurrentStack();
  1303. this.stacks.push( previousStack );
  1304. setCurrentStack( this.stack );
  1305. return this.stack;
  1306. }
  1307. /**
  1308. * Removes the last stack node from the internal stack.
  1309. *
  1310. * @return {StackNode} The removed stack node.
  1311. */
  1312. removeStack() {
  1313. const lastStack = this.stack;
  1314. for ( const node of lastStack.nodes ) {
  1315. const nodeData = this.getDataFromNode( node );
  1316. nodeData.stack = lastStack;
  1317. }
  1318. this.stack = lastStack.parent;
  1319. setCurrentStack( this.stacks.pop() );
  1320. return lastStack;
  1321. }
  1322. /**
  1323. * The builder maintains (cached) data for each node during the building process. This method
  1324. * can be used to get these data for a specific shader stage and cache.
  1325. *
  1326. * @param {Node} node - The node to get the data for.
  1327. * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
  1328. * @param {?NodeCache} cache - An optional cache.
  1329. * @return {Object} The node data.
  1330. */
  1331. getDataFromNode( node, shaderStage = this.shaderStage, cache = null ) {
  1332. cache = cache === null ? ( node.isGlobal( this ) ? this.globalCache : this.cache ) : cache;
  1333. let nodeData = cache.getData( node );
  1334. if ( nodeData === undefined ) {
  1335. nodeData = {};
  1336. cache.setData( node, nodeData );
  1337. }
  1338. if ( nodeData[ shaderStage ] === undefined ) nodeData[ shaderStage ] = {};
  1339. //
  1340. let data = nodeData[ shaderStage ];
  1341. if ( this.subBuildLayers.length === 0 ) return data;
  1342. const subBuilds = nodeData.any ? nodeData.any.subBuilds : null;
  1343. const subBuild = this.getClosestSubBuild( subBuilds );
  1344. if ( subBuild ) {
  1345. if ( data.subBuildsCache === undefined ) data.subBuildsCache = {};
  1346. data = data.subBuildsCache[ subBuild ] || ( data.subBuildsCache[ subBuild ] = {} );
  1347. data.subBuilds = subBuilds;
  1348. }
  1349. return data;
  1350. }
  1351. /**
  1352. * Returns the properties for the given node and shader stage.
  1353. *
  1354. * Properties are typically used within a build stage to reference a node's
  1355. * child node or nodes manually assigned to the properties in a separate build stage.
  1356. * A typical usage pattern for defining nodes manually would be assigning dependency nodes
  1357. * to the current node's properties in the setup stage and building those properties in the generate stage.
  1358. *
  1359. * @param {Node} node - The node to get the properties for.
  1360. * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage='any'] - The shader stage.
  1361. * @return {Object} The node properties.
  1362. */
  1363. getNodeProperties( node, shaderStage = 'any' ) {
  1364. const nodeData = this.getDataFromNode( node, shaderStage );
  1365. return nodeData.properties || ( nodeData.properties = { outputNode: null } );
  1366. }
  1367. /**
  1368. * Returns an instance of {@link NodeAttribute} for the given buffer attribute node.
  1369. *
  1370. * @param {BufferAttributeNode} node - The buffer attribute node.
  1371. * @param {string} type - The node type.
  1372. * @param {?string} [name=null] - The name of the buffer attribute.
  1373. * @return {NodeAttribute} The node attribute.
  1374. */
  1375. getBufferAttributeFromNode( node, type, name = null ) {
  1376. const nodeData = this.getDataFromNode( node, 'vertex' );
  1377. let bufferAttribute = nodeData.bufferAttribute;
  1378. if ( bufferAttribute === undefined ) {
  1379. const index = this.uniforms.index ++;
  1380. if ( name === null ) {
  1381. name = 'nodeAttribute' + index;
  1382. }
  1383. bufferAttribute = new NodeAttribute( name, type, node );
  1384. this.bufferAttributes.push( bufferAttribute );
  1385. nodeData.bufferAttribute = bufferAttribute;
  1386. }
  1387. return bufferAttribute;
  1388. }
  1389. /**
  1390. * Returns an instance of {@link StructType} for the given struct name and shader stage
  1391. * or null if not found.
  1392. *
  1393. * @param {string} name - The name of the struct.
  1394. * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
  1395. * @return {?StructType} The struct type or null if not found.
  1396. */
  1397. getStructTypeNode( name, shaderStage = this.shaderStage ) {
  1398. return this.types[ shaderStage ][ name ] || null;
  1399. }
  1400. /**
  1401. * Returns an instance of {@link StructType} for the given output struct node.
  1402. *
  1403. * @param {OutputStructNode} node - The output struct node.
  1404. * @param {Array<Object>} membersLayout - The output struct types.
  1405. * @param {?string} [name=null] - The name of the struct.
  1406. * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
  1407. * @return {StructType} The struct type attribute.
  1408. */
  1409. getStructTypeFromNode( node, membersLayout, name = null, shaderStage = this.shaderStage ) {
  1410. const nodeData = this.getDataFromNode( node, shaderStage, this.globalCache );
  1411. let structType = nodeData.structType;
  1412. if ( structType === undefined ) {
  1413. const index = this.structs.index ++;
  1414. if ( name === null ) name = 'StructType' + index;
  1415. structType = new StructType( name, membersLayout );
  1416. this.structs[ shaderStage ].push( structType );
  1417. this.types[ shaderStage ][ name ] = node;
  1418. nodeData.structType = structType;
  1419. }
  1420. return structType;
  1421. }
  1422. /**
  1423. * Returns an instance of {@link StructType} for the given output struct node.
  1424. *
  1425. * @param {OutputStructNode} node - The output struct node.
  1426. * @param {Array<Object>} membersLayout - The output struct types.
  1427. * @return {StructType} The struct type attribute.
  1428. */
  1429. getOutputStructTypeFromNode( node, membersLayout ) {
  1430. const structType = this.getStructTypeFromNode( node, membersLayout, 'OutputType', 'fragment' );
  1431. structType.output = true;
  1432. return structType;
  1433. }
  1434. /**
  1435. * Returns an instance of {@link NodeUniform} for the given uniform node.
  1436. *
  1437. * @param {UniformNode} node - The uniform node.
  1438. * @param {string} type - The uniform type.
  1439. * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
  1440. * @param {?string} name - The name of the uniform.
  1441. * @return {NodeUniform} The node uniform.
  1442. */
  1443. getUniformFromNode( node, type, shaderStage = this.shaderStage, name = null ) {
  1444. const nodeData = this.getDataFromNode( node, shaderStage, this.globalCache );
  1445. let nodeUniform = nodeData.uniform;
  1446. if ( nodeUniform === undefined ) {
  1447. const index = this.uniforms.index ++;
  1448. nodeUniform = new NodeUniform( name || ( 'nodeUniform' + index ), type, node );
  1449. this.uniforms[ shaderStage ].push( nodeUniform );
  1450. this.registerDeclaration( nodeUniform );
  1451. nodeData.uniform = nodeUniform;
  1452. }
  1453. return nodeUniform;
  1454. }
  1455. /**
  1456. * Returns an instance of {@link NodeVar} for the given variable node.
  1457. *
  1458. * @param {VarNode} node - The variable node.
  1459. * @param {?string} name - The variable's name.
  1460. * @param {string} [type=node.getNodeType( this )] - The variable's type.
  1461. * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
  1462. * @param {boolean} [readOnly=false] - Whether the variable is read-only or not.
  1463. *
  1464. * @return {NodeVar} The node variable.
  1465. */
  1466. getVarFromNode( node, name = null, type = node.getNodeType( this ), shaderStage = this.shaderStage, readOnly = false ) {
  1467. const nodeData = this.getDataFromNode( node, shaderStage );
  1468. const subBuildVariable = this.getSubBuildProperty( 'variable', nodeData.subBuilds );
  1469. let nodeVar = nodeData[ subBuildVariable ];
  1470. if ( nodeVar === undefined ) {
  1471. const idNS = readOnly ? '_const' : '_var';
  1472. const vars = this.vars[ shaderStage ] || ( this.vars[ shaderStage ] = [] );
  1473. const id = this.vars[ idNS ] || ( this.vars[ idNS ] = 0 );
  1474. if ( name === null ) {
  1475. name = ( readOnly ? 'nodeConst' : 'nodeVar' ) + id;
  1476. this.vars[ idNS ] ++;
  1477. }
  1478. //
  1479. if ( subBuildVariable !== 'variable' ) {
  1480. name = this.getSubBuildProperty( name, nodeData.subBuilds );
  1481. }
  1482. //
  1483. const count = node.getArrayCount( this );
  1484. nodeVar = new NodeVar( name, type, readOnly, count );
  1485. if ( ! readOnly ) {
  1486. vars.push( nodeVar );
  1487. }
  1488. this.registerDeclaration( nodeVar );
  1489. nodeData[ subBuildVariable ] = nodeVar;
  1490. }
  1491. return nodeVar;
  1492. }
  1493. /**
  1494. * Returns whether a Node or its flow is deterministic, useful for use in `const`.
  1495. *
  1496. * @param {Node} node - The varying node.
  1497. * @return {boolean} Returns true if deterministic.
  1498. */
  1499. isDeterministic( node ) {
  1500. if ( node.isMathNode ) {
  1501. return this.isDeterministic( node.aNode ) &&
  1502. ( node.bNode ? this.isDeterministic( node.bNode ) : true ) &&
  1503. ( node.cNode ? this.isDeterministic( node.cNode ) : true );
  1504. } else if ( node.isOperatorNode ) {
  1505. return this.isDeterministic( node.aNode ) &&
  1506. ( node.bNode ? this.isDeterministic( node.bNode ) : true );
  1507. } else if ( node.isArrayNode ) {
  1508. if ( node.values !== null ) {
  1509. for ( const n of node.values ) {
  1510. if ( ! this.isDeterministic( n ) ) {
  1511. return false;
  1512. }
  1513. }
  1514. }
  1515. return true;
  1516. } else if ( node.isConstNode ) {
  1517. return true;
  1518. }
  1519. return false;
  1520. }
  1521. /**
  1522. * Returns an instance of {@link NodeVarying} for the given varying node.
  1523. *
  1524. * @param {(VaryingNode|PropertyNode)} node - The varying node.
  1525. * @param {?string} name - The varying's name.
  1526. * @param {string} [type=node.getNodeType( this )] - The varying's type.
  1527. * @param {?string} interpolationType - The interpolation type of the varying.
  1528. * @param {?string} interpolationSampling - The interpolation sampling type of the varying.
  1529. * @return {NodeVar} The node varying.
  1530. */
  1531. getVaryingFromNode( node, name = null, type = node.getNodeType( this ), interpolationType = null, interpolationSampling = null ) {
  1532. const nodeData = this.getDataFromNode( node, 'any' );
  1533. const subBuildVarying = this.getSubBuildProperty( 'varying', nodeData.subBuilds );
  1534. let nodeVarying = nodeData[ subBuildVarying ];
  1535. if ( nodeVarying === undefined ) {
  1536. const varyings = this.varyings;
  1537. const index = varyings.length;
  1538. if ( name === null ) name = 'nodeVarying' + index;
  1539. //
  1540. if ( subBuildVarying !== 'varying' ) {
  1541. name = this.getSubBuildProperty( name, nodeData.subBuilds );
  1542. }
  1543. //
  1544. nodeVarying = new NodeVarying( name, type, interpolationType, interpolationSampling );
  1545. varyings.push( nodeVarying );
  1546. this.registerDeclaration( nodeVarying );
  1547. nodeData[ subBuildVarying ] = nodeVarying;
  1548. }
  1549. return nodeVarying;
  1550. }
  1551. /**
  1552. * Registers a node declaration in the current shader stage.
  1553. *
  1554. * @param {Object} node - The node to be registered.
  1555. */
  1556. registerDeclaration( node ) {
  1557. const shaderStage = this.shaderStage;
  1558. const declarations = this.declarations[ shaderStage ] || ( this.declarations[ shaderStage ] = {} );
  1559. const property = this.getPropertyName( node );
  1560. let index = 1;
  1561. let name = property;
  1562. // Automatically renames the property if the name is already in use.
  1563. while ( declarations[ name ] !== undefined ) {
  1564. name = property + '_' + index ++;
  1565. }
  1566. if ( index > 1 ) {
  1567. node.name = name;
  1568. warn( `TSL: Declaration name '${ property }' of '${ node.type }' already in use. Renamed to '${ name }'.` );
  1569. }
  1570. declarations[ name ] = node;
  1571. }
  1572. /**
  1573. * Returns an instance of {@link NodeCode} for the given code node.
  1574. *
  1575. * @param {CodeNode} node - The code node.
  1576. * @param {string} type - The node type.
  1577. * @param {('vertex'|'fragment'|'compute'|'any')} [shaderStage=this.shaderStage] - The shader stage.
  1578. * @return {NodeCode} The node code.
  1579. */
  1580. getCodeFromNode( node, type, shaderStage = this.shaderStage ) {
  1581. const nodeData = this.getDataFromNode( node );
  1582. let nodeCode = nodeData.code;
  1583. if ( nodeCode === undefined ) {
  1584. const codes = this.codes[ shaderStage ] || ( this.codes[ shaderStage ] = [] );
  1585. const index = codes.length;
  1586. nodeCode = new NodeCode( 'nodeCode' + index, type );
  1587. codes.push( nodeCode );
  1588. nodeData.code = nodeCode;
  1589. }
  1590. return nodeCode;
  1591. }
  1592. /**
  1593. * Adds a code flow based on the code-block hierarchy.
  1594. * This is used so that code-blocks like If,Else create their variables locally if the Node
  1595. * is only used inside one of these conditionals in the current shader stage.
  1596. *
  1597. * @param {Node} node - The node to add.
  1598. * @param {Node} nodeBlock - Node-based code-block. Usually 'ConditionalNode'.
  1599. */
  1600. addFlowCodeHierarchy( node, nodeBlock ) {
  1601. const { flowCodes, flowCodeBlock } = this.getDataFromNode( node );
  1602. let needsFlowCode = true;
  1603. let nodeBlockHierarchy = nodeBlock;
  1604. while ( nodeBlockHierarchy ) {
  1605. if ( flowCodeBlock.get( nodeBlockHierarchy ) === true ) {
  1606. needsFlowCode = false;
  1607. break;
  1608. }
  1609. nodeBlockHierarchy = this.getDataFromNode( nodeBlockHierarchy ).parentNodeBlock;
  1610. }
  1611. if ( needsFlowCode ) {
  1612. for ( const flowCode of flowCodes ) {
  1613. this.addLineFlowCode( flowCode );
  1614. }
  1615. }
  1616. }
  1617. /**
  1618. * Add a inline-code to the current flow code-block.
  1619. *
  1620. * @param {Node} node - The node to add.
  1621. * @param {string} code - The code to add.
  1622. * @param {Node} nodeBlock - Current ConditionalNode
  1623. */
  1624. addLineFlowCodeBlock( node, code, nodeBlock ) {
  1625. const nodeData = this.getDataFromNode( node );
  1626. const flowCodes = nodeData.flowCodes || ( nodeData.flowCodes = [] );
  1627. const codeBlock = nodeData.flowCodeBlock || ( nodeData.flowCodeBlock = new WeakMap() );
  1628. flowCodes.push( code );
  1629. codeBlock.set( nodeBlock, true );
  1630. }
  1631. /**
  1632. * Add a inline-code to the current flow.
  1633. *
  1634. * @param {string} code - The code to add.
  1635. * @param {?Node} [node= null] - Optional Node, can help the system understand if the Node is part of a code-block.
  1636. * @return {NodeBuilder} A reference to this node builder.
  1637. */
  1638. addLineFlowCode( code, node = null ) {
  1639. if ( code === '' ) return this;
  1640. if ( node !== null && this.context.nodeBlock ) {
  1641. this.addLineFlowCodeBlock( node, code, this.context.nodeBlock );
  1642. }
  1643. code = this.tab + code;
  1644. if ( ! /;\s*$/.test( code ) ) {
  1645. code = code + ';\n';
  1646. }
  1647. this.flow.code += code;
  1648. return this;
  1649. }
  1650. /**
  1651. * Adds a code to the current code flow.
  1652. *
  1653. * @param {string} code - Shader code.
  1654. * @return {NodeBuilder} A reference to this node builder.
  1655. */
  1656. addFlowCode( code ) {
  1657. this.flow.code += code;
  1658. return this;
  1659. }
  1660. /**
  1661. * Add tab in the code that will be generated so that other snippets respect the current tabulation.
  1662. * Typically used in codes with If,Else.
  1663. *
  1664. * @return {NodeBuilder} A reference to this node builder.
  1665. */
  1666. addFlowTab() {
  1667. this.tab += '\t';
  1668. return this;
  1669. }
  1670. /**
  1671. * Removes a tab.
  1672. *
  1673. * @return {NodeBuilder} A reference to this node builder.
  1674. */
  1675. removeFlowTab() {
  1676. this.tab = this.tab.slice( 0, - 1 );
  1677. return this;
  1678. }
  1679. /**
  1680. * Gets the current flow data based on a Node.
  1681. *
  1682. * @param {Node} node - Node that the flow was started.
  1683. * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
  1684. * @return {Object} The flow data.
  1685. */
  1686. getFlowData( node/*, shaderStage*/ ) {
  1687. return this.flowsData.get( node );
  1688. }
  1689. /**
  1690. * Executes the node flow based on a root node to generate the final shader code.
  1691. *
  1692. * @param {Node} node - The node to execute.
  1693. * @return {Object} The code flow.
  1694. */
  1695. flowNode( node ) {
  1696. const output = node.getNodeType( this );
  1697. const flowData = this.flowChildNode( node, output );
  1698. this.flowsData.set( node, flowData );
  1699. return flowData;
  1700. }
  1701. /**
  1702. * Includes a node in the current function node.
  1703. *
  1704. * @param {Node} node - The node to include.
  1705. * @returns {void}
  1706. */
  1707. addInclude( node ) {
  1708. if ( this.currentFunctionNode !== null ) {
  1709. this.currentFunctionNode.includes.push( node );
  1710. }
  1711. }
  1712. /**
  1713. * Returns the native shader operator name for a given generic name.
  1714. * It is a similar type of method like {@link NodeBuilder#getMethod}.
  1715. *
  1716. * @param {ShaderNodeInternal} shaderNode - The shader node to build the function node with.
  1717. * @return {FunctionNode} The build function node.
  1718. */
  1719. buildFunctionNode( shaderNode ) {
  1720. const backend = this.renderer.backend;
  1721. let cache = _functionNodeCache.get( backend );
  1722. if ( cache === undefined ) {
  1723. cache = new WeakMap();
  1724. _functionNodeCache.set( backend, cache );
  1725. }
  1726. let fn = cache.get( shaderNode );
  1727. if ( fn === undefined ) {
  1728. fn = new FunctionNode();
  1729. const previous = this.currentFunctionNode;
  1730. this.currentFunctionNode = fn;
  1731. fn.code = this.buildFunctionCode( shaderNode );
  1732. this.currentFunctionNode = previous;
  1733. cache.set( shaderNode, fn );
  1734. }
  1735. return fn;
  1736. }
  1737. /**
  1738. * Generates a code flow based on a TSL function: Fn().
  1739. *
  1740. * @param {ShaderNodeInternal} shaderNode - A function code will be generated based on the input.
  1741. * @return {Object}
  1742. */
  1743. flowShaderNode( shaderNode ) {
  1744. const layout = shaderNode.layout;
  1745. const inputs = {
  1746. [ Symbol.iterator ]() {
  1747. let index = 0;
  1748. const values = Object.values( this );
  1749. return {
  1750. next: () => ( {
  1751. value: values[ index ],
  1752. done: index ++ >= values.length
  1753. } )
  1754. };
  1755. }
  1756. };
  1757. for ( const input of layout.inputs ) {
  1758. inputs[ input.name ] = new ParameterNode( input.type, input.name );
  1759. }
  1760. //
  1761. shaderNode.layout = null;
  1762. const callNode = shaderNode.call( inputs );
  1763. const flowData = this.flowStagesNode( callNode, layout.type );
  1764. shaderNode.layout = layout;
  1765. return flowData;
  1766. }
  1767. /**
  1768. * Executes the node in a specific build stage.
  1769. *
  1770. * This function can be used to arbitrarily execute the specified build stage
  1771. * outside of the standard build process. For instance, if a node's type depends
  1772. * on properties created by the 'setup' stage, then flowBuildStage(node, 'setup')
  1773. * can be used to execute the setup build stage and access its generated nodes
  1774. * before the standard build process begins.
  1775. *
  1776. * @param {Node} node - The node to execute.
  1777. * @param {string} buildStage - The build stage to execute the node in.
  1778. * @param {?(Node|string)} [output=null] - Expected output type. For example 'vec3'.
  1779. * @return {?(Node|string)} The result of the node build.
  1780. */
  1781. flowBuildStage( node, buildStage, output = null ) {
  1782. const previousBuildStage = this.getBuildStage();
  1783. this.setBuildStage( buildStage );
  1784. const result = node.build( this, output );
  1785. this.setBuildStage( previousBuildStage );
  1786. return result;
  1787. }
  1788. /**
  1789. * Runs the node flow through all the steps of creation, 'setup', 'analyze', 'generate'.
  1790. *
  1791. * @param {Node} node - The node to execute.
  1792. * @param {?string} output - Expected output type. For example 'vec3'.
  1793. * @return {Object}
  1794. */
  1795. flowStagesNode( node, output = null ) {
  1796. const previousFlow = this.flow;
  1797. const previousVars = this.vars;
  1798. const previousDeclarations = this.declarations;
  1799. const previousCache = this.cache;
  1800. const previousBuildStage = this.buildStage;
  1801. const previousStack = this.stack;
  1802. const flow = {
  1803. code: ''
  1804. };
  1805. this.flow = flow;
  1806. this.vars = {};
  1807. this.declarations = {};
  1808. this.cache = new NodeCache();
  1809. this.stack = stack();
  1810. for ( const buildStage of defaultBuildStages ) {
  1811. this.setBuildStage( buildStage );
  1812. flow.result = node.build( this, output );
  1813. }
  1814. flow.vars = this.getVars( this.shaderStage );
  1815. this.flow = previousFlow;
  1816. this.vars = previousVars;
  1817. this.declarations = previousDeclarations;
  1818. this.cache = previousCache;
  1819. this.stack = previousStack;
  1820. this.setBuildStage( previousBuildStage );
  1821. return flow;
  1822. }
  1823. /**
  1824. * Returns the native shader operator name for a given generic name.
  1825. * It is a similar type of method like {@link NodeBuilder#getMethod}.
  1826. *
  1827. * @abstract
  1828. * @param {string} op - The operator name to resolve.
  1829. * @return {?string} The resolved operator name.
  1830. */
  1831. getFunctionOperator( /* op */ ) {
  1832. return null;
  1833. }
  1834. /**
  1835. * Builds the given shader node.
  1836. *
  1837. * @abstract
  1838. * @param {ShaderNodeInternal} shaderNode - The shader node.
  1839. * @return {string} The function code.
  1840. */
  1841. buildFunctionCode( /* shaderNode */ ) {
  1842. warn( 'Abstract function.' );
  1843. }
  1844. /**
  1845. * Generates a code flow based on a child Node.
  1846. *
  1847. * @param {Node} node - The node to execute.
  1848. * @param {?string} output - Expected output type. For example 'vec3'.
  1849. * @return {Object} The code flow.
  1850. */
  1851. flowChildNode( node, output = null ) {
  1852. const previousFlow = this.flow;
  1853. const flow = {
  1854. code: ''
  1855. };
  1856. this.flow = flow;
  1857. flow.result = node.build( this, output );
  1858. this.flow = previousFlow;
  1859. return flow;
  1860. }
  1861. /**
  1862. * Executes a flow of code in a different stage.
  1863. *
  1864. * Some nodes like `varying()` have the ability to compute code in vertex-stage and
  1865. * return the value in fragment-stage even if it is being executed in an input fragment.
  1866. *
  1867. * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
  1868. * @param {Node} node - The node to execute.
  1869. * @param {?string} output - Expected output type. For example 'vec3'.
  1870. * @param {?string} propertyName - The property name to assign the result.
  1871. * @return {?(Object|Node)} The code flow or node.build() result.
  1872. */
  1873. flowNodeFromShaderStage( shaderStage, node, output = null, propertyName = null ) {
  1874. const previousTab = this.tab;
  1875. const previousCache = this.cache;
  1876. const previousShaderStage = this.shaderStage;
  1877. const previousContext = this.context;
  1878. this.setShaderStage( shaderStage );
  1879. const context = { ...this.context };
  1880. delete context.nodeBlock;
  1881. this.cache = this.globalCache;
  1882. this.tab = '\t';
  1883. this.context = context;
  1884. let result = null;
  1885. if ( this.buildStage === 'generate' ) {
  1886. const flowData = this.flowChildNode( node, output );
  1887. if ( propertyName !== null ) {
  1888. flowData.code += `${ this.tab + propertyName } = ${ flowData.result };\n`;
  1889. }
  1890. this.flowCode[ shaderStage ] = this.flowCode[ shaderStage ] + flowData.code;
  1891. result = flowData;
  1892. } else {
  1893. result = node.build( this );
  1894. }
  1895. this.setShaderStage( previousShaderStage );
  1896. this.cache = previousCache;
  1897. this.tab = previousTab;
  1898. this.context = previousContext;
  1899. return result;
  1900. }
  1901. /**
  1902. * Returns an array holding all node attributes of this node builder.
  1903. *
  1904. * @return {Array<NodeAttribute>} The node attributes of this builder.
  1905. */
  1906. getAttributesArray() {
  1907. return this.attributes.concat( this.bufferAttributes );
  1908. }
  1909. /**
  1910. * Returns the attribute definitions as a shader string for the given shader stage.
  1911. *
  1912. * @abstract
  1913. * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
  1914. * @return {string} The attribute code section.
  1915. */
  1916. getAttributes( /*shaderStage*/ ) {
  1917. warn( 'Abstract function.' );
  1918. }
  1919. /**
  1920. * Returns the varying definitions as a shader string for the given shader stage.
  1921. *
  1922. * @abstract
  1923. * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
  1924. * @return {string} The varying code section.
  1925. */
  1926. getVaryings( /*shaderStage*/ ) {
  1927. warn( 'Abstract function.' );
  1928. }
  1929. /**
  1930. * Returns a single variable definition as a shader string for the given variable type and name.
  1931. *
  1932. * @param {string} type - The variable's type.
  1933. * @param {string} name - The variable's name.
  1934. * @param {?number} [count=null] - The array length.
  1935. * @return {string} The shader string.
  1936. */
  1937. getVar( type, name, count = null ) {
  1938. return `${ count !== null ? this.generateArrayDeclaration( type, count ) : this.getType( type ) } ${ name }`;
  1939. }
  1940. /**
  1941. * Returns the variable definitions as a shader string for the given shader stage.
  1942. *
  1943. * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
  1944. * @param {boolean} [global=false] - Whether the variables are global.
  1945. * @return {string} The variable code section.
  1946. */
  1947. getVars( shaderStage, global = false ) {
  1948. const snippets = [];
  1949. const vars = this.vars[ shaderStage ];
  1950. if ( vars !== undefined ) {
  1951. for ( const variable of vars ) {
  1952. snippets.push( `${ this.getVar( variable.type, variable.name, variable.count ) };` );
  1953. }
  1954. }
  1955. return snippets.join( global ? '\n' : '\n\t' );
  1956. }
  1957. /**
  1958. * Returns the uniform definitions as a shader string for the given shader stage.
  1959. *
  1960. * @abstract
  1961. * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
  1962. * @return {string} The uniform code section.
  1963. */
  1964. getUniforms( /*shaderStage*/ ) {
  1965. warn( 'Abstract function.' );
  1966. }
  1967. /**
  1968. * Returns the native code definitions as a shader string for the given shader stage.
  1969. *
  1970. * @param {('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage.
  1971. * @return {string} The native code section.
  1972. */
  1973. getCodes( shaderStage ) {
  1974. const codes = this.codes[ shaderStage ];
  1975. let code = '';
  1976. if ( codes !== undefined ) {
  1977. for ( const nodeCode of codes ) {
  1978. code += nodeCode.code + '\n';
  1979. }
  1980. }
  1981. return code;
  1982. }
  1983. /**
  1984. * Returns the hash of this node builder.
  1985. *
  1986. * @return {string} The hash.
  1987. */
  1988. getHash() {
  1989. return this.vertexShader + this.fragmentShader + this.computeShader;
  1990. }
  1991. /**
  1992. * Sets the current shader stage.
  1993. *
  1994. * @param {?('vertex'|'fragment'|'compute'|'any')} shaderStage - The shader stage to set.
  1995. */
  1996. setShaderStage( shaderStage ) {
  1997. this.shaderStage = shaderStage;
  1998. }
  1999. /**
  2000. * Returns the current shader stage.
  2001. *
  2002. * @return {?('vertex'|'fragment'|'compute'|'any')} The current shader stage.
  2003. */
  2004. getShaderStage() {
  2005. return this.shaderStage;
  2006. }
  2007. /**
  2008. * Sets the current build stage.
  2009. *
  2010. * @param {?('setup'|'analyze'|'generate')} buildStage - The build stage to set.
  2011. */
  2012. setBuildStage( buildStage ) {
  2013. this.buildStage = buildStage;
  2014. }
  2015. /**
  2016. * Returns the current build stage.
  2017. *
  2018. * @return {?('setup'|'analyze'|'generate')} The current build stage.
  2019. */
  2020. getBuildStage() {
  2021. return this.buildStage;
  2022. }
  2023. /**
  2024. * Controls the code build of the shader stages.
  2025. *
  2026. * @abstract
  2027. */
  2028. buildCode() {
  2029. warn( 'Abstract function.' );
  2030. }
  2031. /**
  2032. * Returns the current sub-build layer.
  2033. *
  2034. * @return {SubBuildNode} The current sub-build layers.
  2035. */
  2036. get subBuild() {
  2037. return this.subBuildLayers[ this.subBuildLayers.length - 1 ] || null;
  2038. }
  2039. /**
  2040. * Adds a sub-build layer to the node builder.
  2041. *
  2042. * @param {SubBuildNode} subBuild - The sub-build layer to add.
  2043. */
  2044. addSubBuild( subBuild ) {
  2045. this.subBuildLayers.push( subBuild );
  2046. }
  2047. /**
  2048. * Removes the last sub-build layer from the node builder.
  2049. *
  2050. * @return {SubBuildNode} The removed sub-build layer.
  2051. */
  2052. removeSubBuild() {
  2053. return this.subBuildLayers.pop();
  2054. }
  2055. /**
  2056. * Returns the closest sub-build layer for the given data.
  2057. *
  2058. * @param {Node|Set<string>|Array<string>} data - The data to get the closest sub-build layer from.
  2059. * @return {?string} The closest sub-build name or null if none found.
  2060. */
  2061. getClosestSubBuild( data ) {
  2062. let subBuilds;
  2063. if ( data && data.isNode ) {
  2064. if ( data.isShaderCallNodeInternal ) {
  2065. subBuilds = data.shaderNode.subBuilds;
  2066. } else if ( data.isStackNode ) {
  2067. subBuilds = [ data.subBuild ];
  2068. } else {
  2069. subBuilds = this.getDataFromNode( data, 'any' ).subBuilds;
  2070. }
  2071. } else if ( data instanceof Set ) {
  2072. subBuilds = [ ...data ];
  2073. } else {
  2074. subBuilds = data;
  2075. }
  2076. if ( ! subBuilds ) return null;
  2077. const subBuildLayers = this.subBuildLayers;
  2078. for ( let i = subBuilds.length - 1; i >= 0; i -- ) {
  2079. const subBuild = subBuilds[ i ];
  2080. if ( subBuildLayers.includes( subBuild ) ) {
  2081. return subBuild;
  2082. }
  2083. }
  2084. return null;
  2085. }
  2086. /**
  2087. * Returns the output node of a sub-build layer.
  2088. *
  2089. * @param {Node} node - The node to get the output from.
  2090. * @return {string} The output node name.
  2091. */
  2092. getSubBuildOutput( node ) {
  2093. return this.getSubBuildProperty( 'outputNode', node );
  2094. }
  2095. /**
  2096. * Returns the sub-build property name for the given property and node.
  2097. *
  2098. * @param {string} [property=''] - The property name.
  2099. * @param {?Node} [node=null] - The node to get the sub-build from.
  2100. * @return {string} The sub-build property name.
  2101. */
  2102. getSubBuildProperty( property = '', node = null ) {
  2103. let subBuild;
  2104. if ( node !== null ) {
  2105. subBuild = this.getClosestSubBuild( node );
  2106. } else {
  2107. subBuild = this.subBuildFn;
  2108. }
  2109. let result;
  2110. if ( subBuild ) {
  2111. result = property ? ( subBuild + '_' + property ) : subBuild;
  2112. } else {
  2113. result = property;
  2114. }
  2115. return result;
  2116. }
  2117. /**
  2118. * Prebuild the node builder.
  2119. */
  2120. prebuild() {
  2121. const { object, renderer, material } = this;
  2122. // < renderer.contextNode >
  2123. if ( renderer.contextNode.isContextNode === true ) {
  2124. this.context = { ...this.context, ...renderer.contextNode.getFlowContextData() };
  2125. } else {
  2126. error( 'NodeBuilder: "renderer.contextNode" must be an instance of `context()`.' );
  2127. }
  2128. // < material.contextNode >
  2129. if ( material && material.contextNode ) {
  2130. if ( material.contextNode.isContextNode === true ) {
  2131. this.context = { ...this.context, ...material.contextNode.getFlowContextData() };
  2132. } else {
  2133. error( 'NodeBuilder: "material.contextNode" must be an instance of `context()`.' );
  2134. }
  2135. }
  2136. // < nodeMaterial >
  2137. if ( material !== null ) {
  2138. let nodeMaterial = renderer.library.fromMaterial( material );
  2139. if ( nodeMaterial === null ) {
  2140. error( `NodeBuilder: Material "${ material.type }" is not compatible.` );
  2141. nodeMaterial = new NodeMaterial();
  2142. }
  2143. nodeMaterial.build( this );
  2144. } else {
  2145. this.addFlow( 'compute', object );
  2146. }
  2147. }
  2148. /**
  2149. * Central build method which controls the build for the given object.
  2150. *
  2151. * @return {NodeBuilder} A reference to this node builder.
  2152. */
  2153. build() {
  2154. this.prebuild();
  2155. // setup() -> stage 1: create possible new nodes and/or return an output reference node
  2156. // analyze() -> stage 2: analyze nodes to possible optimization and validation
  2157. // generate() -> stage 3: generate shader
  2158. for ( const buildStage of defaultBuildStages ) {
  2159. this.setBuildStage( buildStage );
  2160. if ( this.context.position && this.context.position.isNode ) {
  2161. this.flowNodeFromShaderStage( 'vertex', this.context.position );
  2162. }
  2163. for ( const shaderStage of shaderStages ) {
  2164. this.setShaderStage( shaderStage );
  2165. const flowNodes = this.flowNodes[ shaderStage ];
  2166. for ( const node of flowNodes ) {
  2167. if ( buildStage === 'generate' ) {
  2168. this.flowNode( node );
  2169. } else {
  2170. node.build( this );
  2171. }
  2172. }
  2173. }
  2174. }
  2175. this.setBuildStage( null );
  2176. this.setShaderStage( null );
  2177. // stage 4: build code for a specific output
  2178. this.buildCode();
  2179. this.buildUpdateNodes();
  2180. return this;
  2181. }
  2182. /**
  2183. * Async version of build() that yields to main thread between shader stages.
  2184. * Use this in compileAsync() to prevent blocking the main thread.
  2185. *
  2186. * @return {Promise<NodeBuilder>} A promise that resolves to this node builder.
  2187. */
  2188. async buildAsync() {
  2189. this.prebuild();
  2190. // setup() -> stage 1: create possible new nodes and/or return an output reference node
  2191. // analyze() -> stage 2: analyze nodes to possible optimization and validation
  2192. // generate() -> stage 3: generate shader
  2193. for ( const buildStage of defaultBuildStages ) {
  2194. this.setBuildStage( buildStage );
  2195. if ( this.context.position && this.context.position.isNode ) {
  2196. this.flowNodeFromShaderStage( 'vertex', this.context.position );
  2197. }
  2198. for ( const shaderStage of shaderStages ) {
  2199. this.setShaderStage( shaderStage );
  2200. const flowNodes = this.flowNodes[ shaderStage ];
  2201. for ( const node of flowNodes ) {
  2202. if ( buildStage === 'generate' ) {
  2203. this.flowNode( node );
  2204. } else {
  2205. node.build( this );
  2206. }
  2207. }
  2208. // Yield to main thread after each shader stage to prevent blocking
  2209. await yieldToMain();
  2210. }
  2211. }
  2212. this.setBuildStage( null );
  2213. this.setShaderStage( null );
  2214. // stage 4: build code for a specific output
  2215. this.buildCode();
  2216. this.buildUpdateNodes();
  2217. return this;
  2218. }
  2219. /**
  2220. * Returns shared data object for the given node.
  2221. *
  2222. * @param {Node} node - The node to get shared data from.
  2223. * @return {Object} The shared data.
  2224. */
  2225. getSharedDataFromNode( node ) {
  2226. let data = sharedNodeData.get( node );
  2227. if ( data === undefined ) {
  2228. data = {};
  2229. }
  2230. return data;
  2231. }
  2232. /**
  2233. * Returns a uniform representation which is later used for UBO generation and rendering.
  2234. *
  2235. * @param {NodeUniform} uniformNode - The uniform node.
  2236. * @param {string} type - The requested type.
  2237. * @return {Uniform} The uniform.
  2238. */
  2239. getNodeUniform( uniformNode, type ) {
  2240. const nodeData = this.getSharedDataFromNode( uniformNode );
  2241. let node = nodeData.cache;
  2242. if ( node === undefined ) {
  2243. if ( type === 'float' || type === 'int' || type === 'uint' ) node = new NumberNodeUniform( uniformNode );
  2244. else if ( type === 'vec2' || type === 'ivec2' || type === 'uvec2' ) node = new Vector2NodeUniform( uniformNode );
  2245. else if ( type === 'vec3' || type === 'ivec3' || type === 'uvec3' ) node = new Vector3NodeUniform( uniformNode );
  2246. else if ( type === 'vec4' || type === 'ivec4' || type === 'uvec4' ) node = new Vector4NodeUniform( uniformNode );
  2247. else if ( type === 'color' ) node = new ColorNodeUniform( uniformNode );
  2248. else if ( type === 'mat2' ) node = new Matrix2NodeUniform( uniformNode );
  2249. else if ( type === 'mat3' ) node = new Matrix3NodeUniform( uniformNode );
  2250. else if ( type === 'mat4' ) node = new Matrix4NodeUniform( uniformNode );
  2251. else {
  2252. throw new Error( `THREE.NodeBuilder: Uniform "${ type }" not implemented.` );
  2253. }
  2254. nodeData.cache = node;
  2255. }
  2256. return node;
  2257. }
  2258. /**
  2259. * Formats the given shader snippet from a given type into another one. E.g.
  2260. * this method might be used to convert a simple float string `"1.0"` into a
  2261. * `vec3` representation: `"vec3<f32>( 1.0 )"`.
  2262. *
  2263. * @param {string} snippet - The shader snippet.
  2264. * @param {string} fromType - The source type.
  2265. * @param {string} toType - The target type.
  2266. * @return {string} The updated shader string.
  2267. */
  2268. format( snippet, fromType, toType ) {
  2269. fromType = this.getVectorType( fromType );
  2270. toType = this.getVectorType( toType );
  2271. if ( fromType === toType || toType === null || this.isReference( toType ) ) {
  2272. return snippet;
  2273. }
  2274. const fromTypeLength = this.getTypeLength( fromType );
  2275. const toTypeLength = this.getTypeLength( toType );
  2276. if ( fromTypeLength === 16 && toTypeLength === 9 ) {
  2277. return `${ this.getType( toType ) }( ${ snippet }[ 0 ].xyz, ${ snippet }[ 1 ].xyz, ${ snippet }[ 2 ].xyz )`;
  2278. }
  2279. if ( fromTypeLength === 9 && toTypeLength === 4 ) {
  2280. return `${ this.getType( toType ) }( ${ snippet }[ 0 ].xy, ${ snippet }[ 1 ].xy )`;
  2281. }
  2282. if ( fromTypeLength > 4 ) { // fromType is matrix-like
  2283. // @TODO: ignore for now
  2284. return snippet;
  2285. }
  2286. if ( toTypeLength > 4 || toTypeLength === 0 ) { // toType is matrix-like or unknown
  2287. // @TODO: ignore for now
  2288. return snippet;
  2289. }
  2290. if ( fromTypeLength === toTypeLength ) {
  2291. return `${ this.getType( toType ) }( ${ snippet } )`;
  2292. }
  2293. if ( fromTypeLength > toTypeLength ) {
  2294. snippet = toType === 'bool' ? `all( ${ snippet } )` : `${ snippet }.${ 'xyz'.slice( 0, toTypeLength ) }`;
  2295. return this.format( snippet, this.getTypeFromLength( toTypeLength, this.getComponentType( fromType ) ), toType );
  2296. }
  2297. if ( toTypeLength === 4 && fromTypeLength > 1 ) { // toType is vec4-like
  2298. return `${ this.getType( toType ) }( ${ this.format( snippet, fromType, 'vec3' ) }, 1.0 )`;
  2299. }
  2300. if ( fromTypeLength === 2 ) { // fromType is vec2-like and toType is vec3-like
  2301. return `${ this.getType( toType ) }( ${ this.format( snippet, fromType, 'vec2' ) }, 0.0 )`;
  2302. }
  2303. if ( fromTypeLength === 1 && toTypeLength > 1 && fromType !== this.getComponentType( toType ) ) { // fromType is float-like
  2304. // convert a number value to vector type, e.g:
  2305. // vec3( 1u ) -> vec3( float( 1u ) )
  2306. snippet = `${ this.getType( this.getComponentType( toType ) ) }( ${ snippet } )`;
  2307. }
  2308. return `${ this.getType( toType ) }( ${ snippet } )`; // fromType is float-like
  2309. }
  2310. /**
  2311. * Returns a signature with the engine's current revision.
  2312. *
  2313. * @return {string} The signature.
  2314. */
  2315. getSignature() {
  2316. return `// Three.js r${ REVISION } - Node System\n`;
  2317. }
  2318. /**
  2319. * Returns `true` if data from the previous frame are required. Relevant
  2320. * when computing motion vectors with {@link VelocityNode}.
  2321. *
  2322. * @return {boolean} Whether data from the previous frame are required or not.
  2323. */
  2324. needsPreviousData() {
  2325. const mrt = this.renderer.getMRT();
  2326. return ( mrt && mrt.has( 'velocity' ) ) || getDataFromObject( this.object ).useVelocity === true;
  2327. }
  2328. }
  2329. export default NodeBuilder;
粤ICP备19079148号