WebGL:如何将值绑定到 mat4 属性?
WebGL: How to bind values to a mat4 attribute?
在某些 WebGL 应用程序中,假设我们有一个像这样启动的 GLSL 顶点着色器:
attribute vec4 foo1;
attribute vec4 foo2;
attribute vec4 foo3;
attribute vec4 foo4;
和一些相应的 Javascript 代码,用于为这些属性绑定数据结构:
var buf = gl.createBuffer(), loc;
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([…]));
loc = gl.getAttribLocation(program, 'foo1');
gl.enableVertexArray(loc);
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false, 16, 0);
loc = gl.getAttribLocation(program, 'foo2');
gl.enableVertexArray(loc);
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false, 16, 4);
loc = gl.getAttribLocation(program, 'foo3');
gl.enableVertexArray(loc);
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false, 16, 8);
loc = gl.getAttribLocation(program, 'foo4');
gl.enableVertexArray(loc);
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false, 16, 12);
现在,根据 GL ES 2.0 规范,顶点着色器属性可以定义为 float
、vec2
、vec3
、vec4
、mat2
、mat3
或 mat4
.
因此,如果我更改顶点着色器代码以仅定义一个 mat4
属性,就像这样...
attribute mat4 foo;
...问题是将一些指针绑定到mat4
属性的相应JS代码是什么?
我找到了问题mat3 attribute in WebGL,但答案不够明确。阅读答案和其他一些文档,似乎正确的解决方案是:
loc = gl.getAttribLocation(program, 'foo');
gl.enableVertexArray(loc);
gl.vertexAttribPointer(loc , 4, gl.FLOAT, false, 16, 0);
gl.vertexAttribPointer(loc+1, 4, gl.FLOAT, false, 16, 4);
gl.vertexAttribPointer(loc+2, 4, gl.FLOAT, false, 16, 8);
gl.vertexAttribPointer(loc+3, 4, gl.FLOAT, false, 16, 12);
我假设 mat4
的 4 个 vec4
组件的 位置始终相邻且按递增顺序排列是否正确? 是否已记录某处?
除了这些位置计入 MAX_VERTEX_ATTRIBS
限制(在 WebGL 中通常为 16 个)之外,还有其他好的做法需要注意吗?
你是对的。 From the spec 第 2.10.4 节
When an attribute variable is declared as a mat2
, its matrix columns are taken from the (x, y)
components of generic attributes i
and i + 1
. When an attribute variable is declared as a mat3
, its matrix columns are taken from the (x, y, z)
components of generic attributes i
through i + 2
. When an attribute variable is declared as a mat4
, its matrix columns are taken from the (x, y, z, w)
components of generic attributes i
through i + 3
.
WebGL 中的步幅和偏移量以字节为单位,所以我怀疑你想要
gl.vertexAttribPointer(loc , 4, gl.FLOAT, false, 64, 0);
gl.vertexAttribPointer(loc+1, 4, gl.FLOAT, false, 64, 16);
gl.vertexAttribPointer(loc+2, 4, gl.FLOAT, false, 64, 32);
gl.vertexAttribPointer(loc+3, 4, gl.FLOAT, false, 64, 48);
让我们检查一下
var vs = `
attribute mat4 matrix;
attribute vec4 color;
varying vec4 v_color;
void main() {
gl_PointSize = 10.0;
gl_Position = matrix * vec4(0, 0, 0, 1);
v_color = color;
}
`;
var fs = `
precision mediump float;
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}
`;
var m4 = twgl.m4;
var gl = document.querySelector("canvas").getContext("webgl");
var program = twgl.createProgramFromSources(gl, [vs, fs]);
var matrixLoc = gl.getAttribLocation(program, "matrix");
var colorLoc = gl.getAttribLocation(program, "color");
function r(min, max) {
if (max === undefined) {
max = min;
min = 0;
}
return Math.random() * (max - min) + min;
}
var numPoints = 100;
var matrices = [];
var colors = [];
for (var ii = 0; ii < numPoints; ++ii) {
matrices.push.apply(matrices, m4.translation([r(-1,1), r(-1,1), 0]));
colors.push(r(1), r(1), r(1), 1);
}
function makeBuffer(gl, array) {
const buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(array), gl.STATIC_DRAW);
return buf;
}
var buffers = {
matrices: makeBuffer(gl, matrices),
colors: makeBuffer(gl, colors),
};
gl.useProgram(program);
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.matrices);
for (var ii = 0; ii < 4; ++ii) {
gl.enableVertexAttribArray(matrixLoc + ii);
gl.vertexAttribPointer(matrixLoc + ii, 4, gl.FLOAT, 0, 64, ii * 16);
}
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.colors);
gl.enableVertexAttribArray(colorLoc);
gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, 0, 0, 0);
gl.drawArrays(gl.POINTS, 0, numPoints);
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/4.x/twgl-full.js" crossorigin></script>
<canvas></canvas>
在某些 WebGL 应用程序中,假设我们有一个像这样启动的 GLSL 顶点着色器:
attribute vec4 foo1;
attribute vec4 foo2;
attribute vec4 foo3;
attribute vec4 foo4;
和一些相应的 Javascript 代码,用于为这些属性绑定数据结构:
var buf = gl.createBuffer(), loc;
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([…]));
loc = gl.getAttribLocation(program, 'foo1');
gl.enableVertexArray(loc);
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false, 16, 0);
loc = gl.getAttribLocation(program, 'foo2');
gl.enableVertexArray(loc);
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false, 16, 4);
loc = gl.getAttribLocation(program, 'foo3');
gl.enableVertexArray(loc);
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false, 16, 8);
loc = gl.getAttribLocation(program, 'foo4');
gl.enableVertexArray(loc);
gl.vertexAttribPointer(loc, 4, gl.FLOAT, false, 16, 12);
现在,根据 GL ES 2.0 规范,顶点着色器属性可以定义为 float
、vec2
、vec3
、vec4
、mat2
、mat3
或 mat4
.
因此,如果我更改顶点着色器代码以仅定义一个 mat4
属性,就像这样...
attribute mat4 foo;
...问题是将一些指针绑定到mat4
属性的相应JS代码是什么?
我找到了问题mat3 attribute in WebGL,但答案不够明确。阅读答案和其他一些文档,似乎正确的解决方案是:
loc = gl.getAttribLocation(program, 'foo');
gl.enableVertexArray(loc);
gl.vertexAttribPointer(loc , 4, gl.FLOAT, false, 16, 0);
gl.vertexAttribPointer(loc+1, 4, gl.FLOAT, false, 16, 4);
gl.vertexAttribPointer(loc+2, 4, gl.FLOAT, false, 16, 8);
gl.vertexAttribPointer(loc+3, 4, gl.FLOAT, false, 16, 12);
我假设 mat4
的 4 个 vec4
组件的 位置始终相邻且按递增顺序排列是否正确? 是否已记录某处?
除了这些位置计入 MAX_VERTEX_ATTRIBS
限制(在 WebGL 中通常为 16 个)之外,还有其他好的做法需要注意吗?
你是对的。 From the spec 第 2.10.4 节
When an attribute variable is declared as a
mat2
, its matrix columns are taken from the(x, y)
components of generic attributesi
andi + 1
. When an attribute variable is declared as amat3
, its matrix columns are taken from the(x, y, z)
components of generic attributesi
throughi + 2
. When an attribute variable is declared as amat4
, its matrix columns are taken from the(x, y, z, w)
components of generic attributesi
throughi + 3
.
WebGL 中的步幅和偏移量以字节为单位,所以我怀疑你想要
gl.vertexAttribPointer(loc , 4, gl.FLOAT, false, 64, 0);
gl.vertexAttribPointer(loc+1, 4, gl.FLOAT, false, 64, 16);
gl.vertexAttribPointer(loc+2, 4, gl.FLOAT, false, 64, 32);
gl.vertexAttribPointer(loc+3, 4, gl.FLOAT, false, 64, 48);
让我们检查一下
var vs = `
attribute mat4 matrix;
attribute vec4 color;
varying vec4 v_color;
void main() {
gl_PointSize = 10.0;
gl_Position = matrix * vec4(0, 0, 0, 1);
v_color = color;
}
`;
var fs = `
precision mediump float;
varying vec4 v_color;
void main() {
gl_FragColor = v_color;
}
`;
var m4 = twgl.m4;
var gl = document.querySelector("canvas").getContext("webgl");
var program = twgl.createProgramFromSources(gl, [vs, fs]);
var matrixLoc = gl.getAttribLocation(program, "matrix");
var colorLoc = gl.getAttribLocation(program, "color");
function r(min, max) {
if (max === undefined) {
max = min;
min = 0;
}
return Math.random() * (max - min) + min;
}
var numPoints = 100;
var matrices = [];
var colors = [];
for (var ii = 0; ii < numPoints; ++ii) {
matrices.push.apply(matrices, m4.translation([r(-1,1), r(-1,1), 0]));
colors.push(r(1), r(1), r(1), 1);
}
function makeBuffer(gl, array) {
const buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(array), gl.STATIC_DRAW);
return buf;
}
var buffers = {
matrices: makeBuffer(gl, matrices),
colors: makeBuffer(gl, colors),
};
gl.useProgram(program);
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.matrices);
for (var ii = 0; ii < 4; ++ii) {
gl.enableVertexAttribArray(matrixLoc + ii);
gl.vertexAttribPointer(matrixLoc + ii, 4, gl.FLOAT, 0, 64, ii * 16);
}
gl.bindBuffer(gl.ARRAY_BUFFER, buffers.colors);
gl.enableVertexAttribArray(colorLoc);
gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, 0, 0, 0);
gl.drawArrays(gl.POINTS, 0, numPoints);
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/4.x/twgl-full.js" crossorigin></script>
<canvas></canvas>