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

Nek*_*ios 3 opengl-es sprite

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

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

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

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

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

Tho*_*mas 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();
Run Code Online (Sandbox Code Playgroud)

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

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

需要注意的是,无论纹理的像素大小是多少,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
Run Code Online (Sandbox Code Playgroud)

因此,您必须为四边形的角设置这些纹理坐标.因为我们有一个像素完美的投影,四边形也必须正好是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();
Run Code Online (Sandbox Code Playgroud)

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