2017-12-21 20 views
1

Ich versuche, zwei Maschen, ein Quadrat und ein Dreieck zu erstellen. Der Code ist am unteren Rand.WebGL VertexAttribPointer zeigt auf den falschen VBO

Zuerst erstelle ich ein Shader-Programm "program1", Array-Puffer "vertexBuffer1" und einen Element-Array-Puffer "indexBuffer1" für das erste Mesh. Das erste Netz ist ein Quadrat.

Dann mache ich das gleiche für die zweite Masche. Die zweite Masche ist ein Dreieck.

Wenn ich den Code ausführen bekomme ich den Fehler:

[.Offscreen-For-WebGL-000002B76A973870]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 0

Ich habe nicht den Fehler, wenn ich diese Zeile aus kommentieren:

//gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0); // <- problem! 

denke ich, was irgendwie passiert, dass Die vbo des Dreiecks ("vertexBuffer2") wird mit dem Shader-Programm des Quadrates ("program1") verbunden. Dies führt dazu, dass

gl.drawElements(gl.TRIANGLES, indices1.length, gl.UNSIGNED_SHORT, 0); 

fehlschlägt, während es versucht, ein Quadrat aus dem Vertexpuffer Dreieck zu zeichnen.

verstehe ich nicht, warum

gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0); // <- problem! 

Ursachen "program1" auf "vertexBuffer2" zu verbinden, wenn das überhaupt das Problem ist. Wie mache ich diese zwei Programme ("program1" und "program2") verbinden Sie mit jedem ihrer Puffer?

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="utf-8"> 
</head> 
<body> 
    <canvas id="canvas" width="500" height="450" style="border:1px solid black"></canvas> 
    <script> 
     // setup gl 
     var canvas = document.getElementById("canvas"); 
     var gl = canvas.getContext("webgl"); 
     gl.enable(gl.DEPTH_TEST); 
     gl.depthFunc(gl.LEQUAL); 
     gl.clearColor(0.5, 0.5, 0.5, 0.9); 
     gl.clearDepth(1.0); 

     gl.viewport(0.0, 0.0, canvas.width, canvas.height); 

     // setup mesh 1 
     // // vertex shader 
     var vertexShader1 = gl.createShader(gl.VERTEX_SHADER); 
     var vertexShaderCode = ` 
      // in 
      attribute vec3 position; 

      void main(void) { 
       gl_Position = vec4(position, 1.); 
      } 
     `; 
     gl.shaderSource(vertexShader1, vertexShaderCode); 
     gl.compileShader(vertexShader1); 
     // // fragment shader 
     var fragmentShader1 = gl.createShader(gl.FRAGMENT_SHADER); 
     var fragmentShaderCode = ` 
      precision mediump float; 
      // in 
      void main(void) { 
       gl_FragColor = vec4(1., 0., 0., 1.); 
      } 
     `; 
     gl.shaderSource(fragmentShader1, fragmentShaderCode); 
     gl.compileShader(fragmentShader1); 
     // // program1 
     var program1 = gl.createProgram(); 
     gl.attachShader(program1, vertexShader1); 
     gl.attachShader(program1, fragmentShader1); 
     gl.linkProgram(program1); 
     gl.useProgram(program1); 

     // // create buffer 1 
     var vertices1 = [ // suqare 
      -0.5, -0.5, 0, 
      0.5, -0.5, 0, 
      0.5, 0.5, 0, 
      -0.5, 0.5, 0, 
     ]; 
     var vertexBuffer1 = gl.createBuffer(); 
     gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer1); 
     gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices1), gl.STATIC_DRAW); 
     var loc = gl.getAttribLocation(program1, "position"); 
     gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0); 
     gl.enableVertexAttribArray(loc); 

     var indices1 = [ 
      0,1,2, 
      0,2,3, 
     ]; 
     var indexBuffer1 = gl.createBuffer(); 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer1); 
     gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices1), gl.STATIC_DRAW); 

     // setup mesh 2 
     // // vertex shader 
     var vertexShader2 = gl.createShader(gl.VERTEX_SHADER); 

     gl.shaderSource(vertexShader2, vertexShaderCode); // uses same vertexShaderCode as above 
     gl.compileShader(vertexShader2); 
     // // fragment shader 
     var fragmentShader2 = gl.createShader(gl.FRAGMENT_SHADER); 

     gl.shaderSource(fragmentShader2, fragmentShaderCode); 
     gl.compileShader(fragmentShader2); 
     // // program2 
     var program2 = gl.createProgram(); 
     gl.attachShader(program2, vertexShader2); 
     gl.attachShader(program2, fragmentShader2); 
     gl.linkProgram(program2); 
     gl.useProgram(program2); 

     // // create buffer 2 
     var vertices2 = [ // triangle one less vertex than in buffer 1 
      -0.5, -0.5, 0, 
      0.5, -0.5, 0, 
      0.5, 0.5, 0, 
     ]; 
     var vertexBuffer2 = gl.createBuffer(); 
     gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer2); 
     gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices2), gl.STATIC_DRAW); 
     var loc = gl.getAttribLocation(program2, "position"); 
     // On the line below it seems like program1 instead of program2 gets connected to the vertexBuffer2 
     gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0); // <- problem! 
     gl.enableVertexAttribArray(loc); 

     var indices2 = [ 
      0,1,2, 
     ]; 
     var indexBuffer2 = gl.createBuffer(); 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer2); 
     gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices2), gl.STATIC_DRAW); 

     // render 
     // // clear 
     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 
     // // render mesh 1 (the square) 
     gl.useProgram(program1); 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer1); 
     gl.drawElements(gl.TRIANGLES, indices1.length, gl.UNSIGNED_SHORT, 0); // <- this line fail 
    </script> 
