坐標(biāo)系統(tǒng)

最近在學(xué)習(xí)OpenGL,把學(xué)習(xí)的一些過程寫在這里,希望與大家共同分享討論。歡迎光臨我的個人網(wǎng)站Orient.ren一起討論學(xué)習(xí)。這里是我的GitHub果您喜歡,不妨點個贊??

坐標(biāo)系統(tǒng)分為五大類:

局部空間(Local Space)或被稱為物體空間(Object Space)

指的是單個物體的坐標(biāo)系統(tǒng)。

世界空間(World Space)

指多個物體同時放在一個世界的坐標(biāo)系統(tǒng)。物體坐標(biāo)從局部空間變換到世界空間是由模型矩陣(Model Matrix)實現(xiàn)的。

模型矩陣:是一種變幻矩陣,它通過對物體進(jìn)行位移、縮放、旋轉(zhuǎn)來將它放置在預(yù)期的位置或朝向。

觀察空間(View Space)或被稱為視覺空間(Eye Space)、攝像機空間(Camera Space)

將世界空間坐標(biāo)轉(zhuǎn)化為用戶視野前方的坐標(biāo)而產(chǎn)生的結(jié)果。也就是從攝像機視角所觀察到的空間。通常由一系列的唯一和旋轉(zhuǎn)的組合來完成。

這些組合被存儲在一個觀察矩陣(View Matrix)里,它被用來將世界坐標(biāo)變幻到觀察空間坐標(biāo)。

裁剪空間(Clip Space)

將規(guī)定范圍之外的物體裁剪掉(不可視化)。它由投影矩陣(Projection Matrix)實現(xiàn)。

投影分為正射投影透視投影

創(chuàng)建正射投影矩陣可以用GLM的內(nèi)置函數(shù)glm::ortho:

/*p1、p2:指定了平截頭體的左右坐標(biāo),
 *p3、p4:制訂了平截頭體的底部和頂部,
 *p5、p6:定義了近平面和遠(yuǎn)平面的距離
 */
glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f);

創(chuàng)建透視投影矩陣可以用以下函數(shù)創(chuàng)建:

/*p1:定義了fov(視野:`Field of View`)的值,并且設(shè)置了觀察空間的大小,一般為了真實效果,設(shè)置為45.0f,
 *p2:設(shè)置寬高比,由視口寬除以高所得,
 *p3、p4:設(shè)置了平截頭體的近、遠(yuǎn)平面距離,通常按以下值設(shè)置。
 */
glm::nat4 proj = glm::perspective(glm::radians(45.0f), (float)width/(float)height, 0.1f, 100.0f);

屏幕空間(Screen Space)

屏幕空間也就是我們在屏幕上所能看見的一個窗口空間

一個物體的頂點坐標(biāo)起始于局部空間(Local Space),在這里被稱為局部坐標(biāo)(Local Coordinate),之后會變味世界坐標(biāo)(World Coordinate),觀察坐標(biāo)(View Coordinate),裁剪坐標(biāo)(Clip Coordinate),在最后以屏幕坐標(biāo)(Screen Coordinate)的形式結(jié)束

一個頂點坐標(biāo)將會根據(jù)以下過程變換到裁剪坐標(biāo):

V(clip) = M(projection) · M(view) · M(model) · V(local)

最后頂點應(yīng)該被賦值到頂點著色器中的gl_Position, OpenGL將會自動進(jìn)行透視除法裁剪將其變化到標(biāo)準(zhǔn)化設(shè)備坐標(biāo),然后通過glViewPort內(nèi)部的參數(shù)來將標(biāo)準(zhǔn)化設(shè)備坐標(biāo)映射到屏幕坐標(biāo)。

3D

模型矩陣

創(chuàng)建一個包含位移、縮放與旋轉(zhuǎn)的模型矩陣,將物體變換到全局的世界空間,下面這個模型矩陣使得物體繞x軸旋轉(zhuǎn),使它看起來像放在地上一樣:

glm::mat4 model;
model = glm::rotate(model, glm::radians(-55.0f), glm::vec3(1.0f, 0.0f, 0.0f));

觀察矩陣

創(chuàng)建一個觀察矩陣,將物體在場景里稍微后移,以使得物體變成可見的:

glm::mat4 view
view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f));

投影矩陣

最后定義一個投影矩陣,在這里使用透視投影:

glm::mat4 projection
projection = glm::perspective(glm::radians(45.0f), screenWidth / screenHeight, 0.1f, 100.0f);

申明uniform變換矩陣

創(chuàng)建變換矩陣后,將它們傳入著色器。首先申明一個uniform變換矩陣然后將它乘以頂點坐標(biāo):

#version 410 core
layout (location = 0) in vec3 aPos;
...
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
}

然后將矩陣傳入著色器(通常在每次的渲染迭代中進(jìn)行,因為變換矩陣會經(jīng)常變動):

int modelLoc = glGetUniformLocation(ourShader.ID, "model");
glUnifromMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
...
//觀察矩陣和投影矩陣類似

繪制旋轉(zhuǎn)的立方體

隨時間旋轉(zhuǎn)函數(shù):

model = glm::rotate(model, (float)glfwGetTime() * glm::radians(50.0f), glm::vec3(0.5, 1.0f, 0.0f));

使用glDrawArrays繪制立方體,總共36個頂點。

glDrawArrays(GL_TRIANGLES, 0, 36);

開始深度測試

z緩沖也叫深度緩沖(Depth Buffer),所有的深度信息都存儲在其中。OpenGL會根據(jù)深度值來判斷物體是否被遮擋,若是則丟棄。這個過程稱為深度測試(Depth Testing),開啟它需要添加以下函數(shù):

glEnable(GL_DEPTH_TEST);

在每次迭代前需要清除深度緩沖:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

繪制更多立方體

首先在一個glm::vec3數(shù)組中定義10個立方體位置:

glm::vec3 cubePositions[] = {
  glm::vec3( 0.0f,  0.0f,  0.0f), 
  glm::vec3( 2.0f,  5.0f, -15.0f), 
  glm::vec3(-1.5f, -2.2f, -2.5f),  
  glm::vec3(-3.8f, -2.0f, -12.3f),  
  glm::vec3( 2.4f, -0.4f, -3.5f),  
  glm::vec3(-1.7f,  3.0f, -7.5f),  
  glm::vec3( 1.3f, -2.0f, -2.5f),  
  glm::vec3( 1.5f,  2.0f, -2.5f), 
  glm::vec3( 1.5f,  0.2f, -1.5f), 
  glm::vec3(-1.3f,  1.0f, -1.5f)  
};

在渲染循環(huán)當(dāng)中調(diào)用glDrawArrays10次:

for (unsigned int i = 0; i < 10; i++) {
    // calculate the matrix for each object and pass it to shader before drawing
    glm::mat4 model;
    model = glm::translate(model, cubePositions[i]);
    float angle = 20.0f * (i + 1);
    model = glm::rotate(model, (float)glfwGetTime() * glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f));
    ourShader.setMat4("model", model);
    
    glDrawArrays(GL_TRIANGLES, 0, 36);
}

最終繪制效果如下:


動圖加載比較慢,請耐心等待
動圖加載比較慢,請耐心等待
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容