执行纹理总和的最有效方法

时间:2014-05-03 22:32:36

标签: opengl textures glsl

从性能的角度来看,哪种方法能够执行(加权)两个纹理内容的总和?我可以在CPU或GPU上执行此操作,因为这是一种快速的方法。请注意,这必须重复多次,因此它不仅仅是一次性的两次总和。

特别是我对几种纹理的加权和感兴趣,但我相信这可以很容易地从两个总和中推广出来。

编辑: 我会更明确地说明我的目标。我将生成具有各种模糊的几个纹理(顺序),因此这些纹理将全部通过在纹理上渲染生成。我认为它们的数量不会超过8/9。

结果必须在屏幕上显示结果。

1 个答案:

答案 0 :(得分:2)

因此,如果正确理解问题,您将渲染为一些纹理,然后需要对所有这些纹理进行加权求和,并希望仅显示该图像。如果是这样,您可以只进行一次额外的渲染过程,同时绑定所有纹理,然后计算片段着色器中所有纹理的加权和。由于您不需要将结果作为texutre,因此您可以直接渲染到默认的帧缓冲区中,因此结果应立即可见。

最多需要9个纹理,你可以实际遵循这个策略,因为会有足够的纹理单元。但是,这种方法可能有点不灵活,特别是如果你必须处理不同数量的纹理以便在不同的时间点进行总结。

如果你可以只有一个带有计数的统一变量,重量值数组,以及着色器中的一个循环可以归结为

,那就太好了。
uniform int count;
uniform float weights[MAX_COUNT];
uniform sampler2D uTex[MAX_COUNT];
[...]
for (i=0; i<count; i++)
    sum += weight[i] * texture(uTex[i], texcoords);

可以从GL 4开始。它支持纹理采样器数组,但要求访问索引动态统一,这意味着所有着色器调用将同时访问相同的纹理采样器。由于循环仅取决于统一变量,因此情况就是如此。

但是,不使用多个纹理可能是一个更好的策略。假设您的所有输入纹理具有相同的分辨率,您最好只使用一个纹理数组。您可以将一个这样的数组纹理层附加到FBO,就像使用普通的2D纹理一样,因此可以独立渲染(或使用多个渲染目标一次渲染到多个图层)工作。然后,您只需要绑定该单个数组纹理,并且可以执行

uniform int count;
uniform float weights[MAX_COUNT];
uniform sampler2Darray uTex;
[...]
for (i=0; i<count; i++)
    sum += weight[i] * texture(uTex, vec3(texcoords,i));

这仅需要GL3级硬件,并且您可以使用的最大计数不受纹理着色器可用的纹理单元数量的限制,而是受纹理阵列限制(通常> 256)和可用内存的限制。但是,如果计数过高,性能会下降。您可能会达到实际使用多个过程的某个点,在这个过程中,由于纹理缓存,您只能将图像的某个子范围相加变得更有效。在该方法中,不同层的所有纹理访问竞争纹理高速缓存,对相邻片段之间的高速缓存命中率产生负面影响。但是,对于8或9个输入图像,这应该没有问题。