effect.js 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245
  1. import { Observable } from "../Misc/observable.js";
  2. import { GetDOMTextContent, IsWindowObjectExist } from "../Misc/domManagement.js";
  3. import { Logger } from "../Misc/logger.js";
  4. import { ShaderProcessor } from "../Engines/Processors/shaderProcessor.js";
  5. import { ShaderStore as EngineShaderStore } from "../Engines/shaderStore.js";
  6. import { ShaderLanguage } from "./shaderLanguage.js";
  7. /**
  8. * Effect containing vertex and fragment shader that can be executed on an object.
  9. */
  10. export class Effect {
  11. /**
  12. * Gets or sets the relative url used to load shaders if using the engine in non-minified mode
  13. */
  14. static get ShadersRepository() {
  15. return EngineShaderStore.ShadersRepository;
  16. }
  17. static set ShadersRepository(repo) {
  18. EngineShaderStore.ShadersRepository = repo;
  19. }
  20. /**
  21. * Observable that will be called when effect is bound.
  22. */
  23. get onBindObservable() {
  24. if (!this._onBindObservable) {
  25. this._onBindObservable = new Observable();
  26. }
  27. return this._onBindObservable;
  28. }
  29. /**
  30. * Gets the shader language type used to write vertex and fragment source code.
  31. */
  32. get shaderLanguage() {
  33. return this._shaderLanguage;
  34. }
  35. /**
  36. * Instantiates an effect.
  37. * An effect can be used to create/manage/execute vertex and fragment shaders.
  38. * @param baseName Name of the effect.
  39. * @param attributesNamesOrOptions List of attribute names that will be passed to the shader or set of all options to create the effect.
  40. * @param uniformsNamesOrEngine List of uniform variable names that will be passed to the shader or the engine that will be used to render effect.
  41. * @param samplers List of sampler variables that will be passed to the shader.
  42. * @param engine Engine to be used to render the effect
  43. * @param defines Define statements to be added to the shader.
  44. * @param fallbacks Possible fallbacks for this effect to improve performance when needed.
  45. * @param onCompiled Callback that will be called when the shader is compiled.
  46. * @param onError Callback that will be called if an error occurs during shader compilation.
  47. * @param indexParameters Parameters to be used with Babylons include syntax to iterate over an array (eg. \{lights: 10\})
  48. * @param key Effect Key identifying uniquely compiled shader variants
  49. * @param shaderLanguage the language the shader is written in (default: GLSL)
  50. */
  51. constructor(baseName, attributesNamesOrOptions, uniformsNamesOrEngine, samplers = null, engine, defines = null, fallbacks = null, onCompiled = null, onError = null, indexParameters, key = "", shaderLanguage = ShaderLanguage.GLSL) {
  52. /**
  53. * String container all the define statements that should be set on the shader.
  54. */
  55. this.defines = "";
  56. /**
  57. * Callback that will be called when the shader is compiled.
  58. */
  59. this.onCompiled = null;
  60. /**
  61. * Callback that will be called if an error occurs during shader compilation.
  62. */
  63. this.onError = null;
  64. /**
  65. * Callback that will be called when effect is bound.
  66. */
  67. this.onBind = null;
  68. /**
  69. * Unique ID of the effect.
  70. */
  71. this.uniqueId = 0;
  72. /**
  73. * Observable that will be called when the shader is compiled.
  74. * It is recommended to use executeWhenCompile() or to make sure that scene.isReady() is called to get this observable raised.
  75. */
  76. this.onCompileObservable = new Observable();
  77. /**
  78. * Observable that will be called if an error occurs during shader compilation.
  79. */
  80. this.onErrorObservable = new Observable();
  81. /** @internal */
  82. this._onBindObservable = null;
  83. this._isDisposed = false;
  84. /** @internal */
  85. this._bonesComputationForcedToCPU = false;
  86. /** @internal */
  87. this._uniformBuffersNames = {};
  88. /** @internal */
  89. this._multiTarget = false;
  90. this._samplers = {};
  91. this._isReady = false;
  92. this._compilationError = "";
  93. this._allFallbacksProcessed = false;
  94. this._uniforms = {};
  95. /**
  96. * Key for the effect.
  97. * @internal
  98. */
  99. this._key = "";
  100. this._fallbacks = null;
  101. this._vertexSourceCodeOverride = "";
  102. this._fragmentSourceCodeOverride = "";
  103. this._transformFeedbackVaryings = null;
  104. /**
  105. * Compiled shader to webGL program.
  106. * @internal
  107. */
  108. this._pipelineContext = null;
  109. /** @internal */
  110. this._vertexSourceCode = "";
  111. /** @internal */
  112. this._fragmentSourceCode = "";
  113. /** @internal */
  114. this._vertexSourceCodeBeforeMigration = "";
  115. /** @internal */
  116. this._fragmentSourceCodeBeforeMigration = "";
  117. /** @internal */
  118. this._rawVertexSourceCode = "";
  119. /** @internal */
  120. this._rawFragmentSourceCode = "";
  121. this._processCodeAfterIncludes = undefined;
  122. this._processFinalCode = null;
  123. this.name = baseName;
  124. this._key = key;
  125. if (attributesNamesOrOptions.attributes) {
  126. const options = attributesNamesOrOptions;
  127. this._engine = uniformsNamesOrEngine;
  128. this._attributesNames = options.attributes;
  129. this._uniformsNames = options.uniformsNames.concat(options.samplers);
  130. this._samplerList = options.samplers.slice();
  131. this.defines = options.defines;
  132. this.onError = options.onError;
  133. this.onCompiled = options.onCompiled;
  134. this._fallbacks = options.fallbacks;
  135. this._indexParameters = options.indexParameters;
  136. this._transformFeedbackVaryings = options.transformFeedbackVaryings || null;
  137. this._multiTarget = !!options.multiTarget;
  138. this._shaderLanguage = options.shaderLanguage ?? ShaderLanguage.GLSL;
  139. if (options.uniformBuffersNames) {
  140. this._uniformBuffersNamesList = options.uniformBuffersNames.slice();
  141. for (let i = 0; i < options.uniformBuffersNames.length; i++) {
  142. this._uniformBuffersNames[options.uniformBuffersNames[i]] = i;
  143. }
  144. }
  145. this._processFinalCode = options.processFinalCode ?? null;
  146. this._processCodeAfterIncludes = options.processCodeAfterIncludes ?? undefined;
  147. }
  148. else {
  149. this._engine = engine;
  150. this.defines = defines == null ? "" : defines;
  151. this._uniformsNames = uniformsNamesOrEngine.concat(samplers);
  152. this._samplerList = samplers ? samplers.slice() : [];
  153. this._attributesNames = attributesNamesOrOptions;
  154. this._uniformBuffersNamesList = [];
  155. this._shaderLanguage = shaderLanguage;
  156. this.onError = onError;
  157. this.onCompiled = onCompiled;
  158. this._indexParameters = indexParameters;
  159. this._fallbacks = fallbacks;
  160. }
  161. this._attributeLocationByName = {};
  162. this.uniqueId = Effect._UniqueIdSeed++;
  163. this._processShaderCode();
  164. }
  165. /** @internal */
  166. _processShaderCode(shaderProcessor = null, keepExistingPipelineContext = false) {
  167. let vertexSource;
  168. let fragmentSource;
  169. const baseName = this.name;
  170. const hostDocument = IsWindowObjectExist() ? this._engine.getHostDocument() : null;
  171. if (typeof baseName === "string") {
  172. vertexSource = baseName;
  173. }
  174. else if (baseName.vertexSource) {
  175. vertexSource = "source:" + baseName.vertexSource;
  176. }
  177. else if (baseName.vertexElement) {
  178. vertexSource = hostDocument?.getElementById(baseName.vertexElement) || baseName.vertexElement;
  179. }
  180. else {
  181. vertexSource = baseName.vertex || baseName;
  182. }
  183. if (typeof baseName === "string") {
  184. fragmentSource = baseName;
  185. }
  186. else if (baseName.fragmentSource) {
  187. fragmentSource = "source:" + baseName.fragmentSource;
  188. }
  189. else if (baseName.fragmentElement) {
  190. fragmentSource = hostDocument?.getElementById(baseName.fragmentElement) || baseName.fragmentElement;
  191. }
  192. else {
  193. fragmentSource = baseName.fragment || baseName;
  194. }
  195. this._processingContext = this._engine._getShaderProcessingContext(this._shaderLanguage);
  196. let processorOptions = {
  197. defines: this.defines.split("\n"),
  198. indexParameters: this._indexParameters,
  199. isFragment: false,
  200. shouldUseHighPrecisionShader: this._engine._shouldUseHighPrecisionShader,
  201. processor: shaderProcessor ?? this._engine._getShaderProcessor(this._shaderLanguage),
  202. supportsUniformBuffers: this._engine.supportsUniformBuffers,
  203. shadersRepository: EngineShaderStore.GetShadersRepository(this._shaderLanguage),
  204. includesShadersStore: EngineShaderStore.GetIncludesShadersStore(this._shaderLanguage),
  205. version: (this._engine.version * 100).toString(),
  206. platformName: this._engine.shaderPlatformName,
  207. processingContext: this._processingContext,
  208. isNDCHalfZRange: this._engine.isNDCHalfZRange,
  209. useReverseDepthBuffer: this._engine.useReverseDepthBuffer,
  210. processCodeAfterIncludes: this._processCodeAfterIncludes,
  211. };
  212. const shaderCodes = [undefined, undefined];
  213. const shadersLoaded = () => {
  214. if (shaderCodes[0] && shaderCodes[1]) {
  215. processorOptions.isFragment = true;
  216. const [migratedVertexCode, fragmentCode] = shaderCodes;
  217. ShaderProcessor.Process(fragmentCode, processorOptions, (migratedFragmentCode, codeBeforeMigration) => {
  218. this._fragmentSourceCodeBeforeMigration = codeBeforeMigration;
  219. if (this._processFinalCode) {
  220. migratedFragmentCode = this._processFinalCode("fragment", migratedFragmentCode);
  221. }
  222. const finalShaders = ShaderProcessor.Finalize(migratedVertexCode, migratedFragmentCode, processorOptions);
  223. processorOptions = null;
  224. this._useFinalCode(finalShaders.vertexCode, finalShaders.fragmentCode, baseName, keepExistingPipelineContext);
  225. }, this._engine);
  226. }
  227. };
  228. this._loadShader(vertexSource, "Vertex", "", (vertexCode) => {
  229. ShaderProcessor.Initialize(processorOptions);
  230. ShaderProcessor.Process(vertexCode, processorOptions, (migratedVertexCode, codeBeforeMigration) => {
  231. this._rawVertexSourceCode = vertexCode;
  232. this._vertexSourceCodeBeforeMigration = codeBeforeMigration;
  233. if (this._processFinalCode) {
  234. migratedVertexCode = this._processFinalCode("vertex", migratedVertexCode);
  235. }
  236. shaderCodes[0] = migratedVertexCode;
  237. shadersLoaded();
  238. }, this._engine);
  239. });
  240. this._loadShader(fragmentSource, "Fragment", "Pixel", (fragmentCode) => {
  241. this._rawFragmentSourceCode = fragmentCode;
  242. shaderCodes[1] = fragmentCode;
  243. shadersLoaded();
  244. });
  245. }
  246. _useFinalCode(migratedVertexCode, migratedFragmentCode, baseName, keepExistingPipelineContext = false) {
  247. if (baseName) {
  248. const vertex = baseName.vertexElement || baseName.vertex || baseName.spectorName || baseName;
  249. const fragment = baseName.fragmentElement || baseName.fragment || baseName.spectorName || baseName;
  250. this._vertexSourceCode = (this._shaderLanguage === ShaderLanguage.WGSL ? "//" : "") + "#define SHADER_NAME vertex:" + vertex + "\n" + migratedVertexCode;
  251. this._fragmentSourceCode = (this._shaderLanguage === ShaderLanguage.WGSL ? "//" : "") + "#define SHADER_NAME fragment:" + fragment + "\n" + migratedFragmentCode;
  252. }
  253. else {
  254. this._vertexSourceCode = migratedVertexCode;
  255. this._fragmentSourceCode = migratedFragmentCode;
  256. }
  257. this._prepareEffect(keepExistingPipelineContext);
  258. }
  259. /**
  260. * Unique key for this effect
  261. */
  262. get key() {
  263. return this._key;
  264. }
  265. /**
  266. * If the effect has been compiled and prepared.
  267. * @returns if the effect is compiled and prepared.
  268. */
  269. isReady() {
  270. try {
  271. return this._isReadyInternal();
  272. }
  273. catch {
  274. return false;
  275. }
  276. }
  277. _isReadyInternal() {
  278. if (this._isReady) {
  279. return true;
  280. }
  281. if (this._pipelineContext) {
  282. return this._pipelineContext.isReady;
  283. }
  284. return false;
  285. }
  286. /**
  287. * The engine the effect was initialized with.
  288. * @returns the engine.
  289. */
  290. getEngine() {
  291. return this._engine;
  292. }
  293. /**
  294. * The pipeline context for this effect
  295. * @returns the associated pipeline context
  296. */
  297. getPipelineContext() {
  298. return this._pipelineContext;
  299. }
  300. /**
  301. * The set of names of attribute variables for the shader.
  302. * @returns An array of attribute names.
  303. */
  304. getAttributesNames() {
  305. return this._attributesNames;
  306. }
  307. /**
  308. * Returns the attribute at the given index.
  309. * @param index The index of the attribute.
  310. * @returns The location of the attribute.
  311. */
  312. getAttributeLocation(index) {
  313. return this._attributes[index];
  314. }
  315. /**
  316. * Returns the attribute based on the name of the variable.
  317. * @param name of the attribute to look up.
  318. * @returns the attribute location.
  319. */
  320. getAttributeLocationByName(name) {
  321. return this._attributeLocationByName[name];
  322. }
  323. /**
  324. * The number of attributes.
  325. * @returns the number of attributes.
  326. */
  327. getAttributesCount() {
  328. return this._attributes.length;
  329. }
  330. /**
  331. * Gets the index of a uniform variable.
  332. * @param uniformName of the uniform to look up.
  333. * @returns the index.
  334. */
  335. getUniformIndex(uniformName) {
  336. return this._uniformsNames.indexOf(uniformName);
  337. }
  338. /**
  339. * Returns the attribute based on the name of the variable.
  340. * @param uniformName of the uniform to look up.
  341. * @returns the location of the uniform.
  342. */
  343. getUniform(uniformName) {
  344. return this._uniforms[uniformName];
  345. }
  346. /**
  347. * Returns an array of sampler variable names
  348. * @returns The array of sampler variable names.
  349. */
  350. getSamplers() {
  351. return this._samplerList;
  352. }
  353. /**
  354. * Returns an array of uniform variable names
  355. * @returns The array of uniform variable names.
  356. */
  357. getUniformNames() {
  358. return this._uniformsNames;
  359. }
  360. /**
  361. * Returns an array of uniform buffer variable names
  362. * @returns The array of uniform buffer variable names.
  363. */
  364. getUniformBuffersNames() {
  365. return this._uniformBuffersNamesList;
  366. }
  367. /**
  368. * Returns the index parameters used to create the effect
  369. * @returns The index parameters object
  370. */
  371. getIndexParameters() {
  372. return this._indexParameters;
  373. }
  374. /**
  375. * The error from the last compilation.
  376. * @returns the error string.
  377. */
  378. getCompilationError() {
  379. return this._compilationError;
  380. }
  381. /**
  382. * Gets a boolean indicating that all fallbacks were used during compilation
  383. * @returns true if all fallbacks were used
  384. */
  385. allFallbacksProcessed() {
  386. return this._allFallbacksProcessed;
  387. }
  388. /**
  389. * Adds a callback to the onCompiled observable and call the callback immediately if already ready.
  390. * @param func The callback to be used.
  391. */
  392. executeWhenCompiled(func) {
  393. if (this.isReady()) {
  394. func(this);
  395. return;
  396. }
  397. this.onCompileObservable.add((effect) => {
  398. func(effect);
  399. });
  400. if (!this._pipelineContext || this._pipelineContext.isAsync) {
  401. setTimeout(() => {
  402. this._checkIsReady(null);
  403. }, 16);
  404. }
  405. }
  406. _checkIsReady(previousPipelineContext) {
  407. try {
  408. if (this._isReadyInternal()) {
  409. return;
  410. }
  411. }
  412. catch (e) {
  413. this._processCompilationErrors(e, previousPipelineContext);
  414. return;
  415. }
  416. if (this._isDisposed) {
  417. return;
  418. }
  419. setTimeout(() => {
  420. this._checkIsReady(previousPipelineContext);
  421. }, 16);
  422. }
  423. _loadShader(shader, key, optionalKey, callback) {
  424. if (typeof HTMLElement !== "undefined") {
  425. // DOM element ?
  426. if (shader instanceof HTMLElement) {
  427. const shaderCode = GetDOMTextContent(shader);
  428. callback(shaderCode);
  429. return;
  430. }
  431. }
  432. // Direct source ?
  433. if (shader.substr(0, 7) === "source:") {
  434. callback(shader.substr(7));
  435. return;
  436. }
  437. // Base64 encoded ?
  438. if (shader.substr(0, 7) === "base64:") {
  439. const shaderBinary = window.atob(shader.substr(7));
  440. callback(shaderBinary);
  441. return;
  442. }
  443. const shaderStore = EngineShaderStore.GetShadersStore(this._shaderLanguage);
  444. // Is in local store ?
  445. if (shaderStore[shader + key + "Shader"]) {
  446. callback(shaderStore[shader + key + "Shader"]);
  447. return;
  448. }
  449. if (optionalKey && shaderStore[shader + optionalKey + "Shader"]) {
  450. callback(shaderStore[shader + optionalKey + "Shader"]);
  451. return;
  452. }
  453. let shaderUrl;
  454. if (shader[0] === "." || shader[0] === "/" || shader.indexOf("http") > -1) {
  455. shaderUrl = shader;
  456. }
  457. else {
  458. shaderUrl = EngineShaderStore.GetShadersRepository(this._shaderLanguage) + shader;
  459. }
  460. // Vertex shader
  461. this._engine._loadFile(shaderUrl + "." + key.toLowerCase() + ".fx", callback);
  462. }
  463. /**
  464. * Gets the vertex shader source code of this effect
  465. * This is the final source code that will be compiled, after all the processing has been done (pre-processing applied, code injection/replacement, etc)
  466. */
  467. get vertexSourceCode() {
  468. return this._vertexSourceCodeOverride && this._fragmentSourceCodeOverride
  469. ? this._vertexSourceCodeOverride
  470. : this._pipelineContext?._getVertexShaderCode() ?? this._vertexSourceCode;
  471. }
  472. /**
  473. * Gets the fragment shader source code of this effect
  474. * This is the final source code that will be compiled, after all the processing has been done (pre-processing applied, code injection/replacement, etc)
  475. */
  476. get fragmentSourceCode() {
  477. return this._vertexSourceCodeOverride && this._fragmentSourceCodeOverride
  478. ? this._fragmentSourceCodeOverride
  479. : this._pipelineContext?._getFragmentShaderCode() ?? this._fragmentSourceCode;
  480. }
  481. /**
  482. * Gets the vertex shader source code before migration.
  483. * This is the source code after the include directives have been replaced by their contents but before the code is migrated, i.e. before ShaderProcess._ProcessShaderConversion is executed.
  484. * This method is, among other things, responsible for parsing #if/#define directives as well as converting GLES2 syntax to GLES3 (in the case of WebGL).
  485. */
  486. get vertexSourceCodeBeforeMigration() {
  487. return this._vertexSourceCodeBeforeMigration;
  488. }
  489. /**
  490. * Gets the fragment shader source code before migration.
  491. * This is the source code after the include directives have been replaced by their contents but before the code is migrated, i.e. before ShaderProcess._ProcessShaderConversion is executed.
  492. * This method is, among other things, responsible for parsing #if/#define directives as well as converting GLES2 syntax to GLES3 (in the case of WebGL).
  493. */
  494. get fragmentSourceCodeBeforeMigration() {
  495. return this._fragmentSourceCodeBeforeMigration;
  496. }
  497. /**
  498. * Gets the vertex shader source code before it has been modified by any processing
  499. */
  500. get rawVertexSourceCode() {
  501. return this._rawVertexSourceCode;
  502. }
  503. /**
  504. * Gets the fragment shader source code before it has been modified by any processing
  505. */
  506. get rawFragmentSourceCode() {
  507. return this._rawFragmentSourceCode;
  508. }
  509. /**
  510. * Recompiles the webGL program
  511. * @param vertexSourceCode The source code for the vertex shader.
  512. * @param fragmentSourceCode The source code for the fragment shader.
  513. * @param onCompiled Callback called when completed.
  514. * @param onError Callback called on error.
  515. * @internal
  516. */
  517. _rebuildProgram(vertexSourceCode, fragmentSourceCode, onCompiled, onError) {
  518. this._isReady = false;
  519. this._vertexSourceCodeOverride = vertexSourceCode;
  520. this._fragmentSourceCodeOverride = fragmentSourceCode;
  521. this.onError = (effect, error) => {
  522. if (onError) {
  523. onError(error);
  524. }
  525. };
  526. this.onCompiled = () => {
  527. const scenes = this.getEngine().scenes;
  528. if (scenes) {
  529. for (let i = 0; i < scenes.length; i++) {
  530. scenes[i].markAllMaterialsAsDirty(63);
  531. }
  532. }
  533. this._pipelineContext._handlesSpectorRebuildCallback?.(onCompiled);
  534. };
  535. this._fallbacks = null;
  536. this._prepareEffect();
  537. }
  538. /**
  539. * Prepares the effect
  540. * @internal
  541. */
  542. _prepareEffect(keepExistingPipelineContext = false) {
  543. const attributesNames = this._attributesNames;
  544. const defines = this.defines;
  545. const previousPipelineContext = this._pipelineContext;
  546. this._isReady = false;
  547. try {
  548. const engine = this._engine;
  549. this._pipelineContext = (keepExistingPipelineContext ? previousPipelineContext : undefined) ?? engine.createPipelineContext(this._processingContext);
  550. this._pipelineContext._name = this._key.replace(/\r/g, "").replace(/\n/g, "|");
  551. const rebuildRebind = (vertexSourceCode, fragmentSourceCode, onCompiled, onError) => this._rebuildProgram(vertexSourceCode, fragmentSourceCode, onCompiled, onError);
  552. if (this._vertexSourceCodeOverride && this._fragmentSourceCodeOverride) {
  553. engine._preparePipelineContext(this._pipelineContext, this._vertexSourceCodeOverride, this._fragmentSourceCodeOverride, true, this._rawVertexSourceCode, this._rawFragmentSourceCode, rebuildRebind, null, this._transformFeedbackVaryings, this._key);
  554. }
  555. else {
  556. engine._preparePipelineContext(this._pipelineContext, this._vertexSourceCode, this._fragmentSourceCode, false, this._rawVertexSourceCode, this._rawFragmentSourceCode, rebuildRebind, defines, this._transformFeedbackVaryings, this._key);
  557. }
  558. engine._executeWhenRenderingStateIsCompiled(this._pipelineContext, () => {
  559. this._attributes = [];
  560. this._pipelineContext._fillEffectInformation(this, this._uniformBuffersNames, this._uniformsNames, this._uniforms, this._samplerList, this._samplers, attributesNames, this._attributes);
  561. // Caches attribute locations.
  562. if (attributesNames) {
  563. for (let i = 0; i < attributesNames.length; i++) {
  564. const name = attributesNames[i];
  565. this._attributeLocationByName[name] = this._attributes[i];
  566. }
  567. }
  568. engine.bindSamplers(this);
  569. this._compilationError = "";
  570. this._isReady = true;
  571. if (this.onCompiled) {
  572. this.onCompiled(this);
  573. }
  574. this.onCompileObservable.notifyObservers(this);
  575. this.onCompileObservable.clear();
  576. // Unbind mesh reference in fallbacks
  577. if (this._fallbacks) {
  578. this._fallbacks.unBindMesh();
  579. }
  580. if (previousPipelineContext && !keepExistingPipelineContext) {
  581. this.getEngine()._deletePipelineContext(previousPipelineContext);
  582. }
  583. });
  584. if (this._pipelineContext.isAsync) {
  585. this._checkIsReady(previousPipelineContext);
  586. }
  587. }
  588. catch (e) {
  589. this._processCompilationErrors(e, previousPipelineContext);
  590. }
  591. }
  592. _getShaderCodeAndErrorLine(code, error, isFragment) {
  593. const regexp = isFragment ? /FRAGMENT SHADER ERROR: 0:(\d+?):/ : /VERTEX SHADER ERROR: 0:(\d+?):/;
  594. let errorLine = null;
  595. if (error && code) {
  596. const res = error.match(regexp);
  597. if (res && res.length === 2) {
  598. const lineNumber = parseInt(res[1]);
  599. const lines = code.split("\n", -1);
  600. if (lines.length >= lineNumber) {
  601. errorLine = `Offending line [${lineNumber}] in ${isFragment ? "fragment" : "vertex"} code: ${lines[lineNumber - 1]}`;
  602. }
  603. }
  604. }
  605. return [code, errorLine];
  606. }
  607. _processCompilationErrors(e, previousPipelineContext = null) {
  608. this._compilationError = e.message;
  609. const attributesNames = this._attributesNames;
  610. const fallbacks = this._fallbacks;
  611. // Let's go through fallbacks then
  612. Logger.Error("Unable to compile effect:");
  613. Logger.Error("Uniforms: " +
  614. this._uniformsNames.map(function (uniform) {
  615. return " " + uniform;
  616. }));
  617. Logger.Error("Attributes: " +
  618. attributesNames.map(function (attribute) {
  619. return " " + attribute;
  620. }));
  621. Logger.Error("Defines:\n" + this.defines);
  622. if (Effect.LogShaderCodeOnCompilationError) {
  623. let lineErrorVertex = null, lineErrorFragment = null, code = null;
  624. if (this._pipelineContext?._getVertexShaderCode()) {
  625. [code, lineErrorVertex] = this._getShaderCodeAndErrorLine(this._pipelineContext._getVertexShaderCode(), this._compilationError, false);
  626. if (code) {
  627. Logger.Error("Vertex code:");
  628. Logger.Error(code);
  629. }
  630. }
  631. if (this._pipelineContext?._getFragmentShaderCode()) {
  632. [code, lineErrorFragment] = this._getShaderCodeAndErrorLine(this._pipelineContext?._getFragmentShaderCode(), this._compilationError, true);
  633. if (code) {
  634. Logger.Error("Fragment code:");
  635. Logger.Error(code);
  636. }
  637. }
  638. if (lineErrorVertex) {
  639. Logger.Error(lineErrorVertex);
  640. }
  641. if (lineErrorFragment) {
  642. Logger.Error(lineErrorFragment);
  643. }
  644. }
  645. Logger.Error("Error: " + this._compilationError);
  646. const notifyErrors = () => {
  647. if (this.onError) {
  648. this.onError(this, this._compilationError);
  649. }
  650. this.onErrorObservable.notifyObservers(this);
  651. };
  652. // In case a previous compilation was successful, we need to restore the previous pipeline context
  653. if (previousPipelineContext) {
  654. this._pipelineContext = previousPipelineContext;
  655. this._isReady = true;
  656. notifyErrors();
  657. }
  658. // Lets try to compile fallbacks as long as we have some.
  659. if (fallbacks) {
  660. this._pipelineContext = null;
  661. if (fallbacks.hasMoreFallbacks) {
  662. this._allFallbacksProcessed = false;
  663. Logger.Error("Trying next fallback.");
  664. this.defines = fallbacks.reduce(this.defines, this);
  665. this._prepareEffect();
  666. }
  667. else {
  668. // Sorry we did everything we can
  669. this._allFallbacksProcessed = true;
  670. notifyErrors();
  671. this.onErrorObservable.clear();
  672. // Unbind mesh reference in fallbacks
  673. if (this._fallbacks) {
  674. this._fallbacks.unBindMesh();
  675. }
  676. }
  677. }
  678. else {
  679. this._allFallbacksProcessed = true;
  680. // In case of error, without any prior successful compilation, let s notify observers
  681. if (!previousPipelineContext) {
  682. notifyErrors();
  683. }
  684. }
  685. }
  686. /**
  687. * Checks if the effect is supported. (Must be called after compilation)
  688. */
  689. get isSupported() {
  690. return this._compilationError === "";
  691. }
  692. /**
  693. * Binds a texture to the engine to be used as output of the shader.
  694. * @param channel Name of the output variable.
  695. * @param texture Texture to bind.
  696. * @internal
  697. */
  698. _bindTexture(channel, texture) {
  699. this._engine._bindTexture(this._samplers[channel], texture, channel);
  700. }
  701. /**
  702. * Sets a texture on the engine to be used in the shader.
  703. * @param channel Name of the sampler variable.
  704. * @param texture Texture to set.
  705. */
  706. setTexture(channel, texture) {
  707. this._engine.setTexture(this._samplers[channel], this._uniforms[channel], texture, channel);
  708. }
  709. /**
  710. * Sets a depth stencil texture from a render target on the engine to be used in the shader.
  711. * @param channel Name of the sampler variable.
  712. * @param texture Texture to set.
  713. */
  714. setDepthStencilTexture(channel, texture) {
  715. this._engine.setDepthStencilTexture(this._samplers[channel], this._uniforms[channel], texture, channel);
  716. }
  717. /**
  718. * Sets an array of textures on the engine to be used in the shader.
  719. * @param channel Name of the variable.
  720. * @param textures Textures to set.
  721. */
  722. setTextureArray(channel, textures) {
  723. const exName = channel + "Ex";
  724. if (this._samplerList.indexOf(exName + "0") === -1) {
  725. const initialPos = this._samplerList.indexOf(channel);
  726. for (let index = 1; index < textures.length; index++) {
  727. const currentExName = exName + (index - 1).toString();
  728. this._samplerList.splice(initialPos + index, 0, currentExName);
  729. }
  730. // Reset every channels
  731. let channelIndex = 0;
  732. for (const key of this._samplerList) {
  733. this._samplers[key] = channelIndex;
  734. channelIndex += 1;
  735. }
  736. }
  737. this._engine.setTextureArray(this._samplers[channel], this._uniforms[channel], textures, channel);
  738. }
  739. /**
  740. * Sets a texture to be the input of the specified post process. (To use the output, pass in the next post process in the pipeline)
  741. * @param channel Name of the sampler variable.
  742. * @param postProcess Post process to get the input texture from.
  743. */
  744. setTextureFromPostProcess(channel, postProcess) {
  745. this._engine.setTextureFromPostProcess(this._samplers[channel], postProcess, channel);
  746. }
  747. /**
  748. * (Warning! setTextureFromPostProcessOutput may be desired instead)
  749. * Sets the input texture of the passed in post process to be input of this effect. (To use the output of the passed in post process use setTextureFromPostProcessOutput)
  750. * @param channel Name of the sampler variable.
  751. * @param postProcess Post process to get the output texture from.
  752. */
  753. setTextureFromPostProcessOutput(channel, postProcess) {
  754. this._engine.setTextureFromPostProcessOutput(this._samplers[channel], postProcess, channel);
  755. }
  756. /**
  757. * Binds a buffer to a uniform.
  758. * @param buffer Buffer to bind.
  759. * @param name Name of the uniform variable to bind to.
  760. */
  761. bindUniformBuffer(buffer, name) {
  762. const bufferName = this._uniformBuffersNames[name];
  763. if (bufferName === undefined || (Effect._BaseCache[bufferName] === buffer && this._engine._features.useUBOBindingCache)) {
  764. return;
  765. }
  766. Effect._BaseCache[bufferName] = buffer;
  767. this._engine.bindUniformBufferBase(buffer, bufferName, name);
  768. }
  769. /**
  770. * Binds block to a uniform.
  771. * @param blockName Name of the block to bind.
  772. * @param index Index to bind.
  773. */
  774. bindUniformBlock(blockName, index) {
  775. this._engine.bindUniformBlock(this._pipelineContext, blockName, index);
  776. }
  777. /**
  778. * Sets an integer value on a uniform variable.
  779. * @param uniformName Name of the variable.
  780. * @param value Value to be set.
  781. * @returns this effect.
  782. */
  783. setInt(uniformName, value) {
  784. this._pipelineContext.setInt(uniformName, value);
  785. return this;
  786. }
  787. /**
  788. * Sets an int2 value on a uniform variable.
  789. * @param uniformName Name of the variable.
  790. * @param x First int in int2.
  791. * @param y Second int in int2.
  792. * @returns this effect.
  793. */
  794. setInt2(uniformName, x, y) {
  795. this._pipelineContext.setInt2(uniformName, x, y);
  796. return this;
  797. }
  798. /**
  799. * Sets an int3 value on a uniform variable.
  800. * @param uniformName Name of the variable.
  801. * @param x First int in int3.
  802. * @param y Second int in int3.
  803. * @param z Third int in int3.
  804. * @returns this effect.
  805. */
  806. setInt3(uniformName, x, y, z) {
  807. this._pipelineContext.setInt3(uniformName, x, y, z);
  808. return this;
  809. }
  810. /**
  811. * Sets an int4 value on a uniform variable.
  812. * @param uniformName Name of the variable.
  813. * @param x First int in int4.
  814. * @param y Second int in int4.
  815. * @param z Third int in int4.
  816. * @param w Fourth int in int4.
  817. * @returns this effect.
  818. */
  819. setInt4(uniformName, x, y, z, w) {
  820. this._pipelineContext.setInt4(uniformName, x, y, z, w);
  821. return this;
  822. }
  823. /**
  824. * Sets an int array on a uniform variable.
  825. * @param uniformName Name of the variable.
  826. * @param array array to be set.
  827. * @returns this effect.
  828. */
  829. setIntArray(uniformName, array) {
  830. this._pipelineContext.setIntArray(uniformName, array);
  831. return this;
  832. }
  833. /**
  834. * Sets an int array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
  835. * @param uniformName Name of the variable.
  836. * @param array array to be set.
  837. * @returns this effect.
  838. */
  839. setIntArray2(uniformName, array) {
  840. this._pipelineContext.setIntArray2(uniformName, array);
  841. return this;
  842. }
  843. /**
  844. * Sets an int array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
  845. * @param uniformName Name of the variable.
  846. * @param array array to be set.
  847. * @returns this effect.
  848. */
  849. setIntArray3(uniformName, array) {
  850. this._pipelineContext.setIntArray3(uniformName, array);
  851. return this;
  852. }
  853. /**
  854. * Sets an int array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
  855. * @param uniformName Name of the variable.
  856. * @param array array to be set.
  857. * @returns this effect.
  858. */
  859. setIntArray4(uniformName, array) {
  860. this._pipelineContext.setIntArray4(uniformName, array);
  861. return this;
  862. }
  863. /**
  864. * Sets an unsigned integer value on a uniform variable.
  865. * @param uniformName Name of the variable.
  866. * @param value Value to be set.
  867. * @returns this effect.
  868. */
  869. setUInt(uniformName, value) {
  870. this._pipelineContext.setUInt(uniformName, value);
  871. return this;
  872. }
  873. /**
  874. * Sets an unsigned int2 value on a uniform variable.
  875. * @param uniformName Name of the variable.
  876. * @param x First unsigned int in uint2.
  877. * @param y Second unsigned int in uint2.
  878. * @returns this effect.
  879. */
  880. setUInt2(uniformName, x, y) {
  881. this._pipelineContext.setUInt2(uniformName, x, y);
  882. return this;
  883. }
  884. /**
  885. * Sets an unsigned int3 value on a uniform variable.
  886. * @param uniformName Name of the variable.
  887. * @param x First unsigned int in uint3.
  888. * @param y Second unsigned int in uint3.
  889. * @param z Third unsigned int in uint3.
  890. * @returns this effect.
  891. */
  892. setUInt3(uniformName, x, y, z) {
  893. this._pipelineContext.setUInt3(uniformName, x, y, z);
  894. return this;
  895. }
  896. /**
  897. * Sets an unsigned int4 value on a uniform variable.
  898. * @param uniformName Name of the variable.
  899. * @param x First unsigned int in uint4.
  900. * @param y Second unsigned int in uint4.
  901. * @param z Third unsigned int in uint4.
  902. * @param w Fourth unsigned int in uint4.
  903. * @returns this effect.
  904. */
  905. setUInt4(uniformName, x, y, z, w) {
  906. this._pipelineContext.setUInt4(uniformName, x, y, z, w);
  907. return this;
  908. }
  909. /**
  910. * Sets an unsigned int array on a uniform variable.
  911. * @param uniformName Name of the variable.
  912. * @param array array to be set.
  913. * @returns this effect.
  914. */
  915. setUIntArray(uniformName, array) {
  916. this._pipelineContext.setUIntArray(uniformName, array);
  917. return this;
  918. }
  919. /**
  920. * Sets an unsigned int array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
  921. * @param uniformName Name of the variable.
  922. * @param array array to be set.
  923. * @returns this effect.
  924. */
  925. setUIntArray2(uniformName, array) {
  926. this._pipelineContext.setUIntArray2(uniformName, array);
  927. return this;
  928. }
  929. /**
  930. * Sets an unsigned int array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
  931. * @param uniformName Name of the variable.
  932. * @param array array to be set.
  933. * @returns this effect.
  934. */
  935. setUIntArray3(uniformName, array) {
  936. this._pipelineContext.setUIntArray3(uniformName, array);
  937. return this;
  938. }
  939. /**
  940. * Sets an unsigned int array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
  941. * @param uniformName Name of the variable.
  942. * @param array array to be set.
  943. * @returns this effect.
  944. */
  945. setUIntArray4(uniformName, array) {
  946. this._pipelineContext.setUIntArray4(uniformName, array);
  947. return this;
  948. }
  949. /**
  950. * Sets an float array on a uniform variable.
  951. * @param uniformName Name of the variable.
  952. * @param array array to be set.
  953. * @returns this effect.
  954. */
  955. setFloatArray(uniformName, array) {
  956. this._pipelineContext.setArray(uniformName, array);
  957. return this;
  958. }
  959. /**
  960. * Sets an float array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
  961. * @param uniformName Name of the variable.
  962. * @param array array to be set.
  963. * @returns this effect.
  964. */
  965. setFloatArray2(uniformName, array) {
  966. this._pipelineContext.setArray2(uniformName, array);
  967. return this;
  968. }
  969. /**
  970. * Sets an float array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
  971. * @param uniformName Name of the variable.
  972. * @param array array to be set.
  973. * @returns this effect.
  974. */
  975. setFloatArray3(uniformName, array) {
  976. this._pipelineContext.setArray3(uniformName, array);
  977. return this;
  978. }
  979. /**
  980. * Sets an float array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
  981. * @param uniformName Name of the variable.
  982. * @param array array to be set.
  983. * @returns this effect.
  984. */
  985. setFloatArray4(uniformName, array) {
  986. this._pipelineContext.setArray4(uniformName, array);
  987. return this;
  988. }
  989. /**
  990. * Sets an array on a uniform variable.
  991. * @param uniformName Name of the variable.
  992. * @param array array to be set.
  993. * @returns this effect.
  994. */
  995. setArray(uniformName, array) {
  996. this._pipelineContext.setArray(uniformName, array);
  997. return this;
  998. }
  999. /**
  1000. * Sets an array 2 on a uniform variable. (Array is specified as single array eg. [1,2,3,4] will result in [[1,2],[3,4]] in the shader)
  1001. * @param uniformName Name of the variable.
  1002. * @param array array to be set.
  1003. * @returns this effect.
  1004. */
  1005. setArray2(uniformName, array) {
  1006. this._pipelineContext.setArray2(uniformName, array);
  1007. return this;
  1008. }
  1009. /**
  1010. * Sets an array 3 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6] will result in [[1,2,3],[4,5,6]] in the shader)
  1011. * @param uniformName Name of the variable.
  1012. * @param array array to be set.
  1013. * @returns this effect.
  1014. */
  1015. setArray3(uniformName, array) {
  1016. this._pipelineContext.setArray3(uniformName, array);
  1017. return this;
  1018. }
  1019. /**
  1020. * Sets an array 4 on a uniform variable. (Array is specified as single array eg. [1,2,3,4,5,6,7,8] will result in [[1,2,3,4],[5,6,7,8]] in the shader)
  1021. * @param uniformName Name of the variable.
  1022. * @param array array to be set.
  1023. * @returns this effect.
  1024. */
  1025. setArray4(uniformName, array) {
  1026. this._pipelineContext.setArray4(uniformName, array);
  1027. return this;
  1028. }
  1029. /**
  1030. * Sets matrices on a uniform variable.
  1031. * @param uniformName Name of the variable.
  1032. * @param matrices matrices to be set.
  1033. * @returns this effect.
  1034. */
  1035. setMatrices(uniformName, matrices) {
  1036. this._pipelineContext.setMatrices(uniformName, matrices);
  1037. return this;
  1038. }
  1039. /**
  1040. * Sets matrix on a uniform variable.
  1041. * @param uniformName Name of the variable.
  1042. * @param matrix matrix to be set.
  1043. * @returns this effect.
  1044. */
  1045. setMatrix(uniformName, matrix) {
  1046. this._pipelineContext.setMatrix(uniformName, matrix);
  1047. return this;
  1048. }
  1049. /**
  1050. * Sets a 3x3 matrix on a uniform variable. (Specified as [1,2,3,4,5,6,7,8,9] will result in [1,2,3][4,5,6][7,8,9] matrix)
  1051. * @param uniformName Name of the variable.
  1052. * @param matrix matrix to be set.
  1053. * @returns this effect.
  1054. */
  1055. setMatrix3x3(uniformName, matrix) {
  1056. // the cast is ok because it is gl.uniformMatrix3fv() which is called at the end, and this function accepts Float32Array and Array<number>
  1057. this._pipelineContext.setMatrix3x3(uniformName, matrix);
  1058. return this;
  1059. }
  1060. /**
  1061. * Sets a 2x2 matrix on a uniform variable. (Specified as [1,2,3,4] will result in [1,2][3,4] matrix)
  1062. * @param uniformName Name of the variable.
  1063. * @param matrix matrix to be set.
  1064. * @returns this effect.
  1065. */
  1066. setMatrix2x2(uniformName, matrix) {
  1067. // the cast is ok because it is gl.uniformMatrix3fv() which is called at the end, and this function accepts Float32Array and Array<number>
  1068. this._pipelineContext.setMatrix2x2(uniformName, matrix);
  1069. return this;
  1070. }
  1071. /**
  1072. * Sets a float on a uniform variable.
  1073. * @param uniformName Name of the variable.
  1074. * @param value value to be set.
  1075. * @returns this effect.
  1076. */
  1077. setFloat(uniformName, value) {
  1078. this._pipelineContext.setFloat(uniformName, value);
  1079. return this;
  1080. }
  1081. /**
  1082. * Sets a boolean on a uniform variable.
  1083. * @param uniformName Name of the variable.
  1084. * @param bool value to be set.
  1085. * @returns this effect.
  1086. */
  1087. setBool(uniformName, bool) {
  1088. this._pipelineContext.setInt(uniformName, bool ? 1 : 0);
  1089. return this;
  1090. }
  1091. /**
  1092. * Sets a Vector2 on a uniform variable.
  1093. * @param uniformName Name of the variable.
  1094. * @param vector2 vector2 to be set.
  1095. * @returns this effect.
  1096. */
  1097. setVector2(uniformName, vector2) {
  1098. this._pipelineContext.setVector2(uniformName, vector2);
  1099. return this;
  1100. }
  1101. /**
  1102. * Sets a float2 on a uniform variable.
  1103. * @param uniformName Name of the variable.
  1104. * @param x First float in float2.
  1105. * @param y Second float in float2.
  1106. * @returns this effect.
  1107. */
  1108. setFloat2(uniformName, x, y) {
  1109. this._pipelineContext.setFloat2(uniformName, x, y);
  1110. return this;
  1111. }
  1112. /**
  1113. * Sets a Vector3 on a uniform variable.
  1114. * @param uniformName Name of the variable.
  1115. * @param vector3 Value to be set.
  1116. * @returns this effect.
  1117. */
  1118. setVector3(uniformName, vector3) {
  1119. this._pipelineContext.setVector3(uniformName, vector3);
  1120. return this;
  1121. }
  1122. /**
  1123. * Sets a float3 on a uniform variable.
  1124. * @param uniformName Name of the variable.
  1125. * @param x First float in float3.
  1126. * @param y Second float in float3.
  1127. * @param z Third float in float3.
  1128. * @returns this effect.
  1129. */
  1130. setFloat3(uniformName, x, y, z) {
  1131. this._pipelineContext.setFloat3(uniformName, x, y, z);
  1132. return this;
  1133. }
  1134. /**
  1135. * Sets a Vector4 on a uniform variable.
  1136. * @param uniformName Name of the variable.
  1137. * @param vector4 Value to be set.
  1138. * @returns this effect.
  1139. */
  1140. setVector4(uniformName, vector4) {
  1141. this._pipelineContext.setVector4(uniformName, vector4);
  1142. return this;
  1143. }
  1144. /**
  1145. * Sets a Quaternion on a uniform variable.
  1146. * @param uniformName Name of the variable.
  1147. * @param quaternion Value to be set.
  1148. * @returns this effect.
  1149. */
  1150. setQuaternion(uniformName, quaternion) {
  1151. this._pipelineContext.setQuaternion(uniformName, quaternion);
  1152. return this;
  1153. }
  1154. /**
  1155. * Sets a float4 on a uniform variable.
  1156. * @param uniformName Name of the variable.
  1157. * @param x First float in float4.
  1158. * @param y Second float in float4.
  1159. * @param z Third float in float4.
  1160. * @param w Fourth float in float4.
  1161. * @returns this effect.
  1162. */
  1163. setFloat4(uniformName, x, y, z, w) {
  1164. this._pipelineContext.setFloat4(uniformName, x, y, z, w);
  1165. return this;
  1166. }
  1167. /**
  1168. * Sets a Color3 on a uniform variable.
  1169. * @param uniformName Name of the variable.
  1170. * @param color3 Value to be set.
  1171. * @returns this effect.
  1172. */
  1173. setColor3(uniformName, color3) {
  1174. this._pipelineContext.setColor3(uniformName, color3);
  1175. return this;
  1176. }
  1177. /**
  1178. * Sets a Color4 on a uniform variable.
  1179. * @param uniformName Name of the variable.
  1180. * @param color3 Value to be set.
  1181. * @param alpha Alpha value to be set.
  1182. * @returns this effect.
  1183. */
  1184. setColor4(uniformName, color3, alpha) {
  1185. this._pipelineContext.setColor4(uniformName, color3, alpha);
  1186. return this;
  1187. }
  1188. /**
  1189. * Sets a Color4 on a uniform variable
  1190. * @param uniformName defines the name of the variable
  1191. * @param color4 defines the value to be set
  1192. * @returns this effect.
  1193. */
  1194. setDirectColor4(uniformName, color4) {
  1195. this._pipelineContext.setDirectColor4(uniformName, color4);
  1196. return this;
  1197. }
  1198. /**
  1199. * Release all associated resources.
  1200. **/
  1201. dispose() {
  1202. if (this._pipelineContext) {
  1203. this._pipelineContext.dispose();
  1204. }
  1205. this._engine._releaseEffect(this);
  1206. this._isDisposed = true;
  1207. }
  1208. /**
  1209. * This function will add a new shader to the shader store
  1210. * @param name the name of the shader
  1211. * @param pixelShader optional pixel shader content
  1212. * @param vertexShader optional vertex shader content
  1213. * @param shaderLanguage the language the shader is written in (default: GLSL)
  1214. */
  1215. static RegisterShader(name, pixelShader, vertexShader, shaderLanguage = ShaderLanguage.GLSL) {
  1216. if (pixelShader) {
  1217. EngineShaderStore.GetShadersStore(shaderLanguage)[`${name}PixelShader`] = pixelShader;
  1218. }
  1219. if (vertexShader) {
  1220. EngineShaderStore.GetShadersStore(shaderLanguage)[`${name}VertexShader`] = vertexShader;
  1221. }
  1222. }
  1223. /**
  1224. * Resets the cache of effects.
  1225. */
  1226. static ResetCache() {
  1227. Effect._BaseCache = {};
  1228. }
  1229. }
  1230. /**
  1231. * Enable logging of the shader code when a compilation error occurs
  1232. */
  1233. Effect.LogShaderCodeOnCompilationError = true;
  1234. Effect._UniqueIdSeed = 0;
  1235. Effect._BaseCache = {};
  1236. /**
  1237. * Store of each shader (The can be looked up using effect.key)
  1238. */
  1239. Effect.ShadersStore = EngineShaderStore.ShadersStore;
  1240. /**
  1241. * Store of each included file for a shader (The can be looked up using effect.key)
  1242. */
  1243. Effect.IncludesShadersStore = EngineShaderStore.IncludesShadersStore;
  1244. //# sourceMappingURL=effect.js.map