WebGLRenderer cleanup

This commit is contained in:
Felipe Alfonso 2018-01-20 01:05:56 -03:00
parent 1da31fb2a5
commit 31be6fa51d
3 changed files with 194 additions and 57 deletions

View file

@ -1,7 +1,7 @@
var WebGLSnapshot = function (sourceCanvas, type, encoderOptions)
{
if (type === undefined) { type = 'image/png'; }
if (encoderOptions === undefined) { encoderOptions = 0.92; }
if (!type) { type = 'image/png'; }
if (!encoderOptions) { encoderOptions = 0.92; }
var gl = sourceCanvas.getContext('experimental-webgl');
var pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4);

View file

@ -15,41 +15,13 @@ var WebGLPipeline = new Class({
this.gl = config.gl;
this.vertexCount = 0;
this.vertexCapacity = config.vertexCapacity;
this.manager = config.manager;
this.resources = config.manager.resourceManager;
this.renderer = config.renderer;
this.vertexData = new ArrayBuffer(config.vertexCapacity * config.vertexSize);
this.vertexBuffer = null;
this.program = null;
this.vertexLayout = config.vertexLayout;
this.vertexBuffer = renderer.createVertexBuffer(this.vertexData.byteLength, gl.STREAM_DRAW);
this.program = renderer.createProgram(config.shader.vert, config.shader.frag);
this.attributes = config.attributes;
this.vertexSize = config.vertexSize;
this.topology = config.topology;
// Initialize Shaders and Buffers
{
var gl = this.gl;
var resources = this.resources;
var vertexSize = this.vertexSize;
var vertexLayout = this.vertexLayout;
var program = resources.createShader(this.name, config.shader);
var vertexBuffer = resources.createBuffer(gl.ARRAY_BUFFER, this.vertexData.byteLength, gl.STREAM_DRAW);
for (var key in vertexLayout)
{
var element = vertexLayout[key];
vertexBuffer.addAttribute(
program.getAttribLocation(key),
element.size,
element.type,
element.normalize,
vertexSize,
element.offset
);
}
this.vertexBuffer = vertexBuffer;
this.program = program;
}
},
shouldFlush: function ()
@ -66,12 +38,31 @@ var WebGLPipeline = new Class({
bind: function (overrideProgram)
{
// Check if we're using a custom program or
// the default one from the pipeline.
if (!overrideProgram) this.program.bind();
else overrideProgram.bind();
var gl = this.gl;
var vertexBuffer = this.vertexBuffer;
var attributes = this.attributes;
var program = (!overrideProgram ? this.program : overrideProgram);
var renderer = this.renderer;
var vertexSize = this.vertexSize;
this.vertexBuffer.bind();
renderer.setProgram(program);
renderer.setVertexBuffer(vertexBuffer);
for (var index = 0; index < attributes.length; ++index)
{
var element = attributes[index];
var location = gl.getAttribLocation(program, element.name);
if (location >= 0)
{
gl.enableVertexAttribArray(location);
gl.vertexAttribPointer(location, element.size, element.type, element.normalized, vertexSize, element.offset);
}
else
{
gl.disableVertexAttribArray(location);
}
}
return this;
},
@ -86,7 +77,7 @@ var WebGLPipeline = new Class({
if (vertexCount === 0) return;
vertexBuffer.updateResource(vertexData, 0);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertexData);
gl.drawArrays(topology, 0, vertexCount);
this.vertexCount = 0;
@ -96,10 +87,10 @@ var WebGLPipeline = new Class({
destroy: function ()
{
var resources = this.resources;
var gl = this.gl;
resources.deleteShader(this.program);
resources.deleteBuffer(this.vertexBuffer);
gl.deleteShader(this.program);
gl.deleteBuffer(this.vertexBuffer);
this.program = null;
this.vertexBuffer = null;
@ -109,67 +100,67 @@ var WebGLPipeline = new Class({
setFloat1: function (name, x)
{
this.gl.uniform1f(this.gl.getUniformLocation(this.program.program, name), x);
this.gl.uniform1f(this.gl.getUniformLocation(this.program, name), x);
return this;
},
setFloat2: function (name, x, y)
{
this.gl.uniform2f(this.gl.getUniformLocation(this.program.program, name), x, y);
this.gl.uniform2f(this.gl.getUniformLocation(this.program, name), x, y);
return this;
},
setFloat3: function (name, x, y, z)
{
this.gl.uniform3f(this.gl.getUniformLocation(this.program.program, name), x, y, z);
this.gl.uniform3f(this.gl.getUniformLocation(this.program, name), x, y, z);
return this;
},
setFloat4: function (name, x, y, z, w)
{
this.gl.uniform4f(this.gl.getUniformLocation(this.program.program, name), x, y, z, w);
this.gl.uniform4f(this.gl.getUniformLocation(this.program, name), x, y, z, w);
return this;
},
setInt1: function (name, x)
{
this.gl.uniform1i(this.gl.getUniformLocation(this.program.program, name), x);
this.gl.uniform1i(this.gl.getUniformLocation(this.program, name), x);
return this;
},
setInt2: function (name, x, y)
{
this.gl.uniform2i(this.gl.getUniformLocation(this.program.program, name), x, y);
this.gl.uniform2i(this.gl.getUniformLocation(this.program, name), x, y);
return this;
},
setInt3: function (name, x, y, z)
{
this.gl.uniform3i(this.gl.getUniformLocation(this.program.program, name), x, y, z);
this.gl.uniform3i(this.gl.getUniformLocation(this.program, name), x, y, z);
return this;
},
setInt4: function (name, x, y, z, w)
{
this.gl.uniform4i(this.gl.getUniformLocation(this.program.program, name), x, y, z, w);
this.gl.uniform4i(this.gl.getUniformLocation(this.program, name), x, y, z, w);
return this;
},
setMatrix2: function (name, transpose, matrix)
{
this.gl.uniformMatrix2fv(this.gl.getUniformLocation(this.program.program, name), transpose, matrix);
this.gl.uniformMatrix2fv(this.gl.getUniformLocation(this.program, name), transpose, matrix);
return this;
},
setMatrix3: function (name, transpose, matrix)
{
this.gl.uniformMatrix2fv(this.gl.getUniformLocation(this.program.program, name), transpose, matrix);
this.gl.uniformMatrix2fv(this.gl.getUniformLocation(this.program, name), transpose, matrix);
return this;
},
setMatrix4: function (name, transpose, matrix)
{
this.gl.uniformMatrix2fv(this.gl.getUniformLocation(this.program.program, name), transpose, matrix);
this.gl.uniformMatrix2fv(this.gl.getUniformLocation(this.program, name), transpose, matrix);
return this;
}

View file

@ -1,5 +1,7 @@
var Class = require('../../utils/Class');
var CONST = require('../../const');
var WebGLSnapshot = require('../snapshot/WebGLSnapshot');
var IsSizePowerOfTwo = require('../../math/pow2/IsSizePowerOfTwo');
var WebGLRenderer = new Class({
@ -30,6 +32,11 @@ var WebGLRenderer = new Class({
this.contextLost = false;
this.autoResize = false;
this.pipelines = null;
this.snapshotState = {
callback: null,
type: null,
encoder: null
};
for (var i = 0; i <= 16; i++)
{
@ -108,6 +115,7 @@ var WebGLRenderer = new Class({
resize: function (width, height, resolution)
{
var gl = this.gl;
var piplines = this.pipelines;
this.width = width * resolution;
this.height = height * resolution;
@ -124,6 +132,10 @@ var WebGLRenderer = new Class({
gl.viewport(0, 0, this.width, this.height);
// Update all registered pipelines
for (var pipelineName in pipelines)
{
pipeline[pipelineName].resize(width, height, resolution);
}
return this;
},
@ -145,6 +157,14 @@ var WebGLRenderer = new Class({
return this.extensions[extensionName];
},
flush: function ()
{
if (this.currentPipeline)
{
this.currentPipeline.flush();
}
},
/* Renderer State Manipulation Functions */
hasPipeline: function (pipelineName)
@ -174,18 +194,30 @@ var WebGLRenderer = new Class({
return this;
},
setPipeline: function (pipelineName)
{
var pipeline = this.getPipeline(pipelineName);
if (this.currentPipeline !== pipeline)
{
this.currentPipeline = pipeline;
this.currentPipeline.bind();
}
return pipeline;
},
setBlendMode: function (blendModeId)
{
var gl = this.gl;
var pipeline = this.currentPipeline;
var blendMode = this.blendModes[blendModeId];
if (blendModeId === CONST.BlendModes.SKIP_CHECK || !pipeline)
if (blendModeId === CONST.BlendModes.SKIP_CHECK)
return;
if (this.currentBlendMode !== blendModeId)
{
pipeline.flush();
this.flush();
gl.enable(gl.BLEND);
gl.blendEquation(blendMode.equation);
@ -257,6 +289,44 @@ var WebGLRenderer = new Class({
},
/* Renderer Resource Creation Functions */
createTextureFromSource: function (source, width, height)
{
var gl = this.gl;
var filter = gl.NEAREST;
var wrap = gl.CLAMP_TO_EDGE;
width = source ? source.width : width;
height = source ? source.height : height;
if (IsSizePowerOfTwo(width, height))
{
wrap = gl.REPEAT;
}
if (!source.glTexture)
{
if (source.scaleMode === ScaleModes.LINEAR)
{
filter = gl.LINEAR;
}
else if (source.scaleMode === ScaleModes.NEAREST || this.game.config.pixelArt)
{
filter = gl.NEAREST;
}
if (!source && typeof width === 'number' && typeof height === 'number')
{
source.glTexture = this.createTexture2D(0, filter, filter, wrap, wrap, gl.RGBA, null, width, height);
}
else
{
source.glTexture = this.createTexture2D(0, filter, filter, wrap, wrap, gl.RGBA, source.image);
}
}
return source;
},
createTexture2D: function (mipLevel, minFilter, magFilter, wrapT, wrapS, format, pixels, width, height, pma)
{
var gl = this.gl;
@ -389,6 +459,82 @@ var WebGLRenderer = new Class({
this.setIndexBuffer(null);
return indexBuffer;
},
/* Rendering Functions */
preRender: function ()
{
if (this.contextLost) return;
},
render: function (scene, children, interpolationPercentage, camera)
{
if (this.contextLost) return;
},
postRender: function ()
{
if (this.contextLost) return;
if (this.snapshotState.callback)
{
this.snapshotState.callback(WebGLSnapshot(this.canvas, this.snapshotState.type, this.snapshotState.encoder));
this.snapshotState.callback = null;
}
},
snapshot: function (callback, type, encoderOptions)
{
this.snapshotState.callback = callback;
this.snapshotState.type = type;
this.snapshotState.encoder = encoderOptions;
return this;
},
canvasToTexture: function (srcCanvas, dstTexture, shouldReallocate)
{
var gl = this.gl;
if (!dstTexture)
{
dstTexture = this.createTextureFromSource(srcCanvas, srcCanvas.width, srcCanvas.height);
}
else
{
this.setTexture2D(dstTexture);
if (!shouldReallocate)
{
gl.texSubImage2D(0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, srcCanvas);
}
else
{
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, srcCanvas);
dstTexture.width = srcCanvas.width;
dstTexture.height = srcCanvas.height;
}
this.setTexture2D(null);
}
return dstTexture;
},
setTextureFilter: function (texture, filter)
{
var gl = this.gl;
var glFilter = [ gl.LINEAR, gl.NEAREST ][filter];
this.setTexture2D(texture, 0);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, glFilter);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, glFilter);
this.setTexture2D(null, 0);
return this;
}
});