OPENGL 半透明贴图

半透明贴图的关键是贴图要包含Alpha通道,即贴图像素格式为RGBA格式。但普通BMP图像是没有Alpha通道的,所以需将像素格式进行转换。也很简单,就是在 RGB数据后再加一个字节,将3字节变为4字节。

/******************************************************************************/
//读取一个BMP文件作为纹理。如果失败,返回0,如果成功,返回1

//alpha值取0~255,0 为完全透明。255为不透明
/******************************************************************************/
bool Draw::LoadTexture(LPTSTR szFileName, GLuint &TextureId,  GLint alpha)
{
    HBITMAP hBMP;
    BITMAP BMP;
    GLint  Index, Pixels;
    GLubyte* PixelsData = NULL;

    //生成新的纹理编号
    glGenTextures(1, &TextureId);    
    if(TextureId == 0 ) return false;

   hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL), szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE );
    if (!hBMP)  return false;                                                  // 装载图像

    GetObject(hBMP, sizeof(BMP), &BMP);                                        // 填充数据

    Pixels = BMP.bmWidth * BMP.bmHeight;                                       //像素总数
    PixelsData = (GLubyte*)malloc(Pixels * 4);                                 //申请内存
    if(PixelsData == NULL)  return false; 

    //复制数据
    for(Index = 0; Index < Pixels; Index++)
    {
        memcpy(PixelsData + (Index * 4), (GLubyte*)BMP.bmBits + (Index * 3), 3);
        PixelsData[(Index * 4) + 3] = alpha;                                   //加入Alpha通道
    }
    
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);                                       

    //绑定纹理号
    glBindTexture(GL_TEXTURE_2D, TextureId);

    //设置滤镜
    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_REPEAT);                //在s方向上的缠绕方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);                //在t方向上的缠绕方式

    //生成纹理
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, BMP.bmWidth, BMP.bmHeight, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, PixelsData); 

    free(PixelsData);                                                            //释放内存
    DeleteObject(hBMP);                                                          //释放图像

    return true;
}

这样得到的贴图就是有Alpha通道的了。贴图使用方法如下:(以画球体为例)

GLfloat ConstColor[4] = {0.0f, 0.0f, 0.0f, 1.0f};          //颜色控制

UINT  Texture;

 

//初始化时装载贴图

void Init()

{

  .......

//创建贴图

   char szOptionPath[MAX_PATH];
    strcpy_s(szOptionPath, _T("\\map\\stone1.bmp"));
    LoadTexture(szOptionPath, Texture, 128);

  ......

};
 

/******************************************************************************/
// 绘制球体 Balldx = 球编号
/******************************************************************************/
void Draw::DrawBall(int Balldx )

   int   nIndex;
    float *pfAngel;

    //座标复位
    glLoadIdentity();

    glPushAttrib(GL_CURRENT_BIT);
    glPushMatrix();               //把矩阵压入堆栈

    //确定球的位置

   if(Balldx == 1)
      glTranslatef(-0.5f, 0.0f, -1.0f); 

  else

      glTranslatef(0.5f, 0.0f, -1.0f); 

    // 绘制球体, 第1、2、3个参数分别表示半径,经度线数、纬度线数
    glDepthMask(GL_FALSE);                                                                                             //关掉深度测试
    glEnable(GL_BLEND);                                                                                                   //开混合模式贴图
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);                             //设置混合方式

    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, Texture);                                    //使用纹理

    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);                                 //贴图模式为混合
    if(Balldx == 1)
    {

       //红色
        ConstColor[0] = 1.0f;  
        ConstColor[1] = 0.0f;
        ConstColor[2] = 0.0f;  
    }
    else
    {

       //蓝色
        ConstColor[0] = 0.0f;  
        ConstColor[1] = 0.0f;
        ConstColor[2] = 1.0f;
    }
    ConstColor[3] = 0.5f;
    glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR, ConstColor);

    //   绘制

    gluQuadricTexture(QuadricObj, GL_TRUE);
    gluSphere(QuadricObj, 2.5f, 50, 50);    //实体    

    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);
    glDepthMask(GL_TRUE);    

    glPopMatrix();   
    glPopAttrib();

}

效果演示:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值