如果我想在WebGL中更改对象的大小或位置,我会获取此对象的原始顶点数据{x,y,z}并将其传递给顶点着色器,并在其中与矩阵相乘,它保存有关转换的信息,产生一组新的坐标,这些坐标只有我的GPU知道,但对我来说是不可见的。
这是唯一可行的,就像唯一重要的是屏幕上的图片,但我希望能够保存变换后的顶点而不需要有关矩阵乘法的附加信息,只需要x,y,z值,就像原始数据一样。
我的想法是,最后一步是在JavaScript中将转换矩阵与我自己的原始顶点数据相乘,但我只是不能让它工作!
我编写了以下函数,通过添加第四个值{1.0}将4x4矩阵与x,y,z值数组相乘,将vec3数据更改为vec4-data ...
function matrixVectorProduct (mat4, data) {
var result = new Array( );
for (var i = 0; i < data.length / 3; i++) {
var n = i * 3;
var vec4 = [data[n], data[n + 1], data[n + 2], 1.0];
var x = mat4[0] * vec4[0] + mat4[1] * vec4[1] +
mat4[2] * vec4[2] + mat4[3] * vec4[3];
var y = mat4[4] * vec4[0] + mat4[5] * vec4[1] +
mat4[6] * vec4[2] + mat4[7] * vec4[3];
var z = mat4[8] * vec4[0] + mat4[9] * vec4[1] +
mat4[10] * vec4[2] + mat4[11] * vec4[3];
var w = mat4[12] * vec4[0] + mat4[13] * vec4[1] +
mat4[14] * vec4[2] + mat4[15] * vec4[3];
result.push(x, y, z, w);
}
return result;
}
...但除了我不知道如何将vec4值转换回vec3值之外,整个概念一定有问题:
假设我们有一个像
这样的简单三角形的顶点var vertices = [0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0];
我们用
创建一个4x4矩阵function createMat4 ( ) {
var mat4 = new Float32Array(16);
mat4[0] = 1; mat4[1] = 0; mat4[2] = 0; mat4[3] = 0;
mat4[4] = 0; mat4[5] = 1; mat4[6] = 0; mat4[7] = 0;
mat4[8] = 0; mat4[9] = 0; mat4[10] = 1; mat4[11] = 0;
mat4[12] = 0; mat4[13] = 0; mat4[14] = 0; mat4[15] = 1;
return mat4;
}
翻译它 - 假设[0,0,-5] - 使用此函数
function translateMat4 (mat4, vec3) {
var x = vec3[0],
y = vec3[1],
z = vec3[2];
var a = mat4;
mat4[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
mat4[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
mat4[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
mat4[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
return mat4;
}
最后使用上面提到的vertices
函数将创建和翻译的矩阵与matrixVectorProduct
中存储的顶点数据相乘,结果应为
translatedVertices = [0.0, 1.0, -5.0, -1.0, -1.0, -5.0, 1.0, -1.0, -5.0];
但它只是[x,y,z,1],因为-5 x 0.0(z值)等于0,所以它不能这样工作。
我做错了什么?
答案 0 :(得分:1)
你非常接近。我将从头开始实现它,仅用于案例。
让我们有一个带顶点的三角形简单模型:
var triangleVertices = [ 0.0, 1.0, 0.0,
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0 ];
现在我们创建一个mat4,它代表在这个模型上完成的所有转换。没有变换由单位矩阵表示,它在对角线上全是0但是1。
var identityMatrix = [ 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 ];
var modelMatrix = identityMatrix.slice(0); // slice = clone the array
我们准备进行翻译,轮换或缩放。在模型上应用它的最佳方法是创建另一个mat4,它将代表我们所需的变换,然后将模型矩阵与变换矩阵相乘。通过这种方式,我们可以通过几个矩阵运算以所需的顺序进行多次转换,而现在我们根本不需要打扰顶点。
所以让我们创建最简单的翻译矩阵。你从单位矩阵开始,你必须只更改mat [12,13,14],即x,y,z。
翻译它 - 让我们说[0,0,-5] - 使用这个函数
var translate = [ 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0,-5.0, 1.0 ];
转换矩阵已完成,我们希望将其与模型矩阵相乘。乘法矩阵是转换,任何转换。矩阵乘法的功能我现在已经完成了。它应该工作我希望:) Math source from wiki.
var mat4Multiply = (function () {
function ABProduct(i, j, a, b) {
var k, sum = 0;
for (k = 0; k < 4; k++) {
sum += a[i * 4 + k] * b[j + k * 4];
}
return sum;
}
function mat4Multiply(a, b) {
var i, j, product = [];
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
product[i * 4 + j] = ABProduct(i, j, a, b);
}
}
return product;
}
return mat4Multiply;
})();
// a = model matrix, b = transformation
只是为了演示如何进行乘法,短代码:
modelMatrix = mat4Multiply(modelMatrix, translate);
// but now I change my mind and I want to move model again by another 3 in Z
translate = [ 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 3.0, 1.0 ];
modelMatrix = mat4Multiply(modelMatrix, translate);
// after this content of the modelMatrix is:
// [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, -2, 1]
现在我们必须只进行顶点的最终转换。正如我所说,翻译是最容易的转换,所以我只会做翻译功能,this is related article from wiki。
注
不要对这张照片感到困惑:
这是OpenGL中使用的表示,但后来我们决定使用矩阵的转置版本,这对下面的图片操作简单:
结束注释
翻译功能:
function vec3TranslateMat4(vec, mat4) {
vec[0] += mat4[12];
vec[1] += mat4[13];
vec[2] += mat4[14];
return vec;
}
要转换三角形顶点,您必须执行以下操作:
var i, vertex;
for(i=0;i<triangleVertices.length;i+=3) {
vertex = triangleVertices.slice(i, i+3);
vertex = vec3TranslateMat4(vertex, modelMatrix)
triangleVertices[i] = vertex[0];
triangleVertices[i+1] = vertex[1];
triangleVertices[i+2] = vertex[2];
}
一旦我们应用了变换矩阵,我们应该再次将模型矩阵设置为单位矩阵。之后,我们可以在修改的顶点上进行新的转换。
我们完成了。 Personaly我使用gl matrix library已经包含了我需要的矩阵和向量的所有操作。
有和没有矩阵的转换
所有转换都可以在没有矩阵的情况下完成。但矩阵允许我们将当前位置保持在一个变量中,而无需立即变换顶点。顶点变换是漫长而耗时的。
另一个很好的理由是你只能使用几个核心功能,mat4Multiply和vec3TransformMat4(我没有告诉你这个)。了解如何在矩阵中集成旋转和比例(图像的左侧部分,右侧部分是相机)。