如何在没有拉伸的情况下在OpenGL(ES)中显示非2次幂纹理作为精灵?

时间:2011-01-21 15:24:32

标签: opengl-es sprite

我想绘制一个任意大小的精灵作为png,说一些完全疯狂的像56宽x 30高。两个维度都不是2的幂。此外,我可能想绘制另一个72宽x 33高的精灵。表明这是因为这里没有'技巧',我需要处理一般情况。

所以我有这个png(透明度),我想把它画成一个绝对没有拉伸,插值等的精灵。我希望它能在屏幕上用像素1:1进行映射。假装这些精灵是像素艺术(它们可能是也可能不是,但它们是为精确的分辨率绘制的。)

我理解精灵绘图 - 两个三角形作为四边形,通过纹理坐标映射渲染我的纹理 - 但是我只能理解它的2的幂。我也不明白如何调整我的'四边形'并设置我的GL矩阵使得我可以使精灵与像精灵一样的像素大小完全相同

我正在使用OpenGL ES,因此使用新扩展来使用非2次幂纹理是不可接受的。

我一次只吸引3-10个精灵,所以我愿意接受有关效率的建议,但我最感兴趣的是“准确”的结果。

1 个答案:

答案 0 :(得分:5)

要获得像素完美的坐标系,您可以按如下方式设置矩阵:

glViewport(0, window_width, 0, window_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, window_width, 0, window_height, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

这确保了OpenGL坐标到像素的1:1映射,并将您的原点放在左下角。

关于你的纹理,如果你不想依赖非幂二扩展,你必须将它填充为2的幂。虽然OpenGL ES规范并没有说它必须是方形的(据我所知),我看到Android上出现奇怪的事情,纹理大小为512 x 128,所以最好坚持 square 两种纹理。

需要注意的是,无论纹理的像素大小是多少,OpenGL中的纹理坐标总是在0和1之间。因此,如果您的精灵宽度为48像素,并且将其填充为64 x 64的纹理,那么它将跨越0到0.75的x坐标:

1 +--------+
  |        |
  |        |
  +-----+  |
  |\_O_/|  |
  |  O  |  |
  | / \ |  |
0 +-----+--+
  0   0.75 1   <- texture coordinates
  0     48 64  <- pixels

因此,您必须为四边形的角设置这些纹理坐标。因为我们有一个像素完美的投影,所以四边形也必须恰好是48像素宽。

总之,要在位置x, y(从左下角开始的像素)中绘制精灵,请执行以下操作:

float texcoord_x = (float)sprite_width / texture_width;
float texcoord_y = (float)sprite_height / texture_height;

glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture_id);

glBegin(GL_QUADS);
// bottom left
glTexCoord2f(0, 0);
glVertex2i(x, y);
// bottom right
glTexCoord2f(texcoord_x, 0);
glVertex2i(x + sprite_width, y);
// top right
glTexCoord2f(texcoord_x, texcoord_y);
glVertex2i(x + sprite_width, y + sprite_height);
// top left
glTexCoord2f(0, texcoord_y);
glVertex2i(x, y + sprite_height);
glEnd();

我知道OpenGL ES没有glVertex2i等等,所以你必须将这些坐标放入缓冲区。并且它不允许四边形,因此您必须将其拆分为三角形。但这是基本的想法。