04-OpenGL渲染基礎(chǔ)

目標:

  • 掌握OpenGL渲染架構(gòu)圖
  • 理解OpenGL數(shù)據(jù)傳遞的三種方式
  • 掌握OpenGL提供的存儲著色器
  • 正投影 / 透視投影API的使用
  • OpenGL常見圖元

一、OpenGL渲染架構(gòu)圖

OpenGL渲染架構(gòu)圖(轉(zhuǎn)自簡書:凡幾多)
  • attribute 屬性(頂點著色器/不能直接傳遞到片元著色器,通過GLSL代碼間接傳遞)

    • 顏色數(shù)據(jù)
    • 頂點數(shù)據(jù)
    • 紋理坐標
    • 光照計算表面法線
  • uniforms 值(直接傳遞到片元著色器/頂點著色器)

    • 傳遞不怎么改變的值
  • texture Data 紋理數(shù)據(jù)

    • 在頂點著色器、片段著色器中都可以對紋理數(shù)據(jù)進行采樣和篩選。
    • 典型的應(yīng)用場景:片段著色器對一個紋理值進行采樣,然后在一個三角形表面應(yīng)用渲染紋理數(shù)據(jù)。
    • 紋理數(shù)據(jù),不僅僅表現(xiàn)在圖形,很多圖形文件格式都是以無符號字節(jié)(每個顏色通道8位)形式對顏色分量進行存儲的。

二、固定管線著色器

使用存儲著色器最方便之處是,你不要考慮到渲染中到底是頂點著色器還是片元著色器.所以你在使用存儲著色器時,不需要思考傳遞數(shù)據(jù)時,該有那種方式傳送.你只需要傳遞不同存儲器所需要的數(shù)據(jù)到參數(shù)列表就可以了. 至于它的底層是如何實現(xiàn)的,并不需要關(guān)心.因為這一切它已經(jīng)封裝起來了.

固定管線著色器都是用UserStockShader函數(shù)調(diào)用

存儲著色器初始化

// GLShaderManager 的初始化 GLShaderManager shaderManager;
shaderManager.InitializeStockShaders();
  • 單元著色器
GLShaderManager::UserStockShader(GLT_SHADER_FLAT,GLfloat mvp[16],GLfloat vColor[4]);

參數(shù)1: 存儲著色器種類-平?著?器 
參數(shù)2: 允許變化的4*4矩陣
參數(shù)3: 顏?
使?用場景: 在繪制圖形時, 可以應(yīng)用變換(模型/投影變化).
  • 平面著色器
GLShaderManager::UserStockShader(GLT_SHADER_FLAT,GLfloat mvp[16],GLfloat vColor[4]);

參數(shù)1: 存儲著?器種類-平?著?器
參數(shù)2: 允許變化的4*4矩陣
參數(shù)3: 顏?
使?場景: 在繪制圖形時, 可以應(yīng)用變換(模型/投影變化).
  • 上色著色器
GLShaderManager::UserStockShader(GLT_SHADER_SHADED,GLfloat mvp[16]);

參數(shù)1:存儲著色器種類 - 上色著色器
參數(shù)2:允許變化的4*4矩陣
使用場景: 在繪制圖形時, 可以應(yīng)?變換(模型/投影變化) 
顏色將會平滑地插入到頂點之間 稱為平滑著?色.
  • 默認光源著色器
GLShaderManager::UserStockShader(GLT_SHADER_DEFAULT_LIGHT,GLfloat mvMatrix[16],GLfloat pMatrix[16],GLfloat vColor[4]);

參數(shù)1: 存儲著色器種類-默認光源著色器 
參數(shù)2: 模型4*4矩陣
參數(shù)3: 投影4*4矩陣
參數(shù)4: 顏?值
使?場景: 在繪制圖形時, 可以應(yīng)用變換(模型/投影變化) 
這種著?色器器會使繪制的圖形產(chǎn)生陰影和光照的效果.
  • 點光源著色器
GLShaderManager::UserStockShader(GLT_SHADER_POINT_LIGHT_DIEF,GLfloat mvMatrix[16],GLfloat pMatrix[16],GLfloat vLightPos[3],GLfloat vColor[4]);

