OpenGLES 矩阵优化

OpenGLES Matrix optimization

我正在 OpenGLES 中渲染 100 多个 3D 对象,我想知道是否可以优化此标准矩阵代码以提高性能速度:

    Matrix.setIdentityM(modelMatrix, 0);
    Matrix.translateM(modelMatrix, 0, x, y, z);
    Matrix.scaleM(modelMatrix,  0, scale,scale,1.0f);
    Matrix.rotateM(modelMatrix, 0, angle, 0.0f, 0.0f, 1.0f);        
    Matrix.multiplyMM(modelViewProjectionMatrix, 0, viewMatrix, 0, modelMatrix, 0);
    Matrix.multiplyMM(modelViewProjectionMatrix, 0, projectionMatrix, 0, modelViewProjectionMatrix, 0);

所有对象都以不同的方式缩放、旋转和定位,我的应用程序运行速度太慢。我正在研究许多其他领域,但探查器显示这段代码对性能有很大影响,那么数学可以更快地完成吗?

任何提示,非常感谢。

通过直接输入矩阵值丢失平移、缩放和旋转调用,您可能会收获很多。旋转调用可能会很慢...

矩阵起始 3x3 子矩阵由 3 个基向量(XYZ)组成,可以设置为(在您发布的示例中):

X = (cos(angle)*scale, sin(angle)*scale, .0f)
Y = (-sin(angle)*scale, cos(angle)*scale, .0f)
Z = (.0f, .0f, 1.0f)

注意:顺序取决于实现

接下来的第 4 行或第 4 列(再次取决于订单实施)在您的情况下是翻译:

T = (x, y, z, 1.0f)

仅此一项不会为您带来任何性能,因为 rotate 中也使用了 4 个昂贵的三角函数调用(sincos)。如果可能,请尝试丢失角度参数并将其替换为 way 向量,该向量是对象面向的向量。一个标准是还包括 up 向量,它是从对象面朝上的向量。有了这两个向量,您就可以使用前两个向量的叉积来计算 right 向量。结果是有 3 个垂直向量,它们应该被归一化并乘以比例,然后直接插入到矩阵中作为上面提到的 3 个基本向量。

在您的情况下,您可以获得一个方向,并且由于您的 Z 向量似乎是静态的,您可以对这两个向量使用叉积来获得第三个方向。

你的矩阵乘法的结果可以写成:

结果 = ITSR。

对于每个矩阵乘法(我假设矩阵是 4x4),你有 64 次乘法和 64 次加法。现在你有 4 个要相乘的矩阵。这是很多加法和乘法!假设您使用的是列向量。

要加快速度,请执行以下操作:

翻译矩阵将只有最后(第 4)列中的值。因此,当您乘以 IxT 时,生成的矩阵仍将只有第 4 列中的值。所以为了加快速度,只需创建一个矩阵,其中第 4 列是平移向量,就像这样,而不是进行完整的矩阵乘法:

So, we have IT =  | 1 0 0 0 |  | 1 0 0 tx |   | 1 0 0 tx |
                  | 0 1 0 0 |  | 0 1 0 ty | = | 0 1 0 ty |
                  | 0 0 1 0 |  | 0 0 1 tz |   | 0 0 1 tz |
                  | 0 0 0 1 |  | 0 0 0  1 |   | 0 0 0  1 |

转到 ITxS,因为缩放只影响对角线 - 它只影响元素 m[0][0]、m[1][1] 和 m[2][2],你可以简单地乘以这些元素矩阵的比例。所以我们将有:

Sx = m[0][0] * scale;
Sy = m[1][1] * scale;
Sz = m[2][2] * 1.0;

但是,由于IT中所有的对角线元素都是1,所以你可以直接把scale值写进对角线里……像这样:

ITS = | Sx  0   0  tx |
      | 0  Sy   0  ty |
      | 0   0  Sz  tz |
      | 0   0   0  1  |

到目前为止,我们没有执行任何矩阵乘法 - 我们只是手动创建了矩阵。所以你可以创建一个看起来像 ITS 的矩阵。这为您节省了 2 次矩阵乘法!!

现在转到 ITSR ......在这里,只需执行标准矩阵乘法即可:

Result = ITSR = | Sx  0   0  tx |  | A  D  G  0 |
                | 0  Sy   0  ty |  | B  E  H  0 |
                | 0   0  Sz  tz |  | C  F  I  0 |
                | 0   0   0  1  |  | 0  0  0  1 |

您可以稍微加快速度,但为了清晰起见,只需进行全矩阵乘法。所以你只需要做一个矩阵乘法,而不是 3.

此外,如果您的相机视图没有改变(viewMatrix),则不必为每一帧都推导它,投影矩阵也是如此。不知道你有没有……只是说。

希望这对您有所帮助。

@user3725725 - 我假设您使用的是列向量

Matrix.setIdentityM(modelMatrix, 0);

// Set up the scale 
modelMatrix[0] = scale;
modelMatrix[5] = scale;

// Set up Translation 
modelMatrix[12] = tx; 
modelMatrix[13] = ty;
modelMatrix[14] = tz;

// Do the rest of the matrix multiplication 
Matrix.rotateM(modelMatrix, 0, angle, 0.0f, 0.0f, 1.0f);
Matrix.multiplyMM(modelViewProjectionMatrix, 0, viewMatrix, 0, modelMatrix, 0);
Matrix.multiplyMM(modelViewProjectionMatrix, 0, projectionMatrix, 0, modelViewProjectionMatrix, 0);

PS。如果这有帮助,请考虑投赞成票 :) 谢谢!