From b5264ae40518231e37c80c368e8f0c8b199befb7 Mon Sep 17 00:00:00 2001 From: Ben Richards Date: Mon, 15 Jul 2024 20:57:40 +1200 Subject: [PATCH] Enable instanced rendering. --- src/renderer/webgl/WebGLRenderer.js | 35 +++++++++++++++++++ .../typedefs/WebGLAttributeBufferLayout.js | 1 + .../webgl/wrappers/WebGLVAOWrapper.js | 15 ++++++++ 3 files changed, 51 insertions(+) diff --git a/src/renderer/webgl/WebGLRenderer.js b/src/renderer/webgl/WebGLRenderer.js index 4a161826c..b7ae039f1 100644 --- a/src/renderer/webgl/WebGLRenderer.js +++ b/src/renderer/webgl/WebGLRenderer.js @@ -3011,6 +3011,41 @@ var WebGLRenderer = new Class({ gl.drawElements(topology || gl.TRIANGLE_STRIP, count, gl.UNSIGNED_SHORT, offset); }, + /** + * Draw a number of instances to a drawing context. + * + * This draws vertices using the ANGLE_instanced_arrays extension. + * This typically uses an instance buffer and a vertex buffer. + * Both should be bound to the VAO. Vertices are drawn as a `TRIANGLE_STRIP` by default. + * + * It does not upload vertex data to buffers. Ensure that this is done + * before calling this method. + * + * @method Phaser.Renderer.WebGL.WebGLRenderer#drawInstancedArrays + * @since 3.90.0 + * @param {Phaser.Renderer.WebGL.DrawingContext} drawingContext - The DrawingContext to draw to. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLTextureWrapper[]} textures - An array of textures to bind. Textures are bound to units corresponding to their indices in the array. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLProgramWrapper} program - The shader program to use. + * @param {Phaser.Renderer.WebGL.Wrappers.WebGLVAOWrapper} vao - The Vertex Array Object to bind. It does not need an index buffer attached. + * @param {number} first - The starting index in the array of vector points. + * @param {number} count - The number of vertices to draw. + * @param {number} instanceCount - The number of instances to render. + */ + drawInstancedArrays: function (drawingContext, textures, program, vao, first, count, instanceCount, topology) + { + var gl = this.gl; + + drawingContext.beginDraw(); + + program.bind(); + + vao.bind(); + + this.glTextureUnits.bindUnits(textures); + + this.instancedArraysExtension.drawArraysInstancedANGLE(topology || gl.TRIANGLE_STRIP, first, count, instanceCount); + }, + /** * Disables the STENCIL_TEST but does not change the status * of the current stencil mask. diff --git a/src/renderer/webgl/typedefs/WebGLAttributeBufferLayout.js b/src/renderer/webgl/typedefs/WebGLAttributeBufferLayout.js index 17aaf20a1..a8873aa72 100644 --- a/src/renderer/webgl/typedefs/WebGLAttributeBufferLayout.js +++ b/src/renderer/webgl/typedefs/WebGLAttributeBufferLayout.js @@ -25,5 +25,6 @@ * @property {number} stride - The stride of the attribute data. * @property {number} count - The maximum number of elements in the buffer. * @property {GLenum|string} usage - The usage pattern of the data store. gl.STATIC_DRAW, gl.DYNAMIC_DRAW or gl.STREAM_DRAW. If the type is a string, it will be converted to the appropriate GLenum, e.g. 'STATIC_DRAW' to gl.STATIC_DRAW. + * @property {number} [instanceDivisor] - The instance divisor of the attribute data. This is how many vertices to draw before moving to the next one. It is only used for instanced rendering. * @property {Phaser.Types.Renderer.WebGL.WebGLAttributeLayout} layout - The layout of the attribute data. */ diff --git a/src/renderer/webgl/wrappers/WebGLVAOWrapper.js b/src/renderer/webgl/wrappers/WebGLVAOWrapper.js index f02b3fff5..392ec2f4b 100644 --- a/src/renderer/webgl/wrappers/WebGLVAOWrapper.js +++ b/src/renderer/webgl/wrappers/WebGLVAOWrapper.js @@ -92,12 +92,18 @@ var WebGLVAOWrapper = new Class({ { var gl = this.renderer.gl; var extVAO = this.renderer.vaoExtension; + var extInstance = this.renderer.instancedArraysExtension; if (!extVAO) { throw new Error('WebGLVertexArrayObject not supported by this browser'); } + if (!extInstance) + { + throw new Error('ANGLE_instanced_arrays extension not supported by this browser'); + } + this.vertexArrayObject = extVAO.createVertexArrayOES(); this.bind(); @@ -113,6 +119,7 @@ var WebGLVAOWrapper = new Class({ attributeBufferLayout.buffer.bind(); var stride = attributeBufferLayout.layout.stride; + var instanceDivisor = attributeBufferLayout.layout.instanceDivisor; for (var j = 0; j < attributeBufferLayout.layout.layout.length; j++) { @@ -139,6 +146,14 @@ var WebGLVAOWrapper = new Class({ stride, offset + bytes * column * size ); + + if (!isNaN(instanceDivisor)) + { + extInstance.vertexAttribDivisorANGLE( + location + column, + instanceDivisor + ); + } } } }