智慧水务管理系统 - 精河县供水工程综合管理平台

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. import Framebuffer from "./Framebuffer.js";
  2. import MultisampleFramebuffer from "./MultisampleFramebuffer.js";
  3. import PixelDatatype from "./PixelDatatype.js";
  4. import Renderbuffer from "./Renderbuffer.js";
  5. import RenderbufferFormat from "./RenderbufferFormat.js";
  6. import Sampler from "./Sampler.js";
  7. import Texture from "./Texture.js";
  8. import Frozen from "../Core/Frozen.js";
  9. import defined from "../Core/defined.js";
  10. import DeveloperError from "../Core/DeveloperError.js";
  11. import PixelFormat from "../Core/PixelFormat.js";
  12. /**
  13. * Creates a wrapper object around a framebuffer and its resources.
  14. *
  15. * @param {object} options Object with the following properties:
  16. * @param {number} [options.numSamples=1] The multisampling rate of the render targets. Requires a WebGL2 context.
  17. * @param {number} [options.colorAttachmentsLength=1] The number of color attachments this FramebufferManager will create.
  18. * @param {boolean} [options.color=true] Whether the FramebufferManager will use color attachments.
  19. * @param {boolean} [options.depth=false] Whether the FramebufferManager will use depth attachments.
  20. * @param {boolean} [options.depthStencil=false] Whether the FramebufferManager will use depth-stencil attachments.
  21. * @param {boolean} [options.supportsDepthTexture=false] Whether the FramebufferManager will create a depth texture when the extension is supported.
  22. * @param {boolean} [options.createColorAttachments=true] Whether the FramebufferManager will construct its own color attachments.
  23. * @param {boolean} [options.createDepthAttachments=true] Whether the FramebufferManager will construct its own depth attachments.
  24. * @param {PixelDatatype} [options.pixelDatatype=undefined] The default pixel datatype to use when creating color attachments.
  25. * @param {PixelFormat} [options.pixelFormat=undefined] The default pixel format to use when creating color attachments.
  26. *
  27. * @exception {DeveloperError} Must enable at least one type of framebuffer attachment.
  28. * @exception {DeveloperError} Cannot have both a depth and depth-stencil attachment.
  29. *
  30. * @private
  31. * @constructor
  32. */
  33. function FramebufferManager(options) {
  34. options = options ?? Frozen.EMPTY_OBJECT;
  35. this._numSamples = options.numSamples ?? 1;
  36. this._colorAttachmentsLength = options.colorAttachmentsLength ?? 1;
  37. this._color = options.color ?? true;
  38. this._depth = options.depth ?? false;
  39. this._depthStencil = options.depthStencil ?? false;
  40. this._supportsDepthTexture = options.supportsDepthTexture ?? false;
  41. //>>includeStart('debug', pragmas.debug);
  42. if (!this._color && !this._depth && !this._depthStencil) {
  43. throw new DeveloperError(
  44. "Must enable at least one type of framebuffer attachment.",
  45. );
  46. }
  47. if (this._depth && this._depthStencil) {
  48. throw new DeveloperError(
  49. "Cannot have both a depth and depth-stencil attachment.",
  50. );
  51. }
  52. //>>includeEnd('debug');
  53. this._createColorAttachments = options.createColorAttachments ?? true;
  54. this._createDepthAttachments = options.createDepthAttachments ?? true;
  55. this._pixelDatatype = options.pixelDatatype;
  56. this._pixelFormat = options.pixelFormat;
  57. this._width = undefined;
  58. this._height = undefined;
  59. this._framebuffer = undefined;
  60. this._multisampleFramebuffer = undefined;
  61. this._colorTextures = undefined;
  62. if (this._color) {
  63. this._colorTextures = new Array(this._colorAttachmentsLength);
  64. this._colorRenderbuffers = new Array(this._colorAttachmentsLength);
  65. }
  66. this._colorRenderbuffer = undefined;
  67. this._depthStencilRenderbuffer = undefined;
  68. this._depthStencilTexture = undefined;
  69. this._depthRenderbuffer = undefined;
  70. this._depthTexture = undefined;
  71. this._attachmentsDirty = false;
  72. }
  73. Object.defineProperties(FramebufferManager.prototype, {
  74. framebuffer: {
  75. get: function () {
  76. if (this._numSamples > 1) {
  77. return this._multisampleFramebuffer.getRenderFramebuffer();
  78. }
  79. return this._framebuffer;
  80. },
  81. },
  82. numSamples: {
  83. get: function () {
  84. return this._numSamples;
  85. },
  86. },
  87. status: {
  88. get: function () {
  89. return this.framebuffer.status;
  90. },
  91. },
  92. });
  93. FramebufferManager.prototype.isDirty = function (
  94. width,
  95. height,
  96. numSamples,
  97. pixelDatatype,
  98. pixelFormat,
  99. ) {
  100. numSamples = numSamples ?? 1;
  101. const dimensionChanged = this._width !== width || this._height !== height;
  102. const samplesChanged = this._numSamples !== numSamples;
  103. const pixelChanged =
  104. (defined(pixelDatatype) && this._pixelDatatype !== pixelDatatype) ||
  105. (defined(pixelFormat) && this._pixelFormat !== pixelFormat);
  106. const framebufferDefined =
  107. numSamples === 1
  108. ? defined(this._framebuffer)
  109. : defined(this._multisampleFramebuffer);
  110. return (
  111. this._attachmentsDirty ||
  112. dimensionChanged ||
  113. samplesChanged ||
  114. pixelChanged ||
  115. !framebufferDefined ||
  116. (this._color && !defined(this._colorTextures[0]))
  117. );
  118. };
  119. FramebufferManager.prototype.update = function (
  120. context,
  121. width,
  122. height,
  123. numSamples,
  124. pixelDatatype,
  125. pixelFormat,
  126. ) {
  127. //>>includeStart('debug', pragmas.debug);
  128. if (!defined(width) || !defined(height)) {
  129. throw new DeveloperError("width and height must be defined.");
  130. }
  131. //>>includeEnd('debug');
  132. numSamples = context.msaa ? (numSamples ?? 1) : 1;
  133. pixelDatatype =
  134. pixelDatatype ??
  135. (this._color
  136. ? (this._pixelDatatype ?? PixelDatatype.UNSIGNED_BYTE)
  137. : undefined);
  138. pixelFormat =
  139. pixelFormat ??
  140. (this._color ? (this._pixelFormat ?? PixelFormat.RGBA) : undefined);
  141. if (this.isDirty(width, height, numSamples, pixelDatatype, pixelFormat)) {
  142. this.destroy();
  143. this._width = width;
  144. this._height = height;
  145. this._numSamples = numSamples;
  146. this._pixelDatatype = pixelDatatype;
  147. this._pixelFormat = pixelFormat;
  148. this._attachmentsDirty = false;
  149. // Create color texture
  150. if (this._color && this._createColorAttachments) {
  151. for (let i = 0; i < this._colorAttachmentsLength; ++i) {
  152. this._colorTextures[i] = new Texture({
  153. context: context,
  154. width: width,
  155. height: height,
  156. pixelFormat: pixelFormat,
  157. pixelDatatype: pixelDatatype,
  158. sampler: Sampler.NEAREST,
  159. });
  160. if (this._numSamples > 1) {
  161. const format = RenderbufferFormat.getColorFormat(pixelDatatype);
  162. this._colorRenderbuffers[i] = new Renderbuffer({
  163. context: context,
  164. width: width,
  165. height: height,
  166. format: format,
  167. numSamples: this._numSamples,
  168. });
  169. }
  170. }
  171. }
  172. // Create depth stencil texture or renderbuffer
  173. if (this._depthStencil && this._createDepthAttachments) {
  174. if (this._supportsDepthTexture && context.depthTexture) {
  175. this._depthStencilTexture = new Texture({
  176. context: context,
  177. width: width,
  178. height: height,
  179. pixelFormat: PixelFormat.DEPTH_STENCIL,
  180. pixelDatatype: PixelDatatype.UNSIGNED_INT_24_8,
  181. sampler: Sampler.NEAREST,
  182. });
  183. if (this._numSamples > 1) {
  184. this._depthStencilRenderbuffer = new Renderbuffer({
  185. context: context,
  186. width: width,
  187. height: height,
  188. format: RenderbufferFormat.DEPTH24_STENCIL8,
  189. numSamples: this._numSamples,
  190. });
  191. }
  192. } else {
  193. this._depthStencilRenderbuffer = new Renderbuffer({
  194. context: context,
  195. width: width,
  196. height: height,
  197. format: RenderbufferFormat.DEPTH_STENCIL,
  198. });
  199. }
  200. }
  201. // Create depth texture
  202. if (this._depth && this._createDepthAttachments) {
  203. if (this._supportsDepthTexture && context.depthTexture) {
  204. this._depthTexture = new Texture({
  205. context: context,
  206. width: width,
  207. height: height,
  208. pixelFormat: PixelFormat.DEPTH_COMPONENT,
  209. pixelDatatype: PixelDatatype.UNSIGNED_INT,
  210. sampler: Sampler.NEAREST,
  211. });
  212. } else {
  213. this._depthRenderbuffer = new Renderbuffer({
  214. context: context,
  215. width: width,
  216. height: height,
  217. format: RenderbufferFormat.DEPTH_COMPONENT16,
  218. });
  219. }
  220. }
  221. if (this._numSamples > 1) {
  222. this._multisampleFramebuffer = new MultisampleFramebuffer({
  223. context: context,
  224. width: this._width,
  225. height: this._height,
  226. colorTextures: this._colorTextures,
  227. colorRenderbuffers: this._colorRenderbuffers,
  228. depthStencilTexture: this._depthStencilTexture,
  229. depthStencilRenderbuffer: this._depthStencilRenderbuffer,
  230. destroyAttachments: false,
  231. });
  232. } else {
  233. this._framebuffer = new Framebuffer({
  234. context: context,
  235. colorTextures: this._colorTextures,
  236. depthTexture: this._depthTexture,
  237. depthRenderbuffer: this._depthRenderbuffer,
  238. depthStencilTexture: this._depthStencilTexture,
  239. depthStencilRenderbuffer: this._depthStencilRenderbuffer,
  240. destroyAttachments: false,
  241. });
  242. }
  243. }
  244. };
  245. FramebufferManager.prototype.getColorTexture = function (index) {
  246. index = index ?? 0;
  247. //>>includeStart('debug', pragmas.debug);
  248. if (index >= this._colorAttachmentsLength) {
  249. throw new DeveloperError(
  250. "index must be smaller than total number of color attachments.",
  251. );
  252. }
  253. //>>includeEnd('debug');
  254. return this._colorTextures[index];
  255. };
  256. FramebufferManager.prototype.setColorTexture = function (texture, index) {
  257. index = index ?? 0;
  258. //>>includeStart('debug', pragmas.debug);
  259. if (this._createColorAttachments) {
  260. throw new DeveloperError(
  261. "createColorAttachments must be false if setColorTexture is called.",
  262. );
  263. }
  264. if (index >= this._colorAttachmentsLength) {
  265. throw new DeveloperError(
  266. "index must be smaller than total number of color attachments.",
  267. );
  268. }
  269. //>>includeEnd('debug');
  270. this._attachmentsDirty = texture !== this._colorTextures[index];
  271. this._colorTextures[index] = texture;
  272. };
  273. FramebufferManager.prototype.getColorRenderbuffer = function (index) {
  274. index = index ?? 0;
  275. //>>includeStart('debug', pragmas.debug);
  276. if (index >= this._colorAttachmentsLength) {
  277. throw new DeveloperError(
  278. "index must be smaller than total number of color attachments.",
  279. );
  280. }
  281. //>>includeEnd('debug');
  282. return this._colorRenderbuffers[index];
  283. };
  284. FramebufferManager.prototype.setColorRenderbuffer = function (
  285. renderbuffer,
  286. index,
  287. ) {
  288. index = index ?? 0;
  289. //>>includeStart('debug', pragmas.debug);
  290. if (this._createColorAttachments) {
  291. throw new DeveloperError(
  292. "createColorAttachments must be false if setColorRenderbuffer is called.",
  293. );
  294. }
  295. if (index >= this._colorAttachmentsLength) {
  296. throw new DeveloperError(
  297. "index must be smaller than total number of color attachments.",
  298. );
  299. }
  300. //>>includeEnd('debug');
  301. this._attachmentsDirty = renderbuffer !== this._colorRenderbuffers[index];
  302. this._colorRenderbuffers[index] = renderbuffer;
  303. };
  304. FramebufferManager.prototype.getDepthRenderbuffer = function () {
  305. return this._depthRenderbuffer;
  306. };
  307. FramebufferManager.prototype.setDepthRenderbuffer = function (renderbuffer) {
  308. //>>includeStart('debug', pragmas.debug);
  309. if (this._createDepthAttachments) {
  310. throw new DeveloperError(
  311. "createDepthAttachments must be false if setDepthRenderbuffer is called.",
  312. );
  313. }
  314. //>>includeEnd('debug');
  315. this._attachmentsDirty = renderbuffer !== this._depthRenderbuffer;
  316. this._depthRenderbuffer = renderbuffer;
  317. };
  318. FramebufferManager.prototype.getDepthTexture = function () {
  319. return this._depthTexture;
  320. };
  321. FramebufferManager.prototype.setDepthTexture = function (texture) {
  322. //>>includeStart('debug', pragmas.debug);
  323. if (this._createDepthAttachments) {
  324. throw new DeveloperError(
  325. "createDepthAttachments must be false if setDepthTexture is called.",
  326. );
  327. }
  328. //>>includeEnd('debug');
  329. this._attachmentsDirty = texture !== this._depthTexture;
  330. this._depthTexture = texture;
  331. };
  332. FramebufferManager.prototype.getDepthStencilRenderbuffer = function () {
  333. return this._depthStencilRenderbuffer;
  334. };
  335. FramebufferManager.prototype.setDepthStencilRenderbuffer = function (
  336. renderbuffer,
  337. ) {
  338. //>>includeStart('debug', pragmas.debug);
  339. if (this._createDepthAttachments) {
  340. throw new DeveloperError(
  341. "createDepthAttachments must be false if setDepthStencilRenderbuffer is called.",
  342. );
  343. }
  344. //>>includeEnd('debug');
  345. this._attachmentsDirty = renderbuffer !== this._depthStencilRenderbuffer;
  346. this._depthStencilRenderbuffer = renderbuffer;
  347. };
  348. FramebufferManager.prototype.getDepthStencilTexture = function () {
  349. return this._depthStencilTexture;
  350. };
  351. FramebufferManager.prototype.setDepthStencilTexture = function (texture) {
  352. //>>includeStart('debug', pragmas.debug);
  353. if (this._createDepthAttachments) {
  354. throw new DeveloperError(
  355. "createDepthAttachments must be false if setDepthStencilTexture is called.",
  356. );
  357. }
  358. //>>includeEnd('debug');
  359. this._attachmentsDirty = texture !== this._depthStencilTexture;
  360. this._depthStencilTexture = texture;
  361. };
  362. /**
  363. * If using MSAA, resolve the stencil.
  364. *
  365. * @param {Context} context
  366. * @param {boolean} blitStencil
  367. *
  368. * @private
  369. */
  370. FramebufferManager.prototype.prepareTextures = function (context, blitStencil) {
  371. if (this._numSamples > 1) {
  372. this._multisampleFramebuffer.blitFramebuffers(context, blitStencil);
  373. }
  374. };
  375. FramebufferManager.prototype.clear = function (
  376. context,
  377. clearCommand,
  378. passState,
  379. ) {
  380. const framebuffer = clearCommand.framebuffer;
  381. clearCommand.framebuffer = this.framebuffer;
  382. clearCommand.execute(context, passState);
  383. clearCommand.framebuffer = framebuffer;
  384. };
  385. FramebufferManager.prototype.destroyFramebuffer = function () {
  386. this._framebuffer = this._framebuffer && this._framebuffer.destroy();
  387. this._multisampleFramebuffer =
  388. this._multisampleFramebuffer && this._multisampleFramebuffer.destroy();
  389. };
  390. FramebufferManager.prototype.destroy = function () {
  391. if (this._color) {
  392. const colorTextures = this._colorTextures;
  393. const colorRenderbuffers = this._colorRenderbuffers;
  394. for (let i = 0; i < colorTextures.length; ++i) {
  395. const texture = colorTextures[i];
  396. if (this._createColorAttachments) {
  397. if (defined(texture) && !texture.isDestroyed()) {
  398. texture.destroy();
  399. }
  400. }
  401. if (defined(texture) && texture.isDestroyed()) {
  402. colorTextures[i] = undefined;
  403. }
  404. const renderbuffer = colorRenderbuffers[i];
  405. if (this._createColorAttachments) {
  406. if (defined(renderbuffer) && !renderbuffer.isDestroyed()) {
  407. renderbuffer.destroy();
  408. }
  409. }
  410. if (defined(renderbuffer) && renderbuffer.isDestroyed()) {
  411. colorRenderbuffers[i] = undefined;
  412. }
  413. }
  414. }
  415. if (this._depthStencil) {
  416. if (this._createDepthAttachments) {
  417. this._depthStencilTexture =
  418. this._depthStencilTexture && this._depthStencilTexture.destroy();
  419. this._depthStencilRenderbuffer =
  420. this._depthStencilRenderbuffer &&
  421. this._depthStencilRenderbuffer.destroy();
  422. }
  423. if (
  424. defined(this._depthStencilTexture) &&
  425. this._depthStencilTexture.isDestroyed()
  426. ) {
  427. this._depthStencilTexture = undefined;
  428. }
  429. if (
  430. defined(this._depthStencilRenderbuffer) &&
  431. this._depthStencilRenderbuffer.isDestroyed()
  432. ) {
  433. this._depthStencilRenderbuffer = undefined;
  434. }
  435. }
  436. if (this._depth) {
  437. if (this._createDepthAttachments) {
  438. this._depthTexture = this._depthTexture && this._depthTexture.destroy();
  439. this._depthRenderbuffer =
  440. this._depthRenderbuffer && this._depthRenderbuffer.destroy();
  441. }
  442. if (defined(this._depthTexture) && this._depthTexture.isDestroyed()) {
  443. this._depthTexture = undefined;
  444. }
  445. if (
  446. defined(this._depthRenderbuffer) &&
  447. this._depthRenderbuffer.isDestroyed()
  448. ) {
  449. this._depthRenderbuffer = undefined;
  450. }
  451. }
  452. this.destroyFramebuffer();
  453. };
  454. export default FramebufferManager;