Home Reference Source

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

  1. // * see framebuffer1
  2.  
  3.  
  4. import { Logger } from "cables-shared-client";
  5. import { Texture } from "./cgl_texture.js";
  6.  
  7.  
  8. const Framebuffer2 = function (cgl, w, h, options)
  9. {
  10. this._log = new Logger("cgl_framebuffer2");
  11. if (cgl.glVersion == 1) return this._log.error("framebuffer2 used on webgl1");
  12. this.Framebuffer2DrawTargetsDefault = null;
  13. this.Framebuffer2BlittingFramebuffer = null;
  14. this.Framebuffer2FinalFramebuffer = null;
  15. this._cgl = cgl;
  16.  
  17. this._cgl.printError("before framebuffer2 constructor");
  18.  
  19. this._width = 0;
  20. this._height = 0;
  21. this.valid = true;
  22.  
  23. this._depthRenderbuffer = null;
  24. this._frameBuffer = null;
  25. this._textureFrameBuffer = null;
  26. this._colorRenderbuffers = [];
  27. this._drawTargetArray = [];
  28. this._disposed = false;
  29.  
  30. if (!this.Framebuffer2BlittingFramebuffer) this.Framebuffer2BlittingFramebuffer = cgl.gl.createFramebuffer();
  31. if (!this.Framebuffer2FinalFramebuffer) this.Framebuffer2FinalFramebuffer = cgl.gl.createFramebuffer();
  32.  
  33. if (!this.Framebuffer2DrawTargetsDefault) this.Framebuffer2DrawTargetsDefault = [cgl.gl.COLOR_ATTACHMENT0];
  34.  
  35. this._options = options || {
  36. "isFloatingPointTexture": false,
  37. };
  38.  
  39. // this._cgl.printError("fb2 before");
  40.  
  41. this.name = this._options.name || "unknown";
  42.  
  43. this._cgl.profileData.addHeavyEvent("framebuffer create", this.name);
  44.  
  45. if (!this._options.hasOwnProperty("numRenderBuffers")) this._options.numRenderBuffers = 1;
  46. if (!this._options.hasOwnProperty("depth")) this._options.depth = true;
  47. if (!this._options.hasOwnProperty("clear")) this._options.clear = true;
  48. if (!this._options.hasOwnProperty("multisampling"))
  49. {
  50. this._options.multisampling = false;
  51. this._options.multisamplingSamples = 0;
  52. }
  53.  
  54. if (this._options.multisamplingSamples)
  55. {
  56. if (this._cgl.glSlowRenderer) this._options.multisamplingSamples = 0;
  57. if (!this._cgl.gl.MAX_SAMPLES) this._options.multisamplingSamples = 0;
  58. else this._options.multisamplingSamples = Math.min(this._cgl.maxSamples, this._options.multisamplingSamples);
  59. }
  60.  
  61. if (!this._options.hasOwnProperty("filter")) this._options.filter = Texture.FILTER_LINEAR;
  62. if (!this._options.hasOwnProperty("wrap")) this._options.wrap = Texture.WRAP_REPEAT;
  63.  
  64. this._numRenderBuffers = this._options.numRenderBuffers;
  65. this._colorTextures = [];
  66.  
  67. this.clearColors = [];
  68. for (let i = 0; i < this._numRenderBuffers; i++) this.clearColors.push([0, 0, 0, 1]);
  69.  
  70.  
  71. if (!options.pixelFormat)
  72. {
  73. if (options.isFloatingPointTexture) this._options.pixelFormat = Texture.PFORMATSTR_RGBA32F;
  74. else this._options.pixelFormat = Texture.PFORMATSTR_RGBA8UB;
  75. }
  76.  
  77. for (let i = 0; i < this._numRenderBuffers; i++)
  78. {
  79. this._colorTextures[i] = new Texture(cgl, {
  80. "name": "fb2 " + this.name + " " + i,
  81. "isFloatingPointTexture": this._options.isFloatingPointTexture,
  82. "anisotropic": this._options.anisotropic || 0,
  83. "pixelFormat": this._options.pixelFormat,
  84. "filter": this._options.filter,
  85. "wrap": this._options.wrap,
  86. });
  87. }
  88.  
  89.  
  90.  
  91. let fil = Texture.FILTER_NEAREST;
  92. if (this._options.shadowMap) fil = Texture.FILTER_LINEAR;
  93.  
  94. const defaultTexSize = 512;
  95.  
  96. if (this._options.depth)
  97. {
  98. this._textureDepth = new Texture(cgl,
  99. {
  100. "name": "fb2 depth " + this.name,
  101. "isDepthTexture": true,
  102. "filter": fil,
  103. "shadowMap": this._options.shadowMap || false,
  104. "width": w || defaultTexSize,
  105. "height": h || defaultTexSize,
  106. });
  107. }
  108.  
  109. if (cgl.aborted) return;
  110.  
  111. this.setSize(w || defaultTexSize, h || defaultTexSize);
  112.  
  113. this._cgl.printError("framebuffer2 constructor");
  114. };
  115.  
  116. Framebuffer2.prototype.getWidth = function ()
  117. {
  118. return this._width;
  119. };
  120. Framebuffer2.prototype.getHeight = function ()
  121. {
  122. return this._height;
  123. };
  124.  
  125. Framebuffer2.prototype.getGlFrameBuffer = function ()
  126. {
  127. return this._frameBuffer;
  128. };
  129.  
  130. Framebuffer2.prototype.getDepthRenderBuffer = function ()
  131. {
  132. return this._depthRenderbuffer;
  133. };
  134.  
  135. Framebuffer2.prototype.getTextureColor = function ()
  136. {
  137. return this._colorTextures[0];
  138. };
  139.  
  140. Framebuffer2.prototype.getTextureColorNum = function (i)
  141. {
  142. return this._colorTextures[i];
  143. };
  144.  
  145. Framebuffer2.prototype.getTextureDepth = function ()
  146. {
  147. return this._textureDepth;
  148. };
  149.  
  150. Framebuffer2.prototype.setFilter = function (f)
  151. {
  152. for (let i = 0; i < this._numRenderBuffers; i++)
  153. {
  154. this._colorTextures[i].filter = f;
  155. this._colorTextures[i].setSize(this._width, this._height);
  156. }
  157. };
  158.  
  159. Framebuffer2.prototype.delete = Framebuffer2.prototype.dispose = function ()
  160. {
  161. this._disposed = true;
  162. let i = 0;
  163. for (i = 0; i < this._numRenderBuffers; i++) this._colorTextures[i].delete();
  164. // this._texture.delete();
  165. if (this._textureDepth) this._textureDepth.delete();
  166. for (i = 0; i < this._numRenderBuffers; i++) this._cgl.gl.deleteRenderbuffer(this._colorRenderbuffers[i]);
  167. this._cgl.gl.deleteRenderbuffer(this._depthRenderbuffer);
  168. this._cgl.gl.deleteFramebuffer(this._frameBuffer);
  169. this._cgl.gl.deleteFramebuffer(this._textureFrameBuffer);
  170. };
  171.  
  172. Framebuffer2.prototype.setSize = function (w, h)
  173. {
  174. if (this._disposed) return this._log.warn("disposed framebuffer setsize...");
  175. this._cgl.profileData.addHeavyEvent("framebuffer resize", this.name);
  176.  
  177. let i = 0;
  178.  
  179. this._width = this._cgl.checkTextureSize(w);
  180. this._height = this._cgl.checkTextureSize(h);
  181.  
  182. this._cgl.profileData.profileFrameBuffercreate++;
  183.  
  184. if (this._frameBuffer)
  185. {
  186. for (i = 0; i < this._numRenderBuffers; i++) this._cgl.gl.deleteRenderbuffer(this._colorRenderbuffers[i]);
  187. // this._cgl.gl.deleteRenderbuffer(this._colorRenderbuffer);
  188. this._cgl.gl.deleteRenderbuffer(this._depthRenderbuffer);
  189. this._cgl.gl.deleteFramebuffer(this._frameBuffer);
  190. this._cgl.gl.deleteFramebuffer(this._textureFrameBuffer);
  191. }
  192.  
  193. this._frameBuffer = this._cgl.gl.createFramebuffer();
  194. this._textureFrameBuffer = this._cgl.gl.createFramebuffer();
  195.  
  196. const depth = this._options.depth;
  197.  
  198. for (i = 0; i < this._numRenderBuffers; i++)
  199. {
  200. this._colorTextures[i].setSize(this._width, this._height);
  201. }
  202.  
  203. for (i = 0; i < this._numRenderBuffers; i++)
  204. {
  205. const renderBuffer = this._cgl.gl.createRenderbuffer();
  206.  
  207. // color renderbuffer
  208.  
  209. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuffer);
  210. this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, renderBuffer);
  211.  
  212. const info = Texture.setUpGlPixelFormat(this._cgl, this._options.pixelFormat);
  213. let internFormat = info.glInternalFormat;
  214.  
  215. // if (this._options.isFloatingPointTexture)
  216. // {
  217. if (CGL.Texture.isPixelFormatHalfFloat(info.pixelFormat))
  218. {
  219. if (!this._cgl.enableExtension("OES_texture_float_linear"))
  220. {
  221. this._options.filter = Texture.FILTER_NEAREST;
  222. this.setFilter(this._options.filter);
  223. }
  224. }
  225. else if (CGL.Texture.isPixelFormatFloat(info.pixelFormat))
  226. {
  227. if (!this._cgl.enableExtension("OES_texture_float_linear"))
  228. {
  229. this._log.warn("no linear pixelformat,using nearest");
  230. this._options.filter = Texture.FILTER_NEAREST;
  231. this.setFilter(this._options.filter);
  232. }
  233. }
  234. // else if (info.pixelFormat == Texture.PFORMATSTR_RGBA32F || info.pixelFormat == Texture.PFORMATSTR_R11FG11FB10F
  235. // else if (info.pixelFormat == Texture.PFORMATSTR_RGBA32F || info.pixelFormat == Texture.PFORMATSTR_R11FG11FB10F
  236. // else if (info.pixelFormat == Texture.PFORMATSTR_RG16F)
  237. // {
  238. // const extcb = this._cgl.enableExtension("EXT_color_buffer_float");
  239.  
  240. // if (!this._cgl.enableExtension("OES_texture_float_linear"))
  241. // {
  242. // console.log("no linear pixelformat,switching to nearest");
  243. // this._options.filter = Texture.FILTER_NEAREST;
  244. // this.setFilter(this._options.filter);
  245. // }
  246. // }
  247. // }
  248.  
  249. if (this._options.multisampling && this._options.multisamplingSamples)
  250. {
  251. this._cgl.gl.renderbufferStorageMultisample(this._cgl.gl.RENDERBUFFER, this._options.multisamplingSamples, internFormat, this._width, this._height);
  252. }
  253. else
  254. {
  255. this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER, internFormat, this._width, this._height);
  256. }
  257.  
  258.  
  259.  
  260. this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0 + i, this._cgl.gl.RENDERBUFFER, renderBuffer);
  261. this._colorRenderbuffers[i] = renderBuffer;
  262. }
  263.  
  264. // this._cgl.gl.bindFramebuffer(this._cgl.gl.DRAW_FRAMEBUFFER, this._textureFrameBuffer);
  265. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._textureFrameBuffer);
  266.  
  267. for (i = 0; i < this._numRenderBuffers; i++)
  268. {
  269. this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0 + i, this._cgl.gl.TEXTURE_2D, this._colorTextures[i].tex, 0);
  270. }
  271.  
  272. if (this._options.depth)
  273. {
  274. this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.TEXTURE_2D, this._textureDepth.tex, 0);
  275. }
  276.  
  277. // depth renderbuffer
  278.  
  279. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuffer);
  280.  
  281.  
  282. let depthType = this._cgl.gl.DEPTH_COMPONENT32F;
  283.  
  284. if (this._cgl.glSlowRenderer) depthType = this._cgl.gl.DEPTH_COMPONENT16;
  285. if (depth)
  286. {
  287. this._textureDepth.setSize(this._width, this._height);
  288. this._depthRenderbuffer = this._cgl.gl.createRenderbuffer();
  289.  
  290. this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, this._depthRenderbuffer);
  291. if (this._options.isFloatingPointTexture)
  292. {
  293. if (this._options.multisampling) this._cgl.gl.renderbufferStorageMultisample(this._cgl.gl.RENDERBUFFER, this._options.multisamplingSamples, depthType, this._width, this._height);
  294. else this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER, depthType, this._width, this._height);
  295. }
  296. else if (this._options.multisampling)
  297. {
  298. this._cgl.gl.renderbufferStorageMultisample(this._cgl.gl.RENDERBUFFER, this._options.multisamplingSamples, depthType, this._width, this._height);
  299. // this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER,depthType, this._width, this._height);
  300. }
  301. else
  302. {
  303. this._cgl.gl.renderbufferStorage(this._cgl.gl.RENDERBUFFER, depthType, this._width, this._height);
  304. }
  305.  
  306. this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.RENDERBUFFER, this._depthRenderbuffer);
  307. }
  308.  
  309. // this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
  310. // this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._textureFrameBuffer);
  311.  
  312. this._drawTargetArray.length = 0;
  313. for (i = 0; i < this._numRenderBuffers; i++) this._drawTargetArray.push(this._cgl.gl.COLOR_ATTACHMENT0 + i);
  314.  
  315. // this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
  316.  
  317.  
  318. if (!this._cgl.gl.isFramebuffer(this._textureFrameBuffer)) this._log.warn("invalid framebuffer");// throw new Error("Invalid framebuffer");
  319. const status = this._cgl.gl.checkFramebufferStatus(this._cgl.gl.FRAMEBUFFER);
  320.  
  321. if (status != this._cgl.gl.FRAMEBUFFER_COMPLETE)
  322. {
  323. this._log.error("framebuffer incomplete: " + this.name, this);
  324. this._log.log("options", this._options);
  325. this._log.log("options pixelformat", this._options.pixelFormat);
  326.  
  327. switch (status)
  328. {
  329. case this._cgl.gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
  330. this._log.warn("FRAMEBUFFER_INCOMPLETE_ATTACHMENT...", this);
  331. throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
  332. case this._cgl.gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
  333. this._log.warn("FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
  334. throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
  335. case this._cgl.gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
  336. this._log.warn("FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
  337. throw new Error("Incomplete framebuffer: FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
  338. case this._cgl.gl.FRAMEBUFFER_UNSUPPORTED:
  339. this._log.warn("FRAMEBUFFER_UNSUPPORTED");
  340. throw new Error("Incomplete framebuffer: FRAMEBUFFER_UNSUPPORTED");
  341. default:
  342. this.valid = false;
  343. this._log.error("incomplete framebuffer", status, this._frameBuffer);
  344. this._cgl.printError();
  345.  
  346. this._frameBuffer = null;
  347. // debugger;
  348. throw new Error("Incomplete framebuffer: " + status);
  349.  
  350. // throw("Incomplete framebuffer: " + status);
  351. }
  352. }
  353.  
  354. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
  355. this._cgl.gl.bindRenderbuffer(this._cgl.gl.RENDERBUFFER, null);
  356.  
  357. // this._cgl.printError("fb setsize");
  358. };
  359.  
  360. Framebuffer2.prototype.renderStart = function ()
  361. {
  362. if (this._disposed) return this._log.warn("disposed framebuffer renderStart...");
  363. this._cgl.checkFrameStarted("fb2 renderstart");
  364. this._cgl.pushModelMatrix(); // needed ??
  365.  
  366. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuffer);
  367. this._cgl.pushGlFrameBuffer(this._frameBuffer);
  368. this._cgl.pushFrameBuffer(this);
  369.  
  370. this._cgl.pushPMatrix();
  371. this._cgl.pushViewPort(0, 0, this._width, this._height);
  372.  
  373. this._cgl.gl.drawBuffers(this._drawTargetArray);
  374.  
  375. if (this._options.clear)
  376. {
  377. this._cgl.gl.clearColor(0, 0, 0, 0);
  378. this._cgl.gl.clear(this._cgl.gl.COLOR_BUFFER_BIT | this._cgl.gl.DEPTH_BUFFER_BIT);
  379. }
  380. };
  381.  
  382. Framebuffer2.prototype.clear = function ()
  383. {
  384. if (this._numRenderBuffers <= 1)
  385. {
  386. this._cgl.gl.bindFramebuffer(this._cgl.gl.READ_FRAMEBUFFER, this._frameBuffer);
  387. this._cgl.gl.bindFramebuffer(this._cgl.gl.DRAW_FRAMEBUFFER, this._textureFrameBuffer);
  388. }
  389. else this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._frameBuffer);
  390.  
  391. this._cgl.gl.drawBuffers(this._drawTargetArray);
  392.  
  393. for (let i = 0; i < this._numRenderBuffers; i++)
  394. {
  395. this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0 + i, this._cgl.gl.TEXTURE_2D, this._colorTextures[i].tex, 0);
  396. this._cgl.gl.clearBufferfv(this._cgl.gl.COLOR, i, this.clearColors[i]);
  397. }
  398. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
  399. };
  400.  
  401. Framebuffer2.prototype.renderEnd = function ()
  402. {
  403. if (this._disposed) return this._log.warn("disposed framebuffer renderEnd...");
  404. this._cgl.popPMatrix();
  405.  
  406. this._cgl.profileData.profileFramebuffer++;
  407.  
  408.  
  409. if (this._numRenderBuffers <= 1)
  410. {
  411. this._cgl.gl.bindFramebuffer(this._cgl.gl.READ_FRAMEBUFFER, this._frameBuffer);
  412. this._cgl.gl.bindFramebuffer(this._cgl.gl.DRAW_FRAMEBUFFER, this._textureFrameBuffer);
  413.  
  414. this._cgl.gl.clearBufferfv(this._cgl.gl.COLOR, 0, [0.0, 0.0, 0.0, 1.0]);
  415. this._cgl.gl.blitFramebuffer(0, 0, this._width, this._height, 0, 0, this._width, this._height, this._cgl.gl.COLOR_BUFFER_BIT | this._cgl.gl.DEPTH_BUFFER_BIT, this._cgl.gl.NEAREST);
  416. }
  417. else
  418. {
  419. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this.Framebuffer2BlittingFramebuffer);
  420. this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.RENDERBUFFER, this._depthRenderbuffer);
  421.  
  422. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this.Framebuffer2FinalFramebuffer);
  423. this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.DEPTH_ATTACHMENT, this._cgl.gl.TEXTURE_2D, this._textureDepth.tex, 0);
  424.  
  425. for (let i = 0; i < this._numRenderBuffers; i++)
  426. {
  427. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this.Framebuffer2BlittingFramebuffer);
  428. this._cgl.gl.framebufferRenderbuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.RENDERBUFFER, this._colorRenderbuffers[i]);
  429.  
  430.  
  431. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this.Framebuffer2FinalFramebuffer);
  432. this._cgl.gl.framebufferTexture2D(this._cgl.gl.FRAMEBUFFER, this._cgl.gl.COLOR_ATTACHMENT0, this._cgl.gl.TEXTURE_2D, this._colorTextures[i].tex, 0);
  433.  
  434. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, null);
  435.  
  436. this._cgl.gl.bindFramebuffer(this._cgl.gl.READ_FRAMEBUFFER, this.Framebuffer2BlittingFramebuffer);
  437. this._cgl.gl.bindFramebuffer(this._cgl.gl.DRAW_FRAMEBUFFER, this.Framebuffer2FinalFramebuffer);
  438.  
  439. // this._cgl.gl.clearBufferfv(this._cgl.gl.COLOR, i, [0.0, 0.0, 0.0, 1.0]);
  440.  
  441.  
  442.  
  443. let flags = this._cgl.gl.COLOR_BUFFER_BIT;
  444. if (i == 0) flags |= this._cgl.gl.DEPTH_BUFFER_BIT;
  445.  
  446. this._cgl.gl.blitFramebuffer(0, 0, this._width, this._height, 0, 0, this._width, this._height, flags, this._cgl.gl.NEAREST);
  447. }
  448. }
  449.  
  450. this._cgl.gl.bindFramebuffer(this._cgl.gl.FRAMEBUFFER, this._cgl.popGlFrameBuffer());
  451. this._cgl.popFrameBuffer();
  452.  
  453. this._cgl.popModelMatrix();
  454. // this._cgl.resetViewPort();
  455. this._cgl.popViewPort();
  456.  
  457.  
  458. if (this._colorTextures[0].filter == Texture.FILTER_MIPMAP)
  459. {
  460. for (let i = 0; i < this._numRenderBuffers; i++)
  461. {
  462. this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, this._colorTextures[i].tex);
  463. this._colorTextures[i].updateMipMap();
  464. this._cgl.gl.bindTexture(this._cgl.gl.TEXTURE_2D, null);
  465. }
  466. }
  467. };
  468.  
  469. export { Framebuffer2 };
  470.  
  471. /// ///////