UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

242 lines (211 loc) 8.39 kB
/** * @author Benjamin D. Richards <benjamindrichards@gmail.com> * @copyright 2013-2026 Phaser Studio Inc. * @license {@link https://opensource.org/licenses/MIT|MIT License} */ var Class = require('../../../utils/Class'); /** * @classdesc * Wrapper for a WebGL Vertex Array Object (VAO). * * A VAO stores the complete vertex attribute configuration for a draw call, * including attribute pointer definitions, enabled attribute arrays, and the * bound element array buffer. Binding a VAO before drawing restores all of * this state in a single call, reducing the number of WebGL API calls needed * per frame. * * A raw WebGLVertexArrayObject should never be exposed outside the * WebGLRenderer, so the WebGLRenderer can handle context loss and other * events without other systems having to be aware of it. * Always use WebGLVAOWrapper instead. * * @class WebGLVAOWrapper * @memberof Phaser.Renderer.WebGL.Wrappers * @constructor * @since 4.0.0 * @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGLRenderer instance that owns this wrapper. * @param {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} program - The shader program that this VAO is associated with. * @param {?Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} indexBuffer - The index buffer used in this VAO, if any. * @param {Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper[]} attributeBufferLayouts - The vertex buffers containing attribute data for this VAO, alongside the relevant attribute layout. */ var WebGLVAOWrapper = new Class({ initialize: function WebGLVAOWrapper (renderer, program, indexBuffer, attributeBufferLayouts) { /** * The WebGLRenderer instance that owns this wrapper. * * @name Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#renderer * @type {Phaser.Renderer.WebGL.WebGLRenderer} * @since 4.0.0 */ this.renderer = renderer; /** * The shader program that this VAO is associated with. * * @name Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#program * @type {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} * @since 4.0.0 */ this.program = program; /** * The WebGLVertexArrayObject being wrapped by this class. * * This property could change at any time. * Therefore, you should never store a reference to this value. * It should only be passed directly to the WebGL API for drawing. * * @name Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#vertexArrayObject * @type {?WebGLVertexArrayObject} * @default null * @since 4.0.0 */ this.vertexArrayObject = null; /** * The element array buffer used in this VAO, if any. * * @name Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#indexBuffer * @type {?Phaser.Renderer.WebGL.Wrappers.WebGLBufferWrapper} * @default null * @since 4.0.0 */ this.indexBuffer = indexBuffer; /** * The vertex buffers containing attribute data for this VAO, * alongside the relevant attribute layout. * * @name Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#attributeBufferLayouts * @type {Phaser.Renderer.WebGL.Wrappers.WebGLVertexBufferLayoutWrapper[]} * @since 4.0.0 */ this.attributeBufferLayouts = attributeBufferLayouts; /** * The state object used to bind this VAO. * * @name Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#glState * @type {object} * @since 4.0.0 */ this.glState = { vao: this }; this.createResource(); }, /** * Creates a new WebGLVertexArrayObject and records the full vertex * attribute configuration into it. This includes binding the optional * index buffer, enabling each vertex attribute array, setting up the * attribute pointers (including per-column pointers for matrix * attributes), and applying instance divisors for instanced rendering. * Once the VAO is fully configured it is unbound, along with any array * and element-array buffers, to leave the WebGL state clean. * * This method is called automatically by the constructor. It is also * called by the WebGLRenderer when the WebGL context is restored after * a context loss event. * * @method Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#createResource * @since 4.0.0 */ createResource: function () { var gl = this.renderer.gl; this.vertexArrayObject = gl.createVertexArray(); this.bind(); if (this.indexBuffer) { this.indexBuffer.bind(); } var program = this.program; var glAttributes = program.glAttributes; var glAttributeNames = program.glAttributeNames; for (var i = 0; i < this.attributeBufferLayouts.length; i++) { var attributeBufferLayout = this.attributeBufferLayouts[i]; attributeBufferLayout.buffer.bind(); var stride = attributeBufferLayout.layout.stride; var instanceDivisor = attributeBufferLayout.layout.instanceDivisor; for (var j = 0; j < attributeBufferLayout.layout.layout.length; j++) { var layout = attributeBufferLayout.layout.layout[j]; // Connect attribute locations from program. var attributeIndex = glAttributeNames.get(layout.name); if (attributeIndex === undefined) { // This attribute is not used in the shader, so skip it. continue; } var attributeInfo = glAttributes[attributeIndex]; layout.location = attributeInfo.location; // Create attribute pointers. var location = layout.location; var bytes = layout.bytes || 4; var columns = layout.columns || 1; var normalized = layout.normalized; var offset = layout.offset; var size = layout.size; var type = layout.type; for (var column = 0; column < columns; column++) { gl.enableVertexAttribArray(location + column); gl.vertexAttribPointer( location + column, size, type, normalized, stride, offset + bytes * column * size ); if (!isNaN(instanceDivisor)) { gl.vertexAttribDivisor( location + column, instanceDivisor ); } } } } // Finalize VAO. this.renderer.glWrapper.updateVAO({ vao: null }); // Force unbind buffers, as they may have been unbound by the VAO // without syncing state management. this.renderer.glWrapper.updateBindings({ bindings: { arrayBuffer: null, elementArrayBuffer: null } }); }, /** * Binds this WebGLVAOWrapper to the current WebGLRenderingContext. * * @method Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#bind * @since 4.0.0 */ bind: function () { this.renderer.glWrapper.updateVAO(this.glState); }, /** * Destroys this WebGLVAOWrapper and removes all associated resources. * * @method Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper#destroy * @since 4.0.0 */ destroy: function () { var gl = this.renderer.gl; if (this.vertexArrayObject) { gl.deleteVertexArray(this.vertexArrayObject); this.vertexArrayObject = null; } this.indexBuffer = null; this.attributeBufferLayouts = null; this.glState = null; this.renderer = null; } }); module.exports = WebGLVAOWrapper;