【问题标题】:WebGL batch drawing textures. Which has better performance and why?WebGL 批量绘制纹理。哪个性能更好,为什么?
【发布时间】:2013-11-28 11:57:01
【问题描述】:

我正在开发一个 WebGL 批处理渲染器(问题在 OpenGL 领域仍然有效)。也就是在尽可能少的 drawArrays/drawElements 调用(理想情况下为 1)中绘制的场景中的所有图形。其中一部分涉及允许根据属性确定纹理。

因此,在我的片段着色器中,我正在考虑两种情况:

1. 将纹理 0 绘制到屏幕上并使用属性来确定纹理位于内存中的精灵表上的“帧”。片段着色器看起来像:

precision mediump float;

uniform sampler2D u_spriteSheet;

// Represents position that's framed.
varying vec4 v_texturePosition;

void main() {
    gl_FragColor = texture2D(u_spriteSheet, v_texturePosition);
}

2. 在着色器中执行“if”语句以确定使用哪个统一 sampler2d。片段着色器看起来像:

precision mediump float;

uniform sampler2D u_image1;
uniform sampler2D u_image2;
uniform sampler2D u_image3;
uniform sampler2D u_image4;
....
uniform sampler2D u_image32;

varying uint v_imageId;
// Represents texture position that's framed
varying vec4 v_texturePosition;

void main() {
    if(v_imageId == 1) {
        gl_FragColor = texture2D(u_image1, v_texturePosition);
    }
    else if (v_imageId == 2) {
        gl_FragColor = texture2D(u_image2, v_texturePosition);
    }
    ...
    else if (v_imageId == 32) {
        gl_FragColor = texture2D(u_image32, v_texturePosition);
    }
}

我知道,对于选项 1,我受到最大纹理大小的限制,而通过方法 2,我受到可用纹理寄存器数量的限制。为了便于讨论,我们假设永远不会超过这些限制。

我正在尝试确定更高效的方法,然后再将大量时间投入到任何一种方法中......所以有什么想法吗?

【问题讨论】:

  • 是否可以选择纹理?
  • 抱歉不熟悉行话,atased?
  • 纹理图集是您所谓的精灵表的更通用术语。

标签: opengl-es webgl


【解决方案1】:

着色器中的 If 语句通常很慢,因为在普通 GPU 硬件上 着色器作为 SIMD 执行,即并行处理许多片段, 每条指令的指令。简而言之,如果是所有线程 处理 then 部分,其中只有具有肯定 if 条件的线程 在其他线程等待时真正执行并存储结果 (甚至进行计算但不存储结果)。后来都 线程执行 else 部分,所有条件为正的线程都在等待。

所以在您的解决方案 #2 中,许多卡上的片段着色器将执行所有 32 个部分,而不仅仅是解决方案 #1 中的一个(在某些卡片上据说 如果该部分后面没有线程,他们将停止执行 if 分支 更多,所以它可能小于 32)。

所以我希望解决方案 #1 比片段着色器更快。但是,您的解决方案可能存在其他瓶颈,因此片段着色器的性能 可能与整体性能无关。

另外的想法是许多 GPU 允许少于 32 个纹理,所以你 如果您想与许多设备保持兼容,可能无法使用 32。 根据 webglstats.com 的数据,99% 有 16 个纹理单元,因为大多数 场景有超过 16 种纹理可能无法解决 实施类似于您的解决方案#1的东西。 另一方面,当您达到可能需要的最大纹理大小时 类似 #2 的东西。

【讨论】:

  • 惊人的洞察力,你太棒了!最后一个问题,如果我不得不做“if”语句,这会破坏批量渲染的性能提升吗?
  • ^Helmut,将采样器放在一个数组中并在其中使用索引有什么好处吗? (而不是 if 语句中的 texture2d()。)
  • @davidvanbrink 我很乐意这样做。我不认为你可以将一系列纹理推送到显卡上。我怎么能这样做?
  • 我不能说清楚,因为我总是使用很少,通常只使用一个绘制调用,并且还限制自己使用两种纹理。 f
  • @davidvanbrink 非常不幸的是,在 WebGL 片段着色器中,数组索引表达式不能是动态表达式(例如变量的值)link
猜你喜欢
  • 2019-05-02
  • 2010-09-11
  • 1970-01-01
  • 1970-01-01
  • 2013-11-28
  • 1970-01-01
  • 2021-10-30
  • 1970-01-01
  • 2015-01-28
相关资源
最近更新 更多