我在我的Opengl项目中制作了一个GUI类。目前我正在做的是创建一个平面然后我绑定一个bmp纹理。有没有办法让它的一部分透明?
现在这就是显示的内容(左下角的白/蓝框):http://imgur.com/OpxsBHi
我希望图像只显示蓝色区域。
如果你想看一下,这是我的代码:
// Struct of bitmap file.
struct BitMapFile
{
int sizeX;
int sizeY;
unsigned char *data;
};
// Routine to read a bitmap file.
// Works only for uncompressed bmp files of 24-bit color.
BitMapFile *getBMPData(string filename)
{
BitMapFile *bmp = new BitMapFile;
unsigned int size, offset, headerSize;
// Read input file name.
ifstream infile(filename.c_str(), ios::binary);
// Get the starting point of the image data.
infile.seekg(10);
infile.read((char *) &offset, 4);
// Get the header size of the bitmap.
infile.read((char *) &headerSize,4);
// Get width and height values in the bitmap header.
infile.seekg(18);
infile.read( (char *) &bmp->sizeX, 4);
infile.read( (char *) &bmp->sizeY, 4);
// Allocate buffer for the image.
size = bmp->sizeX * bmp->sizeY * 24;
bmp->data = new unsigned char[size];
// Read bitmap data.
infile.seekg(offset);
infile.read((char *) bmp->data , size);
// Reverse color from bgr to rgb.
int temp;
for (int i = 0; i < size; i += 3)
{
temp = bmp->data[i];
bmp->data[i] = bmp->data[i+2];
bmp->data[i+2] = temp;
}
return bmp;
}
class GUI
{
public:
GUI();
GUI(float x, float y, float width, float height, string textureName);
void LoadTexture(string textureName);
void Draw();
float GetCenterX() { return m_CenterX; }
float GetCenterY() { return m_CenterY; }
void SetCenterX(float value) { m_CenterX = value; }
void SetCenterY(float value) { m_CenterY = value; }
private:
float m_CenterX, m_CenterY, m_Width, m_Height, m_Depth;
unsigned int m_Texture[1];
unsigned char m_Colour[3];
string m_TextureName;
};
GUI::GUI(float x, float y, float width, float height, string textureName)
{
m_CenterX = x;
m_CenterY = y;
m_Width = width;
m_Height = height;
m_Depth = 0.0;
m_TextureName = textureName;
LoadTexture(textureName);
}
void GUI::Draw()
{
// Turn on OpenGL texturing.
glEnable(GL_TEXTURE_2D);
// Activate a texture.
glBindTexture(GL_TEXTURE_2D, m_Texture[0]);
// Map the texture onto a square polygon.
glBegin(GL_POLYGON);
glTexCoord2f(0.0, 0.0); glVertex3f(m_CenterX - m_Width, m_CenterY - m_Height, -5.0001);
glTexCoord2f(1.0, 0.0); glVertex3f(m_CenterX + m_Width, m_CenterY - m_Height, -5.0001);
glTexCoord2f(1.0, 1.0); glVertex3f(m_CenterX + m_Width, m_CenterY + m_Height, -5.0001);
glTexCoord2f(0.0, 1.0); glVertex3f(m_CenterX - m_Width, m_CenterY + m_Height, -5.0001);
glEnd();
glDisable(GL_TEXTURE_2D);
}
void GUI::LoadTexture(string textureName)
{
// Create texture index array.
glGenTextures(1, m_Texture);
// Local storage for bmp image data.
BitMapFile *image[1];
// Load the texture.
image[0] = getBMPData(textureName);
// Bind image to texture index[0].
glBindTexture(GL_TEXTURE_2D, m_Texture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//used to make the image look blocky
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, GL_RGB, image[0]->sizeX, image[0]->sizeY, 0,
GL_RGB, GL_UNSIGNED_BYTE, image[0]->data);
}
void drawScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
GUI(-3,-3,1,1,0.3,"lifebar.bmp").Draw();
glutSwapBuffers();
}
void setup(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
// Specify how texture values combine with current surface color values.
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glEnable(GL_BLEND);
}
答案 0 :(得分:1)
是。快速而简单,您需要:
1)描述像素透明度的Alpha通道:最简单的方法是加载RGBA图像。
2)启用alpha混合:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
根据您的需要选择混合功能。
编辑请注意,使用RGBA图像时,请正确更改纹理和图像格式(GL_RGB - &gt; GL_RGBA):
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image[0]->sizeX, image[0]->sizeY, 0,
GL_RGBA, GL_UNSIGNED_BYTE, image[0]->data);
EDIT2:我有代码从颜色值创建1x1位图。我用它来为没有它的对象创建虚拟颜色和法线贴图。为了您的测试目的,从这样的缓冲区创建纹理(这是D源,你应该能够很容易地将它转换为C ++):
this(vec4 color) // Create texture from color value
{
ubyte[] buffer = [
cast(ubyte)(color.r*255),
cast(ubyte)(color.g*255),
cast(ubyte)(color.b*255),
cast(ubyte)(color.a*255)
];
this(1, 1, buffer.ptr, GL_RGBA); // Width, height, image buffer, image format
}
使用此纹理,当一切正常时,您应该能够在屏幕上创建任意大小的矩形。更改Alpha值以查看混合是否有效。
EDIT3:上面用C ++编写的代码 - 就像伪代码一样:
BitMapFile *createSinglePixelBitmap()
{
static unsigned char pixel[4] = { 255, 0, 0, 125 }; // Red pixel, alpha ~ 50%
BitMapFile *bitmap = new BitMapFile;
bitmap.sizeX = 1;
bitmap.sizeY = 1;
bitmap.data = pixel;
return bitmap;
}