From 1f8702e323f77570d8814513b6db51ac84449bf6 Mon Sep 17 00:00:00 2001 From: Felipe Alfonso Date: Mon, 27 Feb 2017 17:41:52 -0300 Subject: [PATCH] Shape batch rendering base --- v3/src/renderer/webgl/WebGLRenderer.js | 3 + .../webgl/batches/shape/FragmentShader.js | 7 + .../webgl/batches/shape/ShapeBatch.js | 151 ++++++++++++++++++ .../webgl/batches/shape/VertexShader.js | 10 ++ v3/src/renderer/webgl/batches/shape/const.js | 20 +++ 5 files changed, 191 insertions(+) create mode 100644 v3/src/renderer/webgl/batches/shape/FragmentShader.js create mode 100644 v3/src/renderer/webgl/batches/shape/ShapeBatch.js create mode 100644 v3/src/renderer/webgl/batches/shape/VertexShader.js create mode 100644 v3/src/renderer/webgl/batches/shape/const.js diff --git a/v3/src/renderer/webgl/WebGLRenderer.js b/v3/src/renderer/webgl/WebGLRenderer.js index d0f9666d5..49a483545 100644 --- a/v3/src/renderer/webgl/WebGLRenderer.js +++ b/v3/src/renderer/webgl/WebGLRenderer.js @@ -11,6 +11,7 @@ var CreateTexture2DImage = require('./utils/texture/CreateTexture2DImage'); var BlitterBatch = require('./batches/blitter/BlitterBatch'); var AAQuadBatch = require('./batches/aaquad/AAQuadBatch'); var SpriteBatch = require('./batches/sprite/SpriteBatch'); +var ShapeBatch = require('./batches/shape/ShapeBatch'); var BlendModes = require('../BlendModes'); var WebGLRenderer = function (game) @@ -48,6 +49,7 @@ var WebGLRenderer = function (game) this.blitterBatch = null; this.aaQuadBatch = null; this.spriteBatch = null; + this.shapeBatch = null; this.batch = null; this.currentTexture2D = null; @@ -99,6 +101,7 @@ WebGLRenderer.prototype = { this.blitterBatch = this.addBatch(new BlitterBatch(this.game, gl, this)); this.aaQuadBatch = this.addBatch(new AAQuadBatch(this.game, gl, this)); this.spriteBatch = this.addBatch(new SpriteBatch(this.game, gl, this)); + this.shapeBatch = this.addBatch(new ShapeBatch(this.game, gl, this)); }, createTexture2D: function (source) diff --git a/v3/src/renderer/webgl/batches/shape/FragmentShader.js b/v3/src/renderer/webgl/batches/shape/FragmentShader.js new file mode 100644 index 000000000..1be602a16 --- /dev/null +++ b/v3/src/renderer/webgl/batches/shape/FragmentShader.js @@ -0,0 +1,7 @@ +module.exports = [ + 'precision mediump float;', + 'varying vec4 v_color;', + 'void main() {', + ' gl_FragColor = v_color;', + '}' +].join('\n'); diff --git a/v3/src/renderer/webgl/batches/shape/ShapeBatch.js b/v3/src/renderer/webgl/batches/shape/ShapeBatch.js new file mode 100644 index 000000000..c80d117d3 --- /dev/null +++ b/v3/src/renderer/webgl/batches/shape/ShapeBatch.js @@ -0,0 +1,151 @@ +var BindVertexArray = require('../../utils/vao/BindVertexArray'); +var CreateProgram = require('../../utils/shader/CreateProgram'); +var CreateShader = require('../../utils/shader/CreateShader'); +var CreateBuffer = require('../../utils/buffer/CreateBuffer'); +var CreateAttribDesc = require('../../utils/vao/CreateAttribDesc'); +var Buffer32 = require('../../utils/buffer/Buffer32'); +var VertexArray = require('../../utils/vao/VertexArray'); + +var PHASER_CONST = require('../../../../const'); +var CONST = require('./const'); + +var ShapeBatch = function (game, gl, manager) +{ + this.game = game; + this.type = PHASER_CONST.WEBGL; + this.view = game.canvas; + this.resolution = game.config.resolution; + this.width = game.config.width * game.config.resolution; + this.height = game.config.height * game.config.resolution; + this.glContext = gl; + this.maxVertices = null; + this.vertShader = null; + this.fragShader = null; + this.program = null; + this.vertexArray = null; + this.vertexDataBuffer = null; + this.vertexCount = 0; + this.viewMatrixLocation = null; + + // All of these settings will be able to be controlled via the Game Config + this.config = { + clearBeforeRender: true, + transparent: false, + autoResize: false, + preserveDrawingBuffer: false, + + WebGLContextOptions: { + alpha: true, + antialias: true, + premultipliedAlpha: true, + stencil: true, + preserveDrawingBuffer: false + } + }; + + this.manager = manager; + this.dirty = false; + + this.init(this.glContext); +}; + +ShapeBatch.prototype.constructor = ShapeBatch; + +ShapeBatch.prototype = { + + init: function (gl) + { + + var vertexDataBuffer = new Buffer32(CONST.VERTEX_SIZE * CONST.MAX_VERTICES); + var vertShader = CreateShader(gl, CONST.VERTEX_SHADER_SOURCE, gl.VERTEX_SHADER); + var fragShader = CreateShader(gl, CONST.FRAGMENT_SHADER_SOURCE, gl.FRAGMENT_SHADER); + var program = CreateProgram(gl, vertShader, fragShader); + var attribArray = [ + CreateAttribDesc(gl, program, 'a_position', 2, gl.FLOAT, false, CONST.VERTEX_SIZE, 0), + CreateAttribDesc(gl, program, 'a_color', 4, gl.FLOAT, true, CONST.VERTEX_SIZE, 8), + ]; + var vertexArray = new VertexArray(CreateBuffer(gl, gl.ARRAY_BUFFER, gl.STREAM_DRAW, null, vertexDataBuffer.getByteCapacity()), attribArray); + var viewMatrixLocation = gl.getUniformLocation(program, 'u_view_matrix'); + var max = CONST.MAX_VERTICES; + + this.vertexDataBuffer = vertexDataBuffer; + this.vertShader = vertShader; + this.fragShader = fragShader; + this.program = program; + this.vertexArray = vertexArray; + this.viewMatrixLocation = viewMatrixLocation; + this.maxVertices = max; + + this.bind(); + this.resize(this.width, this.height, this.game.config.resolution); + this.unbind(); + }, + + isFull: function () + { + return (this.vertexDataBuffer.getByteLength() >= this.vertexDataBuffer.getByteCapacity()); + }, + + bind: function () + { + var gl = this.glContext; + + gl.useProgram(this.program); + gl.clearColor(0, 0, 0, 1); + BindVertexArray(gl, this.vertexArray); + }, + + unbind: function () + { + var gl = this.glContext; + + gl.useProgram(null); + gl.bindBuffer(gl.ARRAY_BUFFER, null); + }, + + flush: function () + { + var gl = this.glContext; + var vertexDataBuffer = this.vertexDataBuffer; + + gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertexDataBuffer.getUsedBufferAsFloat()); + gl.drawArrays(gl.TRIANGLES, 0, this.vertexCount); + vertexDataBuffer.clear(); + + this.vertexCount = 0; + }, + + resize: function (width, height, resolution) + { + var gl = this.glContext; + + this.width = width * resolution; + this.height = height * resolution; + + gl.uniformMatrix4fv( + this.viewMatrixLocation, + false, + new Float32Array([ + 2 / this.width, 0, 0, 0, + 0, -2 / this.height, 0, 0, + 0, 0, 1, 1, + -1, 1, 0, 0 + ]) + ); + }, + + destroy: function () + { + var gl = this.glContext; + + if (gl) + { + gl.deleteShader(this.vertShader); + gl.deleteShader(this.fragShader); + gl.deleteProgram(this.program); + gl.deleteBuffer(this.vertexArray.buffer); + } + } +}; + +module.exports = ShapeBatch; diff --git a/v3/src/renderer/webgl/batches/shape/VertexShader.js b/v3/src/renderer/webgl/batches/shape/VertexShader.js new file mode 100644 index 000000000..315134c9a --- /dev/null +++ b/v3/src/renderer/webgl/batches/shape/VertexShader.js @@ -0,0 +1,10 @@ +module.exports = [ + 'uniform mat4 u_view_matrix;', + 'attribute vec2 a_position;', + 'attribute vec4 a_color;', + 'varying vec4 v_color;', + 'void main () {', + ' gl_Position = u_view_matrix * vec4(a_position, 1.0, 1.0);', + ' v_color = a_color;', + '}' +].join('\n'); diff --git a/v3/src/renderer/webgl/batches/shape/const.js b/v3/src/renderer/webgl/batches/shape/const.js new file mode 100644 index 000000000..d1f363ea9 --- /dev/null +++ b/v3/src/renderer/webgl/batches/shape/const.js @@ -0,0 +1,20 @@ +var FragmentShader = require('./FragmentShader'); +var VertexShader = require('./VertexShader'); + +var CONST = { + + // VERTEX_SIZE = sizeof(vec2) + sizeof(uint32) + VERTEX_SIZE: 12, + + // How many 32-bit components does the vertex have. + SHAPE_VERTEX_COMPONENT_COUNT: 5, + + // Can't be bigger than 10,000 since index are 16-bit + MAX_VERTICES: 10000, + + VERTEX_SHADER_SOURCE: VertexShader, + FRAGMENT_SHADER_SOURCE: FragmentShader + +}; + +module.exports = CONST;