UNPKG

gl-shader

Version:
284 lines (255 loc) 5.99 kB
'use strict' module.exports = createAttributeWrapper var GLError = require("./GLError") function ShaderAttribute( gl , wrapper , index , locations , dimension , constFunc) { this._gl = gl this._wrapper = wrapper this._index = index this._locations = locations this._dimension = dimension this._constFunc = constFunc } var proto = ShaderAttribute.prototype proto.pointer = function setAttribPointer( type , normalized , stride , offset) { var self = this var gl = self._gl var location = self._locations[self._index] gl.vertexAttribPointer( location , self._dimension , type || gl.FLOAT , !!normalized , stride || 0 , offset || 0) gl.enableVertexAttribArray(location) } proto.set = function(x0, x1, x2, x3) { return this._constFunc(this._locations[this._index], x0, x1, x2, x3) } Object.defineProperty(proto, 'location', { get: function() { return this._locations[this._index] } , set: function(v) { if(v !== this._locations[this._index]) { this._locations[this._index] = v|0 this._wrapper.program = null } return v|0 } }) var allFns = [ function (gl, v, x0) { if (x0.length === undefined) { return gl.vertexAttrib1f(v, x0) } else { return gl.vertexAttrib1fv(v, x0) } }, function (gl, v, x0, x1) { if (x0.length === undefined) { return gl.vertexAttrib2f(v, x0, x1) } else { return gl.vertexAttrib2fv(v, x0) } }, function (gl, v, x0, x1, x2) { if (x0.length === undefined) { return gl.vertexAttrib3f(v, x0, x1, x2) } else { return gl.vertexAttrib3fv(v, x0) } }, function (gl, v, x0, x1, x2, x3) { if (x0.length === undefined) { return gl.vertexAttrib4f(v, x0, x1, x2, x3) } else { return gl.vertexAttrib4fv(v, x0) } } ] //Adds a vector attribute to obj function addVectorAttribute( gl , wrapper , index , locations , dimension , obj , name) { var constFunc = allFns[dimension] //Create attribute wrapper var attr = new ShaderAttribute( gl , wrapper , index , locations , dimension , constFunc) //Create accessor Object.defineProperty(obj, name, { set: function(x) { gl.disableVertexAttribArray(locations[index]) constFunc(gl, locations[index], x) return x } , get: function() { return attr } , enumerable: true }) } function addMatrixAttribute( gl , wrapper , index , locations , dimension , obj , name) { var parts = new Array(dimension) var attrs = new Array(dimension) for(var i=0; i<dimension; ++i) { addVectorAttribute( gl , wrapper , index[i] , locations , dimension , parts , i) attrs[i] = parts[i] } Object.defineProperty(parts, 'location', { set: function(v) { if(Array.isArray(v)) { for(var i=0; i<dimension; ++i) { attrs[i].location = v[i] } } else { for(var i=0; i<dimension; ++i) { attrs[i].location = v + i } } return v } , get: function() { var result = new Array(dimension) for(var i=0; i<dimension; ++i) { result[i] = locations[index[i]] } return result } , enumerable: true }) parts.pointer = function(type, normalized, stride, offset) { type = type || gl.FLOAT normalized = !!normalized stride = stride || (dimension * dimension) offset = offset || 0 for(var i=0; i<dimension; ++i) { var location = locations[index[i]] gl.vertexAttribPointer( location , dimension , type , normalized , stride , offset + i * dimension) gl.enableVertexAttribArray(location) } } var scratch = new Array(dimension) var vertexAttrib = gl['vertexAttrib' + dimension + 'fv'] Object.defineProperty(obj, name, { set: function(x) { for(var i=0; i<dimension; ++i) { var loc = locations[index[i]] gl.disableVertexAttribArray(loc) if(Array.isArray(x[0])) { vertexAttrib.call(gl, loc, x[i]) } else { for(var j=0; j<dimension; ++j) { scratch[j] = x[dimension*i + j] } vertexAttrib.call(gl, loc, scratch) } } return x } , get: function() { return parts } , enumerable: true }) } //Create shims for attributes function createAttributeWrapper( gl , wrapper , attributes , locations) { var obj = {} for(var i=0, n=attributes.length; i<n; ++i) { var a = attributes[i] var name = a.name var type = a.type var locs = a.locations switch(type) { case 'bool': case 'int': case 'float': addVectorAttribute( gl , wrapper , locs[0] , locations , 1 , obj , name) break default: if(type.indexOf('vec') >= 0) { var d = type.charCodeAt(type.length-1) - 48 if(d < 2 || d > 4) { throw new GLError('', 'Invalid data type for attribute ' + name + ': ' + type) } addVectorAttribute( gl , wrapper , locs[0] , locations , d , obj , name) } else if(type.indexOf('mat') >= 0) { var d = type.charCodeAt(type.length-1) - 48 if(d < 2 || d > 4) { throw new GLError('', 'Invalid data type for attribute ' + name + ': ' + type) } addMatrixAttribute( gl , wrapper , locs , locations , d , obj , name) } else { throw new GLError('', 'Unknown data type for attribute ' + name + ': ' + type) } break } } return obj }