I am under the impression that WebGL is much more powerful than the 2d renderer in the browser but for some reason, my WebGL code runs much slower. Are there any recommended optimization strategies I can use to make my WebGL code run a little bit faster?
Are there any code in my rect function that should be left out because I am new to WebGL and most tutorials don't cover how to make a rect function.
WebGL Code
const canvas = document.getElementById("canvas");
const vertexCode = `
precision mediump float;
attribute vec4 position;
uniform mat4 matrix;
uniform vec4 color;
varying vec4 col;
void main() {
col = color;
gl_Position = matrix * position;
}
`;
const fragmentCode = `
precision mediump float;
varying vec4 col;
void main() {
gl_FragColor = col;
}
`;
const width = canvas.width;
const height = canvas.height;
const gl = canvas.getContext("webgl");
if(!gl) {
console.log("WebGL not supported");
}
const projectionMatrix = [
2/width, 0, 0, 0,
0, -2/height, 0, 0,
0, 0, 1, 0,
-1, 1, 0, 1
];
const vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexCode);
gl.compileShader(vertexShader);
const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentCode);
gl.compileShader(fragmentShader);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
function rect(x, y, w, h) {
const vertex = [
x, y, 0, 1,
x+w, y, 0, 1,
x, y+h, 0, 1,
x+w, y+h, 0, 1
]
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertex), gl.STATIC_DRAW);
const positionLocation = gl.getAttribLocation(program, "position");
gl.enableVertexAttribArray(positionLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(positionLocation, 4, gl.FLOAT, false, 0, 0);
const projectionLocation = gl.getUniformLocation(program, `matrix`);
gl.uniformMatrix4fv(projectionLocation, false, projectionMatrix);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}
function fill(r, g, b, a) {
const projectionLocation = gl.getUniformLocation(program, `color`);
gl.uniform4fv(projectionLocation, [r, g, b, a]);
}
let lastTime = new Date();
function animate() {
let currentTime = new Date();
console.log(1000 / (currentTime.getTime() - lastTime.getTime()));
lastTime = new Date();
requestAnimationFrame(animate);
for(let i=0;i<200;i++) {
fill(1, 0, 0, 1);
rect(random(0, 800), random(0, 600), 10, 10);
}
}
animate();
function random(low, high) {
return low + Math.random() * (high-low)
}
Using the normal 2D renderer
const canvas = document.getElementById("canvas");
const c = canvas.getContext("2d");
let lastTime = new Date();
function animate() {
let currentTime = new Date();
console.log(1000 / (currentTime.getTime() - lastTime.getTime()));
lastTime = new Date();
requestAnimationFrame(animate);
c.fillStyle = "black";
c.fillRect(0, 0, 800, 600);
c.fillStyle = "red";
for(let i=0;i<200;i++) {
c.fillRect(random(0, 800), random(0, 600), 10, 10);
}
}
animate();
function random(low, high) {
return low + Math.random() * (high-low)
}