哪个 WebGL api 使统一值无效?

Which WebGL api's invalidate uniform values?

假设我们有以下代码:

gl.useProgram(p1);
gl.uniform1i(p1_u, 5);
gl.drawArrays(...);

gl.useProgram(p2);
g.uniform1i(p2_u, 100);

// on another loop of the application
// i will   need to use p1 again
gl.useProgram(p1);
gl.uniform1i(p1_u, 5);           // <<------- A

p1 & p2WebGLPrograms 和 p1_u, p2_uWebGLUniformLocations.
如果他们的值没有改变,可以跳过更新制服吗?
即使在切换 GLPrograms 之后?

或者换句话说:
哪个 WebGL api 使统一值无效,需要重新提交?

Which WebGL api's invalidate uniform values, and makes it necessary to re-submit them?

None:所有 WebGL 状态都与您设置的完全一样。除了 (deleteXXX)

之外,没有间接更改状态的 WebGL API

请注意,统一值是程序状态。换句话说,它们对于每个着色器程序都是唯一的。

示例:

const gl = document.querySelector('canvas').getContext('webgl');

const vsrc = `
attribute vec4 position;
void main() {
  gl_Position = position;
  gl_PointSize = 40.0;
}
`;

const fsrc = `
precision mediump float;
uniform vec4 color;
void main() {
  gl_FragColor = color;
}
`;

const vs = createAndCompileShader(gl, gl.VERTEX_SHADER, vsrc);
const fs = createAndCompileShader(gl, gl.FRAGMENT_SHADER, fsrc);

const redPrg = linkProgramAndSetColor(gl, vs, fs, [1, 0, 0, 1]);
const bluePrg = linkProgramAndSetColor(gl, vs, fs, [0, 0, 1, 1]);

function render(time) {
  time *= 0.001; // convert to seconds;
  
  gl.useProgram(redPrg);
  gl.vertexAttrib2f(0, Math.cos(time), Math.sin(time));
  gl.drawArrays(gl.POINTS, 0, 1);

  gl.useProgram(bluePrg);
  gl.vertexAttrib2f(0, Math.sin(time), Math.cos(time));
  gl.drawArrays(gl.POINTS, 0, 1);

  requestAnimationFrame(render);
}
requestAnimationFrame(render);

function createAndCompileShader(gl, type, src) {
  const s = gl.createShader(type);
  gl.shaderSource(s, src);
  gl.compileShader(s);
  if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) {
    throw new Error(gl.getShaderInfoLog(s));
  }
  return s;
}

function linkProgramAndSetColor(gl, vs, fs, color) {
  const p = gl.createProgram();
  gl.attachShader(p, vs);
  gl.attachShader(p, fs);
  gl.bindAttribLocation(p, 0, 'position');  // force position to location 0
  gl.linkProgram(p);
  if (!gl.getProgramParameter(p, gl.LINK_STATUS)) {
    throw new Error(gl.getProgramInfoLog(p));
  }
  gl.useProgram(p);
  gl.uniform4fv(gl.getUniformLocation(p, 'color'), color);
  return p;
}
canvas { border: 1px solid black; }
<canvas></canvas>