Source: Graphics/WebGL/AxWebGLGraphicsDevice.js

/**
 * Creates a new graphics device
 * @constructor
 */
function AxWebGLGraphicsDevice()
{
    this.gl = null;
    
    this.width = 0;
    this.height = 0;
    
    this.currentMesh = null;
    this.currentShader = null;
    
    this.currentRenderTarget = null;
    
    this.cullMode = AxRenderState.CullBackFace;
}



/**
 * Creates a new mesh for the respective device
 * @return {AxGraphicsDeviceMesh} New mesh for the respective device
 */
AxWebGLGraphicsDevice.prototype.CreateMesh = function()
{
    var result = new AxWebGLMesh();
    result.context = this;
    return result;
};

/**
 * Creates a new texture for the respective device
 * @return {AxDeviceTexture2D} New texture for the respective device
 */
AxWebGLGraphicsDevice.prototype.CreateTexture = function()
{
    var result = new AxWebGLTexture2D();
    result.context = this;
    return result;
};

/**
 * Creates a new shader for the respective device
 * @return {AxDeviceShader} New shader for the respective device
 */
AxWebGLGraphicsDevice.prototype.CreateShader = function()
{
    var result = new AxWebGLShader();
    result.context = this;
    return result;
};



/**
 * Sets a target window for presenting the rendering result
 * @param {Canvas} windowHandle Canvas to use for presenting the rendering result
 * @return {Bool} New mesh for the respective device
 */
AxWebGLGraphicsDevice.prototype.SetRenderTargetWindow = function(windowHandle)
{
    if (this.gl === null)
    {
        try 
        {
            this.gl = this.GetGLContext(windowHandle);

            this.gl.enable(this.gl.DEPTH_TEST);
            
            this.gl.enable(this.gl.CULL_FACE);
            this.gl.frontFace(this.gl.CW);
            this.gl.cullFace(this.gl.BACK);
            //
            //this.gl.depthFunc(this.gl.LESSER);
            //this.gl.disable(this.gl.BLEND);
//            this.gl.disable(this.gl.CULL_FACE);
//            this.gl.disable(this.gl.DEPTH_TEST);
//            this.gl.enable(this.gl.BLEND);
//            this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
            


            this.SetViewport(0, 0, windowHandle.width, windowHandle.height);
        }
        catch (e) 
        {
        }

        if (!this.gl) 
        {
            console.log("Could not initialize WebGL Graphics Device");
        }
    }
    else
    {
        this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
        
        this.currentRenderTarget = null;
    
        this.SetViewport(0, 0, this.width, this.height);
    }
};

/**
 * Sets a target texture to render onto
 * @param {AxDeviceTexture2D} texture Texture to use for rendering onto
 * @return {Bool} True if the render target was set successfully
 */
AxWebGLGraphicsDevice.prototype.SetRenderTargetTexture = function(texture)
{
    var glTexture = texture;
    
    if (this.currentRenderTarget === texture)
        return true;
    
    if (!glTexture.isFrameBuffer)
    {
        glTexture.Update(null, glTexture.width, glTexture.height, true);
    }
    
    this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, glTexture.frameBuffer);
    
    this.currentRenderTarget = texture;

    this.gl.clear(this.gl.DEPTH_BUFFER_BIT);

    this.SetViewport(0, 0, glTexture.width, glTexture.height);
    
    return true;
};



/**
 * Gets the pixel format of the device
 * @return {AxPixelFormat} The pixel format of the device
 */
AxWebGLGraphicsDevice.prototype.GetPixelFormat = function()
{
    return new AxPixelFormat(4, 4, 8, 8, 8, 8, AxPixelFormat.ChannelIdRed, AxPixelFormat.ChannelIdGreen, AxPixelFormat.ChannelIdBlue, AxPixelFormat.ChannelIdAlpha);
};



/**
 * Clears the frame buffer with a specified color
 * @param {AxVector4} color Color to cleare the frame buffer with
 */