參數(shù)1: 存儲著色器種類-點光源著?器 
參數(shù)2: 模型4*4矩陣
參數(shù)3: 投影4*4矩陣
參數(shù)4: 點光源的位置
參數(shù)5: 漫反射顏?值
使用場景: 在繪制圖形時, 可以應(yīng)用變換(模型/投影變化) 
這種著?器會使繪制的圖形產(chǎn)? 陰影和光照的效果.
它與默認光源著色器非常類似,區(qū)別只是光源位置可能是特定的.
  • 紋理替換矩陣著色器
GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_REPLACE,GLfloat mvMatrix[16],GLint nTextureUnit);

參數(shù)1: 存儲著?器種類-紋理替換矩陣著色器 
參數(shù)2: 模型4*4矩陣
參數(shù)3: 紋理單元
使?場景: 在繪制圖形時, 可以應(yīng)用變換(模型/投影變化)
這種著?器通過給定的模 型視圖投影矩陣.
使用紋理單元來進行顏?填充.其中每個像素點的顏?是從紋理中 獲取.
  • 紋理調(diào)整著色器
GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_MODULATE,GLfloat mvMatrix[16],GLfloat vColor[4],GLint nTextureUnit);

參數(shù)1: 存儲著?器種類-紋理調(diào)整著色器
參數(shù)2: 模型4*4矩陣
參數(shù)3: 顏?值
參數(shù)4: 紋理單元
使?場景: 在繪制圖形時, 可以應(yīng)用變換(模型/投影變化)
這種著?器通過給定的模型視圖投影矩陣. 
著色器將?個基本?乘以?個取自紋理單元nTextureUnit 的紋理.將顏色與紋理進行顏色混合后才填充到?段中.
  • 紋理光源著色器
GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIEF,G Lfloat mvMatrix[16],GLfloat pMatrix[16],GLfloat vLightPos[3],GLfloat vBaseColor[4],GLint nTextureUnit);

參數(shù)1: 存儲著?器種類-紋理光源著色器 
參數(shù)2: 模型4*4矩陣
參數(shù)3: 投影4*4矩陣
參數(shù)4: 點光源位置
參數(shù)5: 顏色值(?何圖形的基本色) 
參數(shù)6: 紋理單元
使?場景: 在繪制圖形時, 可以應(yīng)用變換(模型/投影變化)
這種著色器通過給定的模型視圖投影矩陣. 
著?器將?個紋理通過漫反射照明計算進行調(diào)整(相乘).

三、OpenGL 7種基本圖元

名稱 圖元 解釋
GL_POINTS 每個頂點在屏幕上都是單獨點
GL_LINES 每一對頂點定義一個線段
條帶線 GL_LINE_STRIP 一個從第?個頂點依次經(jīng)過每?個后續(xù)頂點?而繪制的線條
循環(huán)線 GL_LINE_LOOP 和GL_LINE_STRIP相同,但是最后?個頂點和第?個頂點連接起來了了
獨立三角形 GL_TRIANGLES 每3個頂點定義一個新的三?角形
三角形條帶 GL_TRIANGLE_STRIP 共?用一個條帶(strip)上的頂點的一組三?角形
三角形扇形面 GL_TRIANGLE_FAN 以一個圓點為中?心呈扇形排列列,共?用相鄰頂點的一組三?角形
基本圖元.png

1. 點和線

  • (1) 點
    點 是最簡單的圖像。每個特定的頂點在屏幕上都僅僅是一個單獨的點。默認的情況下,點的大小是一個像素的大小。我們可通過調(diào)用glPointSize改變默認點的大?。?/li>
void glPointSize(GLfloat size);
//  1.最簡單也是最常用的 4.0f,表示點的大小
glPointSize(4.0f);
    
// 2.設(shè)置點的大小范圍和點與點之間的間隔
GLfloat sizes[2] = {2.0f,4.0f};
GLfloat step = 1.0f;

// 3.獲取點大小范圍和最小步長(增量)
glGetFloatv(GL_POINT_SIZE_RANGE,sizes);
glGetFloatv(GL_POINT_GRAULARITY,&step); 

// 4.通過使用程序點大小模式來設(shè)置點大小
glEnable(GL_PROGRAM_POINT_SIZE);

