代码之家  ›  专栏  ›  技术社区  ›  Kawa

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

  •  5
  • Kawa  · 技术社区  · 17 年前

    Terra, from Final Fantasy VI
    (来源: kafuka.org )

    我已经有了在给定帧索引和大小的情况下确定基于整数的剪切矩形的代码:

    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.
    

    使用以下方式运行此代码 frameIndex = 11, cellWidth = 16, cellHeight = 24 (32, 24)-(48, 48)

    实际问题

    左边是首选。

    4 回复  |  直到 7 年前
        1
  •  10
  •   Nicol Bolas    7 年前

    你必须开始在“纹理空间”中思考,其中坐标在[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);
    };
    

    你所要做的就是提交这两个 顶点 和 纹理顶点

        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);
        }
    
    };
    
        2
  •  7
  •   Andreas    16 年前

    这只是一个(非常重要的)旁注,因为一些评论表明情况并非如此。

    请永远不要使用glBegin/glEnd。 永远不要告诉别人使用它。

    只有在第一个OpenGL程序中才可以使用glBegin/glEnd。

    • …他们更快。
    • …它们仍然可以使用较新的OpenGL版本。
    • …他们将与GLES合作。
        3
  •  0
  •   Macke    17 年前

    我假设你正在学习OpenGL,只需要以某种方式让它工作。如果你需要原始速度,有着色器和顶点缓冲区以及各种整洁和复杂的东西。

    要使左上角为零,可以使用gluOrtho()以与普通GL不同的方式设置视图矩阵(查找该函数的文档,将top设置为0,将bottom设置为1,或者如果需要整数坐标,则将screen_height设置为1),或者只需更改绘图循环并执行glVertex2f(x/screen_width,1-y/screen_heights)。

    有更好更快的方法可以做到这一点,但如果你从头开始学习原始OpenGL,这可能是最简单的方法之一。

        4
  •  0
  •   fingerprint211b    17 年前

    1.我加载了纹理 2.我决定了如何将精灵表拆分为单独的精灵。 3.我把它们分成不同的表面 4.我为每个对象制作一个纹理(我有一个精灵类来管理它们)。 5.清理表面。 这需要更多的时间(显然)加载,但以后会有回报。 这样更容易(也更快),因为您只需计算要显示的纹理的索引,然后显示它。然后,您可以根据需要缩放/平移它,并调用显示列表将其渲染为您想要的任何内容。或者,你可以在即时模式下完成,两者都可以:)