如何在不拉伸的情况下在OpenGL(ES)中将非2幂的纹理显示为精灵? [英] How do I display a non-power-of-2-texture as sprite in OpenGL (ES) with no stretching?

查看:101
本文介绍了如何在不拉伸的情况下在OpenGL(ES)中将非2幂的纹理显示为精灵?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想画一个任意大小的精灵作为png,说些完全疯狂的东西,例如56宽x 30高.在任何一个维度上都不为2的幂.另外,我可能还想绘制另一个宽72 x高33的子画面.指出这一点是因为这里不接受技巧",我需要处理一般情况.

I want to draw an arbitrary size sprite as a png, say something TOTALLY CRAZY like 56 wide x 30 high. Not a power of 2 in either dimension. Also I may want to draw another different sprite that's 72 wide x 33 high. Indicating this because no 'tricks' are acceptable here, I need to handle general case.

所以我有这个png(透明),我想将它绘制为一个没有任何拉伸,插值等的精灵.我希望它以1:1的比例在屏幕上映射像素.假装这些精灵是像素艺术(它们可能是也可能不是,但它们是为精确分辨率绘制的).

So I have this png (with transparency) and I want to draw it as a sprite with absolutely no stretching, interpolation, etc. I want it to map 1:1 with pixels on the screen. Pretend these sprites are pixel art (they may or may not be but they are drawn for the exact resolution).

我了解子画面绘制-将2个三角形作为一个四边形,通过纹理坐标映射将我的纹理渲染为该三角形-但是,我仅以2的次幂来理解它,而且我也不了解如何调整四边形"的大小并进行设置我的GL矩阵,这样我就可以使精灵与我的精灵完全一样的像素大小

I understand sprite drawing - 2 triangles as a quad, rendering my texture to that via texture coordinate mapping - however I only understand it for powers of 2. And I also do not understand how to size my 'quad' and set up my GL matricies such that I can make the sprite be the exact same size in pixels as my sprite

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

I'm using OpenGL ES so using the new extensions to use non-power-of-2 textures is not acceptable.

我一次只绘制3-10个Sprite,因此我对效率有所建议,但我对准确的"外观结果最感兴趣.

I'm only drawing 3-10 sprites at a time so I'm open to suggestions about efficiency but I'm most interested in 'accurate' looking results.

推荐答案

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

To get a pixel-perfect coordinate system, you could set up your matrices as follows:

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映射,并将原点放在左下角.

This ensures a 1:1 mapping of OpenGL coordinates to pixels, and puts your origin in the bottom left corner.

关于纹理,如果您不想依赖非2的幂次扩展,则必须 将其填充为2的幂.即使OpenGL ES规范没有说它也必须是正方形的(据我所知),但我已经看到Android在512 x 128的纹理尺寸上发生了奇怪的事情,因此最好坚持使用 square 具有2的幂次幂.

As to your texture, if you don't want to rely on the non-power-of-two extension, you must pad it to be a power of two. Even though the OpenGL ES spec doesn't say it has to be square as well (as far as I know), I've seen strange things happen on Android with texture sizes like 512 x 128, so it might be best to stick to square power-of-two textures.

要注意的是,无论纹理的像素大小如何,OpenGL中的纹理坐标始终在0到1之间.因此,如果您的精灵为48像素宽,并且将其填充为64 x 64的纹理,则它将跨越0到0.75的x坐标:

The thing to note is that texture coordinates in OpenGL are always between 0 and 1, no matter what the pixel size of your texture is. So if your sprite is 48 pixels wide, and you padded it to a texture of 64 x 64, then it will span the x coordinates from 0 to 0.75:

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

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

So you have to set up these texture coordinates for the corners of your quad. Because we have a pixel-perfect projection, the quad must also be exactly 48 pixels wide.

最后,要在x, y位置绘制精灵(从左下角开始以像素为单位),请执行以下操作:

In conclusion, to draw your sprite at position x, y (in pixels from the bottom left), do something like this:

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等,因此您必须将这些坐标放入缓冲区中.而且它不允许四边形,因此您必须将其分成三角形.但这是基本思想.

I know OpenGL ES doesn't have glVertex2i and so on, so you'll have to put these coordinates into a buffer. And it doesn't allow quads, so you'll have to split it up into triangles. But this is the basic idea.

这篇关于如何在不拉伸的情况下在OpenGL(ES)中将非2幂的纹理显示为精灵?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