AxWebGLGraphicsDevice.prototype.ClearScreen = function(color)
{
    this.gl.clearColor(color.x, color.y, color.z, color.w);
    this.gl.clear(this.gl.COLOR_BUFFER_BIT);
};

/**
 * Clears the depth buffer
 */
AxWebGLGraphicsDevice.prototype.ClearDepthBuffer = function() 
{
    this.gl.clear(this.gl.DEPTH_BUFFER_BIT);
};



/**
 * Begins rendering a new scene.
 * This method should be called before rendering a new frame
 */
AxWebGLGraphicsDevice.prototype.BeginScene = function() { };

/**
 * Ends rendering of a scene.
 * This method should be called after all rendering in a frame is done
 */
AxWebGLGraphicsDevice.prototype.EndScene = function() { };



/**
 * Sets the viewport of the frame buffer
 * @param {Integer} x Left boundary in pixels of the viewport
 * @param {Integer} y Top boundary in pixels of the viewport
 * @param {Integer} width Width in pixels of the viewport
 * @param {Integer} height Height in pixels of the viewport
 */
AxWebGLGraphicsDevice.prototype.SetViewport = function(x, y, width, height)
{
    this.gl.viewport(x, y, width, height);
    
    if (this.currentRenderTarget === null)
    {
        this.width = width;
        this.height = height;
    }
};



/**
 * Sets the mesh to render
 * @param {AxDeviceMesh} mesh The mesh to be rendered
 */
AxWebGLGraphicsDevice.prototype.SetMesh = function(mesh)
{
    this.currentMesh = mesh;
};

/**
 * Sets the rendering shader
 * @param {AxDeviceShader} shader The shader to be set
 */
AxWebGLGraphicsDevice.prototype.SetShader = function(shader)
{
    this.currentShader = shader;
    
    this.currentShader.setTextureIndex = 0;
    
    this.gl.useProgram(this.currentShader.shaderProgram);
    
    var viewProjectionMatrix = new AxMatrix();
    AxMatrix.Multiply(viewProjectionMatrix, this.currentShader.viewMatrix, this.currentShader.projectionMatrix);
    this.currentShader.SetParameter(this.currentShader.viewProjectionMatrixAddress, 0, viewProjectionMatrix);
    
    if (this.currentShader.isSkeletalAnimated)
        this.gl.uniformMatrix4fv(this.currentShader.worldMatrixAddress, false, this.currentShader.bones);

    if (this.currentShader.lightsPosIntensityAddress !== -1)
        this.gl.uniform4fv(this.currentShader.lightsPosIntensityAddress, this.currentShader.lightsPosIntensity);
    
    if (this.currentShader.lightsColorAddress !== -1)
        this.gl.uniform4fv(this.currentShader.lightsColorAddress, this.currentShader.lightsColor);
};

/**
 * Sets the render state
 * The render state represents a set of settings for the graphics device
 * @param {AxRenderState} renderState The rendering state to be set
 */
AxWebGLGraphicsDevice.prototype.SetRenderState = function(renderState) 
{
    switch (renderState)
    {
        case AxRenderState.CullBackFace:
        {
            if (this.cullMode !== renderState)
            {
                this.gl.enable(this.gl.CULL_FACE);
                this.gl.cullFace(this.gl.BACK);
                
                this.cullMode = renderState;
            }

            break;
        }

        case AxRenderState.CullFrontFace:
        {
            if (this.cullMode !== renderState)
            {
                this.gl.enable(this.gl.CULL_FACE);
                this.gl.cullFace(this.gl.FRONT);

                this.cullMode = renderState;
            }

            break;
        }

        case AxRenderState.CullNone:
        {
            if (this.cullMode !== renderState)
            {
                this.gl.disable(this.gl.CULL_FACE);

                this.cullMode = renderState;
            }

            break;
        }
    }
};



/**
 * Renders the mesh set to the device using the set shader and device settings
 */
