UNPKG

cesium

Version:

Cesium is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.

279 lines (248 loc) 11.4 kB
/*global define*/ define([ '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', '../Core/destroyObject', '../Core/DeveloperError', '../Core/IndexDatatype', './BufferUsage', './WebGLConstants' ], function( defaultValue, defined, defineProperties, destroyObject, DeveloperError, IndexDatatype, BufferUsage, WebGLConstants) { 'use strict'; /** * @private */ function Buffer(options) { options = defaultValue(options, defaultValue.EMPTY_OBJECT); //>>includeStart('debug', pragmas.debug); if (!defined(options.context)) { throw new DeveloperError('options.context is required.'); } if (!defined(options.typedArray) && !defined(options.sizeInBytes)) { throw new DeveloperError('Either options.sizeInBytes or options.typedArray is required.'); } if (defined(options.typedArray) && defined(options.sizeInBytes)) { throw new DeveloperError('Cannot pass in both options.sizeInBytes and options.typedArray.'); } if (defined(options.typedArray) && !(typeof options.typedArray === 'object' && typeof options.typedArray.byteLength === 'number')) { throw new DeveloperError('options.typedArray must be a typed array'); } if (!BufferUsage.validate(options.usage)) { throw new DeveloperError('usage is invalid.'); } //>>includeEnd('debug'); var gl = options.context._gl; var bufferTarget = options.bufferTarget; var typedArray = options.typedArray; var sizeInBytes = options.sizeInBytes; var usage = options.usage; var hasArray = defined(typedArray); if (hasArray) { sizeInBytes = typedArray.byteLength; } //>>includeStart('debug', pragmas.debug); if (sizeInBytes <= 0) { throw new DeveloperError('Buffer size must be greater than zero.'); } //>>includeEnd('debug'); var buffer = gl.createBuffer(); gl.bindBuffer(bufferTarget, buffer); gl.bufferData(bufferTarget, hasArray ? typedArray : sizeInBytes, usage); gl.bindBuffer(bufferTarget, null); this._gl = gl; this._bufferTarget = bufferTarget; this._sizeInBytes = sizeInBytes; this._usage = usage; this._buffer = buffer; this.vertexArrayDestroyable = true; } /** * Creates a vertex buffer, which contains untyped vertex data in GPU-controlled memory. * <br /><br /> * A vertex array defines the actual makeup of a vertex, e.g., positions, normals, texture coordinates, * etc., by interpreting the raw data in one or more vertex buffers. * * @param {Object} options An object containing the following properties: * @param {Context} options.context The context in which to create the buffer * @param {ArrayBufferView} [options.typedArray] A typed array containing the data to copy to the buffer. * @param {Number} [options.sizeInBytes] A <code>Number</code> defining the size of the buffer in bytes. Required if options.typedArray is not given. * @param {BufferUsage} options.usage Specifies the expected usage pattern of the buffer. On some GL implementations, this can significantly affect performance. See {@link BufferUsage}. * @returns {VertexBuffer} The vertex buffer, ready to be attached to a vertex array. * * @exception {DeveloperError} Must specify either <options.typedArray> or <options.sizeInBytes>, but not both. * @exception {DeveloperError} The buffer size must be greater than zero. * @exception {DeveloperError} Invalid <code>usage</code>. * * * @example * // Example 1. Create a dynamic vertex buffer 16 bytes in size. * var buffer = Buffer.createVertexBuffer({ * context : context, * sizeInBytes : 16, * usage : BufferUsage.DYNAMIC_DRAW * }); * * @example * // Example 2. Create a dynamic vertex buffer from three floating-point values. * // The data copied to the vertex buffer is considered raw bytes until it is * // interpreted as vertices using a vertex array. * var positionBuffer = buffer.createVertexBuffer({ * context : context, * typedArray : new Float32Array([0, 0, 0]), * usage : BufferUsage.STATIC_DRAW * }); * * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGenBuffer.xml|glGenBuffer} * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBindBuffer.xml|glBindBuffer} with <code>ARRAY_BUFFER</code> * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBufferData.xml|glBufferData} with <code>ARRAY_BUFFER</code> */ Buffer.createVertexBuffer = function(options) { //>>includeStart('debug', pragmas.debug); if (!defined(options.context)) { throw new DeveloperError('options.context is required.'); } //>>includeEnd('debug'); return new Buffer({ context: options.context, bufferTarget: WebGLConstants.ARRAY_BUFFER, typedArray: options.typedArray, sizeInBytes: options.sizeInBytes, usage: options.usage }); }; /** * Creates an index buffer, which contains typed indices in GPU-controlled memory. * <br /><br /> * An index buffer can be attached to a vertex array to select vertices for rendering. * <code>Context.draw</code> can render using the entire index buffer or a subset * of the index buffer defined by an offset and count. * * @param {Object} options An object containing the following properties: * @param {Context} options.context The context in which to create the buffer * @param {ArrayBufferView} [options.typedArray] A typed array containing the data to copy to the buffer. * @param {Number} [options.sizeInBytes] A <code>Number</code> defining the size of the buffer in bytes. Required if options.typedArray is not given. * @param {BufferUsage} options.usage Specifies the expected usage pattern of the buffer. On some GL implementations, this can significantly affect performance. See {@link BufferUsage}. * @param {IndexDatatype} indexDatatype The datatype of indices in the buffer. * @returns {IndexBuffer} The index buffer, ready to be attached to a vertex array. * * @exception {DeveloperError} Must specify either <options.typedArray> or <options.sizeInBytes>, but not both. * @exception {DeveloperError} IndexDatatype.UNSIGNED_INT requires OES_element_index_uint, which is not supported on this system. Check context.elementIndexUint. * @exception {DeveloperError} The size in bytes must be greater than zero. * @exception {DeveloperError} Invalid <code>usage</code>. * @exception {DeveloperError} Invalid <code>indexDatatype</code>. * * * @example * // Example 1. Create a stream index buffer of unsigned shorts that is * // 16 bytes in size. * var buffer = Buffer.createIndexBuffer({ * context : context, * sizeInBytes : 16, * usage : BufferUsage.STREAM_DRAW, * indexDatatype : IndexDatatype.UNSIGNED_SHORT * }); * * @example * // Example 2. Create a static index buffer containing three unsigned shorts. * var buffer = Buffer.createIndexBuffer({ * context : context, * typedArray : new Uint16Array([0, 1, 2]), * usage : BufferUsage.STATIC_DRAW, * indexDatatype : IndexDatatype.UNSIGNED_SHORT * }); * * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGenBuffer.xml|glGenBuffer} * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBindBuffer.xml|glBindBuffer} with <code>ELEMENT_ARRAY_BUFFER</code> * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBufferData.xml|glBufferData} with <code>ELEMENT_ARRAY_BUFFER</code> */ Buffer.createIndexBuffer = function(options) { //>>includeStart('debug', pragmas.debug); if (!defined(options.context)) { throw new DeveloperError('options.context is required.'); } if (!IndexDatatype.validate(options.indexDatatype)) { throw new DeveloperError('Invalid indexDatatype.'); } if ((options.indexDatatype === IndexDatatype.UNSIGNED_INT) && !options.context.elementIndexUint) { throw new DeveloperError('IndexDatatype.UNSIGNED_INT requires OES_element_index_uint, which is not supported on this system. Check context.elementIndexUint.'); } //>>includeEnd('debug'); var context = options.context; var indexDatatype = options.indexDatatype; var bytesPerIndex = IndexDatatype.getSizeInBytes(indexDatatype); var buffer = new Buffer({ context : context, bufferTarget : WebGLConstants.ELEMENT_ARRAY_BUFFER, typedArray : options.typedArray, sizeInBytes : options.sizeInBytes, usage : options.usage }); var numberOfIndices = buffer.sizeInBytes / bytesPerIndex; defineProperties(buffer, { indexDatatype: { get : function() { return indexDatatype; } }, bytesPerIndex : { get : function() { return bytesPerIndex; } }, numberOfIndices : { get : function() { return numberOfIndices; } } }); return buffer; }; defineProperties(Buffer.prototype, { sizeInBytes : { get : function() { return this._sizeInBytes; } }, usage: { get : function() { return this._usage; } } }); Buffer.prototype._getBuffer = function() { return this._buffer; }; Buffer.prototype.copyFromArrayView = function(arrayView, offsetInBytes) { offsetInBytes = defaultValue(offsetInBytes, 0); //>>includeStart('debug', pragmas.debug); if (!arrayView) { throw new DeveloperError('arrayView is required.'); } if (offsetInBytes + arrayView.byteLength > this._sizeInBytes) { throw new DeveloperError('This buffer is not large enough.'); } //>>includeEnd('debug'); var gl = this._gl; var target = this._bufferTarget; gl.bindBuffer(target, this._buffer); gl.bufferSubData(target, offsetInBytes, arrayView); gl.bindBuffer(target, null); }; Buffer.prototype.isDestroyed = function() { return false; }; Buffer.prototype.destroy = function() { this._gl.deleteBuffer(this._buffer); return destroyObject(this); }; return Buffer; });