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.

201 lines
5.6 KiB
JavaScript

import Cartesian4 from "../Core/Cartesian4.js";
import defined from "../Core/defined.js";
import destroyObject from "../Core/destroyObject.js";
import PixelFormat from "../Core/PixelFormat.js";
import Framebuffer from "../Renderer/Framebuffer.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";
/**
* @private
*/
function PickDepth() {
this._framebuffer = undefined;
this._depthTexture = undefined;
this._textureToCopy = undefined;
this._copyDepthCommand = undefined;
this._useLogDepth = undefined;
this._debugPickDepthViewportCommand = undefined;
}
function executeDebugPickDepth(pickDepth, context, passState, useLogDepth) {
if (
!defined(pickDepth._debugPickDepthViewportCommand) ||
useLogDepth !== pickDepth._useLogDepth
) {
var fsSource =
"uniform highp sampler2D u_texture;\n" +
"varying vec2 v_textureCoordinates;\n" +
"void main()\n" +
"{\n" +
" float z_window = czm_unpackDepth(texture2D(u_texture, v_textureCoordinates));\n" +
" z_window = czm_reverseLogDepth(z_window); \n" +
" float n_range = czm_depthRange.near;\n" +
" float f_range = czm_depthRange.far;\n" +
" float z_ndc = (2.0 * z_window - n_range - f_range) / (f_range - n_range);\n" +
" float scale = pow(z_ndc * 0.5 + 0.5, 8.0);\n" +
" gl_FragColor = vec4(mix(vec3(0.0), vec3(1.0), scale), 1.0);\n" +
"}\n";
var fs = new ShaderSource({
defines: [useLogDepth ? "LOG_DEPTH" : ""],
sources: [fsSource],
});
pickDepth._debugPickDepthViewportCommand = context.createViewportQuadCommand(
fs,
{
uniformMap: {
u_texture: function () {
return pickDepth._depthTexture;
},
},
owner: pickDepth,
}
);
pickDepth._useLogDepth = useLogDepth;
}
pickDepth._debugPickDepthViewportCommand.execute(context, passState);
}
function destroyTextures(pickDepth) {
pickDepth._depthTexture =
pickDepth._depthTexture &&
!pickDepth._depthTexture.isDestroyed() &&
pickDepth._depthTexture.destroy();
}
function destroyFramebuffers(pickDepth) {
pickDepth._framebuffer =
pickDepth._framebuffer &&
!pickDepth._framebuffer.isDestroyed() &&
pickDepth._framebuffer.destroy();
}
function createTextures(pickDepth, context, width, height) {
pickDepth._depthTexture = new Texture({
context: context,
width: width,
height: height,
pixelFormat: PixelFormat.RGBA,
pixelDatatype: PixelDatatype.UNSIGNED_BYTE,
});
}
function createFramebuffers(pickDepth, context, width, height) {
destroyTextures(pickDepth);
destroyFramebuffers(pickDepth);
createTextures(pickDepth, context, width, height);
pickDepth._framebuffer = new Framebuffer({
context: context,
colorTextures: [pickDepth._depthTexture],
destroyAttachments: false,
});
}
function updateFramebuffers(pickDepth, context, depthTexture) {
var width = depthTexture.width;
var height = depthTexture.height;
var texture = pickDepth._depthTexture;
var textureChanged =
!defined(texture) || texture.width !== width || texture.height !== height;
if (!defined(pickDepth._framebuffer) || textureChanged) {
createFramebuffers(pickDepth, context, width, height);
}
}
function updateCopyCommands(pickDepth, context, depthTexture) {
if (!defined(pickDepth._copyDepthCommand)) {
var fs =
"uniform highp sampler2D u_texture;\n" +
"varying vec2 v_textureCoordinates;\n" +
"void main()\n" +
"{\n" +
" gl_FragColor = czm_packDepth(texture2D(u_texture, v_textureCoordinates).r);\n" +
"}\n";
pickDepth._copyDepthCommand = context.createViewportQuadCommand(fs, {
renderState: RenderState.fromCache(),
uniformMap: {
u_texture: function () {
return pickDepth._textureToCopy;
},
},
owner: pickDepth,
});
}
pickDepth._textureToCopy = depthTexture;
pickDepth._copyDepthCommand.framebuffer = pickDepth._framebuffer;
}
PickDepth.prototype.executeDebugPickDepth = function (
context,
passState,
useLogDepth
) {
executeDebugPickDepth(this, context, passState, useLogDepth);
};
PickDepth.prototype.update = function (context, depthTexture) {
updateFramebuffers(this, context, depthTexture);
updateCopyCommands(this, context, depthTexture);
};
var scratchPackedDepth = new Cartesian4();
var packedDepthScale = new Cartesian4(
1.0,
1.0 / 255.0,
1.0 / 65025.0,
1.0 / 16581375.0
);
PickDepth.prototype.getDepth = function (context, x, y) {
// If this function is called before the framebuffer is created, the depth is undefined.
if (!defined(this._framebuffer)) {
return undefined;
}
var pixels = context.readPixels({
x: x,
y: y,
width: 1,
height: 1,
framebuffer: this._framebuffer,
});
var packedDepth = Cartesian4.unpack(pixels, 0, scratchPackedDepth);
Cartesian4.divideByScalar(packedDepth, 255.0, packedDepth);
return Cartesian4.dot(packedDepth, packedDepthScale);
};
PickDepth.prototype.executeCopyDepth = function (context, passState) {
this._copyDepthCommand.execute(context, passState);
};
PickDepth.prototype.isDestroyed = function () {
return false;
};
PickDepth.prototype.destroy = function () {
destroyTextures(this);
destroyFramebuffers(this);
if (defined(this._copyDepthCommand)) {
this._copyDepthCommand.shaderProgram =
defined(this._copyDepthCommand.shaderProgram) &&
this._copyDepthCommand.shaderProgram.destroy();
}
return destroyObject(this);
};
export default PickDepth;