diff --git a/src/index.js b/src/index.js index c992b02f54..6a17f0208f 100644 --- a/src/index.js +++ b/src/index.js @@ -20,7 +20,7 @@ import Body from "./physics/body.js"; import Bounds from "./physics/bounds.js"; import Tween from "./tweens/tween.js"; import GLShader from "./video/webgl/glshader.js"; -import WebGLCompositor from "./video/webgl/webgl_compositor.js"; +import WebGLCompositor from "./video/webgl/compositors/webgl_compositor.js"; import Renderer from "./video/renderer.js"; import WebGLRenderer from "./video/webgl/webgl_renderer.js"; import CanvasRenderer from "./video/canvas/canvas_renderer.js"; diff --git a/src/video/webgl/compositors/compositor.js b/src/video/webgl/compositors/compositor.js new file mode 100644 index 0000000000..a67a736179 --- /dev/null +++ b/src/video/webgl/compositors/compositor.js @@ -0,0 +1,227 @@ +import * as event from "../../../system/event.js"; + + +/** + * @classdesc + * A base Compositor object. + */ + export default class Compositor { + /** + * @param {WebGLRenderer} renderer - the current WebGL renderer session + */ + constructor (renderer) { + this.init(renderer); + } + + /** + * Initialize the compositor + * @ignore + */ + init (renderer) { + // local reference + var gl = renderer.gl; + + // the associated renderer + this.renderer = renderer; + + // WebGL context + this.gl = renderer.gl; + + // Global fill color + this.color = renderer.currentColor; + + // Global transformation matrix + this.viewMatrix = renderer.currentTransform; + + /** + * a reference to the active WebGL shader + * @type {GLShader} + */ + this.activeShader = null; + + /** + * primitive type to render (gl.POINTS, gl.LINE_STRIP, gl.LINE_LOOP, gl.LINES, gl.TRIANGLE_STRIP, gl.TRIANGLE_FAN, gl.TRIANGLES) + * @type {number} + * @default gl.TRIANGLES + */ + this.mode = gl.TRIANGLES; + + /** + * an array of vertex attribute properties + * @see WebGLCompositor.addAttribute + * @type {Array} + */ + this.attributes = []; + + /** + * the size of a single vertex in bytes + * (will automatically be calculated as attributes definitions are added) + * @see WebGLCompositor.addAttribute + * @type {number} + */ + this.vertexByteSize = 0; + + /** + * the size of a single vertex in floats + * (will automatically be calculated as attributes definitions are added) + * @see WebGLCompositor.addAttribute + * @type {number} + */ + this.vertexSize = 0; + + // register to the CANVAS resize channel + event.on(event.CANVAS_ONRESIZE, (width, height) => { + this.flush(); + this.setViewport(0, 0, width, height); + }); + } + + /** + * Reset compositor internal state + * @ignore + */ + reset() { + // WebGL context + this.gl = this.renderer.gl; + + this.flush(); + + // initial viewport size + this.setViewport( + 0, 0, + this.renderer.getCanvas().width, + this.renderer.getCanvas().height + ); + + // Initialize clear color + this.clearColor(0.0, 0.0, 0.0, 0.0); + } + + /** + * add vertex attribute property definition to the compositor + * @param {string} name - name of the attribute in the vertex shader + * @param {number} size - number of components per vertex attribute. Must be 1, 2, 3, or 4. + * @param {GLenum} type - data type of each component in the array + * @param {boolean} normalized - whether integer data values should be normalized into a certain range when being cast to a float + * @param {number} offset - offset in bytes of the first component in the vertex attribute array + */ + addAttribute(name, size, type, normalized, offset) { + this.attributes.push({ + name: name, + size: size, + type: type, + normalized: normalized, + offset: offset + }); + + switch (type) { + case this.gl.BYTE: + this.vertexByteSize += size * Int8Array.BYTES_PER_ELEMENT; + break; + case this.gl.UNSIGNED_BYTE: + this.vertexByteSize += size * Uint8Array.BYTES_PER_ELEMENT; + break; + case this.gl.SHORT: + this.vertexByteSize += size * Int16Array.BYTES_PER_ELEMENT; + break; + case this.gl.UNSIGNED_SHORT: + this.vertexByteSize += size * Uint16Array.BYTES_PER_ELEMENT; + break; + case this.gl.INT: + this.vertexByteSize += size * Int32Array.BYTES_PER_ELEMENT; + break; + case this.gl.UNSIGNED_INT: + this.vertexByteSize += size * Uint32Array.BYTES_PER_ELEMENT; + break; + case this.gl.FLOAT: + this.vertexByteSize += size * Float32Array.BYTES_PER_ELEMENT; + break; + default: + throw new Error("Invalid GL Attribute type"); + } + this.vertexSize = this.vertexByteSize / Float32Array.BYTES_PER_ELEMENT; + } + + /** + * Sets the viewport + * @param {number} x - x position of viewport + * @param {number} y - y position of viewport + * @param {number} w - width of viewport + * @param {number} h - height of viewport + */ + setViewport(x, y, w, h) { + this.gl.viewport(x, y, w, h); + } + + /** + * set/change the current projection matrix + * @param {Matrix3d} matrix + */ + setProjection(matrix) { + this.activeShader.setUniform("uProjectionMatrix", matrix); + } + + /** + * Select the shader to use for compositing + * @see GLShader + * @param {GLShader} shader - a reference to a GLShader instance + */ + useShader(shader) { + if (this.activeShader !== shader) { + this.flush(); + this.activeShader = shader; + this.activeShader.bind(); + this.activeShader.setUniform("uProjectionMatrix", this.renderer.projectionMatrix); + this.activeShader.setVertexAttributes(this.gl, this.attributes, this.vertexByteSize); + } + } + + /** + * Flush batched texture operations to the GPU + * @param {number} [mode=gl.TRIANGLES] - the GL drawing mode + */ + flush(mode = this.mode) { + var vertex = this.vertexBuffer; + var vertexCount = vertex.vertexCount; + + if (vertexCount > 0) { + var gl = this.gl; + var vertexSize = vertex.vertexSize; + + // Copy data into stream buffer + if (this.renderer.WebGLVersion > 1) { + gl.bufferData(gl.ARRAY_BUFFER, vertex.toFloat32(), gl.STREAM_DRAW, 0, vertexCount * vertexSize); + } else { + gl.bufferData(gl.ARRAY_BUFFER, vertex.toFloat32(0, vertexCount * vertexSize), gl.STREAM_DRAW); + } + + gl.drawArrays(mode, 0, vertexCount); + + // clear the vertex buffer + vertex.clear(); + } + } + + /** + * Clear the frame buffer + * @param {number} [alpha = 0.0] - the alpha value used when clearing the framebuffer + */ + clear(alpha = 0) { + var gl = this.gl; + gl.clearColor(0, 0, 0, alpha); + gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); + } + + /** + * Specify the color values used when clearing color buffers. The values are clamped between 0 and 1. + * @param {number} [r = 0] - the red color value used when the color buffers are cleared + * @param {number} [g = 0] - the green color value used when the color buffers are cleared + * @param {number} [b = 0] - the blue color value used when the color buffers are cleared + * @param {number} [a = 0] - the alpha color value used when the color buffers are cleared + */ + clearColor(r = 0, g = 0, b = 0, a = 0) { + var gl = this.gl; + gl.clearColor(r, g, b, a); + gl.clear(gl.COLOR_BUFFER_BIT); + } +} diff --git a/src/video/webgl/webgl_compositor.js b/src/video/webgl/compositors/webgl_compositor.js similarity index 57% rename from src/video/webgl/webgl_compositor.js rename to src/video/webgl/compositors/webgl_compositor.js index 6174e7c437..d63c399324 100644 --- a/src/video/webgl/webgl_compositor.js +++ b/src/video/webgl/compositors/webgl_compositor.js @@ -1,12 +1,12 @@ -import Vector2d from "./../../math/vector2.js"; -import GLShader from "./glshader.js"; -import VertexArrayBuffer from "./buffer/vertex.js"; -import * as event from "./../../system/event.js"; -import { isPowerOfTwo } from "./../../math/math.js"; -import primitiveVertex from "./shaders/primitive.vert"; -import primitiveFragment from "./shaders/primitive.frag"; -import quadVertex from "./shaders/quad.vert"; -import quadFragment from "./shaders/quad.frag"; +import Vector2d from "../../../math/vector2.js"; +import GLShader from "../glshader.js"; +import VertexArrayBuffer from "../buffer/vertex.js"; +import { isPowerOfTwo } from "../../../math/math.js"; +import primitiveVertex from "./../shaders/primitive.vert"; +import primitiveFragment from "./../shaders/primitive.frag"; +import quadVertex from "./../shaders/quad.vert"; +import quadFragment from "./../shaders/quad.frag"; +import Compositor from "./compositor.js"; // a pool of resuable vectors var V_ARRAY = [ @@ -20,95 +20,35 @@ var V_ARRAY = [ * @classdesc * A WebGL Compositor object. This class handles all of the WebGL state
* Pushes texture regions or shape geometry into WebGL buffers, automatically flushes to GPU + * @augments Compositor */ - export default class WebGLCompositor { - /** - * @param {WebGLRenderer} renderer - the current WebGL renderer session - */ - constructor (renderer) { - this.init(renderer); - } + export default class WebGLCompositor extends Compositor { /** * Initialize the compositor * @ignore */ init (renderer) { - // local reference - var gl = renderer.gl; + super.init(renderer); // list of active texture units this.currentTextureUnit = -1; this.boundTextures = []; - // the associated renderer - this.renderer = renderer; - - // WebGL context - this.gl = renderer.gl; - - // Global fill color - this.color = renderer.currentColor; - - // Global transformation matrix - this.viewMatrix = renderer.currentTransform; - - /** - * a reference to the active WebGL shader - * @type {GLShader} - */ - this.activeShader = null; - - /** - * primitive type to render (gl.POINTS, gl.LINE_STRIP, gl.LINE_LOOP, gl.LINES, gl.TRIANGLE_STRIP, gl.TRIANGLE_FAN, gl.TRIANGLES) - * @type {number} - * @default gl.TRIANGLES - */ - this.mode = gl.TRIANGLES; - - /** - * an array of vertex attribute properties - * @see WebGLCompositor.addAttribute - * @type {Array} - */ - this.attributes = []; - - /** - * the size of a single vertex in bytes - * (will automatically be calculated as attributes definitions are added) - * @see WebGLCompositor.addAttribute - * @type {number} - */ - this.vertexByteSize = 0; - - /** - * the size of a single vertex in floats - * (will automatically be calculated as attributes definitions are added) - * @see WebGLCompositor.addAttribute - * @type {number} - */ - this.vertexSize = 0; - // Load and create shader programs this.primitiveShader = new GLShader(this.gl, primitiveVertex, primitiveFragment); this.quadShader = new GLShader(this.gl, quadVertex, quadFragment); /// define all vertex attributes - this.addAttribute("aVertex", 2, gl.FLOAT, false, 0 * Float32Array.BYTES_PER_ELEMENT); // 0 - this.addAttribute("aRegion", 2, gl.FLOAT, false, 2 * Float32Array.BYTES_PER_ELEMENT); // 1 - this.addAttribute("aColor", 4, gl.UNSIGNED_BYTE, true, 4 * Float32Array.BYTES_PER_ELEMENT); // 2 + this.addAttribute("aVertex", 2, this.gl.FLOAT, false, 0 * Float32Array.BYTES_PER_ELEMENT); // 0 + this.addAttribute("aRegion", 2, this.gl.FLOAT, false, 2 * Float32Array.BYTES_PER_ELEMENT); // 1 + this.addAttribute("aColor", 4, this.gl.UNSIGNED_BYTE, true, 4 * Float32Array.BYTES_PER_ELEMENT); // 2 this.vertexBuffer = new VertexArrayBuffer(this.vertexSize, 6); // 6 vertices per quad // vertex buffer - gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer()); - gl.bufferData(gl.ARRAY_BUFFER, this.vertexBuffer.buffer, gl.STREAM_DRAW); - - // register to the CANVAS resize channel - event.on(event.CANVAS_ONRESIZE, (width, height) => { - this.flush(); - this.setViewport(0, 0, width, height); - }); + this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.gl.createBuffer()); + this.gl.bufferData(this.gl.ARRAY_BUFFER, this.vertexBuffer.buffer, this.gl.STREAM_DRAW); } /** @@ -116,20 +56,7 @@ var V_ARRAY = [ * @ignore */ reset() { - // WebGL context - this.gl = this.renderer.gl; - - this.flush(); - - // initial viewport size - this.setViewport( - 0, 0, - this.renderer.getCanvas().width, - this.renderer.getCanvas().height - ); - - // Initialize clear color - this.clearColor(0.0, 0.0, 0.0, 0.0); + super.reset(); // delete all related bound texture for (var i = 0; i < this.renderer.maxTextures; i++) { @@ -144,62 +71,6 @@ var V_ARRAY = [ this.useShader(this.quadShader); } - /** - * add vertex attribute property definition to the compositor - * @param {string} name - name of the attribute in the vertex shader - * @param {number} size - number of components per vertex attribute. Must be 1, 2, 3, or 4. - * @param {GLenum} type - data type of each component in the array - * @param {boolean} normalized - whether integer data values should be normalized into a certain range when being cast to a float - * @param {number} offset - offset in bytes of the first component in the vertex attribute array - */ - addAttribute(name, size, type, normalized, offset) { - this.attributes.push({ - name: name, - size: size, - type: type, - normalized: normalized, - offset: offset - }); - - switch (type) { - case this.gl.BYTE: - this.vertexByteSize += size * Int8Array.BYTES_PER_ELEMENT; - break; - case this.gl.UNSIGNED_BYTE: - this.vertexByteSize += size * Uint8Array.BYTES_PER_ELEMENT; - break; - case this.gl.SHORT: - this.vertexByteSize += size * Int16Array.BYTES_PER_ELEMENT; - break; - case this.gl.UNSIGNED_SHORT: - this.vertexByteSize += size * Uint16Array.BYTES_PER_ELEMENT; - break; - case this.gl.INT: - this.vertexByteSize += size * Int32Array.BYTES_PER_ELEMENT; - break; - case this.gl.UNSIGNED_INT: - this.vertexByteSize += size * Uint32Array.BYTES_PER_ELEMENT; - break; - case this.gl.FLOAT: - this.vertexByteSize += size * Float32Array.BYTES_PER_ELEMENT; - break; - default: - throw new Error("Invalid GL Attribute type"); - } - this.vertexSize = this.vertexByteSize / Float32Array.BYTES_PER_ELEMENT; - } - - /** - * Sets the viewport - * @param {number} x - x position of viewport - * @param {number} y - y position of viewport - * @param {number} w - width of viewport - * @param {number} h - height of viewport - */ - setViewport(x, y, w, h) { - this.gl.viewport(x, y, w, h); - } - /** * Create a WebGL texture from an image * @param {number} unit - Destination texture unit @@ -330,13 +201,6 @@ var V_ARRAY = [ return this.currentTextureUnit; } - /** - * set/change the current projection matrix - * @param {Matrix3d} matrix - */ - setProjection(matrix) { - this.activeShader.setUniform("uProjectionMatrix", matrix); - } /** * Select the shader to use for compositing @@ -407,32 +271,6 @@ var V_ARRAY = [ this.vertexBuffer.push(vec3.x, vec3.y, u1, v1, tint); } - /** - * Flush batched texture operations to the GPU - * @param {number} [mode=gl.TRIANGLES] - the GL drawing mode - */ - flush(mode = this.mode) { - var vertex = this.vertexBuffer; - var vertexCount = vertex.vertexCount; - - if (vertexCount > 0) { - var gl = this.gl; - var vertexSize = vertex.vertexSize; - - // Copy data into stream buffer - if (this.renderer.WebGLVersion > 1) { - gl.bufferData(gl.ARRAY_BUFFER, vertex.toFloat32(), gl.STREAM_DRAW, 0, vertexCount * vertexSize); - } else { - gl.bufferData(gl.ARRAY_BUFFER, vertex.toFloat32(0, vertexCount * vertexSize), gl.STREAM_DRAW); - } - - gl.drawArrays(mode, 0, vertexCount); - - // clear the vertex buffer - vertex.clear(); - } - } - /** * Draw an array of vertices * @param {GLenum} mode - primitive type to render (gl.POINTS, gl.LINE_STRIP, gl.LINE_LOOP, gl.LINES, gl.TRIANGLE_STRIP, gl.TRIANGLE_FAN, gl.TRIANGLES) @@ -459,27 +297,4 @@ var V_ARRAY = [ // flush this.flush(mode); } - - /** - * Clear the frame buffer - * @param {number} [alpha = 0.0] - the alpha value used when clearing the framebuffer - */ - clear(alpha = 0) { - var gl = this.gl; - gl.clearColor(0, 0, 0, alpha); - gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); - } - - /** - * Specify the color values used when clearing color buffers. The values are clamped between 0 and 1. - * @param {number} [r = 0] - the red color value used when the color buffers are cleared - * @param {number} [g = 0] - the green color value used when the color buffers are cleared - * @param {number} [b = 0] - the blue color value used when the color buffers are cleared - * @param {number} [a = 0] - the alpha color value used when the color buffers are cleared - */ - clearColor(r = 0, g = 0, b = 0, a = 0) { - var gl = this.gl; - gl.clearColor(r, g, b, a); - gl.clear(gl.COLOR_BUFFER_BIT); - } } diff --git a/src/video/webgl/webgl_renderer.js b/src/video/webgl/webgl_renderer.js index 758639f774..3b14802f8a 100644 --- a/src/video/webgl/webgl_renderer.js +++ b/src/video/webgl/webgl_renderer.js @@ -1,6 +1,6 @@ import Color from "./../../math/color.js"; import Matrix2d from "./../../math/matrix2.js"; -import WebGLCompositor from "./webgl_compositor.js"; +import WebGLCompositor from "./compositors/webgl_compositor.js"; import Renderer from "./../renderer.js"; import TextureCache from "./../texture/cache.js"; import { TextureAtlas, createAtlas } from "./../texture/atlas.js";