2013-02-19 66 views
3

我想在opengl中为我的2D游戏绘制大量的2D圆圈。他们都是相同的大小,并具有相同的纹理。许多精灵重叠。什么是最快的方式来做到这一点?性能 - 在opengl中绘制许多2D圆圈

an example of the kind of effect I'm making http://img805.imageshack.us/img805/6379/circles.png

(应当指出的是,黑边只是由于圈子的扩大爆炸,里面装着一会儿这个截屏拍摄后。

目前我我使用了一对带纹理的三角形来制作每一个圆,我在纹理的边缘有透明效果,使它看起来像一个圆圈,使用混合来证明这非常缓慢(并且z culling是不可能的,因为它们是但是我没有使用混合,而是让我的片段着色器丢弃了alpha为0的任何片段。这可以起作用,但这意味着早期的z不是poss ible(作为碎片被丢弃)。

的速度由大量透支和GPU的填充率限制。圆圈的顺序并不重要(假设它在创建闪烁的帧之间不会改变),所以我一直试图确保屏幕上的每个像素只能写入一次。

我试图通过使用深度缓冲区。在每帧开始时,它被清除为1.0f。然后当绘制圆时,它将深度缓冲区的那部分更改为0.0f。如果通常会绘制另一个圆圈,则不是新圆圈的z为0.0f。这不会低于当前深度缓冲区中的0.0f,因此不会被绘制。这是有效的,并且应该减少必须绘制的像素的数量。然而;奇怪的是它并没有更快。我已经提出了一个关于这种行为的问题(opengl depth buffer slow when points have same depth),并且建议在使用相等的z值时,z culling没有被加速。

相反,我必须给所有我的圈子,从0向上分离假z值。然后当我使用glDrawArrays和默认的GL_LESS渲染时,由于z剔除,我们正确地获得了速度提升(尽管早期的z不可能,因为碎片被丢弃以使圆圈可能)。然而,这并不理想,因为我不得不添加大量与z相关的代码来进行2d游戏,而这种游戏根本不需要它(并且如果可能的话,不会传递z值更快)。然而,这是我目前找到的最快捷的方式。

最后,我使用模板缓冲区已经尝试,这里我用

glStencilFunc(GL_EQUAL, 0, 1); 
glStencilOp(GL_KEEP, GL_INCR, GL_INCR); 

当模板缓冲区被重置为0的每个帧。这个想法是在第一次绘制像素之后。然后在模板缓冲区中将其更改为非零。那么该像素不应再次被绘制,从而减少透支量。然而,这已经证明不会比仅仅绘制没有模板缓冲区或深度缓冲区的东西快。

什么是最快的方法人们发现写做什么,我想?

+0

你是在一个批次中绘制它们吗? – 2013-02-19 16:38:48

+0

是的,只有一个glDrawArrays(GL_TRIANGLES,0,100001 *(2 * 3));每帧画出它们全部。 – Ellipsis 2013-02-19 16:52:06

+0

嗯我会期待相当好的结果 - 当窗户较小时,它会更快? – 2013-02-19 17:01:23

回答

2

根本问题是,你是填充有限,这是GPU无法遮盖你要求它在你期待的时间画的所有片段。你是深度缓冲诀窍是无效的原因是,处理的时间最comsuming部分被遮蔽片段(无论是通过你自己的片段着色器,或通过固定功能着色引擎),发生之前深度测试。使用模板也会出现同样的问题;在模版印刷之前着色像素。

有几件事情,可能会有帮助,但取决于您的硬件:

  • 从正面采用深度缓冲来支持渲染你的精灵。现代GPU经常试图确定在将它们发送给阴影之前是否可见碎片集合。粗略地说,检查深度缓冲区(或其表示)以查看是否将要着色的片段可见,如果不是,则处理在该点处终止。这应该有助于减少需要写入帧缓冲区的像素数量。
  • 使用一个片段着色器立即检查你的纹理像素的alpha值,在此之前任何额外的处理丢弃的片段,如:

    varying vec2 texCoord; 
    uniform sampler2D tex; 
    
    void main() 
    { 
        vec4 texel = texture(tex, texCoord); 
    
        if (texel.a < 0.01) discard; 
    
        // rest of your color computations 
    } 
    

(你也可以使用Alpha测试中固定功能片段处理,但是不可能说是否在片段着色完成之前应用测试)。

+0

我可能一直不清楚。如果我给每个圆圈在z轴上的不同值,它实际上是两倍的速度(在我的测试中),根本不使用深度缓冲。但是,对于圆圈,具有相同z值的深度缓冲并不明显快于根本不做z缓冲。 (它看起来应该和它一样工作?)这可能是因为你的第一点。 (这很有趣,因为这听起来像早期的z?我认为这是不可能的,如果你丢弃在片段着色器?)我的片段着色器就是这样。感谢您的答复。 – Ellipsis 2013-02-19 18:30:21

+0

@Ellipsis使用深度缓冲并不意味着:至少您可以将一堆读取 - 修改 - 写入循环保存到颜色和深度缓冲区,所以我并不感到惊讶。至于使用相同的z值,我不知道。这可能是因为快速模式下的深度测试不到深度,或者相同模式下的结果与未进行深度测试的结果基本相同。最后,如果你使用这个技巧,那么有些架构会禁用early-z,但它不是所有GPU的通用特性 - 这是一个实现问题,也是你通过测试发现的。而且,不客气。 – radical7 2013-02-19 18:40:58