@@ -170,6 +170,123 @@ function createTextureUnits(parent, maxUnits = 8) {
170
170
} ;
171
171
}
172
172
173
+ function createAttribValues ( parent , maxAttribs = 8 ) {
174
+ const expander = createExpander ( parent , 'Attribute Values' , { } , `
175
+ Each attribute has a value that is used if it is NOT
176
+ enabled via --gl.enableVertexAttribArray--.
177
+
178
+ For example you have a shader with position and color attributes
179
+
180
+ ---glsl
181
+ attribute vec4 position;
182
+ attribute vec4 color;
183
+ ---
184
+
185
+ To draw a shape where every vertex gets a different color you'd setup
186
+ the color attribute with a buffer
187
+
188
+ ---js
189
+ gl.bindBuffer(gl.ARRAY_BUFFER, bufferWithColorData);
190
+ gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
191
+ gl.enableVertexAttribArray(colorLoc); // use the data from the buffer
192
+ ---
193
+
194
+ To draw a shape where every vertex gets the same color you can
195
+ disable the attribute and set its value
196
+
197
+ ---js
198
+ gl.disableVertexAttribArray(colorLoc);
199
+ gl.vertexAttrib4fv(colorLoc, colorForAllVertices);
200
+ ---
201
+
202
+ > Note: Only 8 attribute values are shown here for space reasons but
203
+ the actual number of attribute available you can look up with
204
+ --gl.getParameter(gl.MAX_VERTEX_ATTRIBS)--
205
+ which will be a minimum of ${ globals . isWebGL2 ? 16 : 8 } .
206
+
207
+ > Note: It's arguably
208
+ confusing that this value is not part of a vertex array
209
+ since the flag to use it or not is in the vertex array.
210
+
211
+ ` ) ;
212
+
213
+ const tbody = createTable ( expander , [ 'value' ] ) ;
214
+ tbody . parentElement . classList . add ( 'attrib-values' ) ;
215
+ const arrows = [ ] ;
216
+
217
+ for ( let i = 0 ; i < maxAttribs ; ++ i ) {
218
+ arrows . push ( { } ) ;
219
+ const tr = addElem ( 'tr' , tbody ) ;
220
+ addElem ( 'td' , tr , {
221
+ className : 'used-when-disabled' ,
222
+ textContent : '0, 0, 0, 1' ,
223
+ dataset : {
224
+ help : helpToMarkdown ( `
225
+ value for this attribute when disabled (the default)
226
+
227
+ ---js
228
+ const loc = gl.getAttribLocation(program, 'someAttrib'); // ${ i } ;
229
+ gl.disableVertexAttribArray(loc); // disable if it's not already disabled
230
+ gl.vertexAttrib4fv(loc, [1, 2, 3, 4]); // set the value
231
+ ---
232
+
233
+ note that the enabled/disabled state is part of
234
+ the current vertex array but the values when disabled
235
+ are global state.
236
+ ` ) ,
237
+ } ,
238
+ } ) ;
239
+ }
240
+
241
+ const updateAttribValue = loc => {
242
+ const row = tbody . rows [ loc ] ;
243
+ const cell = row . cells [ 0 ] ;
244
+ const enabled = gl . getVertexAttrib ( loc , gl . VERTEX_ATTRIB_ARRAY_ENABLED ) ;
245
+ row . classList . toggle ( 'attrib-enable' , enabled ) ;
246
+
247
+ const value = gl . getVertexAttrib ( loc , gl . CURRENT_VERTEX_ATTRIB ) . join ( ', ' ) ;
248
+ if ( updateElemAndFlashExpanderIfClosed ( cell , value ) ) {
249
+ /*
250
+ Note: This code is copied and pasted from the texture unit code above
251
+ so it would have to be adapted but, None of the examples use these
252
+ values, even for a moment, I haven't bothered to make the arrows work.
253
+
254
+ To work, arrows from the current program to an attribute need to change
255
+ so if enabled they connect as they do now but if disable they connect
256
+ to these values.
257
+
258
+ const oldArrow = arrows[unit][targetBinding];
259
+ if (oldArrow) {
260
+ arrowManager.remove(oldArrow);
261
+ arrows[unit][targetBinding] = null;
262
+ }
263
+ if (texture) {
264
+ const targetInfo = getWebGLObjectInfo(texture);
265
+ if (!targetInfo.deleted) {
266
+ arrows[unit][targetBinding] = arrowManager.add(
267
+ cell,
268
+ targetInfo.ui.elem.querySelector('.name'),
269
+ getColorForWebGLObject(texture, targetInfo.ui.elem, unit / maxUnits),
270
+ {offset: { start: {x: 0, y: colNdx * 2 - 4}}});
271
+ }
272
+ }
273
+ */
274
+ }
275
+ } ;
276
+
277
+ const updateAttribValues = ( ) => {
278
+ for ( let i = 0 ; i < maxAttribs ; ++ i ) {
279
+ updateAttribValue ( i ) ;
280
+ }
281
+ } ;
282
+
283
+ return {
284
+ elem : expander ,
285
+ updateAttribValue,
286
+ updateAttribValues,
287
+ } ;
288
+ }
289
+
173
290
function createUniformBufferBindings ( parent , maxUnits = 8 ) {
174
291
const expander = createExpander ( parent , 'Uniform Buffer Bindings' , { } , `
175
292
In each program you tell each uniform block which index to find
@@ -336,6 +453,7 @@ export function createGlobalUI(globalStateElem) {
336
453
commonState : createStateUI ( globalState . commonState , globalStateElem , 'common state' , globalStateQuery ) ,
337
454
textureUnits : createTextureUnits ( globalStateElem , 8 ) ,
338
455
clearState : createStateUI ( globalState . clearState , globalStateElem , 'clear state' , globalStateQuery ) ,
456
+ attribValueState : createAttribValues ( globalStateElem , 8 ) ,
339
457
...globals . isWebGL2 && {
340
458
transformFeedbackState : createStateUI ( globalState . transformFeedbackState , globalStateElem , 'transform feedback' , globalStateQuery ) ,
341
459
uniformBufferBindingsState : createUniformBufferBindings ( globalStateElem , Math . min ( 8 , gl . getParameter ( gl . MAX_UNIFORM_BUFFER_BINDINGS ) ) ) ,
0 commit comments