简体   繁体   English

在OpenGL ES中将不规则形状或其他多边形(漫画,精灵)映射到三角形

[英]Mapping irregular shapes or other polygons (cartoons, sprites) to triangles in OpenGL ES

I don't understand the concept of showing sprites mapped into OpenGL Triangles. 我不明白显示精灵映射到OpenGL三角形的概念。

If OpenGL ES only draws triangles and points, How do you display/map non-triangular shapes? 如果OpenGL ES只绘制三角形和点,那么如何显示/绘制非三角形?

Why would a shape mapped to a triangle not be distorted? 为什么映射到三角形的形状不会失真?

To explain: 解释:

In my mind, mapping, say, a sprite of Mario, to a triangle would produce a distorted or cropped Mario. 在我看来,将一个马里奥的精灵映射到一个三角形会产生一个扭曲或裁剪的马里奥。 In such a case, the head would be squished or invisible. 在这种情况下,头部会被挤压或看不见。

If I've understood the concern correctly: you simply divide the square into two triangles, and use texture coordinates to divide the texture up correspondingly. 如果我正确理解了这个问题:你只需将方块分成两个三角形,然后使用纹理坐标相应地划分纹理。 If you do it right, you get the texture drawn on screen, 1:1, as if it were a sprite. 如果你做得对,你就会在屏幕上画出1:1的纹理,好像它是一个精灵。 (Of course you also have the option of rotation and stretching and whatnot.) (当然你也可以选择旋转和伸展等等。)

0     1  <-- If your square is divided up like this, say, set texcoord
+-----+      for point 0 to be the top left of the sprite; for point 3, the
|\    |      bottom right of the sprite; and correspondingly, for points
| \   |      1 and 2.
|  \  |
|   \ |
|    \|
+-----+
2     3

As it turns out, you won't get a squished sprite in quite the way you're expecting. 事实证明,你不会像你期望的那样得到一个压扁的精灵。 I imagine you're picturing drawing the triangle 0-3-2 from my picture above, say, mapped in the obvious fashion, and getting the top scanline infinitely squeezed into one point (point 0)? 我想你正在想象从我上面的图片中绘制三角形0-3-2,比如说,以明显的方式绘制,并将顶部扫描线无限挤压到一个点(点0)? But in fact this won't happen, because there's only one texture coordinate for point 0, so (if points 2 and 3 are mapped appropriately) you'll only ever get the cut-out part of the sprite. 但实际上这不会发生,因为点0只有一个纹理坐标,所以(如果第2和第3点被适当地映射),你将只得到精灵的截断部分。

(That said, you could assign the same texcoord to two points, though, or make the texture cross over itself, and get it wrong that way -- there's still plenty of scope for making a mess, don't worry.) (也就是说,你可以将相同的texcoord分配给两个点,或者让纹理跨越自己,并以错误的方式弄错 - 仍然有足够的空间制造混乱,不要担心。)

This is explained in the OpenGL programming guide, though it's years and years since I learnt this stuff so I'm not sure how helpful it will be if you're having difficulty: http://glprogramming.com/red/chapter09.html 这可以在OpenGL编程指南中解释,虽然我学习了这些东西已经多年了,所以我不确定如果你遇到困难会有多大帮助: http//glprogramming.com/red/chapter09.html

Quite simply, the texture won't be distorted because you'll only be picking three texture coordinates - one per vertex. 很简单,纹理不会扭曲,因为你只需要挑选三个纹理坐标 - 每个顶点一个。 You'll have to use two triangles as outlined above, and "clip" different portions of the texture. 您将必须使用如上所述的两个三角形,并“剪切”纹理的不同部分。

Pardon my horrible use of ASCII art here, and in the rest of this post: 请原谅我在这里使用ASCII艺术,以及在这篇文章的其余部分:

  Polygon     Texture        ADB        ACD
  A-----C  |  x-----x  |  x        |  x-----x
  |\    |  |  | ___ |  |  |        |    ___ |
  | \   |  |  |<o.o>|  |  |<o      |     .o>|
  |  \  |  |  | ### |  |  | ##     |      # |
  |   \ |  |  | -|- |  |  | -|-    |        |
  |    \|  |  | / \ |  |  | / \    |        |
  B-----D  |  x-----x  |  x-----x  |        x

You'd make two triangles - ADB and ACD. 你会制作两个三角形 - 亚行和ACD。 Point A maps to the top-left of the texture, B to the bottom-left, C to the top-right, and D to the bottom-right. A点映射到纹理的左上角,B映射到左下角,C映射到右上角,D映射到右下角。 If you only map one triangle or the other, you only get half of the sprite (or texture, for a more complex shape.) The same applies for larger or more complex polygons. 如果您只绘制一个三角形或另一个三角形,则只获得精灵的一半(或纹理,对于更复杂的形状。)同样适用于更大或更复杂的多边形。 The texture can be a single unified piece, but the texture coordinates of each vertex has to slice it up in the same manner as the geometry itself. 纹理可以是单个统一的块,但每个顶点的纹理坐标必须以与几何体本身相同的方式将其切片。

