首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将GL_UNSIGNED_SHORT_4_4_4_4用于纹理

将GL_UNSIGNED_SHORT_4_4_4_4用于纹理
EN

Stack Overflow用户
提问于 2013-05-15 05:10:04
回答 2查看 1.4K关注 0票数 0

我有一种将纹理加载到OpenGL中的方法:

代码语言:javascript
运行
复制
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建议我尝试使用以下代码那样,编辑

代码语言:javascript
运行
复制
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位。

代码语言:javascript
运行
复制
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上没有看到性能的提高。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-05-15 08:26:27

最好的办法可能是使用像魔鬼这样的映像库来处理这类事情。

但是,如果您想转换从libpbg获得的图像数据,您可以执行类似于下面代码的操作。

记住,当你这样做的时候,你用大小来换取速度。

代码语言:javascript
运行
复制
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;
}
票数 1
EN

Stack Overflow用户

发布于 2013-05-15 05:56:33

但显然这还不够

您更改的令牌告诉OpenGL传递给它的数组中数据的格式。所以你也得调整一下。但是,OpenGL可以将它转换成它想要的任何内部格式,因为您并没有强迫它转换成特定的格式。这就是内部格式参数的作用(它在外部数据类型上独立工作)。因此,如果要在内部获得16位分辨率,则必须将内部格式参数更改为GL_RGBA4。数据可以保持为每像素格式8位。所以在你的情况下

代码语言:javascript
运行
复制
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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16557317

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档