/*
* File: gl.js
*
* handles initialization with gl
*
*/
"use strict";
let mCanvas = null;
let mGL = null;
/**
* Handles the WebGL2 context for the engine and stenciling functions
* <p>Found in Chapter 3, page 67 of the textbook</p>
* Example:
* {@link https://mylesacd.github.io/build-your-own-2d-game-engine-2e-doc/BookSourceCode/chapter3/3.1.renderable_objects/index.html 3.1 Renderable Objects}
*
* @module gl
*/
/**
* Returns the WebGL2 context for the canvas
* @static
* @returns {WebGL2RenderingContext} rendering context
*/
function get() { return mGL; }
/**
* Closes the canvas and the rendering context with a shut down message
* @static
*/
function cleanUp() {
if ((mGL == null) || (mCanvas == null))
throw new Error("Engine cleanup: system is not initialized.");
mGL = null;
// let the user know
mCanvas.style.position = "fixed";
mCanvas.style.backgroundColor = "rgba(200, 200, 200, 0.5)";
mCanvas = null;
document.body.innerHTML += "<br><br><h1>End of Game</h1><h1>GL System Shut Down</h1>";
}
/**
* Initializes the canvas and rendering context
* @static
* @param {string} htmlCanvasID - the id of the canvas element
* @returns {void} returns early if the WebGL2 context is null
*/
function init(htmlCanvasID) {
mCanvas = document.getElementById(htmlCanvasID);
if (mCanvas == null)
throw new Error("Engine init [" + htmlCanvasID + "] HTML element id not found");
// Thanks to Arsen Mazmanyan (Birdman1104 @github) for pointing out that experimental-webgl2 has been deprecated
// Get the webgl and binds to the Canvas area
// store the results to the instance variable mGL
mGL = mCanvas.getContext("webgl2", {alpha: false, depth: true, stencil: true});
if (mGL === null) {
document.write("<br><b>WebGL 2 is not supported!</b>");
return;
}
// Allows transparency with textures.
mGL.blendFunc(mGL.SRC_ALPHA, mGL.ONE_MINUS_SRC_ALPHA);
mGL.enable(mGL.BLEND);
// Set images to flip y axis to match the texture coordinate space.
mGL.pixelStorei(mGL.UNPACK_FLIP_Y_WEBGL, true);
// make sure depth testing is enabled
mGL.enable(mGL.DEPTH_TEST);
mGL.depthFunc(mGL.LEQUAL);
}
/**
* Begins drawing using a stencil
* @static
* @param {int} bit - reference value for the stencil test
* @param {GLuint} mask - bit-wise mask that is used in comparison
*/
function beginDrawToStencil(bit, mask)
{
mGL.clear(mGL.STENCIL_BUFFER_BIT);
mGL.enable(mGL.STENCIL_TEST);
mGL.colorMask(false, false, false, false);
mGL.depthMask(false);
mGL.stencilFunc(mGL.NEVER, bit, mask);
mGL.stencilOp(mGL.REPLACE, mGL.KEEP, mGL.KEEP);
mGL.stencilMask(mask);
}
/**
* Sets the rendering context to use normal drawing method
* @static
* @param {int} bit - reference value for the stencil test
* @param {GLuint} mask - bit-wise mask that is used in comparison
*/
function endDrawToStencil(bit, mask)
{
mGL.depthMask(mGL.TRUE);
mGL.stencilOp(mGL.KEEP, mGL.KEEP, mGL.KEEP);
mGL.stencilFunc(mGL.EQUAL, bit, mask);
mGL.colorMask(true, true, true, true);
}
/**
* Disables stencil rendering
* @static
*/
function disableDrawToStencil() {
mGL.disable(mGL.STENCIL_TEST);
}
export {
get, init, cleanUp,
// stencil support
disableDrawToStencil, beginDrawToStencil, endDrawToStencil
}