<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: 'Courier New', 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 > 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: 'Courier New', 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: 'Courier New', 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 < 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>