AxWebGLGraphicsDevice.prototype.RenderMesh = function()
{
    if (this.currentShader.vertexPositionAttribute !== -1)
    {
        this.gl.enableVertexAttribArray(this.currentShader.vertexPositionAttribute);
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.currentMesh.verticesPositionsBuffer);
        this.gl.vertexAttribPointer(this.currentShader.vertexPositionAttribute, this.currentMesh.vertexPositionElementsCount, this.gl.FLOAT, false, 0, 0);
    }

    if (this.currentShader.vertexTexCoordsAttribute !== -1)
    {
        this.gl.enableVertexAttribArray(this.currentShader.vertexTexCoordsAttribute);
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.currentMesh.verticesTexCoordsBuffer);
        this.gl.vertexAttribPointer(this.currentShader.vertexTexCoordsAttribute, this.currentMesh.vertexTexCoordsElementsCount, this.gl.FLOAT, false, 0, 0);
    }

    if (this.currentShader.vertexNormalAttribute !== -1)
    {
        this.gl.enableVertexAttribArray(this.currentShader.vertexNormalAttribute);
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.currentMesh.verticesNormalsBuffer);
        this.gl.vertexAttribPointer(this.currentShader.vertexNormalAttribute, this.currentMesh.vertexNormalElementsCount, this.gl.FLOAT, false, 0, 0);
    }
    
    if (this.currentShader.vertexBoneIndicesAttribute !== -1)
    {
        this.gl.enableVertexAttribArray(this.currentShader.vertexBoneIndicesAttribute);
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.currentMesh.verticesBoneIndicesBuffer);
        this.gl.vertexAttribPointer(this.currentShader.vertexBoneIndicesAttribute, this.currentMesh.vertexBoneIndicesElementsCount, this.gl.FLOAT, false, 0, 0);
    }
    
    if (this.currentShader.vertexBoneWeightsAttribute !== -1)
    {
        this.gl.enableVertexAttribArray(this.currentShader.vertexBoneWeightsAttribute);
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.currentMesh.verticesBoneWeightsBuffer);
        this.gl.vertexAttribPointer(this.currentShader.vertexBoneWeightsAttribute, this.currentMesh.vertexBoneWeightsElementsCount, this.gl.FLOAT, false, 0, 0);
    }

    if (this.currentShader.vertexTangentsAttribute !== -1)
    {
        this.gl.enableVertexAttribArray(this.currentShader.vertexTangentsAttribute);
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.currentMesh.verticesTangentBuffer);
        this.gl.vertexAttribPointer(this.currentShader.vertexTangentsAttribute, this.currentMesh.vertexTangentElementsCount, this.gl.FLOAT, false, 0, 0);
    }
    
    if (this.currentShader.vertexBitangentsAttribute !== -1)
    {
        this.gl.enableVertexAttribArray(this.currentShader.vertexBitangentsAttribute);
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.currentMesh.verticesBitangentBuffer);
        this.gl.vertexAttribPointer(this.currentShader.vertexBitangentsAttribute, this.currentMesh.vertexBitangentElementsCount, this.gl.FLOAT, false, 0, 0);
    }
   

    
    this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.currentMesh.indicesBuffer);

    this.gl.drawElements(this.gl.TRIANGLES, this.currentMesh.indicesCount, this.gl.UNSIGNED_SHORT, 0);
};



/**
 * Presents the frame buffer on the screen to the set rendering target window
 * @return {Boolean} True if presenting succeeded.
 */
AxWebGLGraphicsDevice.prototype.Present = function()
{
    
};


/**
 * Gets a GL context from the given canvas element
 * @param {Canvas} canvas The canvas element to get GL context from
 * @return {WebGLContext} If succeeded, a GL context is returned. If failed null is returned
 */
AxWebGLGraphicsDevice.prototype.GetGLContext = function(canvas) 
{
    var glContextCandidateNames = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
    var context = null;
    
    for (var i = 0; (i < glContextCandidateNames.length) && (context === null); i++)
        context = canvas.getContext(glContextCandidateNames[i]);

    return context;
};

Documentation generated by JSDoc 3.5.3 on Mon Feb 19 2018 20:39:26 GMT+0200 (FLE Standard Time)