在可执行文件中嵌入 PNG(或带 alpha 通道的位图)
Embed PNG (Or Bitmap with alpha channel) in executable
TL;DR: 我想创建一个嵌入了图像资源(带有 alpha 通道)的独立应用程序。 modern/standard 执行此操作并提取数据的方法是什么?
我目前正在用 C++ 编写一个使用 OpenGL 作为图形引擎的应用程序(我选择它是因为与 Vulkan 相比开发时间更快,尽管我也很想学习 Vulkan)并且在这个应用程序中我使用用于呈现我的文本的签名距离字段。这需要一个带有 alpha 通道的 Font Atlas 来绘制字符。
我希望能够在可执行文件中嵌入此 Font Atlas(目前它是一个 .PNG 文件)。还有其他图像资源,但我提到这个场景是为了说明为什么我真的需要 alpha 通道。
我使用 Win32 API 执行以下操作:
获取当前模块。
HMODULE getCurrentModule()
{
HMODULE hModule = NULL;
GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)getCurrentModule,
&hModule);
return hModule;
}
为着色器嵌入文本文件。
std::string loadShaderFromResource(int shaderID)
{
// Load resource from executable.
HRSRC shaderResource = FindResource(getCurrentModule(), MAKEINTRESOURCE(shaderID), MAKEINTRESOURCE(TEXTFILE));
HGLOBAL resourceData = LoadResource(getCurrentModule(), shaderResource);
DWORD resourceSize = SizeofResource(getCurrentModule(), shaderResource);
char* resourceFinal = (char*)LockResource(resourceData);
std::string shaderSource;
shaderSource.assign(resourceFinal, resourceSize);
return shaderSource;
}
我的 resource.h 文件。
有点乱,但我把它包括在内是为了提供尽可能多的信息。
/*=======================================================================================================================================*/
/* Setup by Visual Studio. */
/*=======================================================================================================================================*/
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 116
#define _APS_NEXT_COMMAND_VALUE 40003
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
/*=======================================================================================================================================*/
/* Resources. */
/*=======================================================================================================================================*/
//-------------------------------------------------------------------------------------------------
// Resource Types
#define TEXTFILE 255
#define PNG 254
//-------------------------------------------------------------------------------------------------
// Shaders
#define BASIC_SHADER 253
#define STATIC_SHADER 252
#define TEXTURE_SHADER 251
//-------------------------------------------------------------------------------------------------
// ImGui images.
#define COMPONENT_PNG 250
#define DRAW_CIRCUIT_BUCKETS 249
#define DRAW_MCC_PNG 248
//-------------------------------------------------------------------------------------------------
// OpenGL Textures.
#define CIRCUIT_TREE_PNG 247
//-------------------------------------------------------------------------------------------------
// OpenGL Fonts.
#define ARIAL_SDF_FNT 246
#define ARIAL_SDF_PNG 245
#define ARIAL_SDF_BMP 244
#define ARIAL_SDF_MIN_FNT 243
#define ARIAL_SDF_MIN_PNG 242
//-------------------------------------------------------------------------------------------------
// Application icon.
#define IDI_ICON1 116 // Exe icon.
#define ICON_BMP 115 // GLFW icon.
#define PANDA 114
//-------------------------------------------------------------------------------------------------
/*=======================================================================================================================================*/
/* Includes. */
/*=======================================================================================================================================*/
// Windows api for the exe.
#include <Windows.h>
#include <string>
/*=======================================================================================================================================*/
/* Data. */
/*=======================================================================================================================================*/
// Struct that stores the bitmap data.
struct Bitmap {
void* pixelData;
int width = 0;
int height = 0;
};
/*=======================================================================================================================================*/
/* Functions. */
/*=======================================================================================================================================*/
// Load the current module.
HMODULE getCurrentModule();
// Load shader from resource.
std::string loadShaderFromResource(int shaderID);
// Loading bitmaps.
Bitmap loadBitmapFromResource(int bitmapID);
unsigned int loadBitmapToGL(Bitmap bitmap);
/*=======================================================================================================================================*/
/* EOF. */
/*=======================================================================================================================================*/
我的 resource.rc 文件。
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h[=13=]"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"[=13=]"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"[=13=]"
END
#endif // APSTUDIO_INVOKED
/*=======================================================================================================================================*/
/* Resources. */
/*=======================================================================================================================================*/
//-------------------------------------------------------------------------------------------------
// Resource ID Resource Type Resource Path
//-------------------------------------------------------------------------------------------------
// Application icon.
IDI_ICON1 ICON "Icons\circuitIcon128.ico"
ICON_BMP BITMAP "Icons\circuitIcon.bmp"
PANDA BITMAP "Icons\panda.bmp"
//-------------------------------------------------------------------------------------------------
// Shaders.
BASIC_SHADER TEXTFILE "Shaders\basicShader.shader"
STATIC_SHADER TEXTFILE "Shaders\staticShader.shader"
TEXTURE_SHADER TEXTFILE "Shaders\textureShader.shader"
//-------------------------------------------------------------------------------------------------
// ImGui images.
COMPONENT_PNG PNG "Icons\component.png"
DRAW_CIRCUIT_BUCKETS_PNG PNG "Icons\Draw_Circuit_Buckets.png"
DRAW_MCC_PNG PNG "Icons\Draw_MCC.png"
//-------------------------------------------------------------------------------------------------
// OpenGL Textures.
CIRCUIT_TREE_PNG PNG "Textures\circuitTree.png"
//-------------------------------------------------------------------------------------------------
// OpenGL Fonts.
ARIAL_SDF_FNT TEXTFILE "Fonts\Arial_SDF.fnt"
ARIAL_SDF_PNG PNG "Fonts\Arial_SDF_PNG.png"
ARIAL_SDF_BMP BITMAP "Fonts\Arial_SDF_BMP_32.bmp"
ARIAL_SDF_MIN_FNT TEXTFILE "Fonts\Arial_SDF_Min.fnt"
ARIAL_SDF_MIN_PNG PNG "Fonts\Arial_SDF_Min.png"
//-------------------------------------------------------------------------------------------------
#endif // English (United States) resources
//=================================================================================================
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
/*=======================================================================================================================================*/
/* EOF. */
/*=======================================================================================================================================*/
我注意到大多数关于 Win32 API 的论坛和此类问题都非常非常古老。现在还在用吗?有更现代的方法吗?我看到有人在用 CMake。
编辑 1
我尝试按照@Barmak 的建议添加以下内容并进行一些编辑:
HBITMAP loadImageFromResource(int resourceID)
{
HBITMAP hbitmap = NULL;
ULONG_PTR token;
Gdiplus::GdiplusStartupInput tmp;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
if (auto hres = FindResource(getCurrentModule(), MAKEINTRESOURCE(resourceID), RT_RCDATA))
if (auto size = SizeofResource(getCurrentModule(), hres))
if (auto data = LockResource(LoadResource(getCurrentModule(), hres)))
if (auto stream = SHCreateMemStream((BYTE*)data, size))
{
Gdiplus::Bitmap bmp(stream);
stream->Release();
bmp.GetHBITMAP(Gdiplus::Color::Transparent, &hbitmap);
}
Gdiplus::GdiplusShutdown(token);
return hbitmap;
}
但是,在调试模式下查看 hbitmap
时显示 0xffffffffa00513d7 {unused=???}
并且不起作用。
resource.h:
#define ICON_PNG 240 // GLFW icon.
resource.rc:
ICON_PNG RCDATA "Icons\circuitImage.png"
编辑 2
我犯了一个简单的错误。我将这些行添加到函数中:
BITMAP bitmap;
GetObject(hbitmap, sizeof(BITMAP), &bitmap);
现在它通过返回 BITMAP 而不是 HBITMAP 来工作。然而,它是颠倒的,并且在与 glfwSetWindowIcon()
一起使用时,一些颜色似乎不正确。它在其他地方完美运行!
BITMAP loadImageFromResource(int resourceID)
{
HBITMAP hbitmap = NULL;
ULONG_PTR token;
Gdiplus::GdiplusStartupInput tmp;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
if (auto hres = FindResource(getCurrentModule(), MAKEINTRESOURCE(resourceID), RT_RCDATA))
if (auto size = SizeofResource(getCurrentModule(), hres))
if (auto data = LockResource(LoadResource(getCurrentModule(), hres)))
if (auto stream = SHCreateMemStream((BYTE*)data, size))
{
Gdiplus::Bitmap bmp(stream);
stream->Release();
bmp.GetHBITMAP(Gdiplus::Color::Transparent, &hbitmap);
}
Gdiplus::GdiplusShutdown(token);
BITMAP bitmap;
GetObject(hbitmap, sizeof(BITMAP), &bitmap);
return bitmap;
}
首先,通过将这些行添加到以下内容来存储 .PNG 文件:
resource.h
#define ICON_PNG 240 // GLFW icon.
resource.rc
ICON_PNG RCDATA "Icons\circuitImage.png"
然后像这样将 .PNG 作为位图加载:
BITMAP loadImageFromResource(int resourceID)
{
HBITMAP hbitmap = NULL;
ULONG_PTR token;
Gdiplus::GdiplusStartupInput tmp;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
if (auto hres = FindResource(getCurrentModule(), MAKEINTRESOURCE(resourceID), RT_RCDATA))
if (auto size = SizeofResource(getCurrentModule(), hres))
if (auto data = LockResource(LoadResource(getCurrentModule(), hres)))
if (auto stream = SHCreateMemStream((BYTE*)data, size))
{
Gdiplus::Bitmap bmp(stream);
stream->Release();
bmp.GetHBITMAP(Gdiplus::Color::Transparent, &hbitmap);
}
Gdiplus::GdiplusShutdown(token);
BITMAP bitmap;
if(!hbitmap) return NULL;
GetObject(hbitmap, sizeof(BITMAP), &bitmap);
return bitmap;
}
这样称呼:
BITMAP image = loadImageFromResource(ICON_PNG);
编辑 1
我使用这个函数将位图加载到 OpenGL 中:
unsigned int loadBitmapToGL(BITMAP bitmap)
{
unsigned int textureID = 0;
glCreateTextures(GL_TEXTURE_2D, 1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap.bmWidth, bitmap.bmHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)bitmap.bmBits);
return textureID;
}
还按照 Barmak 的建议添加了 if(!hbitmap) return NULL;
。
TL;DR: 我想创建一个嵌入了图像资源(带有 alpha 通道)的独立应用程序。 modern/standard 执行此操作并提取数据的方法是什么?
我目前正在用 C++ 编写一个使用 OpenGL 作为图形引擎的应用程序(我选择它是因为与 Vulkan 相比开发时间更快,尽管我也很想学习 Vulkan)并且在这个应用程序中我使用用于呈现我的文本的签名距离字段。这需要一个带有 alpha 通道的 Font Atlas 来绘制字符。
我希望能够在可执行文件中嵌入此 Font Atlas(目前它是一个 .PNG 文件)。还有其他图像资源,但我提到这个场景是为了说明为什么我真的需要 alpha 通道。
我使用 Win32 API 执行以下操作:
获取当前模块。
HMODULE getCurrentModule()
{
HMODULE hModule = NULL;
GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)getCurrentModule,
&hModule);
return hModule;
}
为着色器嵌入文本文件。
std::string loadShaderFromResource(int shaderID)
{
// Load resource from executable.
HRSRC shaderResource = FindResource(getCurrentModule(), MAKEINTRESOURCE(shaderID), MAKEINTRESOURCE(TEXTFILE));
HGLOBAL resourceData = LoadResource(getCurrentModule(), shaderResource);
DWORD resourceSize = SizeofResource(getCurrentModule(), shaderResource);
char* resourceFinal = (char*)LockResource(resourceData);
std::string shaderSource;
shaderSource.assign(resourceFinal, resourceSize);
return shaderSource;
}
我的 resource.h 文件。
有点乱,但我把它包括在内是为了提供尽可能多的信息。
/*=======================================================================================================================================*/
/* Setup by Visual Studio. */
/*=======================================================================================================================================*/
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 116
#define _APS_NEXT_COMMAND_VALUE 40003
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
/*=======================================================================================================================================*/
/* Resources. */
/*=======================================================================================================================================*/
//-------------------------------------------------------------------------------------------------
// Resource Types
#define TEXTFILE 255
#define PNG 254
//-------------------------------------------------------------------------------------------------
// Shaders
#define BASIC_SHADER 253
#define STATIC_SHADER 252
#define TEXTURE_SHADER 251
//-------------------------------------------------------------------------------------------------
// ImGui images.
#define COMPONENT_PNG 250
#define DRAW_CIRCUIT_BUCKETS 249
#define DRAW_MCC_PNG 248
//-------------------------------------------------------------------------------------------------
// OpenGL Textures.
#define CIRCUIT_TREE_PNG 247
//-------------------------------------------------------------------------------------------------
// OpenGL Fonts.
#define ARIAL_SDF_FNT 246
#define ARIAL_SDF_PNG 245
#define ARIAL_SDF_BMP 244
#define ARIAL_SDF_MIN_FNT 243
#define ARIAL_SDF_MIN_PNG 242
//-------------------------------------------------------------------------------------------------
// Application icon.
#define IDI_ICON1 116 // Exe icon.
#define ICON_BMP 115 // GLFW icon.
#define PANDA 114
//-------------------------------------------------------------------------------------------------
/*=======================================================================================================================================*/
/* Includes. */
/*=======================================================================================================================================*/
// Windows api for the exe.
#include <Windows.h>
#include <string>
/*=======================================================================================================================================*/
/* Data. */
/*=======================================================================================================================================*/
// Struct that stores the bitmap data.
struct Bitmap {
void* pixelData;
int width = 0;
int height = 0;
};
/*=======================================================================================================================================*/
/* Functions. */
/*=======================================================================================================================================*/
// Load the current module.
HMODULE getCurrentModule();
// Load shader from resource.
std::string loadShaderFromResource(int shaderID);
// Loading bitmaps.
Bitmap loadBitmapFromResource(int bitmapID);
unsigned int loadBitmapToGL(Bitmap bitmap);
/*=======================================================================================================================================*/
/* EOF. */
/*=======================================================================================================================================*/
我的 resource.rc 文件。
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (United States) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h[=13=]"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"[=13=]"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"[=13=]"
END
#endif // APSTUDIO_INVOKED
/*=======================================================================================================================================*/
/* Resources. */
/*=======================================================================================================================================*/
//-------------------------------------------------------------------------------------------------
// Resource ID Resource Type Resource Path
//-------------------------------------------------------------------------------------------------
// Application icon.
IDI_ICON1 ICON "Icons\circuitIcon128.ico"
ICON_BMP BITMAP "Icons\circuitIcon.bmp"
PANDA BITMAP "Icons\panda.bmp"
//-------------------------------------------------------------------------------------------------
// Shaders.
BASIC_SHADER TEXTFILE "Shaders\basicShader.shader"
STATIC_SHADER TEXTFILE "Shaders\staticShader.shader"
TEXTURE_SHADER TEXTFILE "Shaders\textureShader.shader"
//-------------------------------------------------------------------------------------------------
// ImGui images.
COMPONENT_PNG PNG "Icons\component.png"
DRAW_CIRCUIT_BUCKETS_PNG PNG "Icons\Draw_Circuit_Buckets.png"
DRAW_MCC_PNG PNG "Icons\Draw_MCC.png"
//-------------------------------------------------------------------------------------------------
// OpenGL Textures.
CIRCUIT_TREE_PNG PNG "Textures\circuitTree.png"
//-------------------------------------------------------------------------------------------------
// OpenGL Fonts.
ARIAL_SDF_FNT TEXTFILE "Fonts\Arial_SDF.fnt"
ARIAL_SDF_PNG PNG "Fonts\Arial_SDF_PNG.png"
ARIAL_SDF_BMP BITMAP "Fonts\Arial_SDF_BMP_32.bmp"
ARIAL_SDF_MIN_FNT TEXTFILE "Fonts\Arial_SDF_Min.fnt"
ARIAL_SDF_MIN_PNG PNG "Fonts\Arial_SDF_Min.png"
//-------------------------------------------------------------------------------------------------
#endif // English (United States) resources
//=================================================================================================
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
/*=======================================================================================================================================*/
/* EOF. */
/*=======================================================================================================================================*/
我注意到大多数关于 Win32 API 的论坛和此类问题都非常非常古老。现在还在用吗?有更现代的方法吗?我看到有人在用 CMake。
编辑 1
我尝试按照@Barmak 的建议添加以下内容并进行一些编辑:
HBITMAP loadImageFromResource(int resourceID)
{
HBITMAP hbitmap = NULL;
ULONG_PTR token;
Gdiplus::GdiplusStartupInput tmp;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
if (auto hres = FindResource(getCurrentModule(), MAKEINTRESOURCE(resourceID), RT_RCDATA))
if (auto size = SizeofResource(getCurrentModule(), hres))
if (auto data = LockResource(LoadResource(getCurrentModule(), hres)))
if (auto stream = SHCreateMemStream((BYTE*)data, size))
{
Gdiplus::Bitmap bmp(stream);
stream->Release();
bmp.GetHBITMAP(Gdiplus::Color::Transparent, &hbitmap);
}
Gdiplus::GdiplusShutdown(token);
return hbitmap;
}
但是,在调试模式下查看 hbitmap
时显示 0xffffffffa00513d7 {unused=???}
并且不起作用。
resource.h:
#define ICON_PNG 240 // GLFW icon.
resource.rc:
ICON_PNG RCDATA "Icons\circuitImage.png"
编辑 2
我犯了一个简单的错误。我将这些行添加到函数中:
BITMAP bitmap;
GetObject(hbitmap, sizeof(BITMAP), &bitmap);
现在它通过返回 BITMAP 而不是 HBITMAP 来工作。然而,它是颠倒的,并且在与 glfwSetWindowIcon()
一起使用时,一些颜色似乎不正确。它在其他地方完美运行!
BITMAP loadImageFromResource(int resourceID)
{
HBITMAP hbitmap = NULL;
ULONG_PTR token;
Gdiplus::GdiplusStartupInput tmp;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
if (auto hres = FindResource(getCurrentModule(), MAKEINTRESOURCE(resourceID), RT_RCDATA))
if (auto size = SizeofResource(getCurrentModule(), hres))
if (auto data = LockResource(LoadResource(getCurrentModule(), hres)))
if (auto stream = SHCreateMemStream((BYTE*)data, size))
{
Gdiplus::Bitmap bmp(stream);
stream->Release();
bmp.GetHBITMAP(Gdiplus::Color::Transparent, &hbitmap);
}
Gdiplus::GdiplusShutdown(token);
BITMAP bitmap;
GetObject(hbitmap, sizeof(BITMAP), &bitmap);
return bitmap;
}
首先,通过将这些行添加到以下内容来存储 .PNG 文件:
resource.h
#define ICON_PNG 240 // GLFW icon.
resource.rc
ICON_PNG RCDATA "Icons\circuitImage.png"
然后像这样将 .PNG 作为位图加载:
BITMAP loadImageFromResource(int resourceID)
{
HBITMAP hbitmap = NULL;
ULONG_PTR token;
Gdiplus::GdiplusStartupInput tmp;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
if (auto hres = FindResource(getCurrentModule(), MAKEINTRESOURCE(resourceID), RT_RCDATA))
if (auto size = SizeofResource(getCurrentModule(), hres))
if (auto data = LockResource(LoadResource(getCurrentModule(), hres)))
if (auto stream = SHCreateMemStream((BYTE*)data, size))
{
Gdiplus::Bitmap bmp(stream);
stream->Release();
bmp.GetHBITMAP(Gdiplus::Color::Transparent, &hbitmap);
}
Gdiplus::GdiplusShutdown(token);
BITMAP bitmap;
if(!hbitmap) return NULL;
GetObject(hbitmap, sizeof(BITMAP), &bitmap);
return bitmap;
}
这样称呼:
BITMAP image = loadImageFromResource(ICON_PNG);
编辑 1
我使用这个函数将位图加载到 OpenGL 中:
unsigned int loadBitmapToGL(BITMAP bitmap)
{
unsigned int textureID = 0;
glCreateTextures(GL_TEXTURE_2D, 1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap.bmWidth, bitmap.bmHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (const void*)bitmap.bmBits);
return textureID;
}
还按照 Barmak 的建议添加了 if(!hbitmap) return NULL;
。