// 5.這種模式下允許我們通過編程在頂點著色器或幾何著色器中設(shè)置點大小。著色器內(nèi)建變量:gl_PointSize,并且可以在著色器源碼直接寫
 gl_PointSize = 5.0;
  • (2) 線
    比點更進一步的是獨立線段。一個線段就是2個頂點之間繪制的。
    默認情況下,線段的寬度是一個像素。改變線段唯一的方式是使用函數(shù)glLineWidth:
void glLineWidth(GLfloat width);
// 設(shè)置獨立線段寬度為1.5f;
glLineWidth(1.5f);
  • (3) 線帶
    線段連續(xù)從一個頂點到下一個頂點繪制的線段,以形成一個真正鏈接的點的線段。
    (為了把圖形連接起來,每個連接的頂點會被選定2次。一次作為線段的終點、一次作為下一條線段的起點)

  • 線環(huán)(line loop)
    是線帶的一種簡單拓展,在線帶的基礎(chǔ)上額外增加一條將線帶閉合。

2. 繪制三角形

(1)單獨的三角形

可能存在的最簡單的實體多邊形就是三角形,它只有3個邊。光柵化硬件最歡迎三角形。并且現(xiàn)在OpenGL已經(jīng)是OpenGL中支持的唯一一種多邊形。每3個頂點定義一個新的三角形。

繪制三角形

(2)環(huán)繞

在繪制第一個三角形時,線條是按照從V0-V1,再到V2。最后再回到V0的一個閉合三角形。
這種順序與方向結(jié)合來指定頂點的方式稱為環(huán)繞。

下圖的2個三角形的環(huán)繞方向完全相反。

三角形環(huán)繞方式

正面與背面:

在默認的情況下,OpenGL認為具有逆時針方向環(huán)繞的多邊形是正面的。而右側(cè)的順時針方向三角形是三角形的背面

//定義前向和背向的多變形:
glFrontFace(mode)
參數(shù):GL_CW | GL_CCW
GL_CCW:表示傳入的mode會選擇逆時針為前向
GL_CW:表示順時針為前向。
默認:GL_CCW 逆向時針為前向。

(3)三角地帶

對于很多表面和形狀來說,我們可能需要繪制幾個相連的三角形。我們可以使
GL_TRIANGLE_STRIP圖元繪制一串相連的三角形。

三角地帶

使用三角帶而不是分別指定每個三角形,這樣做的優(yōu)點:

    1. 用前3個頂點指定第1個三角形之后,對于接下來的每一個三角形,只需要再指定1個頂點。需要繪制大量的三角形時,采用這種方法可以節(jié)省大量的程序代碼和數(shù)據(jù)存儲空間。
  • 2 .提供運算性能和節(jié)省帶寬。更少的頂點意味著數(shù)據(jù)從內(nèi)存?zhèn)鬏數(shù)綀D形卡的速度更快,并且頂點著色器需要處理的次數(shù)也更少了。

(4)三角形扇

除了三角形帶之外,還可以使用GL_TRIANGLE_FAN創(chuàng)建一組圍繞一個中心點的相連三角形。
通過4個頂點所產(chǎn)生的包括3個三角形的三角形扇。 第一個頂點v0構(gòu)建了扇形的原點,用前3個頂點指定了最初的三角形之后,后續(xù)的每個頂點都和原點(V0)以及之前緊挨著它的那個頂點(Vn-1)形成接下來的三角形。

三角形扇

四、簡單的批次容器

GLTools 庫中包含額一個簡單的容器類,叫做GLBatch。這個類可以作為7種圖元的簡單批次容器使用。而且它知道在使用GL_ShaderManager支持的任意存儲著色器時如何對圖元進行渲染。

//首先對批次進行初始化,告訴這個類它代表哪種圖元,其中包括的頂點數(shù),以及(可選)一組或兩組紋理坐標。
void GLBatch::Begain(GLeunm primitive,GLuint nVerts,GLuint nTexttureUnints = 0);
/*
參數(shù)1:圖元
參數(shù)2:頂點數(shù)
參數(shù)3:一組或者2組紋理坐標(可選)
*/
//復制表面法線
void GLBatch::CopyNormalDataf(GLfloat *vNorms);

//復制顏色
void GLBatch::CopyColorData4f(GLfloat *vColors);

//復制紋理坐標
void GLBatch::CopyTexCoordData2f(GLFloat *vTextCoords,GLuint uiTextureLayer);

//結(jié)束繪制
void GLBatch::End(void);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容