You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
383 lines
12 KiB
JavaScript
383 lines
12 KiB
JavaScript
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 ClearCommand from "../Renderer/ClearCommand.js";
|
|
import Framebuffer from "../Renderer/Framebuffer.js";
|
|
import PixelDatatype from "../Renderer/PixelDatatype.js";
|
|
import RenderState from "../Renderer/RenderState.js";
|
|
import Sampler from "../Renderer/Sampler.js";
|
|
import ShaderSource from "../Renderer/ShaderSource.js";
|
|
import Texture from "../Renderer/Texture.js";
|
|
import TextureMagnificationFilter from "../Renderer/TextureMagnificationFilter.js";
|
|
import TextureMinificationFilter from "../Renderer/TextureMinificationFilter.js";
|
|
import TextureWrap from "../Renderer/TextureWrap.js";
|
|
import PassThrough from "../Shaders/PostProcessStages/PassThrough.js";
|
|
import BlendingState from "./BlendingState.js";
|
|
import StencilConstants from "./StencilConstants.js";
|
|
import StencilFunction from "./StencilFunction.js";
|
|
import StencilOperation from "./StencilOperation.js";
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
function InvertClassification() {
|
|
this.previousFramebuffer = undefined;
|
|
this._previousFramebuffer = undefined;
|
|
|
|
this._texture = undefined;
|
|
this._classifiedTexture = undefined;
|
|
this._depthStencilTexture = undefined;
|
|
this._fbo = undefined;
|
|
this._fboClassified = undefined;
|
|
|
|
this._rsUnclassified = undefined;
|
|
this._rsClassified = undefined;
|
|
|
|
this._unclassifiedCommand = undefined;
|
|
this._classifiedCommand = undefined;
|
|
this._translucentCommand = undefined;
|
|
|
|
this._clearColorCommand = new ClearCommand({
|
|
color: new Color(0.0, 0.0, 0.0, 0.0),
|
|
owner: this,
|
|
});
|
|
this._clearCommand = new ClearCommand({
|
|
color: new Color(0.0, 0.0, 0.0, 0.0),
|
|
depth: 1.0,
|
|
stencil: 0,
|
|
});
|
|
|
|
var that = this;
|
|
this._uniformMap = {
|
|
colorTexture: function () {
|
|
return that._texture;
|
|
},
|
|
depthTexture: function () {
|
|
return that._depthStencilTexture;
|
|
},
|
|
classifiedTexture: function () {
|
|
return that._classifiedTexture;
|
|
},
|
|
};
|
|
}
|
|
|
|
Object.defineProperties(InvertClassification.prototype, {
|
|
unclassifiedCommand: {
|
|
get: function () {
|
|
return this._unclassifiedCommand;
|
|
},
|
|
},
|
|
});
|
|
|
|
InvertClassification.isTranslucencySupported = function (context) {
|
|
return context.depthTexture && context.fragmentDepth;
|
|
};
|
|
|
|
var rsUnclassified = {
|
|
depthMask: false,
|
|
stencilTest: {
|
|
enabled: true,
|
|
frontFunction: StencilFunction.EQUAL,
|
|
frontOperation: {
|
|
fail: StencilOperation.KEEP,
|
|
zFail: StencilOperation.KEEP,
|
|
zPass: StencilOperation.KEEP,
|
|
},
|
|
backFunction: StencilFunction.NEVER,
|
|
reference: 0,
|
|
mask: StencilConstants.CLASSIFICATION_MASK,
|
|
},
|
|
blending: BlendingState.ALPHA_BLEND,
|
|
};
|
|
|
|
var rsClassified = {
|
|
depthMask: false,
|
|
stencilTest: {
|
|
enabled: true,
|
|
frontFunction: StencilFunction.NOT_EQUAL,
|
|
frontOperation: {
|
|
fail: StencilOperation.KEEP,
|
|
zFail: StencilOperation.KEEP,
|
|
zPass: StencilOperation.KEEP,
|
|
},
|
|
backFunction: StencilFunction.NEVER,
|
|
reference: 0,
|
|
mask: StencilConstants.CLASSIFICATION_MASK,
|
|
},
|
|
blending: BlendingState.ALPHA_BLEND,
|
|
};
|
|
|
|
// Set the 3D Tiles bit when rendering back into the scene's framebuffer. This is only needed if
|
|
// invert classification does not use the scene's depth-stencil texture, which is the case if the invert
|
|
// classification color is translucent.
|
|
var rsDefault = {
|
|
depthMask: true,
|
|
depthTest: {
|
|
enabled: true,
|
|
},
|
|
stencilTest: StencilConstants.setCesium3DTileBit(),
|
|
stencilMask: StencilConstants.CESIUM_3D_TILE_MASK,
|
|
blending: BlendingState.ALPHA_BLEND,
|
|
};
|
|
|
|
var translucentFS =
|
|
"#extension GL_EXT_frag_depth : enable\n" +
|
|
"uniform sampler2D colorTexture;\n" +
|
|
"uniform sampler2D depthTexture;\n" +
|
|
"uniform sampler2D classifiedTexture;\n" +
|
|
"varying vec2 v_textureCoordinates;\n" +
|
|
"void main()\n" +
|
|
"{\n" +
|
|
" vec4 color = texture2D(colorTexture, v_textureCoordinates);\n" +
|
|
" if (color.a == 0.0)\n" +
|
|
" {\n" +
|
|
" discard;\n" +
|
|
" }\n" +
|
|
" bool isClassified = all(equal(texture2D(classifiedTexture, v_textureCoordinates), vec4(0.0)));\n" +
|
|
"#ifdef UNCLASSIFIED\n" +
|
|
" vec4 highlightColor = czm_invertClassificationColor;\n" +
|
|
" if (isClassified)\n" +
|
|
" {\n" +
|
|
" discard;\n" +
|
|
" }\n" +
|
|
"#else\n" +
|
|
" vec4 highlightColor = vec4(1.0);\n" +
|
|
" if (!isClassified)\n" +
|
|
" {\n" +
|
|
" discard;\n" +
|
|
" }\n" +
|
|
"#endif\n" +
|
|
" gl_FragColor = color * highlightColor;\n" +
|
|
" gl_FragDepthEXT = texture2D(depthTexture, v_textureCoordinates).r;\n" +
|
|
"}\n";
|
|
|
|
var opaqueFS =
|
|
"uniform sampler2D colorTexture;\n" +
|
|
"varying vec2 v_textureCoordinates;\n" +
|
|
"void main()\n" +
|
|
"{\n" +
|
|
" vec4 color = texture2D(colorTexture, v_textureCoordinates);\n" +
|
|
" if (color.a == 0.0)\n" +
|
|
" {\n" +
|
|
" discard;\n" +
|
|
" }\n" +
|
|
"#ifdef UNCLASSIFIED\n" +
|
|
" gl_FragColor = color * czm_invertClassificationColor;\n" +
|
|
"#else\n" +
|
|
" gl_FragColor = color;\n" +
|
|
"#endif\n" +
|
|
"}\n";
|
|
|
|
InvertClassification.prototype.update = function (context) {
|
|
var texture = this._texture;
|
|
var previousFramebufferChanged =
|
|
!defined(texture) || this.previousFramebuffer !== this._previousFramebuffer;
|
|
this._previousFramebuffer = this.previousFramebuffer;
|
|
|
|
var width = context.drawingBufferWidth;
|
|
var height = context.drawingBufferHeight;
|
|
|
|
var textureChanged =
|
|
!defined(texture) || texture.width !== width || texture.height !== height;
|
|
if (textureChanged || previousFramebufferChanged) {
|
|
this._texture = this._texture && this._texture.destroy();
|
|
this._classifiedTexture =
|
|
this._classifiedTexture && this._classifiedTexture.destroy();
|
|
this._depthStencilTexture =
|
|
this._depthStencilTexture && this._depthStencilTexture.destroy();
|
|
|
|
this._texture = new Texture({
|
|
context: context,
|
|
width: width,
|
|
height: height,
|
|
pixelFormat: PixelFormat.RGBA,
|
|
pixelDatatype: PixelDatatype.UNSIGNED_BYTE,
|
|
sampler: new Sampler({
|
|
wrapS: TextureWrap.CLAMP_TO_EDGE,
|
|
wrapT: TextureWrap.CLAMP_TO_EDGE,
|
|
minificationFilter: TextureMinificationFilter.LINEAR,
|
|
magnificationFilter: TextureMagnificationFilter.LINEAR,
|
|
}),
|
|
});
|
|
|
|
if (!defined(this._previousFramebuffer)) {
|
|
this._classifiedTexture = new Texture({
|
|
context: context,
|
|
width: width,
|
|
height: height,
|
|
pixelFormat: PixelFormat.RGBA,
|
|
pixelDatatype: PixelDatatype.UNSIGNED_BYTE,
|
|
sampler: new Sampler({
|
|
wrapS: TextureWrap.CLAMP_TO_EDGE,
|
|
wrapT: TextureWrap.CLAMP_TO_EDGE,
|
|
minificationFilter: TextureMinificationFilter.LINEAR,
|
|
magnificationFilter: TextureMagnificationFilter.LINEAR,
|
|
}),
|
|
});
|
|
this._depthStencilTexture = new Texture({
|
|
context: context,
|
|
width: width,
|
|
height: height,
|
|
pixelFormat: PixelFormat.DEPTH_STENCIL,
|
|
pixelDatatype: PixelDatatype.UNSIGNED_INT_24_8,
|
|
});
|
|
}
|
|
}
|
|
|
|
if (!defined(this._fbo) || textureChanged || previousFramebufferChanged) {
|
|
this._fbo = this._fbo && this._fbo.destroy();
|
|
this._fboClassified = this._fboClassified && this._fboClassified.destroy();
|
|
|
|
var depthStencilTexture;
|
|
var depthStencilRenderbuffer;
|
|
if (defined(this._previousFramebuffer)) {
|
|
depthStencilTexture = this._previousFramebuffer.depthStencilTexture;
|
|
depthStencilRenderbuffer = this._previousFramebuffer
|
|
.depthStencilRenderbuffer;
|
|
} else {
|
|
depthStencilTexture = this._depthStencilTexture;
|
|
}
|
|
|
|
this._fbo = new Framebuffer({
|
|
context: context,
|
|
colorTextures: [this._texture],
|
|
depthStencilTexture: depthStencilTexture,
|
|
depthStencilRenderbuffer: depthStencilRenderbuffer,
|
|
destroyAttachments: false,
|
|
});
|
|
|
|
if (!defined(this._previousFramebuffer)) {
|
|
this._fboClassified = new Framebuffer({
|
|
context: context,
|
|
colorTextures: [this._classifiedTexture],
|
|
depthStencilTexture: depthStencilTexture,
|
|
destroyAttachments: false,
|
|
});
|
|
}
|
|
}
|
|
|
|
if (!defined(this._rsUnclassified)) {
|
|
this._rsUnclassified = RenderState.fromCache(rsUnclassified);
|
|
this._rsClassified = RenderState.fromCache(rsClassified);
|
|
this._rsDefault = RenderState.fromCache(rsDefault);
|
|
}
|
|
|
|
if (!defined(this._unclassifiedCommand) || previousFramebufferChanged) {
|
|
if (defined(this._unclassifiedCommand)) {
|
|
this._unclassifiedCommand.shaderProgram =
|
|
this._unclassifiedCommand.shaderProgram &&
|
|
this._unclassifiedCommand.shaderProgram.destroy();
|
|
this._classifiedCommand.shaderProgram =
|
|
this._classifiedCommand.shaderProgram &&
|
|
this._classifiedCommand.shaderProgram.destroy();
|
|
}
|
|
|
|
var fs = defined(this._previousFramebuffer) ? opaqueFS : translucentFS;
|
|
var unclassifiedFSSource = new ShaderSource({
|
|
defines: ["UNCLASSIFIED"],
|
|
sources: [fs],
|
|
});
|
|
var classifiedFSSource = new ShaderSource({
|
|
sources: [fs],
|
|
});
|
|
this._unclassifiedCommand = context.createViewportQuadCommand(
|
|
unclassifiedFSSource,
|
|
{
|
|
renderState: defined(this._previousFramebuffer)
|
|
? this._rsUnclassified
|
|
: this._rsDefault,
|
|
uniformMap: this._uniformMap,
|
|
owner: this,
|
|
}
|
|
);
|
|
this._classifiedCommand = context.createViewportQuadCommand(
|
|
classifiedFSSource,
|
|
{
|
|
renderState: defined(this._previousFramebuffer)
|
|
? this._rsClassified
|
|
: this._rsDefault,
|
|
uniformMap: this._uniformMap,
|
|
owner: this,
|
|
}
|
|
);
|
|
|
|
if (defined(this._translucentCommand)) {
|
|
this._translucentCommand.shaderProgram =
|
|
this._translucentCommand.shaderProgram &&
|
|
this._translucentCommand.shaderProgram.destroy();
|
|
}
|
|
if (!defined(this._previousFramebuffer)) {
|
|
this._translucentCommand = context.createViewportQuadCommand(
|
|
PassThrough,
|
|
{
|
|
renderState: this._rsUnclassified,
|
|
uniformMap: this._uniformMap,
|
|
owner: this,
|
|
}
|
|
);
|
|
}
|
|
}
|
|
};
|
|
|
|
InvertClassification.prototype.clear = function (context, passState) {
|
|
var framebuffer = passState.framebuffer;
|
|
|
|
if (defined(this._previousFramebuffer)) {
|
|
passState.framebuffer = this._fbo;
|
|
this._clearColorCommand.execute(context, passState);
|
|
} else {
|
|
passState.framebuffer = this._fbo;
|
|
this._clearCommand.execute(context, passState);
|
|
passState.framebuffer = this._fboClassified;
|
|
this._clearCommand.execute(context, passState);
|
|
}
|
|
|
|
passState.framebuffer = framebuffer;
|
|
};
|
|
|
|
InvertClassification.prototype.executeClassified = function (
|
|
context,
|
|
passState
|
|
) {
|
|
if (!defined(this._previousFramebuffer)) {
|
|
var framebuffer = passState.framebuffer;
|
|
|
|
passState.framebuffer = this._fboClassified;
|
|
this._translucentCommand.execute(context, passState);
|
|
|
|
passState.framebuffer = framebuffer;
|
|
}
|
|
this._classifiedCommand.execute(context, passState);
|
|
};
|
|
|
|
InvertClassification.prototype.executeUnclassified = function (
|
|
context,
|
|
passState
|
|
) {
|
|
this._unclassifiedCommand.execute(context, passState);
|
|
};
|
|
|
|
InvertClassification.prototype.isDestroyed = function () {
|
|
return false;
|
|
};
|
|
|
|
InvertClassification.prototype.destroy = function () {
|
|
this._fbo = this._fbo && this._fbo.destroy();
|
|
this._texture = this._texture && this._texture.destroy();
|
|
this._depthStencilTexture =
|
|
this._depthStencilTexture && this._depthStencilTexture.destroy();
|
|
|
|
if (defined(this._unclassifiedCommand)) {
|
|
this._unclassifiedCommand.shaderProgram =
|
|
this._unclassifiedCommand.shaderProgram &&
|
|
this._unclassifiedCommand.shaderProgram.destroy();
|
|
this._classifiedCommand.shaderProgram =
|
|
this._classifiedCommand.shaderProgram &&
|
|
this._classifiedCommand.shaderProgram.destroy();
|
|
}
|
|
|
|
return destroyObject(this);
|
|
};
|
|
export default InvertClassification;
|