UNPKG

seed-engine

Version:

A Lightweight 2D game engine using WebGL2. The engine is designed on the focus of creating a bridge between creating and publishing games to the Seed Network as modules.

168 lines (154 loc) 6.67 kB
import Manager from './Manager'; import DOMManager from './DOMManager'; import * as VertexShader from '../const/VertexShader'; import * as FragmentShader from '../const/FragmentShader'; /** * Manages WebGL Programs so that they only need to be created once across the engine * allowing multiple objects to still share the same reference. * * Elliminates the need for the programmer to compile shaders and create programs, and eases * on-the-fly Shader compiling. */ export class _ProgramManager extends Manager { constructor() { super(); this.programIDCounter = 0; this.programs = {}; } /** * Creates default programs for easy reference later on. */ start() { if (DOMManager.GL == null) return; this.addProgram('Default', VertexShader.DEFAULT_V, FragmentShader.DEFAULT_F, { 'u_color': 'uniform4fv', 'u_matrix': 'uniformMatrix3fv', 'u_depth': 'uniform1f', 'u_texture': 'uniform1i', 'u_subTexcoord': 'uniform4fv', }); this.addProgram('2DGrid', VertexShader.DEFAULT_V, FragmentShader.TILEMAP_F, { 'u_color': 'uniform4fv', 'u_matrix': 'uniformMatrix3fv', 'u_depth': 'uniform1f', 'u_mapDataTexture': 'uniform1i', 'u_texture': 'uniform1i', 'u_tileData': 'uniformMatrix4fv' }); } /** * Returns a Program JSON Object containing the program, name and id. * * @param {string} programKey Name of the program. * * @returns {Program Object} Returns a JSON object with Program data. */ getProgram(programKey) { if (this.programs[programKey] == null) throw 'Program does not exist!'; return this.programs[programKey]; } /** * Creates a Program JSON Object and initializes the program and metadata. * The program is added to the programs array. * * @param {string} programName Name of the program. * @param {string} vertexShaderSource Source code of the vertex shader. * @param {string} fragmentShaderSource Source code of the fragment shader. * @param {Object} uniforms An object of 'string': 'number' values indicating the uniform variable name & data type enum value. */ addProgram(programName, vertexShaderSource, fragmentShaderSource, uniforms) { let program = this._createProgram(vertexShaderSource, fragmentShaderSource); let uniformSetters = this._createProgramLocationSetters(program, uniforms); this.programs[programName] = { name: programName, id: this.programIDCounter++, program, uniformSetters, setUniforms: (uniformDataMapping) => { let setters = Object.keys(uniformDataMapping); for (let i = 0; i < setters.length; i++) { uniformSetters[setters[i]](DOMManager.GL, uniformDataMapping[setters[i]]); } } }; } /** * Creates a WebGL program from a compiled vertex and fragment shader. The program is returned. * * @param {CompiledVertexShader} vertexShader A compiled vertex shader. * @param {CompiledFragmentShader} fragmentShader A compiled fragment shader. * * @returns {Program} A WebGL program. Null if unsuccessful. */ _createShadersProgram(vertexShader, fragmentShader) { let program = DOMManager.GL.createProgram(); DOMManager.GL.attachShader(program, vertexShader); DOMManager.GL.attachShader(program, fragmentShader); DOMManager.GL.linkProgram(program); let success = DOMManager.GL.getProgramParameter(program, DOMManager.GL.LINK_STATUS); if (success) { return program; } console.error(DOMManager.GL.getProgramInfoLog(program)); DOMManager.GL.deleteProgram(program); return null; } /** * Creates a shader of either Vertex or Fragment type and returns the compiled version. * * @param {GLShaderType} type A GL shader type of either VERTEX_SHADER or FRAGMENT_SHADER. * @param {string} source Source code for the shader type. * * @returns {CompiledShader} A compiled shader. Null if unsuccessful. */ _createShader(type, source) { let shader = DOMManager.GL.createShader(type); DOMManager.GL.shaderSource(shader, source); DOMManager.GL.compileShader(shader); let success = DOMManager.GL.getShaderParameter(shader, DOMManager.GL.COMPILE_STATUS); if (success) { return shader; } console.error(DOMManager.GL.getShaderInfoLog(shader)); DOMManager.GL.deleteShader(shader); return null; } /** * Compiles the vertex shader and fragment shader and returns a WebGL program. * * @param {string} vertexShaderSource Source code for a vertex shader. * @param {string} fragmentShaderSource Source code for a fragment shader. * * @returns {Program} A program compiled from the two shader sources. */ _createProgram(vertexShaderSource, fragmentShaderSource) { let vertexShader = this._createShader(DOMManager.GL.VERTEX_SHADER, vertexShaderSource); let fragmentShader = this._createShader(DOMManager.GL.FRAGMENT_SHADER, fragmentShaderSource); return this._createShadersProgram(vertexShader, fragmentShader); } _createProgramLocationSetters(program, uniforms) { let uniformLocationSetters = {}; let uniformKeys = Object.keys(uniforms); for (let i = 0; i < uniformKeys.length; i++) { let location = DOMManager.GL.getUniformLocation(program, uniformKeys[i]); uniformLocationSetters[uniformKeys[i]] = this._getUniformSetterFromString(location, uniforms[uniformKeys[i]]); } return uniformLocationSetters; } _getUniformSetterFromString(location, type) { return { 'uniform4fv': (gl, uniformData) => { gl.uniform4fv(location, uniformData); }, 'uniformMatrix3fv': (gl, uniformData) => { gl.uniformMatrix3fv(location, false, uniformData); }, 'uniformMatrix4fv': (gl, uniformData) => { gl.uniformMatrix4fv(location, false, uniformData); }, 'uniform1f': (gl, uniformData) => { gl.uniform1f(location, uniformData); }, 'uniform1i': (gl, uniformData) => { gl.uniform1i(location, uniformData); }, }[type]; } } /** * Singleton reference to the WebGL Program Manager. */ const ProgramManager = new _ProgramManager(); export default ProgramManager;