Home Reference Source

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

  1. import { Logger } from "cables-shared-client";
  2. import { Texture } from "./cgl_texture.js";
  3. import { MESHES } from "./cgl_simplerect.js";
  4.  
  5. const TextureEffect = function (cgl, options)
  6. {
  7. this._cgl = cgl;
  8. this._log = new Logger("cgl_TextureEffect");
  9.  
  10. if (!cgl.TextureEffectMesh) this.createMesh();
  11.  
  12. this._textureSource = null;
  13. this._options = options;
  14. this.name = options.name || "unknown";
  15.  
  16. // TODO: do we still need the options ?
  17. // var opts=options ||
  18. // {
  19. // isFloatingPointTexture:false,
  20. // filter:CGL.Texture.FILTER_LINEAR
  21. // };
  22. // if(options && options.fp)opts.isFloatingPointTexture=true;
  23.  
  24. this.imgCompVer = 0;
  25. this.aspectRatio = 1;
  26. this._textureTarget = null; // new CGL.Texture(this._cgl,opts);
  27. this._frameBuf = this._cgl.gl.createFramebuffer();
  28. this._frameBuf2 = this._cgl.gl.createFramebuffer();
  29. this._renderbuffer = this._cgl.gl.createRenderbuffer();
  30. this._renderbuffer2 = this._cgl.gl.createRenderbuffer();
  31. this.switched = false;
  32. this.depth = false;
  33. };
  34.  
  35. TextureEffect.prototype.dispose = function ()
  36. {
  37. if (this._renderbuffer) this._cgl.gl.deleteRenderbuffer(this._renderbuffer);
  38. if (this._frameBuf) this._cgl.gl.deleteFramebuffer(this._frameBuf);
  39. if (this._renderbuffer2) this._cgl.gl.deleteRenderbuffer(this._renderbuffer2);
  40. if (this._frameBuf2) this._cgl.gl.deleteFramebuffer(this._frameBuf2);
  41. };
  42.  
  43. TextureEffect.prototype.getWidth = function ()
  44. {
  45. return this._textureSource.width;
  46. };
  47.  
  48. TextureEffect.prototype.getHeight = function ()
  49. {
  50. return this._textureSource.height;
  51. };
  52.  
  53. TextureEffect.prototype.setSourceTexture = function (tex)
  54. {
  55. if (tex === null)
  56. {
  57. this._textureSource = new Texture(this._cgl);
  58. this._textureSource.setSize(16, 16);
  59. }
  60. else
  61. {
  62. this._textureSource = tex;
  63. }
  64.  
  65. if (!this._textureSource.compareSettings(this._textureTarget))
  66. {
  67. if (this._textureTarget) this._textureTarget.delete();
  68.  
  69. this._textureTarget = this._textureSource.clone();
  70.  
  71. this._cgl.profileData.profileEffectBuffercreate++;
  72.  
  73. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuf);
  74.  
  75. this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, this._renderbuffer);
  76.  
  77. // if(tex.textureType==CGL.Texture.TYPE_FLOAT) this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER,this._cgl.gl.RGBA32F, this._textureSource.width,this._textureSource.height);
  78. // else this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER,this._cgl.gl.RGBA8, this._textureSource.width,this._textureSource.height);
  79.  
  80. if (this.depth) this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER, this._cgl.gl.DEPTH_COMPONENT16, this._textureSource.width, this._textureSource.height);
  81. this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.TEXTURE_2D, this._textureTarget.tex, 0);
  82. if (this.depth) this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.RENDERBUFFER, this._renderbuffer);
  83.  
  84. // this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.TEXTURE_2D, this._textureTarget.tex, 0);
  85.  
  86. this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, null);
  87. this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, null);
  88. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
  89.  
  90. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuf2);
  91.  
  92. this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, this._renderbuffer2);
  93.  
  94. // if(tex.textureType==CGL.Texture.TYPE_FLOAT) this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER,this._cgl.gl.RGBA32F, this._textureSource.width,this._textureSource.height);
  95. // else this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER,this._cgl.gl.RGBA8, this._textureSource.width,this._textureSource.height);
  96.  
  97. if (this.depth) this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER, this._cgl.gl.DEPTH_COMPONENT16, this._textureSource.width, this._textureSource.height);
  98. this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.TEXTURE_2D, this._textureSource.tex, 0);
  99.  
  100. if (this.depth) this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.RENDERBUFFER, this._renderbuffer2);
  101.  
  102. // this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.TEXTURE_2D, this._textureSource.tex, 0);
  103.  
  104. this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, null);
  105. this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, null);
  106. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
  107. }
  108.  
  109. this.aspectRatio = this._textureSource.width / this._textureSource.height;
  110. };
  111. TextureEffect.prototype.continueEffect = function ()
  112. {
  113. this._cgl.pushDepthTest(false);
  114. this._cgl.pushModelMatrix();
  115. this._cgl.pushPMatrix();
  116. // todo why two pushs?
  117.  
  118.  
  119.  
  120. this._cgl.pushViewPort(0, 0, this.getCurrentTargetTexture().width, this.getCurrentTargetTexture().height);
  121.  
  122.  
  123.  
  124. mat4.perspective(this._cgl.pMatrix, 45, this.getCurrentTargetTexture().width / this.getCurrentTargetTexture().height, 0.1, 1100.0); // todo: why?
  125.  
  126. this._cgl.pushPMatrix();
  127. mat4.identity(this._cgl.pMatrix);
  128.  
  129. this._cgl.pushViewMatrix();
  130. mat4.identity(this._cgl.vMatrix);
  131.  
  132. this._cgl.pushModelMatrix();
  133. mat4.identity(this._cgl.mMatrix);
  134. };
  135.  
  136.  
  137. TextureEffect.prototype.startEffect = function (bgTex)
  138. {
  139. if (!this._textureTarget)
  140. {
  141. this._log.warn("effect has no target");
  142. return;
  143. }
  144.  
  145. this.switched = false;
  146.  
  147. this.continueEffect();
  148.  
  149. if (bgTex)
  150. {
  151. this._bgTex = bgTex;
  152. }
  153. this._countEffects = 0;
  154. };
  155.  
  156. TextureEffect.prototype.endEffect = function ()
  157. {
  158. this._cgl.popDepthTest();
  159. this._cgl.popModelMatrix();
  160.  
  161. this._cgl.popPMatrix();
  162. this._cgl.popModelMatrix();
  163. this._cgl.popViewMatrix();
  164.  
  165. this._cgl.popPMatrix();
  166. this._cgl.popViewPort();
  167. };
  168.  
  169. TextureEffect.prototype.bind = function ()
  170. {
  171. if (this._textureSource === null)
  172. {
  173. this._log.warn("no base texture set!");
  174. return;
  175. }
  176.  
  177. if (!this.switched)
  178. {
  179. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuf);
  180. this._cgl.pushGlFrameBuffer(this._frameBuf);
  181. }
  182. else
  183. {
  184. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuf2);
  185. this._cgl.pushGlFrameBuffer(this._frameBuf2);
  186. }
  187. };
  188.  
  189. TextureEffect.prototype.finish = function ()
  190. {
  191. if (this._textureSource === null)
  192. {
  193. this._log.warn("no base texture set!");
  194. return;
  195. }
  196.  
  197. this._cgl.TextureEffectMesh.render(this._cgl.getShader());
  198.  
  199. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.popGlFrameBuffer());
  200.  
  201. this._cgl.profileData.profileTextureEffect++;
  202.  
  203. if (this._textureTarget.filter == Texture.FILTER_MIPMAP)
  204. {
  205. if (!this.switched)
  206. {
  207. this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, this._textureTarget.tex);
  208. this._textureTarget.updateMipMap();
  209. }
  210. else
  211. {
  212. this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, this._textureSource.tex);
  213. this._textureSource.updateMipMap();
  214. }
  215.  
  216. this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, null);
  217. }
  218.  
  219. this.switched = !this.switched;
  220. this._countEffects++;
  221. };
  222.  
  223. TextureEffect.prototype.getCurrentTargetTexture = function ()
  224. {
  225. if (this.switched) return this._textureSource;
  226. return this._textureTarget;
  227. };
  228.  
  229. TextureEffect.prototype.getCurrentSourceTexture = function ()
  230. {
  231. if (this._countEffects == 0 && this._bgTex) return this._bgTex;
  232.  
  233. if (this.switched) return this._textureTarget;
  234. return this._textureSource;
  235. };
  236.  
  237. TextureEffect.prototype.delete = function ()
  238. {
  239. if (this._textureTarget) this._textureTarget.delete();
  240. if (this._textureSource) this._textureSource.delete();
  241. this._cgl.gl.deleteRenderbuffer(this._renderbuffer);
  242. this._cgl.gl.deleteFramebuffer(this._frameBuf);
  243. };
  244.  
  245. TextureEffect.prototype.createMesh = function ()
  246. {
  247. this._cgl.TextureEffectMesh = MESHES.getSimpleRect(this._cgl, "texEffectRect");
  248. };
  249.  
  250. // ---------------------------------------------------------------------------------
  251.  
  252. TextureEffect.checkOpNotInTextureEffect = function (op)
  253. {
  254. if (!op.patch.cgl) return true;
  255. if (op.uiAttribs.error && !op.patch.cgl.currentTextureEffect)
  256. {
  257. op.setUiError("textureeffect", null);
  258. return true;
  259. }
  260. if (!op.patch.cgl.currentTextureEffect) return true;
  261.  
  262. if (op.patch.cgl.currentTextureEffect && !op.uiAttribs.error)
  263. {
  264. op.setUiError("textureeffect", "This op can not be a child of a ImageCompose/texture effect! imagecompose should only have textureeffect childs.", 0);
  265. return false;
  266. }
  267.  
  268. if (op.patch.cgl.currentTextureEffect) return false;
  269. return true;
  270. };
  271.  
  272. TextureEffect.checkOpInEffect = function (op, minver)
  273. {
  274. minver = minver || 0;
  275.  
  276. if (op.patch.cgl.currentTextureEffect)
  277. {
  278. if (op.uiAttribs.uierrors && op.patch.cgl.currentTextureEffect.imgCompVer >= minver)
  279. {
  280. op.setUiError("texeffect", null);
  281. return true;
  282. }
  283.  
  284. if (minver && op.patch.cgl.currentTextureEffect.imgCompVer < minver)
  285. {
  286. op.setUiError("texeffect", "This op must be a child of an ImageCompose op with version >=" + minver + " <span class=\"button-small\" onclick=\"gui.patchView.downGradeOp('" + op.id + "','" + op.name + "')\">Downgrade</span> to previous version", 1);
  287. }
  288. }
  289.  
  290. if (op.patch.cgl.currentTextureEffect) return true;
  291.  
  292. if (!op.patch.cgl.currentTextureEffect && (!op.uiAttribs.uierrors || op.uiAttribs.uierrors.length == 0))
  293. {
  294. op.setUiError("texeffect", "This op must be a child of an ImageCompose op! More infos <a href=\"https://cables.gl/docs/image_composition/image_composition.html\" target=\"_blank\">here</a>. ", 1);
  295. return false;
  296. }
  297.  
  298. if (!op.patch.cgl.currentTextureEffect) return false;
  299. return true;
  300. };
  301.  
  302. TextureEffect.getBlendCode = function (ver)
  303. {
  304. let src = "".endl()
  305. + "vec3 _blend(vec3 base,vec3 blend)".endl()
  306. + "{".endl()
  307. + " vec3 colNew=blend;".endl()
  308. + " #ifdef BM_MULTIPLY".endl()
  309. + " colNew=base*blend;".endl()
  310. + " #endif".endl()
  311. + " #ifdef BM_MULTIPLY_INV".endl()
  312. + " colNew=base* vec3(1.0)-blend;".endl()
  313. + " #endif".endl()
  314. + " #ifdef BM_AVERAGE".endl()
  315. + " colNew=((base + blend) / 2.0);".endl()
  316. + " #endif".endl()
  317. + " #ifdef BM_ADD".endl()
  318. + " colNew=min(base + blend, vec3(1.0));".endl()
  319. + " #endif".endl()
  320. + " #ifdef BM_SUBTRACT_ONE".endl()
  321. + " colNew=max(base + blend - vec3(1.0), vec3(0.0));".endl()
  322. + " #endif".endl()
  323.  
  324. + " #ifdef BM_SUBTRACT".endl()
  325. + " colNew=base - blend;".endl()
  326. + " #endif".endl()
  327.  
  328. + " #ifdef BM_DIFFERENCE".endl()
  329. + " colNew=abs(base - blend);".endl()
  330. + " #endif".endl()
  331. + " #ifdef BM_NEGATION".endl()
  332. + " colNew=(vec3(1.0) - abs(vec3(1.0) - base - blend));".endl()
  333. + " #endif".endl()
  334. + " #ifdef BM_EXCLUSION".endl()
  335. + " colNew=(base + blend - 2.0 * base * blend);".endl()
  336. + " #endif".endl()
  337. + " #ifdef BM_LIGHTEN".endl()
  338. + " colNew=max(blend, base);".endl()
  339. + " #endif".endl()
  340. + " #ifdef BM_DARKEN".endl()
  341. + " colNew=min(blend, base);".endl()
  342. + " #endif".endl()
  343. + " #ifdef BM_OVERLAY".endl()
  344. + " #define BlendOverlayf(base, blend) (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))"
  345. // .endl()+' #define BlendOverlay(base, blend) Blend(base, blend, BlendOverlayf)'
  346. // .endl()+' colNew=Blend(base, blend, BlendOverlayf);'
  347. .endl()
  348. + " colNew=vec3(BlendOverlayf(base.r, blend.r),BlendOverlayf(base.g, blend.g),BlendOverlayf(base.b, blend.b));".endl()
  349. + " #endif".endl()
  350. + " #ifdef BM_SCREEN".endl()
  351. + " #define BlendScreenf(base, blend) (1.0 - ((1.0 - base) * (1.0 - blend)))"
  352. // .endl()+' #define BlendScreen(base, blend) Blend(base, blend, BlendScreenf)'
  353. // .endl()+' colNew=Blend(base, blend, BlendScreenf);'
  354. .endl()
  355. + " colNew=vec3(BlendScreenf(base.r, blend.r),BlendScreenf(base.g, blend.g),BlendScreenf(base.b, blend.b));".endl()
  356. + " #endif".endl()
  357. + " #ifdef BM_SOFTLIGHT".endl()
  358. + " #define BlendSoftLightf(base, blend) ((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend)))"
  359. // .endl()+' #define BlendSoftLight(base, blend) Blend(base, blend, BlendSoftLightf)'
  360. // .endl()+' colNew=Blend(base, blend, BlendSoftLightf);'
  361. .endl()
  362. + " colNew=vec3(BlendSoftLightf(base.r, blend.r),BlendSoftLightf(base.g, blend.g),BlendSoftLightf(base.b, blend.b));".endl()
  363. + " #endif".endl()
  364. + " #ifdef BM_HARDLIGHT".endl()
  365. + " #define BlendOverlayf(base, blend) (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))"
  366. // .endl()+' #define BlendOverlay(base, blend) Blend(base, blend, BlendOverlayf)'
  367. // .endl()+' colNew=Blend(blend, base, BlendOverlayf);'
  368. .endl()
  369. + " colNew=vec3(BlendOverlayf(base.r, blend.r),BlendOverlayf(base.g, blend.g),BlendOverlayf(base.b, blend.b));".endl()
  370. + " #endif".endl()
  371. + " #ifdef BM_COLORDODGE".endl()
  372. + " #define BlendColorDodgef(base, blend) ((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0))"
  373. // .endl()+' colNew=Blend(base, blend, BlendColorDodgef);'
  374. .endl()
  375. + " colNew=vec3(BlendColorDodgef(base.r, blend.r),BlendColorDodgef(base.g, blend.g),BlendColorDodgef(base.b, blend.b));".endl()
  376. + " #endif".endl()
  377. + " #ifdef BM_COLORBURN".endl()
  378. + " #define BlendColorBurnf(base, blend) ((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0))"
  379. // .endl()+' colNew=Blend(base, blend, BlendColorBurnf);'
  380. .endl()
  381. + " colNew=vec3(BlendColorBurnf(base.r, blend.r),BlendColorBurnf(base.g, blend.g),BlendColorBurnf(base.b, blend.b));".endl()
  382. + " #endif".endl()
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393. + " return colNew;".endl()
  394. + "}".endl();
  395.  
  396. if (!ver)
  397. src += "vec4 cgl_blend(vec4 oldColor,vec4 newColor,float amount)".endl()
  398. + "{".endl()
  399. + "vec4 col=vec4( _blend(oldColor.rgb,newColor.rgb) ,1.0);".endl()
  400. + "col=vec4( mix( col.rgb, oldColor.rgb ,1.0-oldColor.a*amount),1.0);".endl()
  401. + "return col;".endl()
  402. + "}".endl();
  403.  
  404. if (ver >= 3)
  405. src += "vec4 cgl_blendPixel(vec4 base,vec4 col,float amount)".endl() +
  406. "{".endl() +
  407.  
  408. "#ifdef BM_MATH_ADD".endl() +
  409. " return vec4(base.rgb+col.rgb*amount,1.0);".endl() +
  410. "#endif".endl() +
  411.  
  412. "#ifdef BM_MATH_SUB".endl() +
  413. " return vec4(base.rgb-col.rgb*amount,1.0);".endl() +
  414. "#endif".endl() +
  415.  
  416. "#ifdef BM_MATH_MUL".endl() +
  417. " return vec4(base.rgb*col.rgb*amount,1.0);".endl() +
  418. "#endif".endl() +
  419.  
  420. "#ifdef BM_MATH_DIV".endl() +
  421. " return vec4(base.rgb/col.rgb*amount,1.0);".endl() +
  422. "#endif".endl() +
  423.  
  424.  
  425. "#ifndef BM_MATH".endl() +
  426. "vec3 colNew=_blend(base.rgb,col.rgb);".endl() +
  427.  
  428. "float newA=clamp(base.a+(col.a*amount),0.,1.);".endl() +
  429.  
  430. "#ifdef BM_ALPHAMASKED".endl() +
  431. "newA=base.a;".endl() +
  432. "#endif".endl() +
  433.  
  434. "return vec4(".endl() +
  435. "mix(colNew,base.rgb,1.0-(amount*col.a)),".endl() +
  436. "newA);".endl() +
  437.  
  438. "#endif".endl() +
  439. "}".endl();
  440.  
  441. return src;
  442. };
  443.  
  444. TextureEffect.onChangeBlendSelect = function (shader, blendName, maskAlpha = false)
  445. {
  446. blendName = String(blendName);
  447. shader.toggleDefine("BM_NORMAL", blendName == "normal");
  448. shader.toggleDefine("BM_MULTIPLY", blendName == "multiply");
  449. shader.toggleDefine("BM_MULTIPLY_INV", blendName == "multiply invert");
  450. shader.toggleDefine("BM_AVERAGE", blendName == "average");
  451. shader.toggleDefine("BM_ADD", blendName == "add");
  452. shader.toggleDefine("BM_SUBTRACT_ONE", blendName == "subtract one");
  453. shader.toggleDefine("BM_SUBTRACT", blendName == "subtract");
  454. shader.toggleDefine("BM_DIFFERENCE", blendName == "difference");
  455. shader.toggleDefine("BM_NEGATION", blendName == "negation");
  456. shader.toggleDefine("BM_EXCLUSION", blendName == "exclusion");
  457. shader.toggleDefine("BM_LIGHTEN", blendName == "lighten");
  458. shader.toggleDefine("BM_DARKEN", blendName == "darken");
  459. shader.toggleDefine("BM_OVERLAY", blendName == "overlay");
  460. shader.toggleDefine("BM_SCREEN", blendName == "screen");
  461. shader.toggleDefine("BM_SOFTLIGHT", blendName == "softlight");
  462. shader.toggleDefine("BM_HARDLIGHT", blendName == "hardlight");
  463. shader.toggleDefine("BM_COLORDODGE", blendName == "color dodge");
  464. shader.toggleDefine("BM_COLORBURN", blendName == "color burn");
  465.  
  466. shader.toggleDefine("BM_MATH_ADD", blendName == "Math Add");
  467. shader.toggleDefine("BM_MATH_SUB", blendName == "Math Subtract");
  468. shader.toggleDefine("BM_MATH_MUL", blendName == "Math Multiply");
  469. shader.toggleDefine("BM_MATH_DIV", blendName == "Math Divide");
  470.  
  471. shader.toggleDefine("BM_MATH", blendName.indexOf("Math ") == 0);
  472.  
  473.  
  474. shader.toggleDefine("BM_ALPHAMASKED", maskAlpha);
  475. };
  476.  
  477. TextureEffect.AddBlendSelect = function (op, name, defaultMode)
  478. {
  479. const p = op.inValueSelect(name || "Blend Mode", [
  480. "normal", "lighten", "darken", "multiply", "multiply invert", "average", "add", "subtract", "difference", "negation", "exclusion", "overlay", "screen", "color dodge", "color burn", "softlight", "hardlight", "subtract one",
  481. "Math Add",
  482. "Math Subtract",
  483. "Math Multiply",
  484. "Math Divide",
  485.  
  486. ], defaultMode || "normal");
  487. return p;
  488. };
  489.  
  490. TextureEffect.AddBlendAlphaMask = function (op, name, defaultMode)
  491. {
  492. const p = op.inSwitch(name || "Alpha Mask", ["Off", "On"], defaultMode || "Off");
  493. return p;
  494. };
  495.  
  496. TextureEffect.setupBlending = function (op, shader, blendPort, amountPort, alphaMaskPort)
  497. {
  498. const onChange = () =>
  499. {
  500. let maskAlpha = false;
  501. if (alphaMaskPort) maskAlpha = alphaMaskPort.get() == "On";
  502. TextureEffect.onChangeBlendSelect(shader, blendPort.get(), maskAlpha);
  503.  
  504. let str = blendPort.get();
  505. if (str == "normal") str = null;
  506. else if (str == "multiply") str = "mul";
  507. else if (str == "multiply invert") str = "mulinv";
  508. else if (str == "lighten") str = "light";
  509. else if (str == "darken") str = "darken";
  510. else if (str == "average") str = "avg";
  511. else if (str == "subtract one") str = "sub one";
  512. else if (str == "subtract") str = "sub";
  513. else if (str == "difference") str = "diff";
  514. else if (str == "negation") str = "neg";
  515. else if (str == "exclusion") str = "exc";
  516. else if (str == "overlay") str = "ovl";
  517. else if (str == "color dodge") str = "dodge";
  518. else if (str == "color burn") str = "burn";
  519. else if (str == "softlight") str = "soft";
  520. else if (str == "hardlight") str = "hard";
  521. else if (str == "Math Add") str = "+";
  522. else if (str == "Math Subtract") str = "-";
  523. else if (str == "Math Multiply") str = "*";
  524. else if (str == "Math Divide") str = "/";
  525.  
  526. op.setUiAttrib({ "extendTitle": str });
  527. };
  528. op.setPortGroup("Blending", [blendPort, amountPort, alphaMaskPort]);
  529.  
  530. let maskAlpha = false;
  531.  
  532. blendPort.onChange = onChange;
  533. if (alphaMaskPort)
  534. {
  535. alphaMaskPort.onChange = onChange;
  536. maskAlpha = alphaMaskPort.get() == "On";
  537. }
  538.  
  539. TextureEffect.onChangeBlendSelect(shader, blendPort.get(), maskAlpha);
  540. };
  541.  
  542. export { TextureEffect };