在 OpenGL ES 中将不规则形状或其他多边形(卡通、精灵)映射到三角形
-
27-09-2019 - |
题
我不明白显示映射到 OpenGL 三角形的精灵的概念。
如果OpenGL ES仅绘制三角形和点,如何显示/映射非三角形形状?
为什么映射到三角形的形状不会变形?
解释:
在我看来,将马里奥的精灵映射到三角形会产生扭曲或裁剪的马里奥。在这种情况下,头部会被压扁或看不见。
解决方案
如果我理解正确的担忧:您只需划分方成两个三角形,并使用纹理坐标相应地划分质感起来。如果你做对了,你在屏幕上绘制1质地:1,就好像它是一个精灵。 (当然也有旋转和伸展和诸如此类的东西的选项。)
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
事实证明,你不会很你期待的方式得到一个压扁的精灵。我想你想象绘制三角形0-3-2从我上面的图片,比方说,用显而易见的方式映射,并获得顶部扫描无限挤压到一个点(0点)?但实际上这不会发生,因为只有一个纹理坐标点0,所以(如果点2和3适当映射),你永远只能得到精灵的切除部分。
(这就是说,你可以在同一texcoord分配到两分,不过,还是让纹理交叉网本身,搞错了这样 - 很多方面仍然有余地弄得一团糟,不要担心。 )
这是在OpenGL的编程指南解释说,虽然这是一年又一年,因为我学会了这东西,所以我不知道它是如何有帮助的,如果你遇到了困难:的 http://glprogramming.com/red/chapter09.html
其他提示
很简单,质感也不会失真,因为你只能捡三个纹理坐标 - 每个顶点之一。你将不得不使用两个三角形如上文所概述,以及“剪辑”纹理的不同部分。
原谅我糟糕使用ASCII艺术在这里,在这篇文章的其余部分:
Polygon Texture ADB ACD
A-----C | x-----x | x | x-----x
|\ | | | ___ | | | | ___ |
| \ | | |<o.o>| | |<o | .o>|
| \ | | | ### | | | ## | # |
| \ | | | -|- | | | -|- | |
| \| | | / \ | | | / \ | |
B-----D | x-----x | x-----x | x
您会想办法让两个三角形 - 亚行和ACD。点A映射到左上方的纹理,B到左下,C到右上方,和d到右下角。如果只图一个三角形或其他的,你只能得到精灵的一半(或纹理,为更复杂的形状)。这同样适用于更大或更复杂的多边形。纹理可以是一个单一的统一件,但每个顶点的纹理坐标具有切片它以相同的方式作为几何本身。
更复杂的例子,六边形:
a b
___
/ \
f / . \ c
\ g /
\___/
e d
如果您添加的“G”的中间点和切片它分成了6个三角形(ABG,BCG,CDG等),你必须确保任何纹理您所使用的切片,协调,明智的比赛。这不要紧,如果你仅仅使用GL_TRIANGLES
,因为它是最容易见好就收纹理在它的六边形,但一旦你开始画条或风扇可以翻转,歪斜,或重复的,如果你不保持密切跟踪什么顶点的是映射到纹理的哪一部分,由于描绘顺序。
顺便说一句,如果你只是关注的2D画面对齐的四边形 - 这就是精灵通常是 - 使用的 OES_Draw_Texture iPhone上可用,并保存自己而拿起一个显著速度升压心痛的负荷。
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);
在rect
定义你要剪断出来的纹理坐标(以像素为单位,所以这将是一个64×64的精灵),然后glDrawTexiOES
实际调用扑通一声它的权利与它的左下角屏幕视图上PlayerX的和playerY。
天哪,甚至我得到的感觉“TL;博士”在这里。我该道歉。
原因是在最底层的渲染管线中都是三角形。更复杂的形状(如多边形等)通过称为曲面细分的过程转换为三角形的集合。
因此,如果你想对复杂的马里奥角色进行建模,诀窍实际上是将他制作成三角形的集合,而不是单个三角形。
我在另一个答案中看到您提到了透明像素。我没有使用最新版本的 openGL,但碰撞的传统定义是基于表面和纹理的相交,即使是透明的,也没有被考虑在内。
编辑:
快速谷歌找到了一个使用 iDevGames.com 上的 GL_TRIANGLE_STRIP 的解决方案,网址是 http://www.idevgames.com/forum/showpost.php?p=143983&postcount=6
这是相关的绘制方法:
- (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的其实可以绘制多边形,但它通常是安全的不使用它们,特别是在复杂的形状。多边形可以对自己的“扭曲”,并不能正确地渲染的无效形状。随着三角形,这永远不会发生。这就是为什么人们通常分手复杂形状的三角形。
请参阅 http://www.glprogramming.com/red/chapter02.html# NAME2 以更好,更完整的解释。