OpenGL超級寶典筆記——其餘緩衝區技巧

<h3 style="font-family: tahoma; font-variant: normal; white-space: normal; text-transform: none; word-spacing: 0px; color: rgb(0,0,0); font-style: normal; orphans: 2; widows: 2; letter-spacing: normal; line-height: normal; text-indent: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">使用目標緩衝區</h3> <p style="white-space: normal; text-transform: none; word-spacing: 0px; color: rgb(0,0,0); font: medium tahoma; orphans: 2; widows: 2; letter-spacing: normal; text-indent: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">OpenGL並非直接在屏幕上繪製圖元的,而是先渲染到緩衝區中,而後再交換到屏幕上。顏色緩衝區有兩個一個是前顏色緩衝區,一個是後顏色緩衝區。OpenGL默認是在後顏色緩衝區中繪製,而後再經過glutSwapBuffers(或者操做系統的緩衝區交換函數)交換先後緩衝區。咱們也能夠直接在前緩衝區中進行繪製,這樣咱們能夠看到一些繪製的動畫效果。</p> <p style="white-space: normal; text-transform: none; word-spacing: 0px; color: rgb(0,0,0); font: medium tahoma; orphans: 2; widows: 2; letter-spacing: normal; text-indent: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">使用前緩衝區的第一個方法是調用</p> <p style="white-space: normal; text-transform: none; word-spacing: 0px; color: rgb(0,0,0); font: medium tahoma; orphans: 2; widows: 2; letter-spacing: normal; text-indent: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">void glDrawBuffer(GLenum mode);</p> <p style="white-space: normal; text-transform: none; word-spacing: 0px; color: rgb(0,0,0); font: medium tahoma; orphans: 2; widows: 2; letter-spacing: normal; text-indent: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">mode參數爲GL_FRONT,OpenGL就會在前緩衝區中進行繪製。</p> <p style="white-space: normal; text-transform: none; word-spacing: 0px; color: rgb(0,0,0); font: medium tahoma; orphans: 2; widows: 2; letter-spacing: normal; text-indent: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">第二種方法是不適用雙緩衝區機制。</p> <p style="white-space: normal; text-transform: none; word-spacing: 0px; color: rgb(0,0,0); font: medium tahoma; orphans: 2; widows: 2; letter-spacing: normal; text-indent: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);這個是使用雙緩衝區和RGB顏色緩衝區。</p> <p style="white-space: normal; text-transform: none; word-spacing: 0px; color: rgb(0,0,0); font: medium tahoma; orphans: 2; widows: 2; letter-spacing: normal; text-indent: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px">在glut中能夠簡單地忽略GLUT_DOUBLE參數。glutInitDisplayMode(GLUT_RGB);來實現只使用前緩衝區渲染。進行單緩衝區渲染時,若是但願繪製結果顯示到屏幕上,須要調用glFlush();或glFinish();函數。</p> <div id="codeSnippetWrapper"> <pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"><br /><span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> RenderScene()<br />{<br /> <span style="color: #0000ff">static</span> GLdouble dRadius = 0.1;<br /> <span style="color: #0000ff">static</span> GLdouble dAngle = 0.0;<br /><br /> <span style="color: #0000ff">if</span> (dAngle == 0.0)<br /> {<br /> glClear(GL_COLOR_BUFFER_BIT);<br /> }<br /><br /> glColor3f(0.0f, 1.0f, 0.0f);<br /> <span style="color: #008000">//畫點</span><br /> glBegin(GL_POINTS);<br /> glVertex2f(dRadius * cos(dAngle), dRadius * sin(dAngle));<br /> glEnd();<br /> dRadius *= 1.01;<br /> dAngle += 0.1;<br /><br /> <span style="color: #0000ff">if</span> (dAngle &gt; 30.0)<br /> {<br /> dRadius = 0.1;<br /> dAngle = 0.0;<br /> }<br /> glFlush();<br />}<br /><br /><span style="color: #008000">//定時繪製</span><br /><span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> Timer(<span style="color: #0000ff">int</span> value)<br />{<br /> glutTimerFunc(50, Timer, 0);<br /> glutPostRedisplay();<br />}<br /></pre>git

<br /></div>github

<h3><a href="http://static.oschina.net/uploads/img/201309/20113157_2Mhe.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://static.oschina.net/uploads/img/201309/20113157_i3A0.png" width="244" height="222" /></a></h3>web

<h3>操做深度緩衝區</h3>app

<p>在glut中請求深度緩衝區,只需在其初始化顯示模式的時候,加上GLUT_DEPTH位標記:</p>函數

<p>glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);</p>性能

