OpenGL,多边形上贴BMP (C/C++版)+在QT中的使用

本文介绍如何在OpenGL中加载24位BMP纹理,并将其应用到一个二维多边形上,通过QGLWidget实现。首先定义一个SilderBar类,继承自QGLWidget,在构造函数中禁用背景填充。然后使用load_texture函数读取BMP文件,通过glBindTexture将BMP纹理绑定到多边形上。最后在QT的UI中展示这个图形。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

百度:

可以看到一位前辈的讲解。参考它弄的。

刚开始搞了3天,里面可能会有很多错误。

 

专门定义了一个类

.h

 

#include <QGLWidget>
#include <GL/glut.h>

//glut.h包含了gl.h
//#include <GL/gl.h>

 

class SilderBar:public QGLWidget
{
public:
    SilderBar(const QGLFormat & format, QWidget *parent = 0);
    ~SilderBar();

}

 

.cpp

 

在构造函数中加入

setAutoFillBackground(false);

不然图元不会显示

 

#define BMP_Header_Length 54

void drawSomething()

{

//此类继承QGLWidget类,此函数具体啥作用没调查

    makeCurrent();

 

    glClear(GL_COLOR_BUFFER_BIT);

//设置GL_TEXTURE_2D

     glEnable(GL_TEXTURE_2D);
    GLuint  texWall;

//这里读取了一个24位BMP图片
    texWall = load_texture(FileNameBmp);

 

    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // 这里就是把那个位图跟这个二维图形勾搭上
    glBindTexture(GL_TEXTURE_2D, texWall);

  //画了一个多边形,贴图的时候一一对应,不然肯定画歪

  //glVertex3f可以控制图片的显示范围,例如在这里,图片的白边就不会显示,变相实现BMP透明?
    glBegin(GL_POLYGON);
    glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 0.0f, 0.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, 0.3f, 0.0f);
    glTexCoord2f(0.5f, 1.0f); glVertex3f(0.15f, 0.3f, 0.0f);
    glTexCoord2f(1.0f, 0.5f); glVertex3f(0.3f, 0.15f,0.0f);
    glTexCoord2f(0.5f, 0.0f); glVertex3f(0.15f, 0.0f, 0.0f);

    glEnd();

//取消GL_TEXTURE_2D

//glDisable(GL_TEXTURE_2D);

   doneCurrent
}

 

GLuint load_texture(const char* file_name)
{
     GLint width, height, total_bytes;
     GLubyte* pixels = 0;
     GLuint last_texture_ID, texture_ID = 0;

     // 打开文件,如果失败,返回
     FILE* pFile = fopen(file_name, "rb");
    if( pFile == 0 )
        return 0;

     // 读取文件中图象的宽度和高度
    fseek(pFile, 0x0012, SEEK_SET);
    fread(&width, 4, 1, pFile);
    fread(&height, 4, 1, pFile);
    fseek(pFile, BMP_Header_Length, SEEK_SET);

     // 计算每行像素所占字节数,并根据此数据计算总像素字节数
     {
         GLint line_bytes = width * 3;
        while( line_bytes % 4 != 0 )
             ++line_bytes;
         total_bytes = line_bytes * height;
     }

     // 根据总像素字节数分配内存
     pixels = (GLubyte*)malloc(total_bytes);
    if( pixels == 0 )
     {
        fclose(pFile);
        return 0;
     }

     // 读取像素数据
    if( fread(pixels, total_bytes, 1, pFile) <= 0 )
     {
        free(pixels);
        fclose(pFile);
        return 0;
     }

     // 分配一个新的纹理编号
    glGenTextures(1, &texture_ID);
    if( texture_ID == 0 )
     {
        free(pixels);
        fclose(pFile);
        return 0;
     }

     // 绑定新的纹理,载入纹理并设置纹理参数
     // 在绑定前,先获得原来绑定的纹理编号,以便在最后进行恢复
    glGetIntegerv(GL_TEXTURE_BINDING_2D,(GLint*)&last_texture_ID);
     glBindTexture(GL_TEXTURE_2D, texture_ID);

//纹理过滤设定
     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);
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

//颜色混合模式
     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
         GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
     glBindTexture(GL_TEXTURE_2D, last_texture_ID);

     // 之前为pixels分配的内存可在使用glTexImage2D以后释放
     // 因为此时像素数据已经被OpenGL另行保存了一份(可能被保存到专门的图形硬件中)
    free(pixels);
    return texture_ID;
}

 

以上就是读取24位BMP并贴在一个二维多边形上了

 

.ui文件上的显示

 

    //设定大小

      QRect rectSB(508, 99, 282, 275);

//定义一个scene

      QGraphicsScene *m_scene= new QGraphicsScene();
    m_scene->setSceneRect(rectSB);

 //没啥说的就是搞了那个要显示的对象

    m_Sb = new SilderBar(QGLFormat(QGL::SampleBuffers), this);
    m_Sb->setGeometry(rectSB);
    // 在ui文件上拉了一个graphicsView来显示

    ui->graphicsView->setViewport(m_Sb);
    ui->graphicsView->setScene(m_scene);

初步搞定,其他功能慢慢加
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值