圖元

一、基礎(chǔ)管線

OpenGL 中圖元只不過是頂點(diǎn)的集合以預(yù)定義的方式結(jié)合在一起。
管線分為2個部分:上半部分是客戶機(jī)端,下半部分是服務(wù)器端。
服務(wù)器和客戶端是功能和運(yùn)行上都是異步的,它們是各自獨(dú)立的軟件或硬件塊。


  • 客戶端是存儲在 CPU 存儲器中的,并且在應(yīng)用程序中執(zhí)行,或者在主系統(tǒng)內(nèi)存的驅(qū)動程序中執(zhí)行。驅(qū)動程序會將渲染命令和數(shù)組組合起來,發(fā)送給服務(wù)器執(zhí)行?。ㄔ谝慌_典型的個人計(jì)算機(jī)上,服務(wù)器實(shí)際上就是圖形加速卡上的硬件和內(nèi)存)
  • 服務(wù)器和客戶機(jī)在功能上也是異步的。它們是各自獨(dú)立的軟件塊或硬件塊。我們是希望它們2個端都盡量在不停的工作??蛻舳瞬粩嗟陌褦?shù)據(jù)塊和命令塊組合在一起輸送到緩沖區(qū),然后緩沖區(qū)就會發(fā)送到服務(wù)器執(zhí)行。
  • 如果服務(wù)器停止工作等待客戶機(jī),或者客戶機(jī)停止工作來等待服務(wù)器做好接受更多的命令和準(zhǔn)備,我們把這種情況稱為管線停滯

二、著色器

渲染過程,必備的2個著色器“頂點(diǎn)著色器”和“片元著色器”。
上圖的Vertex Shader(頂點(diǎn)著?色器器) 和 Fragment Shader(?片段著?色器器)。

  • 著?器是使?GLSL編寫的程序,看起來與C語?非常類似。著?器必須從源代碼中編譯和鏈 接在?起。最終準(zhǔn)備就緒的著色器程序
  • 頂點(diǎn)著?器-->處理從客戶機(jī)輸?的數(shù)據(jù)、應(yīng)?變換、進(jìn)?其他的類型的數(shù)學(xué)運(yùn)算來計(jì)算光照效果、位移、顏?色值等等。(**為了渲染共有3個頂點(diǎn)的三角形,頂點(diǎn)著?器將執(zhí)?3次,也就是為了每個頂點(diǎn)執(zhí)行?次)在?前的硬件上有多個執(zhí)行單元同時運(yùn)行,就意味著所有的3個頂點(diǎn)可以同時進(jìn)行處理!
  • 圖上(primitive Assembly)說明的是:3個頂點(diǎn)已經(jīng)組合在一起,而三角形已經(jīng)逐個片段的進(jìn)行了光柵化。每個片段通過執(zhí)行 片元著色器 進(jìn)行填充。片元著色器會輸出我們將屏幕上看到的最終顏色值。

三、3種向 OpenGL 著色器傳遞渲染數(shù)據(jù)的方法

  • 屬性
  • Uniform
  • 紋理

3.1 屬性

屬性:就是對一個頂點(diǎn)都要作改變的數(shù)據(jù)元素。實(shí)際上,頂點(diǎn)位置本身就是一個屬性。屬性就可以浮點(diǎn)類型、整形、布爾類型。

  • 屬性總是以四維向量的形勢進(jìn)行內(nèi)部存儲的,即使我們不會使用所有的4個分量。一個頂點(diǎn)位置可能存儲 (x,y,z),將占有4個分量中的3個。
  • 實(shí)際上如果是在平面情況下:只要在 xy 平面上就能繪制,那么z分量就自動設(shè)置為0。
  • 屬性還可以是:紋理坐標(biāo)、顏色值、光照計(jì)算表面法線
  • 在頂點(diǎn)程序 (shader渲染)可以代表你想要的任何意義。因?yàn)槎际悄阍O(shè)定的。
  • 屬性會從本地客戶機(jī)內(nèi)存中復(fù)制在圖形硬件中的一個緩沖區(qū)上。這些屬性只提供給頂點(diǎn)著色器使用,對于片元著色器沒有太大意義。
  • 聲明 這些屬性對每個頂點(diǎn)都要作改變,但并不意味著它們的值不能重復(fù)。通常情況下,它們都是不一樣的,但有可能整個數(shù)組都是同一值的情況。

3.2 Uniform 值

