2017-12-21 9 views
1

2つのメッシュ、正方形と三角形を作成しようとしています。コードは一番下にあります。WebGLのvertexAttribPointerが間違ったVBOを指しています

最初に、シェーダプログラム "program1"、配列バッファ "vertexBuffer1"、および要素配列バッファ "indexBuffer1"を最初のメッシュ用に作成します。最初のメッシュは正方形です。

次に、2番目のメッシュについても同じことをします。 2番目のメッシュは三角形です。私は、この行をコメントアウトする場合

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

私はエラーを取得していない:私は、コードを実行すると

私はエラーを取得する

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

私は何が起こっているかどうかしていることだと思います三角形のvbo(「vertexBuffer2」)が四角形のシェーダプログラム(「program1」)に接続されます。これにより、三角形頂点バッファから四角形を描画しようとすると、

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

が失敗します。

私はしても問題がある場合、「vertexBuffer2」に接続するために、なぜ

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

原因「プログラム1」を理解していません。どのように2つのプログラム( "program1"と "program2")をそれぞれのバッファに接続させるのですか?

<!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> 

答えて

1

注、gl.vertexAttribPointerは、汎用頂点属性配列の状態を指定します。

まず、vertexBuffer1,indexBuffer1およびprogram1を作成してバインドします。

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); 

第二には、作成してvertexBuffer2indexBuffer2program2をバインドします。そして、あなたが指定します。そして、次のように指定します。

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); 

は、最後にあなたが呼び出す:これはあなたがインデックスを持つ一般的な頂点属性に指定した最後の状態であるため、

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

をこの時点で頂点バッファの状態は、まだ、vertexBuffer2を指し、このような0

変更ヨールコード:

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); 

メッシュを描画する直前に、頂点属性sateを設定するだけで十分です。さまざまな頂点属性の状態を管理するには、WebGL 2.0でサポートされているVertexArrayObjectsを使用するか、WebGL 1.0のextensionで使用できます。


コードスニペットを参照してください:

// 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>

関連する問題