Home Reference Source

cables_dev/cables/src/core/cgp/cgp_shader.js

  1. import { Logger } from "cables-shared-client";
  2. import Uniform from "./cgp_uniform.js";
  3. import { preproc } from "../cg/preproc.js";
  4. import { CgShader } from "../cg/cg_shader.js";
  5. import Binding from "./cgp_binding.js";
  6.  
  7. export default class Shader extends CgShader
  8. {
  9. constructor(_cgp, _name, options = {})
  10. {
  11. super();
  12. if (!_cgp) throw new Error("shader constructed without cgp " + _name);
  13. this._log = new Logger("cgp_shader");
  14. this._cgp = _cgp;
  15. this._name = _name;
  16. this._uniforms = [];
  17. this.compute = options.compute || false;
  18.  
  19. if (!_name) this._log.stack("no shader name given");
  20. this._name = _name || "unknown";
  21. this._compileReason = "";
  22. this.gpuShaderModule = null;
  23. this._needsRecompile = true;
  24. this.bindingCounter = 0;
  25. this.bindCountlastFrame = -1;
  26. this._bindingIndexCount = 0;
  27.  
  28. this.defaultBindingVert = new Binding(_cgp, "vsUniforms", { "stage": "vert", "bindingType": "uniform", "index": this._bindingIndexCount++ });
  29. this.defaultBindingFrag = new Binding(_cgp, "fsUniforms", { "stage": "frag", "bindingType": "uniform", "index": this._bindingIndexCount++ });
  30. this.defaultBindingComp = new Binding(_cgp, "computeUniforms", { "bindingType": "uniform", "index": this._bindingIndexCount++ });
  31. this.bindingsFrag = [this.defaultBindingFrag];
  32. this.bindingsVert = [this.defaultBindingVert];
  33. this.bindingsComp = [this.defaultBindingComp];
  34.  
  35. if (!this.compute)
  36. {
  37. this.uniModelMatrix = this.addUniformVert("m4", "modelMatrix");
  38. this.uniViewMatrix = this.addUniformVert("m4", "viewMatrix");
  39. this.uniProjMatrix = this.addUniformVert("m4", "projMatrix");
  40. this.uniNormalMatrix = this.addUniformVert("m4", "normalMatrix");
  41. this.uniModelViewMatrix = this.addUniformVert("m4", "modelViewMatrix");
  42. this._tempNormalMatrix = mat4.create();
  43. this._tempModelViewMatrix = mat4.create();
  44. }
  45.  
  46.  
  47. this._src = "";
  48.  
  49. this._cgp.on("deviceChange", () =>
  50. {
  51. this.gpuShaderModule = null;
  52. this._needsRecompile = "device changed";
  53. });
  54. }
  55.  
  56. incBindingCounter()
  57. {
  58. if (this.bindCountlastFrame != this._cgp.frame) this.bindingCounter = 0;
  59. else this.bindingCounter++;
  60. this.bindCountlastFrame = this._cgp.frame;
  61. }
  62.  
  63. reInit()
  64. {
  65.  
  66. }
  67.  
  68. get isValid()
  69. {
  70. return this._isValid;
  71. }
  72.  
  73. get uniforms()
  74. {
  75. return this._uniforms;
  76. }
  77.  
  78. getName()
  79. {
  80. return this._name;
  81. }
  82.  
  83. setWhyCompile(why)
  84. {
  85. this._compileReason = why;
  86. }
  87.  
  88. getNewBindingIndex()
  89. {
  90. return ++this._bindingIndexCount;
  91. }
  92.  
  93.  
  94. setSource(src)
  95. {
  96. this._src = src;
  97. this.setWhyCompile("Source changed");
  98. this._needsRecompile = true;
  99. }
  100.  
  101. _replaceMods(vs)
  102. {
  103. let srcHeadVert = "";
  104. for (let i = 0; i < this._moduleNames.length; i++)
  105. {
  106. let srcVert = "";
  107.  
  108. for (let j = 0; j < this._modules.length; j++)
  109. {
  110. const mod = this._modules[j];
  111. if (mod.name == this._moduleNames[i])
  112. {
  113. srcHeadVert += "\n//---- MOD: group:" + mod.group + ": idx:" + j + " - prfx:" + mod.prefix + " - " + mod.title + " ------\n";
  114.  
  115. srcVert += "\n\n//---- MOD: " + mod.title + " / " + mod.priority + " ------\n";
  116.  
  117. if (mod.attributes)
  118. for (let k = 0; k < mod.attributes.length; k++)
  119. {
  120. const r = this._getAttrSrc(mod.attributes[k], false);
  121. if (r.srcHeadVert)srcHeadVert += r.srcHeadVert;
  122. if (r.srcVert)srcVert += r.srcVert;
  123. }
  124.  
  125. srcHeadVert += mod.srcHead || "";
  126. srcVert += mod.srcBody || "";
  127.  
  128. srcHeadVert += "\n//---- end mod ------\n";
  129.  
  130. srcVert += "\n//---- end mod ------\n";
  131.  
  132. srcVert = srcVert.replace(/{{mod}}/g, mod.prefix);
  133. srcHeadVert = srcHeadVert.replace(/{{mod}}/g, mod.prefix);
  134.  
  135. srcVert = srcVert.replace(/MOD_/g, mod.prefix);
  136. srcHeadVert = srcHeadVert.replace(/MOD_/g, mod.prefix);
  137. }
  138. }
  139.  
  140. vs = vs.replace("{{" + this._moduleNames[i] + "}}", srcVert);
  141. }
  142.  
  143. vs = vs.replace("{{MODULES_HEAD}}", srcHeadVert);
  144. return vs;
  145. }
  146.  
  147. getProcessedSource()
  148. {
  149. const defs = {};
  150. for (let i = 0; i < this._defines.length; i++)
  151. defs[this._defines[i][0]] = this._defines[i][1] || true;
  152.  
  153.  
  154. let src = preproc(this._src, defs);
  155.  
  156. let bindingsHeadVert = "";
  157. for (let i = 0; i < this.bindingsFrag.length; i++)
  158. bindingsHeadVert += this.bindingsFrag[i].getShaderHeaderCode();
  159.  
  160. let bindingsHeadFrag = "";
  161. for (let i = 0; i < this.bindingsVert.length; i++)
  162. bindingsHeadFrag += this.bindingsVert[i].getShaderHeaderCode();
  163.  
  164.  
  165.  
  166. src = bindingsHeadFrag + "\n\n////////////////\n\n" + bindingsHeadVert + "\n\n////////////////\n\n" + src;
  167. src = this._replaceMods(src);
  168.  
  169. return src;
  170. // console.log("----------------\n", src, "\n----------------------------");
  171. }
  172.  
  173. compile()
  174. {
  175. console.log("compile", this._compileReason);
  176. this._isValid = true;
  177. this._cgp.pushErrorScope("cgp_shader " + this._name);
  178. // console.log(this.getProcessedSource());
  179. this.gpuShaderModule = this._cgp.device.createShaderModule({ "code": this.getProcessedSource(), "label": this._name });
  180. this._cgp.popErrorScope(this.error.bind(this));
  181. this._needsRecompile = false;
  182.  
  183. this.emitEvent("compiled");
  184. }
  185.  
  186. error(e)
  187. {
  188. this._isValid = false;
  189. }
  190.  
  191. bind()
  192. {
  193. if (!this.compute)
  194. {
  195. this.uniModelMatrix.setValue(this._cgp.mMatrix);
  196. this.uniViewMatrix.setValue(this._cgp.vMatrix);
  197. this.uniProjMatrix.setValue(this._cgp.pMatrix);
  198.  
  199. // mat4.invert(this._tempNormalMatrix, this._cgp.mMatrix);
  200. // mat4.transpose(this._tempNormalMatrix, this._tempNormalMatrix);
  201. mat4.mul(this._tempModelViewMatrix, this._cgp.vMatrix, this._cgp.mMatrix);
  202.  
  203.  
  204.  
  205. // mat4.set(this._tempNormalMatrix, this._tempModelViewMatrix);
  206. mat4.invert(this._tempNormalMatrix, this._tempModelViewMatrix);
  207. mat4.transpose(this._tempNormalMatrix, this._tempNormalMatrix);
  208.  
  209.  
  210. // cpu billboarding?
  211. // this._tempModelViewMatrix[0 * 4 + 0] = 1.0;
  212. // this._tempModelViewMatrix[0 * 4 + 1] = 0.0;
  213. // this._tempModelViewMatrix[0 * 4 + 2] = 0.0;
  214.  
  215. // // #ifndef BILLBOARDING_CYLINDRIC
  216. // this._tempModelViewMatrix[1 * 4 + 0] = 0.0;
  217. // this._tempModelViewMatrix[1 * 4 + 1] = 1.0;
  218. // this._tempModelViewMatrix[1 * 4 + 2] = 0.0;
  219. // // #endif
  220.  
  221. // this._tempModelViewMatrix[2 * 4 + 0] = 0.0;
  222. // this._tempModelViewMatrix[2 * 4 + 1] = 0.0;
  223. // this._tempModelViewMatrix[2 * 4 + 2] = 1.0;
  224.  
  225. this.uniModelViewMatrix.setValue(this._tempModelViewMatrix);
  226. this.uniNormalMatrix.setValue(this._tempNormalMatrix);
  227. }
  228.  
  229. if (this._needsRecompile) this.compile();
  230. }
  231.  
  232. /**
  233. * add a uniform to the fragment shader
  234. * @param {String} type ['f','t', etc]
  235. * @param {String} name
  236. * @param {any} valueOrPort value or port
  237. * @param p2
  238. * @param p3
  239. * @param p4
  240. * @memberof Shader
  241. * @instance
  242. * @function addUniformFrag
  243. * @returns {Uniform}
  244. */
  245. addUniformFrag(type, name, valueOrPort, p2, p3, p4)
  246. {
  247. const uni = new Uniform(this, type, name, valueOrPort, p2, p3, p4);
  248. uni.shaderType = "frag";
  249.  
  250. this.defaultBindingFrag.addUniform(uni);
  251. this.needsPipelineUpdate = "add frag uniform";
  252.  
  253. return uni;
  254. }
  255.  
  256. /**
  257. * add a uniform to the vertex shader
  258. * @param {String} type ['f','t', etc]
  259. * @param {String} name
  260. * @param {any} valueOrPort value or port
  261. * @param p2
  262. * @param p3
  263. * @param p4
  264. * @memberof Shader
  265. * @instance
  266. * @function addUniformVert
  267. * @returns {Uniform}
  268. */
  269. addUniformVert(type, name, valueOrPort, p2, p3, p4)
  270. {
  271. const uni = new Uniform(this, type, name, valueOrPort, p2, p3, p4);
  272. uni.shaderType = "vert";
  273.  
  274. this.defaultBindingVert.addUniform(uni);
  275. this.needsPipelineUpdate = "add ver uniform";
  276.  
  277. return uni;
  278. }
  279.  
  280. /**
  281. * add a uniform to all shader programs
  282. * @param {String} type ['f','t', etc]
  283. * @param {String} name
  284. * @param {any} valueOrPort value or port
  285. * @param p2
  286. * @param p3
  287. * @param p4
  288. * @memberof Shader
  289. * @instance
  290. * @function addUniform
  291. * @returns {Uniform}
  292. */
  293. addUniform(type, name, valueOrPort, p2, p3, p4)
  294. {
  295. const uni = new Uniform(this, type, name, valueOrPort, p2, p3, p4);
  296. uni.shaderType = "both";
  297. return uni;
  298. }
  299.  
  300. _addUniform(uni)
  301. {
  302. this._uniforms.push(uni);
  303. this.setWhyCompile("add uniform " + name);
  304. this._needsRecompile = true;
  305. }
  306.  
  307. getUniform(name)
  308. {
  309. for (let i = 0; i < this._uniforms.length; i++)
  310. {
  311. if (this._uniforms[i].getName() == name) return this._uniforms[i];
  312. }
  313. }
  314.  
  315. /**
  316. * copy current shader
  317. * @function copy
  318. * @memberof Shader
  319. * @instance
  320. * @returns newShader
  321. */
  322. copy()
  323. {
  324. const shader = new Shader(this._cgp, this._name + " copy");
  325. shader.setSource(this._src);
  326.  
  327. shader._modules = JSON.parse(JSON.stringify(this._modules));
  328. shader._defines = JSON.parse(JSON.stringify(this._defines));
  329.  
  330. shader._modGroupCount = this._modGroupCount;
  331. shader._moduleNames = this._moduleNames;
  332.  
  333. // shader.glPrimitive = this.glPrimitive;
  334. // shader.offScreenPass = this.offScreenPass;
  335. // shader._extensions = this._extensions;
  336. // shader.wireframe = this.wireframe;
  337. // shader._attributes = this._attributes;
  338.  
  339. for (let i = 0; i < this._uniforms.length; i++) this._uniforms[i].copy(shader);
  340.  
  341. shader.bindingsFrag = [];
  342. for (let i = 0; i < this.bindingsFrag.length; i++) this.bindingsFrag[i].copy(shader);
  343. shader.defaultBindingFrag = this.bindingsFrag[0];
  344.  
  345. shader.bindingsVert = [];
  346. for (let i = 0; i < this.bindingsVert.length; i++) this.bindingsVert[i].copy(shader);
  347. shader.defaultBindingVert = this.bindingsVert[0];
  348.  
  349. shader.bindingsComp = [];
  350. for (let i = 0; i < this.bindingsComp.length; i++) this.bindingsComp[i].copy(shader);
  351. shader.defaultBindingComp = this.bindingsComp[0];
  352.  
  353. console.log("copyyyyyyyyyy", shader.bindingsVert, this.bindingsVert);
  354.  
  355. this.setWhyCompile("copy");
  356. shader._needsRecompile = true;
  357. return shader;
  358. }
  359.  
  360.  
  361. /**
  362. * copy all uniform values from another shader
  363. * @function copyUniforms
  364. * @memberof Shader
  365. * @instance
  366. * @param origShader uniform values will be copied from this shader
  367. */
  368. copyUniformValues(origShader)
  369. {
  370. for (let i = 0; i < origShader._uniforms.length; i++)
  371. {
  372. if (!this._uniforms[i])
  373. {
  374. this._log.log("unknown uniform?!");
  375. continue;
  376. }
  377. this.getUniform(origShader._uniforms[i].getName()).set(origShader._uniforms[i].getValue());
  378. }
  379.  
  380. // this.popTextures();
  381. // for (let i = 0; i < origShader._textureStackUni.length; i++)
  382. // {
  383. // this._textureStackUni[i] = origShader._textureStackUni[i];
  384. // this._textureStackTex[i] = origShader._textureStackTex[i];
  385. // this._textureStackType[i] = origShader._textureStackType[i];
  386. // this._textureStackTexCgl[i] = origShader._textureStackTexCgl[i];
  387. // }
  388. }
  389. }