我如何优化WebGL以快速渲染更多对象?

问题描述 投票:0回答:1

我给人的印象是WebGL比浏览器中的2d渲染器功能强大得多,但是由于某些原因,我的WebGL代码运行得慢得多。有什么推荐的优化策略可以使我的WebGL代码运行得更快一些?

我的rect函数中是否有任何应删除的代码,因为我是WebGL的新手,并且大多数教程都不介绍如何制作rect函数。

WebGL代码

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

使用普通的2D渲染器

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)
}
javascript webgl
1个回答
0
投票

一旦绑定缓冲区并在渲染后最后调用buffer,您就可以重用getAttribLocation,在getUniformLocation函数之外提取rectvertexAttribPointer以及requestAnimationFrame

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

const positionBuffer = gl.createBuffer();
const positionLocation = gl.getAttribLocation(program, "position");
const projectionLocation = gl.getUniformLocation(program, `matrix`);
const projectionColorLocation = gl.getUniformLocation(program, `color`);
gl.enableVertexAttribArray(positionLocation);
const vertex = [
    0, 0, 0, 1,
    0, 0, 0, 1,
    0, 0, 0, 1,
    0, 0, 0, 1
  ]
const floatArray = new Float32Array(vertex)
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(positionLocation, 4, gl.FLOAT, false, 0, 0);
gl.uniformMatrix4fv(projectionLocation, false, projectionMatrix);

function rect(x, y, w, h) {
  floatArray[0] = x;
  floatArray[1] = y;
  floatArray[4] = x + w;
  floatArray[5] = y;
  floatArray[8] = x;
  floatArray[9] = y + h;
  floatArray[12] = x + w;
  floatArray[13] = y + h;
  
  gl.bufferData(gl.ARRAY_BUFFER, floatArray, gl.STATIC_DRAW);    
  gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
  
}
function fill(r, g, b, a) { 
  gl.uniform4fv(projectionColorLocation, [r, g, b, a]);
}
let lastTime = new Date();
function animate() {
  let currentTime = new Date();
  console.log(1000 / (currentTime.getTime() - lastTime.getTime()));
  lastTime = new Date();
  for(let i=0;i<200;i++) {
    fill(1, 0, 0, 1);
    rect(random(0, 800), random(0, 600), 10, 10);
  }
  requestAnimationFrame(animate);
  
}
animate();
function random(low, high) {
  return low + Math.random() * (high-low)
}
<canvas id="canvas" width="500" height="300"></canvas>
© www.soinside.com 2019 - 2024. All rights reserved.