WebGL:如何将值绑定到 mat4 属性? [英] WebGL: How to bind values to a mat4 attribute?

查看:30
本文介绍了WebGL:如何将值绑定到 mat4 属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在一些 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 规范,顶点着色器属性可以定义为 floatvec2vec3vec4mat2mat3mat4.

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 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 中的步幅和偏移量以字节为单位,所以我怀疑你想要

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