OpenGL_Qt學習筆記之_05(紋理映射)

2022-01-30 Qt教程

紋理映射基礎知識

  什麼叫紋理映射,一開始我也不明白,感覺這個詞好專業(畢竟沒有學過圖形學),後面經過網上查找資料和這次實驗稍微理解了點。紋理映射簡單的講,就是把一個紋理(其實說白了,紋理可以理解為一幅圖像)映射到空間物體的表面上,因此紋理映射也叫貼圖,這個表明不一定是矩形,比如說我可以是球面,或者是任意曲面。在上一篇文章OpenGL_Qt學習筆記之_04(3D圖形的繪製和旋轉)中,我們繪製的空間體的表面都是一些光滑的顏色,如果要在其表面採用那種方法繪製圖像的話,則必須利用微分的思想,一個一個的繪製小圖像,然後拼接起來,可想而知,這個過程是多麼的複雜,opengl的紋理映射就可以很好的解決這一問題。

     下面來看看紋理映射的一個示意圖片(百度百科上的): 

  這個示意圖說明,將中間的紋理(即圖片)映射到左邊的茶壺曲面上,就形成了右邊的圖了。在右邊的圖中,可以看到茶壺的表面上布滿了圖片,這就像中國古代的陶器繪圖一樣。

  紋理映射另外一個好處是能夠保證在變換多邊形時,多邊形上的紋理也會隨之變化。

  紋理映射相關函數

  要進行紋理映射,得先了解下opengl中有關紋理映射的一些相關函數。

  void glGenTextures(GLsizei n, GLuint *textures);

  該函數的作用是開闢存儲紋理的內存空間,其中參數n為開闢紋理內存的個數,texture為存儲紋理的地址索引。

  void glBindTexture(GLenum target,   GLuint texture);

  該函數的作用是把存儲紋理的對象texture綁定到紋理目標target上,在opengl中紋理目標分為GL_TEXTURE_1D和GL_TEXTURE_2D。該句代碼運行完後,對target的操作也對應於對texture指向的內容的操作。

  void glTexImage2D(GLenum target,GLint level,GLint components,GLsizei width, glsizei height,GLint border,GLenum format,GLenum type, const GLvoid *pixels);

  參數1為紋理目標;參數2為目標的層次,即目標的詳細程度,一般情況採用0即可;參數3表示的是數據成分的個數,如果數據由RGB構成,則將該參數設置為3;參數4和5分別為創建紋理數據的長和寬;參數6為邊框的值,一般也設為0;參數8為數據的通道格式;參數9為紋理的數據元素類型;參數10為紋理的數據內容。

  這個函數的功能是創建一個紋理,並為該紋理分配了數據。

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

  該函數表示的是當所顯示的紋理比加載進來的紋理小時,採用GL_LINEAR的方法來處理。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  和上面的函數類似,注意該函數的參數2為GL_TEXTURE_MAG_FILTER,不要誤認為是GL_TEXTURE_MAG_FILTER。

  第一個參數是X坐標。0.0f 是紋理的左側。0.5f 是紋理的中點, 1.0f 是紋理的右側。第二個參數是Y坐標。0.0f 是紋理的底部。0.5f 是紋理的中點,1.0f 是紋理的頂部。

 

  給定一張紋理圖,它的坐標示意圖如下:

   

  其中紋理的中心點坐標為(0.5, 0.5).

 

  實驗說明:

  這個實驗室在上一篇博文OpenGL_Qt學習筆記之_04(3D圖形的繪製和旋轉) 繪製的立方體上貼每個面上貼上一張紋理(即圖片)。

  我們需要在GLWidget這個類中添加一個函數來加載紋理數據,該函數為loadTextures().

  另外,在QGLWidget這個類中,initializeGL(), paintGL(), resizeGL()這3個函數的執行順序是該類啟動時就執行initializeGL(),主要用於初始化opengl,通常用來設置一些前期的背景色,光照參數等等。paintGL()用於渲染整個場景;resizeGL()用於在widget大小變化的時候產生合理view。

  注意,本實驗給的圖片長和寬必須是2的n次方,最大不要超過256,最小也不要小於64。我這裡採用的是256*256像素的圖片。

 

  實驗結果:

  加載紋理的圖像為:

  

 

  紋理映射後的效果如下:

  

  實驗主要部分代碼及注釋(附錄有工程code下載地址):



