2017-12-21 35 views
1

사각형과 삼각형 두 개의 메시를 만들려고합니다. 코드가 맨 아래에 있습니다.WebGL vertexAttribPointer가 잘못된 VBO를 가리 킵니다

먼저 셰이더 프로그램 "program1", 배열 버퍼 "vertexBuffer1"및 첫 번째 메쉬에 대한 요소 배열 버퍼 "indexBuffer1"을 만듭니다. 첫 번째 메쉬는 사각형입니다.

두 번째 메쉬에 대해서도 동일한 작업을 수행합니다. 두 번째 메쉬는 삼각형입니다. 나는이 줄을 주석 경우

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

은 삼각형 버텍스 버퍼에서 사각형을 그리는 데 실패합니다.

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

원인 "프로그램 1은"을 "vertexBuffer2"를 연결하는 이유도 문제가있는 경우

나는 이해가 안 돼요. 두 개의 프로그램 ("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, indexBuffer1program1을 만들고 바인딩하십시오.

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

둘째 작성하고 vertexBuffer2, indexBuffer2program2 바인딩 : 그리고 당신은 지정합니다. 그리고 당신은 지정

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

가 마지막으로 전화 : 정점 버퍼 상태가 여전히 vertexBuffer2을 의미 지금이 순간

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

을, 이것은 당신이 인덱스 일반 정점 속성에 지정된 마지막 상태이기 때문에 이 같은 0

변경을 yor 코드 :

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를 설정하면 충분합니다. 서로 다른 버텍스 애트리뷰트를 관리하기 위해 VertexArrayObjects을 사용할 수 있습니다. 이는 WebGL 2.0에서 지원되거나 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>

:


는 코드를 참조하십시오