1. 程式人生 > >OpenGL學習腳印: 模型變換(model transformation)

OpenGL學習腳印: 模型變換(model transformation)

寫在前面
前面為本節內容準備了向量和矩陣線性變換等內容,本節開始學習OpenGL中的座標處理。OpenGL中的座標處理過程包括模型變換、視變換、投影變換、視口變換等內容,這個主題的內容有些多,因此分節學習,主題將分為5節內容來學習。本節主要學習模型變換。本節示例程式碼均可在我的github處下載。

通過本節可以瞭解到

  • 模型變換的作用
  • 模型變換的型別和計算方法

座標處理的全域性過程(瞭解,另文詳述)

OpenGL中的座標處理包括模型變換、視變換、投影變換、視口變換等內容,具體過程如下圖1所示:

座標變換
每一個過程處理都有其原因,這些內容計劃將會在不同節裡分別介紹,最後再整體把握一遍。
今天我們學習第一個階段——模型變換。

為什麼需要模型變換

我們在OpenGL中通過定義一組頂點來定義一個模型,或者通過其他3D建模軟體事先建好模型然後匯入到OpenGL中。頂點屬性定義了模型。如果我們要在一個場景中不同位置顯示同一個模型怎麼辦? 如果我們要以不同的比例、不同角度顯示同一個模型又怎麼辦 ?
如果繼續以類似的頂點屬性資料定義同一個模型,調整它滿足上述需求的話,不僅浪費顯示卡記憶體,而且這個調整的工作量也很大,因此效率很低。更好地解決方法是,我們定義的模型根據需要可以執行放大、縮小等操作來不同比例顯示,可以通過平移來放在不同位置,可以通過旋轉來按不同角度顯示。這種方式就是執行模型變換。
模型變換通過對模型執行平移(translation)、縮放(scale)、旋轉(rotation)、映象(reflection)、錯切(shear)等操作,來調整模型的過程。通過模型變換,我們可以按照合理方式指定場景中物體的位置等資訊。

平移變換

平移就是將物體從一個位置p=(x,y,z),移動到另一個位置p=(x,y,z)的過程,記為p=p+d,其中d=(xx,yy,zz)=(tx,ty,tz)。使用齊次座標系表示為:

p=Tp=100001000010txtytz1xyz1=x+txy+tyz+tz1

如果對向量和矩陣不熟悉,可以回過去看前面介紹的向量和矩陣;如果對上面使用的齊次座標系不熟悉,可以回過去看前面介紹的線性變換部分。

本節的模型變換在OpenGL程式中,可以使用GLM數學庫實現。例如平移變換實現如下:

glm:
:mat4 model; // 構造單位矩陣 model = glm::translate(model, glm::vec3(-0.5f, 0.0f, 0.0f));

上述表示平移向量為(-0.5,0.0,0.0),得到一個平移矩陣儲存到model中。

在程式中我們繪製了4個矩形,通過平移將其放在不同位置,效果如下圖所示:
模型變換

在上圖示例中,我們使用不同的著色器還繪製了座標軸,座標軸通過箭頭和軸線繪製。在xoy座標系中,第一個象限為原圖,第二個象限為平移(-0.5,0.0,0.0)後的矩形,第三象限為平移(-0.8,-0.8,0.0)後的矩形,第四個象限為平移(0.0,-0.5,0.0)後的矩形。

注意 通過上面座標處理的全域性過程圖1可以看到,實際頂點輸出還需要經過視變換、投影變換過程等處理,本節主要討論模型變換,因此我們在程式碼中,不考慮視變換和投影變換,使用預設的視變換和投影變換,即這兩個變換保持為單位矩陣。預設的方式就是我們一直在使用的正交投影方式。變換矩陣在著色器中使用uniform變數傳遞,在c++程式中使用glm::mat4與之對應。對uniform變數不熟悉的話,可以回過頭去看2D紋理部分的使用方法。

設定預設視變換和投影變換矩陣的程式碼如下:

   glm::mat4 projection;// 投影變換矩陣
   glm::mat4 view; // 視變換矩陣
   glm::mat4 model; // 模型變換矩陣
   glUniformMatrix4fv(
     glGetUniformLocation(shader.programId,"projection"),
     1, GL_FALSE, glm::value_ptr(projection));  
  glUniformMatrix4fv(
    glGetUniformLocation(shader.programId,"view"),
    1,GL_FALSE, glm::value_ptr(view));

繪製四個矩形的程式碼為:

   // 繪製第一個矩形
   glUniformMatrix4fv(
    glGetUniformLocation(shader.programId, "model"),
    1, GL_FALSE, glm::value_ptr(model));
  glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);

  // 繪製第二個矩形
 model = glm::mat4();
 model = glm::translate(model, glm::vec3(-0.5f, 0.0f, 0.0f));
glUniformMatrix4fv(
    glGetUniformLocation(shader.programId, "model"),
     1, GL_FALSE, glm::value_ptr(model));
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);

// 繪製第三個矩形
model = glm::mat4();
model = glm::translate(model, glm::vec3(-0.8f, -0.8f, 0.0f));
glUniformMatrix4fv(
  glGetUniformLocation(shader.programId, "model"),   1, GL_FALSE, glm::value_ptr(model));
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);

