最近要写个 web 交互式发光可交互的框架。没查到啥好资料,自己一个人摸索了很久,有些失望,可是毕竟是探索过的东西,所以做个记录,怀念我过去好多天掉的青丝(捂脸)。我在前面那篇博客里面已经介绍了如何让用户与 3D 场景中的组件交互(其实这个技术应该比较成熟了,只是我自己还不熟),所以这篇呢,主要是介绍一下 THREEJS 中的后期处理通道(ShaderPass)以及特效合成器(effectComposer),因为没看到什么资料介绍 THREEJS 后期处理这块儿的。如果有童鞋有更好的办法或者建议或者想一起学习什么的,都可以留言,感觉学 WebGL 的不多,心塞塞。
首先简单介绍一下后期处理通道(Pass),每个通道都是一个ShaderPass,也就是一个Shader,熟悉 GLSL 的 learner 都可以自定义ShaderPass,每个通道就类似于美图秀秀的滤镜的功能,能给你的画面一些特效,比如发光、褐色、清新之类的。而特效合成器(effectComposer)就会把叠加在这个画面上的所有通道(一个画面可以叠加多个通道,类似于一个图片用多个滤镜)的结果计算并渲染出来,所以特效合成器也算是一个render。
THREEJS 的 github 的下载包中,有一个文件夹:three.js-master\examples\js\shaders,这个文件中存放着一些常用的着色器(shader),比如:FresnelShader(根据 Fresnel Reflection 原理)、SSAOShader(根据 SSAO 原理)等,都是依据计算机图形学中知名的算法生成的,想深入了解 WebGL 着色器的同学可以看看源码,都是一些现有公式的实现和应用。还有后期处理通道:three.js-master\examples\js\postprocessing:这个文件夹中包含一些常见的处理通道,比如:BloomPass、HDRPass、MaskPass等,其实都是从 OpenGL 的基础上发展而来的,都是可以直接应用的“滤镜”。
下面我们通过解决几个问题来说明一下怎么应用这些 Shders 和 postProcessing Pass。
问题一:如何给 THREEJS 场景加背景图片?
方法一:
直接给 canvas 所在的 div 设置背景图片,这样做就和 WebGL 渲染没啥关系了,但是是最快的办法,如果没有其他要求的话。但是有一个问题就是,在这种背景下,你的 canvas 中添加后期通道处理的时候会出现一些问题。我这儿是在添加 outlinepass 的时候,div 背景图片变暗了,甚至直接变成了黑色,两者的 α 通道部分的功能冲突了。
方法二:
利用天空盒,也就是 THREEJS 的 立方体纹理(CubeTexture),这种立方体纹理其实就是造了一个超大的立方体盒子,用户渲染的东西在盒子里面,盒子四面八方的纹理就是背景。示例:https://github.com/mrdoob/three.js/blob/master/examples/webgl_postprocessing_backgrounds.html
方法三:
在我看来这是最正经的解决办法,这是原理:http://blog.csdn.net/xiaoge132/article/details/51448326。就是设置让两个渲染的场景叠加,一个是sceneBackground,一个是scene。sceneBackground 中渲染一个 Plane,这个 Plane 有一个正交相机 CameraBG,这个渲染出来的场景就是一个铺满整个窗口的背景。scene 中就用来渲染就要渲染的组件。这样sceneBackground渲染的场景作为背景,scene中场景就是 3D 可视部分。因为是两个场景,所以需要两个渲染通道(renderPass),分别渲染各自的,然后由特效合成器叠加,呈现出最终结果。https://github.com/josdirksen/learning-threejs/blob/master/chapter-11/03-post-processing-masks.html,这个示例可以帮助大家理解。
问题二:如何让整个场景发光?
了解计算机图形学的同学应该都了解SSAO、HDR、Bloom、outLinePass等这些常见的场景发光算法。THREEJS 中也有现成的通道可以用,用户可自定义调节场景参数,达到自己想要的效果。
大家可以自行查看 THREEJS 官方对应的示例:https://threejs.org/examples/。下面给出几个加了通道的画面对比:第一张:不叠加任何通道,第二张:添加Bloom通道,只是个简单示例而已。
问题三:如何在3D场景中添加文字?
方法一:
直接将文字 P 在纹理上,简单粗暴。
方法二:
利用 THREEJS 提供的 3D 文本模型(TextGeometry(text , parameters)),将文本渲染在场景中的任意地方,但是能使用的字体有限,three.js-master\examples\fonts,该文件夹下列出了所有可用的字体类型。
问题四:如何模拟 3D 场景中的物理效果?
在愤怒的小鸟中,小鸟遇到障碍物就会模拟碰撞后的相关“滚出”轨迹,那在 threejs 中如何实现这种效果呢。其实 THREEJS 官方给出了一个模拟物理碰撞的扩展库:Physijs。这个库其实是基于Ammo.js的,Ammo.js又是在 Bullet 物理引擎上发展而来的,Bullet 物理引擎是三大物理引擎之一,还是开源的,但是应用较少,资料也不多。有兴趣的可以看看 Bullet 的官方 Wiki : http://bulletphysics.org/mediawiki-1.5.8/index.php/Hello_World。其实就是在 THREEJS 的 3D 组件外层添加了可检测碰撞的 Shape ,然后模拟重力、受力、线速度、角速度等来使物体运动,都是根据物理公式实现的。
问题五:THREEJS 到底能做什么。有什么应用场景?
这也是我有疑问的地方,THREEJS 可以 web 端建模,展示,数据可视化,都能用到,然后呢?还能干什么,做 3D 试衣间?在网页中嵌入 3D 可视化部分使页面炫酷???其实我之前看到过一篇文章,大意是说 2D 可视化已经足够了,3D 数据可视化只会给用户带来阅读障碍,想想也觉得有道理。而且对于 WebGL,虽然现在慢慢的很多浏览器都支持了,可是各浏览器之间还是有差异,除了谷歌和火狐之外,其他浏览器都存在各种不支持的问题。除了环境之外,电脑的性能也是个问题,3D 可视化对于 CPU 和 GPU 的要求更高,至少我自己 PC 的显卡就很差劲,其实对于大众用户来说,这也是个瓶颈。。希望以后 webGL 能有更广泛的用途,而不只是展示。