OpenGL 裁剪與混合

一、裁剪

另一種提高渲染性能的方法是只刷新屏幕上發(fā)生變化的部分。我們可能還需要將 OpengGL 渲染限制在窗口中一個較小的矩形區(qū)域(剪裁框)中。裁剪測試 是片元可見性判斷的第一個附加測試。
默認情況下,剪裁框與窗口同樣大小,并且不會進行裁剪測試。我們可以使用幾乎處處都會用到的 glEnable 函數開啟裁剪測試。

glEnable(GL_SCISSOR_TEST);// 開啟裁剪測試

也可以使用相應的 glDisable 函數關閉裁剪測試。

glDisable(GL_SCISSOR_TEST);// 關閉裁剪測試

剪裁框可以通過下面的函數設置位置與大?。?/p>

void glScissor(Glint x,Glint y,GLSize width,GLSize height);
參數 x,y:指定裁剪框左下?的點位置(x,y);
參數 width , height:指定裁剪的寬和高。

下面這個程序利用剪裁測試繪制一組重疊的彩色矩形,它對顏色緩沖區(qū)進行了3次清除操作,每次清除之前都指定了一個比上一個較小的剪裁框。

// 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)設置裁剪區(qū)顏色為紅色
glScissor(50, 50, 300, 200);// (2)設置裁剪尺寸
glEnable(GL_SCISSOR_TEST);// (3)開啟裁剪測試
glClear(GL_COLOR_BUFFER_BIT);// (4)開啟清屏,執(zhí)行裁剪
    
// 2.最后裁剪一個綠色的小矩形
// 設置清屏顏色為綠色
glClearColor(0.0f, 1.0f, 0.0f, 0.0f);
glScissor(100, 100, 200, 100);
glClear(GL_COLOR_BUFFER_BIT);
    
// 關閉裁剪測試
glDisable(GL_SCISSOR_TEST);
    
// 進行緩沖區(qū)交換并刷新
glutSwapBuffers();

函數思考- glFlush 和 glutSwapBuffers

  • 函數原型:
    void glFlush(void void)
    void glutSwapBuffers(void)
  • 函數說明:
    glFlush 是強制馬上輸出命令執(zhí)行的結果,而不是存儲在緩沖區(qū)中,繼續(xù)等待其他 OpenGL 命令。
    當執(zhí)行雙緩沖交換的時候,使用 glutSwapBuffers。但是在有
    glutSwapBuffers 的情況下, 不需要 glFlush 就可以達到同樣的效果,因為我們執(zhí)行雙緩沖交換的時候,就隱形的執(zhí)行了一次刷新操作。

展示結果如圖:


opengl5.png

二、混合

我們知道,通常 OpenGL 渲染時會把顏色值放在顏色緩沖區(qū),每個像素的深度值放在深度緩沖區(qū)。當深度測試被關閉,新的顏色值會簡單地覆蓋顏色緩沖區(qū)中已經存在的其他值。當深度測試被打開,則會保留深度值Z更小的。但如果打開了 混合功能,那么下層的顏色值就不會被清除了。
開啟混合功能:

glEnable(GL_BLEND);

在打開混合功能的情況下,新的顏色會與一家存在的顏色值在顏色緩沖區(qū)中進行組合。

1、組合顏色

目標顏色: 已經存儲在顏色緩沖區(qū)中的顏色值。
源顏色: 作為當前渲染命令的結果進入顏色緩沖區(qū)的顏色值,它可能與目標顏色進行交互,也可能不交互。
目標顏色和源顏色都包含了單獨的紅、綠、藍成分和一個可選的 **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)-(Rs,Gs,Bs) 1-As
GL_DST_ALPHA (Rd,Gd,Bd) 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);

例如,如果顏色緩沖區(qū)已經有一種 藍色(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 值越高,添加的源顏色成分就越多,目標顏色所保留的成分就越少

opengl06.png

2、改變混合方程式

默認混合?方程式:
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 );

3、抗鋸齒

OpenGL 混合功能的另一個用途是抗鋸齒。大多數情況下一個獨立的渲染片段將會映射到計算機屏幕上的一個像素。這些像素是正方形的(或者說近似正方形的),通??梢郧宄乜吹絻煞N顏色的分界。它們常常被稱為 鋸齒,讓人覺得圖像不自然。
為了消除圖元之間的鋸齒狀邊緣,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

4、多重采樣

抗鋸齒處理對點和直線的平滑處理得到廣泛支持,但對多邊形的平滑處理并沒有在所有平臺上都得到實現。即使在可以使用 GL_POLYGON_SMOOTH 的時候,對整個場景進行抗鋸齒處理并沒有想象中那么方便。這是因為抗鋸齒處理是基于混合操作的,這就需要從前到后對所有的圖元進行排序,這是非常麻煩的。
OpenGL 1.3 新增了一個特性,稱為 多重采樣(multisampling),可以用來解決這個問題。在已經包含了顏色、深度和模板值的幀緩沖區(qū)就會添加一個額外的緩沖區(qū)。所有的圖元在每個像素上都進行了多次采樣,其結果就存儲在這個緩沖區(qū)中。每次當這個像素進行更新時,這些采樣值進行解析,以產生一個單獨的值。
GLUT提供了一個位段(GLUT_MULTISAMPLE),允許請求這種幀緩沖區(qū)。例如為請求一個多重采樣、完全顏色、帶深度的雙緩沖鎮(zhèn)緩沖區(qū),可以調用:

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);// 開啟多重采樣

// 繪制多邊形

如果沒有多重采樣緩沖區(qū), OpenGL 就當做 GL_MULTISAMPLE 是被禁用的。
多重采樣緩沖區(qū)在默認情況下使用片段的 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);
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容