我目前正在尝试使用OpenGL 4设置2D精灵动画。 例如,我设计了一个与Gimp平滑旋转的球。大约有32帧(4行8帧)。
我的目标是在2D纹理中创建一个精灵图集,并将我的精灵数据存储在缓冲区(VBO)中。我的精灵矩形总是相同的(即rect(0,0,32,32))但每次帧索引递增时我的纹理坐标都会改变。
我想知道如何修改坐标。
我花了很多时间使用OpenGL 1.x ....几个月前我回到了OpenGL,但我意识到很多事情都发生了变化。我会尝试几种选择,但欢迎您的建议和经验。
答案 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文本,但它是相同的概念!
我希望有所帮助!