OIT.js 24 KB

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