OpenGL spritesheets - 初学者需要一些指导

Kaw*_*awa 5 opengl sprite

想象一下以下场景:您有一组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中绘制它?有在零坐标顶部左侧是首选.

Fra*_*ger 8

你必须开始考虑坐标在[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)

  • 一个男人的倒置是另一个男人的正面朝上.:-)很高兴你按照你喜欢的方式得到它. (2认同)
  • @Kawa:实际上使用glBegin/End是一个非常糟糕的主意.CPU开销是可测量的.并且不推荐使用glBegin/End.在一个(预先计算的)数组中使用所有可能的"帧"然后使用glDrawArrays的第二个参数(例如frameIndex*4)将是一个很大的收获,因为GFX硬件可以缓存阵列. (2认同)

And*_*eas 6

弗兰克斯解决方案已经很好了.

只是一个(非常重要的)旁注,因为有些评论建议不然.

请不要使用glBegin/glEnd.不要告诉别人使用它.

唯一可以使用glBegin/glEnd的是你的第一个OpenGL程序.

数组并不难处理,但......

  • ......他们更快
  • ......他们仍然可以使用更新的OpenGL版本.
  • ......他们将与GLES合作.
  • ...从文件加载它们要容易得多.