使用 OpenGL ES 在 2D 空间中定位元素

发布于 2024-07-26 12:56:05 字数 1180 浏览 4 评论 0原文

在业余时间,我喜欢使用 OpenGL ES 在 iPhone 上进行游戏开发。 我正在制作一个小型 2D 横向卷轴演示,只是为了好玩,而且我对 OpenGL 还比较陌生,我想获得一些更有经验的开发人员对此的意见。

所以这是我的问题:在模型空间中指定每个 2D 元素的顶点,然后每次绘制框架时将每个元素转换到它的最终视图空间是否有意义?

例如,假设我有一组方块(方块)构成了横向卷轴游戏中的地面。 每个方块的定义如下:

const GLfloat squareVertices[] = {
        -1.0, 1.0, -6.0,            // Top left
        -1.0, -1.0, -6.0,           // Bottom left
        1.0, -1.0, -6.0,            // Bottom right
        1.0, 1.0, -6.0              // Top right
    }

假设我有 10 个这样的方块,我需要将它们绘制在一起作为下一帧的地面。 我应该对当前场景中可见的每个方块做这样的事情吗?

glPushMatrix();
{
    glTranslatef(currentSquareX, currentSquareY, 0.0);
    glVertexPointer(3, GL_FLOAT, 0, squareVertices);
    glEnableClientState(GL_VERTEX_ARRAY);

    // Do the drawing
}
glPopMatrix();

在我看来,对场景中的每个 2D 元素、每一帧执行此操作会有点紧张,我想那些比我更多地使用 OpenGL 的聪明人可能有更好的方法来执行此操作。

话虽如此,我希望听到我应该分析代码并看看可能存在瓶颈:对那些人,我说:我还没有编写任何代码,我只是在这个过程中让我全神贯注于它,这样当我真正去写它时,它会变得更顺利。

关于分析和优化的主题,我真的不想在这里过早地优化,我只是想集中精力思考如何设置 2D 场景并渲染它。 就像我说的,我对 OpenGL 还比较陌生,我只是想了解一下事情是如何完成的。 如果有人对更好的方法有任何建议,我很想听听您的想法。

请记住,我目前对 3D 不感兴趣,只对 2D 感兴趣。 谢谢!

In my spare time I like to play around with game development on the iPhone with OpenGL ES. I'm throwing together a small 2D side-scroller demo for fun, and I'm relatively new to OpenGL, and I wanted to get some more experienced developers' input on this.

So here is my question: does it make sense to specify the vertices of each 2D element in model space, then translate each element to it's final view space each time a frame is drawn?

For example, say I have a set of blocks (squares) that make up the ground in my side-scroller. Each square is defined as:

const GLfloat squareVertices[] = {
        -1.0, 1.0, -6.0,            // Top left
        -1.0, -1.0, -6.0,           // Bottom left
        1.0, -1.0, -6.0,            // Bottom right
        1.0, 1.0, -6.0              // Top right
    }

Say I have 10 of these squares that I need to draw together as the ground for the next frame. Should I do something like this, for each square visible in the current scene?

glPushMatrix();
{
    glTranslatef(currentSquareX, currentSquareY, 0.0);
    glVertexPointer(3, GL_FLOAT, 0, squareVertices);
    glEnableClientState(GL_VERTEX_ARRAY);

    // Do the drawing
}
glPopMatrix();

It seems to me that doing this for every 2D element in the scene, for every frame, gets a bit intense and I would imagine the smarter people who use OpenGL much more than I do may have a better way of doing this.

That all being said, I'm expecting to hear that I should profile the code and see where any bottlenecks may be: to those people, I say: I haven't written any of this code yet, I'm simply in the process of wrapping my mind around it so that when I do go to write it it goes smoother.

On the subject of profiling and optimization, I'm really not trying to prematurely optimize here, I'm just trying to wrap my mind around how one would set up a 2D scene and render it. Like I said, I'm relatively new to OpenGL and I'm just trying to get a feel for how things are done. If anyone has any suggestions on a better way to do this, I'd love to hear your thoughts.

Please keep in mind that I'm not interested in 3D, just 2D for now. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

内心旳酸楚 2024-08-02 12:56:06

当您有很多模型时,您关心将模型(在本例中为正方形)从模型坐标转换为世界坐标所需的开销。 这似乎是对静态模型的明显优化。

