📄 tutorial_36.htm
字号:
透视纹理刚好借助一个函数来完成。我们需要绘制我们的实体然后利用glCopytexImage函数复制这个结果(在交换前,后缓冲器之前)后到纹理。<br>
问题二:在3D实体前精确地协调纹理。<br>
我们知道:如果我们在没有设置正确的透视的情况下改变了视口,我们就得到一个我们的实体的一个被拉伸的透视图。例如如果我们设置一个是视口足够宽我们就得到一个垂直地被拉伸的透视图。<br>
解决方法是首先设置一个视口正如我们的纹理(128×128)。透视我们的实体到这个纹理之后,我们利用当前屏幕决议着色这个纹理到屏幕。这种方法
OpenGL缩减这个实体去适应纹理,并且我们拉伸纹理到全屏大小时,OpenGL重新调整纹理的大小去完美的适应在我们的3d实体顶端。希望我没有丢掉
任何一点。另一个灵活的例子是,如果你取一个640×480大小screenshot,然后调整成为256x256的位图,你可以以一个纹理装载这个位
图,并拉伸它使之适合640x480的屏幕。这个质量可能不会以前一样好,但是这个纹理排列起的效果应当接近最初的640x480图象。<br>
On to the fun stuff! 这个函数相当简单,并且是我的首选的“设计窍门”之一。它设置一个与我们的BlurTexture度数相匹配的大小的视口。然后它被弹簧的着色程序调用。弹簧将由于视口被拉伸适应128*128的纹理。<br>
在弹簧被拉伸至128x128视口大小之后,我们约定BlurTexture 且用glCopyTexImage2D从视口拷贝色彩缓冲器到BlurTexture。<br>
参数如下:<br>
GL_TEXTURE_2D指出我们正使用一个2Dimensional纹理,0是我们想要拷贝缓冲器到mip的绘图等级,默认等级是0。
GL_LUMINANCE指出被拷贝的数据格式。我之所以使用GL_LUMINANCE因为最终结果看起来比较好。这种情形缓冲器的亮度部分将被拷贝到纹
理。其它参数可以是GL_ALPHA, GL_RGB, GL_INTENSITY等等。<br>
其次的两个参数告诉OpenGL从(0,0)开始拷贝到哪里。宽度和高度(128,128)是从左到右有多少象素要拷贝并且上下拷贝多少。最后一个参数仅用来指出我们是否想要一个边界——哪个不想要。<br>
既然在我们的BlurTexture我们已经有了一个色彩缓冲器的副本(和被拉伸的弹簧一致),我们可以清除那个缓冲器,向后设置那个视口到适当的度数(640x480全屏)。<br>
重要:<br>
这个窍门能用在只有双缓冲器象素格式的情况下。原因是所有这些操作从观察者面前被隐藏起来。(在后缓冲器完成)。<br></td><td background="Tutorial_36_files/r.png"><img src="Tutorial_36_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_36_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_36_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_36_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3">
</font><pre><font color="#aaffaa" size="3">void RenderToTexture() <font color="#ffffaa">// 着色到一个纹理</font>
{
glViewport(0,0,128,128); <font color="#ffffaa">// 设置我们的视口</font>
ProcessHelix(); <font color="#ffffaa">// 着色螺旋</font>
glBindTexture(GL_TEXTURE_2D,BlurTexture); <font color="#ffffaa">// 绑定模糊纹理</font>
<font color="#ffffaa">// 拷贝我们的视口到模糊纹理 (从 0,0 到 128,128... 无边界)</font>
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, 128, 128, 0);
glClearColor(0.0f, 0.0f, 0.5f, 0.5); <font color="#ffffaa">//调整清晰的色彩到中等蓝色</font>
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); <font color="#ffffaa">// 清屏和深度缓冲</font>
glViewport(0 , 0,640 ,480); <font color="#ffffaa">// 调整视口 (0,0 to 640x480)</font>
}
</font></pre>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_36_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_36_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_36_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_36_files/l.png"><img src="Tutorial_36_files/l.png"></td>
<td valign="top" width="100%">DrawBlur函数仅在我们的3D场景前绘制一些混合的方块——用BlurTexture我们以前已实现。这样,借由阿尔发和缩放这个纹理,我们得到了真正看起来象辐射状的模糊的效果。<br>
我首先禁用GEN_S 和 GEN_T(我沉溺于球体影射,因此我的程序通常启用这些指令:P)。<br>
我们启用2D纹理,禁用深度测试,调整正确的函数,起用混合然后约束BlurTexture。<br>
下一件我们要作的事情是转换到标准视图,那样比较容易绘制一些完美适应屏幕大小的方块。这是我们在3D实体顶端排列纹理的方法(通过拉伸纹理匹配屏幕比例)。这是问题二要解决的地方。<br></td><td background="Tutorial_36_files/r.png"><img src="Tutorial_36_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_36_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_36_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_36_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3">
<pre>void DrawBlur(int times, float inc) <font color="#ffffaa">// 绘制模糊的图象</font>
{
float spost = 0.0f; <font color="#ffffaa">// 纹理坐标偏移量</font>
float alphainc = 0.9f / times; <font color="#ffffaa">// alpha混合的衰减量</font>
float alpha = 0.2f; <font color="#ffffaa">// Alpha初值
// 禁用自动生成纹理坐标</font>
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_2D); <font color="#ffffaa">// 启用 2D 纹理映射</font>
glDisable(GL_DEPTH_TEST); <font color="#ffffaa">// 深度测试不可用</font>
glBlendFunc(GL_SRC_ALPHA,GL_ONE); <font color="#ffffaa">// 设置混合模式</font>
glEnable(GL_BLEND); <font color="#ffffaa">// 启用混合</font>
glBindTexture(GL_TEXTURE_2D,BlurTexture); <font color="#ffffaa">// 绑定混合纹理</font>
ViewOrtho(); <font color="#ffffaa">// 切换到标准视图</font>
alphainc = alpha / times; <font color="#ffffaa">// 减少alpha值</font>
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_36_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_36_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_36_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_36_files/l.png"><img src="Tutorial_36_files/l.png"></td>
<td valign="top" width="100%">我们多次绘制这个纹理用于创建那个辐射效果, 缩放这个纹理坐标并且每次我们做另一个关口时增大混合因数
。我们绘制25个方块,每次按照0.015f拉伸这个纹理。</td>
<td background="Tutorial_36_files/r.png"><img src="Tutorial_36_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_36_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_36_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_36_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3">
<pre> glBegin(GL_QUADS); <font color="#ffffaa">// 开始绘制方块</font>
for (int num = 0;num < times;num++) <font color="#ffffaa">// 着色模糊物的次数</font>
{
glColor4f(1.0f, 1.0f, 1.0f, alpha); <font color="#ffffaa">// 调整alpha值</font>
glTexCoord2f(0+spost,1-spost);
glVertex2f(0,0);
glTexCoord2f(0+spost,0+spost);
glVertex2f(0,480);
glTexCoord2f(1-spost,0+spost);
glVertex2f(640,480);
glTexCoord2f(1-spost,1-spost);
glVertex2f(640,0);
spost += inc; <font color="#ffffaa">// 逐渐增加 spost (快速靠近纹理中心)</font>
alpha = alpha - alphainc; <font color="#ffffaa">// 逐渐增加 alpha (逐渐淡出纹理)</font>
}
glEnd(); <font color="#ffffaa">// 完成绘制方块</font>
ViewPerspective(); <font color="#ffffaa">// 转换到一个透视视图</font>
glEnable(GL_DEPTH_TEST); <font color="#ffffaa">// 深度测试可用</font>
glDisable(GL_TEXTURE_2D); <font color="#ffffaa">// 2D纹理映射不可用</font>
glDisable(GL_BLEND); <font color="#ffffaa">// 混合不可用</font>
glBindTexture(GL_TEXTURE_2D,0); <font color="#ffffaa">// 释放模糊纹理</font>
}
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_36_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_36_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_36_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_36_files/l.png"><img src="Tutorial_36_files/l.png"></td>
<td valign="top" width="100%">瞧,这是以前从未见过的最短的绘制程序,有很棒的视觉效果!<br>
我们调用RenderToTexture 函数。幸亏我们视口改变这个函数才着色被拉伸的弹簧。 对于我们的纹理拉伸的弹簧被着色,并且这些缓冲器被清除。<br>
我们之后绘制“真正的”弹簧 (你在屏幕上看到的3D实体) 通过调用 ProcessHelix( )。
<p>最后我们在弹簧前面绘制一些混合的方块。有织纹的方块将被拉伸以适应在真正的3D弹簧<br>
上面。<br>
</p></td><td background="Tutorial_36_files/r.png"><img src="Tutorial_36_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_36_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_36_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_36_files/br.png" height="28" width="28"></td></tr></tbody></table>
<font color="#aaffaa" size="3">
<pre>void Draw (void) <font color="#ffffaa">// 绘制场景</font>
{
glClearColor(0.0f, 0.0f, 0.0f, 0.5); <font color="#ffffaa">// 将清晰的颜色设定为黑色</font>
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); <font color="#ffffaa">// 清除屏幕和深度缓冲器</font>
glLoadIdentity(); <font color="#ffffaa">// 重置视图</font>
RenderToTexture(); <font color="#ffffaa">// 着色纹理</font>
ProcessHelix(); <font color="#ffffaa">// 绘制我们的螺旋</font>
DrawBlur(25,0.02f); <font color="#ffffaa">// 绘制模糊效果</font>
glFlush (); <font color="#ffffaa">// 强制OpenGL绘制我们所有的图形</font>
}
</pre>
</font>
<table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_36_files/tl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_36_files/tc.png" height="28" width="100%"></td><td><img src="Tutorial_36_files/tr.png" height="28" width="28"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td background="Tutorial_36_files/l.png"><img src="Tutorial_36_files/l.png"></td>
<td valign="top" width="100%"><p>我希望你满意这篇指南,它实在没有比透视一个纹理讲授更多其它内容,但它是一个干脆地添加到你的3D应用程序中有趣的效果。
<br>
如果你有任何的注释建议或者如果你知道一种更好的方法执行这个效果联系我rio@spinningkids.org。<br>
我也想要委托你去做一列事情(家庭作业):D<br>
1) 更改DrawBlur程序变为一个水平的模糊之物,垂直的模糊之物和一些更好的效果。(转动模糊之物!)。<br>
2) 玩转DrawBlur参数(添加,删除)变为一个好的程序和你的音乐同步。<br>
3) 用GL_LUMINANCE玩弄DrawBlur参数和一个SMALL纹理(惊人的光亮!)。<br>
4) 用暗色纹理代替亮色尝试大骗(哈哈,自己造的)测定体积的阴影。<br>
好了,这应该是所有的了(到此为止)。<br>
访问我的站点http://www.spinningkids.org/rio. <br>
获得更多的最新指南。</p>
<table border="1" width="100%">
<tbody><tr>
<td width="27%"><img src="Tutorial_36_files/logo%25203.jpg" align="middle" height="200" width="209"></td>
<td width="73%">版权与使用声明:<br>
我是个对学习和生活充满激情的普通男孩,在网络上我以DancingWind为昵称,我的联系方式是zhouwei02@mails.tsinghua.edu.cn,如果你有任何问题,都可以联系我。
<p>引子<br>
网络是一个共享的资源,但我在自己的学习生涯中浪费大量的时间去搜索可用的资料,在现实生活中花费了大量的金钱和时间在书店中寻找资料,于是我给自己起了
个昵称DancingWind,其意义是想风一样从各个知识的站点中吸取成长的养料。在飘荡了多年之后,我决定把自己收集的资料整理为一个统一的资源库。</p>
<p>版权声明<br>
所有DancingWind发表的内容,大多都来自共享的资源,所以我没有资格把它们据为己有,或声称自己为这些资源作出了一点贡献。故任何人都可以复
制,修改,重新发表,甚至以自己的名义发表,我都不会追究,但你在做以上事情的时候必须保证内容的完整性,给后来的人一个完整的教程。最后,任何人不能以
这些资料的任何部分,谋取任何形式的报酬。</p>
<p>发展计划<br>
在国外,很多资料都是很多人花费几年的时间慢慢积累起来的。如果任何人有兴趣与别人共享你的知识,我很欢迎你与我联系,但你必须同意我上面的声明。</p>
<p>感谢<br>
感谢我的母亲一直以来对我的支持和在生活上的照顾。<br>
感谢我深爱的女友田芹,一直以来默默的在精神上和生活中对我的支持,她甚至把买衣服的钱都用来给我买书了,她真的是我见过的最好的女孩,希望我能带给她幸福。</p>
<p>资源下载: <br>
文档 <a href="http://www.owlei.com/DancingWind/Res/mht/NeHe%20OpenGL%20Chinese%20Course%2036.mht">网页格式</a>
<a href="http://www.owlei.com/DancingWind/Res/pdf/OpenGL_Nehe_Course_Tutorial_36.pdf">PDF格式</a><br>
源码 <a href="http://www.owlei.com/DancingWind/Res/Src/36_Blur.rar">RAR格式</a></p></td>
</tr>
</tbody></table><table border="0" width="100%">
<tbody><tr><td align="left" width="50%"><b><font size="-1"><a href="http://www.owlei.com/DancingWind/Course/Tutorial_35.htm"><
第35课 </a></font></b></td>
<td align="right" width="50%"><b><font size="-1"><a href="http://www.owlei.com/DancingWind/Course/Tutorial_37.htm">第37课
></a></font></b></td>
</tr></tbody></table>
</td>
<td background="Tutorial_36_files/r.png"><img src="Tutorial_36_files/r.png"></td></tr></tbody></table><table border="0" cellpadding="0" cellspacing="0" width="100%"><tbody><tr><td><img src="Tutorial_36_files/bl.png" height="28" width="28"></td><td width="100%"><img src="Tutorial_36_files/bc.png" height="28" width="100%"></td><td><img src="Tutorial_36_files/br.png" height="28" width="28"></td></tr></tbody></table>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -