我有一种将纹理加载到OpenGL中的方法:
bool AndroidGraphicsManager::setTexture(
UINT& id, UCHAR* image, UINT width, UINT height,
bool wrapURepeat, bool wrapVRepeat, bool useMipmaps)
{
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA,
width, height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, (GLvoid*) image);
int minFilter = GL_LINEAR;
if (useMipmaps) {
glGenerateMipmap(GL_TEXTURE_2D);
minFilter = GL_NEAREST_MIPMAP_NEAREST;
}
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, GL_NEAREST);
int wrap_u = wrapURepeat ?
GL_REPEAT : GL_CLAMP_TO_EDGE;
int wrap_v = wrapVRepeat ?
GL_REPEAT : GL_CLAMP_TO_EDGE;
glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_WRAP_S, wrap_u);
glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_WRAP_T, wrap_v);
glBindTexture(GL_TEXTURE_2D, 0);
return !checkGLError("Loading texture.");
}
这个很好用。我使用libpng加载纹理。这给了我一系列未签名的字符。然后将这个数组传递给我上面指定的方法。图片是32位,所以我假设在UCHAR数组中,每个UCHAR包含一个颜色分量,四个UCHAR组成一个像素。我想尝试使用16位纹理。我将GL_UNSIGNED_BYTE改为GL_UNSIGNED_SHORT_4_4_4_4。但显然这还不够,因为它给了我这样的结果:
我还需要改变什么才能正确显示16位纹理呢?
正如@DatenWolf建议我尝试使用以下代码那样,编辑:
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA4,
width, height, 0, GL_RGBA,
GL_UNSIGNED_SHORT_4_4_4_4, (GLvoid*) image);
我在我的引擎的Linux版本上使用了它,但是结果和之前的android截图完全一样。那么,假设问题是libpng和它生成我的UCHAR数组的方式是安全的吗?
EDIT2所以我终于把32位的纹理压缩成16位了。我所需要的只是通过32位纹理数据进行简单的迭代,并通过几个位移位操作将32位压缩为16位。
void* rgba8888ToRgba4444(void* in, int size) {
int pixelCount = size / 4;
ULONG* input = static_cast<ULONG*>(in);
USHORT* output = new USHORT[pixelCount];
for (int i = 0; i < pixelCount; i++) {
ULONG pixel = input[i];
// Unpack the source data as 8 bit values
UINT r = pixel & 0xff;
UINT g = (pixel >> 8) & 0xff;
UINT b = (pixel >> 16) & 0xff;
UINT a = (pixel >> 24) & 0xff;
// Convert to 4 bit vales
r >>= 4; g >>= 4; b >>= 4; a >>= 4;
output[i] = r << 12 | g << 8 | b << 4 | a;
}
return static_cast<void*>(output);
}
我认为对于移动设备来说,这会带来性能的提高,但不幸的是,我在Galaxy上没有看到性能的提高。
发布于 2013-05-15 08:26:27
最好的办法可能是使用像魔鬼这样的映像库来处理这类事情。
但是,如果您想转换从libpbg获得的图像数据,您可以执行类似于下面代码的操作。
记住,当你这样做的时候,你用大小来换取速度。
struct Color {
unsigned char r:4;
unsigned char g:4;
unsigned char b:4;
unsigned char a:4;
};
float factor = 16 / 255;
Color colors[imgWidth*imgHeight];
for(int i = 0; i < imgWidth*imgHeight; ++i)
{
colors[i].r = image[i*4]*factor;
colors[i].g = image[i*4+1]*factor;
colors[i].b = image[i*4+2]*factor;
colors[i].a = image[i*4+3]*factor;
}
发布于 2013-05-15 05:56:33
但显然这还不够
您更改的令牌告诉OpenGL传递给它的数组中数据的格式。所以你也得调整一下。但是,OpenGL可以将它转换成它想要的任何内部格式,因为您并没有强迫它转换成特定的格式。这就是内部格式参数的作用(它在外部数据类型上独立工作)。因此,如果要在内部获得16位分辨率,则必须将内部格式参数更改为GL_RGBA4
。数据可以保持为每像素格式8位。所以在你的情况下
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA4,
width, height, 0, GL_RGBA,
…, (GLvoid*) image);
类型参数必须与数据的布局匹配。如果最初每像素有8位,那么GL_UNSIGNED_BYTE。但是,如果它是预先打包的RGBA在ushorts咬咬,那么GL_UNSIGNED_SHORT_4_4_4_4
https://stackoverflow.com/questions/16557317
复制相似问题