<p>開啓深度測試:</p>測試

<p>glEnable(GL_DEPTH_TEST);</p>動畫

<p>即便深度測試未被開啓。opengl仍是會往深度緩衝區中寫深度值。有時候你須要暫時關掉往深度緩衝區中寫值。能夠調用:</p>ui

<p>void glDepthMask(GLboolean mask);</p>spa

<p>設置mask這個參數值爲GL_FALSE來達到禁用往深度緩衝區裏寫值。使用GL_TRUE則從新啓動往深度緩衝區中寫值。</p>

<h3>使用剪刀進行裁剪</h3>

<p>一種提升渲染性能的方式是隻渲染屏幕上產生變化的那一部分。你也許須要限制Opengl只渲染一小塊矩形區域。OpenGL容許在窗口中指定一個裁剪矩形。打開裁剪測試</p>

<p>glEnable(GL_SCISSOR_TEST);</p>

<p>關閉裁剪測試glDisable(GL_SCISSOR_TEST);指定裁剪框,一窗口座標(像素)形式指定。</p>

<p>void glScissor(GLint x, GLint y, GLsizei width, GLsizei height);</p>

<p>x和y指定了裁剪框的左下角座標,width和height分別指定了寬帶和高度。</p>

<div id="codeSnippetWrapper"> <pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"><span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> RenderScene()<br />{<br /> glClear(GL_COLOR_BUFFER_BIT);<br /> <span style="color: #008000">//設置裁剪框</span><br /> glScissor(100, 100, 400, 400);<br /> glClearColor(1.0f, 0.0f, 0.0f, 1.0f);<br /> <span style="color: #008000">//啓用裁剪功能</span><br /> glEnable(GL_SCISSOR_TEST);<br /> glClear(GL_COLOR_BUFFER_BIT);<br /><br /> glScissor(200, 200, 200, 200);<br /> glClearColor(1.0f, 1.0f, 0.0f, 1.0f);<br /> glClear(GL_COLOR_BUFFER_BIT);<br /> <br /> glDisable(GL_SCISSOR_TEST);<br /> glFlush();<br />}<br /></pre>

<br /></div>

<p><a href="http://static.oschina.net/uploads/img/201309/20113158_7SBj.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://static.oschina.net/uploads/img/201309/20113159_o3My.png" width="236" height="244" /></a></p>

<h3>使用模板緩衝區</h3>

<p>若是咱們但願使用一個模板忽然來渲染一個不規則的形狀。在OpenGL中可使用模板緩衝區。</p>

<p><a href="http://static.oschina.net/uploads/img/201309/20113159_Gzow.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://static.oschina.net/uploads/img/201309/20113200_VlUu.png" width="420" height="221" /></a></p>

<p>首先咱們須要請求一個模板緩衝區,在GLUT中可使用GLUT_STENCIL位來初始化顯示模式。</p>

<p>glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_STENCIL);</p>

<p>在現代的OpenGL實現中,模板操做時被硬件加速過的。咱們可使用glEnable/glDisable來打開或關閉模板測試.</p>

<p>glEnable(GL_STENCIL_TEST);</p>

<p>當打開模板測試的時候,在經過模板測試的地方纔會進行繪製。設置模板測試的函數:</p>

<p>void glStencilFunc(GLenum func, GLint ref, GLuint mask);</p>

<p>第一個參數func來設置比較函數。能夠是GL_NEVER, GL_ALWAYS, GL_LESS, GL_GREATER, GL_LEQUAL, GL_EUQAL, GL_GEUQAL 和GL_NOTEQUAL。這個參數值告訴Opengl如何去和你傳進來的第二個參數ref進行比較。另外你還能夠設置掩碼值mask。這個掩碼值會和ref模板緩衝區中的值進行與操做。即mask先和這兩個值進行與操做 後再進行比較。</p>

