如何在 win32 可执行文件中嵌入任何 *.jpg 图像并在 运行 时间使用它
How to embed any *.jpg image inside win32 executable and use it at run time
我正在用纯 OpenGL 和 FREEGLUT 做一个名为 Space Voyager 的项目。问题是在 运行 期间,当程序调用一个函数来加载所有图像时,播放器必须在加载屏幕上等待大约 2 分钟!!!!有些图像像 16 MB 的文件,否则平均为 1 MB。总共有20张图片。我需要在开始关卡之前加载所有图像。
现在我正在使用 SOIL 在我的游戏中加载图像。 SOIL 具有从内存中加载图像的功能 SOIL_load_OGL_texture_load_from_memory( unsigned char *image_in_RAM ,...).
我的解决办法是把所有的图片都嵌入到游戏的*.exe文件中,在运行的时候使用,这样可以节省游戏中加载所有图片的时间。
我对如何将 jpg 图像准确地嵌入可执行文件和
感到非常困惑
在 运行 时间将其用作 unsigned char* imagePointer ??????
My solution is to embed all the images in *.exe file of the game and use it at run time so as to save the time to load all the images in game.
你认为这会怎样?存储设备上的数据带有什么标签并不重要。计算机系统的努力是不变的。将资源放在计算机的单独文件中都没关系,这没有任何区别。
Some of the images are like 16 MB files otherwise 1 MB in average. There are like 20 images in all. I need to load all the images before staring the level.
这不是很多数据。 20 张图片,平均 1MiB,也就是平均 20MiB。即使是旋转生锈的慢速 HDD 磁盘也可以轻松提供 10MiB/s 的速度。如今,对于便宜的 HDD,更常见的数字是 50MiB 到 80MiB/s。无论你的瓶颈在哪里,都不是 I/O.
另外请记住,如果您将文件 RAW 嵌入到可执行文件中,您将迫使系统通过 I/O 推送更多数据;将图像压缩到可执行文件中仍然需要您解压缩。考虑到大多数时候你是 I/O 绑定而不是 CPU 存储压缩图像是可取的。
更新
你的问题是这样的:
您要求土壤将每个图像重新缩放到下一个更大的尺寸,即 2 的幂。在 OpenGL-2 之前必须这样做,因为 OpenGL-1 只接受 2 的幂大小图像的纹理。自从 OpenGL-2 问世(现在你很难找到不支持 OpenGL-2 的 GPU),这个限制就被解除了。
另一个耗时的操作是生成 mipmaps (SOIL_FLAG_MIPMAPS),因为这需要为每个图像生成整个图像金字塔。现在 mipmapping 是您通常想要拥有的东西。如果您有 >=OpenGL-3 的上下文,您可以使用 OpenGL 内置的 mipmap 生成器。您还要求 SOIL 为您生成纹理 ID,但您也自己生成 ID。使用其中一个,但不要同时使用。
这会导致对您的代码进行以下建议的更改:
while( GL_NO_ERROR != glGetError() ); // flush OpenGL errors;
GLint gl_version;
glGetIntegerv(GL_MAJOR_VERSION, &gl_version);
if( GL_NO_ERROR != glGetError() ) {
// GL_MAJOR_VERSION enum supported only since OpenGL-3
gl_version = 1;
while( GL_NO_ERROR != glGetError() ); // flush OpenGL errors;
}
bool const gl3_or_later = 3 <= gl_version;
tex_id = SOIL_load_OGL_texture(
fileNameConstant,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
gl3_or_later ? 0 : SOIL_FLAG_MIPMAPS );
if( gl3_or_later ) {
glBindTexture(GL_TEXTURE_2D, tex_id);
glGenerateTextureMipmap(GL_TEXTURE_2D);
glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_MAX_LEVEL,
1000);
}
我正在用纯 OpenGL 和 FREEGLUT 做一个名为 Space Voyager 的项目。问题是在 运行 期间,当程序调用一个函数来加载所有图像时,播放器必须在加载屏幕上等待大约 2 分钟!!!!有些图像像 16 MB 的文件,否则平均为 1 MB。总共有20张图片。我需要在开始关卡之前加载所有图像。
现在我正在使用 SOIL 在我的游戏中加载图像。 SOIL 具有从内存中加载图像的功能 SOIL_load_OGL_texture_load_from_memory( unsigned char *image_in_RAM ,...).
我的解决办法是把所有的图片都嵌入到游戏的*.exe文件中,在运行的时候使用,这样可以节省游戏中加载所有图片的时间。
我对如何将 jpg 图像准确地嵌入可执行文件和
感到非常困惑
在 运行 时间将其用作 unsigned char* imagePointer ??????
My solution is to embed all the images in *.exe file of the game and use it at run time so as to save the time to load all the images in game.
你认为这会怎样?存储设备上的数据带有什么标签并不重要。计算机系统的努力是不变的。将资源放在计算机的单独文件中都没关系,这没有任何区别。
Some of the images are like 16 MB files otherwise 1 MB in average. There are like 20 images in all. I need to load all the images before staring the level.
这不是很多数据。 20 张图片,平均 1MiB,也就是平均 20MiB。即使是旋转生锈的慢速 HDD 磁盘也可以轻松提供 10MiB/s 的速度。如今,对于便宜的 HDD,更常见的数字是 50MiB 到 80MiB/s。无论你的瓶颈在哪里,都不是 I/O.
另外请记住,如果您将文件 RAW 嵌入到可执行文件中,您将迫使系统通过 I/O 推送更多数据;将图像压缩到可执行文件中仍然需要您解压缩。考虑到大多数时候你是 I/O 绑定而不是 CPU 存储压缩图像是可取的。
更新
你的问题是这样的:
您要求土壤将每个图像重新缩放到下一个更大的尺寸,即 2 的幂。在 OpenGL-2 之前必须这样做,因为 OpenGL-1 只接受 2 的幂大小图像的纹理。自从 OpenGL-2 问世(现在你很难找到不支持 OpenGL-2 的 GPU),这个限制就被解除了。
另一个耗时的操作是生成 mipmaps (SOIL_FLAG_MIPMAPS),因为这需要为每个图像生成整个图像金字塔。现在 mipmapping 是您通常想要拥有的东西。如果您有 >=OpenGL-3 的上下文,您可以使用 OpenGL 内置的 mipmap 生成器。您还要求 SOIL 为您生成纹理 ID,但您也自己生成 ID。使用其中一个,但不要同时使用。
这会导致对您的代码进行以下建议的更改:
while( GL_NO_ERROR != glGetError() ); // flush OpenGL errors;
GLint gl_version;
glGetIntegerv(GL_MAJOR_VERSION, &gl_version);
if( GL_NO_ERROR != glGetError() ) {
// GL_MAJOR_VERSION enum supported only since OpenGL-3
gl_version = 1;
while( GL_NO_ERROR != glGetError() ); // flush OpenGL errors;
}
bool const gl3_or_later = 3 <= gl_version;
tex_id = SOIL_load_OGL_texture(
fileNameConstant,
SOIL_LOAD_AUTO,
SOIL_CREATE_NEW_ID,
gl3_or_later ? 0 : SOIL_FLAG_MIPMAPS );
if( gl3_or_later ) {
glBindTexture(GL_TEXTURE_2D, tex_id);
glGenerateTextureMipmap(GL_TEXTURE_2D);
glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(
GL_TEXTURE_2D,
GL_TEXTURE_MAX_LEVEL,
1000);
}