想象一下以下场景:您有一组PNG格式的RPG角色spritesheets,并且您希望在OpenGL应用程序中使用它们.
单独的字符(通常)大小为16乘24像素(即24像素高),并且可以处于任何宽度和高度而不留下填充.有点像:
来自最终幻想VI的Terra http://helmet.kafuka.org/terra.net/nomura/Terra.png
我已经有了代码来确定给定帧索引和大小的基于整数的剪切矩形:
int framesPerRow = sheet.Width / cellWidth;
int framesPerColumn = sheet.Height / cellHeight;
framesTotal = framesPerRow * framesPerColumn;
int left = frameIndex % framesPerRow;
int top = frameIndex / framesPerRow;
//Clipping rect's width and height are obviously cellWidth and cellHeight.
Run Code Online (Sandbox Code Playgroud)
运行此代码frameIndex = 11, cellWidth = 16, cellHeight = 24将返回一个cliprect,(32, 24)-(48, 48)假设它的右/底与宽度/高度相对.
实际的问题
现在,给定一个剪切矩形和一个X/Y坐标来放置精灵,我该如何在OpenGL中绘制它?有在零坐标顶部左侧是首选.
你必须开始考虑坐标在[0,1]范围内的"纹理空间".
所以,如果你有一个精灵表:
class SpriteSheet {
int spriteWidth, spriteHeight;
int texWidth, texHeight;
int tex;
public:
SpriteSheet(int t, int tW, int tH, int sW, int sH)
: tex(t), texWidth(tW), texHeight(tH), spriteWidth(sW), spriteHeight(sH)
{}
void drawSprite(float posX, float posY, int frameIndex);
};
Run Code Online (Sandbox Code Playgroud)
您所要做的就是将顶点和纹理顶点提交给OpenGL:
void SpriteSheet::drawSprite(float posX, float posY, int frameIndex) {
const float verts[] = {
posX, posY,
posX + spriteWidth, posY,
posX + spriteWidth, posY + spriteHeight,
posX, posY + spriteHeight
};
const float tw = float(spriteWidth) / texWidth;
const float th = float(spriteHeight) / texHeight;
const int numPerRow = texWidth / spriteWidth;
const float tx = (frameIndex % numPerRow) * tw;
const float ty = (frameIndex / numPerRow + 1) * th;
const float texVerts[] = {
tx, ty,
tx + tw, ty,
tx + tw, ty + th,
tx, ty + th
};
// ... Bind the texture, enable the proper arrays
glVertexPointer(2, GL_FLOAT, verts);
glTexCoordPointer(2, GL_FLOAT, texVerts);
glDrawArrays(GL_TRI_STRIP, 0, 4);
}
};
Run Code Online (Sandbox Code Playgroud)
弗兰克斯解决方案已经很好了.
只是一个(非常重要的)旁注,因为有些评论建议不然.
请不要使用glBegin/glEnd.不要告诉别人使用它.
唯一可以使用glBegin/glEnd的是你的第一个OpenGL程序.
数组并不难处理,但......