C++ OpenGL位图透明度问题
Posted
技术标签:
【中文标题】C++ OpenGL位图透明度问题【英文标题】:C++ OpenGL Bitmap transparency issues 【发布时间】:2014-12-27 15:13:19 【问题描述】:我从 opengl 纹理开始,一切运行良好。现在我正在尝试加载 bmp 并使用 glEnable(GL_BLEND); 使白色部分透明和 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
这是我的源代码:
float kSpeedForw=0.0f;
GLuint texture[1];
CCamera g_Camera;
GLfloat xrot = 0;
GLfloat yrot = 0;
GLfloat zrot = 0;
bool g_bFullScreen = true;
HWND g_hWnd;
RECT g_rRect;
HDC g_hDC;
HGLRC g_hRC;
HINSTANCE g_hInstance;
float jump = -0.1;
GLfloat LightAmbient[] = 0.5f, 0.5f, 0.5f, 1.0f ;
GLfloat LightDiffuse[] = 1.0f, 1.0f, 1.0f, 1.0f ;
GLfloat LightPosition[] = 0.0f, 0.0f, 2.0f, 1.0f ;
void Init(HWND hWnd)
glEnable(GL_TEXTURE_2D); // Enable Texture Mapping
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); // Setup The Ambient Light
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); // Setup The Diffuse Light
glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); // Position The Light
glEnable(GL_LIGHT1); // Enable Light One
glColor4f(1.0f, 1.0f, 1.0f, 0.5); // Full Brightness. 50% Alpha
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
g_hWnd = hWnd;
GetClientRect(g_hWnd, &g_rRect);
InitializeOpenGL(g_rRect.right, g_rRect.bottom);
g_Camera.PositionCamera(0, 1.5f, 6, 0, 1.5f, 5, 0, 1, 0);
ShowCursor(false);
GLuint LoadTexture(const char * filename)
glEnable(GL_TEXTURE_2D);
GLuint texture;
int width, height;
unsigned char * data;
FILE * file;
file = fopen(filename, "rb");
if (file == NULL) return 0;
if (filename=="Data/weed.bmp")
width = 200;
height = 200;
if (filename == "Data/gun.bmp")
width = 300;
height = 300;
data = (unsigned char *)malloc(width * height * 3);
fread(data, width * height * 3, 1, file);
fclose(file);
for (int i = 0; i < width * height; ++i)
int index = i * 3;
unsigned char B, R;
B = data[index];
R = data[index + 2];
data[index] = R;
data[index + 2] = B;
if (filename == "Data/weed.bmp")
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, GL_RGB, GL_UNSIGNED_BYTE, data);
free(data);
if (filename == "Data/gun.bmp")
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3,width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
return texture;
WPARAM MainLoop() // main function
MSG msg;
Init(g_hWnd);
glClearColor(0, 0, 255, 0);
while (1)
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
else if (LockFrameRate(60))
g_Camera.SetViewByMouse();
kSpeedForw = 0;
if (jump > -0.1)jump-=0.01;
CheckForMovement();
g_Camera.MoveCamera(kSpeedForw, jump);
RenderScene();
DeInit();
return(msg.wParam);
void RenderScene()
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glDisable(GL_BLEND);
glEnable(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(g_Camera.m_vPosition.x, g_Camera.m_vPosition.y, g_Camera.m_vPosition.z,
g_Camera.m_vView.x, g_Camera.m_vView.y, g_Camera.m_vView.z,
g_Camera.m_vUpVector.x, g_Camera.m_vUpVector.y, g_Camera.m_vUpVector.z);
GLuint texture;
texture = LoadTexture("Data/weed.bmp");
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
float i = 0;
glColor3f(1,1,1);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-10 + i / 5, 0, 10 - i / 5);
glTexCoord2f(50.0f, 0.0f);
glVertex3f(-10 + i / 5, 0, -10 + i / 5);
glTexCoord2f(50.0f, 50.0f);
glVertex3f(10 - i / 5, 0, -10 + i / 5);
glTexCoord2f(0.0f, 50.0f);
glVertex3f(10 - i / 5, 0, 10 - i / 5);
glEnd();
////////////////////////////////////////////////////////////HUD
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SMOOTH);
glEnable(GL_BLEND); // Turn Blending On
int vPort[4];
glGetIntegerv(GL_VIEWPORT, vPort);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, vPort[2], 0, vPort[3], -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
GLuint ruka;
ruka = LoadTexture("Data/gun.bmp");
glBindTexture(GL_TEXTURE_2D, ruka);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f);
glVertex2f(0, 0);
glTexCoord2f(1.0f, 0.0f);
glVertex2f(450,0);
glTexCoord2f(1.0f, 1.0f);
glVertex2f(450,450);
glTexCoord2f(0.0f, 1.0f);
glVertex2f(0,450);
glEnd();
SwapBuffers(g_hDC);
该代码可以很好地加载和渲染平台(weed.bmp),它还可以很好地加载和渲染枪。但是 gun.bmp 的很大一部分是白色的。我希望让那部分变得透明。我还希望添加更多 HUD 功能,这些功能也需要部分透明。
我的 gun.bmp 文件:https://drive.google.com/file/d/0BxxlNcAI0eh9cHZGd1ZfMTFwYmM/view?usp=sharing
如果您知道此问题的解决方案,请发布。谢谢
【问题讨论】:
我真的很想知道您是如何期望白色神奇地通过启用GL_BLEND
变得透明的。
我尝试使用 alpha 通道加载 32 位 bmp 并加载为 GL_RGBA,但它立即崩溃了。我不知道我是否在这里遗漏了什么,但如果是,请向我解释一下。我将不胜感激。
你应该为此使用一个实际的图像加载库(或者一个不太容易混淆的文件扩展名)。我的印象是您的“.bmp”文件实际上不是设备独立位图。 DIB 格式有一个复杂的标头,您必须处理,并且您还必须考虑每行对齐 4 字节(这里不是问题,因为 200*3 和 300*3 都可以被 4 整除而没有余数)。
将其发布为带有图像加载库和格式推荐的答案(我应该使用 png,对),我很乐意接受它作为答案。
这不是一个真正的答案。我仍然不知道为什么当您使用 24 位 bmp 时它会起作用。但一般来说,PNG 可能是存储 Alpha 通道的最广泛支持的图像格式(用于编辑软件和加载库)。至于图书馆,我会指出你here。仅在上个月,我就看到了 DevIL、FreeImage 和 SOIL 问题,因此您应该不会太难找到支持。
【参考方案1】:
您将图像加载为 GL_RGB,您希望 GL_RGBA 具有 alpha 通道。 此外,您需要一个 32 位的位图(8 位/通道 × 4 通道 = 32 位)。
【讨论】:
谢谢。实际上,我确实尝试过,但它立即导致崩溃 您必须使用 32 位位图并读取width * height * 4
字节。
是的,我确实使用了 32 位位图。它被加载为 GL_RGBA 并使用 alpha 通道保存。以上是关于C++ OpenGL位图透明度问题的主要内容,如果未能解决你的问题,请参考以下文章
将位图 (bmp) 转换为具有透明度的 png (Windows c++)
Opengl ES 2.0 - glDrawElements(GL_TRIANGLES)的颜色不透明度问题
我要用opengl 显示一张图片,现在已经可以显示出来; 我现在需要把它旋转90,不知道怎么旋转。help~~