为什么gl.drawArraysInstanced无法在后续调用中绘制多个形状?

时间:2017-12-25 21:33:13

标签: javascript canvas webgl2

我正在使用WebGL2并尝试调用gl.drawArraysInstanced来绘制多个形状。 gl.drawArraysInstanced的第一次调用可以绘制2个或更多元素。

  

gl.drawArraysInstanced(gl.TRIANGLES,0,numVertices,3);

然后我在3秒后调用相同的函数,但它只画了一个三角形。 (见下面的例子)



var canvas = document.getElementById('canvas');
gl = canvas.getContext('webgl2');

var cube = {};
var vertices = [
  -0.2, -0.2, 0,
   0.2, -0.2, 0,
   0.2,  0.2, 0,
];
var numVertices = vertices.length / 3;

var vertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

var vertexShader = getAndCompileShader('vertexShader', 'vertex');
var fragmentShader = getAndCompileShader('fragmentShader', 'fragment');
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
gl.useProgram(shaderProgram);

var vao = gl.createVertexArray();
gl.bindVertexArray(vao);

var positionAttributeLocation = gl.getAttribLocation(shaderProgram, 'position');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, vertexPositionBuffer);
gl.vertexAttribPointer(positionAttributeLocation, 3, gl.FLOAT, false, 0, 0);

function getAndCompileShader(id, shaderType) {
    var shader;
    var shaderElement = document.getElementById(id);
    var shaderText = shaderElement.text.trim();
    shader = gl.createShader(
        shaderType==='vertex' ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER
    );
    gl.shaderSource(shader, shaderText);
    gl.compileShader(shader);

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        console.log(gl.getShaderInfoLog(shader));
        return true;
    }
    console.log('Shader ' + id + ' compiled.')
    return shader;
}

function start() {
  gl.clearColor(.5,0,0,1);
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.bindVertexArray(vao);
  gl.drawArraysInstanced(gl.TRIANGLES, 0, numVertices, 2);
  console.log('Drawing 2 triangles');
  setTimeout(function() {
    gl.clearColor(.5,0,0,1);
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArraysInstanced(gl.TRIANGLES, 0, numVertices, 2);
    console.log('Drawing 2 triangles again');
  }, 3000);    
}

start();

    <script id="vertexShader" type="x-shader/x-vertex">
#version 300 es
in vec3 position;

void main() {
    if(gl_InstanceID==0) {
        gl_Position = vec4(position.x - 0.2, position.yz, 1);
    } else {
    	  gl_Position = vec4(position.x + 0.2, position.yz, 1);    
    }
}
    </script>
    <script id="fragmentShader" type="x-shader/x-fragment">
#version 300 es
precision mediump float;
out vec4 finalColor;

void main() {
    finalColor = vec4(0.5,0.5,0.5,1.0);;
}
    </script>
    
    <body>
        <canvas id="canvas" style="width: 300px; height: 200px" width="600" height="400"></canvas>    
    </body>
&#13;
&#13;
&#13;

另外,调用 gl.drawArraysInstanced 应该比 gl.drawArrays 更有效吗? 感谢

1 个答案:

答案 0 :(得分:0)

绘制完成后,需要调用gl.useProgram(null)。

gl.enable(gl.DEPTH_TEST);
  gl.clearColor(.5, 0, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  gl.bindVertexArray(vao);
  gl.drawArraysInstanced(gl.TRIANGLES, 0, numVertices, 2);
  gl.useProgram(null);
  console.log('Drawing 2 triangles');
  setInterval(function () {
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    gl.useProgram(shaderProgram);
    gl.drawArraysInstanced(gl.TRIANGLES, 0, numVertices, 2);
    gl.useProgram(null);
    console.log('Drawing 2 triangles again');
  }, 3000);