【发布时间】:2018-10-15 11:46:00
【问题描述】:
我正在尝试加载已存储为大量无符号字符的图像。更具体地说,由无符号字符组成的结构数组
typedef struct {
unsigned char
r,
g,
b;
}RGB;
图像数据本身从 gimp 导出为一个非常大的 c 源文件,看起来像这样
RGB Image[25000]={
{0,0,0},{0,0,0},{0,0,0},{174,174,174},{175,175,175},{177,177,177},
{180,180,180},{183,183,183},{187,187,187},{192,192,192},{196,196,196},
{202,202,202},{207,207,207},{213,213,213},{239,239,239},
...
}
我知道图像的宽度、高度,并且知道它是 8 位格式的 RGB。我试图将它传递给 glTexImage2D,但它总是呈现全黑。
这样说
unsigned int imageWidth = 960;
unsigned int imageHeight = 540;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imageWidth, imageHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, &Image);
问题不在于我的着色器代码或程序中的其他任何地方,因为如果我从文件加载纹理,一切正常。我只是不知道这些数据是否可以按原样读取,或者我是否必须以某种方式准备它,或者其他任何东西,我是 openGL 的新手。
我的目标是将几个纹理硬编码到应用程序中,这样它们就不能轻易被交换或修改。我正在使用 Gimp 插件将纹理导出到 c 源代码。还有另一个 Gimp 导出插件,它提供了我在 gcc/g++ 编译器上工作的源代码,但是当我尝试从 Visual Studio 编译时,它抱怨字符串太长
编译器限制:字符串长度超过 65535 个字节
不过,它适用于 gcc/g++。在这种情况下,源看起来像这样
static const struct Image{
unsigned int width;
unsigned int height;
unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */
unsigned char pixel_data[960 * 540 * 4 + 1];
} ImageImage = {
960, 540, 4,
"\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000"
"\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000"
"\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000"
"\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377"
"\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000"
"\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000"
"\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000"
"\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377"
...
}
这适用于 gcc/g++,但视觉工作室抱怨。这是一个非常长的文件,所以我并不感到惊讶,但我无法让它工作,这真是太糟糕了。我尝试通过将每个最大限制字符串转换为 std::string 并将每个无符号字符从这些字符串传递到无符号字符向量来解析它,我知道我不应该这样做,但我正在抓住稻草这点
std::vector<unsigned char> _charVec;
std::string tempString = "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000"
"\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000"
"\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000"
"\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377"
"\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000"
...
_charVec.insert(_charVec.end(), tempString.begin(), tempString.end());
无论如何,这并不能解决问题。它会停止编译器错误,但是当我尝试访问存储数据的任何类对象或将容器传递给另一个方法时会导致崩溃。
我没有其他方法可以将我的纹理转换为源代码,并且我绝对不希望将其中的一两个原始数据分发,因此我想在 openGL 中加载这两个纹理源中的一个。只要我使用 Visual Studio 构建,第一种源格式可能就是我需要使用的,因为它无法处理第二种方法中的长字符串,并且尝试从中填充向量或数组似乎更多比需要的额外步骤。由于我对 openGL 的细微差别还不是很熟悉,所以我可能会搞错这一切。任何建议将不胜感激。
【问题讨论】:
-
您的纹理之一是 RGB,另一个是 RGBA。对于这两种情况,
glTexImage2D调用需要不同,glPixelStore设置必须反映结构中的实际对齐/填充。 -
通常有比将大数组转换为源代码更好的方法将大数组转换为应用程序二进制文件。在 gcc 世界中,
objcopy可以从数据创建一个目标文件,在进程中导出变量(C 代码可以通过声明extern具有相同名称的全局变量来使用这些变量)。使用 Microsoft 工具也可以做到这一点,但最简单的方法可能是再次使用objcopy并指定 Microsoft COFF 作为输出格式。 -
我上面提到的方法在这里解释的很好:csl.name/post/embedding-binary-data
-
我会采用将文件读入数组的老方法,并将其传递给
glTexImage2D -
你在哪里设置纹理过滤器?这看起来像是尝试使用非 mipmap-complete 纹理对象的标准错误。
标签: c++ c opengl textures hardcoded