UNPKG

5.65 kBJavaScriptView Raw
1'use strict'
2
3module.exports = createAttributeWrapper
4
5function ShaderAttribute(
6 gl
7 , wrapper
8 , index
9 , locations
10 , dimension
11 , constFunc) {
12 this._gl = gl
13 this._wrapper = wrapper
14 this._index = index
15 this._locations = locations
16 this._dimension = dimension
17 this._constFunc = constFunc
18}
19
20var proto = ShaderAttribute.prototype
21
22proto.pointer = function setAttribPointer(
23 type
24 , normalized
25 , stride
26 , offset) {
27
28 var self = this
29 var gl = self._gl
30 var location = self._locations[self._index]
31
32 gl.vertexAttribPointer(
33 location
34 , self._dimension
35 , type || gl.FLOAT
36 , !!normalized
37 , stride || 0
38 , offset || 0)
39 gl.enableVertexAttribArray(location)
40}
41
42proto.set = function(x0, x1, x2, x3) {
43 return this._constFunc(this._locations[this._index], x0, x1, x2, x3)
44}
45
46Object.defineProperty(proto, 'location', {
47 get: function() {
48 return this._locations[this._index]
49 }
50 , set: function(v) {
51 if(v !== this._locations[this._index]) {
52 this._locations[this._index] = v|0
53 this._wrapper.program = null
54 }
55 return v|0
56 }
57})
58
59//Adds a vector attribute to obj
60function addVectorAttribute(
61 gl
62 , wrapper
63 , index
64 , locations
65 , dimension
66 , obj
67 , name) {
68
69 //Construct constant function
70 var constFuncArgs = [ 'gl', 'v' ]
71 var varNames = []
72 for(var i=0; i<dimension; ++i) {
73 constFuncArgs.push('x'+i)
74 varNames.push('x'+i)
75 }
76 constFuncArgs.push(
77 'if(x0.length===void 0){return gl.vertexAttrib' +
78 dimension + 'f(v,' +
79 varNames.join() +
80 ')}else{return gl.vertexAttrib' +
81 dimension +
82 'fv(v,x0)}')
83 var constFunc = Function.apply(null, constFuncArgs)
84
85 //Create attribute wrapper
86 var attr = new ShaderAttribute(
87 gl
88 , wrapper
89 , index
90 , locations
91 , dimension
92 , constFunc)
93
94 //Create accessor
95 Object.defineProperty(obj, name, {
96 set: function(x) {
97 gl.disableVertexAttribArray(locations[index])
98 constFunc(gl, locations[index], x)
99 return x
100 }
101 , get: function() {
102 return attr
103 }
104 , enumerable: true
105 })
106}
107
108function addMatrixAttribute(
109 gl
110 , wrapper
111 , index
112 , locations
113 , dimension
114 , obj
115 , name) {
116
117 var parts = new Array(dimension)
118 var attrs = new Array(dimension)
119 for(var i=0; i<dimension; ++i) {
120 addVectorAttribute(
121 gl
122 , wrapper
123 , index[i]
124 , locations
125 , dimension
126 , parts
127 , i)
128 attrs[i] = parts[i]
129 }
130
131 Object.defineProperty(parts, 'location', {
132 set: function(v) {
133 if(Array.isArray(v)) {
134 for(var i=0; i<dimension; ++i) {
135 attrs[i].location = v[i]
136 }
137 } else {
138 for(var i=0; i<dimension; ++i) {
139 attrs[i].location = v + i
140 }
141 }
142 return v
143 }
144 , get: function() {
145 var result = new Array(dimension)
146 for(var i=0; i<dimension; ++i) {
147 result[i] = locations[index[i]]
148 }
149 return result
150 }
151 , enumerable: true
152 })
153
154 parts.pointer = function(type, normalized, stride, offset) {
155 type = type || gl.FLOAT
156 normalized = !!normalized
157 stride = stride || (dimension * dimension)
158 offset = offset || 0
159 for(var i=0; i<dimension; ++i) {
160 var location = locations[index[i]]
161 gl.vertexAttribPointer(
162 location
163 , dimension
164 , type
165 , normalized
166 , stride
167 , offset + i * dimension)
168 gl.enableVertexAttribArray(location)
169 }
170 }
171
172 var scratch = new Array(dimension)
173 var vertexAttrib = gl['vertexAttrib' + dimension + 'fv']
174
175 Object.defineProperty(obj, name, {
176 set: function(x) {
177 for(var i=0; i<dimension; ++i) {
178 var loc = locations[index[i]]
179 gl.disableVertexAttribArray(loc)
180 if(Array.isArray(x[0])) {
181 vertexAttrib.call(gl, loc, x[i])
182 } else {
183 for(var j=0; j<dimension; ++j) {
184 scratch[j] = x[dimension*i + j]
185 }
186 vertexAttrib.call(gl, loc, scratch)
187 }
188 }
189 return x
190 }
191 , get: function() {
192 return parts
193 }
194 , enumerable: true
195 })
196}
197
198//Create shims for attributes
199function createAttributeWrapper(
200 gl
201 , wrapper
202 , attributes
203 , locations) {
204
205 var obj = {}
206 for(var i=0, n=attributes.length; i<n; ++i) {
207
208 var a = attributes[i]
209 var name = a.name
210 var type = a.type
211 var locs = a.locations
212
213 switch(type) {
214 case 'bool':
215 case 'int':
216 case 'float':
217 addVectorAttribute(
218 gl
219 , wrapper
220 , locs[0]
221 , locations
222 , 1
223 , obj
224 , name)
225 break
226
227 default:
228 if(type.indexOf('vec') >= 0) {
229 var d = type.charCodeAt(type.length-1) - 48
230 if(d < 2 || d > 4) {
231 throw new Error('gl-shader: Invalid data type for attribute ' + name + ': ' + type)
232 }
233 addVectorAttribute(
234 gl
235 , wrapper
236 , locs[0]
237 , locations
238 , d
239 , obj
240 , name)
241 } else if(type.indexOf('mat') >= 0) {
242 var d = type.charCodeAt(type.length-1) - 48
243 if(d < 2 || d > 4) {
244 throw new Error('gl-shader: Invalid data type for attribute ' + name + ': ' + type)
245 }
246 addMatrixAttribute(
247 gl
248 , wrapper
249 , locs
250 , locations
251 , d
252 , obj
253 , name)
254 } else {
255 throw new Error('gl-shader: Unknown data type for attribute ' + name + ': ' + type)
256 }
257 break
258 }
259 }
260 return obj
261}