OpenGL並不是直接在屏幕上繪制圖元的,而是先渲染到緩沖區中,然後再交換到屏幕上。顏色緩沖區有兩個一個是前顏色緩沖區,一個是後顏色緩沖區。OpenGL默認是在後顏色緩沖區中繪制,然後再通過glutSwapBuffers(或者操作系統的緩沖區交換函數)交換前後緩沖區。我們也可以直接在前緩沖區中進行繪制,這樣我們可以看到一些繪制的動畫效果。
使用前緩沖區的第一個方法是調用
void glDrawBuffer(GLenum mode);
mode參數為GL_FRONT,OpenGL就會在前緩沖區中進行繪制。
第二種方法是不適用雙緩沖區機制。
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);這個是使用雙緩沖區和RGB顏色緩沖區。
在glut中可以簡單地忽略GLUT_DOUBLE參數。glutInitDisplayMode(GLUT_RGB);來實現只使用前緩沖區渲染。進行單緩沖區渲染時,如果希望繪制結果顯示到屏幕上,需要調用glFlush();或glFinish();函數。
static void RenderScene()
{
static GLdouble dRadius = 0.1;
static GLdouble dAngle = 0.0;
if (dAngle == 0.0)
{
glClear(GL_COLOR_BUFFER_BIT);
}
glColor3f(0.0f, 1.0f, 0.0f);
//畫點
glBegin(GL_POINTS);
glVertex2f(dRadius * cos(dAngle), dRadius * sin(dAngle));
glEnd();
dRadius *= 1.01;
dAngle += 0.1;
if (dAngle > 30.0)
{
dRadius = 0.1;
dAngle = 0.0;
}
glFlush();
}
//定時繪制
static void Timer(int value)
{
glutTimerFunc(50, Timer, 0);
glutPostRedisplay();
}
在glut中請求深度緩沖區,只需在其初始化顯示模式的時候,加上GLUT_DEPTH位標記:
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
開啟深度測試:
glEnable(GL_DEPTH_TEST);
即使深度測試未被開啟。opengl還是會往深度緩沖區中寫深度值。有時候你需要暫時關掉往深度緩沖區中寫值。可以調用:
void glDepthMask(GLboolean mask);
設置mask這個參數值為GL_FALSE來達到禁用往深度緩沖區裡寫值。使用GL_TRUE則重新啟動往深度緩沖區中寫值。
一種提高渲染性能的方式是只渲染屏幕上產生變化的那一部分。你也許需要限制Opengl只渲染一小塊矩形區域。OpenGL允許在窗口中指定一個裁剪矩形。打開裁剪測試
glEnable(GL_SCISSOR_TEST);
關閉裁剪測試glDisable(GL_SCISSOR_TEST);指定裁剪框,一窗口坐標(像素)形式指定。
void glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
x和y指定了裁剪框的左下角坐標,width和height分別指定了寬帶和高度。
static void RenderScene()
{
glClear(GL_COLOR_BUFFER_BIT);
//設置裁剪框
glScissor(100, 100, 400, 400);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
//啟用裁剪功能
glEnable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
glScissor(200, 200, 200, 200);
glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDisable(GL_SCISSOR_TEST);
glFlush();
}
如果我們希望使用一個模板突然來渲染一個不規則的形狀。在OpenGL中可以使用模板緩沖區。
首先我們需要請求一個模板緩沖區,在GLUT中可以使用GLUT_STENCIL位來初始化顯示模式。
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_STENCIL);
在現代的OpenGL實現中,模板操作時被硬件加速過的。我們可以使用glEnable/glDisable來打開或關閉模板測試.
glEnable(GL_STENCIL_TEST);
當打開模板測試的時候,在通過模板測試的地方才會進行繪制。設置模板測試的函數:
void glStencilFunc(GLenum func, GLint ref, GLuint mask);
第一個參數func來設置比較函數。可以是GL_NEVER, GL_ALWAYS, GL_LESS, GL_GREATER, GL_LEQUAL, GL_EUQAL, GL_GEUQAL 和GL_NOTEQUAL。這個參數值告訴Opengl如何去和你傳進來的第二個參數ref進行比較。另外你還可以設置掩碼值mask。這個掩碼值會和ref模板緩沖區中的值進行與操作。即mask先和這兩個值進行與操作 後再進行比較。
開始繪圖之前,我們要先清除模板緩沖區。這與glClear函數清除顏色和深度緩沖區的方法是一樣的,只不過使用的位掩碼是GL_STENCIL_BUFFER_BIT。
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glClearStencil(GLint s);這個函數來設置清除模板緩沖區時使用的值。
在啟用了模板測試之後,渲染命令就使用glStencilFunc函數的參數與存儲在模板緩沖區中的值進行測試。根據模板測試的結果,來判斷值應該被寫入或被丟棄。在測試的過程中,模板緩沖區本身也可以被修改,進入模板緩沖區的值取決於glStencilOp函數設置的參數。
void glStencilOp(GLenum fail, Glenum zfail, GLenum zpass);
第一個參數告訴opengl,如果模板測試失敗,模板緩沖區的值應該如何被修改。第二個參數和第三個參數則說明當通過模板測試且深度測試失敗或當通過模板測試且深度測試通過時,模板緩沖區的值應該如何被修改。這些參數的合法值包括GL_KEEP(保持當前值), GL_ZERO(設置為0), GL_REPLACE(用參考值即glStencilFunc設置的ref值代替), GL_INCR(增加這個值), GL_DECR(減少這個值), GL_INVERT(將這個值進行反轉),GL_INCR_WRAP(循環增加), GL_DECR_WRAP(循環減少).
例子:
static void RenderScene()
{
GLdouble dRadius = 0.1; //最初的螺旋半徑
GLdouble dAngle;
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
//使用0值來清除模板緩沖區
glClearStencil(0.0f);
glEnable(GL_STENCIL_TEST);
//清除模板緩沖區
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//先初始化模板,讓所有的模板測試都不通過,只是改變模板緩沖區的值
glStencilFunc(GL_NEVER, 0x0, 0x0);
glStencilOp(GL_INCR, GL_INCR, GL_INCR);
//用白線繪制螺旋模型
glColor3f(1.0f, 1.0f ,1.0f);
glBegin(GL_LINE_STRIP);
for (dAngle = 0; dAngle < 400.0; dAngle += 0.1)
{
glVertex2d(dRadius * cos(dAngle), dRadius * sin(dAngle));
dRadius *= 1.002;
}
glEnd();
//現在允許進行繪圖,但不包含那些模板模型是0x1的地方
glStencilFunc(GL_NOTEQUAL, 0x1, 0x1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
//繪制紅色的反彈方塊
glColor3f(1.0f, 0.0f, 0.0f);
glRectf(x, y, x + rsize, y - rsize);
glutSwapBuffers();
}
OpenGL超級寶典 第4版 中文版PDF+英文版+源代碼 見 http://www.linuxidc.com/Linux/2013-10/91413.htm
OpenGL編程指南(原書第7版)中文掃描版PDF 下載 http://www.linuxidc.com/Linux/2012-08/67925.htm
OpenGL 渲染篇 http://www.linuxidc.com/Linux/2011-10/45756.htm
Ubuntu 13.04 安裝 OpenGL http://www.linuxidc.com/Linux/2013-05/84815.htm
OpenGL三維球體數據生成與繪制【附源碼】 http://www.linuxidc.com/Linux/2013-04/83235.htm
Ubuntu下OpenGL編程基礎解析 http://www.linuxidc.com/Linux/2013-03/81675.htm
如何在Ubuntu使用eclipse for c++配置OpenGL http://www.linuxidc.com/Linux/2012-11/74191.htm
更多《OpenGL超級寶典學習筆記》相關知識 見 http://www.linuxidc.com/search.aspx?where=nkey&keyword=34581