8

例如,如果我使用如下顶点着色器:

#version 400 core

uniform mat4 projM;
uniform mat4 viewM;
uniform mat4 modelM;

in vec4 in_Position;

out vec4 pass_position_model;

void main(void) {
    gl_Position = projM * viewM * modelM * in_Position;
    pass_position_model = modelM * in_Position;
}

它会projM * viewM * modelM为每个顶点进行矩阵乘法,还是足够聪明地计算一次并且在统一变量改变之前不重新计算?如果它不够“聪明”,那么除了计算 CPU 上的所有统一相关值并将它们作为统一变量发送到 GPU 之外,还有其他方法可以优化它吗?
我也对以后可以毫无问题地移植到 OpenGL ES 2.0 的解决方案感兴趣。

4

4 回答 4

10

因此,据我所知,没有一般的答案。不过,我对我的硬件做了一些测试。我的库存中有 2 个 GPU,Intel HD Graphics 3000并且NVidia GeForce GT 555M. 我在顶点着色器中使用矩阵乘法测试了我的程序(程序本身是用 java/scala 编写的),然后将乘法移动到 CPU 程序并再次测试。

(sphereN - 它是一个具有 2*N^2 四边形的连续旋转球体,使用 glDrawElements(GL_QUADS,...) 绘制,具有 1 个纹理且没有任何照明/其他效果)

顶点着色器中的矩阵乘法:

intel:
    sphere400: 57.17552887364208 fps
    sphere40: 128.1394156842645 fps
nvidia:
    sphere400: 134.9527665317139 fps
    sphere40: 242.0135527589545 fps

cpu上的矩阵乘法:

intel:
    sphere400: 57.37234652897303 fps
    sphere40: 128.2051282051282 fps
nvidia:
    sphere400: 142.28799089356858 fps
    sphere40: 247.1576866040534 fps

测试表明,在顶点着色器中乘法(均匀)矩阵是个坏主意,至少在这个硬件上是这样。所以一般来说可能不依赖于相应的 GLSL 编译器优化。

于 2013-03-18T11:19:45.437 回答
3

它会为每个顶点执行 projM * viewM * modelM 矩阵乘法,还是足够聪明地计算一次并且在统一变量更改之前不重新计算?

询问相关 OpenGL 实现的开发人员。OpenGL 规范对此没有任何规定,但驱动程序和 GLSL 编译器编写者可能已经为此实现了优化。

如果它不够“聪明”,那么除了计算 CPU 上的所有统一相关值并将它们作为统一变量发送到 GPU 之外,还有其他方法可以优化它吗?

不,你必须自己做跑腿工作。

于 2013-03-17T15:02:10.967 回答
1

所有 OpenGL 和 GLSL 优化都是特定于供应商的。很难说 glsl 编译器的最终输出是什么。

您可以在此处查找供应商特定信息: http ://renderingpipeline.com/graphics-literature/low-level-gpu-documentation/

对于您的代码,您始终可以将矩阵“打包”到新的 uniform:matModelViewProjection中,在应用程序中将其相乘并将其发送到顶点着色器。

于 2013-03-17T15:06:12.173 回答
0

这完全取决于驱动程序。OpenGL 是一个规范,如果您向他们支付实施实施的权利,他们会给您一个示例实施以供使用,但仅此而已。

除此之外,您需要考虑矩阵乘法限制,doingprojM * viewM * modelM * vertex与doing 不同vertex * projM * viewM * modelM。那是因为矩阵是从右到左相乘的,顺序确实很重要。所以着色器不能预先计算projM * viewM * modelM以在顶点之间共享,因为这会给你带来虚假的结果。

于 2013-03-17T15:15:46.967 回答