<h3>建立模板圖案</h3>

<p>開始繪圖以前,咱們要先清除模板緩衝區。這與glClear函數清除顏色和深度緩衝區的方法是同樣的,只不過使用的位掩碼是GL_STENCIL_BUFFER_BIT。</p>

<p>glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);</p>

<p>glClearStencil(GLint s);這個函數來設置清除模板緩衝區時使用的值。</p>

<p>在啓用了模板測試以後,渲染命令就使用glStencilFunc函數的參數與存儲在模板緩衝區中的值進行測試。根據模板測試的結果,來判斷值應該被寫入或被丟棄。在測試的過程當中,模板緩衝區自己也能夠被修改,進入模板緩衝區的值取決於glStencilOp函數設置的參數。</p>

<p>void glStencilOp(GLenum fail, Glenum zfail, GLenum zpass);</p>

<p>第一個參數告訴opengl,若是模板測試失敗,模板緩衝區的值應該如何被修改。第二個參數和第三個參數則說明當經過模板測試且深度測試失敗或當經過模板測試且深度測試經過時,模板緩衝區的值應該如何被修改。這些參數的合法值包括GL_KEEP(保持當前值), GL_ZERO(設置爲0), GL_REPLACE(用參考值即glStencilFunc設置的ref值代替), GL_INCR(增長這個值), GL_DECR(減小這個值), GL_INVERT(將這個值進行反轉),GL_INCR_WRAP(循環增長), GL_DECR_WRAP(循環減小).</p>

<p>例子:</p>

<div id="codeSnippetWrapper"> <pre id="codeSnippet" style="border-top-style: none; overflow: visible; font-size: 8pt; border-left-style: none; font-family: &#39;Courier New&#39;, courier, monospace; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; line-height: 12pt; padding-right: 0px; width: 100%; background-color: #f4f4f4"><br /><span style="color: #0000ff">static</span> <span style="color: #0000ff">void</span> RenderScene()<br />{<br /> GLdouble dRadius = 0.1; <span style="color: #008000">//最初的螺旋半徑</span><br /> GLdouble dAngle;<br /><br /> glClearColor(0.0f, 0.0f, 1.0f, 0.0f);<br /><br /> <span style="color: #008000">//使用0值來清除模板緩衝區</span><br /> glClearStencil(0.0f);<br /> glEnable(GL_STENCIL_TEST);<br /> <span style="color: #008000">//清除模板緩衝區</span><br /> glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);<br /><br /> <span style="color: #008000">//先初始化模板,讓全部的模板測試都不經過,只是改變模板緩衝區的值</span><br /> glStencilFunc(GL_NEVER, 0x0, 0x0);<br /> glStencilOp(GL_INCR, GL_INCR, GL_INCR);<br /><br /> <span style="color: #008000">//用白線繪製螺旋模型</span><br /> glColor3f(1.0f, 1.0f ,1.0f);<br /> glBegin(GL_LINE_STRIP);<br /> <span style="color: #0000ff">for</span> (dAngle = 0; dAngle &lt; 400.0; dAngle += 0.1)<br /> {<br /> glVertex2d(dRadius * cos(dAngle), dRadius * sin(dAngle));<br /> dRadius *= 1.002;<br /> }<br /> glEnd();<br /><br /> <span style="color: #008000">//如今容許進行繪圖,但不包含那些模板模型是0x1的地方</span><br /> glStencilFunc(GL_NOTEQUAL, 0x1, 0x1);<br /> glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);<br /> <span style="color: #008000">//繪製紅色的反彈方塊</span><br /> glColor3f(1.0f, 0.0f, 0.0f);<br /> glRectf(x, y, x + rsize, y - rsize);<br /><br /> glutSwapBuffers();<br /><br />}</pre>

<br /></div>

<p><a href="http://static.oschina.net/uploads/img/201309/20113200_g2qi.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="http://static.oschina.net/uploads/img/201309/20113201_Mk6n.png" width="244" height="217" /></a></p>

<p>源碼:<a href="https://github.com/sweetdark/openglex/tree/master/otherbuffer">https://github.com/sweetdark/openglex/tree/master/otherbuffer</a></p>

相關文章
相關標籤/搜索