使用OpenGL的2D Sprite动画技术

时间:2015-01-02 19:07:28

标签: c++ opengl animation sprite vbo

我目前正在尝试使用OpenGL 4设置2D精灵动画。 例如,我设计了一个与Gimp平滑旋转的球。大约有32帧(4行8帧)。

我的目标是在2D纹理中创建一个精灵图集,并将我的精灵数据存储在缓冲区(VBO)中。我的精灵矩形总是相同的(即rect(0,0,32,32))但每次帧索引递增时我的纹理坐标都会改变。

我想知道如何修改坐标。

  1. 由于精灵图块存储在多行上,如果在着色器中难以管理它。
  2. 使用glBufferSubData()?
  3. 修改缓冲区内的精灵纹理坐标

    我花了很多时间使用OpenGL 1.x ....几个月前我回到了OpenGL,但我意识到很多事情都发生了变化。我会尝试几种选择,但欢迎您的建议和经验。

3 个答案:

答案 0 :(得分:4)

  

由于精灵图块存储在多行上(如果看起来像是)   很难在着色器中管理它。

不是真的,你所有的精灵都是相同的大小,所以你得到一个完美的均匀网格,从一些1D索引到2D只是一个除法和模数的问题。不是很难。

但是,为什么甚至将单帧存储在m x n网格中?现在你可以将它们存储在一行中。但是,在现代GL中,我们有array textures。这些基本上是一组独立的2D图层,大小相同。您只需通过3D坐标访问它们,第三个坐标是从o到n-1的图层。这非常适合您的使用案例,并且可以消除边界处纹理过滤/渗色的任何问题,并且它也可以与mipmapping一起使用(如果您需要)。当引入数组纹理时,实现需要支持的最小层数为64(现在它要高得多),因此即使对于旧GPU,32帧也是小菜一碟。

答案 1 :(得分:1)

你可以做到这一百万种方式,但我会提出一个天真的解决方案:

创建一个具有32(框架正方形)* 2(每个框架正方形的三角形)* 3(三角形顶点)* 5(每个顶点的x,y,z,u,v)= 960个浮动空间的VBO。用2个三角形每帧的方式填充所有精灵的顶点。

现在根据glDrawArrays的文档,您可以指定开始的位置以及渲染时间。使用此功能,您可以指定以下内容:

int indicesPerFrame = 960/32;
int indexToStart = indicesPerFrame*currentBallFrame;
glDrawArrays( GL_TRIANGLES, indexToStart, indicesPerFrame);

无需修改VBO。现在从我的角度来看,一次只渲染32帧1帧就太过分了。这个问题有更好的解决方案,但这对于学习OpenGL4来说是最简单的。

答案 2 :(得分: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文本,但它是相同的概念!

我希望有所帮助!