vertex-array-object.html (22318B)
1 <!-- 2 Copyright (c) 2019 The Khronos Group Inc. 3 Use of this source code is governed by an MIT-style license that can be 4 found in the LICENSE.txt file. 5 --> 6 7 <!DOCTYPE html> 8 <html> 9 <head> 10 <meta charset="utf-8"> 11 <title>WebGL vertex_array_object Conformance Tests</title> 12 <link rel="stylesheet" href="../../resources/js-test-style.css"/> 13 <script src="../../js/js-test-pre.js"></script> 14 <script src="../../js/webgl-test-utils.js"></script> 15 </head> 16 <body> 17 <div id="description"></div> 18 <canvas id="canvas" style="width: 50px; height: 50px;"> </canvas> 19 <div id="console"></div> 20 <script id="vshader" type="x-shader/x-vertex"> 21 attribute vec4 a_position; 22 attribute vec4 a_color; 23 varying vec4 v_color; 24 void main(void) { 25 gl_Position = a_position; 26 v_color = a_color; 27 } 28 </script> 29 <script id="fshader" type="x-shader/x-fragment"> 30 precision mediump float; 31 varying vec4 v_color; 32 void main(void) { 33 gl_FragColor = v_color; 34 } 35 </script> 36 <script> 37 "use strict"; 38 description("This test verifies the functionality of the Vertex Array Objects."); 39 40 debug(""); 41 42 var wtu = WebGLTestUtils; 43 var canvas = document.getElementById("canvas"); 44 var gl = wtu.create3DContext(canvas, null, 2); 45 var vao = null; 46 47 if (!gl) { 48 testFailed("WebGL context does not exist"); 49 } else { 50 testPassed("WebGL context exists"); 51 52 runBindingTest(); 53 runObjectTest(); 54 runAttributeTests(); 55 runAttributeValueTests(); 56 runDrawTests(); 57 runUnboundDeleteTests(); 58 runBoundDeleteTests(); 59 runArrayBufferBindTests(); 60 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "there should be no errors"); 61 } 62 63 function runBindingTest() { 64 debug("Testing binding enum"); 65 66 shouldBe("gl.VERTEX_ARRAY_BINDING", "0x85B5"); 67 68 gl.getParameter(gl.VERTEX_ARRAY_BINDING); 69 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "VERTEX_ARRAY_BINDING query should succeed"); 70 71 // Default value is null 72 if (gl.getParameter(gl.VERTEX_ARRAY_BINDING) === null) { 73 testPassed("Default value of VERTEX_ARRAY_BINDING is null"); 74 } else { 75 testFailed("Default value of VERTEX_ARRAY_BINDING is not null"); 76 } 77 78 debug("Testing binding a VAO"); 79 var vao0 = gl.createVertexArray(); 80 var vao1 = gl.createVertexArray(); 81 shouldBeNull("gl.getParameter(gl.VERTEX_ARRAY_BINDING)"); 82 gl.bindVertexArray(vao0); 83 if (gl.getParameter(gl.VERTEX_ARRAY_BINDING) == vao0) { 84 testPassed("gl.getParameter(gl.VERTEX_ARRAY_BINDING) is expected VAO"); 85 } else { 86 testFailed("gl.getParameter(gl.VERTEX_ARRAY_BINDING) is not expected VAO") 87 } 88 gl.bindVertexArray(vao1); 89 if (gl.getParameter(gl.VERTEX_ARRAY_BINDING) == vao1) { 90 testPassed("gl.getParameter(gl.VERTEX_ARRAY_BINDING) is expected VAO"); 91 } else { 92 testFailed("gl.getParameter(gl.VERTEX_ARRAY_BINDING) is not expected VAO") 93 } 94 gl.deleteVertexArray(vao1); 95 shouldBeNull("gl.getParameter(gl.VERTEX_ARRAY_BINDING)"); 96 gl.bindVertexArray(vao1); 97 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "binding a deleted vertex array object"); 98 gl.bindVertexArray(null); 99 shouldBeNull("gl.getParameter(gl.VERTEX_ARRAY_BINDING)"); 100 gl.deleteVertexArray(vao1); 101 } 102 103 function runObjectTest() { 104 debug("Testing object creation"); 105 106 vao = gl.createVertexArray(); 107 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "createVertexArray should not set an error"); 108 shouldBeNonNull("vao"); 109 110 // Expect false if never bound 111 shouldBeFalse("gl.isVertexArray(vao)"); 112 gl.bindVertexArray(vao); 113 shouldBeTrue("gl.isVertexArray(vao)"); 114 gl.bindVertexArray(null); 115 shouldBeTrue("gl.isVertexArray(vao)"); 116 117 shouldBeFalse("gl.isVertexArray(null)"); 118 119 gl.deleteVertexArray(vao); 120 vao = null; 121 } 122 123 function runAttributeTests() { 124 debug("Testing attributes work across bindings"); 125 126 var states = []; 127 128 var attrCount = gl.getParameter(gl.MAX_VERTEX_ATTRIBS); 129 for (var n = 0; n < attrCount; n++) { 130 gl.bindBuffer(gl.ARRAY_BUFFER, null); 131 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); 132 133 var state = {}; 134 states.push(state); 135 136 var vao = state.vao = gl.createVertexArray(); 137 gl.bindVertexArray(vao); 138 139 var enableArray = (n % 2 == 0); 140 if (enableArray) { 141 gl.enableVertexAttribArray(n); 142 } else { 143 gl.disableVertexAttribArray(n); 144 } 145 146 if (enableArray) { 147 var buffer = state.buffer = gl.createBuffer(); 148 gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 149 gl.bufferData(gl.ARRAY_BUFFER, 1024, gl.STATIC_DRAW); 150 151 gl.vertexAttribPointer(n, 1 + n % 4, gl.FLOAT, true, n * 4, n * 4); 152 } 153 154 if (enableArray) { 155 var elbuffer = state.elbuffer = gl.createBuffer(); 156 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elbuffer); 157 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 1024, gl.STATIC_DRAW); 158 } 159 160 gl.bindVertexArray(null); 161 } 162 163 var anyMismatch = false; 164 for (var n = 0; n < attrCount; n++) { 165 var state = states[n]; 166 167 gl.bindVertexArray(state.vao); 168 169 var shouldBeEnabled = (n % 2 == 0); 170 var isEnabled = gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_ENABLED); 171 if (shouldBeEnabled != isEnabled) { 172 testFailed("VERTEX_ATTRIB_ARRAY_ENABLED not preserved"); 173 anyMismatch = true; 174 } 175 176 var buffer = gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING); 177 if (shouldBeEnabled) { 178 if (buffer == state.buffer) { 179 // Matched 180 if ((gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_SIZE) == 1 + n % 4) && 181 (gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_TYPE) == gl.FLOAT) && 182 (gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_NORMALIZED) == true) && 183 (gl.getVertexAttrib(n, gl.VERTEX_ATTRIB_ARRAY_STRIDE) == n * 4) && 184 (gl.getVertexAttribOffset(n, gl.VERTEX_ATTRIB_ARRAY_POINTER) == n * 4)) { 185 // Matched 186 } else { 187 testFailed("VERTEX_ATTRIB_ARRAY_* not preserved"); 188 anyMismatch = true; 189 } 190 } else { 191 testFailed("VERTEX_ATTRIB_ARRAY_BUFFER_BINDING not preserved"); 192 anyMismatch = true; 193 } 194 } else { 195 // GL_CURRENT_VERTEX_ATTRIB is not preserved 196 if (buffer) { 197 testFailed("VERTEX_ATTRIB_ARRAY_BUFFER_BINDING not preserved"); 198 anyMismatch = true; 199 } 200 } 201 202 var elbuffer = gl.getParameter(gl.ELEMENT_ARRAY_BUFFER_BINDING); 203 if (shouldBeEnabled) { 204 if (elbuffer == state.elbuffer) { 205 // Matched 206 } else { 207 testFailed("ELEMENT_ARRAY_BUFFER_BINDING not preserved"); 208 anyMismatch = true; 209 } 210 } else { 211 if (elbuffer == null) { 212 // Matched 213 } else { 214 testFailed("ELEMENT_ARRAY_BUFFER_BINDING not preserved"); 215 anyMismatch = true; 216 } 217 } 218 } 219 gl.bindVertexArray(null); 220 if (!anyMismatch) { 221 testPassed("All attributes preserved across bindings"); 222 } 223 224 for (var n = 0; n < attrCount; n++) { 225 var state = states[n]; 226 gl.deleteVertexArray(state.vao); 227 } 228 } 229 230 function runAttributeValueTests() { 231 debug("Testing that attribute values are not attached to bindings"); 232 233 var v; 234 var vao0 = gl.createVertexArray(); 235 var anyFailed = false; 236 237 gl.bindVertexArray(null); 238 gl.vertexAttrib4f(0, 0, 1, 2, 3); 239 240 v = gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB); 241 if (!(v[0] == 0 && v[1] == 1 && v[2] == 2 && v[3] == 3)) { 242 testFailed("Vertex attrib value not round-tripped?"); 243 anyFailed = true; 244 } 245 246 gl.bindVertexArray(vao0); 247 248 v = gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB); 249 if (!(v[0] == 0 && v[1] == 1 && v[2] == 2 && v[3] == 3)) { 250 testFailed("Vertex attrib value reset across bindings"); 251 anyFailed = true; 252 } 253 254 gl.vertexAttrib4f(0, 4, 5, 6, 7); 255 gl.bindVertexArray(null); 256 257 v = gl.getVertexAttrib(0, gl.CURRENT_VERTEX_ATTRIB); 258 if (!(v[0] == 4 && v[1] == 5 && v[2] == 6 && v[3] == 7)) { 259 testFailed("Vertex attrib value bound to buffer"); 260 anyFailed = true; 261 } 262 263 if (!anyFailed) { 264 testPassed("Vertex attribute values are not attached to bindings") 265 } 266 267 gl.bindVertexArray(null); 268 gl.deleteVertexArray(vao0); 269 } 270 271 function runDrawTests() { 272 debug("Testing draws with various VAO bindings"); 273 274 canvas.width = 50; canvas.height = 50; 275 gl.viewport(0, 0, canvas.width, canvas.height); 276 277 var vao0 = gl.createVertexArray(); 278 var vao1 = gl.createVertexArray(); 279 280 var opt_positionLocation = 0; 281 var opt_texcoordLocation = 1; 282 283 var program = wtu.setupSimpleTextureProgram(gl, opt_positionLocation, opt_texcoordLocation); 284 285 function setupQuad(s) { 286 var vertexObject = gl.createBuffer(); 287 gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); 288 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 289 1.0 * s, 1.0 * s, 0.0, 290 -1.0 * s, 1.0 * s, 0.0, 291 -1.0 * s, -1.0 * s, 0.0, 292 1.0 * s, 1.0 * s, 0.0, 293 -1.0 * s, -1.0 * s, 0.0, 294 1.0 * s, -1.0 * s, 0.0]), gl.STATIC_DRAW); 295 gl.enableVertexAttribArray(opt_positionLocation); 296 gl.vertexAttribPointer(opt_positionLocation, 3, gl.FLOAT, false, 0, 0); 297 298 var vertexObject = gl.createBuffer(); 299 gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); 300 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 301 1.0 * s, 1.0 * s, 302 0.0 * s, 1.0 * s, 303 0.0 * s, 0.0 * s, 304 1.0 * s, 1.0 * s, 305 0.0 * s, 0.0 * s, 306 1.0 * s, 0.0 * s]), gl.STATIC_DRAW); 307 gl.enableVertexAttribArray(opt_texcoordLocation); 308 gl.vertexAttribPointer(opt_texcoordLocation, 2, gl.FLOAT, false, 0, 0); 309 }; 310 311 function readLocation(x, y) { 312 var pixels = new Uint8Array(1 * 1 * 4); 313 gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels); 314 return pixels; 315 }; 316 function testPixel(blockList, allowList) { 317 function testList(list, expected) { 318 for (var n = 0; n < list.length; n++) { 319 var l = list[n]; 320 var x = -Math.floor(l * canvas.width / 2) + canvas.width / 2; 321 var y = -Math.floor(l * canvas.height / 2) + canvas.height / 2; 322 var source = readLocation(x, y); 323 if (Math.abs(source[0] - expected) > 2) { 324 return false; 325 } 326 } 327 return true; 328 } 329 return testList(blockList, 0) && testList(allowList, 255); 330 }; 331 function verifyDraw(drawNumber, s) { 332 wtu.clearAndDrawUnitQuad(gl); 333 var blockList = []; 334 var allowList = []; 335 var points = [0.0, 0.2, 0.4, 0.6, 0.8, 1.0]; 336 for (var n = 0; n < points.length; n++) { 337 if (points[n] <= s) { 338 blockList.push(points[n]); 339 } else { 340 allowList.push(points[n]); 341 } 342 } 343 if (testPixel(blockList, allowList)) { 344 testPassed("Draw " + drawNumber + " passed pixel test"); 345 } else { 346 testFailed("Draw " + drawNumber + " failed pixel test"); 347 } 348 }; 349 350 // Setup all bindings 351 setupQuad(1); 352 gl.bindVertexArray(vao0); 353 setupQuad(0.5); 354 gl.bindVertexArray(vao1); 355 setupQuad(0.25); 356 357 // Verify drawing 358 gl.bindVertexArray(null); 359 verifyDraw(0, 1); 360 gl.bindVertexArray(vao0); 361 verifyDraw(1, 0.5); 362 gl.bindVertexArray(vao1); 363 verifyDraw(2, 0.25); 364 365 gl.bindVertexArray(null); 366 gl.deleteVertexArray(vao0); 367 gl.deleteVertexArray(vao1); 368 369 // Disable global vertex attrib array 370 gl.disableVertexAttribArray(opt_positionLocation); 371 gl.disableVertexAttribArray(opt_texcoordLocation); 372 373 // Draw with values. 374 var positionLoc = 0; 375 var colorLoc = 1; 376 var gridRes = 1; 377 wtu.setupIndexedQuad(gl, gridRes, positionLoc); 378 // Set the vertex color to red. 379 gl.vertexAttrib4f(colorLoc, 1, 0, 0, 1); 380 381 var vao0 = gl.createVertexArray(); 382 gl.bindVertexArray(vao0); 383 var program = wtu.setupSimpleVertexColorProgram(gl, positionLoc, colorLoc); 384 wtu.setupIndexedQuad(gl, gridRes, positionLoc); 385 // Set the vertex color to green. 386 gl.vertexAttrib4f(colorLoc, 0, 1, 0, 1); 387 wtu.clearAndDrawIndexedQuad(gl, gridRes); 388 wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green") 389 gl.deleteVertexArray(vao0); 390 wtu.clearAndDrawIndexedQuad(gl, gridRes); 391 wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green") 392 } 393 394 function runUnboundDeleteTests() { 395 debug("Testing using buffers that are deleted when attached to unbound VAOs"); 396 397 var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position", "a_color"]); 398 gl.useProgram(program); 399 400 var positionBuffer = gl.createBuffer(); 401 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 402 gl.bufferData( 403 gl.ARRAY_BUFFER, 404 new Float32Array([ 405 1.0, 1.0, 406 -1.0, 1.0, 407 -1.0, -1.0, 408 1.0, -1.0]), 409 gl.STATIC_DRAW); 410 411 var colors = [ 412 [255, 0, 0, 255], 413 [ 0, 255, 0, 255], 414 [ 0, 0, 255, 255], 415 [ 0, 255, 255, 255] 416 ]; 417 var colorBuffers = []; 418 var elementBuffers = []; 419 var vaos = []; 420 for (var ii = 0; ii < colors.length; ++ii) { 421 var vao = gl.createVertexArray(); 422 vaos.push(vao); 423 gl.bindVertexArray(vao); 424 // Set the position buffer 425 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 426 gl.enableVertexAttribArray(0); 427 gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0); 428 429 var elementBuffer = gl.createBuffer(); 430 elementBuffers.push(elementBuffer); 431 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer); 432 gl.bufferData( 433 gl.ELEMENT_ARRAY_BUFFER, 434 new Uint8Array([0, 1, 2, 0, 2, 3]), 435 gl.STATIC_DRAW); 436 437 // Setup the color attrib 438 var color = colors[ii]; 439 if (ii < 3) { 440 var colorBuffer = gl.createBuffer(); 441 colorBuffers.push(colorBuffer); 442 gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 443 gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array( 444 [ color[0], color[1], color[2], color[3], 445 color[0], color[1], color[2], color[3], 446 color[0], color[1], color[2], color[3], 447 color[0], color[1], color[2], color[3] 448 ]), gl.STATIC_DRAW); 449 gl.enableVertexAttribArray(1); 450 gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, 0); 451 } else { 452 gl.vertexAttrib4f(1, color[0] / 255, color[1] / 255, color[2] / 255, color[3] / 255); 453 } 454 } 455 456 // delete the color buffers AND the position buffer. 457 gl.bindVertexArray(null); 458 for (var ii = 0; ii < colorBuffers.length; ++ii) { 459 gl.deleteBuffer(colorBuffers[ii]); 460 gl.deleteBuffer(elementBuffers[ii]); 461 gl.bindVertexArray(vaos[ii]); 462 var boundBuffer = gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING); 463 // The buffers should still be valid at this point, since it was attached to the VAO 464 if(boundBuffer != colorBuffers[ii]) { 465 testFailed("buffer removed too early"); 466 } 467 } 468 gl.bindVertexArray(null); 469 gl.deleteBuffer(positionBuffer); 470 471 // Render with the deleted buffers. As they are referenced by VAOs they 472 // must still be around. 473 for (var ii = 0; ii < colors.length; ++ii) { 474 var color = colors[ii]; 475 gl.bindVertexArray(vaos[ii]); 476 gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0); 477 wtu.checkCanvas(gl, color, "should be " + color); 478 } 479 480 // Clean up. 481 for (var ii = 0; ii < colorBuffers.length; ++ii) { 482 gl.deleteVertexArray(vaos[ii]); 483 } 484 485 for (var ii = 0; ii < colorBuffers.length; ++ii) { 486 // The buffers should no longer be valid now that the VAOs are deleted 487 if(gl.isBuffer(colorBuffers[ii])) { 488 testFailed("buffer not properly cleaned up after VAO deletion"); 489 } 490 } 491 } 492 493 function runBoundDeleteTests() { 494 debug("Testing using buffers that are deleted when attached to bound VAOs"); 495 496 var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_position", "a_color"]); 497 gl.useProgram(program); 498 499 var positionBuffer = gl.createBuffer(); 500 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 501 gl.bufferData( 502 gl.ARRAY_BUFFER, 503 new Float32Array([ 504 1.0, 1.0, 505 -1.0, 1.0, 506 -1.0, -1.0, 507 1.0, -1.0]), 508 gl.STATIC_DRAW); 509 510 // Setup the color attrib 511 var colorBuffer = gl.createBuffer(); 512 gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 513 gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array( 514 [ 255, 0, 0, 255, 515 0, 255, 0, 255, 516 0, 0, 255, 255, 517 0, 255, 255, 255 518 ]), gl.STATIC_DRAW); 519 520 var vaos = []; 521 var elementBuffers = []; 522 for (var ii = 0; ii < 4; ++ii) { 523 var vao = gl.createVertexArray(); 524 vaos.push(vao); 525 gl.bindVertexArray(vao); 526 527 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 528 gl.enableVertexAttribArray(0); 529 gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0); 530 531 var elementBuffer = gl.createBuffer(); 532 elementBuffers.push(elementBuffer); 533 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer); 534 gl.bufferData( 535 gl.ELEMENT_ARRAY_BUFFER, 536 new Uint8Array([0, 1, 2, 0, 2, 3]), 537 gl.STATIC_DRAW); 538 539 gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); 540 gl.enableVertexAttribArray(1); 541 gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, 0); 542 } 543 544 // delete the color buffers AND the position buffer, that are bound to the current VAO 545 for (var ii = 0; ii < vaos.length; ++ii) { 546 gl.bindVertexArray(vaos[ii]); 547 548 gl.deleteBuffer(colorBuffer); 549 gl.deleteBuffer(positionBuffer); 550 551 // After the first iteration, deleteBuffer will be a no-op, and will not unbind its matching 552 // bind points on the now-bound VAO like it did on the first iteration. 553 var expectRetained = (ii != 0); 554 var shouldBeStr = (expectRetained ? "retained" : "cleared"); 555 556 var boundPositionBuffer = gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING); 557 if (expectRetained != (boundPositionBuffer == positionBuffer)) { 558 testFailed("Position attrib stored buffer should be " + shouldBeStr + "."); 559 } 560 561 var boundColorBuffer = gl.getVertexAttrib(1, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING); 562 if (expectRetained != (boundColorBuffer == colorBuffer)) { 563 testFailed("Color attrib stored buffer should be " + shouldBeStr + "."); 564 } 565 566 // If retained, everything should still work. If cleared, drawing should now fail. 567 gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0); 568 var expectedError = (expectRetained ? gl.NO_ERROR : gl.INVALID_OPERATION); 569 wtu.glErrorShouldBe(gl, expectedError, 570 "Draw call should " + (expectRetained ? "not " : "") + "fail."); 571 572 if (gl.isBuffer(positionBuffer)) { 573 testFailed("References from unbound VAOs don't keep Position buffer alive."); 574 } 575 if (gl.isBuffer(colorBuffer)) { 576 testFailed("References from unbound VAOs don't keep Color buffer alive"); 577 } 578 } 579 } 580 581 function runArrayBufferBindTests() { 582 debug("Testing that VAOs don't effect ARRAY_BUFFER binding."); 583 584 gl.bindVertexArray(null); 585 586 var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["a_color", "a_position"]); 587 gl.useProgram(program); 588 589 // create shared element buuffer 590 var elementBuffer = gl.createBuffer(); 591 // bind to default 592 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer); 593 gl.bufferData( 594 gl.ELEMENT_ARRAY_BUFFER, 595 new Uint8Array([0, 1, 2, 0, 2, 3]), 596 gl.STATIC_DRAW); 597 598 // first create the buffers for no vao draw. 599 var nonVAOColorBuffer = gl.createBuffer(); 600 gl.bindBuffer(gl.ARRAY_BUFFER, nonVAOColorBuffer); 601 gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array( 602 [ 0, 255, 0, 255, 603 0, 255, 0, 255, 604 0, 255, 0, 255, 605 0, 255, 0, 255, 606 ]), gl.STATIC_DRAW); 607 608 // shared position buffer. 609 var positionBuffer = gl.createBuffer(); 610 gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); 611 gl.bufferData( 612 gl.ARRAY_BUFFER, 613 new Float32Array([ 614 1.0, 1.0, 615 -1.0, 1.0, 616 -1.0, -1.0, 617 1.0, -1.0]), 618 gl.STATIC_DRAW); 619 620 // attach position buffer to default 621 gl.enableVertexAttribArray(1); 622 gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0); 623 624 // now create vao 625 var vao = gl.createVertexArray(); 626 gl.bindVertexArray(vao); 627 628 // attach the position buffer vao 629 gl.enableVertexAttribArray(1); 630 gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0); 631 632 var vaoColorBuffer = gl.createBuffer(); 633 gl.enableVertexAttribArray(0); 634 gl.vertexAttribPointer(0, 4, gl.UNSIGNED_BYTE, true, 0, 0); 635 gl.bindBuffer(gl.ARRAY_BUFFER, vaoColorBuffer); 636 gl.bufferData(gl.ARRAY_BUFFER, new Uint8Array( 637 [ 255, 0, 0, 255, 638 255, 0, 0, 255, 639 255, 0, 0, 255, 640 255, 0, 0, 255, 641 ]), gl.STATIC_DRAW); 642 gl.enableVertexAttribArray(0); 643 gl.vertexAttribPointer(0, 4, gl.UNSIGNED_BYTE, true, 0, 0); 644 645 // now set the buffer back to the nonVAOColorBuffer 646 gl.bindBuffer(gl.ARRAY_BUFFER, nonVAOColorBuffer); 647 648 // bind to vao 649 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer); 650 gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0); 651 wtu.checkCanvas(gl, [255, 0, 0, 255], "should be red"); 652 653 // unbind vao 654 gl.bindVertexArray(null); 655 656 // At this point the nonVAOColorBuffer should be still be bound. 657 // If the WebGL impl is emulating VAOs it must make sure 658 // it correctly restores this binding. 659 gl.enableVertexAttribArray(0); 660 gl.vertexAttribPointer(0, 4, gl.UNSIGNED_BYTE, true, 0, 0); 661 gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_BYTE, 0); 662 wtu.checkCanvas(gl, [0, 255, 0, 255], "should be green"); 663 } 664 665 debug(""); 666 var successfullyParsed = true; 667 </script> 668 <script src="../../js/js-test-post.js"></script> 669 670 </body> 671 </html>