More complex example, a hexagon: 更复杂的例子,一个六边形:

   a   b
    ___
   /   \
f /  .  \ c
  \  g  /
   \___/
  e     d

If you add a middle point of "G" and slice it up into six triangles (ABG, BCG, CDG, etc) you'll have to make sure that whatever texture you're using is sliced up coordinate-wise to match. 如果你添加一个中间点“G”并将其切成六个三角形(ABG,BCG,CDG等),你必须确保你正在使用的任何纹理都是以坐标方式切片以匹配。 This doesn't matter if you're just using GL_TRIANGLES , since it's easiest to just leave the texture in its hexagonal shape, but once you start drawing strips or fans you can flip, skew, or duplicate if you don't keep close track of what vertex is mapping to what part of the texture, due to the drawing order. 如果您只使用GL_TRIANGLES ,这GL_TRIANGLES ,因为最简单的方法是将纹理保留为六边形,但是一旦开始绘制条带或扇形,如果不保持近距离跟踪,则可以翻转,倾斜或复制由于绘制顺序,什么顶点映射到纹理的哪个部分。

As an aside, if you're just concerned with 2D screen-aligned quads - which is what sprites are generally for - use the OES_Draw_Texture extension available on the iPhone and save yourself a load of heartache while picking up a significant speed boost. 顺便说一句 ,如果你只关心2D屏幕对齐的四边形 - 这是精灵通常用于 - 使用iPhone上提供的OES_Draw_Texture扩展,并在获得显着的速度提升时节省一大堆心痛。

int rect[4] = {0, 0, 64, 64}; 
glBindTexture(GL_TEXTURE_2D, texMario); 
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect); 
glDrawTexiOES(playerX, playerY, spriteZ, width, height); 

The rect defines the coordinates of the texture you're going to snip out (in pixels, so this would be a 64x64 sprite) and then the actual call to glDrawTexiOES plops it right into the screen view with its lower-left corner on playerX and playerY. rect定义了你要剪出的纹理的坐标(以像素为单位,所以这将是一个64x64精灵)然后实际调用glDrawTexiOES将其直接放到屏幕视图中,其左下角放在playerX上playerY。

Goodness, even I get the feeling of "tl;dr" here. 天哪,即使我在这里感受到“tl; dr”的感觉。 I apologize for that. 我为此道歉。

The reason is in the rendering pipeline at the lowest level it is all triangles. 原因是在最低级别的渲染管道中它是所有三角形。 More complicated shapes like polygons and the like are transformed into a collection of triangles through a process called tessellation. 诸如多边形等更复杂的形状通过称为曲面细分的过程被转换成三角形的集合。

So if you want to model your complicated Mario character the trick is actually to make him into a collection of triangles, not a single one. 因此,如果你想对复杂的马里奥角色进行建模,那么诀窍就是让他成为三角形的集合,而不是一个三角形。

I see in another answer you mentioned transparent pixels. 我在另一个答案中看到你提到透明像素。 I have not used the newest versions of openGL but the traditional definition a collision is based on intersecting the surface and the texture, even a transparent one, was not taken into account. 我没有使用最新版本的openGL,但传统的定义是碰撞是基于表面和纹理的交叉,即使是透明的,也没有考虑到。

EDIT: 编辑:

A quick google turned up a solution using a GL_TRIANGLE_STRIP off of iDevGames.com The Url is http://www.idevgames.com/forum/showpost.php?p=143983&postcount=6 快速谷歌使用了iDevGames.com的GL_TRIANGLE_STRIP找到了解决方案。网址是http://www.idevgames.com/forum/showpost.php?p=143983&postcount=6

Here is the relevant draw method: 这是相关的绘制方法:

- (void)drawView {

    // Replace the implementation of this method to do your own custom drawing

    const GLfloat squareVertices[] = {
        -0.5f, -0.5f,
        0.5f,  -0.5f,
        -0.5f,  0.5f,
        0.5f,   0.5f,
    };

    GLshort genericTexCoords[] = { 0, 1, 1, 1, 0, 0, 1, 0 };

    [EAGLContext setCurrentContext:context];

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glViewport(0, 0, backingWidth, backingHeight);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);
    glMatrixMode(GL_MODELVIEW);
    glRotatef(3.0f, 0.0f, 0.0f, 1.0f);

    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glVertexPointer(2, GL_FLOAT, 0, squareVertices);
    glTexCoordPointer(2, GL_SHORT, 0, genericTexCoords);

    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, sprite);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}

openGL can actually draw polygons, but it's usually safer not to use them, specially in complex shapes. openGL实际上可以绘制多边形,但通常不使用它们更安全,特别是在复杂的形状中。 Polygons can "twist" on themselves and make an invalid shape that can't be correctly rendered. 多边形可以“扭曲”自身并形成无法正确渲染的无效形状。 With triangles, this never happens. 对于三角形,这种情况从未发生 That's why people usually break up complex shapes to triangles. 这就是人们通常将复杂形状分解为三角形的原因。

See http://www.glprogramming.com/red/chapter02.html#name2 for a better, more complete explanation. 有关更好,更完整的说明,请参见http://www.glprogramming.com/red/chapter02.html#name2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM