gfx.js
Version:
WebGL wrappings for Graphics
1,722 lines (1,480 loc) • 80 kB
JavaScript
/*
* gfx.js v1.2.15
* (c) 2018 @Johnny Wu
* Released under the MIT License.
*/
var gfx = (function () {
'use strict';
var GL_NEAREST = 9728; // gl.NEAREST
var GL_LINEAR = 9729; // gl.LINEAR
var GL_NEAREST_MIPMAP_NEAREST = 9984; // gl.NEAREST_MIPMAP_NEAREST
var GL_LINEAR_MIPMAP_NEAREST = 9985; // gl.LINEAR_MIPMAP_NEAREST
var GL_NEAREST_MIPMAP_LINEAR = 9986; // gl.NEAREST_MIPMAP_LINEAR
var GL_LINEAR_MIPMAP_LINEAR = 9987; // gl.LINEAR_MIPMAP_LINEAR
// const GL_BYTE = 5120; // gl.BYTE
var GL_UNSIGNED_BYTE = 5121; // gl.UNSIGNED_BYTE
// const GL_SHORT = 5122; // gl.SHORT
var GL_UNSIGNED_SHORT = 5123; // gl.UNSIGNED_SHORT
var GL_UNSIGNED_INT = 5125; // gl.UNSIGNED_INT
var GL_FLOAT = 5126; // gl.FLOAT
var GL_UNSIGNED_SHORT_5_6_5 = 33635; // gl.UNSIGNED_SHORT_5_6_5
var GL_UNSIGNED_SHORT_4_4_4_4 = 32819; // gl.UNSIGNED_SHORT_4_4_4_4
var GL_UNSIGNED_SHORT_5_5_5_1 = 32820; // gl.UNSIGNED_SHORT_5_5_5_1
var GL_HALF_FLOAT_OES = 36193; // gl.HALF_FLOAT_OES
var GL_DEPTH_COMPONENT = 6402; // gl.DEPTH_COMPONENT
var GL_ALPHA = 6406; // gl.ALPHA
var GL_RGB = 6407; // gl.RGB
var GL_RGBA = 6408; // gl.RGBA
var GL_LUMINANCE = 6409; // gl.LUMINANCE
var GL_LUMINANCE_ALPHA = 6410; // gl.LUMINANCE_ALPHA
var GL_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0; // ext.COMPRESSED_RGB_S3TC_DXT1_EXT
var GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1; // ext.COMPRESSED_RGBA_S3TC_DXT1_EXT
var GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2; // ext.COMPRESSED_RGBA_S3TC_DXT3_EXT
var GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3; // ext.COMPRESSED_RGBA_S3TC_DXT5_EXT
var GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00; // ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG
var GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG = 0x8C01; // ext.COMPRESSED_RGB_PVRTC_2BPPV1_IMG
var GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02; // ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
var GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG = 0x8C03; // ext.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
var GL_COMPRESSED_RGB_ETC1_WEBGL = 0x8D64; // ext.COMPRESSED_RGB_ETC1_WEBGL
var _filterGL = [
[ GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR ],
[ GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR ] ];
var _textureFmtGL = [
// TEXTURE_FMT_RGB_DXT1: 0
{ format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_S3TC_DXT1_EXT, pixelType: null },
// TEXTURE_FMT_RGBA_DXT1: 1
{ format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, pixelType: null },
// TEXTURE_FMT_RGBA_DXT3: 2
{ format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, pixelType: null },
// TEXTURE_FMT_RGBA_DXT5: 3
{ format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, pixelType: null },
// TEXTURE_FMT_RGB_ETC1: 4
{ format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_ETC1_WEBGL, pixelType: null },
// TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5
{ format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, pixelType: null },
// TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6
{ format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, pixelType: null },
// TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7
{ format: GL_RGB, internalFormat: GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, pixelType: null },
// TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8
{ format: GL_RGBA, internalFormat: GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, pixelType: null },
// TEXTURE_FMT_A8: 9
{ format: GL_ALPHA, internalFormat: GL_ALPHA, pixelType: GL_UNSIGNED_BYTE },
// TEXTURE_FMT_L8: 10
{ format: GL_LUMINANCE, internalFormat: GL_LUMINANCE, pixelType: GL_UNSIGNED_BYTE },
// TEXTURE_FMT_L8_A8: 11
{ format: GL_LUMINANCE_ALPHA, internalFormat: GL_LUMINANCE_ALPHA, pixelType: GL_UNSIGNED_BYTE },
// TEXTURE_FMT_R5_G6_B5: 12
{ format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_UNSIGNED_SHORT_5_6_5 },
// TEXTURE_FMT_R5_G5_B5_A1: 13
{ format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_SHORT_5_5_5_1 },
// TEXTURE_FMT_R4_G4_B4_A4: 14
{ format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_SHORT_4_4_4_4 },
// TEXTURE_FMT_RGB8: 15
{ format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_UNSIGNED_BYTE },
// TEXTURE_FMT_RGBA8: 16
{ format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_UNSIGNED_BYTE },
// TEXTURE_FMT_RGB16F: 17
{ format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_HALF_FLOAT_OES },
// TEXTURE_FMT_RGBA16F: 18
{ format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_HALF_FLOAT_OES },
// TEXTURE_FMT_RGB32F: 19
{ format: GL_RGB, internalFormat: GL_RGB, pixelType: GL_FLOAT },
// TEXTURE_FMT_RGBA32F: 20
{ format: GL_RGBA, internalFormat: GL_RGBA, pixelType: GL_FLOAT },
// TEXTURE_FMT_R32F: 21
{ format: null, internalFormat: null, pixelType: null },
// TEXTURE_FMT_111110F: 22
{ format: null, internalFormat: null, pixelType: null },
// TEXTURE_FMT_SRGB: 23
{ format: null, internalFormat: null, pixelType: null },
// TEXTURE_FMT_SRGBA: 24
{ format: null, internalFormat: null, pixelType: null },
// TEXTURE_FMT_D16: 25
{ format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_SHORT },
// TEXTURE_FMT_D32: 26
{ format: GL_DEPTH_COMPONENT, internalFormat: GL_DEPTH_COMPONENT, pixelType: GL_UNSIGNED_INT },
// TEXTURE_FMT_D24S8: 27
{ format: null, internalFormat: null, pixelType: null } ];
/**
* enums
*/
var enums = {
// buffer usage
USAGE_STATIC: 35044, // gl.STATIC_DRAW
USAGE_DYNAMIC: 35048, // gl.DYNAMIC_DRAW
USAGE_STREAM: 35040, // gl.STREAM_DRAW
// index buffer format
INDEX_FMT_UINT8: 5121, // gl.UNSIGNED_BYTE
INDEX_FMT_UINT16: 5123, // gl.UNSIGNED_SHORT
INDEX_FMT_UINT32: 5125, // gl.UNSIGNED_INT (OES_element_index_uint)
// vertex attribute semantic
ATTR_POSITION: 'a_position',
ATTR_NORMAL: 'a_normal',
ATTR_TANGENT: 'a_tangent',
ATTR_BITANGENT: 'a_bitangent',
ATTR_WEIGHTS: 'a_weights',
ATTR_JOINTS: 'a_joints',
ATTR_COLOR: 'a_color',
ATTR_COLOR0: 'a_color0',
ATTR_COLOR1: 'a_color1',
ATTR_UV: 'a_uv',
ATTR_UV0: 'a_uv0',
ATTR_UV1: 'a_uv1',
ATTR_UV2: 'a_uv2',
ATTR_UV3: 'a_uv3',
ATTR_UV4: 'a_uv4',
ATTR_UV5: 'a_uv5',
ATTR_UV6: 'a_uv6',
ATTR_UV7: 'a_uv7',
// vertex attribute type
ATTR_TYPE_INT8: 5120, // gl.BYTE
ATTR_TYPE_UINT8: 5121, // gl.UNSIGNED_BYTE
ATTR_TYPE_INT16: 5122, // gl.SHORT
ATTR_TYPE_UINT16: 5123, // gl.UNSIGNED_SHORT
ATTR_TYPE_INT32: 5124, // gl.INT
ATTR_TYPE_UINT32: 5125, // gl.UNSIGNED_INT
ATTR_TYPE_FLOAT32: 5126, // gl.FLOAT
// texture filter
FILTER_NEAREST: 0,
FILTER_LINEAR: 1,
// texture wrap mode
WRAP_REPEAT: 10497, // gl.REPEAT
WRAP_CLAMP: 33071, // gl.CLAMP_TO_EDGE
WRAP_MIRROR: 33648, // gl.MIRRORED_REPEAT
// texture format
// compress formats
TEXTURE_FMT_RGB_DXT1: 0,
TEXTURE_FMT_RGBA_DXT1: 1,
TEXTURE_FMT_RGBA_DXT3: 2,
TEXTURE_FMT_RGBA_DXT5: 3,
TEXTURE_FMT_RGB_ETC1: 4,
TEXTURE_FMT_RGB_PVRTC_2BPPV1: 5,
TEXTURE_FMT_RGBA_PVRTC_2BPPV1: 6,
TEXTURE_FMT_RGB_PVRTC_4BPPV1: 7,
TEXTURE_FMT_RGBA_PVRTC_4BPPV1: 8,
// normal formats
TEXTURE_FMT_A8: 9,
TEXTURE_FMT_L8: 10,
TEXTURE_FMT_L8_A8: 11,
TEXTURE_FMT_R5_G6_B5: 12,
TEXTURE_FMT_R5_G5_B5_A1: 13,
TEXTURE_FMT_R4_G4_B4_A4: 14,
TEXTURE_FMT_RGB8: 15,
TEXTURE_FMT_RGBA8: 16,
TEXTURE_FMT_RGB16F: 17,
TEXTURE_FMT_RGBA16F: 18,
TEXTURE_FMT_RGB32F: 19,
TEXTURE_FMT_RGBA32F: 20,
TEXTURE_FMT_R32F: 21,
TEXTURE_FMT_111110F: 22,
TEXTURE_FMT_SRGB: 23,
TEXTURE_FMT_SRGBA: 24,
// depth formats
TEXTURE_FMT_D16: 25,
TEXTURE_FMT_D32: 26,
TEXTURE_FMT_D24S8: 27,
// depth and stencil function
DS_FUNC_NEVER: 512, // gl.NEVER
DS_FUNC_LESS: 513, // gl.LESS
DS_FUNC_EQUAL: 514, // gl.EQUAL
DS_FUNC_LEQUAL: 515, // gl.LEQUAL
DS_FUNC_GREATER: 516, // gl.GREATER
DS_FUNC_NOTEQUAL: 517, // gl.NOTEQUAL
DS_FUNC_GEQUAL: 518, // gl.GEQUAL
DS_FUNC_ALWAYS: 519, // gl.ALWAYS
// render-buffer format
RB_FMT_RGBA4: 32854, // gl.RGBA4
RB_FMT_RGB5_A1: 32855, // gl.RGB5_A1
RB_FMT_RGB565: 36194, // gl.RGB565
RB_FMT_D16: 33189, // gl.DEPTH_COMPONENT16
RB_FMT_S8: 36168, // gl.STENCIL_INDEX8
RB_FMT_D24S8: 34041, // gl.DEPTH_STENCIL
// blend-equation
BLEND_FUNC_ADD: 32774, // gl.FUNC_ADD
BLEND_FUNC_SUBTRACT: 32778, // gl.FUNC_SUBTRACT
BLEND_FUNC_REVERSE_SUBTRACT: 32779, // gl.FUNC_REVERSE_SUBTRACT
// blend
BLEND_ZERO: 0, // gl.ZERO
BLEND_ONE: 1, // gl.ONE
BLEND_SRC_COLOR: 768, // gl.SRC_COLOR
BLEND_ONE_MINUS_SRC_COLOR: 769, // gl.ONE_MINUS_SRC_COLOR
BLEND_DST_COLOR: 774, // gl.DST_COLOR
BLEND_ONE_MINUS_DST_COLOR: 775, // gl.ONE_MINUS_DST_COLOR
BLEND_SRC_ALPHA: 770, // gl.SRC_ALPHA
BLEND_ONE_MINUS_SRC_ALPHA: 771, // gl.ONE_MINUS_SRC_ALPHA
BLEND_DST_ALPHA: 772, // gl.DST_ALPHA
BLEND_ONE_MINUS_DST_ALPHA: 773, // gl.ONE_MINUS_DST_ALPHA
BLEND_CONSTANT_COLOR: 32769, // gl.CONSTANT_COLOR
BLEND_ONE_MINUS_CONSTANT_COLOR: 32770, // gl.ONE_MINUS_CONSTANT_COLOR
BLEND_CONSTANT_ALPHA: 32771, // gl.CONSTANT_ALPHA
BLEND_ONE_MINUS_CONSTANT_ALPHA: 32772, // gl.ONE_MINUS_CONSTANT_ALPHA
BLEND_SRC_ALPHA_SATURATE: 776, // gl.SRC_ALPHA_SATURATE
// stencil operation
STENCIL_OP_KEEP: 7680, // gl.KEEP
STENCIL_OP_ZERO: 0, // gl.ZERO
STENCIL_OP_REPLACE: 7681, // gl.REPLACE
STENCIL_OP_INCR: 7682, // gl.INCR
STENCIL_OP_INCR_WRAP: 34055, // gl.INCR_WRAP
STENCIL_OP_DECR: 7683, // gl.DECR
STENCIL_OP_DECR_WRAP: 34056, // gl.DECR_WRAP
STENCIL_OP_INVERT: 5386, // gl.INVERT
// cull
CULL_NONE: 0,
CULL_FRONT: 1028,
CULL_BACK: 1029,
CULL_FRONT_AND_BACK: 1032,
// primitive type
PT_POINTS: 0, // gl.POINTS
PT_LINES: 1, // gl.LINES
PT_LINE_LOOP: 2, // gl.LINE_LOOP
PT_LINE_STRIP: 3, // gl.LINE_STRIP
PT_TRIANGLES: 4, // gl.TRIANGLES
PT_TRIANGLE_STRIP: 5, // gl.TRIANGLE_STRIP
PT_TRIANGLE_FAN: 6, // gl.TRIANGLE_FAN
};
/**
* @method attrTypeBytes
* @param {ATTR_TYPE_*} attrType
*/
function attrTypeBytes(attrType) {
if (attrType === enums.ATTR_TYPE_INT8) {
return 1;
} else if (attrType === enums.ATTR_TYPE_UINT8) {
return 1;
} else if (attrType === enums.ATTR_TYPE_INT16) {
return 2;
} else if (attrType === enums.ATTR_TYPE_UINT16) {
return 2;
} else if (attrType === enums.ATTR_TYPE_INT32) {
return 4;
} else if (attrType === enums.ATTR_TYPE_UINT32) {
return 4;
} else if (attrType === enums.ATTR_TYPE_FLOAT32) {
return 4;
}
console.warn(("Unknown ATTR_TYPE: " + attrType));
return 0;
}
/**
* @method glFilter
* @param {WebGLContext} gl
* @param {FILTER_*} filter
* @param {FILTER_*} mipFilter
*/
function glFilter(gl, filter, mipFilter) {
if ( mipFilter === void 0 ) mipFilter = -1;
var result = _filterGL[filter][mipFilter+1];
if (result === undefined) {
console.warn(("Unknown FILTER: " + filter));
return mipFilter === -1 ? gl.LINEAR : gl.LINEAR_MIPMAP_LINEAR;
}
return result;
}
/**
* @method glTextureFmt
* @param {TEXTURE_FMT_*} fmt
*/
function glTextureFmt(fmt) {
var result = _textureFmtGL[fmt];
if (result === undefined) {
console.warn(("Unknown TEXTURE_FMT: " + fmt));
return _textureFmtGL[enums.TEXTURE_FMT_RGBA8];
}
return result;
}
// ====================
// exports
// ====================
var VertexFormat = function VertexFormat(infos) {
var this$1 = this;
this._attr2el = {};
this._elements = [];
this._bytes = 0;
var offset = 0;
for (var i = 0, len = infos.length; i < len; ++i) {
var info = infos[i];
var el = {
name: info.name,
offset: offset,
stride: 0,
stream: -1,
type: info.type,
num: info.num,
normalize: (info.normalize === undefined) ? false : info.normalize,
bytes: info.num * attrTypeBytes(info.type),
};
this$1._attr2el[el.name] = el;
this$1._elements.push(el);
this$1._bytes += el.bytes;
offset += el.bytes;
}
for (var i$1 = 0, len$1 = this._elements.length; i$1 < len$1; ++i$1) {
var el$1 = this$1._elements[i$1];
el$1.stride = this$1._bytes;
}
};
/**
* @method element
* @param {string} attrName
*/
VertexFormat.prototype.element = function element (attrName) {
return this._attr2el[attrName];
};
var IndexBuffer = function IndexBuffer(device, format, usage, data, numIndices) {
this._device = device;
this._format = format;
this._usage = usage;
this._numIndices = numIndices;
this._bytesPerIndex = 0;
// calculate bytes
if (format === enums.INDEX_FMT_UINT8) {
this._bytesPerIndex = 1;
} else if (format === enums.INDEX_FMT_UINT16) {
this._bytesPerIndex = 2;
} else if (format === enums.INDEX_FMT_UINT32) {
this._bytesPerIndex = 4;
}
this._bytes = this._bytesPerIndex * numIndices;
// update
this._glID = device._gl.createBuffer();
this.update(0, data);
// stats
device._stats.ib += this._bytes;
};
var prototypeAccessors = { count: { configurable: true } };
/**
* @method destroy
*/
IndexBuffer.prototype.destroy = function destroy () {
if (this._glID === -1) {
console.error('The buffer already destroyed');
return;
}
var gl = this._device._gl;
gl.deleteBuffer(this._glID);
this._device._stats.ib -= this.bytes;
this._glID = -1;
};
/**
* @method update
* @param {Number} offset
* @param {ArrayBuffer} data
*/
IndexBuffer.prototype.update = function update (offset, data) {
if (this._glID === -1) {
console.error('The buffer is destroyed');
return;
}
if (data && data.byteLength + offset > this._bytes) {
console.error('Failed to update data, bytes exceed.');
return;
}
var gl = this._device._gl;
var glUsage = this._usage;
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._glID);
if (!data) {
if (this._bytes) {
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this._bytes, glUsage);
} else {
console.warn('bufferData should not submit 0 bytes data');
}
} else {
if (offset) {
gl.bufferSubData(gl.ELEMENT_ARRAY_BUFFER, offset, data);
} else {
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, glUsage);
}
}
this._device._restoreIndexBuffer();
};
prototypeAccessors.count.get = function () {
return this._numIndices;
};
Object.defineProperties( IndexBuffer.prototype, prototypeAccessors );
var VertexBuffer = function VertexBuffer(device, format, usage, data, numVertices) {
this._device = device;
this._format = format;
this._usage = usage;
this._numVertices = numVertices;
// calculate bytes
this._bytes = this._format._bytes * numVertices;
// update
this._glID = device._gl.createBuffer();
this.update(0, data);
// stats
device._stats.vb += this._bytes;
};
var prototypeAccessors$1 = { count: { configurable: true } };
/**
* @method destroy
*/
VertexBuffer.prototype.destroy = function destroy () {
if (this._glID === -1) {
console.error('The buffer already destroyed');
return;
}
var gl = this._device._gl;
gl.deleteBuffer(this._glID);
this._device._stats.vb -= this.bytes;
this._glID = -1;
};
/**
* @method update
* @param {Number} offset
* @param {ArrayBuffer} data
*/
VertexBuffer.prototype.update = function update (offset, data) {
if (this._glID === -1) {
console.error('The buffer is destroyed');
return;
}
if (data && data.byteLength + offset > this._bytes) {
console.error('Failed to update data, bytes exceed.');
return;
}
var gl = this._device._gl;
var glUsage = this._usage;
gl.bindBuffer(gl.ARRAY_BUFFER, this._glID);
if (!data) {
if (this._bytes) {
gl.bufferData(gl.ARRAY_BUFFER, this._bytes, glUsage);
} else {
console.warn('bufferData should not submit 0 bytes data');
}
} else {
if (offset) {
gl.bufferSubData(gl.ARRAY_BUFFER, offset, data);
} else {
gl.bufferData(gl.ARRAY_BUFFER, data, glUsage);
}
}
gl.bindBuffer(gl.ARRAY_BUFFER, null);
};
prototypeAccessors$1.count.get = function () {
return this._numVertices;
};
Object.defineProperties( VertexBuffer.prototype, prototypeAccessors$1 );
var _genID = 0;
function _parseError(out, type, errorLog) {
errorLog.split('\n').forEach(function (msg) {
if (msg.length < 5) {
return;
}
var parts = /^ERROR\:\s+(\d+)\:(\d+)\:\s*(.*)$/.exec(msg);
if (parts) {
out.push({
type: type,
fileID: parts[1] | 0,
line: parts[2] | 0,
message: parts[3].trim()
});
} else if (msg.length > 0) {
out.push({
type: type,
fileID: -1,
line: 0,
message: msg
});
}
});
}
var Program = function Program(device, options) {
this._device = device;
// stores gl information: { location, type }
this._attributes = [];
this._uniforms = [];
this._samplers = [];
this._errors = [];
this._linked = false;
this._vertSource = options.vert;
this._fragSource = options.frag;
this._glID = null;
this._id = _genID++;
};
var prototypeAccessors$2 = { id: { configurable: true } };
prototypeAccessors$2.id.get = function () {
return this._id;
};
Program.prototype.link = function link () {
var this$1 = this;
if (this._linked) {
return;
}
var gl = this._device._gl;
var vertShader = _createShader(gl, gl.VERTEX_SHADER, this._vertSource);
var fragShader = _createShader(gl, gl.FRAGMENT_SHADER, this._fragSource);
var program = gl.createProgram();
gl.attachShader(program, vertShader);
gl.attachShader(program, fragShader);
gl.linkProgram(program);
var failed = false;
var errors = this._errors;
if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)) {
_parseError(errors, 'vs', gl.getShaderInfoLog(vertShader));
failed = true;
}
if (!gl.getShaderParameter(fragShader, gl.COMPILE_STATUS)) {
_parseError(errors, 'fs', gl.getShaderInfoLog(fragShader));
failed = true;
}
gl.deleteShader(vertShader);
gl.deleteShader(fragShader);
if (failed) {
errors.forEach(function (err) {
console.error(("Failed to compile " + (err.type) + " " + (err.fileID) + " (ln " + (err.line) + "): " + (err.message)));
});
return;
}
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error(("Failed to link shader program: " + (gl.getProgramInfoLog(program))));
failed = true;
}
if (failed) {
return;
}
this._glID = program;
// parse attribute
var numAttributes = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
for (var i = 0; i < numAttributes; ++i) {
var info = gl.getActiveAttrib(program, i);
var location = gl.getAttribLocation(program, info.name);
this$1._attributes.push({
name: info.name,
location: location,
type: info.type,
});
}
// parse uniform
var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
for (var i$1 = 0; i$1 < numUniforms; ++i$1) {
var info$1 = gl.getActiveUniform(program, i$1);
var name = info$1.name;
var location$1 = gl.getUniformLocation(program, name);
var isArray = name.substr(name.length - 3) === '[0]';
if (isArray) {
name = name.substr(0, name.length - 3);
}
this$1._uniforms.push({
name: name,
location: location$1,
type: info$1.type,
size: isArray ? info$1.size : undefined, // used when uniform is an array
});
}
this._linked = true;
};
Program.prototype.destroy = function destroy () {
var gl = this._device._gl;
gl.deleteProgram(this._glID);
this._linked = false;
this._glID = null;
this._attributes = [];
this._uniforms = [];
this._samplers = [];
};
Object.defineProperties( Program.prototype, prototypeAccessors$2 );
// ====================
// internal
// ====================
function _createShader(gl, type, src) {
var shader = gl.createShader(type);
gl.shaderSource(shader, src);
gl.compileShader(shader);
return shader;
}
var Texture = function Texture(device) {
this._device = device;
this._width = 4;
this._height = 4;
this._hasMipmap = false;
this._compressed = false;
this._anisotropy = 1;
this._minFilter = enums.FILTER_LINEAR;
this._magFilter = enums.FILTER_LINEAR;
this._mipFilter = enums.FILTER_LINEAR;
this._wrapS = enums.WRAP_REPEAT;
this._wrapT = enums.WRAP_REPEAT;
// wrapR available in webgl2
// this._wrapR = enums.WRAP_REPEAT;
this._format = enums.TEXTURE_FMT_RGBA8;
this._target = -1;
};
/**
* @method destroy
*/
Texture.prototype.destroy = function destroy () {
if (this._glID === -1) {
console.error('The texture already destroyed');
return;
}
var gl = this._device._gl;
gl.deleteTexture(this._glID);
this._device._stats.tex -= this.bytes;
this._glID = -1;
};
function isPow2(v) {
return !(v & (v - 1)) && (!!v);
}
var Texture2D = (function (Texture$$1) {
function Texture2D(device, options) {
Texture$$1.call(this, device);
var gl = this._device._gl;
this._target = gl.TEXTURE_2D;
this._glID = gl.createTexture();
// always alloc texture in GPU when we create it.
options.images = options.images || [null];
this.update(options);
}
if ( Texture$$1 ) Texture2D.__proto__ = Texture$$1;
Texture2D.prototype = Object.create( Texture$$1 && Texture$$1.prototype );
Texture2D.prototype.constructor = Texture2D;
/**
* @method update
* @param {Object} options
* @param {Array} options.images
* @param {Boolean} options.mipmap
* @param {Number} options.width
* @param {Number} options.height
* @param {TEXTURE_FMT_*} options.format
* @param {Number} options.anisotropy
* @param {FILTER_*} options.minFilter
* @param {FILTER_*} options.magFilter
* @param {FILTER_*} options.mipFilter
* @param {WRAP_*} options.wrapS
* @param {WRAP_*} options.wrapT
* @param {Boolean} options.flipY
* @param {Boolean} options.premultiplyAlpha
*/
Texture2D.prototype.update = function update (options) {
var gl = this._device._gl;
var genMipmap = this._hasMipmap;
if (options) {
if (options.width !== undefined) {
this._width = options.width;
}
if (options.height !== undefined) {
this._height = options.height;
}
if (options.anisotropy !== undefined) {
this._anisotropy = options.anisotropy;
}
if (options.minFilter !== undefined) {
this._minFilter = options.minFilter;
}
if (options.magFilter !== undefined) {
this._magFilter = options.magFilter;
}
if (options.mipFilter !== undefined) {
this._mipFilter = options.mipFilter;
}
if (options.wrapS !== undefined) {
this._wrapS = options.wrapS;
}
if (options.wrapT !== undefined) {
this._wrapT = options.wrapT;
}
if (options.format !== undefined) {
this._format = options.format;
this._compressed = (
this._format >= enums.TEXTURE_FMT_RGB_DXT1 &&
this._format <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1
);
}
// check if generate mipmap
if (options.mipmap !== undefined) {
this._hasMipmap = options.mipmap;
genMipmap = options.mipmap;
}
if (options.images !== undefined) {
if (options.images.length > 1) {
genMipmap = false;
var maxLength = options.width > options.height ? options.width : options.height;
if (maxLength >> (options.images.length - 1) !== 1) {
console.error('texture-2d mipmap is invalid, should have a 1x1 mipmap.');
}
}
}
}
// NOTE: get pot after this._width, this._height has been assigned.
var pot = isPow2(this._width) && isPow2(this._height);
if (!pot) {
genMipmap = false;
}
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this._glID);
if (options.images !== undefined && options.images.length > 0) {
this._setMipmap(options.images, options.flipY, options.premultiplyAlpha);
}
this._setTexInfo();
if (genMipmap) {
gl.hint(gl.GENERATE_MIPMAP_HINT, gl.NICEST);
gl.generateMipmap(gl.TEXTURE_2D);
}
this._device._restoreTexture(0);
};
/**
* @method updateSubImage
* @param {Object} options
* @param {Number} options.x
* @param {Number} options.y
* @param {Number} options.width
* @param {Number} options.height
* @param {Number} options.level
* @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image
* @param {Boolean} options.flipY
* @param {Boolean} options.premultiplyAlpha
*/
Texture2D.prototype.updateSubImage = function updateSubImage (options) {
var gl = this._device._gl;
var glFmt = glTextureFmt(this._format);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this._glID);
this._setSubImage(glFmt, options);
this._device._restoreTexture(0);
};
/**
* @method updateImage
* @param {Object} options
* @param {Number} options.width
* @param {Number} options.height
* @param {Number} options.level
* @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image
* @param {Boolean} options.flipY
* @param {Boolean} options.premultiplyAlpha
*/
Texture2D.prototype.updateImage = function updateImage (options) {
var gl = this._device._gl;
var glFmt = glTextureFmt(this._format);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this._glID);
this._setImage(glFmt, options);
this._device._restoreTexture(0);
};
Texture2D.prototype._setSubImage = function _setSubImage (glFmt, options) {
var gl = this._device._gl;
var flipY = options.flipY;
var premultiplyAlpha = options.premultiplyAlpha;
var img = options.image;
if (
img instanceof HTMLCanvasElement ||
img instanceof HTMLImageElement ||
img instanceof HTMLVideoElement
) {
if (flipY === undefined) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
} else {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
}
if (premultiplyAlpha === undefined) {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
} else {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
}
gl.texSubImage2D(gl.TEXTURE_2D, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img);
} else {
if (flipY === undefined) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
} else {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
}
if (premultiplyAlpha === undefined) {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
} else {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
}
if (this._compressed) {
gl.compressedTexSubImage2D(gl.TEXTURE_2D,
options.level,
options.x,
options.y,
options.width,
options.height,
glFmt.format,
img
);
} else {
gl.texSubImage2D(
gl.TEXTURE_2D,
options.level,
options.x,
options.y,
options.width,
options.height,
glFmt.format,
glFmt.pixelType,
img
);
}
}
};
Texture2D.prototype._setImage = function _setImage (glFmt, options) {
var gl = this._device._gl;
var flipY = options.flipY;
var premultiplyAlpha = options.premultiplyAlpha;
var img = options.image;
if (
img instanceof HTMLCanvasElement ||
img instanceof HTMLImageElement ||
img instanceof HTMLVideoElement
) {
if (flipY === undefined) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
} else {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
}
if (premultiplyAlpha === undefined) {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
} else {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
}
gl.texImage2D(
gl.TEXTURE_2D,
options.level,
glFmt.internalFormat,
glFmt.format,
glFmt.pixelType,
img
);
} else {
if (flipY === undefined) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
} else {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
}
if (premultiplyAlpha === undefined) {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
} else {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
}
if (this._compressed) {
gl.compressedTexImage2D(
gl.TEXTURE_2D,
options.level,
glFmt.internalFormat,
options.width,
options.height,
0,
img
);
} else {
gl.texImage2D(
gl.TEXTURE_2D,
options.level,
glFmt.internalFormat,
options.width,
options.height,
0,
glFmt.format,
glFmt.pixelType,
img
);
}
}
};
Texture2D.prototype._setMipmap = function _setMipmap (images, flipY, premultiplyAlpha) {
var this$1 = this;
var glFmt = glTextureFmt(this._format);
var options = {
width: this._width,
height: this._height,
flipY: flipY,
premultiplyAlpha: premultiplyAlpha,
level: 0,
image: null
};
for (var i = 0; i < images.length; ++i) {
options.level = i;
options.width = this$1._width >> i;
options.height = this$1._height >> i;
options.image = images[i];
this$1._setImage(glFmt, options);
}
};
Texture2D.prototype._setTexInfo = function _setTexInfo () {
var gl = this._device._gl;
var pot = isPow2(this._width) && isPow2(this._height);
// WebGL1 doesn't support all wrap modes with NPOT textures
if (!pot && (this._wrapS !== enums.WRAP_CLAMP || this._wrapT !== enums.WRAP_CLAMP)) {
console.warn('WebGL1 doesn\'t support all wrap modes with NPOT textures');
this._wrapS = enums.WRAP_CLAMP;
this._wrapT = enums.WRAP_CLAMP;
}
var mipFilter = this._hasMipmap ? this._mipFilter : -1;
if (!pot && mipFilter !== -1) {
console.warn('NPOT textures do not support mipmap filter');
mipFilter = -1;
}
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, glFilter(gl, this._minFilter, mipFilter));
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, glFilter(gl, this._magFilter, -1));
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this._wrapS);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this._wrapT);
var ext = this._device.ext('EXT_texture_filter_anisotropic');
if (ext) {
gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisotropy);
}
};
return Texture2D;
}(Texture));
var TextureCube = (function (Texture$$1) {
function TextureCube(device, options) {
Texture$$1.call(this, device);
var gl = this._device._gl;
this._target = gl.TEXTURE_CUBE_MAP;
this._glID = gl.createTexture();
this.update(options);
}
if ( Texture$$1 ) TextureCube.__proto__ = Texture$$1;
TextureCube.prototype = Object.create( Texture$$1 && Texture$$1.prototype );
TextureCube.prototype.constructor = TextureCube;
/**
* @method update
* @param {Object} options
* @param {Array} options.images
* @param {Boolean} options.mipmap
* @param {Number} options.width
* @param {Number} options.height
* @param {TEXTURE_FMT_*} options.format
* @param {Number} options.anisotropy
* @param {FILTER_*} options.minFilter
* @param {FILTER_*} options.magFilter
* @param {FILTER_*} options.mipFilter
* @param {WRAP_*} options.wrapS
* @param {WRAP_*} options.wrapT
* @param {WRAP_*} options.wrapR
* @param {Boolean} options.flipY
* @param {Boolean} options.premultiplyAlpha
*/
TextureCube.prototype.update = function update (options) {
var gl = this._device._gl;
var genMipmap = this._hasMipmap;
if (options) {
if (options.width !== undefined) {
this._width = options.width;
}
if (options.height !== undefined) {
this._height = options.height;
}
if (options.anisotropy !== undefined) {
this._anisotropy = options.anisotropy;
}
if (options.minFilter !== undefined) {
this._minFilter = options.minFilter;
}
if (options.magFilter !== undefined) {
this._magFilter = options.magFilter;
}
if (options.mipFilter !== undefined) {
this._mipFilter = options.mipFilter;
}
if (options.wrapS !== undefined) {
this._wrapS = options.wrapS;
}
if (options.wrapT !== undefined) {
this._wrapT = options.wrapT;
}
// wrapR available in webgl2
// if (options.wrapR !== undefined) {
// this._wrapR = options.wrapR;
// }
if (options.format !== undefined) {
this._format = options.format;
this._compressed = (
this._format >= enums.TEXTURE_FMT_RGB_DXT1 &&
this._format <= enums.TEXTURE_FMT_RGBA_PVRTC_4BPPV1
);
}
// check if generate mipmap
if (options.mipmap !== undefined) {
this._hasMipmap = options.mipmap;
genMipmap = options.mipmap;
}
if (options.images !== undefined) {
if (options.images.length > 1) {
genMipmap = false;
if (options.width !== options.height) {
console.warn('texture-cube width and height should be identical.');
}
if (options.width >> (options.images.length - 1) !== 1) {
console.error('texture-cube mipmap is invalid. please set mipmap as 1x1, 2x2, 4x4 ... nxn');
}
}
}
}
// NOTE: get pot after this._width, this._height has been assigned.
var pot = isPow2(this._width) && isPow2(this._height);
if (!pot) {
genMipmap = false;
}
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._glID);
if (options.images !== undefined && options.images.length > 0) {
this._setMipmap(options.images, options.flipY, options.premultiplyAlpha);
}
this._setTexInfo();
if (genMipmap) {
gl.hint(gl.GENERATE_MIPMAP_HINT, gl.NICEST);
gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
}
this._device._restoreTexture(0);
};
/**
* @method updateSubImage
* @param {Object} options
* @param {Number} options.x
* @param {Number} options.y
* @param {Number} options.width
* @param {Number} options.height
* @param {Number} options.level
* @param {Number} options.faceIndex
* @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image
* @param {Boolean} options.flipY
* @param {Boolean} options.premultiplyAlpha
*/
TextureCube.prototype.updateSubImage = function updateSubImage (options) {
var gl = this._device._gl;
var glFmt = glTextureFmt(this._format);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._glID);
this._setSubImage(glFmt, options);
this._device._restoreTexture(0);
};
/**
* @method updateImage
* @param {Object} options
* @param {Number} options.width
* @param {Number} options.height
* @param {Number} options.level
* @param {Number} options.faceIndex
* @param {HTMLCanvasElement | HTMLImageElement | HTMLVideoElement | ArrayBufferView} options.image
* @param {Boolean} options.flipY
* @param {Boolean} options.premultiplyAlpha
*/
TextureCube.prototype.updateImage = function updateImage (options) {
var gl = this._device._gl;
var glFmt = glTextureFmt(this._format);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, this._glID);
this._setImage(glFmt, options);
this._device._restoreTexture(0);
};
TextureCube.prototype._setSubImage = function _setSubImage (glFmt, options) {
var gl = this._device._gl;
var flipY = options.flipY;
var premultiplyAlpha = options.premultiplyAlpha;
var faceIndex = options.faceIndex;
var img = options.image;
if (flipY === undefined) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
} else {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
}
if (premultiplyAlpha === undefined) {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
} else {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
}
if (
img instanceof HTMLCanvasElement ||
img instanceof HTMLImageElement ||
img instanceof HTMLVideoElement
) {
gl.texSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, options.level, options.x, options.y, glFmt.format, glFmt.pixelType, img);
} else {
if (this._compressed) {
gl.compressedTexSubImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex,
options.level,
options.x,
options.y,
options.width,
options.height,
glFmt.format,
img
);
} else {
gl.texSubImage2D(
gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex,
options.level,
options.x,
options.y,
options.width,
options.height,
glFmt.format,
glFmt.pixelType,
img
);
}
}
};
TextureCube.prototype._setImage = function _setImage (glFmt, options) {
var gl = this._device._gl;
var flipY = options.flipY;
var premultiplyAlpha = options.premultiplyAlpha;
var faceIndex = options.faceIndex;
var img = options.image;
if (flipY === undefined) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
} else {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);
}
if (premultiplyAlpha === undefined) {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
} else {
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, premultiplyAlpha);
}
if (
img instanceof HTMLCanvasElement ||
img instanceof HTMLImageElement ||
img instanceof HTMLVideoElement
) {
gl.texImage2D(
gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex,
options.level,
glFmt.internalFormat,
glFmt.format,
glFmt.pixelType,
img
);
} else {
if (this._compressed) {
gl.compressedTexImage2D(
gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex,
options.level,
glFmt.internalFormat,
options.width,
options.height,
0,
img
);
} else {
gl.texImage2D(
gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex,
options.level,
glFmt.internalFormat,
options.width,
options.height,
0,
glFmt.format,
glFmt.pixelType,
img
);
}
}
};
// levelImages = [imagePosX, imageNegX, imagePosY, imageNegY, imagePosZ, imageNegz]
// images = [levelImages0, levelImages1, ...]
TextureCube.prototype._setMipmap = function _setMipmap (images, flipY, premultiplyAlpha) {
var this$1 = this;
var glFmt = glTextureFmt(this._format);
var options = {
width: this._width,
height: this._height,
faceIndex: 0,
flipY: flipY,
premultiplyAlpha: premultiplyAlpha,
level: 0,
image: null
};
for (var i = 0; i < images.length; ++i) {
var levelImages = images[i];
options.level = i;
options.width = this$1._width >> i;
options.height = this$1._height >> i;
for (var face = 0; face < 6; ++face) {
options.faceIndex = face;
options.image = levelImages[face];
this$1._setImage(glFmt, options);
}
}
};
TextureCube.prototype._setTexInfo = function _setTexInfo () {
var gl = this._device._gl;
var pot = isPow2(this._width) && isPow2(this._height);
// WebGL1 doesn't support all wrap modes with NPOT textures
if (!pot && (this._wrapS !== enums.WRAP_CLAMP || this._wrapT !== enums.WRAP_CLAMP)) {
console.warn('WebGL1 doesn\'t support all wrap modes with NPOT textures');
this._wrapS = enums.WRAP_CLAMP;
this._wrapT = enums.WRAP_CLAMP;
}
var mipFilter = this._hasMipmap ? this._mipFilter : -1;
if (!pot && mipFilter !== -1) {
console.warn('NPOT textures do not support mipmap filter');
mipFilter = -1;
}
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, glFilter(gl, this._minFilter, mipFilter));
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, glFilter(gl, this._magFilter, -1));
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, this._wrapS);
gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, this._wrapT);
// wrapR available in webgl2
// gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_R, this._wrapR);
var ext = this._device.ext('EXT_texture_filter_anisotropic');
if (ext) {
gl.texParameteri(gl.TEXTURE_CUBE_MAP, ext.TEXTURE_MAX_ANISOTROPY_EXT, this._anisotropy);
}
};
return TextureCube;
}(Texture));
var RenderBuffer = function RenderBuffer(device, format, width, height) {
this._device = device;
this._format = format;
this._width = width;
this._height = height;
var gl = device._gl;
this._glID = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, this._glID);
gl.renderbufferStorage(gl.RENDERBUFFER, format, width, height);
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
};
/**
* @method destroy
*/
RenderBuffer.prototype.destroy = function destroy () {
if (this._glID === null) {
console.error('The render-buffer already destroyed');
return;
}
var gl = this._device._gl;
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
gl.deleteRenderbuffer(this._glID);
this._glID = null;
};
var FrameBuffer = function FrameBuffer(device, width, height, options) {
this._device = device;
this._width = width;
this._height = height;
this._colors = options.colors || [];
this._depth = options.depth || null;
this._stencil = options.stencil || null;
this._depthStencil = options.depthStencil || null;
this._glID = device._gl.createFramebuffer();
};
/**
* @method destroy
*/
FrameBuffer.prototype.destroy = function destroy () {
if (this._glID === null) {
console.error('The frame-buffer already destroyed');
return;
}
var gl = this._device._gl;
gl.deleteFramebuffer(this._glID);
this._glID = null;
};
var _default = {
// blend
blend: false,
blendSep: false,
blendColor: 0xffffffff,
blendEq: enums.BLEND_FUNC_ADD,
blendAlphaEq: enums.BLEND_FUNC_ADD,
blendSrc: enums.BLEND_ONE,
blendDst: enums.BLEND_ZERO,
blendSrcAlpha: enums.BLEND_ONE,
blendDstAlpha: enums.BLEND_ZERO,
// depth
depthTest: false,
depthWrite: false,
depthFunc: enums.DS_FUNC_LESS,
// stencil
stencilTest: false,
stencilSep: false,
stencilFuncFront: enums.DS_FUNC_ALWAYS,
stencilRefFront: 0,
stencilMaskFront: 0xff,
stencilFailOpFront: enums.STENCIL_OP_KEEP,
stencilZFailOpFront: enums.STENCIL_OP_KEEP,
stencilZPassOpFront: enums.STENCIL_OP_KEEP,
stencilWriteMaskFront: 0xff,
stencilFuncBack: enums.DS_FUNC_ALWAYS,
stencilRefBack: 0,
stencilMaskBack: 0xff,
stencilFailOpBack: enums.STENCIL_OP_KEEP,
stencilZFailOpBack: enums.STENCIL_OP_KEEP,
stencilZPassOpBack: enums.STENCIL_OP_KEEP,
stencilWriteMaskBack: 0xff,
// cull-mode
cullMode: enums.CULL_BACK,
// primitive-type
primitiveType: enums.PT_TRIANGLES,
// bindings
maxStream: -1,
vertexBuffers: [],
vertexBufferOffsets: [],
indexBuffer: null,
maxTextureSlot: -1,
textureUnits: [],
program: null,
};
var State = function State(device) {
// bindings
this.vertexBuffers = new Array(device._caps.maxVertexStreams);
this.vertexBufferOffsets = new Array(device._caps.maxVertexStreams);
this.textureUnits = new Array(device._caps.maxTextureUnits);
this.set(_default);
};
State.initDefault = function initDefault (device) {
_default.vertexBuffers = new Array(device._caps.maxVertexStreams);
_default.vertexBufferOffsets = new Array(device._caps.maxVertexStreams);
_default.textureUnits = new Array(device._caps.maxTextureUnits);
};
State.prototype.reset = function reset () {
this.set(_default);
};
State.prototype.set = function set (cpy) {
var this$1 = this;
// blending
this.blend = cpy.blend;
this.blendSep = cpy.blendSep;
this.blendColor = cpy.blendColor;
this.blendEq = cpy.blendEq;
this.blendAlphaEq = cpy.blendAlphaEq;
this.blendSrc = cpy.blendSrc;
this.blendDst = cpy.blendDst;
this.blendSrcAlpha = cpy.blendSrcAlpha;
this.blendDstAlpha = cpy.blendDstAlpha;
// depth
this.depthTest = cpy.depthTest;
this.depthWrite = cpy.depthWrite;
this.depthFunc = cpy.depthFunc;
// stencil
this.stencilTest = cpy.stencilTest;
this.stencilSep = cpy.stencilSep;
this.stencilFuncFront = cpy.stencilFuncFront;
this.stencilRefFront = cpy.stencilRefFront;
this.stencilMaskFront = cpy.stencilMaskFront;
this.stencilFailOpFront = cpy.stencilFailOpFront;
this.stencilZFailOpFront = cpy.stencilZFailOpFront;
this.stencilZPassOpFront = cpy.stencilZPassOpFront;
this.stencilWriteMaskFront = cpy.stencilWriteMaskFront;
this.stencilFuncBack = cpy.stencilFuncBack;
this.stencilRefBack = cpy.stencilRefBack;
this.stencilMaskBack = cpy.stencilMaskBack;
this.stencilFailOpBack = cpy.stencilFailOpBack;
this.stencilZFailOpBack = cpy.stencilZFailOpBack;
this.stencilZPassOpBack = cpy.stencilZPassOpBack;
this.stencilWriteMaskBack = cpy.stencilWriteMaskBack;
// cull-mode
this.cullMode = cpy.cullMode;
// primitive-type
this.primitiveType = cpy.primitiveType;
// buffer bindings
this.maxStream = cpy.maxStream;
for (var i = 0; i < cpy.vertexBuffers.length; ++i) {
this$1.vertexBuffers[i] = cpy.vertexBuffers[i];
}
for (var i$1 = 0; i$1 < cpy.vertexBufferOffsets.length; ++i$1) {
this$1.vertexBufferOffsets[i$1] = cpy.vertexBufferOffsets[i$1];
}
this.indexBuffer = cpy.indexBuffer;
// texture bindings
this.maxTextureSlot = cpy.maxTextureSlot;
for (var i$2 = 0; i$2 < cpy.textureUnits.length; ++i$2) {
this$1.textureUnits[i$2] = cpy.textureUnits[i$2];
}
this.program = cpy.program;
};
var GL_INT = 5124;
var GL_FLOAT$1 = 5126;
var GL_FLOAT_VEC2 = 35664;
var GL_FLOAT_VEC3 = 35665;
var GL_FLOAT_VEC4 = 35666;
var GL_INT_VEC2 = 35667;
var GL_INT_VEC3 = 35668;
var GL_INT_VEC4 = 35669;
var GL_BOOL = 35670;
var GL_BOOL_VEC2 = 35671;
var GL_BOOL_VEC3 = 35672;
var GL_BOOL_VEC4 = 35673;
var GL_FLOAT_MAT2 = 35674;
var GL_FLOAT_MAT3 = 35675;
var GL_FLOAT_MAT4 = 35676;
var GL_SAMPLER_2D = 35678;
var GL_SAMPLER_CUBE = 35680;
/**
* _type2uniformCommit
*/
var _type2uniformCommit = {};
_type2uniformCommit[GL_INT] = function (gl, id, value) {
gl.uniform1i(id, value);
};
_type2uniformCommit[GL_FLOAT$1] = function (gl, id, value) {
gl.uniform1f(id, value);
};
_type2uniformCommit[GL_FLOAT_VEC2] = function (gl, id, value) {
gl.uniform2fv(id, value);
};
_type2uniformCommit[GL_FLOAT_VEC3] = function (gl, id, value) {
gl.uniform3fv(id, value);
};
_type2uniformCommit[GL_FLOAT_VEC4] = function (gl, id, value) {
gl.uniform4fv(id, value);
};
_type2uniformCommit[GL_INT_VEC2] = function (gl, id, value) {
gl.uniform2iv(id, value);
};
_type2uniformCommit[GL_INT_VEC3] = function (gl, id, value) {
gl.uniform3iv(id, value);
};
_type2uniformCommit[GL_INT_VEC4] = function (gl, id, value) {
gl.uniform4iv(id, value);
};
_type2uniformCommit[GL_BOOL] = function (gl, id, value) {
gl.uniform1i(id, value);
};
_type2uniformCommit[GL_BOOL_VEC2] = function (gl, id, value) {
gl.uniform2iv(id, value);
};
_type2uniformCommit[GL_BOOL_VEC3] = function (gl, id, value) {
gl.uniform3iv(id, value);
};
_type2uniformCommit[GL_BOOL_VEC4] = function (gl, id, value) {
gl.uniform4iv(id, value);
};
_type2uniformCommit[GL_FLOAT_MAT2] = function (gl, id, value) {
gl.uniformMatrix2fv(id, false, value);
};
_type2uniformCommit[GL_FLOAT_MAT3] = function (gl, id, value) {
gl.uniformMatrix3fv(id, false, value);
};
_type2uniformCommit[GL_FLOAT_MAT4] = function (gl, id, value) {
gl.uniformMatrix4fv(id, false, value);
};
_type2uniformCommit[GL_SAMPLER_2D] = function (gl, id, value) {
gl.uniform1i(id, value);
};
_type2uniformCommit[GL_SAMPLER_CUBE] = function (gl, id, value) {
gl.uniform1i(id, value);
};
/**
* _type2uniformArrayCommit
*/
var _type2uniformArrayCommit = {};
_type2uniformArrayCommit[GL_INT] = function (gl, id, value) {
gl.uniform1iv(id, value);
};
_type2uniformArrayCommit[GL_FLOAT$1] = function (gl, id, value) {
gl.uniform1fv(id, value);
};
_type2uniformArrayCommit[GL_FLOAT_VEC2] = function (gl, id, value) {
gl.uniform2fv(id, value);
};
_type2uniformArrayCommit[GL_FLOAT_VEC3] = function (gl, id, value) {
gl.uniform3fv(id, value);
};
_type2uniformArrayCommit[GL_FLOAT_VEC4] = function (gl, id, value) {
gl.uniform4fv(id, value);
};
_type2uniformArrayCommit[GL_INT_VEC2] = function (gl, id, value) {
gl.uniform2iv(id, value);
};
_type2uniformArrayCommit[GL_INT_VEC3] = function (gl, id, value) {
gl.uniform3iv(id, value);
};
_type2uniformArrayCommit[GL_INT_VEC4] = function (gl, id, value) {
gl.uniform4iv(id, value);
};
_type2uniformArrayCommit[GL_BOOL] = function (gl, id, value) {
gl.uniform1iv(id, value);
};
_type2uniformArrayCommit[GL_BOOL_VEC2] = function (gl, id, value) {
gl.uniform2iv(id, value);