Home Reference Source

cables_dev/cables/src/core/cgl/cgl_shader.js

  1. import { Logger } from "cables-shared-client";
  2. import { ShaderLibMods } from "./cgl_shader_lib.js";
  3. import { now } from "../timer.js";
  4. import { MESH } from "./cgl_mesh.js";
  5. import { CONSTANTS } from "./constants.js";
  6. import { escapeHTML } from "./cgl_utils.js";
  7. import { CgShader } from "../cg/cg_shader.js";
  8. import defaultShaderSrcVert from "./cgl_shader_default_glsl.vert";
  9. import { simpleId } from "../utils.js";
  10. // ---------------------------------------------------------------------------
  11.  
  12.  
  13. /*
  14.  
  15. proposal default shader variable names:
  16.  
  17. attrVertex - currently: vPosition
  18. attrVertexIndex - currently: attrVertIndex
  19. attrTexCoord
  20. attrInstMat - currently: instMat
  21. attrVertColor
  22. attrTangent
  23. attrBiTangent
  24.  
  25. uProjMatrix - currently: projMatrix
  26. uModelMatrix - currently: modelMatrix
  27. uNormalMatrix - currently: normalMatrix
  28. uCamPosition - currently: camPos
  29.  
  30. */
  31.  
  32.  
  33. // ---------------------------------------------------------------------------
  34.  
  35. let materialIdCounter = 0;
  36.  
  37.  
  38.  
  39.  
  40. function getDefaultVertexShader()
  41. {
  42. return defaultShaderSrcVert;
  43. }
  44.  
  45.  
  46. function getDefaultFragmentShader(r, g, b)
  47. {
  48. if (r == undefined)
  49. {
  50. r = 0.5;
  51. g = 0.5;
  52. b = 0.5;
  53. }
  54. return ""
  55. .endl() + "IN vec2 texCoord;"
  56. .endl() + "{{MODULES_HEAD}}"
  57. .endl() + "void main()"
  58. .endl() + "{"
  59. .endl() + " vec4 col=vec4(" + r + "," + g + "," + b + ",1.0);"
  60. .endl() + " {{MODULE_COLOR}}"
  61. .endl() + " outColor = col;"
  62. .endl() + "}";
  63. };
  64.  
  65.  
  66. /**
  67. * @class
  68. * @namespace external:CGL
  69. * @hideconstructor
  70. * @param _cgl
  71. * @param _name
  72. * @param _op
  73. * @example
  74. * var shader=new CGL.Shader(cgl,'MinimalMaterial');
  75. * shader.setSource(attachments.shader_vert,attachments.shader_frag);
  76. */
  77. class Shader extends CgShader
  78. {
  79. constructor (_cgl, _name, _op)
  80. {
  81. super();
  82. if (!_cgl) throw new Error("shader constructed without cgl " + _name);
  83.  
  84. this._log = new Logger("cgl_shader");
  85. this._cgl = _cgl;
  86.  
  87. if (!_name) this._log.stack("no shader name given");
  88. this._name = _name || "unknown";
  89.  
  90. if (_op) this.opId = _op.id;
  91. this.glslVersion = 0;
  92. if (_cgl.glVersion > 1) this.glslVersion = 300;
  93.  
  94. this._materialId = ++materialIdCounter;
  95.  
  96. this._program = null;
  97. this._uniforms = [];
  98. this._drawBuffers = [true];
  99.  
  100. this._needsRecompile = true;
  101. this._compileReason = "initial";
  102.  
  103. this.ignoreMissingUniforms = false;
  104. this._projMatrixUniform = null;
  105. this._mvMatrixUniform = null;
  106. this._mMatrixUniform = null;
  107. this._vMatrixUniform = null;
  108. this._camPosUniform = null;
  109. this._normalMatrixUniform = null;
  110. this._inverseViewMatrixUniform = null;
  111. this._fromUserInteraction = false;
  112.  
  113. this._attrVertexPos = -1;
  114. this.precision = _cgl.patch.config.glslPrecision || "highp";
  115.  
  116. this._pMatrixState = -1;
  117. this._vMatrixState = -1;
  118.  
  119. this._countMissingUniforms = 0;
  120. this._modGroupCount = 0; // not needed anymore...
  121. this._feedBackNames = [];
  122. this._attributes = [];
  123.  
  124. this.glPrimitive = null;
  125. this.offScreenPass = false;
  126. this._extensions = [];
  127. this.srcVert = getDefaultVertexShader();
  128. this.srcFrag = getDefaultFragmentShader();
  129. this.lastCompile = 0;
  130.  
  131.  
  132. this._libs = [];
  133. this._structNames = [];
  134. this._structUniformNames = [];
  135. this._textureStackUni = [];
  136. this._textureStackTex = [];
  137. this._textureStackType = [];
  138. this._textureStackTexCgl = [];
  139.  
  140. this._tempNormalMatrix = mat4.create();
  141. this._tempCamPosMatrix = mat4.create();
  142. this._tempInverseViewMatrix = mat4.create();
  143. this._tempInverseProjMatrix = mat4.create();
  144.  
  145. this.setModules(["MODULE_VERTEX_POSITION", "MODULE_COLOR", "MODULE_BEGIN_FRAG", "MODULE_VERTEX_MODELVIEW"]);
  146. };
  147.  
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154. isValid()
  155. {
  156. return this._isValid;
  157. };
  158.  
  159. getCgl()
  160. {
  161. return this._cgl;
  162. };
  163.  
  164. getName()
  165. {
  166. return this._name;
  167. };
  168.  
  169. /**
  170. * enable an extension for the shader
  171. * @function enableExtension
  172. * @memberof Shader
  173. * @instance
  174. * @param name extension name
  175. */
  176. enableExtension(name)
  177. {
  178. this.setWhyCompile("enable extension " + name);
  179. this._needsRecompile = true;
  180. this._extensions.push(name);
  181. };
  182.  
  183. getAttrVertexPos()
  184. {
  185. return this._attrVertexPos;
  186. };
  187.  
  188. hasTextureUniforms()
  189. {
  190. for (let i = 0; i < this._uniforms.length; i++)
  191. if (this._uniforms[i].getType() == "t") return true;
  192. return false;
  193. };
  194.  
  195. setWhyCompile(why)
  196. {
  197. this._compileReason = why;
  198. };
  199.  
  200. /**
  201. * copy all uniform values from another shader
  202. * @function copyUniforms
  203. * @memberof Shader
  204. * @instance
  205. * @param origShader uniform values will be copied from this shader
  206. */
  207. copyUniformValues(origShader)
  208. {
  209. // console.log(origShader._uniforms);
  210. for (let i = 0; i < origShader._uniforms.length; i++)
  211. {
  212. if (!this._uniforms[i])
  213. {
  214. this._log.log("unknown uniform?!");
  215. continue;
  216. }
  217.  
  218. // this._log.log(origShader._uniforms[i].getName());
  219. // this.getUniform(origShader._uniforms[i].)
  220. // this._uniforms[i].set(origShader._uniforms[i].getValue());
  221.  
  222.  
  223. // if (origShader._uniforms[i].getName().contains("pathPoints"))
  224. // console.log("copyUniformValues", origShader._uniforms[i].getName(), origShader._uniforms[i].getValue());
  225.  
  226. this.getUniform(origShader._uniforms[i].getName()).set(origShader._uniforms[i].getValue());
  227. }
  228.  
  229. this.popTextures();
  230. for (let i = 0; i < origShader._textureStackUni.length; i++)
  231. {
  232. this._textureStackUni[i] = origShader._textureStackUni[i];
  233. this._textureStackTex[i] = origShader._textureStackTex[i];
  234. this._textureStackType[i] = origShader._textureStackType[i];
  235. this._textureStackTexCgl[i] = origShader._textureStackTexCgl[i];
  236. }
  237.  
  238. // this._textureStackUni = [];
  239. // this._textureStackTex = [];
  240. // this._textureStackType = [];
  241. // this._textureStackTexCgl = [];
  242. };
  243.  
  244. /**
  245. * copy current shader
  246. * @function copy
  247. * @memberof Shader
  248. * @instance
  249. * @returns newShader
  250. */
  251. copy()
  252. {
  253. const shader = new Shader(this._cgl, this._name + " copy");
  254. shader.setSource(this.srcVert, this.srcFrag);
  255.  
  256. shader._modules = JSON.parse(JSON.stringify(this._modules));
  257. shader._defines = JSON.parse(JSON.stringify(this._defines));
  258.  
  259. shader._modGroupCount = this._modGroupCount;
  260. shader._moduleNames = this._moduleNames;
  261. shader.glPrimitive = this.glPrimitive;
  262. shader.offScreenPass = this.offScreenPass;
  263. shader._extensions = this._extensions;
  264. shader.wireframe = this.wireframe;
  265. shader._attributes = this._attributes;
  266.  
  267. for (let i = 0; i < this._uniforms.length; i++)
  268. {
  269. const u = this._uniforms[i].copy(shader);
  270. u.resetLoc();
  271. }
  272.  
  273. this.setWhyCompile("copy");
  274. shader._needsRecompile = true;
  275. return shader;
  276. };
  277.  
  278.  
  279. /**
  280. * set shader source code
  281. * @function setSource
  282. * @memberof Shader
  283. * @instance
  284. * @param {String} srcVert
  285. * @param {String} srcFrag
  286. * @param {Bool} fromUserInteraction
  287. */
  288. setSource(srcVert, srcFrag, fromUserInteraction)
  289. {
  290. this._fromUserInteraction = fromUserInteraction;
  291. this.srcVert = srcVert;
  292. this.srcFrag = srcFrag;
  293. this.setWhyCompile("Source changed");
  294. this._needsRecompile = true;
  295. this._isValid = true;
  296. };
  297.  
  298. _addLibs(src)
  299. {
  300. for (const id in ShaderLibMods)
  301. {
  302. if (src.contains(id))
  303. {
  304. const lib = new ShaderLibMods[id]();
  305. src = src.replace("{{" + id + "}}", lib.srcHeadFrag);
  306. this._libs.push(lib);
  307. if (lib.initUniforms)lib.initUniforms(this);
  308. }
  309. }
  310.  
  311. return src;
  312. };
  313.  
  314. createStructUniforms()
  315. {
  316. // * create structs
  317. let structStrFrag = "";
  318. let structStrVert = ""; // TODO: not used yet
  319.  
  320. this._structNames = [];
  321. // * reset the arrays holding the value each recompile so we don't skip structs
  322. // * key value mapping so the same struct can be added twice (two times the same modifier)
  323. this._injectedStringsFrag = {};
  324. this._injectedStringsVert = {};
  325.  
  326. this._structUniformNamesIndicesFrag = [];
  327. this._structUniformNamesIndicesVert = [];
  328.  
  329. for (let i = 0; i < this._uniforms.length; i++)
  330. {
  331. // * only add uniforms to struct that are a member of a struct
  332. if (this._uniforms[i].isStructMember())
  333. {
  334. const injectionString = "{{INJECTION_POINT_STRUCT_" + this._uniforms[i]._structName + "}}";
  335.  
  336. // * check if struct is not already part of shader
  337. if (!this._structNames.includes(this._uniforms[i]._structName))
  338. {
  339. // * create struct definition with placeholder string to inject
  340. const structDefinition = "struct "
  341. + this._uniforms[i]._structName + " {".endl()
  342. + injectionString
  343. + "};".endl().endl();
  344.  
  345. if (this._uniforms[i].getShaderType() === "both" || this._uniforms[i].getShaderType() === "frag")
  346. structStrFrag = structStrFrag.concat(structDefinition);
  347.  
  348. if (this._uniforms[i].getShaderType() === "both" || this._uniforms[i].getShaderType() === "vert")
  349. structStrVert = structStrVert.concat(structDefinition);
  350.  
  351. this._structNames.push(this._uniforms[i]._structName);
  352. this._injectedStringsFrag[this._uniforms[i]._structName] = [];
  353. this._injectedStringsVert[this._uniforms[i]._structName] = [];
  354. }
  355.  
  356. // * create member & comment
  357. let comment = "";
  358. if (this._uniforms[i].comment) comment = " // " + this._uniforms[i].comment;
  359.  
  360. let stringToInsert = "";
  361. if (this._uniforms[i].getGlslTypeString() == undefined)stringToInsert += "//";
  362. stringToInsert += " " + this._uniforms[i].getGlslTypeString()
  363. + " " + this._uniforms[i]._propertyName + ";"
  364. + comment;
  365.  
  366. if (this._uniforms[i].getShaderType() === "both")
  367. {
  368. // * inject member before {injectionString}
  369. if (
  370. !this._injectedStringsFrag[this._uniforms[i]._structName].contains(stringToInsert)
  371. && !this._injectedStringsVert[this._uniforms[i]._structName].contains(stringToInsert))
  372. {
  373. const insertionIndexFrag = structStrFrag.lastIndexOf(injectionString);
  374. const insertionIndexVert = structStrVert.lastIndexOf(injectionString);
  375.  
  376. structStrFrag =
  377. structStrFrag.slice(0, insertionIndexFrag)
  378. + stringToInsert + structStrFrag.slice(insertionIndexFrag - 1);
  379.  
  380. structStrVert =
  381. structStrVert.slice(0, insertionIndexVert)
  382. + stringToInsert + structStrVert.slice(insertionIndexVert - 1);
  383.  
  384. this._injectedStringsFrag[this._uniforms[i]._structName].push(stringToInsert);
  385. this._injectedStringsVert[this._uniforms[i]._structName].push(stringToInsert);
  386. }
  387.  
  388. if (!this._structUniformNamesIndicesFrag.includes(i)) this._structUniformNamesIndicesFrag.push(i);
  389. if (!this._structUniformNamesIndicesVert.includes(i)) this._structUniformNamesIndicesVert.push(i);
  390. }
  391. else if (this._uniforms[i].getShaderType() === "frag")
  392. {
  393. // * inject member before {injectionString}
  394. if (!this._injectedStringsFrag[this._uniforms[i]._structName].includes(stringToInsert)) //
  395. {
  396. const insertionIndexFrag = structStrFrag.lastIndexOf(injectionString);
  397.  
  398. structStrFrag =
  399. structStrFrag.slice(0, insertionIndexFrag)
  400. + stringToInsert + structStrFrag.slice(insertionIndexFrag - 1);
  401.  
  402. this._injectedStringsFrag[this._uniforms[i]._structName].push(stringToInsert);
  403. }
  404.  
  405. if (!this._structUniformNamesIndicesFrag.includes(i)) this._structUniformNamesIndicesFrag.push(i);
  406. }
  407. else if (this._uniforms[i].getShaderType() === "vert")
  408. {
  409. // * inject member before {injectionString}
  410. if (!this._injectedStringsVert[this._uniforms[i]._structName].includes(stringToInsert))
  411. {
  412. const insertionIndexVert = structStrVert.lastIndexOf(injectionString);
  413.  
  414. structStrVert =
  415. structStrVert.slice(0, insertionIndexVert)
  416. + stringToInsert + structStrVert.slice(insertionIndexVert - 1);
  417.  
  418. this._injectedStringsVert[this._uniforms[i]._structName].push(stringToInsert);
  419. }
  420.  
  421. if (!this._structUniformNamesIndicesVert.includes(i)) this._structUniformNamesIndicesVert.push(i);
  422. }
  423. }
  424. }
  425.  
  426. // * dedupe injected uni declarations
  427. this._uniDeclarationsFrag = [];
  428. this._uniDeclarationsVert = [];
  429.  
  430. // * remove struct injection points and add uniform in fragment
  431. for (let i = 0; i < this._structUniformNamesIndicesFrag.length; i += 1)
  432. {
  433. const index = this._structUniformNamesIndicesFrag[i];
  434. const uniDeclarationString = "UNI " + this._uniforms[index]._structName + " " + this._uniforms[index]._structUniformName + ";".endl();
  435.  
  436. if (!this._uniDeclarationsFrag.includes(uniDeclarationString))
  437. {
  438. const injectionString = "{{INJECTION_POINT_STRUCT_" + this._uniforms[index]._structName + "}}";
  439.  
  440. structStrFrag = structStrFrag.replace(injectionString, "");
  441. structStrFrag += uniDeclarationString;
  442.  
  443. this._uniDeclarationsFrag.push(uniDeclarationString);
  444. }
  445. }
  446.  
  447. // * remove struct injection points and add uniform in vertex
  448. for (let i = 0; i < this._structUniformNamesIndicesVert.length; i += 1)
  449. {
  450. const index = this._structUniformNamesIndicesVert[i];
  451. const uniDeclarationString = "UNI " + this._uniforms[index]._structName + " " + this._uniforms[index]._structUniformName + ";".endl();
  452.  
  453. if (!this._uniDeclarationsVert.includes(uniDeclarationString))
  454. {
  455. const injectionString = "{{INJECTION_POINT_STRUCT_" + this._uniforms[index]._structName + "}}";
  456.  
  457. structStrVert = structStrVert.replace(injectionString, "");
  458. structStrVert += uniDeclarationString;
  459. this._uniDeclarationsVert.push(uniDeclarationString);
  460. }
  461. }
  462.  
  463. return [structStrVert, structStrFrag];
  464. };
  465.  
  466. _getAttrSrc(attr, firstLevel)
  467. {
  468. const r = {};
  469. if (attr.name && attr.type)
  470. {
  471. r.srcHeadVert = "";
  472. if (!firstLevel) r.srcHeadVert += "#ifndef ATTRIB_" + attr.name.endl();
  473. r.srcHeadVert += "#define ATTRIB_" + attr.name.endl();
  474. r.srcHeadVert += "IN " + attr.type + " " + attr.name + ";".endl();
  475. if (!firstLevel) r.srcHeadVert += "#endif".endl();
  476.  
  477. if (attr.nameFrag)
  478. {
  479. r.srcHeadVert += "";
  480. if (!firstLevel) r.srcHeadVert += "#ifndef ATTRIB_" + attr.nameFrag.endl();
  481. r.srcHeadVert += "#define ATTRIB_" + attr.nameFrag.endl();
  482. r.srcHeadVert += "OUT " + attr.type + " " + attr.nameFrag + ";".endl();
  483. if (!firstLevel) r.srcHeadVert += "#endif".endl();
  484.  
  485. r.srcVert = "".endl() + attr.nameFrag + "=" + attr.name + ";";
  486.  
  487. r.srcHeadFrag = "";
  488. if (!firstLevel) r.srcHeadFrag += "#ifndef ATTRIB_" + attr.nameFrag.endl();
  489. r.srcHeadFrag += "#define ATTRIB_" + attr.nameFrag.endl();
  490. r.srcHeadFrag += "IN " + attr.type + " " + attr.nameFrag + ";".endl();
  491. if (!firstLevel) r.srcHeadFrag += "#endif".endl();
  492. }
  493. }
  494. return r;
  495. };
  496.  
  497. compile()
  498. {
  499. if (this._cgl.aborted) return;
  500. const startTime = performance.now();
  501.  
  502.  
  503.  
  504. this._cgl.profileData.profileShaderCompiles++;
  505. this._cgl.profileData.profileShaderCompileName = this._name + " [" + this._compileReason + "]";
  506.  
  507. let extensionString = "";
  508. if (this._extensions)
  509. for (let i = 0; i < this._extensions.length; i++)
  510. extensionString += "#extension " + this._extensions[i] + " : enable".endl();
  511.  
  512. let definesStr = "";
  513. if (this._defines.length) definesStr = "\n// cgl generated".endl();
  514. for (let i = 0; i < this._defines.length; i++)
  515. definesStr += "#define " + this._defines[i][0] + " " + this._defines[i][1] + "".endl();
  516.  
  517. const structStrings = this.createStructUniforms();
  518. this._cgl.profileData.addHeavyEvent("shader compile", this._name + " [" + this._compileReason + "]");
  519. this._compileReason = "";
  520.  
  521.  
  522.  
  523. if (this._uniforms)
  524. {
  525. // * we create an array of the uniform names to check our indices & an array to save them
  526. const uniNames = this._uniforms.map((uni) => { return uni._name; });
  527. const indicesToRemove = [];
  528.  
  529. // * we go through our uniforms and check if the same name is contained somewhere further in the array
  530. // * if so, we add the current index to be removed later
  531. for (let i = 0; i < this._uniforms.length; i++)
  532. {
  533. const uni = this._uniforms[i];
  534. const nextIndex = uniNames.indexOf(uni._name, i + 1);
  535. if (nextIndex > -1) indicesToRemove.push(i);
  536. }
  537.  
  538. // * after that, we go through the uniforms backwards (so we keep the order) and remove the indices
  539. // * also, we reset the locations of all the other valid uniforms
  540. for (let j = this._uniforms.length - 1; j >= 0; j -= 1)
  541. {
  542. if (indicesToRemove.includes(j)) this._uniforms.splice(j, 1);
  543. else this._uniforms[j].resetLoc();
  544. }
  545. }
  546.  
  547. this._cgl.printError("uniform resets");
  548.  
  549. if (this.hasTextureUniforms()) definesStr += "#define HAS_TEXTURES".endl();
  550.  
  551. let vs = "";
  552. let fs = "";
  553.  
  554. if (!this.srcFrag)
  555. {
  556. this._log.warn("[cgl shader] has no fragment source!", this._name, this);
  557. this.srcVert = getDefaultVertexShader();
  558. this.srcFrag = getDefaultFragmentShader();
  559. // return;
  560. }
  561.  
  562. if (this.glslVersion == 300)
  563. {
  564. vs = "#version 300 es"
  565. .endl() + "// "
  566. .endl() + "// vertex shader " + this._name
  567. .endl() + "// "
  568. .endl() + "precision " + this.precision + " float;"
  569. .endl() + "precision " + this.precision + " sampler2D;"
  570. .endl() + ""
  571. .endl() + "#define WEBGL2"
  572. .endl() + "#define texture2D texture"
  573. .endl() + "#define UNI uniform"
  574. .endl() + "#define IN in"
  575. .endl() + "#define OUT out"
  576. .endl();
  577.  
  578. fs = "#version 300 es"
  579. .endl() + "// "
  580. .endl() + "// fragment shader " + this._name
  581. .endl() + "// "
  582. .endl() + "precision " + this.precision + " float;"
  583. .endl() + "precision " + this.precision + " sampler2D;"
  584. .endl() + ""
  585. .endl() + "#define WEBGL2"
  586. .endl() + "#define texture2D texture"
  587. .endl() + "#define IN in"
  588. .endl() + "#define OUT out"
  589. .endl() + "#define UNI uniform"
  590. .endl() + "{{DRAWBUFFER}}"
  591.  
  592. .endl();
  593. }
  594. else
  595. {
  596. fs = ""
  597. .endl() + "// "
  598. .endl() + "// fragment shader " + this._name
  599. .endl() + "// "
  600. .endl() + "#define WEBGL1"
  601. .endl() + "#define texture texture2D"
  602. .endl() + "#define outColor gl_FragColor"
  603. .endl() + "#define IN varying"
  604. .endl() + "#define UNI uniform"
  605. .endl();
  606.  
  607. vs = ""
  608. .endl() + "// "
  609. .endl() + "// vertex shader " + this._name
  610. .endl() + "// "
  611. .endl() + "#define WEBGL1"
  612. .endl() + "#define texture texture2D"
  613. .endl() + "#define OUT varying"
  614. .endl() + "#define IN attribute"
  615. .endl() + "#define UNI uniform"
  616. .endl();
  617. }
  618.  
  619. let uniformsStrVert = "\n// cgl generated".endl();
  620. let uniformsStrFrag = "\n// cgl generated".endl();
  621.  
  622.  
  623. fs += "\n// active mods: --------------- ";
  624. vs += "\n// active mods: --------------- ";
  625.  
  626. let foundModsFrag = false;
  627. let foundModsVert = false;
  628. for (let i = 0; i < this._moduleNames.length; i++)
  629. {
  630. for (let j = 0; j < this._modules.length; j++)
  631. {
  632. if (this._modules[j].name == this._moduleNames[i])
  633. {
  634. if (this._modules[j].srcBodyFrag || this._modules[j].srcHeadFrag)
  635. {
  636. foundModsFrag = true;
  637. fs += "\n// " + i + "." + j + ". " + this._modules[j].title + " (" + this._modules[j].name + ")";
  638. }
  639. if (this._modules[j].srcBodyVert || this._modules[j].srcHeadVert)
  640. {
  641. vs += "\n// " + i + "." + j + ". " + this._modules[j].title + " (" + this._modules[j].name + ")";
  642. foundModsVert = true;
  643. }
  644. }
  645. }
  646. }
  647. if (!foundModsVert)fs += "\n// no mods used...";
  648. if (!foundModsFrag)fs += "\n// no mods used...";
  649. fs += "\n";
  650. vs += "\n";
  651.  
  652. for (let i = 0; i < this._uniforms.length; i++)
  653. {
  654. if (this._uniforms[i].shaderType && !this._uniforms[i].isStructMember())
  655. {
  656. let uniStr = "";
  657. if (!this._uniforms[i].getGlslTypeString())uniStr += "// ";
  658. uniStr += "UNI " + this._uniforms[i].getGlslTypeString() + " " + this._uniforms[i].getName();
  659. let comment = "";
  660. if (this._uniforms[i].comment) comment = " // " + this._uniforms[i].comment;
  661.  
  662. if (this._uniforms[i].shaderType == "vert" || this._uniforms[i].shaderType == "both")
  663. if (!this.srcVert.contains(uniStr) && !this.srcVert.contains("uniform " + this._uniforms[i].getGlslTypeString() + " " + this._uniforms[i].getName()))
  664. uniformsStrVert += uniStr + ";" + comment.endl();
  665.  
  666. if (this._uniforms[i].shaderType == "frag" || this._uniforms[i].shaderType == "both")
  667. if (!this.srcFrag.contains(uniStr) && !this.srcFrag.contains("uniform " + this._uniforms[i].getGlslTypeString() + " " + this._uniforms[i].getName()))
  668. uniformsStrFrag += uniStr + ";" + comment.endl();
  669. }
  670. }
  671.  
  672.  
  673. let countUniFrag = 0;
  674. let countUniVert = 0;
  675. for (let i = 0; i < this._uniforms.length; i++)
  676. {
  677. if (this._uniforms[i].shaderType && !this._uniforms[i].isStructMember())
  678. {
  679. if (this._uniforms[i].shaderType == "vert" || this._uniforms[i].shaderType == "both") countUniVert++;
  680. if (this._uniforms[i].shaderType == "frag" || this._uniforms[i].shaderType == "both") countUniFrag++;
  681. }
  682. }
  683. if (countUniFrag >= this._cgl.maxUniformsFrag) this._log.warn("[cgl_shader] num uniforms frag: " + countUniFrag + " / " + this._cgl.maxUniformsFrag);
  684. if (countUniVert >= this._cgl.maxUniformsVert) this._log.warn("[cgl_shader] num uniforms vert: " + countUniVert + " / " + this._cgl.maxUniformsVert);
  685.  
  686.  
  687. if (!fs.contains("precision")) fs = "precision " + this.precision + " float;".endl() + fs;
  688. if (!vs.contains("precision")) vs = "precision " + this.precision + " float;".endl() + vs;
  689. if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent))
  690. {
  691. fs += "#define MOBILE".endl();
  692. vs += "#define MOBILE".endl();
  693. }
  694. vs = extensionString + vs + definesStr + structStrings[0] + uniformsStrVert + "\n// -- \n" + this.srcVert;
  695. fs = extensionString + fs + definesStr + structStrings[1] + uniformsStrFrag + "\n// -- \n" + this.srcFrag;
  696.  
  697.  
  698. let srcHeadVert = "";
  699. let srcHeadFrag = "";
  700.  
  701. // testing if this breaks things...
  702. // this._modules.sort(function (a, b)
  703. // {
  704. // return a.group - b.group;
  705. // });
  706.  
  707. this._modules.sort(function (a, b)
  708. {
  709. return a.priority || 0 - b.priority || 0;
  710. });
  711.  
  712.  
  713. let addedAttribs = false;
  714.  
  715. for (let i = 0; i < this._moduleNames.length; i++)
  716. {
  717. let srcVert = "";
  718. let srcFrag = "";
  719.  
  720. if (!addedAttribs)
  721. {
  722. addedAttribs = true;
  723.  
  724. for (let k = 0; k < this._attributes.length; k++)
  725. {
  726. const r = this._getAttrSrc(this._attributes[k], true);
  727. if (r.srcHeadVert)srcHeadVert += r.srcHeadVert;
  728. if (r.srcVert)srcVert += r.srcVert;
  729. if (r.srcHeadFrag)srcHeadFrag += r.srcHeadFrag;
  730. }
  731. }
  732.  
  733. for (let j = 0; j < this._modules.length; j++)
  734. {
  735. const mod = this._modules[j];
  736. if (mod.name == this._moduleNames[i])
  737. {
  738. srcHeadVert += "\n//---- MOD: group:" + mod.group + ": idx:" + j + " - prfx:" + mod.prefix + " - " + mod.title + " ------\n";
  739. srcHeadFrag += "\n//---- MOD: group:" + mod.group + ": idx:" + j + " - prfx:" + mod.prefix + " - " + mod.title + " ------\n";
  740.  
  741. srcVert += "\n\n//---- MOD: " + mod.title + " / " + mod.priority + " ------\n";
  742. srcFrag += "\n\n//---- MOD: " + mod.title + " / " + mod.priority + " ------\n";
  743.  
  744. if (mod.attributes)
  745. for (let k = 0; k < mod.attributes.length; k++)
  746. {
  747. const r = this._getAttrSrc(mod.attributes[k], false);
  748. if (r.srcHeadVert)srcHeadVert += r.srcHeadVert;
  749. if (r.srcVert)srcVert += r.srcVert;
  750. if (r.srcHeadFrag)srcHeadFrag += r.srcHeadFrag;
  751. }
  752.  
  753. srcHeadVert += mod.srcHeadVert || "";
  754. srcHeadFrag += mod.srcHeadFrag || "";
  755. srcVert += mod.srcBodyVert || "";
  756. srcFrag += mod.srcBodyFrag || "";
  757.  
  758. srcHeadVert += "\n//---- end mod ------\n";
  759. srcHeadFrag += "\n//---- end mod ------\n";
  760.  
  761. srcVert += "\n//---- end mod ------\n";
  762. srcFrag += "\n//---- end mod ------\n";
  763.  
  764. srcVert = srcVert.replace(/{{mod}}/g, mod.prefix);
  765. srcFrag = srcFrag.replace(/{{mod}}/g, mod.prefix);
  766. srcHeadVert = srcHeadVert.replace(/{{mod}}/g, mod.prefix);
  767. srcHeadFrag = srcHeadFrag.replace(/{{mod}}/g, mod.prefix);
  768.  
  769. srcVert = srcVert.replace(/MOD_/g, mod.prefix);
  770. srcFrag = srcFrag.replace(/MOD_/g, mod.prefix);
  771. srcHeadVert = srcHeadVert.replace(/MOD_/g, mod.prefix);
  772. srcHeadFrag = srcHeadFrag.replace(/MOD_/g, mod.prefix);
  773. }
  774. }
  775.  
  776.  
  777. vs = vs.replace("{{" + this._moduleNames[i] + "}}", srcVert);
  778. fs = fs.replace("{{" + this._moduleNames[i] + "}}", srcFrag);
  779. }
  780.  
  781.  
  782. vs = vs.replace("{{MODULES_HEAD}}", srcHeadVert);
  783. fs = fs.replace("{{MODULES_HEAD}}", srcHeadFrag);
  784.  
  785.  
  786. vs = this._addLibs(vs);
  787. fs = this._addLibs(fs);
  788.  
  789.  
  790. // SETUP draw buffers / multi texture render targets
  791.  
  792. let drawBufferStr = "";
  793. for (let i = 0; i < 16; i++)
  794. if (fs.contains("outColor" + i)) this._drawBuffers[i] = true;
  795.  
  796. if (this._drawBuffers.length == 1)
  797. {
  798. drawBufferStr = "out vec4 outColor;".endl();
  799. drawBufferStr += "#define gl_FragColor outColor".endl();
  800. }
  801. else
  802. {
  803. drawBufferStr += "#define MULTI_COLORTARGETS".endl();
  804. drawBufferStr += "vec4 outColor;".endl();
  805.  
  806. let count = 0;
  807. for (let i = 0; i < this._drawBuffers.length; i++)
  808. {
  809. if (count == 0) drawBufferStr += "#define gl_FragColor outColor" + i + "".endl();
  810. drawBufferStr += "layout(location = " + i + ") out vec4 outColor" + i + ";".endl();
  811. count++;
  812. }
  813. }
  814.  
  815. fs = fs.replace("{{DRAWBUFFER}}", drawBufferStr);
  816. // //////
  817.  
  818.  
  819. if (!this._program)
  820. {
  821. this._program = this._createProgram(vs, fs);
  822. }
  823. else
  824. {
  825. // this.vshader=createShader(vs, gl.VERTEX_SHADER, this.vshader );
  826. // this.fshader=createShader(fs, gl.FRAGMENT_SHADER, this.fshader );
  827. // linkProgram(program);
  828. this._program = this._createProgram(vs, fs);
  829.  
  830. this._projMatrixUniform = null;
  831.  
  832. for (let i = 0; i < this._uniforms.length; i++) this._uniforms[i].resetLoc();
  833. }
  834.  
  835. this.finalShaderFrag = fs;
  836. this.finalShaderVert = vs;
  837.  
  838.  
  839. MESH.lastMesh = null;
  840. MESH.lastShader = null;
  841.  
  842. this._countMissingUniforms = 0;
  843. this._needsRecompile = false;
  844. this.lastCompile = now();
  845.  
  846. // this._cgl.printError("shader compile");
  847.  
  848. this._cgl.profileData.shaderCompileTime += performance.now() - startTime;
  849. };
  850.  
  851. hasChanged()
  852. {
  853. return this._needsRecompile;
  854. }
  855.  
  856.  
  857. bind()
  858. {
  859. if (!this._isValid || this._cgl.aborted) return;
  860.  
  861. MESH.lastShader = this;
  862.  
  863. if (!this._program || this._needsRecompile) this.compile();
  864. if (!this._isValid) return;
  865.  
  866. if (!this._projMatrixUniform && !this.ignoreMissingUniforms)
  867. {
  868. this._countMissingUniforms++;
  869. // if (this._countMissingUniforms == 10)console.log("stopping getlocation of missing uniforms...", this._name);
  870. if (this._countMissingUniforms < 10)
  871. {
  872. this._projMatrixUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_PROJMAT);
  873. this._attrVertexPos = this._cgl.glGetAttribLocation(this._program, CONSTANTS.SHADER.SHADERVAR_VERTEX_POSITION);
  874. this._mvMatrixUniform = this._cgl.gl.getUniformLocation(this._program, "mvMatrix");
  875. this._vMatrixUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_VIEWMAT);
  876. this._mMatrixUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_MODELMAT);
  877. this._camPosUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_VIEWPOS);
  878. this._normalMatrixUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_NORMALMAT);
  879. this._inverseViewMatrixUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_INVVIEWMAT);
  880. this._inverseProjMatrixUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_INVPROJMAT);
  881. this._materialIdUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_MATERIALID);
  882. this._objectIdUniform = this._cgl.gl.getUniformLocation(this._program, CONSTANTS.SHADER.SHADERVAR_UNI_OBJECTID);
  883.  
  884. for (let i = 0; i < this._uniforms.length; i++) this._uniforms[i].needsUpdate = true;
  885. }
  886. }
  887.  
  888.  
  889. if (this._cgl.currentProgram != this._program)
  890. {
  891. this._cgl.profileData.profileShaderBinds++;
  892. this._cgl.gl.useProgram(this._program);
  893. this._cgl.currentProgram = this._program;
  894. }
  895.  
  896. for (let i = 0; i < this._uniforms.length; i++)
  897. if (this._uniforms[i].needsUpdate) this._uniforms[i].updateValue();
  898.  
  899. if (this._pMatrixState != this._cgl.getProjectionMatrixStateCount())
  900. {
  901. this._pMatrixState = this._cgl.getProjectionMatrixStateCount();
  902. this._cgl.gl.uniformMatrix4fv(this._projMatrixUniform, false, this._cgl.pMatrix);
  903. this._cgl.profileData.profileMVPMatrixCount++;
  904. }
  905.  
  906. if (this._objectIdUniform)
  907. this._cgl.gl.uniform1f(this._objectIdUniform, ++this._cgl.tempData.objectIdCounter);
  908.  
  909. if (this._materialIdUniform)
  910. this._cgl.gl.uniform1f(this._materialIdUniform, this._materialId);
  911.  
  912. if (this._vMatrixUniform)
  913. {
  914. if (this._vMatrixState != this._cgl.getViewMatrixStateCount())
  915. {
  916. this._cgl.gl.uniformMatrix4fv(this._vMatrixUniform, false, this._cgl.vMatrix);
  917. this._cgl.profileData.profileMVPMatrixCount++;
  918. this._vMatrixState = this._cgl.getViewMatrixStateCount();
  919.  
  920. if (this._inverseViewMatrixUniform)
  921. {
  922. mat4.invert(this._tempInverseViewMatrix, this._cgl.vMatrix);
  923. this._cgl.gl.uniformMatrix4fv(this._inverseViewMatrixUniform, false, this._tempInverseViewMatrix);
  924. this._cgl.profileData.profileMVPMatrixCount++;
  925. }
  926. if (this._inverseProjMatrixUniform)
  927. {
  928. mat4.invert(this._tempInverseProjMatrix, this._cgl.pMatrix);
  929. this._cgl.gl.uniformMatrix4fv(this._inverseProjMatrixUniform, false, this._tempInverseProjMatrix);
  930. this._cgl.profileData.profileMVPMatrixCount++;
  931. }
  932. }
  933. this._cgl.gl.uniformMatrix4fv(this._mMatrixUniform, false, this._cgl.mMatrix);
  934. this._cgl.profileData.profileMVPMatrixCount++;
  935.  
  936. if (this._camPosUniform)
  937. {
  938. mat4.invert(this._tempCamPosMatrix, this._cgl.vMatrix);
  939. this._cgl.gl.uniform3f(this._camPosUniform, this._tempCamPosMatrix[12], this._tempCamPosMatrix[13], this._tempCamPosMatrix[14]);
  940. this._cgl.profileData.profileMVPMatrixCount++;
  941. }
  942. }
  943. else
  944. {
  945. // mvmatrix deprecated....
  946. const tempmv = mat4.create();
  947.  
  948. mat4.mul(tempmv, this._cgl.vMatrix, this._cgl.mMatrix);
  949. this._cgl.gl.uniformMatrix4fv(this._mvMatrixUniform, false, tempmv);
  950. this._cgl.profileData.profileMVPMatrixCount++;
  951. }
  952.  
  953. if (this._normalMatrixUniform)
  954. {
  955. // mat4.mul(this._tempNormalMatrix, this._cgl.vMatrix, this._cgl.mMatrix);
  956. mat4.invert(this._tempNormalMatrix, this._cgl.mMatrix);
  957. mat4.transpose(this._tempNormalMatrix, this._tempNormalMatrix);
  958.  
  959. this._cgl.gl.uniformMatrix4fv(this._normalMatrixUniform, false, this._tempNormalMatrix);
  960. this._cgl.profileData.profileMVPMatrixCount++;
  961. }
  962.  
  963. for (let i = 0; i < this._libs.length; i++)
  964. {
  965. if (this._libs[i].onBind) this._libs[i].onBind.bind(this._libs[i])(this._cgl, this);
  966. }
  967.  
  968. this._bindTextures();
  969.  
  970. return this._isValid;
  971. };
  972.  
  973. unBind()
  974. {
  975. };
  976.  
  977.  
  978. dispose()
  979. {
  980. this._cgl.gl.deleteProgram(this._program);
  981. };
  982.  
  983. needsRecompile()
  984. {
  985. return this._needsRecompile;
  986. };
  987.  
  988. setDrawBuffers(arr)
  989. {
  990. console.log("useless drawbuffers...?!");
  991. // if (this._drawBuffers.length !== arr.length)
  992. // {
  993. // this._drawBuffers = arr;
  994. // this._needsRecompile = true;
  995. // this.setWhyCompile("setDrawBuffers");
  996. // return;
  997. // }
  998. // for (let i = 0; i < arr.length; i++)
  999. // {
  1000. // if (arr[i] !== this._drawBuffers[i])
  1001. // {
  1002. // this._drawBuffers = arr;
  1003. // this._needsRecompile = true;
  1004. // this.setWhyCompile("setDrawBuffers");
  1005. // return;
  1006. // }
  1007. // }
  1008. };
  1009.  
  1010. getUniforms()
  1011. {
  1012. return this._uniforms;
  1013. };
  1014.  
  1015. getUniform(name)
  1016. {
  1017. for (let i = 0; i < this._uniforms.length; i++)
  1018. if (this._uniforms[i].getName() == name)
  1019. return this._uniforms[i];
  1020. return null;
  1021. };
  1022.  
  1023. removeAllUniforms()
  1024. {
  1025. this._uniforms = [];
  1026. // for (let i = 0; i < this._uniforms.length; i++)
  1027. // this.removeUniform(this._uniforms[i].name);
  1028. };
  1029.  
  1030. removeUniform(name)
  1031. {
  1032. for (let i = 0; i < this._uniforms.length; i++)
  1033. {
  1034. if (this._uniforms[i].getName() == name)
  1035. {
  1036. this._uniforms.splice(i, 1);
  1037. }
  1038. }
  1039. this._needsRecompile = true;
  1040. this.setWhyCompile("remove uniform " + name);
  1041. };
  1042.  
  1043.  
  1044. _addUniform(uni)
  1045. {
  1046. this._uniforms.push(uni);
  1047. this.setWhyCompile("add uniform " + name);
  1048. this._needsRecompile = true;
  1049. };
  1050.  
  1051. /**
  1052. * add a uniform to the fragment shader
  1053. * @param {String} type ['f','t', etc]
  1054. * @param {String} name
  1055. * @param {any} valueOrPort value or port
  1056. * @param p2
  1057. * @param p3
  1058. * @param p4
  1059. * @memberof Shader
  1060. * @instance
  1061. * @function addUniformFrag
  1062. * @returns {CGL.Uniform}
  1063. */
  1064. addUniformFrag(type, name, valueOrPort, p2, p3, p4)
  1065. {
  1066. const uni = new CGL.Uniform(this, type, name, valueOrPort, p2, p3, p4);
  1067. uni.shaderType = "frag";
  1068. return uni;
  1069. };
  1070.  
  1071. /**
  1072. * add a uniform to the vertex shader
  1073. * @param {String} type ['f','t', etc]
  1074. * @param {String} name
  1075. * @param {any} valueOrPort value or port
  1076. * @param p2
  1077. * @param p3
  1078. * @param p4
  1079. * @memberof Shader
  1080. * @instance
  1081. * @function addUniformVert
  1082. * @returns {CGL.Uniform}
  1083. */
  1084. addUniformVert(type, name, valueOrPort, p2, p3, p4)
  1085. {
  1086. const uni = new CGL.Uniform(this, type, name, valueOrPort, p2, p3, p4);
  1087. uni.shaderType = "vert";
  1088. return uni;
  1089. };
  1090. /**
  1091. * add a uniform to both shaders
  1092. * @param {String} type ['f','t', etc]
  1093. * @param {String} name
  1094. * @param {any} valueOrPort value or port
  1095. * @param p2
  1096. * @param p3
  1097. * @param p4
  1098. * @memberof Shader
  1099. * @instance
  1100. * @function addUniformBoth
  1101. * @returns {CGL.Uniform}
  1102. */
  1103. addUniformBoth(type, name, valueOrPort, p2, p3, p4)
  1104. {
  1105. const uni = new CGL.Uniform(this, type, name, valueOrPort, p2, p3, p4);
  1106. uni.shaderType = "both";
  1107. return uni;
  1108. };
  1109.  
  1110. /**
  1111. * add a struct & its uniforms to the fragment shader
  1112. * @param {String} structName name of the struct, i.e.: LightStruct
  1113. * @param {String} uniformName name of the struct uniform in the shader, i.e.: lightUni
  1114. * @param {Array} members array of objects containing the struct members. see example for structure
  1115.  
  1116. * @memberof Shader
  1117. * @instance
  1118. * @function addUniformStructFrag
  1119. * @returns {Object}
  1120. * @example
  1121. * const shader = new CGL.Shader(cgl, 'MinimalMaterial');
  1122. * shader.setSource(attachments.shader_vert, attachments.shader_frag);
  1123. * shader.addUniformStructFrag("Light", "uniformLight", [
  1124. * { "type": "3f", "name": "position", "v1": null },
  1125. * { "type": "4f", "name": "color", "v1": inR, v2: inG, v3: inB, v4: inAlpha }
  1126. * ]);
  1127. */
  1128. addUniformStructFrag(structName, uniformName, members)
  1129. {
  1130. const uniforms = {};
  1131.  
  1132. if (!members) return uniforms;
  1133.  
  1134. for (let i = 0; i < members.length; i += 1)
  1135. {
  1136. const member = members[i];
  1137. if (!this.hasUniform(uniformName + "." + member.name))
  1138. {
  1139. const uni = new CGL.Uniform(this, member.type, uniformName + "." + member.name, member.v1, member.v2, member.v3, member.v4, uniformName, structName, member.name);
  1140. uni.shaderType = "frag";
  1141. uniforms[uniformName + "." + member.name] = uni;
  1142. }
  1143. }
  1144.  
  1145. return uniforms;
  1146. };
  1147.  
  1148. /**
  1149. * add a struct & its uniforms to the vertex shader
  1150. * @param {String} structName name of the struct, i.e.: LightStruct
  1151. * @param {String} uniformName name of the struct uniform in the shader, i.e.: lightUni
  1152. * @param {Array} members array of objects containing the struct members. see example for structure
  1153.  
  1154. * @memberof Shader
  1155. * @instance
  1156. * @function addUniformStructVert
  1157. * @returns {CGL.Uniform}
  1158. * @example
  1159. * const shader = new CGL.Shader(cgl, 'MinimalMaterial');
  1160. * shader.setSource(attachments.shader_vert, attachments.shader_frag);
  1161. * shader.addUniformStructVert("Light", "uniformLight", [
  1162. * { "type": "3f", "name": "position", "v1": null },
  1163. * { "type": "4f", "name": "color", "v1": inR, v2: inG, v3: inB, v4: inAlpha }
  1164. * ]);
  1165. */
  1166. addUniformStructVert(structName, uniformName, members)
  1167. {
  1168. const uniforms = {};
  1169.  
  1170. if (!members) return uniforms;
  1171.  
  1172. for (let i = 0; i < members.length; i += 1)
  1173. {
  1174. const member = members[i];
  1175. if (!this.hasUniform(uniformName + "." + member.name))
  1176. {
  1177. const uni = new CGL.Uniform(this, member.type, uniformName + "." + member.name, member.v1, member.v2, member.v3, member.v4, uniformName, structName, member.name);
  1178. uni.shaderType = "vert";
  1179. uniforms[uniformName + "." + member.name] = uni;
  1180. }
  1181. }
  1182.  
  1183. return uniforms;
  1184. };
  1185.  
  1186. /**
  1187. * add a struct & its uniforms to the both shaders. PLEASE NOTE: it is not possible to add the same struct to both shaders when it contains ANY integer members.
  1188. * @param {String} structName name of the struct, i.e.: LightStruct
  1189. * @param {String} uniformName name of the struct uniform in the shader, i.e.: lightUni
  1190. * @param {Array} members array of objects containing the struct members. see example for structure
  1191.  
  1192. * @memberof Shader
  1193. * @instance
  1194. * @function addUniformStructBoth
  1195. * @returns {Object}
  1196. * @example
  1197. * const shader = new CGL.Shader(cgl, 'MinimalMaterial');
  1198. * shader.setSource(attachments.shader_vert, attachments.shader_frag);
  1199. * shader.addUniformStructBoth("Light", "uniformLight", [
  1200. * { "type": "3f", "name": "position", "v1": null },
  1201. * { "type": "4f", "name": "color", "v1": inR, v2: inG, v3: inB, v4: inAlpha }
  1202. * ]);
  1203. */
  1204. addUniformStructBoth(structName, uniformName, members)
  1205. {
  1206. const uniforms = {};
  1207.  
  1208. if (!members) return uniforms;
  1209.  
  1210. for (let i = 0; i < members.length; i += 1)
  1211. {
  1212. const member = members[i];
  1213. if ((member.type === "2i" || member.type === "i" || member.type === "3i"))
  1214. this._log.error("Adding an integer struct member to both shaders can potentially error. Please use different structs for each shader. Error occured in struct:", structName, " with member:", member.name, " of type:", member.type, ".");
  1215. if (!this.hasUniform(uniformName + "." + member.name))
  1216. {
  1217. const uni = new CGL.Uniform(this, member.type, uniformName + "." + member.name, member.v1, member.v2, member.v3, member.v4, uniformName, structName, member.name);
  1218. uni.shaderType = "both";
  1219. uniforms[uniformName + "." + member.name] = uni;
  1220. }
  1221. }
  1222.  
  1223. return uniforms;
  1224. };
  1225.  
  1226. hasUniform(name)
  1227. {
  1228. for (let i = 0; i < this._uniforms.length; i++)
  1229. {
  1230. if (this._uniforms[i].getName() == name) return true;
  1231. }
  1232. return false;
  1233. };
  1234.  
  1235. _createProgram(vstr, fstr)
  1236. {
  1237. this._cgl.printError("before _createprogram");
  1238.  
  1239. const program = this._cgl.gl.createProgram();
  1240.  
  1241. this.vshader = Shader.createShader(this._cgl, vstr, this._cgl.gl.VERTEX_SHADER, this);
  1242. this.fshader = Shader.createShader(this._cgl, fstr, this._cgl.gl.FRAGMENT_SHADER, this);
  1243.  
  1244.  
  1245. if (this.vshader && this.fshader)
  1246. {
  1247. this._cgl.gl.attachShader(program, this.vshader);
  1248. this._cgl.gl.attachShader(program, this.fshader);
  1249.  
  1250. this._linkProgram(program, vstr, fstr);
  1251. }
  1252. else
  1253. {
  1254. this._isValid = false;
  1255. this._cgl.printError("shader _createProgram");
  1256. this._log.error("could not link shaderprogram");
  1257. return null;
  1258. }
  1259.  
  1260. this._cgl.printError("shader _createProgram");
  1261. return program;
  1262. };
  1263.  
  1264. hasErrors()
  1265. {
  1266. return this._hasErrors;
  1267. };
  1268.  
  1269. _linkProgram(program, vstr, fstr)
  1270. {
  1271. this._cgl.printError("before _linkprogram");
  1272.  
  1273. if (this._feedBackNames.length > 0)
  1274. {
  1275. this._cgl.gl.transformFeedbackVaryings(program, this._feedBackNames, this._cgl.gl.SEPARATE_ATTRIBS);
  1276. // INTERLEAVED_ATTRIBS
  1277. // SEPARATE_ATTRIBS
  1278. }
  1279.  
  1280. this._cgl.gl.linkProgram(program);
  1281. this._cgl.printError("gl.linkprogram");
  1282. this._isValid = true;
  1283.  
  1284. this._hasErrors = false;
  1285.  
  1286. if (this._cgl.patch.config.glValidateShader !== false)
  1287. {
  1288. this._cgl.gl.validateProgram(program);
  1289.  
  1290. if (!this._cgl.gl.getProgramParameter(program, this._cgl.gl.VALIDATE_STATUS))
  1291. {
  1292. // validation failed
  1293. console.log("shaderprogram validation failed...");
  1294. console.log(this._name + " programinfo: ", this._cgl.gl.getProgramInfoLog(program));
  1295. }
  1296.  
  1297. if (!this._cgl.gl.getProgramParameter(program, this._cgl.gl.LINK_STATUS))
  1298. {
  1299. this._hasErrors = true;
  1300.  
  1301. const infoLogFrag = this._cgl.gl.getShaderInfoLog(this.fshader);
  1302. const infoLogVert = this._cgl.gl.getShaderInfoLog(this.vshader);
  1303.  
  1304. if (infoLogFrag) this._log.warn(this._cgl.gl.getShaderInfoLog(this.fshader));
  1305. if (infoLogVert) this._log.warn(this._cgl.gl.getShaderInfoLog(this.vshader));
  1306.  
  1307. this._log.error(this._name + " shader linking fail...");
  1308.  
  1309. console.log(this._name + " programinfo: ", this._cgl.gl.getProgramInfoLog(program));
  1310. console.log(this);
  1311. this._isValid = false;
  1312.  
  1313. this._name = "errorshader";
  1314. this.setSource(Shader.getDefaultVertexShader(), Shader.getErrorFragmentShader());
  1315. this._cgl.printError("shader link err");
  1316. }
  1317. }
  1318. };
  1319.  
  1320. getProgram()
  1321. {
  1322. return this._program;
  1323. };
  1324.  
  1325. setFeedbackNames(names)
  1326. {
  1327. this.setWhyCompile("setFeedbackNames");
  1328. this._needsRecompile = true;
  1329. this._feedBackNames = names;
  1330. };
  1331.  
  1332. // getDefaultVertexShader()
  1333. // {
  1334. // return defaultShaderSrcVert;
  1335. // }
  1336.  
  1337. // getDefaultFragmentShader()
  1338. // {
  1339. // return this.getDefaultFragmentShader()
  1340. // }
  1341.  
  1342.  
  1343. /**
  1344. * adds attribute definition to shader header without colliding with other shader modules...
  1345. * when attrFrag is defined, vertex shader will output this attribute to the fragment shader
  1346. * @function
  1347. * @memberof Shader
  1348. * @instance
  1349. * @param {Object} attr {type:x,name:x,[nameFrag:x]}
  1350. * @return {Object}
  1351. */
  1352. addAttribute = function (attr)
  1353. {
  1354. for (let i = 0; i < this._attributes.length; i++)
  1355. {
  1356. if (this._attributes[i].name == attr.name && this._attributes[i].nameFrag == attr.nameFrag) return;
  1357. }
  1358. this._attributes.push(attr);
  1359. this._needsRecompile = true;
  1360. this.setWhyCompile("addAttribute");
  1361. };
  1362.  
  1363. bindTextures()
  1364. {
  1365. this._bindTextures();
  1366. }
  1367. _bindTextures()
  1368. {
  1369. if (this._textureStackTex.length > this._cgl.maxTextureUnits)
  1370. {
  1371. this._log.warn("[shader._bindTextures] too many textures bound", this._textureStackTex.length + "/" + this._cgl.maxTextureUnits);
  1372. }
  1373.  
  1374. // for (let i = this._textureStackTex.length + 1; i < this._cgl.maxTextureUnits; i++) this._cgl.setTexture(i, null);
  1375.  
  1376. for (let i = 0; i < this._textureStackTex.length; i++)
  1377. {
  1378. // console.log(this._textureStackTex.length, i);
  1379. if (!this._textureStackTex[i] && !this._textureStackTexCgl[i])
  1380. {
  1381. this._log.warn("no texture for pushtexture", this._name);
  1382. }
  1383. else
  1384. {
  1385. let t = this._textureStackTex[i];
  1386. if (this._textureStackTexCgl[i])
  1387. {
  1388. t = this._textureStackTexCgl[i].tex || CGL.Texture.getEmptyTexture(this._cgl).tex;
  1389. }
  1390.  
  1391. let bindOk = true;
  1392.  
  1393. if (!this._textureStackUni[i])
  1394. {
  1395. // throw(new Error('no uniform given to texturestack'));
  1396. this._log.warn("no uniform for pushtexture", this._name);
  1397. bindOk = this._cgl.setTexture(i, t, this._textureStackType[i]);
  1398. }
  1399. else
  1400. {
  1401. this._textureStackUni[i].setValue(i);
  1402. bindOk = this._cgl.setTexture(i, t, this._textureStackType[i]);
  1403.  
  1404. // console.log(bindOk, i, t, this._textureStackType[i]);
  1405. }
  1406. if (!bindOk) console.warn("tex bind failed", this.getName(), this._textureStackUni[i]);
  1407. }
  1408. }
  1409. };
  1410.  
  1411. setUniformTexture = function (uni, tex)
  1412. {
  1413. tex = tex || CGL.Texture.getTempTexture(this._cgl);
  1414. for (let i = 0; i < this._textureStackUni.length; i++)
  1415. if (this._textureStackUni[i] == uni)
  1416. {
  1417. const old = this._textureStackTex[i] || this._textureStackTexCgl[i];
  1418. if (tex.hasOwnProperty("tex"))
  1419. {
  1420. this._textureStackTexCgl[i] = tex;
  1421. this._textureStackTex[i] = null;
  1422. }
  1423. else
  1424. {
  1425. this._textureStackTexCgl[i] = null;
  1426. this._textureStackTex[i] = tex;
  1427. }
  1428.  
  1429. // this._textureStackTex[i] = tex;
  1430. // this._cgl.setTexture(i, tex, this._textureStackType[i]);
  1431. return old;
  1432. }
  1433. return null;
  1434. };
  1435.  
  1436. /**
  1437. * push a texture on the stack. those textures will be bound when binding the shader. texture slots are automatically set
  1438. * @param {uniform} uniform texture uniform
  1439. * @param {texture} t texture
  1440. * @param {type} type texture type, can be ignored when TEXTURE_2D
  1441. * @function pushTexture
  1442. * @memberof Shader
  1443. * @instance
  1444. */
  1445. pushTexture = function (uniform, t, type)
  1446. {
  1447. if (!uniform)
  1448. {
  1449. // console.log("pushtexture: no uniform given to texturestack", "shader:"+this._name,uniform,t,type);
  1450. return;
  1451. }
  1452. if (!t)
  1453. {
  1454. // if(uniform)this._log.warn("pushtexture: no tex","shader:"+this._name," uniform:"+uniform.name);
  1455. return;
  1456. }
  1457. if (!t.hasOwnProperty("tex") && !(t instanceof WebGLTexture))
  1458. {
  1459. this._log.warn(new Error("invalid texture").stack);
  1460.  
  1461. this._log.warn("[cgl_shader] invalid texture...", t);
  1462. return;
  1463. }
  1464.  
  1465. this._textureStackUni.push(uniform);
  1466.  
  1467. if (t.hasOwnProperty("tex"))
  1468. {
  1469. this._textureStackTexCgl.push(t);
  1470. this._textureStackTex.push(null);
  1471. }
  1472. else
  1473. {
  1474. this._textureStackTexCgl.push(null);
  1475. this._textureStackTex.push(t);
  1476. }
  1477.  
  1478. this._textureStackType.push(type);
  1479. };
  1480.  
  1481. /**
  1482. * pop last texture
  1483. * @function popTexture
  1484. * @memberof Shader
  1485. * @instance
  1486. */
  1487. popTexture = function ()
  1488. {
  1489. this._textureStackUni.pop();
  1490. this._textureStackTex.pop();
  1491. this._textureStackTexCgl.pop();
  1492. this._textureStackType.pop();
  1493. };
  1494.  
  1495. /**
  1496. * pop all textures
  1497. * @function popTextures
  1498. * @memberof Shader
  1499. * @instance
  1500. */
  1501. popTextures = function ()
  1502. {
  1503. this._textureStackTex.length =
  1504. this._textureStackTexCgl.length =
  1505. this._textureStackType.length =
  1506. this._textureStackUni.length = 0;
  1507. };
  1508.  
  1509. getMaterialId()
  1510. {
  1511. return this._materialId;
  1512. };
  1513.  
  1514. getInfo()
  1515. {
  1516. const info = {};
  1517. info.name = this._name;
  1518. // info.modules = JSON.parse(JSON.stringify(this._modules));
  1519. // info.defines = JSON.parse(JSON.stringify(this._defines));
  1520. info.defines = this.getDefines();
  1521. info.hasErrors = this.hasErrors();
  1522.  
  1523. return info;
  1524. };
  1525.  
  1526.  
  1527. getDefaultFragmentShader=function(r,g,b,a)
  1528. {
  1529. return getDefaultFragmentShader(r,g,b,a);
  1530. }
  1531.  
  1532. getDefaultVertexShader=function()
  1533. {
  1534. return getDefaultVertexShader();
  1535. }
  1536.  
  1537.  
  1538. }
  1539.  
  1540.  
  1541.  
  1542.  
  1543.  
  1544.  
  1545.  
  1546.  
  1547.  
  1548.  
  1549.  
  1550.  
  1551.  
  1552.  
  1553.  
  1554.  
  1555.  
  1556.  
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564. // --------------------------
  1565.  
  1566. Shader.getDefaultVertexShader=getDefaultVertexShader;
  1567. Shader.getDefaultFragmentShader=getDefaultFragmentShader;
  1568.  
  1569.  
  1570. Shader.getErrorFragmentShader = function ()
  1571. {
  1572. return ""
  1573. .endl() + "void main()"
  1574. .endl() + "{"
  1575. .endl() + " float g=mod((gl_FragCoord.y+gl_FragCoord.x),50.0)/50.0;"
  1576. .endl() + " g= step(0.1,g);"
  1577. .endl() + " outColor = vec4( g+0.5, 0.0, 0.0, 1.0);"
  1578. .endl() + "}";
  1579. };
  1580.  
  1581. Shader.createShader = function (cgl, str, type, cglShader)
  1582. {
  1583. if (cgl.aborted) return;
  1584.  
  1585. // cgl.printError("[Shader.createShader] ", cglShader._name);
  1586.  
  1587. function getBadLines(infoLog)
  1588. {
  1589. const basLines = [];
  1590. const lines = infoLog.split("\n");
  1591. for (const i in lines)
  1592. {
  1593. const divide = lines[i].split(":");
  1594. if (parseInt(divide[2], 10)) basLines.push(parseInt(divide[2], 10));
  1595. }
  1596. return basLines;
  1597. }
  1598.  
  1599.  
  1600. const shader = cgl.gl.createShader(type);
  1601. cgl.gl.shaderSource(shader, str);
  1602. cgl.gl.compileShader(shader);
  1603.  
  1604. if (!cgl.gl.getShaderParameter(shader, cgl.gl.COMPILE_STATUS))
  1605. {
  1606. let infoLog = cgl.gl.getShaderInfoLog(shader);
  1607. if (!infoLog)
  1608. {
  1609. console.warn("empty shader info log", this._name);
  1610. return;
  1611. }
  1612.  
  1613.  
  1614. const badLines = getBadLines(infoLog);
  1615. let htmlWarning = "<pre style=\"margin-bottom:0px;\"><code class=\"shaderErrorCode language-glsl\" style=\"padding-bottom:0px;max-height: initial;max-width: initial;\">";
  1616. const lines = str.match(/^.*((\r\n|\n|\r)|$)/gm);
  1617.  
  1618. if (!cgl.aborted && infoLog)
  1619. {
  1620. if (type == cgl.gl.VERTEX_SHADER) console.log("VERTEX_SHADER");
  1621. if (type == cgl.gl.FRAGMENT_SHADER) console.log("FRAGMENT_SHADER");
  1622.  
  1623. for (const i in lines)
  1624. {
  1625. const j = parseInt(i, 10) + 1;
  1626. const line = j + ": " + lines[i];
  1627.  
  1628. let isBadLine = false;
  1629. for (const bj in badLines)
  1630. if (badLines[bj] == j) isBadLine = true;
  1631.  
  1632. if (isBadLine)
  1633. {
  1634. htmlWarning += "</code></pre>";
  1635. htmlWarning += "<pre style=\"margin:0\"><code class=\"language-glsl\" style=\"background-color:#660000;padding-top:0px;padding-bottom:0px\">";
  1636.  
  1637. cglShader._log.log("bad line: `" + line + "`");
  1638. }
  1639. htmlWarning += escapeHTML(line);
  1640.  
  1641. if (isBadLine)
  1642. {
  1643. htmlWarning += "</code></pre>";
  1644. htmlWarning += "<pre style=\"margin:0\"><code class=\"language-glsl\" style=\";padding-top:0px;padding-bottom:0px\">";
  1645. }
  1646. }
  1647. }
  1648.  
  1649. infoLog = infoLog.replace(/\n/g, "<br/>");
  1650. if (cgl.patch.isEditorMode())console.log("Shader error ", cglShader._name, infoLog, this);
  1651.  
  1652. htmlWarning = infoLog + "<br/>" + htmlWarning + "<br/><br/>";
  1653. htmlWarning += "</code></pre>";
  1654.  
  1655. if (this._fromUserInteraction)
  1656. {
  1657. // console.log("todo show modal?");
  1658. // cgl.patch.emitEvent("criticalError", { "title": "Shader error " + cglShader._name, "text": htmlWarning, "exception": { "message": infoLog } });
  1659. }
  1660.  
  1661. cglShader.setSource(Shader.getDefaultVertexShader(), Shader.getErrorFragmentShader());
  1662. }
  1663. else
  1664. {
  1665. // console.log(name+' shader compiled...');
  1666. }
  1667. // cgl.printError("shader create2");
  1668. return shader;
  1669. };
  1670.  
  1671.  
  1672. export { Shader };
  1673.  
  1674.  
  1675.  
  1676.  
  1677.  
  1678.  
  1679.  
  1680.  
  1681.