123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593 |
- define([
- '../Core/Color',
- '../Core/defined',
- '../Core/destroyObject',
- '../Core/PixelFormat',
- '../Renderer/ClearCommand',
- '../Renderer/PixelDatatype',
- '../Renderer/RenderState',
- '../Renderer/ShaderSource',
- '../Shaders/AdjustTranslucentFS',
- '../Shaders/CompositeOITFS',
- './BlendEquation',
- './BlendFunction'
- ], function(
- Color,
- defined,
- destroyObject,
- PixelFormat,
- ClearCommand,
- PixelDatatype,
- RenderState,
- ShaderSource,
- AdjustTranslucentFS,
- CompositeOITFS,
- BlendEquation,
- BlendFunction) {
- "use strict";
-
-
- var OIT = function(context) {
- var extensionsSupported = context.floatingPointTexture && context.depthTexture;
- this._translucentMRTSupport = context.drawBuffers && extensionsSupported;
-
- this._translucentMultipassSupport = !this._translucentMRTSupport && extensionsSupported;
- this._opaqueTexture = undefined;
- this._accumulationTexture = undefined;
- this._depthTexture = undefined;
- this._opaqueFBO = undefined;
- this._translucentFBO = undefined;
- this._alphaFBO = undefined;
- this._adjustTranslucentFBO = undefined;
- this._adjustAlphaFBO = undefined;
- 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._translucentShaderCache = {};
- this._alphaShaderCache = {};
- this._compositeCommand = undefined;
- this._adjustTranslucentCommand = undefined;
- this._adjustAlphaCommand = undefined;
- };
- function destroyTextures(oit) {
- oit._opaqueTexture = oit._opaqueTexture && !oit._opaqueTexture.isDestroyed() && oit._opaqueTexture.destroy();
- oit._accumulationTexture = oit._accumulationTexture && !oit._accumulationTexture.isDestroyed() && oit._accumulationTexture.destroy();
- oit._revealageTexture = oit._revealageTexture && !oit._revealageTexture.isDestroyed() && oit._revealageTexture.destroy();
- oit._depthTexture = oit._depthTexture && !oit._depthTexture.isDestroyed() && oit._depthTexture.destroy();
- }
- function destroyFramebuffers(oit) {
- oit._opaqueFBO = oit._opaqueFBO && !oit._opaqueFBO.isDestroyed() && oit._opaqueFBO.destroy();
- oit._translucentFBO = oit._translucentFBO && !oit._translucentFBO.isDestroyed() && oit._translucentFBO.destroy();
- oit._alphaFBO = oit._alphaFBO && !oit._alphaFBO.isDestroyed() && oit._alphaFBO.destroy();
- oit._adjustTranslucentFBO = oit._adjustTranslucentFBO && !oit._adjustTranslucentFBO.isDestroyed() && oit._adjustTranslucentFBO.destroy();
- oit._adjustAlphaFBO = oit._adjustAlphaFBO && !oit._adjustAlphaFBO.isDestroyed() && oit._adjustAlphaFBO.destroy();
- }
- function destroyResources(oit) {
- destroyTextures(oit);
- destroyFramebuffers(oit);
- }
- function updateTextures(oit, context, width, height) {
- destroyTextures(oit);
- oit._opaqueTexture = context.createTexture2D({
- width : width,
- height : height,
- pixelFormat : PixelFormat.RGBA,
- pixelDatatype : PixelDatatype.UNSIGNED_BYTE
- });
- oit._accumulationTexture = context.createTexture2D({
- width : width,
- height : height,
- pixelFormat : PixelFormat.RGBA,
- pixelDatatype : PixelDatatype.FLOAT
- });
- oit._revealageTexture = context.createTexture2D({
- width : width,
- height : height,
- pixelFormat : PixelFormat.RGBA,
- pixelDatatype : PixelDatatype.FLOAT
- });
- oit._depthTexture = context.createTexture2D({
- width : width,
- height : height,
- pixelFormat : PixelFormat.DEPTH_COMPONENT,
- pixelDatatype : PixelDatatype.UNSIGNED_SHORT
- });
- }
- function updateFramebuffers(oit, context) {
- destroyFramebuffers(oit);
- var completeFBO = WebGLRenderingContext.FRAMEBUFFER_COMPLETE;
- var supported = true;
-
- if (oit._translucentMRTSupport) {
- oit._translucentFBO = context.createFramebuffer({
- colorTextures : [oit._accumulationTexture, oit._revealageTexture],
- depthTexture : oit._depthTexture,
- destroyAttachments : false
- });
- oit._adjustTranslucentFBO = context.createFramebuffer({
- colorTextures : [oit._accumulationTexture, oit._revealageTexture],
- destroyAttachments : false
- });
- if (oit._translucentFBO.status !== completeFBO || oit._adjustTranslucentFBO.status !== completeFBO) {
- destroyFramebuffers(oit);
- oit._translucentMRTSupport = false;
- }
- }
-
- if (!oit._translucentMRTSupport) {
- oit._translucentFBO = context.createFramebuffer({
- colorTextures : [oit._accumulationTexture],
- depthTexture : oit._depthTexture,
- destroyAttachments : false
- });
- oit._alphaFBO = context.createFramebuffer({
- colorTextures : [oit._revealageTexture],
- depthTexture : oit._depthTexture,
- destroyAttachments : false
- });
- oit._adjustTranslucentFBO = context.createFramebuffer({
- colorTextures : [oit._accumulationTexture],
- destroyAttachments : false
- });
- oit._adjustAlphaFBO = context.createFramebuffer({
- colorTextures : [oit._revealageTexture],
- destroyAttachments : false
- });
- var translucentComplete = oit._translucentFBO.status === completeFBO;
- var alphaComplete = oit._alphaFBO.status === completeFBO;
- var adjustTranslucentComplete = oit._adjustTranslucentFBO.status === completeFBO;
- var adjustAlphaComplete = oit._adjustAlphaFBO.status === completeFBO;
- if (!translucentComplete || !alphaComplete || !adjustTranslucentComplete || !adjustAlphaComplete) {
- destroyResources(oit);
- oit._translucentMultipassSupport = false;
- supported = false;
- }
- }
- if (supported) {
- oit._opaqueFBO = context.createFramebuffer({
- colorTextures : [oit._opaqueTexture],
- depthTexture : oit._depthTexture,
- destroyAttachments : false
- });
- }
- return supported;
- }
- OIT.prototype.update = function(context) {
- if (!this.isSupported()) {
- return;
- }
- var width = context.drawingBufferWidth;
- var height = context.drawingBufferHeight;
- var opaqueTexture = this._opaqueTexture;
- var textureChanged = !defined(opaqueTexture) || opaqueTexture.width !== width || opaqueTexture.height !== height;
- if (textureChanged) {
- updateTextures(this, context, width, height);
- }
- if (!defined(this._opaqueFBO) || textureChanged) {
- if (!updateFramebuffers(this, context)) {
-
- return;
- }
- }
- var that = this;
- var fs;
- var 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, {
- renderState : context.createRenderState(),
- 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._depthTexture;
- }
- };
- this._adjustTranslucentCommand = context.createViewportQuadCommand(fs, {
- renderState : context.createRenderState(),
- 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._depthTexture;
- }
- };
- this._adjustTranslucentCommand = context.createViewportQuadCommand(fs, {
- renderState : context.createRenderState(),
- uniformMap : uniformMap,
- owner : this
- });
- uniformMap = {
- u_bgColor : function() {
- return that._alphaClearCommand.color;
- },
- u_depthTexture : function() {
- return that._depthTexture;
- }
- };
- this._adjustAlphaCommand = context.createViewportQuadCommand(fs, {
- renderState : context.createRenderState(),
- uniformMap : uniformMap,
- owner : this
- });
- }
- }
- };
- var 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
- };
- var 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
- };
- var 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) {
- var translucentState = cache[renderState.id];
- if (!defined(translucentState)) {
- var rs = RenderState.clone(renderState);
- rs.depthMask = false;
- rs.blending = translucentBlending;
- translucentState = context.createRenderState(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);
- }
- var 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';
- var 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';
- var alphaShaderSource =
- ' float ai = czm_gl_FragColor.a;\n' +
- ' gl_FragColor = vec4(ai);\n';
- function getTranslucentShaderProgram(context, shaderProgram, cache, source) {
- var id = shaderProgram.id;
- var shader = cache[id];
- if (!defined(shader)) {
- var attributeLocations = shaderProgram._attributeLocations;
- var fs = shaderProgram.fragmentShaderSource.clone();
- fs.sources = fs.sources.map(function(source) {
- source = source.replace(/void\s+main\s*\(\s*(?:void)?\s*\)/g, 'void 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;
- });
-
-
- 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.createShaderProgram(shaderProgram.vertexShaderSource, fs, attributeLocations);
- cache[id] = shader;
- }
- return shader;
- }
- function getTranslucentMRTShaderProgram(oit, context, shaderProgram) {
- return getTranslucentShaderProgram(context, shaderProgram, oit._translucentShaderCache, mrtShaderSource);
- }
- function getTranslucentColorShaderProgram(oit, context, shaderProgram) {
- return getTranslucentShaderProgram(context, shaderProgram, oit._translucentShaderCache, colorShaderSource);
- }
- function getTranslucentAlphaShaderProgram(oit, context, shaderProgram) {
- return getTranslucentShaderProgram(context, shaderProgram, oit._alphaShaderCache, alphaShaderSource);
- }
- function executeTranslucentCommandsSortedMultipass(oit, scene, executeFunction, passState, commands) {
- var command;
- var renderState;
- var shaderProgram;
- var j;
- var context = scene.context;
- var framebuffer = passState.framebuffer;
- var length = commands.length;
- passState.framebuffer = oit._adjustTranslucentFBO;
- oit._adjustTranslucentCommand.execute(context, passState);
- passState.framebuffer = oit._adjustAlphaFBO;
- oit._adjustAlphaCommand.execute(context, passState);
- var debugFramebuffer = oit._opaqueFBO;
- passState.framebuffer = oit._translucentFBO;
- for (j = 0; j < length; ++j) {
- command = commands[j];
- if (!defined(command.oit) || command.shaderProgram.id !== command.oit.shaderProgramId) {
- command.oit = {
- colorRenderState : getTranslucentColorRenderState(oit, context, command.renderState),
- alphaRenderState : getTranslucentAlphaRenderState(oit, context, command.renderState),
- colorShaderProgram : getTranslucentColorShaderProgram(oit, context, command.shaderProgram),
- alphaShaderProgram : getTranslucentAlphaShaderProgram(oit, context, command.shaderProgram),
- shaderProgramId : command.shaderProgram.id
- };
- }
- renderState = command.oit.colorRenderState;
- shaderProgram = command.oit.colorShaderProgram;
- executeFunction(command, scene, context, passState, renderState, shaderProgram, debugFramebuffer);
- }
- passState.framebuffer = oit._alphaFBO;
- for (j = 0; j < length; ++j) {
- command = commands[j];
- renderState = command.oit.alphaRenderState;
- shaderProgram = command.oit.alphaShaderProgram;
- executeFunction(command, scene, context, passState, renderState, shaderProgram, debugFramebuffer);
- }
- passState.framebuffer = framebuffer;
- }
- function executeTranslucentCommandsSortedMRT(oit, scene, executeFunction, passState, commands) {
- var context = scene.context;
- var framebuffer = passState.framebuffer;
- var length = commands.length;
- passState.framebuffer = oit._adjustTranslucentFBO;
- oit._adjustTranslucentCommand.execute(context, passState);
- var debugFramebuffer = oit._opaqueFBO;
- passState.framebuffer = oit._translucentFBO;
- for (var j = 0; j < length; ++j) {
- var command = commands[j];
- if (!defined(command.oit) || command.shaderProgram.id !== command.oit.shaderProgramId) {
- command.oit = {
- translucentRenderState : getTranslucentMRTRenderState(oit, context, command.renderState),
- translucentShaderProgram : getTranslucentMRTShaderProgram(oit, context, command.shaderProgram),
- shaderProgramId : command.shaderProgram.id
- };
- }
- var renderState = command.oit.translucentRenderState;
- var shaderProgram = command.oit.translucentShaderProgram;
- executeFunction(command, scene, context, passState, renderState, shaderProgram, debugFramebuffer);
- }
- passState.framebuffer = framebuffer;
- }
- OIT.prototype.executeCommands = function(scene, executeFunction, passState, commands) {
- if (this._translucentMRTSupport) {
- executeTranslucentCommandsSortedMRT(this, scene, executeFunction, passState, commands);
- return;
- }
- executeTranslucentCommandsSortedMultipass(this, scene, executeFunction, passState, commands);
- };
- OIT.prototype.execute = function(context, passState) {
- this._compositeCommand.execute(context, passState);
- };
- OIT.prototype.clear = function(context, passState, clearColor) {
- var framebuffer = passState.framebuffer;
- passState.framebuffer = this._opaqueFBO;
- Color.clone(clearColor, this._opaqueClearCommand.color);
- this._opaqueClearCommand.execute(context, passState);
- passState.framebuffer = this._translucentFBO;
- var translucentClearCommand = this._translucentMRTSupport ? this._translucentMRTClearCommand : this._translucentMultipassClearCommand;
- translucentClearCommand.execute(context, passState);
- if (this._translucentMultipassSupport) {
- passState.framebuffer = this._alphaFBO;
- this._alphaClearCommand.execute(context, passState);
- }
- passState.framebuffer = framebuffer;
- };
- OIT.prototype.getColorFramebuffer = function() {
- return this._opaqueFBO;
- };
- 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();
- }
- var name;
- var cache = this._translucentShaderCache;
- for (name in cache) {
- if (cache.hasOwnProperty(name) && defined(cache[name])) {
- cache[name].destroy();
- }
- }
- this._translucentShaderCache = {};
- cache = this._alphaShaderCache;
- for (name in cache) {
- if (cache.hasOwnProperty(name) && defined(cache[name])) {
- cache[name].destroy();
- }
- }
- this._alphaShaderCache = {};
- return destroyObject(this);
- };
- return OIT;
- });
|