I wrote some WebGL2 code to render a few thousand circles using drawArraysInstanced. I'm using code from https://webgl2fundamentals.org/webgl/lessons/webgl-instanced-drawing.html.
I also have a fullscreen quad to display a more appealing background than black. Both work independently, but rendering the instanced array of circles disrupts the background rendering.
I suspect I should unbind or unset something after rendering the circles, but I can't tell what. The problem is that the webgl2 fundamentals example doesn't specify what has to happen every frame and what has to happen once, and it doesn't attempt to render anything but the instanced arrays.
How can I clean the webgl2 state after rendering the instanced arrays so that regular rendering works again?
https://jsfiddle.net/g2xkoc56/
gl.useProgram(shader);
gl.uniform4fv(colorUniform, color);
gl.uniformMatrix4fv(viewProjectionMatrixUniform, false, viewProjectionMatrix);
bindIndexBuffer(gl, indexBuffer);
// upload the new matrix data
for (let i = 0; i < count; ++i) {
const offset = i * 16;
mat4.fromTranslation(matrixData.subarray(offset, offset + 16), positions[i]);
}
gl.bindBuffer(gl.ARRAY_BUFFER, matrixBuffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, matrixData);
const bytesPerMatrix = 4 * 16;
for (let i = 0; i < 4; ++i) {
const loc = matrixAttribute + i;
gl.enableVertexAttribArray(loc);
// note the stride and offset
const offset = i * 16; // 4 floats per row, 4 bytes per float
gl.vertexAttribPointer(
loc, // location
4, // size (num values to pull from buffer per iteration)
gl.FLOAT, // type of data in buffer
false, // normalize
bytesPerMatrix, // stride, num bytes to advance to get to next set of values
offset, // offset in buffer
);
// this line says this attribute only changes for each 1 instance
gl.vertexAttribDivisor(loc, 1);
}
bindVertexBuffer(gl, vertexPositionAttribute, vertexBuffer, 3);
bindIndexBuffer(gl, indexBuffer);
gl.drawArraysInstanced(
gl.TRIANGLE_FAN, // GL Fan, strip, etc.
0, // offset
sides+2, // num vertices per instance
count, // num instances
);
unbindIndexBuffer(gl);
unbindVertexBuffer(gl, vertexPositionAttribute);
for (let i = 0; i < 4; ++i) {
gl.disableVertexAttribArray(matrixAttribute + i);
}
I wasn't clearing the vertex attrib divisor for the instanced matrices properly after rendering the instanced particles, which was preventing the background from rendering next frame. (Though some people didn't have an issue with the same code, so maybe it was something else.)
After rendering the particles, before the break between frames:
for (let i = 0; i < 4; ++i) {
gl.vertexAttribDivisor(matrixAttribute + i, 0);
}