将向量数组传递给着色器

Passing Array Of Vectors To Shader

尝试将 vec3 数组传递给着色器时,Firefox 给我这个警告:

WebGL warning: uniform setter: (uniform u_colors[0]) 'values' length (4) must be a positive integer multiple of size of <enum 0x8b51>.

此外,它只呈现黑色,而不是给定的颜色。

const colrs = [
    [239, 71, 111],
    [255, 209, 102],
    [6, 214, 160],
    [17, 138, 178]
  ],
  dmnsn = [1200, 300],
  glCtx = (() => twgl.getContext(document.createElement("canvas")))(
    twgl.setDefaults({ attribPrefix: "a_" })
  );

var bfInf = twgl.primitives.createXYQuadBufferInfo(glCtx),
  pgInf = twgl.createProgramInfo(glCtx, ["vs", "fs"]);
function rendr(fbi, pi, u) {
  twgl.bindFramebufferInfo(glCtx, fbi);
  twgl.drawObjectList(glCtx, [
    {
      programInfo: pi,
      bufferInfo: bfInf,
      uniforms: u
    }
  ]);
}
function prepr() {
  glCtx.canvas.width = dmnsn[0];
  glCtx.canvas.height = dmnsn[1];
  document.body.append(glCtx.canvas);
  rendr(null, pgInf, { u_colors: colrs });
}
prepr();
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<script id="vs" type="x-shader/x-vertex">
  attribute vec4 a_position;
  attribute vec2 a_texcoord;

  varying vec2 v_texcoord;

  void main() {
    v_texcoord = a_texcoord;
    gl_Position = a_position;
  }
</script>
<script id="fs" type="x-shader/x-fragment">
  precision highp float;
  
  uniform vec3 u_colors[4];

  void main() {
    gl_FragColor= vec4(u_colors[0], 1.0);
  }
</script> 

WebGL 不需要数组的数组。

const someArrayWith4ArraysOf3Values = [
  [11, 22, 33],
  [44, 55, 66],
  [77, 88, 99],
  [10, 11, 12],
];
gl.uniform3fv(some4ElementVec3Uniform, someArrayWith4ArraysOf3Values); // bad

它想要一个平面阵列。

const someArrayWith12Values = [
  11, 22, 33,
  44, 55, 66,
  77, 88, 99,
  10, 11, 12,
];
gl.uniform3fv(some4ElementVec3Uniform, someArrayWith12Values); // good

此外,着色器中的颜色是从 0 到 1 的浮点值,因此您可能希望在着色器中将颜色设置为 0 到 1 的值或除以 255

const colrs = [
    [1, 0.7, 0.5],
    [255, 209, 102],
    [6, 214, 160],
    [17, 138, 178]
  ].flat(),
  dmnsn = [1200, 300],
  glCtx = (() => twgl.getContext(document.createElement("canvas")))(
    twgl.setDefaults({ attribPrefix: "a_" })
  );

var bfInf = twgl.primitives.createXYQuadBufferInfo(glCtx),
  pgInf = twgl.createProgramInfo(glCtx, ["vs", "fs"]);
function rendr(fbi, pi, u) {
  twgl.bindFramebufferInfo(glCtx, fbi);
  twgl.drawObjectList(glCtx, [
    {
      programInfo: pi,
      bufferInfo: bfInf,
      uniforms: u
    }
  ]);
}
function prepr() {
  glCtx.canvas.width = dmnsn[0];
  glCtx.canvas.height = dmnsn[1];
  document.body.append(glCtx.canvas);
  rendr(null, pgInf, { u_colors: colrs });
}
prepr();
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<script id="vs" type="x-shader/x-vertex">
  attribute vec4 a_position;
  attribute vec2 a_texcoord;

  varying vec2 v_texcoord;

  void main() {
    v_texcoord = a_texcoord;
    gl_Position = a_position;
  }
</script>
<script id="fs" type="x-shader/x-fragment">
  precision highp float;
  
  uniform vec3 u_colors[4];

  void main() {
    gl_FragColor=vec4(u_colors[0], 1.0);
  }
</script>