</body> 
</html> 

Antwort

1

Note, gl.vertexAttribPointer gibt den Zustand für eine generische Vertexattributanordnung.

Zuerst erstellen und binden Sie vertexBuffer1, indexBuffer1 und program1. Und geben Sie an:

gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer1); 
.... 
var loc = gl.getAttribLocation(program1, "position"); // loc == 0 
gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0); 
gl.enableVertexAttribArray(loc); 

Zweite Sie erstellen und binden vertexBuffer2, indexBuffer2 und program2. Und geben Sie an:

gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer2); 
.... 
var loc = gl.getAttribLocation(program2, "position"); // loc == 0 
gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0); 
gl.enableVertexAttribArray(loc); 

Schließlich rufen Sie:

gl.useProgram(program1); 
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer1); 
gl.drawElements(gl.TRIANGLES, indices1.length, gl.UNSIGNED_SHORT, 0); 

In diesem Moment der Vertex Pufferstaat noch vertexBuffer2 bezieht, denn dies ist der letzte Zustand ist, die Sie mit dem Index für das generische Vertexattribut angegeben 0.

ändern yor Code wie folgt:

gl.linkProgram(program1); 
var loc1 = gl.getAttribLocation(program1, "position"); 

.... 

gl.useProgram(program1); 
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer1); 
gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0); 
gl.enableVertexAttribArray(loc); 
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer1); 
gl.drawElements(gl.TRIANGLES, indices1.length, gl.UNSIGNED_SHORT, 0); 

Hinweis: Es reicht aus, das Vertex-Attribut sate unmittelbar vor dem Zeichnen eines Netzes zu setzen. Zum Verwalten verschiedener Status von Vertexattributen können Sie VertexArrayObjects verwenden, die in WebGL 2.0 unterstützt werden oder in WebGL 1.0 über extension verfügbar sind.


Siehe Code-Schnipsel:

