WebGL:如何将值绑定到 mat4 属性? [英] WebGL: How to bind values to a mat4 attribute?
问题描述
在一些 WebGL 应用程序中,假设我们有一个 GLSL 顶点着色器,它的开头是这样的:
In some WebGL application, let's assume that we have a GLSL vertex shader which starts like this:
attribute vec4 foo1;
attribute vec4 foo2;
attribute vec4 foo3;
attribute vec4 foo4;
以及一些用于为这些属性绑定数据结构的相应 Javascript 代码:
and some corresponding Javascript code for binding a data structure for those attributes:
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
.
Now, according to the GL ES 2.0 specs, a vertex shader attribute can be defined as either a float
, vec2
, vec3
, vec4
, mat2
, mat3
or mat4
.
因此,如果我更改顶点着色器代码以仅定义一个 mat4
属性,就像这样...
So if I change the vertex shader code to define just one mat4
attribute, like so...
attribute mat4 foo;
...问题是将一些指针绑定到mat4
属性的相应JS代码是什么?
... the question is what is the corresponding JS code to bind some pointers to a mat4
attribute?
我找到了mat3 attribute in WebGL这个问题,但是答案不够明确.阅读答案和其他一些文档,似乎正确的解决方案是:
I have found the question mat3 attribute in WebGL, but the answer is not explicit enough. Reading the answers and some other documentation, it seems that the correct solution is along the lines of:
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
组件的 位置总是相邻且按递增顺序排列?记录在某处?
Am I right in assuming that the locations of the 4 vec4
components of a mat4
are always adjacent and in increasing order? Is this documented somewhere?
除了这些位置计入 MAX_VERTEX_ATTRIBS
限制(在 WebGL 中通常为 16 个)之外,还有其他需要注意的良好做法吗?
Besides these locations counting towards the MAX_VERTEX_ATTRIBS
limit (normally 16 in WebGL), is there any other good practice to be aware of?
推荐答案
你是对的.来自规范第 2.10.4 节
You're correct. From the spec section 2.10.4
当属性变量声明为 mat2
时,其矩阵列取自通用属性 i
(x, y) 组件> 和 i + 1
.当属性变量声明为 mat3
时,其矩阵列取自通用属性 i
的 (x, y, z)
组件通过 i + 2
.当属性变量声明为 mat4
时,其矩阵列取自通用属性 i
的 (x, y, z, w)
组件代码> 到 i + 3
.
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 中的步幅和偏移量以字节为单位,所以我怀疑你想要
stride and offsets in WebGL are in bytes so I suspect you wanted
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:如何将值绑定到 mat4 属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!