個人
OpenGL
專題學習目錄,但願和你們一塊兒學習交流進步!編程
- OpenGL學習(一)-- 術語瞭解
- OpenGL學習(二)-- Xcode 搭建 OpenGL 環境
- OpenGL學習(三)-- OpenGL 基礎渲染
- OpenGL學習(四)-- 正面&背面剔除和深度測試
- OpenGL學習(五)-- 裁剪與混合
- OpenGL學習(六)-- 基礎紋理
- OpenGL學習(七)-- 基礎變化綜合練習實踐總結
- OpenGL學習(八)-- OpenGL ES 初探(上)
- OpenGL學習(九)-- OpenGL ES 初探(下)GLKit
- OpenGL學習(十)-- 着色語言 GLSL 語法介紹
- OpenGL學習(十一)-- 用 GLSL 實現加載圖片
- OpenGL學習(十二)-- OpenGL ES 紋理翻轉的策略對比
另外一種提升渲染性能的方法是隻刷新屏幕上發生變化的部分。咱們可能還須要將 OpengGL 渲染限制在窗口中一個較小的矩形區域(剪裁框)中。裁剪測試 是片元可見性判斷的第一個附加測試。 默認狀況下,剪裁框與窗口一樣大小,而且不會進行 裁剪測試。咱們可使用幾乎到處都會用到的 glEnable
函數開啓裁剪測試。數組
glEnable(GL_SCISSOR_TEST);// 開啓裁剪測試
複製代碼
也可使用相應的 glDisable
函數關閉裁剪測試。函數
glDisable(GL_SCISSOR_TEST);// 關閉裁剪測試
複製代碼
剪裁框能夠經過下面的函數設置位置與大小:post
void glScissor(Glint x,Glint y,GLSize width,GLSize height);
性能
參數 x,y: 指定裁剪框左下⻆的點位置 (x,y);學習
參數 width , height:指定裁剪的寬和高。測試
下面這個程序利用剪裁測試繪製一組重疊的彩色矩形,它對顏色緩衝區進行了 3 次清除操做,每次清除以前都指定了一個比上一個較小的剪裁框。spa
// 1.先設置總體部分清屏顏色爲藍色
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 2.如今剪裁爲中間紅色矩形部分
glClearColor(1.0f, 0.0f, 0.0f, 0.0f);// (1)設置裁剪區顏色爲紅色
glScissor(50, 50, 300, 200);// (2)設置裁剪尺寸
glEnable(GL_SCISSOR_TEST);// (3)開啓裁剪測試
glClear(GL_COLOR_BUFFER_BIT);// (4)開啓清屏,執行裁剪
// 2.最後裁剪一個綠色的小矩形
// 設置清屏顏色爲綠色
glClearColor(0.0f, 1.0f, 0.0f, 0.0f);
glScissor(100, 100, 200, 100);
glClear(GL_COLOR_BUFFER_BIT);
// 關閉裁剪測試
glDisable(GL_SCISSOR_TEST);
// 進行緩衝區交換並刷新
glutSwapBuffers();
複製代碼
函數思考 --
glFlush
和glutSwapBuffers
code
函數原型:cdn
void glFlush(void void)
void glutSwapBuffers(void)
- 函數說明:
glFlush
是強制立刻輸出命令執行的結果,而不是存儲在緩衝區中,繼續等待其餘 OpenGL 命令。 當執行雙緩衝交換的時候,使用glutSwapBuffers
。可是在有glutSwapBuffers
的狀況下, 不須要glFlush
就能夠達到一樣的效果,由於咱們執行雙緩衝交換的時候,就隱形的執行了一次刷新操做。
效果圖以下所示:
咱們知道,一般 OpenGL 渲染時會把顏色值放在顏色緩衝區,每一個像素的深度值放在深度緩衝區。當深度測試被關閉,新的顏色值會簡單地覆蓋顏色緩衝區中已經存在的其餘值。當深度測試被打開,則會保留深度值Z更小的。但若是打開了 混合功能,那麼下層的顏色值就不會被清除了。
開啓混合功能:glEnable(GL_BLEND);
在打開混合功能的狀況下,新的顏色會與一家存在的顏色值在顏色緩衝區中進行組合。
目標顏色: 已經存儲在顏色緩衝區中的顏色值。
源顏色: 做爲當前渲染命令的結果進入顏色緩衝區的顏色值,它可能與目標顏色進行交互,也可能不交互。 目標顏色和源顏色都包含了單獨的紅、綠、藍成分和一個可選的 alpha 值。若是咱們忽略 alpha 值,OpenGL 會將它設爲1.0。 當混合功能被啓用時,源顏色和目標顏色的組合方式是由混合方程式控制的。默認狀況下方程式以下: Cf = (CS * S) + (Cd * D)
- Cf :最終計算產生的顏色
- Cs :源顏色
- Cd :是目標顏色
- S :源混合因子
- D :目標混合因子。
這些混合因子是用 glBlendFunc
函數進行設置的: glBlendFunc(GLenum s, GLenum D);
S 和 D 都是枚舉值,不是可直接指定的實際值。
下表列出了混合函數可使用的值:
函數 | RGB混合因子 | Alpha混合因子 |
---|---|---|
GL_ZERO | (0,0,0) | 0 |
GL_ONE | (1,1,1) | 1 |
GL_SRC_COLOR | (Rs,Gs,Bs) | As |
GL_ONE_MINUS_SRC_COLOR | (1,1,1)-(Rs,Gs,Bs) | 1-As |
GL_DST_COLOR | (Rd,Gd,Bd) | Ad |
GL_ONE_MINUS_DST_COLOR | (1,1,1)-(Rd,Gd,Bd) | 1-Ad |
GL_SRC_ALPHA | (As,As,As) | As |
GL_ONE_MINUS_SRC_ALPHA | (1,1,1)- (As,As,As) | 1-As |
GL_DST_ALPHA | (Ad,Ad,Ad) | Ad |
GL_ONE_MINUS_DST_ALPHA | (1,1,1)- (Ad,Ad,Ad) | 1-Ad |
GL_CONSTANT_COLOR | (Rc,Gc,Bc) | Ac |
GL_ONE_MINUS_CONSTANT_COLOR | (1,1,1)-(Rc,Gc,Bc) | 1-Ac |
GL_CONSTANT_ALPHA | (Ac,Ac,Ac) | Ac |
GL_ONE_MINUS_CONSTANT_ALPHA | (1,1,1)-(Ac,Ac,Ac) | 1-Ac |
GL_SRC_ALPHA_SATURATE | (f,f,f)* | 1 |
其中 f=min(As, 1 - Ad) 顏色是用浮點數表示的,因此對他們進行加減甚至乘法都是徹底合法的。上表可能看上去有點困惑,下面經過一個常見的混合函數組合來舉例說明一下。
glBlendFun(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
例如,若是顏色緩衝區已經有一種 藍色(0.0f, 0.0f, 1.0f, 0.0f),這是目標顏色 (Cd)。若是在這上面用一種 alpha 值爲 0.6 的 **紅色(1.0f, 0.0f, 0.0f, 0.6f)**畫了一些什麼東西,就能夠像下面這樣計算最終顏色。 Cd = 目標顏色 = (0.0f, 0.0f, 1.0f, 0.0f)
Cs = 源顏色 = (1.0f, 0.0f, 0.0f, 0.6f)
S = 源 alpha 值 = 0.6
D = 1 減去 alpha 值 = 1.0 - 0.6 = 0.4
方程式: Cf = (Cs * S)+ (Cd * D)
等價於 Cf = (Red * S)+ (Blue * 0.4)
最終的顏色是原先的藍色(目標顏色)與後來的紅色(源顏色)進行縮放後的組合。源顏色的 alpha 值越高,添加的源顏色成分就越多,目標顏色所保留的成分就越少。如圖:
默認混合⽅方程式: Cf = (Cs * S) + (Cd * D)
實際上咱們可從 5 個不一樣的混合方程式中進行選擇,以下表,咱們能夠經過下面的函數進行選擇:
void glBlendEquation(GLenum mode);
複製代碼
模式 | 函數 |
---|---|
GL_FUNC _ADD | Cf = (Cs * S) + (Cd * D) |
GL_FUNC_SUBTRACT | Cf = (Cs * S) - (Cd * D) |
GL_FUNC_REVERSE_SUBTRACT | Cf = (Cd * D) - (Cs * S) |
GL_MIN | Cf = min(Cs, Cd) |
GL_MAX | Cf = max(Cs, Cd) |
除了glBlendFunc
以外,哈能夠利用下面的函數更加靈活地進行選擇。
void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
複製代碼
- strRGB: 源顏色的混合因⼦
- dstRGB: ⽬標顏⾊色的混合因⼦
- strAlpha: 源顏色的 Alpha 因⼦
- dstAlpha: ⽬標顏色的 Alpha 因⼦
其中 glBlendFunc
函數指定了源和目標 RGBA 值的混合函數,而 glBlendFuncSeparate
函數則容許爲 RGB 和 alpha 成分單獨指定混合函數。
在混合因子表中, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA 值都容許在混合方程式中引入一個常量混合顏色。這個顏色的初始爲黑色**(0.0f, 0.0f, 0.0f, 0.0f)**,但能夠用下面這函數修改:
void glBlendColor(GLclampf red ,GLclampf green ,GLclampf blue ,GLclampf alpha );
複製代碼
OpenGL 混合功能的另外一個用途是抗鋸齒。大多數狀況下一個獨立的渲染片斷將會映射到計算機屏幕上的一個像素。這些像素是正方形的(或者說近似正方形的),一般能夠清除地看到兩種顏色的分界。它們經常被稱爲 鋸齒,讓人以爲圖像不天然。 爲了消除圖元之間的鋸齒狀邊緣,OpengGL使用混合功能來混合片斷的顏色,也就是把像素的目標顏色與周圍像素的顏色進行混合。 開啓抗鋸齒功能很是簡單,首先啓動混合功能
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
複製代碼
咱們還須要確保把混合方程式設置爲 GL_ADD
。在啓用混合功能並選擇正確的混合函數以及混合方程式以後,能夠選擇調用 glEnable
函數對點、直線和多邊形進行抗鋸齒處理。
glEnable(GL_POINT_SMOOTH); // Smooth out points
glEnable(GL_LINE_SMOOTH); // Smooth out lines
glEnable(GL_POLYGON_SMOOTH); // Smooth out polygon edges
複製代碼
抗鋸齒處理對點和直線的平滑處理獲得普遍支持,但對多邊形的平滑處理並無在全部平臺上都獲得實現。即便在可使用 GL_POLYGON_SMOOTH
的時候,對整個場景進行抗鋸齒處理並無想象中那麼方便。這是由於抗鋸齒處理是基於混合操做的,這就須要從前到後對全部的圖元進行排序,這是很是麻煩的。
OpenGL 1.3 新增了一個特性,稱爲 多重採樣(multisampling),能夠用來解決這個問題。在已經包含了顏色、深度和模板值的幀緩衝區就會添加一個額外的緩衝區。全部的圖元在每一個像素上都進行了屢次採樣,其結果就存儲在這個緩衝區中。每次當這個像素進行更新時,這些採樣值進行解析,以產生一個單獨的值。 GLUT 提供了一個位段(GLUT_MULTISAMPLE),容許請求這種幀緩衝區。例如爲請求一個多重採樣、徹底顏色、帶深度的雙緩衝鎮緩衝區,能夠調用:
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_MULTISAMPLE);
複製代碼
可使用 glEnable/glDisable 組合(使用 GLUT_MULTISAMPLE 標記)打開或關閉多重採樣。
glEnable(GL_MULTISAMPLE)
複製代碼
或
glDisable(GL_MULTISAMPLE)
複製代碼
當多重採樣被啓用時,點、直線和多邊形的平滑特性都將被忽略(若是這些特性被啓用的話)。這意味着在使用多重採樣時,就不能同時使用點和線的平滑處理(抗鋸齒處理)。在某些特定的實現中,點和直線若是採用抗鋸齒會比多重採樣效果更好。所以,當繪製點和直線時,能夠 關閉多重採樣,在繪製其餘實心幾何圖形時再 打開多重採樣。以下例子:
glDisable(GL_MULTISAMPLE);// 關閉多重採樣
glEnable(GL_POINT_SMOOTH);// 開啓點的抗鋸齒處理
glEnable(GL_LINE_SMOOTH);// 開啓線的抗鋸齒處理
// 繪製點、線
……
glDisable(GL_POINT_SMOOTH);// 關閉點的抗鋸齒處理
glDisable(GL_LINE_SMOOTH);// 關閉線的抗鋸齒處理
glEnable(GL_MULTISAMPLE);// 開啓多重採樣
// 繪製多邊形
……
複製代碼
若是沒有多重採樣緩衝區, OpenGL 就當作 GL_MULTISAMPLE
是被禁用的。
多重採樣緩衝區在默認狀況下使用片斷的 RGB 值,並不包括顏色的 alpha 成分。咱們能夠經過調用 glEnable(使用下面 3 個值之一)來修改這個行爲。
GL_SAMPLE_ALPHA_TO_COVERAGE
—— 使用 alpha 值。GL_SAMPLE_ALPHA_TO_ON
—— 將 alpha 值設爲 1 並使用它。GL_SAMPLE_COVERAGE
—— 使用glSampleCoverage
所設置的值。
當啓用 GL_SAMPLE_ALPHA_TO_COVERAGE
時,glSampleConverage
函數容許指定一個特定的值,它是與片斷覆蓋值進行按位與操做的結果。 void glSampleConverage (GLclampf value, GLboolean invert);
以上的總結參考了並部分摘抄瞭如下文章,很是感謝如下做者的分享!:
一、《OpenGL超級寶典 第5版》
二、《OpenGL編程指南(英文第八版)》