程序运行截图如下:
源码如下:
myglwidget.h
#ifndef MYGLWIDGET_H
#define MYGLWIDGET_H
#include <QOpenGLWidget>
#include <QWidget>
class SkyBox;
class MyGLWidget : public QOpenGLWidget
{
Q_OBJECT
public:
explicit MyGLWidget(QWidget *parent = 0);
SkyBox *m_skybox;
double m_axle_X;
double m_axle_Y;
double m_rotate_value;
int m_verticalValue;
public slots:
protected:
void initializeGL();
void resizeGL(int w,int h);
void paintGL();
};
#endif // MYGLWIDGET_H
skybox.h
#ifndef SKYBOX_H
#define SKYBOX_H
#include <GL/gl.h>
#include <GL/glu.h>
#include <QString>
class QImage;
class SkyBox
{
public:
SkyBox();
void draw();
void Init();
protected:
GLuint CreateTexture2DFromBMP(const char*bmpPath);
unsigned char * LoadFileContent(const char *path, int &filesize);
unsigned char *DecodeBMP(unsigned char*bmpFileData, int&width, int&height);
GLuint createTexture2D(unsigned char *piexlData, int width, int height, GLenum type);
private:
GLuint m_textures[6];
};
#endif // SKYBOX_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
public slots:
void upBtnClicked();
void downBtnClicked();
void leftBtnClicked();
void rightBtnClicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
myglwidget.cpp
#include "myglwidget.h"
#include <GL/glu.h>
#include <QDebug>
#include "skybox.h"
MyGLWidget::MyGLWidget(QWidget *parent) : QOpenGLWidget(parent)
{
m_skybox=new SkyBox;
m_axle_X=0.0;
m_axle_Y=0.0;
m_rotate_value=0.0;
m_verticalValue=0;
}
void MyGLWidget::initializeGL()
{
glMatrixMode(GL_PROJECTION);
gluPerspective(50.0f,800.0f/600.0f,0.1f,1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
m_skybox->Init();
}
void MyGLWidget::resizeGL(int w, int h)
{
Q_UNUSED(w)
Q_UNUSED(h)
}
void MyGLWidget::paintGL()
{
glClearColor(0.0f,0.0f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
m_skybox->draw();
if(m_axle_X==1){
if(m_verticalValue>=90||m_verticalValue<=-90){
return;
}
}
glRotatef(m_rotate_value,m_axle_X,m_axle_Y,0.0);
}
skybox.cpp
#include "skybox.h"
#include <QImage>
#include <QDebug>
#include <QFile>
SkyBox::SkyBox()
{
}
void SkyBox::draw()
{
glDisable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, m_textures[0]);
glBegin(GL_QUADS);
glColor4ub(255,255,255,255);
glTexCoord2f(0.0f,0.0f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glTexCoord2f(1.0f,0.0f);
glVertex3f(0.5f,-0.5f,-0.5f);
glTexCoord2f(1.0f,1.0f);
glVertex3f(0.5f,0.5f,-0.5f);
glTexCoord2f(0.0f,1.0f);
glVertex3f(-0.5f,0.5f,-0.5f);
glEnd();
glBindTexture(GL_TEXTURE_2D, m_textures[1]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f,0.0f);
glVertex3f(0.5f,-0.5f,0.5f);
glTexCoord2f(1.0f,0.0f);
glVertex3f(-0.5f,-0.5f,0.5f);
glTexCoord2f(1.0f,1.0f);
glVertex3f(-0.5f,0.5f,0.5f);
glTexCoord2f(0.0f,1.0f);
glVertex3f(0.5f,0.5f,0.5f);
glEnd();
glBindTexture(GL_TEXTURE_2D, m_textures[2]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f,0.0f);
glVertex3f(-0.5f,-0.5f,0.5f);
glTexCoord2f(1.0f,0.0f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glTexCoord2f(1.0f,1.0f);
glVertex3f(-0.5f,0.5f,-0.5f);
glTexCoord2f(0.0f,1.0f);
glVertex3f(-0.5f,0.5f,0.5f);
glEnd();
glBindTexture(GL_TEXTURE_2D, m_textures[3]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f,0.0f);
glVertex3f(0.5f,-0.5f,-0.5f);
glTexCoord2f(1.0f,0.0f);
glVertex3f(0.5f,-0.5f,0.5f);
glTexCoord2f(1.0f,1.0f);
glVertex3f(0.5f,0.5f, 0.5f);
glTexCoord2f(0.0f,1.0f);
glVertex3f(0.5f,0.5f,-0.5f);
glEnd();
glBindTexture(GL_TEXTURE_2D, m_textures[4]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f,0.0f);
glVertex3f(-0.5f,0.5f,-0.5f);
glTexCoord2f(1.0f,0.0f);
glVertex3f(0.5f,0.5f,-0.5f);
glTexCoord2f(1.0f,1.0f);
glVertex3f(0.5f,0.5f,0.5f);
glTexCoord2f(0.0f,1.0f);
glVertex3f(-0.5f,0.5f,0.5f);
glEnd();
glBindTexture(GL_TEXTURE_2D,m_textures[5]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f,0.0f);
glVertex3f(-0.5f,-0.5f,0.5f);
glTexCoord2f(1.0f,0.0f);
glVertex3f(0.5f,-0.5f,0.5f);
glTexCoord2f(1.0f,1.0f);
glVertex3f(0.5f,-0.5f,-0.5f);
glTexCoord2f(0.0f,1.0f);
glVertex3f(-0.5f,-0.5f,-0.5f);
glEnd();
}
void SkyBox::Init()
{
m_textures[0]=CreateTexture2DFromBMP("E:\\Qt2018\\SkyOpenGL\\Res\\front.bmp");
m_textures[1]=CreateTexture2DFromBMP("E:\\Qt2018\\SkyOpenGL\\Res\\back.bmp");
m_textures[2]=CreateTexture2DFromBMP("E:\\Qt2018\\SkyOpenGL\\Res\\left.bmp");
m_textures[3]=CreateTexture2DFromBMP("E:\\Qt2018\\SkyOpenGL\\Res\\right.bmp");
m_textures[4]=CreateTexture2DFromBMP("E:\\Qt2018\\SkyOpenGL\\Res\\top.bmp");
m_textures[5]=CreateTexture2DFromBMP("E:\\Qt2018\\SkyOpenGL\\Res\\bottom.bmp");
}
GLuint SkyBox::CreateTexture2DFromBMP(const char *bmpPath)
{
int nFileSize=0;
unsigned char *bmpFileContent=LoadFileContent(bmpPath,nFileSize);
if (bmpFileContent==nullptr){
return 0;
}
int bmpWidth=0,bmpHeight=0;
unsigned char*pixelData=DecodeBMP(bmpFileContent,bmpWidth,bmpHeight);
if (bmpWidth==0){
delete bmpFileContent;
return 0;
}
GLuint texture=createTexture2D(pixelData,bmpWidth,bmpHeight,GL_RGB);
delete bmpFileContent;
return texture;
}
unsigned char *SkyBox::LoadFileContent(const char *path,int &filesize)
{
unsigned char*fileContent=nullptr;
filesize=0;
FILE*pFile=fopen(path,"rb");
if(pFile){
fseek(pFile,0,SEEK_END);
int nLen=ftell(pFile);
if(nLen>0){
rewind(pFile);
fileContent=new unsigned char[nLen + 1];
fread(fileContent,sizeof(unsigned char),nLen,pFile);
fileContent[nLen] ='\0';
filesize=nLen;
}
fclose(pFile);
}
return fileContent;
}
unsigned char *SkyBox::DecodeBMP(unsigned char *bmpFileData,int &width,int &height)
{
if (0x4D42==*((unsigned short*)bmpFileData)){
int pixelDataOffset=*((int*)(bmpFileData+10));
width=*((int*)(bmpFileData+18));
height=*((int*)(bmpFileData+22));
unsigned char*pixelData=bmpFileData+pixelDataOffset;
for (int i=0;i<width*height*3;i+=3){
unsigned char temp=pixelData[i];
pixelData[i]=pixelData[i+2];
pixelData[i+2]=temp;
}
return pixelData;
}
return nullptr;
}
GLuint SkyBox::createTexture2D(unsigned char *piexlData, int width, int height, GLenum type)
{
GLuint texture;
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);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D,0,type,width,height,0,type,GL_UNSIGNED_BYTE,piexlData);
return texture;
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "skybox.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->upPushButton,SIGNAL(clicked(bool)),this,SLOT(upBtnClicked()));
connect(ui->downPushButton,SIGNAL(clicked(bool)),this,SLOT(downBtnClicked()));
connect(ui->leftPushButton,SIGNAL(clicked(bool)),this,SLOT(leftBtnClicked()));
connect(ui->rightPushButton,SIGNAL(clicked(bool)),this,SLOT(rightBtnClicked()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::upBtnClicked()
{
ui->openGLWidget->m_axle_X=1.0;
ui->openGLWidget->m_axle_Y=0.0;
ui->openGLWidget->m_rotate_value=-2.0;
ui->openGLWidget->m_verticalValue+=1;
ui->openGLWidget->update();
}
void Widget::downBtnClicked()
{
ui->openGLWidget->m_axle_X=1.0;
ui->openGLWidget->m_axle_Y=0.0;
ui->openGLWidget->m_rotate_value=2.0;
ui->openGLWidget->m_verticalValue-=1;
ui->openGLWidget->update();
}
void Widget::leftBtnClicked()
{
ui->openGLWidget->m_axle_X=0.0;
ui->openGLWidget->m_axle_Y=1.0;
ui->openGLWidget->m_rotate_value=-2.0;
ui->openGLWidget->update();
}
void Widget::rightBtnClicked()
{
ui->openGLWidget->m_axle_X=0.0;
ui->openGLWidget->m_axle_Y=1.0;
ui->openGLWidget->m_rotate_value=2.0;
ui->openGLWidget->update();
}