【问题标题】:Opengl C++: How do I make parts of a texture transparent?Opengl C++:如何使部分纹理透明?
【发布时间】:2014-12-25 20:21:20
【问题描述】:

我正在我的 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);
}

【问题讨论】:

  • 你应该首先在纹理中添加一个 alpha 组件
  • @ratchetfreak 如何添加 alpha 组件?
  • 最简单的方法是加载 RGBA 图像,其中 alpha (A) 通道已经存在并且希望是正确的。其他可能性包括创建单独的 Alpha 通道(“灰度”图像),但我不知道如何将它们与固定管道一起使用(假设您没有使用自己的自定义着色器)。
  • 查看 Photoshop 我发现由于某种原因它不允许我保存带有 alpha 的 .bmp。该选项显示为灰色,我找不到原因。我一直试图摆脱固定管道,因为我一直听到它有多糟糕。我一直在尝试找到一个关于顶点数组或其他东西的好教程,但可惜我找不到任何可以给出明确答案的东西。对这两个问题有什么建议吗?
  • 我没有用过 Photoshop,所以我不知道,但我很确定它不仅可以保存 Alpha 通道,而且可能还有创建它们的工具。固定功能管道还不错,只是比现代方法慢,但另一方面,你也可以更快地工作。在事情开始发生之前,迁移到现代 OpenGL 可能需要一些代码。我用这些教程来学习东西:opengl-tutorial.org

标签: c++ opengl user-interface


【解决方案1】:

是的。快速简单地,您需要:

1) 描述像素透明度的 Alpha 通道:最简单的方法是加载 RGBA 图像。

2) 启用 alpha 混合:

glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

根据需要选择混合功能。

编辑:注意,使用 RGBA 图像时,请正确更改纹理和图像格式(GL_RGB -> 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;
}

【讨论】:

  • 我已经有了 glenable。当我添加 glBlendFunc 时,会发生这种情况:imgur.com/MhZKcaR。知道为什么要这样做吗?
  • @WhyYouNoWork 尝试将glClearColor(0.0, 0.0, 0.0, 0.0); 更改为glClearColor(0.0, 0.0, 0.0, 1.0);。还要检查你的上下文是否有 alpha 缓冲区
  • @Nazar554 我改变了它,但它仍然给我同样的问题。上下文是什么意思?
  • 您以某种方式创建窗口,并且您很可能还创建了 opengl 上下文。我使用 SDL 创建它,所以我使用 SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8) 只是为了确保它为上下文创建 alpha 层。
  • @Nazar554 对于使用 SRC_ALPHA 的混合函数,您不需要带 alpha 的帧缓冲区。仅当混合函数包含 DST_ALPHA 时才需要。
猜你喜欢
  • 1970-01-01
  • 2010-10-19
  • 1970-01-01
  • 1970-01-01
  • 2011-04-03
  • 2015-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多