// 繪製第四個矩形
model = glm::mat4();
model = glm::translate(model, glm::vec3(0.0f, -0.5f, 0.0f));
glUniformMatrix4fv(
    glGetUniformLocation(shader.programId, "model"),1, GL_FALSE, glm::value_ptr(model));
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);

這裡繪製矩形使用的頂點屬性資料,以及紋理使用方法,可以回過頭去檢視上一節2D紋理對映內容。
本節繪製矩形的頂點著色器中都使用程式碼:

#version 330

layout(location = 0) in vec3 position;
layout(location = 1) in vec3 color;
layout(location = 2) in vec2 textCoord;

out vec3 VertColor;
out vec2 TextCoord;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

void main()
{
     gl_Position = 
     projection * view * model * vec4(position, 1.0);
     VertColor = color;
     TextCoord = textCoord;
}

本節繪製矩形的片元著色器中都使用程式碼:

#version 330

in vec3 VertColor;
in vec2 TextCoord;

uniform sampler2D tex;

out vec4 color;


void main()
{
  color = texture(tex, vec2(TextCoord.s, 1.0 -TextCoord.t) );
}

程式碼中使用座標vec2(TextCoord.s, 1.0 -TextCoord.t)表示將紋理的y軸翻轉,避免紋理倒立顯示。
座標和變換的數學基礎一節中,我們已經提到,對於4x4仿射變換矩陣,可以表示平移(仿射變換)、縮放、旋轉等線性變換,其中矩陣的形式為:
仿射變換
記住這一點,對於矩陣形式理解會比較清楚。

縮放變換

縮放可以沿著三個座標軸的方向獨立進行,當縮放參數一致時是均勻縮放,否則是非均勻縮放。對於以原點為中心的縮放來講,根據座標和變換的數學基礎,一節所得到的結論:線性變換矩陣為變換後基向量組成。縮放因子為(sx,sy,sz),則得到縮放後的+x軸基向量為(sx,0,0),+y軸基向量為(0,sy,0),+z軸縮放後基向量為(0,0,sz),由這些基向量組成的縮放矩陣的前三列,構成4x4矩陣後表示為:

p=Sp=sx0000sy0000sz00001

相關推薦

OpenGL學習腳印: 模型變換(model transformation)

寫在前面 前面為本節內容準備了向量和矩陣、線性變換等內容,本節開始學習OpenGL中的座標處理。OpenGL中的座標處理過程包括模型變換、視變換、投影變換、視口變換等內容,這個主題的內容有些多,因此分節學習,主題將分為5節內容來學習。本節主要學習模型變

OpenGL學習腳印:模型載入初步-載入obj模型(load obj model)

寫在前面 前面介紹了光照基礎內容,以及材質和lighting maps,和光源型別,我們對使用光照增強場景真實感有了一定了解。但是到目前為止,我們通過在程式中指定的立方體資料,繪製立方體,看起來還是很乏味。本節開始介紹模型載入,通過載入豐富的模型,能夠豐富我們

OpenGL學習腳印: 投影矩陣和視口變換矩陣(math-projection and viewport matrix)

寫在前面 前面幾節分別介紹了模型變換,視變換,本節繼續學習OpenGL座標變換過程中的投影變換。這裡主要是從數學角度推導投影矩陣。對數學不感興趣的,可以稍微瞭解下,或者跳過本節內容。 ,這裡對他的推導思路稍微進行了整理。 通過本節可以瞭解到 透

OpenGL學習腳印:Blinn-Phong光照模型

寫在前面 在前面基礎光照部分,我們學習了Phong Shading模型,Blinn-Phong模型對Phong模型的鏡面光成分進行了改進,雖然在物理上解釋沒有Phong好,但是能更好地模擬光照。本節程式碼可以在我的github下載。 Phong不

OpenGL學習腳印:模板測試(stencil testing)

寫在前面 上一節介紹了深度測試,本節繼續學習一個高階主題-模板測試(stencil testing)。模板緩衝同之前介紹的顏色緩衝、深度緩衝類似,通過它我們可以實現很多的特效,例如輪廓、鏡面效果,陰影效果等。本節示例程式均可以從我的github下載。 通過本

OpenGL學習腳印: 反走樣初步(Anti-aliasing basic)