#include "glwidget.h"#include "ui_glwidget.h"
#include <QtGui>#include <QtCore>#include <QtOpenGL>
GLWidget::GLWidget(QGLWidget *parent) : QGLWidget(parent), ui(new Ui::GLWidget){ ui->setupUi(this); fullscreen = false; rotate_angle = 0.0;}
void GLWidget::initializeGL(){ setGeometry(300, 150, 500, 500); loadTextures(); glEnable(GL_TEXTURE_2D); glShadeModel(GL_SMOOTH); glClearColor(0.0, 0.0, 0.0, 0); glClearDepth(1.0); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);}
void GLWidget::paintGL(){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity(); glRotatef(rotate_angle, -0.2f, 0.2f, -0.3f); glBegin(GL_QUADS); glTexCoord2f(0.0, 1.0); glVertex3f(-0.3f, 0.3f, -0.3f); glTexCoord2f(0.0, 0.0); glVertex3f(-0.3f, 0.3f, 0.3f); glTexCoord2f(1.0, 0.0); glVertex3f(0.3f, 0.3f, 0.3f); glTexCoord2f(1.0, 1.0); glVertex3f(0.3f, 0.3f, -0.3f); glTexCoord2f(0.0, 1.0); glVertex3f(-0.3f, -0.3f, -0.3f); glTexCoord2f(0.0, 0.0); glVertex3f(-0.3f, -0.3f, 0.3f); glTexCoord2f(1.0, 0.0); glVertex3f(0.3f, -0.3f, 0.3f); glTexCoord2f(1.0, 1.0); glVertex3f(0.3f, -0.3f, -0.3f); glTexCoord2f(0.0, 1.0); glVertex3f(-0.3f, 0.3f, 0.3f); glTexCoord2f(0.0, 0.0); glVertex3f(-0.3f, -0.3f, 0.3f); glTexCoord2f(1.0, 0.0); glVertex3f(0.3f, -0.3f, 0.3f); glTexCoord2f(1.0, 1.0); glVertex3f(0.3f, 0.3f, 0.3f); glTexCoord2f(0.0, 1.0); glVertex3f(0.3f, 0.3f, 0.3f); glTexCoord2f(0.0, 0.0); glVertex3f(0.3f, -0.3f, 0.3f); glTexCoord2f(1.0, 0.0); glVertex3f(0.3f, -0.3f, -0.3f); glTexCoord2f(1.0, 1.0); glVertex3f(0.3f, 0.3f, -0.3f); glTexCoord2f(0.0, 1.0); glVertex3f(-0.3f, 0.3f, -0.3f); glTexCoord2f(0.0, 0.0); glVertex3f(0.3f, 0.3f, -0.3f); glTexCoord2f(1.0, 0.0); glVertex3f(0.3f, -0.3f, -0.3f); glTexCoord2f(1.0, 1.0); glVertex3f(-0.3f, -0.3f, -0.3f); glTexCoord2f(0.0, 1.0); glVertex3f(-0.3f, 0.3f, -0.3f); glTexCoord2f(0.0, 0.0); glVertex3f(-0.3f, -0.3f, -0.3f); glTexCoord2f(1.0, 0.0); glVertex3f(-0.3f, -0.3f, 0.3f); glTexCoord2f(1.0, 1.0); glVertex3f(-0.3f, 0.3f, 0.3f); rotate_angle -= 3; glEnd();}
void GLWidget::resizeGL(int width, int height){ if(0 == height) height = 1; glViewport(0, 0, (GLint)width, (GLint)height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity();
}void GLWidget::keyPressEvent(QKeyEvent *e){ switch(e->key()) { case Qt::Key_F1: fullscreen = !fullscreen; if(fullscreen) showFullScreen(); else { setGeometry(300, 150, 500, 500); showNormal(); } updateGL(); break; case Qt::Key_Escape: close(); }}
void GLWidget::loadTextures(){ QImage tex, buf; if(!buf.load("../opengl_nehe_05/cherry.jpg")) { qWarning("Cannot open the image..."); QImage dummy(128, 128, QImage::Format_RGB32); dummy.fill(Qt::green); buf = dummy; } tex = convertToGLFormat(buf); glGenTextures(1, &texture[0]); glBindTexture(GL_TEXTURE_2D, texture[0]); glTexImage2D(GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);}
GLWidget::~GLWidget(){ delete ui;}

  總結:

  了解了opengl中的紋理映射機制後,對空間體的表面進行貼圖還是比較方便的。

 

   參考資料:

   http://nehe.gamedev.net/ 

   http://www.owlei.com/DancingWind/

   http://blog.csdn.net/qp120291570/article/details/7853513

     http://www.qiliang.net/old/nehe_qt/

 

相關焦點

  • OpenGL 學習系列 --- 紋理
    接下來探索紋理了。紋理,簡單的理解就是一副圖像。而把一副圖像映射到圖形上的過程,叫做紋理映射。比如有如下圖形和三角形,想要把圖形中的一部分映射到三角形上。這就是紋理映射的一個小小例子。基本原理要注意到,OpenGL 繪製的物體是 3D 的,而紋理是 2D 的,那麼紋理映射就是將 2D 的紋理映射到 3D 的物體上,可以想像成用一張紙裹著一個物體一樣,不過要按照一定規律來。
  • UE4精品課程 | OpenGL學習筆記(五)紋理
    >為了能夠把紋理映射(Map)到三角形上,我們需要指定三角形的每個頂點各自對應紋理的哪個部分;這樣每個頂點就會關聯著一個紋理坐標,用來標明該從紋理圖像的哪個部分採樣,之後在圖形的其它片段上進行片段插值(Fragment Interpolation);紋理坐標在x和y軸上,範圍為0到1之間(2D紋理圖像);使用紋理坐標獲取紋理顏色叫做採樣(Sampling
  • 音視頻開發之旅(12) OpenGL ES之紋理
    圖片坐標系的(0,0)在圖片左上角,紋理坐標的(0,0)在紋理左下角紋理映射為了能夠把紋理映射(Map)到三角形上,我們需要指定三角形的每個頂點各自對應紋理的哪個部分。這樣每個頂點就會關聯著一個紋理坐標(Texture Coordinate),用來標明該從紋理圖像的哪個部分採樣。
  • 【GAMES101-現代計算機圖形學課程筆記】Lecture 09 Shading 3 (紋理映射)
    這樣一來,比如A紋理原來的大小是100x100,B紋理原來的大小是20x20,很顯然映射後A所對應的紋理平面的紋理會更密集,而B則會相對稀疏。Texture Coordinates本節內容概要:重心坐標(barycentric coordinates)1.
  • 計算機圖形學:紋理映射(Texture Mapping)及Mipmap技術
    紋理映射及Mipmap技術在本篇文章中,我們會具體的討論如何利用紋理映射讓場景擁有豐富的顏色信息,以及紋理貼圖精度大小所帶來的問題
  • OpenGL-點光源陰影
    幀緩衝對象和立方體貼圖的處理看起是這樣的:// 1. first render to depth cubemapglViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);glClear(GL_DEPTH_BUFFER_BIT);
  • ps之漸變映射講解10
    大家好,今天小編帶大家學習一哈ps中漸變映射知識學習。1.漸變映射是對圖片的明暗進行黑白的映射。亮部區域變成2.新建圖層,在圖層中新建漸變映射,調出控制面板3.可以調出漸變編輯器進行調節4.也可以點擊漸變編輯器中「預設」後面的小箭頭調出更為細緻的調試界面進行調試5.反向可以使一張彩色的圖片變成黑白照片
  • R語言可視化學習筆記之gganimate包
    它在ggplot2的基礎上了補充了一個美學映射frame,就像x,y,size,color,fill一樣進行映射。安裝if(!frame,這也符合我們的直覺,但是這並不意味著我們只能將時間映射給frame,我們可以將任何想要的變量映射給frame。
  • 如何做好學習筆記
    學習方法,這是無數同學思考的問題,然而並沒有一套放之四海而皆準的學習方法,每個人都有一套屬於自己的學習方法,但效果好不好就因人而異了,今天我們分享一個學習方法:做筆記。學習筆記是無數同學和老師經常強調的方法,然而很多同學並不會做學習筆記,很多時候被筆記帶偏,反而影響學習,拉低自己的分數。如何做筆記才是正確的姿勢呢?我們看一看不正確的筆記方法就知道如何做筆記了。1.整節課都在記筆記
  • 學習方法——提高課堂學習效率之正確記錄和使用「課堂筆記」
    學習方法——提高課堂學習效率之提高「聽課」效率),今天從「課堂筆記」角度講述提高課堂學習效率,本文主要包含「記錄筆記」和「正確使用筆記」兩個方面。一、為什麼要記筆記課堂學習是整個學習過程中最重要的部分,沒有之一。
  • 腦島解剖學習筆記
    學習筆記 | 神經外科手術畫線腦靜脈解剖與數字「3」的不解之緣腦動脈解剖提綱學習簡圖學習頭皮及顱底的孔與裂腦膜解剖學習之——軟腦膜翼顎窩骨性結構圖解腦池的解剖知識總結如何在MRI上準確辨識腦幹重要橫斷面腦幹內非顱神經核之「中繼核」學習總結顱神經和顱神經核的功能解剖學習筆記
  • OpenGL ES 真的無所不能嗎
    大頭小頭效果舊文中我們知道,利用 OpenGL 紋理映射(紋理貼圖)的基本原理,可以很輕易的實現對圖像指定的區域進行拉伸和縮放。典型的紋理映射著色器。 float;layout(location = 0) out vec4 outColor;in vec2 v_texCoord;uniform sampler2D s_TextureMap;void main() {    outColor = texture(s_TextureMap, v_texCoord);}舊文中,紋理映射都是發生在規則的矩形區域
  • Substance Painter入門學習筆記 (2)
    【學習】操作三 做舊現實世界的物品沒有完美的,基本上都有破損、掉漆或者有灰、劃痕等現象。用Substance Painter製作這些東西,很容易。1、點擊油漆那層,添加一個白色MASK遮罩。添加之後沒有反應啊?
  • 最美學習筆記來襲!感受筆尖上的浙大範兒!
    最美學習筆記來襲!感受筆尖上的浙大範兒!第二屆浙大最美學習筆記大賽上,50份優秀學子的筆記成功入圍,來一睹學霸們筆記的風採吧!前方多圖來襲!來源:杭州發布抖音號01包潔婷 求是學院紫雲碧峰學園
  • 筆記在英語學習中的重要性與記筆記的方法
    記筆記是學生在學習過程中養成的良好習慣。它不僅在平時的研究中起著重要的作用,而且在複習階段也起著重要的作用。那麼,如果筆記學習風格,在英語學習中使用,會起到什麼作用呢?學生在做筆記時,應該注意什麼?接下來,我會詳細解釋給你聽。
  • 學習英語怎麼樣記錄筆記?
    每一個科目的學習過程中都需要記筆記。學習筆記的正確使用是可以幫助我們在學習上提高效率的。英語的學習更需要記錄筆記了。英語做為一種另外的語言,想要學習好,更需要有效的記錄筆記來幫我們提高學習效率。而我提倡的記錄筆記的方法就是多管齊下的方法。
  • 靈芝:拉丁舞學習筆記之-倫巴基本步練習方法
    本文轉載自【微信公眾號:靈芝的心靈舞蹈成長營,ID:lzwd221】經微信公眾號授權轉載,如需轉載與原文作者聯繫今天,我們對學習倫巴、恰恰舞的練習方式做一個簡單的理解和認識我們在學習倫巴舞時,不要一上來就想著學擺蕩,學放胯,這樣容易導致姿態歪斜、軸心不穩,破壞了最基本舞蹈姿態的美感。
  • 大咖說|Shader知識普及之:材質貼圖紋理的區別
    在3D世界中,我們經常會聽到諸如材質、貼圖、紋理等名詞,給人感覺都是用於呈現物體表面的外觀效果又好像三者之間存在著某些關聯,本文我們一起來了解一下
  • 《Unity Shader入門精要》筆記(八)
    本文為《Unity Shader入門精要》第七章內容《基礎紋理》下部分的筆記。
  • 2021初中生物學習方法:做筆記
    中考網整理了關於2021初中生物學習方法:做筆記,希望對同學們有所幫助,僅供參考。   魯迅先生說:「無論什麼事,如果繼續收集資料,積累十年,總可以成為一個學者。」總結中外許多學者的經驗,可以說,做筆記是一條成才的途徑。做筆記的方式很多,在生物學學習中,主要有閱讀筆記、聽講筆記和觀察筆記三種。