OpenGL中的2D精灵动画技术

4
我目前正在尝试使用OpenGL 4设置2D精灵动画。例如,我通过Gimp设计了一个平滑旋转的球体。大约有32帧(4行8帧)。
我打算在2D纹理中创建一个精灵图集,并将我的精灵数据存储在缓冲区(VBO)中。我的精灵矩形始终相同(即rect(0,0,32,32)),但每次帧索引增加时,我的纹理坐标会发生变化。
我想知道如何修改这些坐标。
  1. 由于精灵图块存储在多个行中,因此似乎很难在着色器中管理。
  2. 使用glBufferSubData()在缓冲区内修改精灵纹理坐标?
我花了很多时间研究OpenGL 1.x....几个月前重新开始学OpenGL时意识到很多东西已经改变了。我会尝试几个选项,但是欢迎您的建议和经验。
3个回答

5
由于精灵瓦片存储在几行中,因此似乎很难在着色器中管理它。
实际上不是这样的,因为您的所有精灵都是相同大小的,所以您可以获得完美均匀的网格,并且从1D索引到2D只是除法和模数的问题。并不难。
然而,为什么您要将单个帧存储在m×n网格中呢?现在您可以将它们存储在一行中。但是,在现代GL中,我们有{{link1:array textures}}。这些基本上是一组独立的2D图层,全部具有相同的大小。您只需通过三维坐标访问它们,其中第三个坐标是从o到n-1的图层。这非常适合您的用例,并且将消除任何纹理过滤/边缘渗透问题,它还将与mipmapping很好地配合使用(如果需要)。当引入数组纹理时,实现必须支持的最小层数为64(现在要高得多),因此即使对于旧GPU,32个帧也很容易。

3
您可以用无数种方法来实现此操作,但我将提出一种简单的解决方案:
创建一个VBO,其中包含32个(帧矩形)* 2个(每帧两个三角形)* 3个(每个三角形三个顶点)* 5个(每个顶点的x、y、z、u、v)= 960个浮点空间。 使用“2个三角形每帧”的方式填充所有精灵的顶点。
现在根据glDrawArrays文档,您可以指定开始渲染的位置和持续时间。使用此功能,您可以指定以下内容:
int indicesPerFrame = 960/32;
int indexToStart = indicesPerFrame*currentBallFrame;
glDrawArrays( GL_TRIANGLES, indexToStart, indicesPerFrame);

无需修改VBO。我认为,仅以每帧渲染32帧的方式来完成此任务是过度的。有更好的解决方案,但这是学习OpenGL4最简单的方法。

谢谢sgtHale。那是我计划实现的解决方案的一部分 :) - Zyend

0
在OpenGL 2.1中,我正在使用您的第二个选项:
void setActiveRegion(int regionIndex)
{
    UVs.clear();

    int numberOfRegions = (int) textureSize / spriteWidth;

    float uv_x = (regionIndex % numberOfRegions)/numberOfRegions;
    float uv_y = (regionIndex / numberOfRegions)/numberOfRegions;

    glm::vec2 uv_up_left    = glm::vec2( uv_x                     , uv_y );
    glm::vec2 uv_up_right   = glm::vec2( uv_x+1.0f/numberOfRegions, uv_y );
    glm::vec2 uv_down_right = glm::vec2( uv_x+1.0f/numberOfRegions, (uv_y + 1.0f/numberOfRegions) );
    glm::vec2 uv_down_left  = glm::vec2( uv_x                     , (uv_y + 1.0f/numberOfRegions) );


    UVs.push_back(uv_up_left   );
    UVs.push_back(uv_down_left );
    UVs.push_back(uv_up_right  );

    UVs.push_back(uv_down_right);
    UVs.push_back(uv_up_right);
    UVs.push_back(uv_down_left);

    glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
    glBufferSubData(GL_ARRAY_BUFFER, 0, UVs.size() * sizeof(glm::vec2), &UVs[0]);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

}

来源:http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-11-2d-text/

他实现了它来渲染2D文本,但是概念是相同的!

希望有所帮助!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接