如果您在世界坐标中构建正方形的顶点,那么当然会更快,因为每个正方形将避免这三个函数(glPushMatrix、glPopMatrix 和 glTranslatef)的额外成本,因为不需要从模型转换到世界渲染时的坐标。 我不知道这会快多少,我怀疑这不会是一个巨大的优化,并且您失去了将正方形保留在模型坐标中的模块化性:如果将来您决定希望这些正方形可移动怎么办? 如果你将它们的顶点保留在世界坐标中,这将会困难得多。

简而言之,这是一个权衡:

世界坐标

  • 更多内存 - 每个方块都需要它的
    自己的一组顶点。
  • 更少的计算 - 无需执行
    glPushMatrix、glPopMatrix 或
    glTranslatef 在渲染时为每个方块。
  • 灵活性较差 - 缺乏支持(或
    复杂化)用于动态移动这些方块

模型坐标

  • 更少的内存 - 方块可以共享相同的顶点数据
  • 更多计算 - 每个方块必须
    执行三个额外功能
    渲染时间。
  • 更灵活 - 正方形可以很容易地
    通过操纵来移动
    glTranslatef 调用。

我想知道什么是正确决定的唯一方法是通过实践和分析。 我知道你说你还没有写这个,但我怀疑无论你的方块是在模型坐标还是世界坐标中,都不会产生太大的区别 - 如果有的话,我无法想象你可以构建的架构创建难以将方块从模型切换到世界坐标的位置,反之亦然。

祝您和您的 iPhone 游戏开发之旅好运!

You are concerned with the overhead it takes to transform a model (in this case a square) from model coordinates to world coordinates when you have a lot of models. This seems like an obvious optimization for static models.

If you build your square's vertices in world coordinates, then of course it is going to be faster as each square will avoid the extra cost of these three functions (glPushMatrix, glPopMatrix, and glTranslatef) since there is no need to translate from model to world coordinates at render time. I have no idea how much faster this will be, I suspect that it won't be a humongous optimization, and you lose the modularity of keeping the squares in model coordinates: What if in the future you decide you want these squares to be moveable? That will be a lot harder if you're keeping their vertices in world coordinates.

In short, it's a tradeoff:

World Coordinates

  • More Memory - each square needs its
    own set of vertices.
  • Less computation - no need to perform
    glPushMatrix, glPopMatrix, or
    glTranslatef for each square at render time.
  • Less flexible - lacks support (or
    complicates) for dynamically moving these squares

Model Coordinates

  • Less memory - the squares can share the same vertex data
  • More Computation - each square must
    perform three extra functions at
    render time.
  • More Flexible - squares can easily be
    moved by manipulating the
    glTranslatef call.

I guess the only way to know what is the right decision is by doing and profiling. I know you said you haven't written this yet, but I suspect that whether your squares are in model or world coordinates it won't make much of a difference - and if it does, I can't imagine an architecture that you could create where it would be hard to switch your squares from model to world coordinates or vice-versa.

Good luck to you and your adventures in iPhone game development!

南冥有猫 2024-08-02 12:56:06

如果您仅使用屏幕对齐的四边形,则使用 OES 可能会更容易绘制纹理扩展。 然后,您可以使用单个纹理来保存所有游戏“精灵”。 首先通过设置GL_TEXTURE_CROP_RECT_OES TexParameter 来指定裁剪矩形。 这是较大纹理内精灵的边界。 要进行渲染,请调用 glDrawTexiOES 并传入所需的位置和位置。 视口坐标中的大小。

int rect[4] = {0, 0, 16, 16};
glBindTexture(GL_TEXTURE_2D, sprites);
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect);
glDrawTexiOES(x, y, z, width, height);

此扩展并非在所有设备上都可用,但它在 iPhone 上运行良好。

If you are only using screen aligned quads it might be easier to use the OES Draw Texture extension. Then you can use a single texture to hold all your game "sprites". First specify the crop rectangle by setting the GL_TEXTURE_CROP_RECT_OES TexParameter. This is the boundry of the sprite within the larger texture. To render, call glDrawTexiOES passing in the desired position & size in viewport coordinates.

int rect[4] = {0, 0, 16, 16};
glBindTexture(GL_TEXTURE_2D, sprites);
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect);
glDrawTexiOES(x, y, z, width, height);

This extension isn't available on all devices, but it works great on the iPhone.

青瓷清茶倾城歌 2024-08-02 12:56:06

您还可以考虑使用静态图像并仅滚动该图像,而不是绘制地板的每个单独块并平移其位置等。

You might also consider using a static image and just scrolling that instead of drawing each individual block of the floor, and translating its position, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文