Home Reference Source

cables_dev/cables/src/libs/cgl/shadergraph/cgl_shadergraphprogram.js

  1. import { Events } from "cables-shared-client";
  2. import { ShaderGraph } from "./cgl_shadergraph.js";
  3.  
  4. const ShaderGraphProgram = class extends Events
  5. {
  6. constructor(op, port, type)
  7. {
  8. super();
  9. this._type = type;
  10. this._op = op;
  11. this._port = port;
  12. this.uniforms = [];
  13.  
  14. this._opIdsHeadFuncSrc = {};
  15. this._opIdsFuncCallSrc = {};
  16. this._functionIdInHead = {};
  17.  
  18. this._headFuncSrc = "";
  19. this._headUniSrc = "";
  20. this._callFuncStack = [];
  21. this.finalSrc = "";
  22. }
  23.  
  24. setOpShaderId(op)
  25. {
  26. if (!op.shaderId) op.shaderId = CGL.ShaderGraph.getNewId();
  27. }
  28.  
  29. replaceId(op, txt)
  30. {
  31. this.setOpShaderId(op);
  32. return txt.replaceAll("_ID", "_" + op.shaderId);
  33. }
  34.  
  35. addOpShaderFuncCode(op)
  36. {
  37. if (!op.sgOp)
  38. {
  39. console.warn("HAS NO SGOP!", op);
  40. return;
  41. }
  42. // if (!op.sgOp.info) return;
  43.  
  44.  
  45. if (this._opIdsHeadFuncSrc[op.id])
  46. {
  47. // console.log("already exist",op.name,op.id);
  48. return;
  49. }
  50. this._opIdsHeadFuncSrc[op.id] = true;
  51.  
  52. if (op.sgOp && op.sgOp._defines)
  53. for (let i = 0; i < op.sgOp._defines.length; i++)
  54. this._headFuncSrc += "#define " + op.sgOp._defines[i][0] + "\n";
  55.  
  56. // if (op.shaderSrc)
  57. // {
  58. // let src = op.shaderSrc.endl();// +"/* "+op.id+" */".endl();;
  59. // src = this.replaceId(op, src);
  60. // this._headFuncSrc += src;
  61. // }
  62.  
  63.  
  64. if (op.sgOp.info)
  65. {
  66. // console.log(op.sgOp.info.name, op.sgOp.info.functions);
  67. for (let i = 0; i < op.sgOp.info.functions.length; i++)
  68. {
  69. const f = op.sgOp.info.functions[i];
  70. // console.log("ADD FUNCTION CODE", f.name, f.uniqueName, this._functionIdInHead[f.uniqueName]);
  71. if (this._functionIdInHead[f.uniqueName]) continue;
  72. if (!f.name.contains("_ID")) this._functionIdInHead[f.uniqueName] = true;
  73. let src = f.src;
  74. // console.log("src", src);
  75. src = this.replaceId(op, src);
  76. this._headFuncSrc += src;
  77. }
  78. }
  79.  
  80. if (op.shaderUniforms)
  81. {
  82. for (let i = 0; i < op.shaderUniforms.length; i++)
  83. {
  84. const uni = op.shaderUniforms[i];
  85. if (!uni.static)
  86. {
  87. this._headUniSrc += "uniform " + CGL.Uniform.glslTypeString(uni.type) + " " + uni.name + ";".endl();
  88. this.uniforms.push(uni);
  89. }
  90. else
  91. this._headUniSrc += this.uniformAsStaticVar(uni);
  92. }
  93. }
  94. }
  95.  
  96. uniformAsStaticVar(uni)
  97. {
  98. const typeStr = CGL.Uniform.glslTypeString(uni.type);
  99. let str = "";
  100.  
  101. if (typeStr == "float")
  102. {
  103. let floatStr = String(uni.ports[0].get());
  104. if (!floatStr.contains("."))floatStr += ".";
  105. str = typeStr + " " + uni.name + " = " + floatStr + ";".endl();
  106. }
  107. else
  108. {
  109. str = typeStr + " " + uni.name + "=" + typeStr + "(";
  110.  
  111. for (let i = 0; i < uni.ports.length; i++)
  112. {
  113. str += uni.ports[i].get();
  114. if (i != uni.ports.length - 1)str += ",";
  115. }
  116.  
  117. str += ");".endl();
  118. }
  119. return str;
  120. }
  121.  
  122. callFunc(op, convertTo)
  123. {
  124. this.setOpShaderId(op);
  125. let callstr = " ";
  126.  
  127. const varname = "var_" + op.getTitle() + "_" + op.shaderId;
  128. if (convertTo)callstr += ShaderGraph.typeConv(convertTo) + " " + varname + " = ";
  129.  
  130. if (this._opIdsFuncCallSrc[op.shaderId])
  131. {
  132. if (varname) return varname;
  133. return;
  134. }
  135. this._opIdsFuncCallSrc[op.shaderId] = true;
  136.  
  137. callstr += this.replaceId(op, op.shaderFunc || "") + "(";
  138.  
  139. this.addOpShaderFuncCode(op);
  140.  
  141. const numObjectPorts = this.countObjectInputPorts(op);
  142. let count = 0;
  143. for (let i = 0; i < op.portsIn.length; i++)
  144. {
  145. let paramStr = "";
  146. const p = op.portsIn[i];
  147. if (p.uiAttribs.objType == "sg_void") continue;
  148. if (p.type != CABLES.OP_PORT_TYPE_OBJECT) continue;
  149.  
  150. // parameters...
  151. if (p.isLinked())
  152. {
  153. for (let j = 0; j < p.links.length; j++)
  154. {
  155. const otherPort = p.links[j].getOtherPort(p);
  156. paramStr = this._getPortParamStr(otherPort, p.uiAttribs.objType);
  157.  
  158. // console.log("objtype", p.uiAttribs.objType);
  159. this.addOpShaderFuncCode(otherPort.op);
  160. }
  161. }
  162. else
  163. {
  164. this.addOpShaderFuncCode(p.op);
  165. // if (p.uiAttribs.objType == "sg_sampler2D")
  166. // {
  167. // // callstr = "vec4(1.0)";
  168. // // break;
  169. // // paramStr = "null";
  170. // // break;
  171. // }
  172. // else
  173. // {
  174. paramStr = ShaderGraph.getDefaultParameter(p.uiAttribs.objType);
  175. // }
  176. }
  177.  
  178. if (p.op.shaderCodeOperator)
  179. {
  180. callstr += paramStr;
  181. if (count < numObjectPorts - 1) callstr += " " + p.op.shaderCodeOperator + " ";
  182. }
  183. else
  184. if (paramStr)
  185. {
  186. callstr += paramStr;
  187. if (count < numObjectPorts - 1) callstr += ", ";
  188. }
  189. count++;
  190. }
  191.  
  192. callstr += ");";
  193.  
  194. this._callFuncStack.push(callstr);
  195.  
  196. return varname;
  197. }
  198.  
  199. countObjectInputPorts(op)
  200. {
  201. let count = 0;
  202. for (let i = 0; i < op.portsIn.length; i++)
  203. if (op.portsIn[i].type == CABLES.OP_PORT_TYPE_OBJECT)
  204. count++;
  205. return count;
  206. }
  207.  
  208.  
  209. _getPortParamStr(p, convertTo)
  210. {
  211. let paramStr = "";
  212.  
  213. if (p.op.shaderVar)
  214. {
  215. paramStr = p.op.shaderVar;
  216. }
  217. else
  218. if (p.direction == CABLES.PORT_DIR_OUT)
  219. {
  220. paramStr += this.callFunc(p.op, p.uiAttribs.objType);
  221. }
  222.  
  223. if (convertTo && convertTo != p.uiAttribs.objType)
  224. {
  225. paramStr = ShaderGraph.convertTypes(convertTo, p.uiAttribs.objType, paramStr);
  226. }
  227.  
  228. return paramStr;
  229. }
  230.  
  231. compile()
  232. {
  233. const port = this._port;
  234. const l = port.links;
  235.  
  236. this.uniforms = [];
  237. this._callFuncStack = [];
  238. this._functionIdInHead = {};
  239. this._opIdsFuncCallSrc = {};
  240. this._opIdsHeadFuncSrc = {};
  241. this._headFuncSrc = "";
  242. this._headUniSrc = "";
  243. let callSrc = "";
  244.  
  245. for (let i = 0; i < l.length; i++)
  246. {
  247. const lnk = l[i];
  248. callSrc += this.callFunc(lnk.getOtherPort(port).op) + ";".endl();
  249. }
  250.  
  251. callSrc = this._callFuncStack.join("\n");
  252.  
  253. let src = "".endl() + "{{MODULES_HEAD}}".endl().endl();
  254.  
  255. // console.log("COMPILE", this._type);
  256. // todo use shader attrib system...
  257.  
  258. if (this._type == "frag") src += "IN vec2 texCoord;".endl().endl();
  259. if (this._type == "vert") src += "IN vec3 vPosition;".endl() +
  260. "IN vec2 attrTexCoord;".endl() +
  261. "OUT vec2 texCoord;".endl().endl();
  262.  
  263. if (this._type == "vert")src += "".endl() +
  264. "UNI mat4 projMatrix;".endl().endl() +
  265. "UNI mat4 viewMatrix;".endl().endl() +
  266. "UNI mat4 modelMatrix;".endl().endl();
  267.  
  268. src +=
  269. this._headUniSrc.endl().endl() +
  270. this._headFuncSrc.endl().endl() +
  271. "void main()".endl() +
  272. "{".endl();
  273.  
  274. if (this._type == "frag")src += " {{MODULE_BEGIN_FRAG}}".endl();
  275. if (this._type == "vert")src += " {{MODULE_BEGIN_VERTEX}}".endl();
  276.  
  277. src += callSrc.endl() +
  278. "}".endl();
  279.  
  280. this.finalSrc = src;
  281.  
  282. this.emitEvent("compiled");
  283. }
  284. };
  285.  
  286. export { ShaderGraphProgram };