2017-03-02 129 views
0

我试图让使用this tutorial在OpenGL水模拟。的OpenGL ES 2.0:缓冲区调整

到目前为止它已经相当不错了,我试图尽可能地提高效率,所以不是像以前那样每帧都使用glBufferData,而是试图使用glBufferSubData。这是伟大的,因为我真的需要更新的唯一事情是顶水位的Y坐标,所以我跳过了大量的数据。

然而,由于水模拟有水滴,我碰到的一个问题。看来使用glBufferSubData时,由于液滴频繁出现和消失,我似乎无法找到一种方法,以任何添加到缓冲区,你不能添加新的数据。

因为唯一的其他选项似乎是使用索引VAO,所以我使用一个VBO作为水和水滴,但由于没有任何重复的顶点,这似乎毫无意义。

有另一种方式,我不知道这将帮助我,还是我使用glBufferData所有数据卡住下去吗?

+0

你可以预先分配足够的内存来满足您所有的液滴。 – BDL

+0

我不知道这会是多少内存 – MysteryPancake

回答

0

调整大小的缓冲器通常是不存在的概念。您不知道在需要增加的缓冲区之后是否有空间,或者存储是否可用。所有似乎有此选项的操作实际上都会检查这些异常,并在需要时重新分配缓冲区。

但在你的情况下,GPU上的缓冲区非常接近设备内存中的缓冲区。您甚至可以映射内存以使用glMapBuffer来接收void*指针,但请检查完成此过程的整个过程。

结合这些事实,您可以单独管理缓冲区中的数据。如果缓冲区需要膨胀,则应该创建一个新缓冲区,然后将旧数据复制到其中。其中一个程序将是2的倍数需要时充气缓冲:

  • 开始与一些固定的缓冲区大小,可以说currentSize = sizof(GLfloat*3*1000)
  • 保持填充数据和跟踪你的房间有多少。当缓冲器满它充气
  • newSize = currentSize*2膨胀由2
  • 分配一个新的缓冲区与新的大小
  • 地图两个缓冲器的
  • 复制第一currentSize字节到新的缓冲器(memcpy
  • currentSizenewSize

但现在,这是比较容易的部分。您的问题还包含可能会丢弃缓冲块的情况。所以你需要跟踪这些人。你删除一个

的事情是

  • 使它们的坐标关闭屏幕
  • 将它们标记为可废弃的
  • 推回数据每次:该是我能想到的几种方法他们每个人都有缺点。我个人会去与一个废弃:

    假设您正在使用的ObjectiveC/C的工作(如果你使用的是斯威夫特只是不打扰)。你将有一个顶点结构:

    struct MyVertex { 
        GLfloat x,y; 
        // Add additional values here like color or whatever 
        GLfloat discarded; 
    }; 
    

    然后对你的对象中的单个片段S结构:

    struct Drop { 
        MyVertex vertices[6]; // or wahtever 
    } 
    

    现在,您可以设置属性的指针,你将需要添加另外一个这是可丢弃的(在glAttributePointer)。对于您正在使用的位置NULL+offsetof(MyVertex, x),可丢弃NULL+offsetof(MyVertex, discarded)。并且步幅sizeof(MyVertex) ...

    现在在片段着色器中检查丢弃的值,并丢弃片段(如果它具有某个值)(您可以选择任何值表示任何值)。

    所以,现在每当你要添加的下降,你可以通过你的阵列中的存储和检查跌幅之一被丢弃,并使用一个。所以,你的所有顶点设置drops[index].vertices[i].discarded = 0.0和使用缓冲子数据程序来更新缓冲区的这一部分。

    当你想删除它,你需要设置丢弃到1.0(或任何你想要的),但也记得设置顶点等于值(例如全0)。这是因为您减少了生成的碎片数量。如果你只是产生一些完全离屏的坐标,这是最佳的。

    如果可能永远不会使用魔法的数字,从来没有使用固定的值。该sizeofoffsetofstructunion应该足以有效地管理原始数据。通过使用这种变化,结构永远不会破坏你的逻辑。

相关问题