通過設(shè)置 Uniform 變量就緊接著發(fā)送一個圖元批次命令。Uniform 變量實(shí)際上可以無限地使用,設(shè)置一個應(yīng)用于整個表面的單個顏色值。還可以設(shè)置一個時間值。在每次渲染某種類型的頂點(diǎn)動畫時修改它。

  • 注意 這里的 uniform 變量每個批次改變一次,而不是每個頂點(diǎn)改變一次。
  • uniform 變量最常見的應(yīng)用是在頂點(diǎn)渲染中設(shè)置變換矩陣
  • 與屬性相同點(diǎn):可以是浮點(diǎn)型、整數(shù)、布爾值
  • 與屬性不同點(diǎn):頂點(diǎn)著色器和片元著色器都可以使用 uniform 變量。uniform 變量還可以是標(biāo)量類型、矢量類型、uniform 矩陣。

3.3 紋理

簡單的說,紋理就是矩形的數(shù)據(jù)數(shù)組。例如顏色、亮度數(shù)據(jù)等,之所以復(fù)雜,是因?yàn)榫匦渭y理可以映射到非矩形的區(qū)域。

四、創(chuàng)建坐標(biāo)系

GLFrustum frustum;
void SetOrthographic(GLfloat xMin, GLfloat xMax, GLfloat yMin, GLfloat yMax, GLfloat zMin, GLfloat zMax);

五、透視投影

GLFrustum frustum;
void SetPerspective(float fFov, float fAspect, float fNear, float fFar);

透視投影會進(jìn)行透視除法對距離觀察者很遠(yuǎn)的對象進(jìn)行縮放和收縮。在投影到屏幕之后,視景體背面與視景體正面的寬度測量標(biāo)準(zhǔn)不同。
上圖所示: 平頭截體(frustum)的幾何體,它的觀察方向是從金字塔的尖端到寬闊端。觀察者的視點(diǎn)與金字塔的尖端拉開一定距離。

GLFrustum類通過setPerspective ?方法為我們構(gòu)建?一個平截頭體。
參數(shù):
fFov:垂直?方向上的視場?角度
fAspect:窗?口的寬度與?高度的縱橫?比
fNear:近裁剪?面距離
fFar:遠(yuǎn)裁剪?面距離
縱橫?比 = 寬(w)/?高(h)

 CLFrustum::SetPerspective(float fFov,float fAspect,float fNear
,float fFar);

六、存儲著色器

6.1 GLShaderManager 的初始化

  GLShaderManager shaderManager;
  shaderManager.InitializeStockShaders();
  shaderManager.UseStockShader(參數(shù)列表) // 使用      

6.2 GLShaderManager 屬性

標(biāo)識符 描述符
GLT_ATTRIBUTE_VERTEX 3分量(x,y,z)頂點(diǎn)位置
GLT_ATTRIBUTE_COLOR 4分量(r,g,b,a)顏色值
GLT_ATTRIBUTE_NORMAL 3分量(x,y,z)表面法線
GLT_ATTRIBUTE_TEXTUREO 第一對2分量(s,t)紋理坐標(biāo)
GLT_ATTRIBUTE_TEXTURE1 第二對2分量(s,t)紋理坐標(biāo)

存儲著色器為每一個變量都使用一致的內(nèi)部變量命名規(guī)則和相同的屬性槽。

6.3 GLShaderManager 的 uniform 值

  • 一般情況,要對幾何圖形進(jìn)行渲染,我們需要給對象遞交屬性矩陣,首先要綁定我們要使用的著色程序上,并提供程序的 uniform 值。但是 GLShanderManager 類可以暫時為我們完成工作。
  • useStockShader 函數(shù)會選擇一個存儲著色器并提供這個著色器的 unifrom 值。