寫在前面 目前,我們繪製的圖形中存在瑕疵的,觀察下面這個立方體: 仔細看,立方體的邊緣部分存在折線,如果我們放大了看,則可以看到這種瑕疵更明顯: 這種繪製的物體邊緣部分出現鋸齒的現象稱之為走樣(aliasing)。反走樣(Anti-

OpenGl 學習——三種變換的理解

    剛開始學OpenGL, 沒有認真看書,結果似懂非懂,其實一點都沒有搞懂,尤其是被裡面的各種變換搞得暈來轉去的。沒辦法,反覆的讀《OpenGL 程式設計指南》紅寶書中關於變換的章節,終於有了點眉目了。瞬間感覺:啊,世界變得清明瞭許多!     廢話不多說,直接切入正題

OpenGL學習腳印:立方體紋理和天空包圍盒(Cubemaps And Skybox)

寫在前面 之前學習了2D紋理對映,實際上還有其他型別的紋理有待我們進一步學習,本節將要學習的立方體紋理(cubemaps),是一種將多個紋理圖片複合到一個立方體表面的技術。在遊戲中應用得較多的天空包圍盒可以使用cubemap實現。本節示例程式均可

OpenGL學習腳印: 二維紋理對映(2D textures)

寫在前面 前面兩節介紹了向量和矩陣,以及座標和轉換相關的數學,再繼續討論模型變換等其他包含數學內容的部分之前,本節介紹二維紋理對映,為後面學習做一個準備。紋理對映本身也是比較大的主題,本節只限於討論二維紋理的基本使用,對於紋理對映的其他方法,後面會繼續

OpenGL學習腳印:深度測試(depth testing)

寫在前面 上一節我們使用AssImp載入了3d模型,效果已經令人激動了。但是繪製效率和場景真實感還存在不足,接下來我們還是要保持耐心,繼續學習一些高階主題,等學完後面的高階主題,我們再次來改進我們載入模型的過程。本節將會學習深度測試,文中示例程式原始碼均可

OpenGL學習腳印:背面剔除(Face Culling)

寫在前面 在繪製封閉型別的幾何物件時,開啟背面剔除功能能夠提高渲染效能。本節簡要介紹下背面剔除,示例程式可以在我的github下載。 什麼是背面剔除 當我們觀察場景中物件時,一般只能以一定角度來觀察,那麼物件的某些面我們是看不到的,例如你觀察一個立

OpenGL學習腳印:建立更多的例項(instancing object)

寫在前面 前面我們學習了模型載入的相關內容,併成功載入了模型,令人十分興奮。那時候載入的是少量的模型,如果需要載入多個模型,就需要考慮到效率問題了,例如下圖所示的是載入了400多個納米戰鬥服機器人的效果圖: 渲染一個模型更多的例項,需要使用到例項

OpenGL學習腳印: 繪製一個三角形

寫在前面 接著上一節內容,開發環境搭建好後,我們當然想立即編寫3D應用程式了。不過我們還需要些耐心,因為OpenGL是一套底層的API,因而我們要掌握的基本知識稍微多一點,在開始繪製3D圖形之前,本節我們將通過繪製一個三角形的程式來熟悉現代Op

OpenGL學習腳印:幾何著色器(geometry shader)

寫在前面 一直以來我們使用了頂點著色器(vertex shader)和片元著色器(fragment shader),實際上OpenGL還提供了一個可選的幾何著色器(geometry shader)。幾何著色器位於頂點和片元著色器之間,如果沒有使用時,則

OpenGl學習筆記3之模型變換、檢視變換、投影變換、視口變換介紹

模型變換、檢視變換、投影變換、視口變換介紹 opengl中存在四種變換,分別是模型變換,檢視變換,投影變換,視口變換。這四種變換是圖形渲染的基本操作,實質上這四種變換都是由矩陣乘法表示(這些操作都是由一個4*4的矩陣來完成的),通過變換,我們可以看到各種通的顯示效果,最簡單

斯坦福大學公開課機器學習:Neural network-model representation(神經網絡模型及神經單元的理解)

如何 work 單元 pre 結果 mda s函數 額外 權重 神經網絡是在模仿大腦中的神經元或者神經網絡時發明的。因此,要解釋如何表示模型假設,我們先來看單個神經元在大腦中是什麽樣的。如下圖,我們的大腦中充滿了神經元,神經元是大腦中的細胞,其中有兩點值得我們註意,一是神經

Django學習(2)-- 模型Model

ORM框架是python中內建的框架,它的作用就是能夠讓我們通過對這個框架的操作就能完成對資料庫的操作。 O(object)代表的是類物件的意思; R(relation)代表的是資料庫中資料表的意思; M(mapping)代表對映的意思。 在ORM框架,它能讓我們通過對類和類物件的操作就能完成資料庫中

opengl學習筆記(三)——玩弄模型(使用者互動)

經過前面兩節的功夫,我們算是搞到了一個還算可以的模型,但我們想要把模型翻來翻去,移動一下還是不行的。並且,根據使用者(老師)需求,我們要讓模型能以線框,點的方式繪製。也就有了這最後一講。 首先,我們通過滑鼠左鍵來旋轉物體。這就需要在滑鼠回撥函式裡下功夫了 if (state == GLUT_DO

opengl學習筆跡——讀取ply檔案並繪製模型

首先要做的是讀取ply檔案,我們開啟notepad++檢視ply檔案可以看到如上格式。有用的是第四行的37702代表頂點數量,11行的75404,代表面數。所以我們設定瞭如下的讀取程式碼(非常地暴力) char ch[50]; ifstream in("lizhenxiout

Angular JS1學習筆記之一ng-model模型

Angular JS ng-model指令 ng-model用於繫結應用程式(input、select、textarea)的資料到html的controller裡。 與ng-bind區別在於,input是用於使用者輸入的,資料要用ng-model從