cables_dev/cables/src/core/cg/cg_shader.js
- import { EventTarget } from "../eventtarget.js";
- import { simpleId } from "../utils.js";
-
- class CgShader extends EventTarget
- {
- constructor()
- {
- super();
- this.id = simpleId();
- this._isValid = true;
- this._defines = [];
-
- this._moduleNames = [];
- this._modules = [];
- this._moduleNumId = 0;
- }
-
- /**
- * easily enable/disable a define without a value
- * @function toggleDefine
- * @memberof Shader
- * @instance
- * @param {name} name
- * @param {any} enabled value or port
- */
- toggleDefine(name, enabled)
- {
- if (enabled && typeof (enabled) == "object" && enabled.addEventListener) // port
- {
- if (enabled.changeListener)enabled.removeEventListener(enabled.changeListener);
-
- enabled.onToggleDefine = (v) =>
- {
- this.toggleDefine(name, v);
- };
-
- enabled.changeListener = enabled.on("change", enabled.onToggleDefine);
- enabled = enabled.get();
- }
-
- if (enabled) this.define(name);
- else this.removeDefine(name);
- }
-
- /**
- * add a define to a shader, e.g. #define DO_THIS_THAT 1
- * @function define
- * @memberof Shader
- * @instance
- * @param {String} name
- * @param {Any} value (can be empty)
- */
- define(name, value)
- {
- if (value === null || value === undefined) value = "";
-
- if (typeof (value) == "object") // port
- {
- value.removeEventListener("change", value.onDefineChange);
- value.onDefineChange = (v) =>
- {
- this.define(name, v);
- };
- value.on("change", value.onDefineChange);
-
- value = value.get();
- }
-
-
- for (let i = 0; i < this._defines.length; i++)
- {
- if (this._defines[i][0] == name && this._defines[i][1] == value) return;
- if (this._defines[i][0] == name)
- {
- this._defines[i][1] = value;
- this.setWhyCompile("define " + name + " " + value);
-
- this._needsRecompile = true;
- return;
- }
- }
- this.setWhyCompile("define " + name + " " + value);
- this._needsRecompile = true;
- this._defines.push([name, value]);
- }
-
- getDefines()
- {
- return this._defines;
- }
-
- getDefine(name)
- {
- for (let i = 0; i < this._defines.length; i++)
- if (this._defines[i][0] == name) return this._defines[i][1];
- return null;
- }
-
- /**
- * return true if shader has define
- * @function hasDefine
- * @memberof Shader
- * @instance
- * @param {String} name
- * @return {Boolean}
- */
- hasDefine(name)
- {
- for (let i = 0; i < this._defines.length; i++)
- if (this._defines[i][0] == name) return true;
- }
-
- /**
- * remove a define from a shader
- * @param {name} name
- * @function removeDefine
- * @memberof Shader
- * @instance
- */
- removeDefine(name)
- {
- for (let i = 0; i < this._defines.length; i++)
- {
- if (this._defines[i][0] == name)
- {
- this._defines.splice(i, 1);
- this._needsRecompile = true;
-
- this.setWhyCompile("define removed:" + name);
-
- return;
- }
- }
- }
-
-
- hasModule(modId)
- {
- for (let i = 0; i < this._modules.length; i++)
- {
- if (this._modules[i].id == modId) return true;
- }
- return false;
- }
-
- setModules(names)
- {
- this._moduleNames = names;
- }
-
-
- /**
- * remove a module from shader
- * @function removeModule
- * @memberof Shader
- * @instance
- * @param {shaderModule} mod the module to be removed
- */
- removeModule(mod)
- {
- for (let i = 0; i < this._modules.length; i++)
- {
- if (mod && mod.id)
- {
- if (this._modules[i].id == mod.id || !this._modules[i])
- {
- let found = true;
- while (found)
- {
- found = false;
- for (let j = 0; j < this._uniforms.length; j++)
- {
- if (this._uniforms[j].getName().startsWith(mod.prefix))
- {
- this._uniforms.splice(j, 1);
- found = true;
- continue;
- }
- }
- }
-
- this._needsRecompile = true;
- this.setWhyCompile("remove module " + mod.title);
- this._modules.splice(i, 1);
- break;
- }
- }
- }
- }
-
-
- getNumModules()
- {
- return this._modules.length;
- }
-
-
- getCurrentModules() { return this._modules; }
-
-
- /**
- * add a module
- * @function addModule
- * @memberof Shader
- * @instance
- * @param {shaderModule} mod the module to be added
- * @param {shaderModule} [sibling] sibling module, new module will share the same group
- */
- addModule(mod, sibling)
- {
- if (this.hasModule(mod.id)) return;
- if (!mod.id) mod.id = CABLES.simpleId();
- if (!mod.numId) mod.numId = this._moduleNumId;
- if (!mod.num)mod.num = this._modules.length;
- if (sibling && !sibling.group) sibling.group = simpleId();
-
- if (!mod.group)
- if (sibling) mod.group = sibling.group;
- else mod.group = simpleId();
-
- mod.prefix = "mod" + mod.group + "_";
- this._modules.push(mod);
-
- this._needsRecompile = true;
- this.setWhyCompile("add module " + mod.title);
- this._moduleNumId++;
-
- return mod;
- }
-
- getAttributeSrc(mod, srcHeadVert, srcVert)
- {
- if (mod.attributes)
- for (let k = 0; k < mod.attributes.length; k++)
- {
- const r = this._getAttrSrc(mod.attributes[k], false);
- if (r.srcHeadVert)srcHeadVert += r.srcHeadVert;
- if (r.srcVert)srcVert += r.srcVert;
- }
-
- return { "srcHeadVert": srcHeadVert, "srcVert": srcVert };
- }
-
- replaceModuleSrc()
- {
- let srcHeadVert = "";
-
- for (let j = 0; j < this._modules.length; j++)
- {
- const mod = this._modules[j];
- if (mod.name == this._moduleNames[i])
- {
- srcHeadVert += "\n//---- MOD: group:" + mod.group + ": idx:" + j + " - prfx:" + mod.prefix + " - " + mod.title + " ------\n";
-
- srcVert += "\n\n//---- MOD: " + mod.title + " / " + mod.priority + " ------\n";
-
-
- if (mod.getAttributeSrc)
- {
- const r = getAttributeSrc(mod, srcHeadVert, srcVert);
- if (r.srcHeadVert)srcHeadVert += r.srcHeadVert;
- if (r.srcVert)srcVert += r.srcVert;
- }
-
-
- srcHeadVert += mod.srcHeadVert || "";
- srcVert += mod.srcBodyVert || "";
-
- srcHeadVert += "\n//---- end mod ------\n";
-
- srcVert += "\n//---- end mod ------\n";
-
- srcVert = srcVert.replace(/{{mod}}/g, mod.prefix);
- srcHeadVert = srcHeadVert.replace(/{{mod}}/g, mod.prefix);
-
- srcVert = srcVert.replace(/MOD_/g, mod.prefix);
- srcHeadVert = srcHeadVert.replace(/MOD_/g, mod.prefix);
- }
- }
-
-
- vs = vs.replace("{{" + this._moduleNames[i] + "}}", srcVert);
- }
- }
-
- export { CgShader };