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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946
  1. import BoundingRectangle from "../Core/BoundingRectangle.js";
  2. import Color from "../Core/Color.js";
  3. import defined from "../Core/defined.js";
  4. import destroyObject from "../Core/destroyObject.js";
  5. import PixelFormat from "../Core/PixelFormat.js";
  6. import WebGLConstants from "../Core/WebGLConstants.js";
  7. import ClearCommand from "../Renderer/ClearCommand.js";
  8. import DrawCommand from "../Renderer/DrawCommand.js";
  9. import FramebufferManager from "../Renderer/FramebufferManager.js";
  10. import PixelDatatype from "../Renderer/PixelDatatype.js";
  11. import RenderState from "../Renderer/RenderState.js";
  12. import ShaderSource from "../Renderer/ShaderSource.js";
  13. import Texture from "../Renderer/Texture.js";
  14. import AdjustTranslucentFS from "../Shaders/AdjustTranslucentFS.js";
  15. import CompositeOITFS from "../Shaders/CompositeOITFS.js";
  16. import BlendEquation from "./BlendEquation.js";
  17. import BlendFunction from "./BlendFunction.js";
  18. /**
  19. * @private
  20. * @constructor
  21. * @param {Context} context
  22. */
  23. function OIT(context) {
  24. this._numSamples = 1;
  25. // We support multipass for the Chrome D3D9 backend and ES 2.0 on mobile.
  26. this._translucentMultipassSupport = false;
  27. this._translucentMRTSupport = false;
  28. const extensionsSupported =
  29. context.colorBufferFloat && context.depthTexture && context.floatBlend;
  30. this._translucentMRTSupport = context.drawBuffers && extensionsSupported;
  31. this._translucentMultipassSupport =
  32. !this._translucentMRTSupport && extensionsSupported;
  33. this._opaqueFBO = undefined;
  34. this._opaqueTexture = undefined;
  35. this._depthStencilTexture = undefined;
  36. this._accumulationTexture = undefined;
  37. this._translucentFBO = new FramebufferManager({
  38. colorAttachmentsLength: this._translucentMRTSupport ? 2 : 1,
  39. createColorAttachments: false,
  40. createDepthAttachments: false,
  41. depth: true,
  42. });
  43. this._alphaFBO = new FramebufferManager({
  44. createColorAttachments: false,
  45. createDepthAttachments: false,
  46. depth: true,
  47. });
  48. this._adjustTranslucentFBO = new FramebufferManager({
  49. colorAttachmentsLength: this._translucentMRTSupport ? 2 : 1,
  50. createColorAttachments: false,
  51. });
  52. this._adjustAlphaFBO = new FramebufferManager({
  53. createColorAttachments: false,
  54. });
  55. this._opaqueClearCommand = new ClearCommand({
  56. color: new Color(0.0, 0.0, 0.0, 0.0),
  57. owner: this,
  58. });
  59. this._translucentMRTClearCommand = new ClearCommand({
  60. color: new Color(0.0, 0.0, 0.0, 1.0),
  61. owner: this,
  62. });
  63. this._translucentMultipassClearCommand = new ClearCommand({
  64. color: new Color(0.0, 0.0, 0.0, 0.0),
  65. owner: this,
  66. });
  67. this._alphaClearCommand = new ClearCommand({
  68. color: new Color(1.0, 1.0, 1.0, 1.0),
  69. owner: this,
  70. });
  71. this._translucentRenderStateCache = {};
  72. this._alphaRenderStateCache = {};
  73. this._compositeCommand = undefined;
  74. this._adjustTranslucentCommand = undefined;
  75. this._adjustAlphaCommand = undefined;
  76. this._viewport = new BoundingRectangle();
  77. this._rs = undefined;
  78. this._useScissorTest = false;
  79. this._scissorRectangle = undefined;
  80. this._useHDR = false;
  81. }
  82. /**
  83. * @private
  84. * @param {OIT} oit
  85. */
  86. function destroyTextures(oit) {
  87. oit._accumulationTexture =
  88. oit._accumulationTexture &&
  89. !oit._accumulationTexture.isDestroyed() &&
  90. oit._accumulationTexture.destroy();
  91. oit._revealageTexture =
  92. oit._revealageTexture &&
  93. !oit._revealageTexture.isDestroyed() &&
  94. oit._revealageTexture.destroy();
  95. }
  96. /**
  97. * @private
  98. * @param {OIT} oit
  99. */
  100. function destroyFramebuffers(oit) {
  101. oit._translucentFBO.destroy();
  102. oit._alphaFBO.destroy();
  103. oit._adjustTranslucentFBO.destroy();
  104. oit._adjustAlphaFBO.destroy();
  105. }
  106. /**
  107. * @private
  108. * @param {OIT} oit
  109. */
  110. function destroyResources(oit) {
  111. destroyTextures(oit);
  112. destroyFramebuffers(oit);
  113. }
  114. /**
  115. * @private
  116. * @param {OIT} oit
  117. * @param {Context} context
  118. * @param {number} width
  119. * @param {number} height
  120. */
  121. function updateTextures(oit, context, width, height) {
  122. destroyTextures(oit);
  123. oit._accumulationTexture = new Texture({
  124. context: context,
  125. width: width,
  126. height: height,
  127. pixelFormat: PixelFormat.RGBA,
  128. pixelDatatype: PixelDatatype.FLOAT,
  129. });
  130. oit._revealageTexture = new Texture({
  131. context: context,
  132. pixelFormat: PixelFormat.RGBA,
  133. pixelDatatype: PixelDatatype.FLOAT,
  134. width: width,
  135. height: height,
  136. flipY: false,
  137. });
  138. }
  139. /**
  140. * @private
  141. * @param {OIT} oit
  142. * @param {Context} context
  143. * @returns {boolean}
  144. */
  145. function updateFramebuffers(oit, context) {
  146. destroyFramebuffers(oit);
  147. const completeFBO = WebGLConstants.FRAMEBUFFER_COMPLETE;
  148. let supported = true;
  149. const { width, height } = oit._accumulationTexture;
  150. // if MRT is supported, attempt to make an FBO with multiple color attachments
  151. if (oit._translucentMRTSupport) {
  152. oit._translucentFBO.setColorTexture(oit._accumulationTexture, 0);
  153. oit._translucentFBO.setColorTexture(oit._revealageTexture, 1);
  154. oit._translucentFBO.setDepthStencilTexture(oit._depthStencilTexture);
  155. oit._translucentFBO.update(context, width, height);
  156. oit._adjustTranslucentFBO.setColorTexture(oit._accumulationTexture, 0);
  157. oit._adjustTranslucentFBO.setColorTexture(oit._revealageTexture, 1);
  158. oit._adjustTranslucentFBO.update(context, width, height);
  159. if (
  160. oit._translucentFBO.status !== completeFBO ||
  161. oit._adjustTranslucentFBO.status !== completeFBO
  162. ) {
  163. destroyFramebuffers(oit);
  164. oit._translucentMRTSupport = false;
  165. }
  166. }
  167. // either MRT isn't supported or FBO creation failed, attempt multipass
  168. if (!oit._translucentMRTSupport) {
  169. oit._translucentFBO.setColorTexture(oit._accumulationTexture);
  170. oit._translucentFBO.setDepthStencilTexture(oit._depthStencilTexture);
  171. oit._translucentFBO.update(context, width, height);
  172. oit._alphaFBO.setColorTexture(oit._revealageTexture);
  173. oit._alphaFBO.setDepthStencilTexture(oit._depthStencilTexture);
  174. oit._alphaFBO.update(context, width, height);
  175. oit._adjustTranslucentFBO.setColorTexture(oit._accumulationTexture);
  176. oit._adjustTranslucentFBO.update(context, width, height);
  177. oit._adjustAlphaFBO.setColorTexture(oit._revealageTexture);
  178. oit._adjustAlphaFBO.update(context, width, height);
  179. const translucentComplete = oit._translucentFBO.status === completeFBO;
  180. const alphaComplete = oit._alphaFBO.status === completeFBO;
  181. const adjustTranslucentComplete =
  182. oit._adjustTranslucentFBO.status === completeFBO;
  183. const adjustAlphaComplete = oit._adjustAlphaFBO.status === completeFBO;
  184. if (
  185. !translucentComplete ||
  186. !alphaComplete ||
  187. !adjustTranslucentComplete ||
  188. !adjustAlphaComplete
  189. ) {
  190. destroyResources(oit);
  191. oit._translucentMultipassSupport = false;
  192. supported = false;
  193. }
  194. }
  195. return supported;
  196. }
  197. /**
  198. * @private
  199. * @param {Context} context
  200. * @param {PassState} passState
  201. * @param {Framebuffer} framebuffer
  202. * @param {boolean} useHDR
  203. * @param {number} numSamples
  204. */
  205. OIT.prototype.update = function (
  206. context,
  207. passState,
  208. framebuffer,
  209. useHDR,
  210. numSamples,
  211. ) {
  212. if (!this.isSupported()) {
  213. return;
  214. }
  215. this._opaqueFBO = framebuffer;
  216. this._opaqueTexture = framebuffer.getColorTexture(0);
  217. this._depthStencilTexture = framebuffer.getDepthStencilTexture();
  218. const { width, height } = this._opaqueTexture;
  219. const accumulationTexture = this._accumulationTexture;
  220. const textureChanged =
  221. !defined(accumulationTexture) ||
  222. accumulationTexture.width !== width ||
  223. accumulationTexture.height !== height ||
  224. useHDR !== this._useHDR;
  225. const samplesChanged = this._numSamples !== numSamples;
  226. if (textureChanged || samplesChanged) {
  227. this._numSamples = numSamples;
  228. updateTextures(this, context, width, height);
  229. }
  230. if (
  231. !defined(this._translucentFBO.framebuffer) ||
  232. textureChanged ||
  233. samplesChanged
  234. ) {
  235. if (!updateFramebuffers(this, context)) {
  236. // framebuffer creation failed
  237. return;
  238. }
  239. }
  240. this._useHDR = useHDR;
  241. const that = this;
  242. let fs;
  243. let uniformMap;
  244. if (!defined(this._compositeCommand)) {
  245. fs = new ShaderSource({
  246. sources: [CompositeOITFS],
  247. });
  248. if (this._translucentMRTSupport) {
  249. fs.defines.push("MRT");
  250. }
  251. uniformMap = {
  252. u_opaque: function () {
  253. return that._opaqueTexture;
  254. },
  255. u_accumulation: function () {
  256. return that._accumulationTexture;
  257. },
  258. u_revealage: function () {
  259. return that._revealageTexture;
  260. },
  261. };
  262. this._compositeCommand = context.createViewportQuadCommand(fs, {
  263. uniformMap: uniformMap,
  264. owner: this,
  265. });
  266. }
  267. if (!defined(this._adjustTranslucentCommand)) {
  268. if (this._translucentMRTSupport) {
  269. fs = new ShaderSource({
  270. defines: ["MRT"],
  271. sources: [AdjustTranslucentFS],
  272. });
  273. uniformMap = {
  274. u_bgColor: function () {
  275. return that._translucentMRTClearCommand.color;
  276. },
  277. u_depthTexture: function () {
  278. return that._depthStencilTexture;
  279. },
  280. };
  281. this._adjustTranslucentCommand = context.createViewportQuadCommand(fs, {
  282. uniformMap: uniformMap,
  283. owner: this,
  284. });
  285. } else if (this._translucentMultipassSupport) {
  286. fs = new ShaderSource({
  287. sources: [AdjustTranslucentFS],
  288. });
  289. uniformMap = {
  290. u_bgColor: function () {
  291. return that._translucentMultipassClearCommand.color;
  292. },
  293. u_depthTexture: function () {
  294. return that._depthStencilTexture;
  295. },
  296. };
  297. this._adjustTranslucentCommand = context.createViewportQuadCommand(fs, {
  298. uniformMap: uniformMap,
  299. owner: this,
  300. });
  301. uniformMap = {
  302. u_bgColor: function () {
  303. return that._alphaClearCommand.color;
  304. },
  305. u_depthTexture: function () {
  306. return that._depthStencilTexture;
  307. },
  308. };
  309. this._adjustAlphaCommand = context.createViewportQuadCommand(fs, {
  310. uniformMap: uniformMap,
  311. owner: this,
  312. });
  313. }
  314. }
  315. this._viewport.width = width;
  316. this._viewport.height = height;
  317. const useScissorTest = !BoundingRectangle.equals(
  318. this._viewport,
  319. passState.viewport,
  320. );
  321. let updateScissor = useScissorTest !== this._useScissorTest;
  322. this._useScissorTest = useScissorTest;
  323. if (!BoundingRectangle.equals(this._scissorRectangle, passState.viewport)) {
  324. this._scissorRectangle = BoundingRectangle.clone(
  325. passState.viewport,
  326. this._scissorRectangle,
  327. );
  328. updateScissor = true;
  329. }
  330. if (
  331. !defined(this._rs) ||
  332. !BoundingRectangle.equals(this._viewport, this._rs.viewport) ||
  333. updateScissor
  334. ) {
  335. this._rs = RenderState.fromCache({
  336. viewport: this._viewport,
  337. scissorTest: {
  338. enabled: this._useScissorTest,
  339. rectangle: this._scissorRectangle,
  340. },
  341. });
  342. }
  343. if (defined(this._compositeCommand)) {
  344. this._compositeCommand.renderState = this._rs;
  345. }
  346. if (this._adjustTranslucentCommand) {
  347. this._adjustTranslucentCommand.renderState = this._rs;
  348. }
  349. if (defined(this._adjustAlphaCommand)) {
  350. this._adjustAlphaCommand.renderState = this._rs;
  351. }
  352. };
  353. const translucentMRTBlend = {
  354. enabled: true,
  355. color: new Color(0.0, 0.0, 0.0, 0.0),
  356. equationRgb: BlendEquation.ADD,
  357. equationAlpha: BlendEquation.ADD,
  358. functionSourceRgb: BlendFunction.ONE,
  359. functionDestinationRgb: BlendFunction.ONE,
  360. functionSourceAlpha: BlendFunction.ZERO,
  361. functionDestinationAlpha: BlendFunction.ONE_MINUS_SOURCE_ALPHA,
  362. };
  363. const translucentColorBlend = {
  364. enabled: true,
  365. color: new Color(0.0, 0.0, 0.0, 0.0),
  366. equationRgb: BlendEquation.ADD,
  367. equationAlpha: BlendEquation.ADD,
  368. functionSourceRgb: BlendFunction.ONE,
  369. functionDestinationRgb: BlendFunction.ONE,
  370. functionSourceAlpha: BlendFunction.ONE,
  371. functionDestinationAlpha: BlendFunction.ONE,
  372. };
  373. const translucentAlphaBlend = {
  374. enabled: true,
  375. color: new Color(0.0, 0.0, 0.0, 0.0),
  376. equationRgb: BlendEquation.ADD,
  377. equationAlpha: BlendEquation.ADD,
  378. functionSourceRgb: BlendFunction.ZERO,
  379. functionDestinationRgb: BlendFunction.ONE_MINUS_SOURCE_ALPHA,
  380. functionSourceAlpha: BlendFunction.ZERO,
  381. functionDestinationAlpha: BlendFunction.ONE_MINUS_SOURCE_ALPHA,
  382. };
  383. function getTranslucentRenderState(
  384. context,
  385. translucentBlending,
  386. cache,
  387. renderState,
  388. ) {
  389. let translucentState = cache[renderState.id];
  390. if (!defined(translucentState)) {
  391. const rs = RenderState.getState(renderState);
  392. rs.depthMask = false;
  393. rs.blending = translucentBlending;
  394. translucentState = RenderState.fromCache(rs);
  395. cache[renderState.id] = translucentState;
  396. }
  397. return translucentState;
  398. }
  399. function getTranslucentMRTRenderState(oit, context, renderState) {
  400. return getTranslucentRenderState(
  401. context,
  402. translucentMRTBlend,
  403. oit._translucentRenderStateCache,
  404. renderState,
  405. );
  406. }
  407. function getTranslucentColorRenderState(oit, context, renderState) {
  408. return getTranslucentRenderState(
  409. context,
  410. translucentColorBlend,
  411. oit._translucentRenderStateCache,
  412. renderState,
  413. );
  414. }
  415. function getTranslucentAlphaRenderState(oit, context, renderState) {
  416. return getTranslucentRenderState(
  417. context,
  418. translucentAlphaBlend,
  419. oit._alphaRenderStateCache,
  420. renderState,
  421. );
  422. }
  423. const mrtShaderSource =
  424. " vec3 Ci = czm_out_FragColor.rgb * czm_out_FragColor.a;\n" +
  425. " float ai = czm_out_FragColor.a;\n" +
  426. " float wzi = czm_alphaWeight(ai);\n" +
  427. " out_FragData_0 = vec4(Ci * wzi, ai);\n" +
  428. " out_FragData_1 = vec4(ai * wzi);\n";
  429. const colorShaderSource =
  430. " vec3 Ci = czm_out_FragColor.rgb * czm_out_FragColor.a;\n" +
  431. " float ai = czm_out_FragColor.a;\n" +
  432. " float wzi = czm_alphaWeight(ai);\n" +
  433. " out_FragColor = vec4(Ci, ai) * wzi;\n";
  434. const alphaShaderSource =
  435. " float ai = czm_out_FragColor.a;\n" + " out_FragColor = vec4(ai);\n";
  436. /**
  437. * @private
  438. * @param {Context} context
  439. * @param {ShaderProgram} shaderProgram
  440. * @param {string} keyword
  441. * @param {string} source
  442. * @returns {ShaderProgram}
  443. */
  444. function getTranslucentShaderProgram(context, shaderProgram, keyword, source) {
  445. const { shaderCache } = context;
  446. const shader = shaderCache.getDerivedShaderProgram(shaderProgram, keyword);
  447. if (defined(shader)) {
  448. return shader;
  449. }
  450. const attributeLocations = shaderProgram._attributeLocations;
  451. const fs = shaderProgram.fragmentShaderSource.clone();
  452. fs.sources = fs.sources.map(function (fsSource) {
  453. return ShaderSource.replaceMain(fsSource, "czm_translucent_main")
  454. .replace(/out_FragColor/g, "czm_out_FragColor")
  455. .replace(
  456. /layout\s*\(location\s*=\s*0\)\s*out\s+vec4\s+out_FragColor;/g,
  457. "",
  458. )
  459. .replace(/\bdiscard\b/g, "czm_discard = true")
  460. .replace(/czm_phong/g, "czm_translucentPhong");
  461. });
  462. // Discarding the fragment in main is a workaround for ANGLE D3D9
  463. // shader compilation errors.
  464. //
  465. // CESIUM_REDIRECTED_COLOR_OUTPUT: A general-purpose flag to indicate that this shader
  466. // is a derived/modified version created by Cesium's rendering pipeline.
  467. // This flag can be used to avoid color attachment conflicts when shaders
  468. // need different output declarations for different rendering passes.
  469. // For example, MRT (Multiple Render Targets) features can check this flag
  470. // to conditionally declare their output variables only when not conflicting
  471. // with the derived shader's output layout.
  472. fs.sources.splice(
  473. 0,
  474. 0,
  475. `#define CESIUM_REDIRECTED_COLOR_OUTPUT\n` +
  476. `vec4 czm_out_FragColor;\n` +
  477. `bool czm_discard = false;\n`,
  478. );
  479. const fragDataMatches = [...source.matchAll(/out_FragData_(\d+)/g)];
  480. let fragDataDeclarations = ``;
  481. for (let i = 0; i < fragDataMatches.length; i++) {
  482. const fragDataMatch = fragDataMatches[i];
  483. fragDataDeclarations = `layout (location = ${fragDataMatch[1]}) out vec4 ${fragDataMatch[0]};\n${fragDataDeclarations}`;
  484. }
  485. fs.sources.push(fragDataDeclarations);
  486. fs.sources.push(
  487. `${
  488. "void main()\n" +
  489. "{\n" +
  490. " czm_translucent_main();\n" +
  491. " if (czm_discard)\n" +
  492. " {\n" +
  493. " discard;\n" +
  494. " }\n"
  495. }${source}}\n`,
  496. );
  497. return shaderCache.createDerivedShaderProgram(shaderProgram, keyword, {
  498. vertexShaderSource: shaderProgram.vertexShaderSource,
  499. fragmentShaderSource: fs,
  500. attributeLocations: attributeLocations,
  501. });
  502. }
  503. function getTranslucentMRTShaderProgram(context, shaderProgram) {
  504. return getTranslucentShaderProgram(
  505. context,
  506. shaderProgram,
  507. "translucentMRT",
  508. mrtShaderSource,
  509. );
  510. }
  511. function getTranslucentColorShaderProgram(context, shaderProgram) {
  512. return getTranslucentShaderProgram(
  513. context,
  514. shaderProgram,
  515. "translucentMultipass",
  516. colorShaderSource,
  517. );
  518. }
  519. function getTranslucentAlphaShaderProgram(context, shaderProgram) {
  520. return getTranslucentShaderProgram(
  521. context,
  522. shaderProgram,
  523. "alphaMultipass",
  524. alphaShaderSource,
  525. );
  526. }
  527. /**
  528. * @private
  529. * @param {DrawCommand} command
  530. * @param {Context} context
  531. * @param {*} result
  532. * @returns {*}
  533. */
  534. OIT.prototype.createDerivedCommands = function (command, context, result) {
  535. if (!defined(result)) {
  536. result = {};
  537. }
  538. if (this._translucentMRTSupport) {
  539. let translucentShader;
  540. let translucentRenderState;
  541. if (defined(result.translucentCommand)) {
  542. translucentShader = result.translucentCommand.shaderProgram;
  543. translucentRenderState = result.translucentCommand.renderState;
  544. }
  545. result.translucentCommand = DrawCommand.shallowClone(
  546. command,
  547. result.translucentCommand,
  548. );
  549. if (
  550. !defined(translucentShader) ||
  551. result.shaderProgramId !== command.shaderProgram.id
  552. ) {
  553. result.translucentCommand.shaderProgram = getTranslucentMRTShaderProgram(
  554. context,
  555. command.shaderProgram,
  556. );
  557. result.translucentCommand.renderState = getTranslucentMRTRenderState(
  558. this,
  559. context,
  560. command.renderState,
  561. );
  562. result.shaderProgramId = command.shaderProgram.id;
  563. } else {
  564. result.translucentCommand.shaderProgram = translucentShader;
  565. result.translucentCommand.renderState = translucentRenderState;
  566. }
  567. return result;
  568. }
  569. let colorShader;
  570. let colorRenderState;
  571. let alphaShader;
  572. let alphaRenderState;
  573. if (defined(result.translucentCommand)) {
  574. colorShader = result.translucentCommand.shaderProgram;
  575. colorRenderState = result.translucentCommand.renderState;
  576. alphaShader = result.alphaCommand.shaderProgram;
  577. alphaRenderState = result.alphaCommand.renderState;
  578. }
  579. result.translucentCommand = DrawCommand.shallowClone(
  580. command,
  581. result.translucentCommand,
  582. );
  583. result.alphaCommand = DrawCommand.shallowClone(command, result.alphaCommand);
  584. if (
  585. !defined(colorShader) ||
  586. result.shaderProgramId !== command.shaderProgram.id
  587. ) {
  588. result.translucentCommand.shaderProgram = getTranslucentColorShaderProgram(
  589. context,
  590. command.shaderProgram,
  591. );
  592. result.translucentCommand.renderState = getTranslucentColorRenderState(
  593. this,
  594. context,
  595. command.renderState,
  596. );
  597. result.alphaCommand.shaderProgram = getTranslucentAlphaShaderProgram(
  598. context,
  599. command.shaderProgram,
  600. );
  601. result.alphaCommand.renderState = getTranslucentAlphaRenderState(
  602. this,
  603. context,
  604. command.renderState,
  605. );
  606. result.shaderProgramId = command.shaderProgram.id;
  607. } else {
  608. result.translucentCommand.shaderProgram = colorShader;
  609. result.translucentCommand.renderState = colorRenderState;
  610. result.alphaCommand.shaderProgram = alphaShader;
  611. result.alphaCommand.renderState = alphaRenderState;
  612. }
  613. return result;
  614. };
  615. /**
  616. * @private
  617. * @param {OIT} oit
  618. * @param {Scene} scene
  619. * @param {Function} executeFunction
  620. * @param {PassState} passState
  621. * @param {DrawCommand[]} commands
  622. * @param {InvertClassification} invertClassification
  623. */
  624. function executeTranslucentCommandsSortedMultipass(
  625. oit,
  626. scene,
  627. executeFunction,
  628. passState,
  629. commands,
  630. invertClassification,
  631. ) {
  632. const { context, frameState } = scene;
  633. const { useLogDepth, shadowState } = frameState;
  634. const useHdr = scene._hdr;
  635. const framebuffer = passState.framebuffer;
  636. const lightShadowsEnabled = shadowState.lightShadowsEnabled;
  637. passState.framebuffer = oit._adjustTranslucentFBO.framebuffer;
  638. oit._adjustTranslucentCommand.execute(context, passState);
  639. passState.framebuffer = oit._adjustAlphaFBO.framebuffer;
  640. oit._adjustAlphaCommand.execute(context, passState);
  641. const debugFramebuffer = oit._opaqueFBO.framebuffer;
  642. passState.framebuffer = oit._translucentFBO.framebuffer;
  643. for (let j = 0; j < commands.length; ++j) {
  644. let command = commands[j];
  645. command = useLogDepth ? command.derivedCommands.logDepth.command : command;
  646. command = useHdr ? command.derivedCommands.hdr.command : command;
  647. const derivedCommand =
  648. lightShadowsEnabled && command.receiveShadows
  649. ? command.derivedCommands.oit.shadows.translucentCommand
  650. : command.derivedCommands.oit.translucentCommand;
  651. executeFunction(derivedCommand, scene, passState, debugFramebuffer);
  652. }
  653. if (defined(invertClassification)) {
  654. const command = invertClassification.unclassifiedCommand;
  655. const derivedCommand =
  656. lightShadowsEnabled && command.receiveShadows
  657. ? command.derivedCommands.oit.shadows.translucentCommand
  658. : command.derivedCommands.oit.translucentCommand;
  659. executeFunction(derivedCommand, scene, passState, debugFramebuffer);
  660. }
  661. passState.framebuffer = oit._alphaFBO.framebuffer;
  662. for (let j = 0; j < commands.length; ++j) {
  663. let command = commands[j];
  664. command = useLogDepth ? command.derivedCommands.logDepth.command : command;
  665. command = useHdr ? command.derivedCommands.hdr.command : command;
  666. const derivedCommand =
  667. lightShadowsEnabled && command.receiveShadows
  668. ? command.derivedCommands.oit.shadows.alphaCommand
  669. : command.derivedCommands.oit.alphaCommand;
  670. executeFunction(derivedCommand, scene, passState, debugFramebuffer);
  671. }
  672. if (defined(invertClassification)) {
  673. const command = invertClassification.unclassifiedCommand;
  674. const derivedCommand =
  675. lightShadowsEnabled && command.receiveShadows
  676. ? command.derivedCommands.oit.shadows.alphaCommand
  677. : command.derivedCommands.oit.alphaCommand;
  678. executeFunction(derivedCommand, scene, passState, debugFramebuffer);
  679. }
  680. passState.framebuffer = framebuffer;
  681. }
  682. /**
  683. * @private
  684. * @param {OIT} oit
  685. * @param {Scene} scene
  686. * @param {Function} executeFunction
  687. * @param {PassState} passState
  688. * @param {DrawCommand[]} commands
  689. * @param {InvertClassification} invertClassification
  690. */
  691. function executeTranslucentCommandsSortedMRT(
  692. oit,
  693. scene,
  694. executeFunction,
  695. passState,
  696. commands,
  697. invertClassification,
  698. ) {
  699. const { context, frameState } = scene;
  700. const { useLogDepth, shadowState } = frameState;
  701. const useHdr = scene._hdr;
  702. const framebuffer = passState.framebuffer;
  703. const lightShadowsEnabled = shadowState.lightShadowsEnabled;
  704. passState.framebuffer = oit._adjustTranslucentFBO.framebuffer;
  705. oit._adjustTranslucentCommand.execute(context, passState);
  706. const debugFramebuffer = oit._opaqueFBO.framebuffer;
  707. passState.framebuffer = oit._translucentFBO.framebuffer;
  708. for (let j = 0; j < commands.length; ++j) {
  709. let command = commands[j];
  710. command = useLogDepth ? command.derivedCommands.logDepth.command : command;
  711. command = useHdr ? command.derivedCommands.hdr.command : command;
  712. const derivedCommand =
  713. lightShadowsEnabled && command.receiveShadows
  714. ? command.derivedCommands.oit.shadows.translucentCommand
  715. : command.derivedCommands.oit.translucentCommand;
  716. executeFunction(derivedCommand, scene, passState, debugFramebuffer);
  717. }
  718. if (defined(invertClassification)) {
  719. const command = invertClassification.unclassifiedCommand;
  720. const derivedCommand =
  721. lightShadowsEnabled && command.receiveShadows
  722. ? command.derivedCommands.oit.shadows.translucentCommand
  723. : command.derivedCommands.oit.translucentCommand;
  724. executeFunction(derivedCommand, scene, passState, debugFramebuffer);
  725. }
  726. passState.framebuffer = framebuffer;
  727. }
  728. /**
  729. * @private
  730. * @param {Scene} scene
  731. * @param {Function} executeFunction
  732. * @param {PassState} passState
  733. * @param {DrawCommand[]} commands
  734. * @param {InvertClassification} invertClassification
  735. */
  736. OIT.prototype.executeCommands = function (
  737. scene,
  738. executeFunction,
  739. passState,
  740. commands,
  741. invertClassification,
  742. ) {
  743. if (this._translucentMRTSupport) {
  744. executeTranslucentCommandsSortedMRT(
  745. this,
  746. scene,
  747. executeFunction,
  748. passState,
  749. commands,
  750. invertClassification,
  751. );
  752. return;
  753. }
  754. executeTranslucentCommandsSortedMultipass(
  755. this,
  756. scene,
  757. executeFunction,
  758. passState,
  759. commands,
  760. invertClassification,
  761. );
  762. };
  763. /**
  764. * @private
  765. * @param {Context} context
  766. * @param {PassState} passState
  767. */
  768. OIT.prototype.execute = function (context, passState) {
  769. this._compositeCommand.execute(context, passState);
  770. };
  771. /**
  772. * @private
  773. * @param {Context} context
  774. * @param {PassState} passState
  775. * @param {Color} clearColor
  776. */
  777. OIT.prototype.clear = function (context, passState, clearColor) {
  778. const framebuffer = passState.framebuffer;
  779. passState.framebuffer = this._opaqueFBO.framebuffer;
  780. Color.clone(clearColor, this._opaqueClearCommand.color);
  781. this._opaqueClearCommand.execute(context, passState);
  782. passState.framebuffer = this._translucentFBO.framebuffer;
  783. const translucentClearCommand = this._translucentMRTSupport
  784. ? this._translucentMRTClearCommand
  785. : this._translucentMultipassClearCommand;
  786. translucentClearCommand.execute(context, passState);
  787. if (this._translucentMultipassSupport) {
  788. passState.framebuffer = this._alphaFBO.framebuffer;
  789. this._alphaClearCommand.execute(context, passState);
  790. }
  791. passState.framebuffer = framebuffer;
  792. };
  793. /**
  794. * @private
  795. * @returns {boolean}
  796. */
  797. OIT.prototype.isSupported = function () {
  798. return this._translucentMRTSupport || this._translucentMultipassSupport;
  799. };
  800. /**
  801. * @private
  802. * @returns {boolean}
  803. */
  804. OIT.prototype.isDestroyed = function () {
  805. return false;
  806. };
  807. /**
  808. * @private
  809. */
  810. OIT.prototype.destroy = function () {
  811. destroyResources(this);
  812. if (defined(this._compositeCommand)) {
  813. this._compositeCommand.shaderProgram =
  814. this._compositeCommand.shaderProgram &&
  815. this._compositeCommand.shaderProgram.destroy();
  816. }
  817. if (defined(this._adjustTranslucentCommand)) {
  818. this._adjustTranslucentCommand.shaderProgram =
  819. this._adjustTranslucentCommand.shaderProgram &&
  820. this._adjustTranslucentCommand.shaderProgram.destroy();
  821. }
  822. if (defined(this._adjustAlphaCommand)) {
  823. this._adjustAlphaCommand.shaderProgram =
  824. this._adjustAlphaCommand.shaderProgram &&
  825. this._adjustAlphaCommand.shaderProgram.destroy();
  826. }
  827. return destroyObject(this);
  828. };
  829. export default OIT;