// setup gl 
 
     var canvas = document.getElementById("canvas"); 
 
     var gl = canvas.getContext("webgl"); 
 
     gl.enable(gl.DEPTH_TEST); 
 
     gl.depthFunc(gl.LEQUAL); 
 
     gl.clearColor(0.5, 0.5, 0.5, 0.9); 
 
     gl.clearDepth(1.0); 
 

 
     gl.viewport(0.0, 0.0, canvas.width, canvas.height); 
 

 
     // setup mesh 1 
 
     // // vertex shader 
 
     var vertexShader1 = gl.createShader(gl.VERTEX_SHADER); 
 
     var vertexShaderCode = ` 
 
      // in 
 
      attribute vec3 position; 
 

 
      void main(void) { 
 
       gl_Position = vec4(position, 1.); 
 
      } 
 
     `; 
 
     gl.shaderSource(vertexShader1, vertexShaderCode); 
 
     gl.compileShader(vertexShader1); 
 
     // // fragment shader 
 
     var fragmentShader1 = gl.createShader(gl.FRAGMENT_SHADER); 
 
     var fragmentShaderCode = ` 
 
      precision mediump float; 
 
      // in 
 
      void main(void) { 
 
       gl_FragColor = vec4(1., 0., 0., 1.); 
 
      } 
 
     `; 
 
     gl.shaderSource(fragmentShader1, fragmentShaderCode); 
 
     gl.compileShader(fragmentShader1); 
 
     // // program1 
 
     var program1 = gl.createProgram(); 
 
     gl.attachShader(program1, vertexShader1); 
 
     gl.attachShader(program1, fragmentShader1); 
 
     gl.linkProgram(program1); 
 
     var loc1 = gl.getAttribLocation(program1, "position"); 
 
     
 
     // // create buffer 1 
 
     var vertices1 = [ // suqare 
 
      -0.5, -0.5, 0, 
 
      0.5, -0.5, 0, 
 
      0.5, 0.5, 0, 
 
      -0.5, 0.5, 0, 
 
     ]; 
 
     var vertexBuffer1 = gl.createBuffer(); 
 
     gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer1); 
 
     gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices1), gl.STATIC_DRAW); 
 
        
 
     var indices1 = [ 
 
      0,1,2, 
 
      0,2,3, 
 
     ]; 
 
     var indexBuffer1 = gl.createBuffer(); 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer1); 
 
     gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices1), gl.STATIC_DRAW); 
 

 
     // setup mesh 2 
 
     // // vertex shader 
 
     var vertexShader2 = gl.createShader(gl.VERTEX_SHADER); 
 

 
     gl.shaderSource(vertexShader2, vertexShaderCode); // uses same vertexShaderCode as above 
 
     gl.compileShader(vertexShader2); 
 
     // // fragment shader 
 
     var fragmentShader2 = gl.createShader(gl.FRAGMENT_SHADER); 
 

 
     gl.shaderSource(fragmentShader2, fragmentShaderCode); 
 
     gl.compileShader(fragmentShader2); 
 
     // // program2 
 
     var program2 = gl.createProgram(); 
 
     gl.attachShader(program2, vertexShader2); 
 
     gl.attachShader(program2, fragmentShader2); 
 
     gl.linkProgram(program2); 
 
     var loc2 = gl.getAttribLocation(program2, "position"); 
 
     
 
     // // create buffer 2 
 
     var vertices2 = [ // triangle one less vertex than in buffer 1 
 
      -0.5, -0.5, 0, 
 
      0.5, -0.5, 0, 
 
      0.5, 0.5, 0, 
 
     ]; 
 
     var vertexBuffer2 = gl.createBuffer(); 
 
     gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer2); 
 
     gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices2), gl.STATIC_DRAW); 
 

 
     var indices2 = [ 
 
      0,1,2, 
 
     ]; 
 
     var indexBuffer2 = gl.createBuffer(); 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer2); 
 
     gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices2), gl.STATIC_DRAW); 
 

 
     // render 
 
     // // clear 
 
     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); 
 
     // // render mesh 1 (the square) 
 
     gl.useProgram(program1); 
 
     gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer1); 
 
     gl.vertexAttribPointer(loc1, 3, gl.FLOAT, false, 0, 0); // <- problem! 
 
     gl.enableVertexAttribArray(loc1); 
 
     gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer1); 
 
     gl.drawElements(gl.TRIANGLES, indices1.length, gl.UNSIGNED_SHORT, 0); // <- this line fail
<canvas id="canvas" width="500" height="450" style="border:1px solid black"></canvas>

Verwandte Themen