GLShaderManager::UserStockShader(GLeunm shader ...);
  • 單位著色器 只是簡單地使用默認(rèn)笛卡爾坐標(biāo)系(坐標(biāo)范圍(-1.0,1.0))。所有的片段都應(yīng)用同一種顏色,幾何圖形為實(shí)心和為渲染的。 需要這種存儲著色器一個屬性: GLT_ATTRIBUTE_VERTEX (頂點(diǎn)分量)vColor[4] 需要的顏色

    GLShaderManager::UserStockShader(GLT_ATTRIBUTE_VERTEX,GLfloat vColor[4]);
    
  • 平面著色器 它將統(tǒng)一著色器進(jìn)行拓展。允許為幾何圖形變換指定一個 4*4 變換矩陣。經(jīng)常被統(tǒng)稱為“模型視圖投影矩陣”

    參數(shù)1:平面著色器
    參數(shù)2:允許變化的 4*4 矩陣

    GLShaderManager::UserStockShader(GLT_ATTRIBUTE_VERTEX,GLfloat vColor[4]);
    
  • 上色著色器 在幾何圖形中應(yīng)用的變換矩陣。需要設(shè)置存儲著色器的 GLT_ATTRIBUTE_VERTEX (頂點(diǎn)分量) 和 GLT_ATTRIBUTE_COLOR (顏色分量)2個屬性。顏色值將被平滑地插入頂點(diǎn)之間(平滑著色)

    GLShaderManager::UserStockShader(GLT_SHADER_SHADED,GLfloat mvp[16]);
    
  • 默認(rèn)光源著色器 這種著色器,是對象產(chǎn)生陰影的光照效果。需要設(shè)置存儲著色器的GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量)GLT_ATTRIBUTE_NORMAL(表面法線)
    參數(shù)1:默認(rèn)光源著色器
    參數(shù)2:模型視圖矩陣
    參數(shù)3:投影矩陣
    參數(shù)4:顏色值

    GLShaderManager::UserStockShader(GLT_SHADER_DEFAULT_LIGHT,GLfloat   mvMatrix[16],GLfloat pMatrix[16],GLfloat vColor[4]);
    
  • 點(diǎn)光源著色器 點(diǎn)光源著色器和默認(rèn)光源著色器很相似,區(qū)別在于,光源位置是特定的。同樣需要設(shè)置存儲著色器的GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量)GLT_ATTRIBUTE_NORMAL(表面法線)
    參數(shù)1:點(diǎn)光源著色器
    參數(shù)2:模型視圖矩陣
    參數(shù)3:投影矩陣
    參數(shù)4:視點(diǎn)坐標(biāo)光源位置
    參數(shù)5:顏色值

    GLShaderManager::UserStockShader(GLT_SHADER_DEFAULT_LIGHT_DIEF,GLfloat  mvMatrix[16],GLfloat pMatrix[16],GLfloat vLightPos[3],GLfloat vColor[4]);
    
  • 紋理替換矩陣 著色器通過給定的模型視圖投影矩陣,使用綁定到nTextureUnit(紋理單元)指定紋理單元的紋理對幾何圖形進(jìn)行變化。
    片段顏色:是直接從紋理樣本中直接獲取的。
    需要設(shè)置存儲著色器的 GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量)GLT_ATTRIBUTE_NORMAL(表面法 線)

    GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_REPLACE,GLfloat     mvMatrix[16],GLintnTextureUnit);
    
  • 紋理調(diào)整著色器 將紋理調(diào)整著色器乘以一個取自紋理單元 nTextureUnit的紋理。需要設(shè)置存儲著色器的 GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量)GLT_ATTRIBUTE_TEXTURE0(紋理坐標(biāo))

    GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_MODULATE,GLfloat
      mvMatrix[16],GLfloat vColor[4],GLint nTextureUnit);
    
  • 紋理光源著色器 將一個紋理通過漫反射照明計(jì)算機(jī)進(jìn)行調(diào)整(相乘)。光線在視覺空間中的位置是給定的。需要設(shè)置存儲著色器的 GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量)GLT_ATTRIBUTE_TEXTURE0(紋理坐標(biāo))、GLT_ATTRIBUTE_NORMAL(表面法線)
    參數(shù)1:紋理光源著色器
    參數(shù)2:投影矩陣
    參數(shù)3:視覺空間中的光源位置
    參數(shù)4:幾何圖形的基本色
    參數(shù)5:將要使用的紋理單元

    GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_MODULATE,GLfloat
    mvMatrix[16],GLfloat vColor[4],GLint nTextureUnit);
    

七、OpenGL 圖元

點(diǎn)、線、線帶、線環(huán)、三角形、三角形金字塔、三角形帶、三角形扇

//修改點(diǎn)的大小
glPointSize(4.0f);
//設(shè)置點(diǎn)的大小范圍,點(diǎn)和點(diǎn)之間的距離
GLfloat sizes[2] = {2.0f,4.0f};
GLfloat stepSize = 1.0f;
//獲取點(diǎn)的大小范圍和步長
glGetFloatv(GL_POINT_SIZE_RANGE,sizes);
glGetFloatv(GL_POINT_GRAULRITY,&stepSize);
//3.通過使用程序點(diǎn)大小模式設(shè)置點(diǎn)大小
glEnable(GL_PROGAM_POINT_SIZE);
//GLSL程序
gl_PointSize = 5.0f;

八、GLBatch 容器(幫助類)

void GLBatch::Begin(GLenum primitive, GLuint nVerts, GLuint nTextureUnits = 0);
void GLBatch::CopyNormalDataf(M3DVector3f *vNorms);
void GLBatch::CopyColorData4f(M3DVector4f *vColors);
void GLBatch::CopyTexCoordData2f(M3DVector2f *vTexCoords, GLuint uiTextureLayer);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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