OPenGL笔记--给立方体贴图(纹理)
生活随笔
收集整理的這篇文章主要介紹了
OPenGL笔记--给立方体贴图(纹理)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
文章目錄
- 一、前置知識
- 二、效果展示、
- 三、完整代碼
- 附、給立方體每個面渲染不同的紋理
一、前置知識
經(jīng)過前面的學(xué)習(xí),我們已經(jīng)知道了立方體怎么創(chuàng)建了,接下來學(xué)習(xí)怎么給立方體貼圖;
為了將紋理正確的映射到四邊形上,您必須:
- 將紋理的 右上角 映射到四邊形的 右上角 ;
- 紋理的 左上角 映射到四邊形的 左上角 ;
- 紋理的 右下角 映射到四邊形的 右下角 ;
- 紋理的 左下角 映射到四邊形的 左下角 ;
如果映射錯誤的話,圖像顯示時可能上下 顛倒,側(cè)向一邊或者什么都不是
glTexCoord2f(x, y):
- 第一個參數(shù)是X坐標(biāo);0.0 是紋理的左側(cè)、0.5 是紋理的中點、 1.0 是紋理的右側(cè);
- 第二個參數(shù)是Y坐標(biāo);0.0 是紋理的底部、 0.5 是紋理的中點、1.0 是紋理的頂部;
二、效果展示、
三、完整代碼
#ifndef GL_TEST_H #define GL_TEST_H#include <qgl.h> //因為QGLWidget類被包含在qgl.h頭文件中 #include <glut.h> //使用glut庫中的API #include <QKeyEvent> #include <QTimer>//繼承QGLWidget得到OPenGL窗口部件類 class GL_Test : public QGLWidget { public:GL_Test(QWidget* parent = 0, bool fs = false);~GL_Test();protected:/*************************************************************************************************QGLWidget 類已經(jīng)內(nèi)置了對 OpenGL 的處理,就是通過對 initializeGL()、 paintGL()和 resizeGL()這個三個函數(shù)實現(xiàn)*************************************************************************************************/void initializeGL() override; //用來初始化OPenGL窗口,可以在里面設(shè)定一些有關(guān)選項void paintGL() override; //用來繪制OPenGL的窗口,只要有更新發(fā)生,這個函數(shù)就會被調(diào)用void resizeGL(int w, int h) override; //用來處理窗口大小變換這一事件,resizeGL()在處理完后會自動刷新屏幕void keyPressEvent(QKeyEvent* e) override; //Qt鍵盤事件處理函數(shù)void loadGLTextures(); //載入指定的圖片并生成相應(yīng)的紋理protected:bool fullscreen; //用來保存窗口是否處于全屏狀態(tài)的變量GLfloat xRot, yRot, zRot; //用來處理立方體的旋轉(zhuǎn)GLuint texture[1]; //用來存儲紋理(長度為1的數(shù)組) };#endif // GL_TEST_H #include "gl_test.h"GL_Test::GL_Test(QWidget* parent, bool fs): QGLWidget(parent) {fullscreen = fs;xRot = 0.0;yRot = 0.0;zRot = 0.0;setGeometry(500,500,640,480); //設(shè)置窗口大小、位置setWindowTitle("The first OpenGL Window"); //設(shè)置窗口標(biāo)題if(fullscreen) {showFullScreen();}QTimer* timer = new QTimer(this);connect(timer,&QTimer::timeout,[=]{updateGL();});timer->start(50); }GL_Test::~GL_Test() {}void GL_Test::initializeGL() {loadGLTextures(); //載入紋理glEnable(GL_TEXTURE_2D); //啟用紋理glShadeModel(GL_SMOOTH); //啟用smooth shading(陰影平滑)glClearColor(0.0, 0.0, 0.0, 0.5); //清除屏幕時所用的顏色,rgba【0.0(最黑)~1.0(最亮)】glClearDepth(1.0); //設(shè)置深度緩存glEnable(GL_DEPTH_TEST); //啟動深度測試glDepthFunc(GL_LEQUAL); //所作深度測試的類型glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //真正精細(xì)的透視修正,告訴OPenGL我們希望進行最好的透視修正,這會十分輕微的影響性能,但使得透視圖看起來好一點 }void GL_Test::paintGL() {glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度緩存//-----------------------------------------glLoadIdentity(); //重置當(dāng)前的模型觀察矩陣glTranslatef(0.0, 0.0, -5.0);glRotatef(xRot, 1.0, 0.0, 0.0); //繞X軸旋轉(zhuǎn)xRot度glRotatef(yRot, 0.0, 1.0, 0.0); //繞X軸旋轉(zhuǎn)yRot度glRotatef(zRot, 0.0, 0.0, 1.0); //繞X軸旋轉(zhuǎn)zRot度//選擇我們使用的紋理glBindTexture(GL_TEXTURE_2D, texture[0]);//如果您在您的場景中使用多個紋理,您應(yīng)該使用來 glBindTexture(GL_TEXTURE_2D, texture[所使用紋理對應(yīng)的數(shù)字]) 選擇要綁定的紋理;//當(dāng)您想改變紋理時,應(yīng)該綁定新的紋理。并且您不能在glBegin()和glEnd()之間綁定紋理,必須在glBegin()之前或glEnd()之后綁定;//繪制正方形開始glBegin(GL_QUADS);//前面glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, 1.0 );//后面glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, -1.0 );//頂面glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 1.0, 1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 1.0, 1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 );//底面glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, -1.0, -1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, -1.0, -1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );//右面glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, -1.0, -1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );//左面glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, 1.0, 1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 );glEnd();//繪制正方形結(jié)束//-----------------------------------------xRot += 2;yRot += 3;zRot += 4; }void GL_Test::resizeGL(int w, int h) {if(h == 0) { //防止h為0h = 1;}glViewport(0, 0, (GLint)w, (GLint)h); //重置當(dāng)前的視口(Viewport)glMatrixMode(GL_PROJECTION); //選擇投影矩陣glLoadIdentity(); //重置投影矩陣gluPerspective( 45.0, (GLfloat)w/(GLfloat)h, 0.1, 100.0 ); //建立透視投影矩陣glMatrixMode(GL_MODELVIEW); //選擇模型觀察矩陣glLoadIdentity(); //重置模型觀察矩陣 }void GL_Test::keyPressEvent(QKeyEvent* e) {switch (e->key()) {case Qt::Key_Q: {fullscreen = !fullscreen;if(fullscreen) {showFullScreen();}else {showNormal();setGeometry(500,500,640,480);}updateGL();break;}//case Qt::Key_Qcase Qt::Key_Escape: {close();}//Qt::Key_Escape}//switch (e->key()) }void GL_Test::loadGLTextures() {QImage tex,buf;if(!buf.load(":/Images/1591561503-gB5rD.jpg")) { //用QImage類載入紋理圖片QImage dummy(128,128,QImage::Format_RGB32); //如果載入不成功,生成一個128*128的32位色的綠色圖片dummy.fill(Qt::green);buf = dummy;}tex = QGLWidget::convertToGLFormat(buf); //QGLWidget的靜態(tài)函數(shù),專門用來轉(zhuǎn)換圖片glGenTextures(1,&texture[0]); //創(chuàng)建一個紋理glBindTexture(GL_TEXTURE_2D,texture[0]); //使用來自位圖數(shù)據(jù)生成的典型紋理/*告訴OPenGL將紋理名字texture[0]綁定到紋理目標(biāo)上;2D紋理只有高度(在Y軸上)和寬度(在X軸上)*///真正的創(chuàng)建紋理//GL_TEXTURE_2D:告訴 OpenGL 此紋理是一個 2D 紋理;//數(shù)字0:代表圖像的詳細(xì)程度;//數(shù)字3:是數(shù)據(jù)的成分?jǐn)?shù);//tex.width():是紋理的寬度//tex.height():是紋理的高度;//GL_RGBA:告訴 OpenGL 圖像數(shù)據(jù)由紅、綠、藍(lán)三色數(shù)據(jù)以及 alpha 通道數(shù)據(jù)組成;//GL_UNSIGNED_BYTE:意味著組成圖像的數(shù)據(jù)是無符號字節(jié)類型的;//tex.bits():告訴 OpenGL 紋理數(shù)據(jù)的來源;glTexImage2D(GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());//告訴 OpenGL 在顯示圖像時,當(dāng)它比放大得原始的紋理大(GL_TEXTURE_MAG_FILTER)或縮小得比原始得紋理小(GL_TEXTURE_MIN_FILTER)時,//OpenGL 采用的濾波方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//我們都采用 GL_LINEAR,這使得紋理從很遠(yuǎn)處到離屏幕很近時都平滑顯示;//使用 GL_LINEAR 需要 CPU 和顯卡做更多的運算,如果您的機器很慢,您也許應(yīng)該采用 GL_NEAREST;//過濾的紋理在放大的時候,看起來斑駁的很,您也可以結(jié)合這兩種濾波方式: 在近處時使用 GL_LINEAR,遠(yuǎn)處時 GL_NEAREST; }附、給立方體每個面渲染不同的紋理
1、創(chuàng)建多個紋理
void GL_Test::loadGLTextures() {QStringList Images;Images << ":/Images/1591561503-gB5rD.jpg";Images << ":/Images/AI.png";Images << ":/Images/wallhaven-283q5m.png";Images << ":/Images/wallhaven-q2oxx7.png";Images << ":/Images/wallhaven-y85ojk.png";Images << ":/Images/wallhaven-z8pm7y.png";for(int i=0; i<6; ++i) {QImage tex,buf;if(!buf.load(Images.at(i))) { //用QImage類載入紋理圖片QImage dummy(128,128,QImage::Format_RGB32); //如果載入不成功,生成一個128*128的32位色的綠色圖片dummy.fill(Qt::green);buf = dummy;}tex = QGLWidget::convertToGLFormat(buf); //QGLWidget的靜態(tài)函數(shù),專門用來轉(zhuǎn)換圖片glGenTextures(1,&texture[i]); //創(chuàng)建1個紋理,存儲在texture[i]中//---------------------------------------------------------------------------------------glBindTexture(GL_TEXTURE_2D,texture[i]); //使用來自位圖數(shù)據(jù)生成的典型紋理/*告訴OPenGL將紋理名字texture[0]綁定到紋理目標(biāo)上;2D紋理只有高度(在Y軸上)和寬度(在X軸上)*///真正的創(chuàng)建紋理//GL_TEXTURE_2D:告訴 OpenGL 此紋理是一個 2D 紋理;//數(shù)字0:代表圖像的詳細(xì)程度;//數(shù)字3:是數(shù)據(jù)的成分?jǐn)?shù);//tex.width():是紋理的寬度//tex.height():是紋理的高度;//GL_RGBA:告訴 OpenGL 圖像數(shù)據(jù)由紅、綠、藍(lán)三色數(shù)據(jù)以及 alpha 通道數(shù)據(jù)組成;//GL_UNSIGNED_BYTE:意味著組成圖像的數(shù)據(jù)是無符號字節(jié)類型的;//tex.bits():告訴 OpenGL 紋理數(shù)據(jù)的來源;glTexImage2D(GL_TEXTURE_2D,0,3,tex.width(),tex.height(),0, GL_RGBA,GL_UNSIGNED_BYTE,tex.bits());//告訴 OpenGL 在顯示圖像時,當(dāng)它比放大得原始的紋理大(GL_TEXTURE_MAG_FILTER)或縮小得比原始得紋理小(GL_TEXTURE_MIN_FILTER)時,//OpenGL 采用的濾波方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//我們都采用 GL_LINEAR,這使得紋理從很遠(yuǎn)處到離屏幕很近時都平滑顯示;//使 用 GL_LINEAR 需要 CPU 和顯卡做更多的運算,如果您的機器很慢,您也許應(yīng)該采用 GL_NEAREST;//過濾的紋理在放大的時候,看起來斑駁的很,您也可以結(jié)合這兩種濾波方式: 在近處時使用 GL_LINEAR,遠(yuǎn)處時 GL_NEAREST;} }2、不同面使用不同紋理
void GL_Test::paintGL() {glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度緩存glLoadIdentity(); //重置當(dāng)前的模型觀察矩陣glTranslatef(0.0, 0.0, zoom);glRotatef(xRot, 1.0, 0.0, 0.0); //繞X軸旋轉(zhuǎn)xRot度glRotatef(yRot, 0.0, 1.0, 0.0); //繞X軸旋轉(zhuǎn)yRot度// //選擇我們使用的紋理 // glBindTexture(GL_TEXTURE_2D, texture[filter]); // //如果您在您的場景中使用多個紋理,您應(yīng)該使用來 glBindTexture(GL_TEXTURE_2D, texture[所使用紋理對應(yīng)的數(shù)字]) 選擇要綁定的紋理; // //當(dāng)您想改變紋理時,應(yīng)該綁定新的紋理。并且您不能在glBegin()和glEnd()之間綁定紋理,必須在glBegin()之前或glEnd()之后綁定;//-----------------------------------------glBindTexture(GL_TEXTURE_2D, texture[0]);//繪制正方形開始glBegin(GL_QUADS);//前面glNormal3f(0.0, 0.0, 1.0); //x、y、z,垂直于面的法線向量glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, 1.0 );glEnd();//繪制正方形結(jié)束//-----------------------------------------//-----------------------------------------glBindTexture(GL_TEXTURE_2D, texture[1]);//繪制正方形開始glBegin(GL_QUADS);//后面glNormal3f(0.0, 0.0, -1.0); //x、y、z,垂直于面的法線向量glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, -1.0 );glEnd();//繪制正方形結(jié)束//-----------------------------------------//-----------------------------------------glBindTexture(GL_TEXTURE_2D, texture[2]);//繪制正方形開始glBegin(GL_QUADS);//頂面glNormal3f(0.0, 1.0, 0.0); //x、y、z,垂直于面的法線向量glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, 1.0, 1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 1.0, 1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 );glEnd();//繪制正方形結(jié)束//-----------------------------------------//-----------------------------------------glBindTexture(GL_TEXTURE_2D, texture[3]);//繪制正方形開始glBegin(GL_QUADS);//底面glNormal3f(0.0, -1.0, 0.0); //x、y、z,垂直于面的法線向量glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, -1.0, -1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, -1.0, -1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );glEnd();//繪制正方形結(jié)束//-----------------------------------------//-----------------------------------------glBindTexture(GL_TEXTURE_2D, texture[4]);//繪制正方形開始glBegin(GL_QUADS);//右面glNormal3f(1.0, 0.0, 0.0); //x、y、z,垂直于面的法線向量glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, -1.0, -1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, -1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );glEnd();//繪制正方形結(jié)束//-----------------------------------------//-----------------------------------------glBindTexture(GL_TEXTURE_2D, texture[5]);//繪制正方形開始glBegin(GL_QUADS);//左面glNormal3f(-1.0, 0.0, 0.0);glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0, -1.0 );glTexCoord2f( 1.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );glTexCoord2f( 1.0, 1.0 ); glVertex3f( -1.0, 1.0, 1.0 );glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, -1.0 );glEnd();//繪制正方形結(jié)束//-----------------------------------------xRot += xSpeed;yRot += ySpeed; }總結(jié)
以上是生活随笔為你收集整理的OPenGL笔记--给立方体贴图(纹理)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 爬取张国荣最火的 8 首歌
- 下一篇: 频谱仪维修之频谱分析仪常用配件