我有一种将纹理加载到 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 SIII 的性能提升。