客戶端是存儲在CPU存儲器中的,而且在應用程序中執行(或者驅動程序),驅動程序將渲染命令和數據組合起來,發動到服務器執行。
服務器和客戶機在功能上是異步的,他們是各自獨立的軟件模塊或者硬件模塊。性能優化
數據先傳給頂點着色器,而後是片斷着色器,幾何着色器(可選擇)出如今二者之間 服務器
Vertex Shader
) Fragment Shader
) 片斷(fragment)不是最後的像素數據,但和像素對應
片斷(fragment)須要通過處理,blend,texture,lighting...,纔會獲得最後的像素。異步
繪圖命令指定了一組頂點屬性,描述了圖元的幾何形狀和圖元類型。頂點着色器使用這些頂點屬性計算頂點的位置、顏色以及紋理座標,這樣才能傳到片斷着色器。
好比爲了渲染一個三角形,頂點着色器執行3次,也就是爲每一個頂點執行一次。
在目前硬件上有多個執行單元同時運行,因此這3個頂點能夠同時進行處理函數
這些着色器處理過的頂點被組裝到一個個獨立的幾何圖元中,例如:三角形、線、點
對於每一個圖元,必須肯定它是否位於視椎體內(3維空間顯示在屏幕上的可見區域)
背面剔除操做也會執行,它根據圖元是正面仍是背面,進行背面剔除 oop
光柵化階段把圖元轉換成片斷集合,以後會提交給片斷着色器處理,這些片斷集合表示能夠被繪製到屏幕的像素。
輸出的時每一個片斷對應的屏幕座標,和屬性(顏色,紋理座標)性能
每一個片斷執行片斷着色器進行填充,片斷着色器會輸出咱們將在屏幕上看到的顏色
當前的硬件是大規模並行運算的,同時執行上百個甚至更多這種着色器程序並不困難 測試
有3種向OpenGL着色器傳遞渲染數據的方法: 優化
每一個頂點都要存儲的數據元素。
頂點自己就是一種屬性,還有紋理座標,顏色值和用於光照計算的表面法線。
屬性會從本地客戶機內存中複製存儲到圖形硬件中得一個緩衝區中。
這些屬性只供頂點着色器使用,對片斷着色器無心義spa
Uniform可使用屢次,可使用它設置一個應用於整個表面的單個顏色值
頂點着色器和片斷着色器都有3d
頂點着色器和片斷着色器中均可以對紋理值進行採樣和篩選
咱們關心的不是屏幕座標和像素,而是視景體中的位置屬性。將這些點,線和三角形從3D空間投影到計算機屏幕的2D圖形則是着色器程序和光柵化所要完成的
GL_TRIANGLE_STRIP
渲染效果圖:
GL_TRIANGLE_FAN
渲染效果圖
點是最簡單的圖元,默認點的大小是一個像素,能夠經過glPointSize改變
void glPointSize(GLfloat size);
點的大小是存在限制的,咱們能夠得到支持的點尺寸的範圍
GLfloat sizes[2]; GLfloat step; // 獲取支持的點的尺寸範圍和步長 glGetFloatv(GL_POINT_SIZE_RANGE, sizes); glGetFloatv(GL_POINT_SIZE_GRANULARITY, &step);
指定的點在範圍外並不會發生錯誤,只是限定到最接近的範圍內的值
默認狀況下,點和其餘圖元不一樣,它並不會受到透視除法的影響,也就是說不會由於離視點遠看上去變小。
另外,點老是正方形的,即便改變了大小點也仍是正方形,爲了得到圓點,必須在抗鋸齒模式下繪點。
默認狀況下線段寬度爲一個像素。改變線段寬度的惟一方式是使用glLineWidth
void glLineWidth(GLfloat width);
繪製三角形頂點的順序就是指定頂點的順序。
OpenGL默認認爲具備逆時針方向環繞的多邊形是正面的,反之就是多邊形背面。
一個三角形若是是正面的,那麼它旋轉後可能變成背面(笛卡爾座標系,繞y軸180度)
可使用下面函數改變
// GL_CW 順時針環繞的多邊形被認爲是正面 // GL_CCW glFrontFace(GL_CW)
用前3個頂點指定第一個三角形,對於接下來的每一個三角形,都只須要再指定一個頂點。
優點:
+ 能夠建立一組圍繞一箇中心點得相連三角形。
+ 第一個頂點是扇形的原點。
+ 前3個頂點指定最初的一個三角形,接下來的三角形只需指定一個頂點,它將和它相鄰的頂點還有原點組成三角形。
1.開啓表面剔除
glEnable(GL_CULL_FACE);
glDisable(GL_CULL_FACE);
2.指定正面仍是背面剔除
void glCullFace(Glenum mode);
繪製一個像素時,將一個表明它到觀察者距離的Z值,分配給像素.
而後,當第二次在此位置繪製像素時,比較其Z值,而後決定是否繪製。
這裏使用了OpenGL的深度緩衝區,它存儲了屏幕上每一個像素的深度值。
啓用深度測試:
glEnable(GL_DEPTH_TEST)
若是沒有深度緩衝區,那麼啓用深度測試的命令將被忽略。
深度測試在繪製多個對象時能進一步解決性能問題,此時先繪製離觀察者近的對象,那麼就不用繪製距離遠的對象了。
多邊形(含三角形)不必定是實心的。默認下多邊形是實心繪製,能夠經過下面函數指定多邊形渲染模式,實體,輪廓,點。
也能夠指定多邊形的面,正面,背面,兩面
void glPolygonMode(GLeum face, GLenum mode);
有意將多個幾何圖形繪製到同一位置或在一個圖形上繪製另外一個圖形稱爲貼花(decal
),這樣會致使深度緩衝區值相同,致使片斷深度測試不可預料的經過或失敗,稱爲Z衝突(z-fighting
)
有時爲了繪製實體圖形,又想在其上繪製線框圖形,這是就會出現Z衝突。 這時能夠在繪製線框時修改Z的偏移來解決這個問題。
注意:只能沿Z軸向鏡頭方向移動,偏移量必須大小適中,不然沒有效果或者出現縫隙。
下面函數能夠調節片斷的深度值,這樣就能使深度值偏移而並不實際並不改變控件中的物理位置。
void glPolygonOffset(GLfloat factor, GLfloat units);
深度偏移公式:
Depth Offset=(DZ x factor) + (r x units)
其中DZ是深度值相對於多邊形屏幕區域的變化量,r 是使深度緩衝區值產生變化的最小值。並無硬性規定可以找到一個萬無一失的值。
負值使z軸距離咱們更近,正值相反。
處理設置偏移值,還必須啓用多邊形單獨偏移
// GL_POLYGON_OFFSET_FILL 填充幾何圖形 // GL_POLYGON_OFFSET_LINE 線 // GL_POLYGON_OFFSET_POINT 點 glEnable(GL_POLYGON_OFFSET_LINE);
裁剪(scissor)
這種提升渲染性能的方法就是隻刷新屏幕上發生變化的部分,可能還須要將OpenGL的渲染限制在窗口中一個較小的矩形區域中。
OpenGL容許咱們在將要渲染的窗口中制定一個裁剪框。默認狀況下,裁剪框與窗口大小同樣,而且不會進行裁剪測試。
開啓裁剪測試
glEnable(GL_SCISSOR_TEST);
指定裁剪框,要繪製的區域
void glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
一般OpenGL渲染時會把顏色值放在顏色緩衝區中,每一個片斷的深度值放在深度緩衝區中
當打開OpenGL混合功能時,下層顏色不會被清除,而是和已存在的顏色值在顏色緩衝區進行組合,不一樣組合方式產生不一樣特殊效果
啓用混合
glEnable(GL_BLEND);
已經存在顏色緩衝區的顏色值叫目標顏色
做爲新輸入顏色緩衝區的顏色叫源顏色
顏色包含4個部分,紅,綠,藍,Alpha值,忽略的Alpha默認爲1.0
默認混合公式以下:
Cf=(Cs*S)+(Cd*D)
其中,Cf是最終的顏色,Cs是源顏色,Cd是目標顏色,S和D分別是源顏色和目標顏色的混合因子
能夠設置混合因子:
glBlendFunc(GLenum S, GLenum D);
還可使用下面函數靈活進行選擇
void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
在設定因子的時候,某些帶CONSTANT
字樣的參數值,須要一個另外的顏色常量來參與計算,這個常量經過下面函數指定的
void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
改變混合公式:
void glBlendEquation(GLenum mode);
混合功能的另外一個用途是抗鋸齒,多數狀況,一個獨立的渲染片斷將會映射到計算機屏幕上的一個像素。
這些像素是正方形的,一般能夠至關清楚的看到兩種顏色的分界,稱爲鋸齒
。
爲了消除圖元之間的鋸齒狀邊緣,OpenGL使用混合功能來混合片斷顏色,也就是把像素的目標顏色和周圍像素的顏色進行混合。
glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // 還須要確保吧混合公式設置爲GL_ADD(默認) // 如今對圖元分別進行抗鋸齒處理 glEnable(GL_POINT_SMOOTH); glEnable(GL_LINE_SMOOTH); glEnable(GL_POLYGON_SMOOTH); // 能夠設置抗鋸齒質量(GL_FASTEST) glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
點和直線的抗鋸齒處理支持較好,可是多邊形的平滑處理並無在全部平臺上都獲得實現。
多重採樣就能夠解決多邊形平滑處理的問題
存在一個緩衝區,全部的圖元在每一個像素上都進行屢次採樣,結果就存儲在這個緩衝區中。每次當某個像素更新時,會對其進行從新採樣,並更新到緩衝區中
首先必須存在多重採樣緩衝區,這個不一樣平臺可能不一樣
如glut提供的方式
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_MULT I SAMPLE)
打開多重採樣。若是沒有多重採樣緩衝區,那麼無效
glEnable(GL_MULTISAMPLE)
注意:若是開啓多重採樣,那麼點,直線和多邊形的平滑屬性(GL_LINE_SMOOTH
)將無效,意味着若是使用多重採樣,就不能同時使用點和直線的平滑處理。
那麼咱們能夠這樣處理:
繪製點和直線時,關閉多重採樣,繪製多邊形時,開啓多重採樣。
Tips:
狀態排序
打開或關閉狀態將會修改驅動程序的內部狀態,這種改變可能會對渲染性能形成影響
能夠將須要相同狀態的圖元一塊兒繪製,這樣就能夠提升性能(遊戲性能優化)
多重採樣的緩衝區默認使用片斷的RGB值,並沒有alpha值,能夠經過下面方法改變這個行爲
GL_SAMPLE_ALPHA_TO_COVERAGE |
使用alpha值 |
GL_SAMPLE_ALPHA_TO_ON | 將alpha設置1,並使用它 |
GL_SAMPLE_COVERAGE | 使用glSampleCoverage設置的值 |
當啓用GL_SAMPLE_COVERAGE時,glSampleCoverage函數容許指定一個特定值,與片斷覆蓋值進行位與操做
void glSampleCoverage(GLclampf value, GLboolean invert)