OIT.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  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 = !this._translucentMRTSupport && extensionsSupported;
  28. this._opaqueFBO = undefined;
  29. this._opaqueTexture = undefined;
  30. this._depthStencilTexture = undefined;
  31. this._accumulationTexture = undefined;
  32. this._translucentFBO = undefined;
  33. this._alphaFBO = undefined;
  34. this._adjustTranslucentFBO = undefined;
  35. this._adjustAlphaFBO = undefined;
  36. this._opaqueClearCommand = new ClearCommand({
  37. color : new Color(0.0, 0.0, 0.0, 0.0),
  38. owner : this
  39. });
  40. this._translucentMRTClearCommand = new ClearCommand({
  41. color : new Color(0.0, 0.0, 0.0, 1.0),
  42. owner : this
  43. });
  44. this._translucentMultipassClearCommand = new ClearCommand({
  45. color : new Color(0.0, 0.0, 0.0, 0.0),
  46. owner : this
  47. });
  48. this._alphaClearCommand = new ClearCommand({
  49. color : new Color(1.0, 1.0, 1.0, 1.0),
  50. owner : this
  51. });
  52. this._translucentRenderStateCache = {};
  53. this._alphaRenderStateCache = {};
  54. this._compositeCommand = undefined;
  55. this._adjustTranslucentCommand = undefined;
  56. this._adjustAlphaCommand = undefined;
  57. this._viewport = new BoundingRectangle();
  58. this._rs = undefined;
  59. this._useScissorTest = false;
  60. this._scissorRectangle = undefined;
  61. this._useHDR = false;
  62. }
  63. function destroyTextures(oit) {
  64. oit._accumulationTexture = oit._accumulationTexture && !oit._accumulationTexture.isDestroyed() && oit._accumulationTexture.destroy();
  65. oit._revealageTexture = oit._revealageTexture && !oit._revealageTexture.isDestroyed() && oit._revealageTexture.destroy();
  66. }
  67. function destroyFramebuffers(oit) {
  68. oit._translucentFBO = oit._translucentFBO && !oit._translucentFBO.isDestroyed() && oit._translucentFBO.destroy();
  69. oit._alphaFBO = oit._alphaFBO && !oit._alphaFBO.isDestroyed() && oit._alphaFBO.destroy();
  70. oit._adjustTranslucentFBO = oit._adjustTranslucentFBO && !oit._adjustTranslucentFBO.isDestroyed() && oit._adjustTranslucentFBO.destroy();
  71. oit._adjustAlphaFBO = oit._adjustAlphaFBO && !oit._adjustAlphaFBO.isDestroyed() && oit._adjustAlphaFBO.destroy();
  72. }
  73. function destroyResources(oit) {
  74. destroyTextures(oit);
  75. destroyFramebuffers(oit);
  76. }
  77. function updateTextures(oit, context, width, height) {
  78. destroyTextures(oit);
  79. oit._accumulationTexture = new Texture({
  80. context : context,
  81. width : width,
  82. height : height,
  83. pixelFormat : PixelFormat.RGBA,
  84. pixelDatatype : PixelDatatype.FLOAT
  85. });
  86. // Use zeroed arraybuffer instead of null to initialize texture
  87. // to workaround Firefox. Only needed for the second color attachment.
  88. var source = new Float32Array(width * height * 4);
  89. oit._revealageTexture = new Texture({
  90. context : context,
  91. pixelFormat : PixelFormat.RGBA,
  92. pixelDatatype : PixelDatatype.FLOAT,
  93. source : {
  94. arrayBufferView : source,
  95. width : width,
  96. height : height
  97. },
  98. flipY : false
  99. });
  100. }
  101. function updateFramebuffers(oit, context) {
  102. destroyFramebuffers(oit);
  103. var completeFBO = WebGLConstants.FRAMEBUFFER_COMPLETE;
  104. var supported = true;
  105. // if MRT is supported, attempt to make an FBO with multiple color attachments
  106. if (oit._translucentMRTSupport) {
  107. oit._translucentFBO = new Framebuffer({
  108. context : context,
  109. colorTextures : [oit._accumulationTexture, oit._revealageTexture],
  110. depthStencilTexture : oit._depthStencilTexture,
  111. destroyAttachments : false
  112. });
  113. oit._adjustTranslucentFBO = new Framebuffer({
  114. context : context,
  115. colorTextures : [oit._accumulationTexture, oit._revealageTexture],
  116. destroyAttachments : false
  117. });
  118. if (oit._translucentFBO.status !== completeFBO || oit._adjustTranslucentFBO.status !== completeFBO) {
  119. destroyFramebuffers(oit);
  120. oit._translucentMRTSupport = false;
  121. }
  122. }
  123. // either MRT isn't supported or FBO creation failed, attempt multipass
  124. if (!oit._translucentMRTSupport) {
  125. oit._translucentFBO = new Framebuffer({
  126. context : context,
  127. colorTextures : [oit._accumulationTexture],
  128. depthStencilTexture : oit._depthStencilTexture,
  129. destroyAttachments : false
  130. });
  131. oit._alphaFBO = new Framebuffer({
  132. context : context,
  133. colorTextures : [oit._revealageTexture],
  134. depthStencilTexture : oit._depthStencilTexture,
  135. destroyAttachments : false
  136. });
  137. oit._adjustTranslucentFBO = new Framebuffer({
  138. context : context,
  139. colorTextures : [oit._accumulationTexture],
  140. destroyAttachments : false
  141. });
  142. oit._adjustAlphaFBO = new Framebuffer({
  143. context : context,
  144. colorTextures : [oit._revealageTexture],
  145. destroyAttachments : false
  146. });
  147. var translucentComplete = oit._translucentFBO.status === completeFBO;
  148. var alphaComplete = oit._alphaFBO.status === completeFBO;
  149. var adjustTranslucentComplete = oit._adjustTranslucentFBO.status === completeFBO;
  150. var adjustAlphaComplete = oit._adjustAlphaFBO.status === completeFBO;
  151. if (!translucentComplete || !alphaComplete || !adjustTranslucentComplete || !adjustAlphaComplete) {
  152. destroyResources(oit);
  153. oit._translucentMultipassSupport = false;
  154. supported = false;
  155. }
  156. }
  157. return supported;
  158. }
  159. OIT.prototype.update = function(context, passState, framebuffer, useHDR) {
  160. if (!this.isSupported()) {
  161. return;
  162. }
  163. this._opaqueFBO = framebuffer;
  164. this._opaqueTexture = framebuffer.getColorTexture(0);
  165. this._depthStencilTexture = framebuffer.depthStencilTexture;
  166. var width = this._opaqueTexture.width;
  167. var height = this._opaqueTexture.height;
  168. var accumulationTexture = this._accumulationTexture;
  169. var textureChanged = !defined(accumulationTexture) || accumulationTexture.width !== width || accumulationTexture.height !== height || useHDR !== this._useHDR;
  170. if (textureChanged) {
  171. updateTextures(this, context, width, height);
  172. }
  173. if (!defined(this._translucentFBO) || textureChanged) {
  174. if (!updateFramebuffers(this, context)) {
  175. // framebuffer creation failed
  176. return;
  177. }
  178. }
  179. this._useHDR = useHDR;
  180. var that = this;
  181. var fs;
  182. var uniformMap;
  183. if (!defined(this._compositeCommand)) {
  184. fs = new ShaderSource({
  185. sources : [CompositeOITFS]
  186. });
  187. if (this._translucentMRTSupport) {
  188. fs.defines.push('MRT');
  189. }
  190. uniformMap = {
  191. u_opaque : function() {
  192. return that._opaqueTexture;
  193. },
  194. u_accumulation : function() {
  195. return that._accumulationTexture;
  196. },
  197. u_revealage : function() {
  198. return that._revealageTexture;
  199. }
  200. };
  201. this._compositeCommand = context.createViewportQuadCommand(fs, {
  202. uniformMap : uniformMap,
  203. owner : this
  204. });
  205. }
  206. if (!defined(this._adjustTranslucentCommand)) {
  207. if (this._translucentMRTSupport) {
  208. fs = new ShaderSource({
  209. defines : ['MRT'],
  210. sources : [AdjustTranslucentFS]
  211. });
  212. uniformMap = {
  213. u_bgColor : function() {
  214. return that._translucentMRTClearCommand.color;
  215. },
  216. u_depthTexture : function() {
  217. return that._depthStencilTexture;
  218. }
  219. };
  220. this._adjustTranslucentCommand = context.createViewportQuadCommand(fs, {
  221. uniformMap : uniformMap,
  222. owner : this
  223. });
  224. } else if (this._translucentMultipassSupport) {
  225. fs = new ShaderSource({
  226. sources : [AdjustTranslucentFS]
  227. });
  228. uniformMap = {
  229. u_bgColor : function() {
  230. return that._translucentMultipassClearCommand.color;
  231. },
  232. u_depthTexture : function() {
  233. return that._depthStencilTexture;
  234. }
  235. };
  236. this._adjustTranslucentCommand = context.createViewportQuadCommand(fs, {
  237. uniformMap : uniformMap,
  238. owner : this
  239. });
  240. uniformMap = {
  241. u_bgColor : function() {
  242. return that._alphaClearCommand.color;
  243. },
  244. u_depthTexture : function() {
  245. return that._depthStencilTexture;
  246. }
  247. };
  248. this._adjustAlphaCommand = context.createViewportQuadCommand(fs, {
  249. uniformMap : uniformMap,
  250. owner : this
  251. });
  252. }
  253. }
  254. this._viewport.width = width;
  255. this._viewport.height = height;
  256. var useScissorTest = !BoundingRectangle.equals(this._viewport, passState.viewport);
  257. var updateScissor = useScissorTest !== this._useScissorTest;
  258. this._useScissorTest = useScissorTest;
  259. if (!BoundingRectangle.equals(this._scissorRectangle, passState.viewport)) {
  260. this._scissorRectangle = BoundingRectangle.clone(passState.viewport, this._scissorRectangle);
  261. updateScissor = true;
  262. }
  263. if (!defined(this._rs) || !BoundingRectangle.equals(this._viewport, this._rs.viewport) || updateScissor) {
  264. this._rs = RenderState.fromCache({
  265. viewport : this._viewport,
  266. scissorTest : {
  267. enabled : this._useScissorTest,
  268. rectangle : this._scissorRectangle
  269. }
  270. });
  271. }
  272. if (defined(this._compositeCommand)) {
  273. this._compositeCommand.renderState = this._rs;
  274. }
  275. if (this._adjustTranslucentCommand) {
  276. this._adjustTranslucentCommand.renderState = this._rs;
  277. }
  278. if (defined(this._adjustAlphaCommand)) {
  279. this._adjustAlphaCommand.renderState = this._rs;
  280. }
  281. };
  282. var translucentMRTBlend = {
  283. enabled : true,
  284. color : new Color(0.0, 0.0, 0.0, 0.0),
  285. equationRgb : BlendEquation.ADD,
  286. equationAlpha : BlendEquation.ADD,
  287. functionSourceRgb : BlendFunction.ONE,
  288. functionDestinationRgb : BlendFunction.ONE,
  289. functionSourceAlpha : BlendFunction.ZERO,
  290. functionDestinationAlpha : BlendFunction.ONE_MINUS_SOURCE_ALPHA
  291. };
  292. var translucentColorBlend = {
  293. enabled : true,
  294. color : new Color(0.0, 0.0, 0.0, 0.0),
  295. equationRgb : BlendEquation.ADD,
  296. equationAlpha : BlendEquation.ADD,
  297. functionSourceRgb : BlendFunction.ONE,
  298. functionDestinationRgb : BlendFunction.ONE,
  299. functionSourceAlpha : BlendFunction.ONE,
  300. functionDestinationAlpha : BlendFunction.ONE
  301. };
  302. var translucentAlphaBlend = {
  303. enabled : true,
  304. color : new Color(0.0, 0.0, 0.0, 0.0),
  305. equationRgb : BlendEquation.ADD,
  306. equationAlpha : BlendEquation.ADD,
  307. functionSourceRgb : BlendFunction.ZERO,
  308. functionDestinationRgb : BlendFunction.ONE_MINUS_SOURCE_ALPHA,
  309. functionSourceAlpha : BlendFunction.ZERO,
  310. functionDestinationAlpha : BlendFunction.ONE_MINUS_SOURCE_ALPHA
  311. };
  312. function getTranslucentRenderState(context, translucentBlending, cache, renderState) {
  313. var translucentState = cache[renderState.id];
  314. if (!defined(translucentState)) {
  315. var rs = RenderState.getState(renderState);
  316. rs.depthMask = false;
  317. rs.blending = translucentBlending;
  318. translucentState = RenderState.fromCache(rs);
  319. cache[renderState.id] = translucentState;
  320. }
  321. return translucentState;
  322. }
  323. function getTranslucentMRTRenderState(oit, context, renderState) {
  324. return getTranslucentRenderState(context, translucentMRTBlend, oit._translucentRenderStateCache, renderState);
  325. }
  326. function getTranslucentColorRenderState(oit, context, renderState) {
  327. return getTranslucentRenderState(context, translucentColorBlend, oit._translucentRenderStateCache, renderState);
  328. }
  329. function getTranslucentAlphaRenderState(oit, context, renderState) {
  330. return getTranslucentRenderState(context, translucentAlphaBlend, oit._alphaRenderStateCache, renderState);
  331. }
  332. var mrtShaderSource =
  333. ' vec3 Ci = czm_gl_FragColor.rgb * czm_gl_FragColor.a;\n' +
  334. ' float ai = czm_gl_FragColor.a;\n' +
  335. ' float wzi = czm_alphaWeight(ai);\n' +
  336. ' gl_FragData[0] = vec4(Ci * wzi, ai);\n' +
  337. ' gl_FragData[1] = vec4(ai * wzi);\n';
  338. var colorShaderSource =
  339. ' vec3 Ci = czm_gl_FragColor.rgb * czm_gl_FragColor.a;\n' +
  340. ' float ai = czm_gl_FragColor.a;\n' +
  341. ' float wzi = czm_alphaWeight(ai);\n' +
  342. ' gl_FragColor = vec4(Ci, ai) * wzi;\n';
  343. var alphaShaderSource =
  344. ' float ai = czm_gl_FragColor.a;\n' +
  345. ' gl_FragColor = vec4(ai);\n';
  346. function getTranslucentShaderProgram(context, shaderProgram, keyword, source) {
  347. var shader = context.shaderCache.getDerivedShaderProgram(shaderProgram, keyword);
  348. if (!defined(shader)) {
  349. var attributeLocations = shaderProgram._attributeLocations;
  350. var fs = shaderProgram.fragmentShaderSource.clone();
  351. fs.sources = fs.sources.map(function(source) {
  352. source = ShaderSource.replaceMain(source, 'czm_translucent_main');
  353. source = source.replace(/gl_FragColor/g, 'czm_gl_FragColor');
  354. source = source.replace(/\bdiscard\b/g, 'czm_discard = true');
  355. source = source.replace(/czm_phong/g, 'czm_translucentPhong');
  356. return source;
  357. });
  358. // Discarding the fragment in main is a workaround for ANGLE D3D9
  359. // shader compilation errors.
  360. fs.sources.splice(0, 0,
  361. (source.indexOf('gl_FragData') !== -1 ? '#extension GL_EXT_draw_buffers : enable \n' : '') +
  362. 'vec4 czm_gl_FragColor;\n' +
  363. 'bool czm_discard = false;\n');
  364. fs.sources.push(
  365. 'void main()\n' +
  366. '{\n' +
  367. ' czm_translucent_main();\n' +
  368. ' if (czm_discard)\n' +
  369. ' {\n' +
  370. ' discard;\n' +
  371. ' }\n' +
  372. source +
  373. '}\n');
  374. shader = context.shaderCache.createDerivedShaderProgram(shaderProgram, keyword, {
  375. vertexShaderSource : shaderProgram.vertexShaderSource,
  376. fragmentShaderSource : fs,
  377. attributeLocations : attributeLocations
  378. });
  379. }
  380. return shader;
  381. }
  382. function getTranslucentMRTShaderProgram(context, shaderProgram) {
  383. return getTranslucentShaderProgram(context, shaderProgram, 'translucentMRT', mrtShaderSource);
  384. }
  385. function getTranslucentColorShaderProgram(context, shaderProgram) {
  386. return getTranslucentShaderProgram(context, shaderProgram, 'translucentMultipass', colorShaderSource);
  387. }
  388. function getTranslucentAlphaShaderProgram(context, shaderProgram) {
  389. return getTranslucentShaderProgram(context, shaderProgram, 'alphaMultipass', alphaShaderSource);
  390. }
  391. OIT.prototype.createDerivedCommands = function(command, context, result) {
  392. if (!defined(result)) {
  393. result = {};
  394. }
  395. if (this._translucentMRTSupport) {
  396. var translucentShader;
  397. var translucentRenderState;
  398. if (defined(result.translucentCommand)) {
  399. translucentShader = result.translucentCommand.shaderProgram;
  400. translucentRenderState = result.translucentCommand.renderState;
  401. }
  402. result.translucentCommand = DrawCommand.shallowClone(command, result.translucentCommand);
  403. if (!defined(translucentShader) || result.shaderProgramId !== command.shaderProgram.id) {
  404. result.translucentCommand.shaderProgram = getTranslucentMRTShaderProgram(context, command.shaderProgram);
  405. result.translucentCommand.renderState = getTranslucentMRTRenderState(this, context, command.renderState);
  406. result.shaderProgramId = command.shaderProgram.id;
  407. } else {
  408. result.translucentCommand.shaderProgram = translucentShader;
  409. result.translucentCommand.renderState = translucentRenderState;
  410. }
  411. } else {
  412. var colorShader;
  413. var colorRenderState;
  414. var alphaShader;
  415. var alphaRenderState;
  416. if (defined(result.translucentCommand)) {
  417. colorShader = result.translucentCommand.shaderProgram;
  418. colorRenderState = result.translucentCommand.renderState;
  419. alphaShader = result.alphaCommand.shaderProgram;
  420. alphaRenderState = result.alphaCommand.renderState;
  421. }
  422. result.translucentCommand = DrawCommand.shallowClone(command, result.translucentCommand);
  423. result.alphaCommand = DrawCommand.shallowClone(command, result.alphaCommand);
  424. if (!defined(colorShader) || result.shaderProgramId !== command.shaderProgram.id) {
  425. result.translucentCommand.shaderProgram = getTranslucentColorShaderProgram(context, command.shaderProgram);
  426. result.translucentCommand.renderState = getTranslucentColorRenderState(this, context, command.renderState);
  427. result.alphaCommand.shaderProgram = getTranslucentAlphaShaderProgram(context, command.shaderProgram);
  428. result.alphaCommand.renderState = getTranslucentAlphaRenderState(this, context, command.renderState);
  429. result.shaderProgramId = command.shaderProgram.id;
  430. } else {
  431. result.translucentCommand.shaderProgram = colorShader;
  432. result.translucentCommand.renderState = colorRenderState;
  433. result.alphaCommand.shaderProgram = alphaShader;
  434. result.alphaCommand.renderState = alphaRenderState;
  435. }
  436. }
  437. return result;
  438. };
  439. function executeTranslucentCommandsSortedMultipass(oit, scene, executeFunction, passState, commands, invertClassification) {
  440. var command;
  441. var derivedCommand;
  442. var j;
  443. var context = scene.context;
  444. var useLogDepth = scene.frameState.useLogDepth;
  445. var useHdr = scene._hdr;
  446. var framebuffer = passState.framebuffer;
  447. var length = commands.length;
  448. var lightShadowsEnabled = scene.frameState.shadowState.lightShadowsEnabled;
  449. passState.framebuffer = oit._adjustTranslucentFBO;
  450. oit._adjustTranslucentCommand.execute(context, passState);
  451. passState.framebuffer = oit._adjustAlphaFBO;
  452. oit._adjustAlphaCommand.execute(context, passState);
  453. var debugFramebuffer = oit._opaqueFBO;
  454. passState.framebuffer = oit._translucentFBO;
  455. for (j = 0; j < length; ++j) {
  456. command = commands[j];
  457. command = useLogDepth ? command.derivedCommands.logDepth.command : command;
  458. command = useHdr ? command.derivedCommands.hdr.command : command;
  459. derivedCommand = (lightShadowsEnabled && command.receiveShadows) ? command.derivedCommands.oit.shadows.translucentCommand : command.derivedCommands.oit.translucentCommand;
  460. executeFunction(derivedCommand, scene, context, passState, debugFramebuffer);
  461. }
  462. if (defined(invertClassification)) {
  463. command = invertClassification.unclassifiedCommand;
  464. derivedCommand = (lightShadowsEnabled && command.receiveShadows) ? command.derivedCommands.oit.shadows.translucentCommand : command.derivedCommands.oit.translucentCommand;
  465. executeFunction(derivedCommand, scene, context, passState, debugFramebuffer);
  466. }
  467. passState.framebuffer = oit._alphaFBO;
  468. for (j = 0; j < length; ++j) {
  469. command = commands[j];
  470. command = useLogDepth ? command.derivedCommands.logDepth.command : command;
  471. command = useHdr ? command.derivedCommands.hdr.command : command;
  472. derivedCommand = (lightShadowsEnabled && command.receiveShadows) ? command.derivedCommands.oit.shadows.alphaCommand : command.derivedCommands.oit.alphaCommand;
  473. executeFunction(derivedCommand, scene, context, passState, debugFramebuffer);
  474. }
  475. if (defined(invertClassification)) {
  476. command = invertClassification.unclassifiedCommand;
  477. derivedCommand = (lightShadowsEnabled && command.receiveShadows) ? command.derivedCommands.oit.shadows.alphaCommand : command.derivedCommands.oit.alphaCommand;
  478. executeFunction(derivedCommand, scene, context, passState, debugFramebuffer);
  479. }
  480. passState.framebuffer = framebuffer;
  481. }
  482. function executeTranslucentCommandsSortedMRT(oit, scene, executeFunction, passState, commands, invertClassification) {
  483. var context = scene.context;
  484. var useLogDepth = scene.frameState.useLogDepth;
  485. var useHdr = scene._hdr;
  486. var framebuffer = passState.framebuffer;
  487. var length = commands.length;
  488. var lightShadowsEnabled = scene.frameState.shadowState.lightShadowsEnabled;
  489. passState.framebuffer = oit._adjustTranslucentFBO;
  490. oit._adjustTranslucentCommand.execute(context, passState);
  491. var debugFramebuffer = oit._opaqueFBO;
  492. passState.framebuffer = oit._translucentFBO;
  493. var command;
  494. var derivedCommand;
  495. for (var j = 0; j < length; ++j) {
  496. command = commands[j];
  497. command = useLogDepth ? command.derivedCommands.logDepth.command : command;
  498. command = useHdr ? command.derivedCommands.hdr.command : command;
  499. derivedCommand = (lightShadowsEnabled && command.receiveShadows) ? command.derivedCommands.oit.shadows.translucentCommand : command.derivedCommands.oit.translucentCommand;
  500. executeFunction(derivedCommand, scene, context, passState, debugFramebuffer);
  501. }
  502. if (defined(invertClassification)) {
  503. command = invertClassification.unclassifiedCommand;
  504. derivedCommand = (lightShadowsEnabled && command.receiveShadows) ? command.derivedCommands.oit.shadows.translucentCommand : command.derivedCommands.oit.translucentCommand;
  505. executeFunction(derivedCommand, scene, context, passState, debugFramebuffer);
  506. }
  507. passState.framebuffer = framebuffer;
  508. }
  509. OIT.prototype.executeCommands = function(scene, executeFunction, passState, commands, invertClassification) {
  510. if (this._translucentMRTSupport) {
  511. executeTranslucentCommandsSortedMRT(this, scene, executeFunction, passState, commands, invertClassification);
  512. return;
  513. }
  514. executeTranslucentCommandsSortedMultipass(this, scene, executeFunction, passState, commands, invertClassification);
  515. };
  516. OIT.prototype.execute = function(context, passState) {
  517. this._compositeCommand.execute(context, passState);
  518. };
  519. OIT.prototype.clear = function(context, passState, clearColor) {
  520. var framebuffer = passState.framebuffer;
  521. passState.framebuffer = this._opaqueFBO;
  522. Color.clone(clearColor, this._opaqueClearCommand.color);
  523. this._opaqueClearCommand.execute(context, passState);
  524. passState.framebuffer = this._translucentFBO;
  525. var translucentClearCommand = this._translucentMRTSupport ? this._translucentMRTClearCommand : this._translucentMultipassClearCommand;
  526. translucentClearCommand.execute(context, passState);
  527. if (this._translucentMultipassSupport) {
  528. passState.framebuffer = this._alphaFBO;
  529. this._alphaClearCommand.execute(context, passState);
  530. }
  531. passState.framebuffer = framebuffer;
  532. };
  533. OIT.prototype.isSupported = function() {
  534. return this._translucentMRTSupport || this._translucentMultipassSupport;
  535. };
  536. OIT.prototype.isDestroyed = function() {
  537. return false;
  538. };
  539. OIT.prototype.destroy = function() {
  540. destroyResources(this);
  541. if (defined(this._compositeCommand)) {
  542. this._compositeCommand.shaderProgram = this._compositeCommand.shaderProgram && this._compositeCommand.shaderProgram.destroy();
  543. }
  544. if (defined(this._adjustTranslucentCommand)) {
  545. this._adjustTranslucentCommand.shaderProgram = this._adjustTranslucentCommand.shaderProgram && this._adjustTranslucentCommand.shaderProgram.destroy();
  546. }
  547. if (defined(this._adjustAlphaCommand)) {
  548. this._adjustAlphaCommand.shaderProgram = this._adjustAlphaCommand.shaderProgram && this._adjustAlphaCommand.shaderProgram.destroy();
  549. }
  550. return destroyObject(this);
  551. };
  552. export default OIT;