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.
594 lines
14 KiB
JavaScript
594 lines
14 KiB
JavaScript
import defaultValue from "../Core/defaultValue.js";
|
|
import defined from "../Core/defined.js";
|
|
import PrimitiveType from "../Core/PrimitiveType.js";
|
|
|
|
/**
|
|
* Represents a command to the renderer for drawing.
|
|
*
|
|
* @private
|
|
*/
|
|
function DrawCommand(options) {
|
|
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
|
|
|
|
this._boundingVolume = options.boundingVolume;
|
|
this._orientedBoundingBox = options.orientedBoundingBox;
|
|
this._cull = defaultValue(options.cull, true);
|
|
this._occlude = defaultValue(options.occlude, true);
|
|
this._modelMatrix = options.modelMatrix;
|
|
this._primitiveType = defaultValue(
|
|
options.primitiveType,
|
|
PrimitiveType.TRIANGLES
|
|
);
|
|
this._vertexArray = options.vertexArray;
|
|
this._count = options.count;
|
|
this._offset = defaultValue(options.offset, 0);
|
|
this._instanceCount = defaultValue(options.instanceCount, 0);
|
|
this._shaderProgram = options.shaderProgram;
|
|
this._uniformMap = options.uniformMap;
|
|
this._renderState = options.renderState;
|
|
this._framebuffer = options.framebuffer;
|
|
this._pass = options.pass;
|
|
this._executeInClosestFrustum = defaultValue(
|
|
options.executeInClosestFrustum,
|
|
false
|
|
);
|
|
this._owner = options.owner;
|
|
this._debugShowBoundingVolume = defaultValue(
|
|
options.debugShowBoundingVolume,
|
|
false
|
|
);
|
|
this._debugOverlappingFrustums = 0;
|
|
this._castShadows = defaultValue(options.castShadows, false);
|
|
this._receiveShadows = defaultValue(options.receiveShadows, false);
|
|
this._pickId = options.pickId;
|
|
this._pickOnly = defaultValue(options.pickOnly, false);
|
|
|
|
this._depthForTranslucentClassification = defaultValue(
|
|
options.depthForTranslucentClassification,
|
|
false
|
|
);
|
|
|
|
this.dirty = true;
|
|
this.lastDirtyTime = 0;
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
this.derivedCommands = {};
|
|
}
|
|
|
|
Object.defineProperties(DrawCommand.prototype, {
|
|
/**
|
|
* The bounding volume of the geometry in world space. This is used for culling and frustum selection.
|
|
* <p>
|
|
* For best rendering performance, use the tightest possible bounding volume. Although
|
|
* <code>undefined</code> is allowed, always try to provide a bounding volume to
|
|
* allow the tightest possible near and far planes to be computed for the scene, and
|
|
* minimize the number of frustums needed.
|
|
* </p>
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Object}
|
|
* @default undefined
|
|
*
|
|
* @see DrawCommand#debugShowBoundingVolume
|
|
*/
|
|
boundingVolume: {
|
|
get: function () {
|
|
return this._boundingVolume;
|
|
},
|
|
set: function (value) {
|
|
if (this._boundingVolume !== value) {
|
|
this._boundingVolume = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* The oriented bounding box of the geometry in world space. If this is defined, it is used instead of
|
|
* {@link DrawCommand#boundingVolume} for plane intersection testing.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {OrientedBoundingBox}
|
|
* @default undefined
|
|
*
|
|
* @see DrawCommand#debugShowBoundingVolume
|
|
*/
|
|
orientedBoundingBox: {
|
|
get: function () {
|
|
return this._orientedBoundingBox;
|
|
},
|
|
set: function (value) {
|
|
if (this._orientedBoundingBox !== value) {
|
|
this._orientedBoundingBox = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* When <code>true</code>, the renderer frustum and horizon culls the command based on its {@link DrawCommand#boundingVolume}.
|
|
* If the command was already culled, set this to <code>false</code> for a performance improvement.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Boolean}
|
|
* @default true
|
|
*/
|
|
cull: {
|
|
get: function () {
|
|
return this._cull;
|
|
},
|
|
set: function (value) {
|
|
if (this._cull !== value) {
|
|
this._cull = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* When <code>true</code>, the horizon culls the command based on its {@link DrawCommand#boundingVolume}.
|
|
* {@link DrawCommand#cull} must also be <code>true</code> in order for the command to be culled.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Boolean}
|
|
* @default true
|
|
*/
|
|
occlude: {
|
|
get: function () {
|
|
return this._occlude;
|
|
},
|
|
set: function (value) {
|
|
if (this._occlude !== value) {
|
|
this._occlude = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* The transformation from the geometry in model space to world space.
|
|
* <p>
|
|
* When <code>undefined</code>, the geometry is assumed to be defined in world space.
|
|
* </p>
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Matrix4}
|
|
* @default undefined
|
|
*/
|
|
modelMatrix: {
|
|
get: function () {
|
|
return this._modelMatrix;
|
|
},
|
|
set: function (value) {
|
|
if (this._modelMatrix !== value) {
|
|
this._modelMatrix = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* The type of geometry in the vertex array.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {PrimitiveType}
|
|
* @default PrimitiveType.TRIANGLES
|
|
*/
|
|
primitiveType: {
|
|
get: function () {
|
|
return this._primitiveType;
|
|
},
|
|
set: function (value) {
|
|
if (this._primitiveType !== value) {
|
|
this._primitiveType = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* The vertex array.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {VertexArray}
|
|
* @default undefined
|
|
*/
|
|
vertexArray: {
|
|
get: function () {
|
|
return this._vertexArray;
|
|
},
|
|
set: function (value) {
|
|
if (this._vertexArray !== value) {
|
|
this._vertexArray = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* The number of vertices to draw in the vertex array.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Number}
|
|
* @default undefined
|
|
*/
|
|
count: {
|
|
get: function () {
|
|
return this._count;
|
|
},
|
|
set: function (value) {
|
|
if (this._count !== value) {
|
|
this._count = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* The offset to start drawing in the vertex array.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Number}
|
|
* @default 0
|
|
*/
|
|
offset: {
|
|
get: function () {
|
|
return this._offset;
|
|
},
|
|
set: function (value) {
|
|
if (this._offset !== value) {
|
|
this._offset = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* The number of instances to draw.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Number}
|
|
* @default 0
|
|
*/
|
|
instanceCount: {
|
|
get: function () {
|
|
return this._instanceCount;
|
|
},
|
|
set: function (value) {
|
|
if (this._instanceCount !== value) {
|
|
this._instanceCount = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* The shader program to apply.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {ShaderProgram}
|
|
* @default undefined
|
|
*/
|
|
shaderProgram: {
|
|
get: function () {
|
|
return this._shaderProgram;
|
|
},
|
|
set: function (value) {
|
|
if (this._shaderProgram !== value) {
|
|
this._shaderProgram = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* Whether this command should cast shadows when shadowing is enabled.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Boolean}
|
|
* @default false
|
|
*/
|
|
castShadows: {
|
|
get: function () {
|
|
return this._castShadows;
|
|
},
|
|
set: function (value) {
|
|
if (this._castShadows !== value) {
|
|
this._castShadows = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* Whether this command should receive shadows when shadowing is enabled.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Boolean}
|
|
* @default false
|
|
*/
|
|
receiveShadows: {
|
|
get: function () {
|
|
return this._receiveShadows;
|
|
},
|
|
set: function (value) {
|
|
if (this._receiveShadows !== value) {
|
|
this._receiveShadows = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* An object with functions whose names match the uniforms in the shader program
|
|
* and return values to set those uniforms.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Object}
|
|
* @default undefined
|
|
*/
|
|
uniformMap: {
|
|
get: function () {
|
|
return this._uniformMap;
|
|
},
|
|
set: function (value) {
|
|
if (this._uniformMap !== value) {
|
|
this._uniformMap = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* The render state.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {RenderState}
|
|
* @default undefined
|
|
*/
|
|
renderState: {
|
|
get: function () {
|
|
return this._renderState;
|
|
},
|
|
set: function (value) {
|
|
if (this._renderState !== value) {
|
|
this._renderState = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* The framebuffer to draw to.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Framebuffer}
|
|
* @default undefined
|
|
*/
|
|
framebuffer: {
|
|
get: function () {
|
|
return this._framebuffer;
|
|
},
|
|
set: function (value) {
|
|
if (this._framebuffer !== value) {
|
|
this._framebuffer = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* The pass when to render.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Pass}
|
|
* @default undefined
|
|
*/
|
|
pass: {
|
|
get: function () {
|
|
return this._pass;
|
|
},
|
|
set: function (value) {
|
|
if (this._pass !== value) {
|
|
this._pass = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* Specifies if this command is only to be executed in the frustum closest
|
|
* to the eye containing the bounding volume. Defaults to <code>false</code>.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Boolean}
|
|
* @default false
|
|
*/
|
|
executeInClosestFrustum: {
|
|
get: function () {
|
|
return this._executeInClosestFrustum;
|
|
},
|
|
set: function (value) {
|
|
if (this._executeInClosestFrustum !== value) {
|
|
this._executeInClosestFrustum = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* The object who created this command. This is useful for debugging command
|
|
* execution; it allows us to see who created a command when we only have a
|
|
* reference to the command, and can be used to selectively execute commands
|
|
* with {@link Scene#debugCommandFilter}.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Object}
|
|
* @default undefined
|
|
*
|
|
* @see Scene#debugCommandFilter
|
|
*/
|
|
owner: {
|
|
get: function () {
|
|
return this._owner;
|
|
},
|
|
set: function (value) {
|
|
if (this._owner !== value) {
|
|
this._owner = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* This property is for debugging only; it is not for production use nor is it optimized.
|
|
* <p>
|
|
* Draws the {@link DrawCommand#boundingVolume} for this command, assuming it is a sphere, when the command executes.
|
|
* </p>
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Boolean}
|
|
* @default false
|
|
*
|
|
* @see DrawCommand#boundingVolume
|
|
*/
|
|
debugShowBoundingVolume: {
|
|
get: function () {
|
|
return this._debugShowBoundingVolume;
|
|
},
|
|
set: function (value) {
|
|
if (this._debugShowBoundingVolume !== value) {
|
|
this._debugShowBoundingVolume = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
|
|
/**
|
|
* Used to implement Scene.debugShowFrustums.
|
|
* @private
|
|
*/
|
|
debugOverlappingFrustums: {
|
|
get: function () {
|
|
return this._debugOverlappingFrustums;
|
|
},
|
|
set: function (value) {
|
|
if (this._debugOverlappingFrustums !== value) {
|
|
this._debugOverlappingFrustums = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
/**
|
|
* A GLSL string that will evaluate to a pick id. When <code>undefined</code>, the command will only draw depth
|
|
* during the pick pass.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {String}
|
|
* @default undefined
|
|
*/
|
|
pickId: {
|
|
get: function () {
|
|
return this._pickId;
|
|
},
|
|
set: function (value) {
|
|
if (this._pickId !== value) {
|
|
this._pickId = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
/**
|
|
* Whether this command should be executed in the pick pass only.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Boolean}
|
|
* @default false
|
|
*/
|
|
pickOnly: {
|
|
get: function () {
|
|
return this._pickOnly;
|
|
},
|
|
set: function (value) {
|
|
if (this._pickOnly !== value) {
|
|
this._pickOnly = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
/**
|
|
* Whether this command should be derived to draw depth for classification of translucent primitives.
|
|
*
|
|
* @memberof DrawCommand.prototype
|
|
* @type {Boolean}
|
|
* @default false
|
|
*/
|
|
depthForTranslucentClassification: {
|
|
get: function () {
|
|
return this._depthForTranslucentClassification;
|
|
},
|
|
set: function (value) {
|
|
if (this._depthForTranslucentClassification !== value) {
|
|
this._depthForTranslucentClassification = value;
|
|
this.dirty = true;
|
|
}
|
|
},
|
|
},
|
|
});
|
|
|
|
/**
|
|
* @private
|
|
*/
|
|
DrawCommand.shallowClone = function (command, result) {
|
|
if (!defined(command)) {
|
|
return undefined;
|
|
}
|
|
if (!defined(result)) {
|
|
result = new DrawCommand();
|
|
}
|
|
|
|
result._boundingVolume = command._boundingVolume;
|
|
result._orientedBoundingBox = command._orientedBoundingBox;
|
|
result._cull = command._cull;
|
|
result._occlude = command._occlude;
|
|
result._modelMatrix = command._modelMatrix;
|
|
result._primitiveType = command._primitiveType;
|
|
result._vertexArray = command._vertexArray;
|
|
result._count = command._count;
|
|
result._offset = command._offset;
|
|
result._instanceCount = command._instanceCount;
|
|
result._shaderProgram = command._shaderProgram;
|
|
result._uniformMap = command._uniformMap;
|
|
result._renderState = command._renderState;
|
|
result._framebuffer = command._framebuffer;
|
|
result._pass = command._pass;
|
|
result._executeInClosestFrustum = command._executeInClosestFrustum;
|
|
result._owner = command._owner;
|
|
result._debugShowBoundingVolume = command._debugShowBoundingVolume;
|
|
result._debugOverlappingFrustums = command._debugOverlappingFrustums;
|
|
result._castShadows = command._castShadows;
|
|
result._receiveShadows = command._receiveShadows;
|
|
result._pickId = command._pickId;
|
|
result._pickOnly = command._pickOnly;
|
|
result._depthForTranslucentClassification =
|
|
command._depthForTranslucentClassification;
|
|
|
|
result.dirty = true;
|
|
result.lastDirtyTime = 0;
|
|
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Executes the draw command.
|
|
*
|
|
* @param {Context} context The renderer context in which to draw.
|
|
* @param {PassState} [passState] The state for the current render pass.
|
|
*/
|
|
DrawCommand.prototype.execute = function (context, passState) {
|
|
context.draw(this, passState);
|
|
};
|
|
export default DrawCommand;
|