| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892 | import BoundingRectangle from "../Core/BoundingRectangle.js";import Color from "../Core/Color.js";import defined from "../Core/defined.js";import destroyObject from "../Core/destroyObject.js";import PixelFormat from "../Core/PixelFormat.js";import WebGLConstants from "../Core/WebGLConstants.js";import ClearCommand from "../Renderer/ClearCommand.js";import DrawCommand from "../Renderer/DrawCommand.js";import FramebufferManager from "../Renderer/FramebufferManager.js";import PixelDatatype from "../Renderer/PixelDatatype.js";import RenderState from "../Renderer/RenderState.js";import ShaderSource from "../Renderer/ShaderSource.js";import Texture from "../Renderer/Texture.js";import AdjustTranslucentFS from "../Shaders/AdjustTranslucentFS.js";import CompositeOITFS from "../Shaders/CompositeOITFS.js";import BlendEquation from "./BlendEquation.js";import BlendFunction from "./BlendFunction.js";/** * @private */function OIT(context) {  this._numSamples = 1;  // We support multipass for the Chrome D3D9 backend and ES 2.0 on mobile.  this._translucentMultipassSupport = false;  this._translucentMRTSupport = false;  const extensionsSupported = context.colorBufferFloat && context.depthTexture;  this._translucentMRTSupport = context.drawBuffers && extensionsSupported;  this._translucentMultipassSupport =    !this._translucentMRTSupport && extensionsSupported;  this._opaqueFBO = undefined;  this._opaqueTexture = undefined;  this._depthStencilTexture = undefined;  this._accumulationTexture = undefined;  this._translucentFBO = new FramebufferManager({    colorAttachmentsLength: this._translucentMRTSupport ? 2 : 1,    createColorAttachments: false,    createDepthAttachments: false,    depth: true,  });  this._alphaFBO = new FramebufferManager({    createColorAttachments: false,    createDepthAttachments: false,    depth: true,  });  this._adjustTranslucentFBO = new FramebufferManager({    colorAttachmentsLength: this._translucentMRTSupport ? 2 : 1,    createColorAttachments: false,  });  this._adjustAlphaFBO = new FramebufferManager({    createColorAttachments: false,  });  this._opaqueClearCommand = new ClearCommand({    color: new Color(0.0, 0.0, 0.0, 0.0),    owner: this,  });  this._translucentMRTClearCommand = new ClearCommand({    color: new Color(0.0, 0.0, 0.0, 1.0),    owner: this,  });  this._translucentMultipassClearCommand = new ClearCommand({    color: new Color(0.0, 0.0, 0.0, 0.0),    owner: this,  });  this._alphaClearCommand = new ClearCommand({    color: new Color(1.0, 1.0, 1.0, 1.0),    owner: this,  });  this._translucentRenderStateCache = {};  this._alphaRenderStateCache = {};  this._compositeCommand = undefined;  this._adjustTranslucentCommand = undefined;  this._adjustAlphaCommand = undefined;  this._viewport = new BoundingRectangle();  this._rs = undefined;  this._useScissorTest = false;  this._scissorRectangle = undefined;  this._useHDR = false;}function destroyTextures(oit) {  oit._accumulationTexture =    oit._accumulationTexture &&    !oit._accumulationTexture.isDestroyed() &&    oit._accumulationTexture.destroy();  oit._revealageTexture =    oit._revealageTexture &&    !oit._revealageTexture.isDestroyed() &&    oit._revealageTexture.destroy();}function destroyFramebuffers(oit) {  oit._translucentFBO.destroy();  oit._alphaFBO.destroy();  oit._adjustTranslucentFBO.destroy();  oit._adjustAlphaFBO.destroy();}function destroyResources(oit) {  destroyTextures(oit);  destroyFramebuffers(oit);}function updateTextures(oit, context, width, height) {  destroyTextures(oit);  oit._accumulationTexture = new Texture({    context: context,    width: width,    height: height,    pixelFormat: PixelFormat.RGBA,    pixelDatatype: PixelDatatype.FLOAT,  });  // Use zeroed arraybuffer instead of null to initialize texture  // to workaround Firefox. Only needed for the second color attachment.  const source = new Float32Array(width * height * 4);  oit._revealageTexture = new Texture({    context: context,    pixelFormat: PixelFormat.RGBA,    pixelDatatype: PixelDatatype.FLOAT,    source: {      arrayBufferView: source,      width: width,      height: height,    },    flipY: false,  });}function updateFramebuffers(oit, context) {  destroyFramebuffers(oit);  const completeFBO = WebGLConstants.FRAMEBUFFER_COMPLETE;  let supported = true;  const width = oit._accumulationTexture.width;  const height = oit._accumulationTexture.height;  // if MRT is supported, attempt to make an FBO with multiple color attachments  if (oit._translucentMRTSupport) {    oit._translucentFBO.setColorTexture(oit._accumulationTexture, 0);    oit._translucentFBO.setColorTexture(oit._revealageTexture, 1);    oit._translucentFBO.setDepthStencilTexture(oit._depthStencilTexture);    oit._translucentFBO.update(context, width, height);    oit._adjustTranslucentFBO.setColorTexture(oit._accumulationTexture, 0);    oit._adjustTranslucentFBO.setColorTexture(oit._revealageTexture, 1);    oit._adjustTranslucentFBO.update(context, width, height);    if (      oit._translucentFBO.status !== completeFBO ||      oit._adjustTranslucentFBO.status !== completeFBO    ) {      destroyFramebuffers(oit);      oit._translucentMRTSupport = false;    }  }  // either MRT isn't supported or FBO creation failed, attempt multipass  if (!oit._translucentMRTSupport) {    oit._translucentFBO.setColorTexture(oit._accumulationTexture);    oit._translucentFBO.setDepthStencilTexture(oit._depthStencilTexture);    oit._translucentFBO.update(context, width, height);    oit._alphaFBO.setColorTexture(oit._revealageTexture);    oit._alphaFBO.setDepthStencilTexture(oit._depthStencilTexture);    oit._alphaFBO.update(context, width, height);    oit._adjustTranslucentFBO.setColorTexture(oit._accumulationTexture);    oit._adjustTranslucentFBO.update(context, width, height);    oit._adjustAlphaFBO.setColorTexture(oit._revealageTexture);    oit._adjustAlphaFBO.update(context, width, height);    const translucentComplete = oit._translucentFBO.status === completeFBO;    const alphaComplete = oit._alphaFBO.status === completeFBO;    const adjustTranslucentComplete =      oit._adjustTranslucentFBO.status === completeFBO;    const adjustAlphaComplete = oit._adjustAlphaFBO.status === completeFBO;    if (      !translucentComplete ||      !alphaComplete ||      !adjustTranslucentComplete ||      !adjustAlphaComplete    ) {      destroyResources(oit);      oit._translucentMultipassSupport = false;      supported = false;    }  }  return supported;}OIT.prototype.update = function (  context,  passState,  framebuffer,  useHDR,  numSamples) {  if (!this.isSupported()) {    return;  }  this._opaqueFBO = framebuffer;  this._opaqueTexture = framebuffer.getColorTexture(0);  this._depthStencilTexture = framebuffer.getDepthStencilTexture();  const width = this._opaqueTexture.width;  const height = this._opaqueTexture.height;  const accumulationTexture = this._accumulationTexture;  const textureChanged =    !defined(accumulationTexture) ||    accumulationTexture.width !== width ||    accumulationTexture.height !== height ||    useHDR !== this._useHDR;  const samplesChanged = this._numSamples !== numSamples;  if (textureChanged || samplesChanged) {    this._numSamples = numSamples;    updateTextures(this, context, width, height);  }  if (    !defined(this._translucentFBO.framebuffer) ||    textureChanged ||    samplesChanged  ) {    if (!updateFramebuffers(this, context)) {      // framebuffer creation failed      return;    }  }  this._useHDR = useHDR;  const that = this;  let fs;  let uniformMap;  if (!defined(this._compositeCommand)) {    fs = new ShaderSource({      sources: [CompositeOITFS],    });    if (this._translucentMRTSupport) {      fs.defines.push("MRT");    }    uniformMap = {      u_opaque: function () {        return that._opaqueTexture;      },      u_accumulation: function () {        return that._accumulationTexture;      },      u_revealage: function () {        return that._revealageTexture;      },    };    this._compositeCommand = context.createViewportQuadCommand(fs, {      uniformMap: uniformMap,      owner: this,    });  }  if (!defined(this._adjustTranslucentCommand)) {    if (this._translucentMRTSupport) {      fs = new ShaderSource({        defines: ["MRT"],        sources: [AdjustTranslucentFS],      });      uniformMap = {        u_bgColor: function () {          return that._translucentMRTClearCommand.color;        },        u_depthTexture: function () {          return that._depthStencilTexture;        },      };      this._adjustTranslucentCommand = context.createViewportQuadCommand(fs, {        uniformMap: uniformMap,        owner: this,      });    } else if (this._translucentMultipassSupport) {      fs = new ShaderSource({        sources: [AdjustTranslucentFS],      });      uniformMap = {        u_bgColor: function () {          return that._translucentMultipassClearCommand.color;        },        u_depthTexture: function () {          return that._depthStencilTexture;        },      };      this._adjustTranslucentCommand = context.createViewportQuadCommand(fs, {        uniformMap: uniformMap,        owner: this,      });      uniformMap = {        u_bgColor: function () {          return that._alphaClearCommand.color;        },        u_depthTexture: function () {          return that._depthStencilTexture;        },      };      this._adjustAlphaCommand = context.createViewportQuadCommand(fs, {        uniformMap: uniformMap,        owner: this,      });    }  }  this._viewport.width = width;  this._viewport.height = height;  const useScissorTest = !BoundingRectangle.equals(    this._viewport,    passState.viewport  );  let updateScissor = useScissorTest !== this._useScissorTest;  this._useScissorTest = useScissorTest;  if (!BoundingRectangle.equals(this._scissorRectangle, passState.viewport)) {    this._scissorRectangle = BoundingRectangle.clone(      passState.viewport,      this._scissorRectangle    );    updateScissor = true;  }  if (    !defined(this._rs) ||    !BoundingRectangle.equals(this._viewport, this._rs.viewport) ||    updateScissor  ) {    this._rs = RenderState.fromCache({      viewport: this._viewport,      scissorTest: {        enabled: this._useScissorTest,        rectangle: this._scissorRectangle,      },    });  }  if (defined(this._compositeCommand)) {    this._compositeCommand.renderState = this._rs;  }  if (this._adjustTranslucentCommand) {    this._adjustTranslucentCommand.renderState = this._rs;  }  if (defined(this._adjustAlphaCommand)) {    this._adjustAlphaCommand.renderState = this._rs;  }};const translucentMRTBlend = {  enabled: true,  color: new Color(0.0, 0.0, 0.0, 0.0),  equationRgb: BlendEquation.ADD,  equationAlpha: BlendEquation.ADD,  functionSourceRgb: BlendFunction.ONE,  functionDestinationRgb: BlendFunction.ONE,  functionSourceAlpha: BlendFunction.ZERO,  functionDestinationAlpha: BlendFunction.ONE_MINUS_SOURCE_ALPHA,};const translucentColorBlend = {  enabled: true,  color: new Color(0.0, 0.0, 0.0, 0.0),  equationRgb: BlendEquation.ADD,  equationAlpha: BlendEquation.ADD,  functionSourceRgb: BlendFunction.ONE,  functionDestinationRgb: BlendFunction.ONE,  functionSourceAlpha: BlendFunction.ONE,  functionDestinationAlpha: BlendFunction.ONE,};const translucentAlphaBlend = {  enabled: true,  color: new Color(0.0, 0.0, 0.0, 0.0),  equationRgb: BlendEquation.ADD,  equationAlpha: BlendEquation.ADD,  functionSourceRgb: BlendFunction.ZERO,  functionDestinationRgb: BlendFunction.ONE_MINUS_SOURCE_ALPHA,  functionSourceAlpha: BlendFunction.ZERO,  functionDestinationAlpha: BlendFunction.ONE_MINUS_SOURCE_ALPHA,};function getTranslucentRenderState(  context,  translucentBlending,  cache,  renderState) {  let translucentState = cache[renderState.id];  if (!defined(translucentState)) {    const rs = RenderState.getState(renderState);    rs.depthMask = false;    rs.blending = translucentBlending;    translucentState = RenderState.fromCache(rs);    cache[renderState.id] = translucentState;  }  return translucentState;}function getTranslucentMRTRenderState(oit, context, renderState) {  return getTranslucentRenderState(    context,    translucentMRTBlend,    oit._translucentRenderStateCache,    renderState  );}function getTranslucentColorRenderState(oit, context, renderState) {  return getTranslucentRenderState(    context,    translucentColorBlend,    oit._translucentRenderStateCache,    renderState  );}function getTranslucentAlphaRenderState(oit, context, renderState) {  return getTranslucentRenderState(    context,    translucentAlphaBlend,    oit._alphaRenderStateCache,    renderState  );}const mrtShaderSource =  "    vec3 Ci = czm_gl_FragColor.rgb * czm_gl_FragColor.a;\n" +  "    float ai = czm_gl_FragColor.a;\n" +  "    float wzi = czm_alphaWeight(ai);\n" +  "    gl_FragData[0] = vec4(Ci * wzi, ai);\n" +  "    gl_FragData[1] = vec4(ai * wzi);\n";const colorShaderSource =  "    vec3 Ci = czm_gl_FragColor.rgb * czm_gl_FragColor.a;\n" +  "    float ai = czm_gl_FragColor.a;\n" +  "    float wzi = czm_alphaWeight(ai);\n" +  "    gl_FragColor = vec4(Ci, ai) * wzi;\n";const alphaShaderSource =  "    float ai = czm_gl_FragColor.a;\n" + "    gl_FragColor = vec4(ai);\n";function getTranslucentShaderProgram(context, shaderProgram, keyword, source) {  let shader = context.shaderCache.getDerivedShaderProgram(    shaderProgram,    keyword  );  if (!defined(shader)) {    const attributeLocations = shaderProgram._attributeLocations;    const fs = shaderProgram.fragmentShaderSource.clone();    fs.sources = fs.sources.map(function (source) {      source = ShaderSource.replaceMain(source, "czm_translucent_main");      source = source.replace(/gl_FragColor/g, "czm_gl_FragColor");      source = source.replace(/\bdiscard\b/g, "czm_discard = true");      source = source.replace(/czm_phong/g, "czm_translucentPhong");      return source;    });    // Discarding the fragment in main is a workaround for ANGLE D3D9    // shader compilation errors.    fs.sources.splice(      0,      0,      `${        source.indexOf("gl_FragData") !== -1          ? "#extension GL_EXT_draw_buffers : enable \n"          : ""      }vec4 czm_gl_FragColor;\n` + `bool czm_discard = false;\n`    );    fs.sources.push(      `${        "void main()\n" +        "{\n" +        "    czm_translucent_main();\n" +        "    if (czm_discard)\n" +        "    {\n" +        "        discard;\n" +        "    }\n"      }${source}}\n`    );    shader = context.shaderCache.createDerivedShaderProgram(      shaderProgram,      keyword,      {        vertexShaderSource: shaderProgram.vertexShaderSource,        fragmentShaderSource: fs,        attributeLocations: attributeLocations,      }    );  }  return shader;}function getTranslucentMRTShaderProgram(context, shaderProgram) {  return getTranslucentShaderProgram(    context,    shaderProgram,    "translucentMRT",    mrtShaderSource  );}function getTranslucentColorShaderProgram(context, shaderProgram) {  return getTranslucentShaderProgram(    context,    shaderProgram,    "translucentMultipass",    colorShaderSource  );}function getTranslucentAlphaShaderProgram(context, shaderProgram) {  return getTranslucentShaderProgram(    context,    shaderProgram,    "alphaMultipass",    alphaShaderSource  );}OIT.prototype.createDerivedCommands = function (command, context, result) {  if (!defined(result)) {    result = {};  }  if (this._translucentMRTSupport) {    let translucentShader;    let translucentRenderState;    if (defined(result.translucentCommand)) {      translucentShader = result.translucentCommand.shaderProgram;      translucentRenderState = result.translucentCommand.renderState;    }    result.translucentCommand = DrawCommand.shallowClone(      command,      result.translucentCommand    );    if (      !defined(translucentShader) ||      result.shaderProgramId !== command.shaderProgram.id    ) {      result.translucentCommand.shaderProgram = getTranslucentMRTShaderProgram(        context,        command.shaderProgram      );      result.translucentCommand.renderState = getTranslucentMRTRenderState(        this,        context,        command.renderState      );      result.shaderProgramId = command.shaderProgram.id;    } else {      result.translucentCommand.shaderProgram = translucentShader;      result.translucentCommand.renderState = translucentRenderState;    }  } else {    let colorShader;    let colorRenderState;    let alphaShader;    let alphaRenderState;    if (defined(result.translucentCommand)) {      colorShader = result.translucentCommand.shaderProgram;      colorRenderState = result.translucentCommand.renderState;      alphaShader = result.alphaCommand.shaderProgram;      alphaRenderState = result.alphaCommand.renderState;    }    result.translucentCommand = DrawCommand.shallowClone(      command,      result.translucentCommand    );    result.alphaCommand = DrawCommand.shallowClone(      command,      result.alphaCommand    );    if (      !defined(colorShader) ||      result.shaderProgramId !== command.shaderProgram.id    ) {      result.translucentCommand.shaderProgram = getTranslucentColorShaderProgram(        context,        command.shaderProgram      );      result.translucentCommand.renderState = getTranslucentColorRenderState(        this,        context,        command.renderState      );      result.alphaCommand.shaderProgram = getTranslucentAlphaShaderProgram(        context,        command.shaderProgram      );      result.alphaCommand.renderState = getTranslucentAlphaRenderState(        this,        context,        command.renderState      );      result.shaderProgramId = command.shaderProgram.id;    } else {      result.translucentCommand.shaderProgram = colorShader;      result.translucentCommand.renderState = colorRenderState;      result.alphaCommand.shaderProgram = alphaShader;      result.alphaCommand.renderState = alphaRenderState;    }  }  return result;};function executeTranslucentCommandsSortedMultipass(  oit,  scene,  executeFunction,  passState,  commands,  invertClassification) {  let command;  let derivedCommand;  let j;  const context = scene.context;  const useLogDepth = scene.frameState.useLogDepth;  const useHdr = scene._hdr;  const framebuffer = passState.framebuffer;  const length = commands.length;  const lightShadowsEnabled = scene.frameState.shadowState.lightShadowsEnabled;  passState.framebuffer = oit._adjustTranslucentFBO.framebuffer;  oit._adjustTranslucentCommand.execute(context, passState);  passState.framebuffer = oit._adjustAlphaFBO.framebuffer;  oit._adjustAlphaCommand.execute(context, passState);  const debugFramebuffer = oit._opaqueFBO.framebuffer;  passState.framebuffer = oit._translucentFBO.framebuffer;  for (j = 0; j < length; ++j) {    command = commands[j];    command = useLogDepth ? command.derivedCommands.logDepth.command : command;    command = useHdr ? command.derivedCommands.hdr.command : command;    derivedCommand =      lightShadowsEnabled && command.receiveShadows        ? command.derivedCommands.oit.shadows.translucentCommand        : command.derivedCommands.oit.translucentCommand;    executeFunction(      derivedCommand,      scene,      context,      passState,      debugFramebuffer    );  }  if (defined(invertClassification)) {    command = invertClassification.unclassifiedCommand;    derivedCommand =      lightShadowsEnabled && command.receiveShadows        ? command.derivedCommands.oit.shadows.translucentCommand        : command.derivedCommands.oit.translucentCommand;    executeFunction(      derivedCommand,      scene,      context,      passState,      debugFramebuffer    );  }  passState.framebuffer = oit._alphaFBO.framebuffer;  for (j = 0; j < length; ++j) {    command = commands[j];    command = useLogDepth ? command.derivedCommands.logDepth.command : command;    command = useHdr ? command.derivedCommands.hdr.command : command;    derivedCommand =      lightShadowsEnabled && command.receiveShadows        ? command.derivedCommands.oit.shadows.alphaCommand        : command.derivedCommands.oit.alphaCommand;    executeFunction(      derivedCommand,      scene,      context,      passState,      debugFramebuffer    );  }  if (defined(invertClassification)) {    command = invertClassification.unclassifiedCommand;    derivedCommand =      lightShadowsEnabled && command.receiveShadows        ? command.derivedCommands.oit.shadows.alphaCommand        : command.derivedCommands.oit.alphaCommand;    executeFunction(      derivedCommand,      scene,      context,      passState,      debugFramebuffer    );  }  passState.framebuffer = framebuffer;}function executeTranslucentCommandsSortedMRT(  oit,  scene,  executeFunction,  passState,  commands,  invertClassification) {  const context = scene.context;  const useLogDepth = scene.frameState.useLogDepth;  const useHdr = scene._hdr;  const framebuffer = passState.framebuffer;  const length = commands.length;  const lightShadowsEnabled = scene.frameState.shadowState.lightShadowsEnabled;  passState.framebuffer = oit._adjustTranslucentFBO.framebuffer;  oit._adjustTranslucentCommand.execute(context, passState);  const debugFramebuffer = oit._opaqueFBO.framebuffer;  passState.framebuffer = oit._translucentFBO.framebuffer;  let command;  let derivedCommand;  for (let j = 0; j < length; ++j) {    command = commands[j];    command = useLogDepth ? command.derivedCommands.logDepth.command : command;    command = useHdr ? command.derivedCommands.hdr.command : command;    derivedCommand =      lightShadowsEnabled && command.receiveShadows        ? command.derivedCommands.oit.shadows.translucentCommand        : command.derivedCommands.oit.translucentCommand;    executeFunction(      derivedCommand,      scene,      context,      passState,      debugFramebuffer    );  }  if (defined(invertClassification)) {    command = invertClassification.unclassifiedCommand;    derivedCommand =      lightShadowsEnabled && command.receiveShadows        ? command.derivedCommands.oit.shadows.translucentCommand        : command.derivedCommands.oit.translucentCommand;    executeFunction(      derivedCommand,      scene,      context,      passState,      debugFramebuffer    );  }  passState.framebuffer = framebuffer;}OIT.prototype.executeCommands = function (  scene,  executeFunction,  passState,  commands,  invertClassification) {  if (this._translucentMRTSupport) {    executeTranslucentCommandsSortedMRT(      this,      scene,      executeFunction,      passState,      commands,      invertClassification    );    return;  }  executeTranslucentCommandsSortedMultipass(    this,    scene,    executeFunction,    passState,    commands,    invertClassification  );};OIT.prototype.execute = function (context, passState) {  this._compositeCommand.execute(context, passState);};OIT.prototype.clear = function (context, passState, clearColor) {  const framebuffer = passState.framebuffer;  passState.framebuffer = this._opaqueFBO.framebuffer;  Color.clone(clearColor, this._opaqueClearCommand.color);  this._opaqueClearCommand.execute(context, passState);  passState.framebuffer = this._translucentFBO.framebuffer;  const translucentClearCommand = this._translucentMRTSupport    ? this._translucentMRTClearCommand    : this._translucentMultipassClearCommand;  translucentClearCommand.execute(context, passState);  if (this._translucentMultipassSupport) {    passState.framebuffer = this._alphaFBO.framebuffer;    this._alphaClearCommand.execute(context, passState);  }  passState.framebuffer = framebuffer;};OIT.prototype.isSupported = function () {  return this._translucentMRTSupport || this._translucentMultipassSupport;};OIT.prototype.isDestroyed = function () {  return false;};OIT.prototype.destroy = function () {  destroyResources(this);  if (defined(this._compositeCommand)) {    this._compositeCommand.shaderProgram =      this._compositeCommand.shaderProgram &&      this._compositeCommand.shaderProgram.destroy();  }  if (defined(this._adjustTranslucentCommand)) {    this._adjustTranslucentCommand.shaderProgram =      this._adjustTranslucentCommand.shaderProgram &&      this._adjustTranslucentCommand.shaderProgram.destroy();  }  if (defined(this._adjustAlphaCommand)) {    this._adjustAlphaCommand.shaderProgram =      this._adjustAlphaCommand.shaderProgram &&      this._adjustAlphaCommand.shaderProgram.destroy();  }  return destroyObject(this);};export default OIT;
 |