主要基于WebGLRendere类的render方法开展,需要读者有基本的计算机图形知识,比如计算机图形管线(实时渲染管线)之类的。
在Three.js的渲染中,大概可以分为以下几步:
- 清空当前帧缓冲区,更新MVP矩阵;
- 将物体分为透明和不透明两类,按照离摄像机从近到远排序(也可在Object3D单独设置renderOrder);
- 根据灯光信息,阴影计算,如果有开启平面裁剪就对进行剪裁;
- 开始逐个渲染物体,按以下顺序,背景、不透明物体、透明物体;
- 渲染前后还有两个类似于生命周期的回调函数,scene.onBeforeRender和scene.onAfterRender;
- 最后将深度、模版测试、多边形偏移恢复默认。
其中1、2和5、6都是准备和善后工作,2中为物体分为不透明、透明进行排序,原因有二:
一、为了最大限度地避免overdraw,一个重要的优化策略就是控制绘制顺序。由于深度测试的存在,如果我们可以保证物体都是从前往后绘制的,那么就可以很大程度上减少overdraw。这是因为,在后面绘制的物体由于无法通过深度测试,因此,就不会再进行后面的渲染处理。
二、把透明物体抽出来最后渲染,是为了和不透明物体进行颜色混合。
阴影计算
简单说明下,在threejs的阴影渲染的原理:
-
将相机移动光源位置称为shadowCamera,记录下当前像素点的深度值,记为Z1;
-
将相机移动原来位置, 绘制是将当前像素点的深度值Z与Z1比较,如果小于Z1则说明是光源照不到的地方,画上阴影
(为什么是小于,因为有一个默认规定,相机的上方向是以相机为原点的坐标轴的Y轴,视线为-Z轴方向)。
这一部分也可以叫做实时阴影计算,与光照贴图添加阴影(·lightMap)区别。具体逻辑在WebGLShadowMap类里,它也是做了第一步,将深度信息存在texture里,具体第二步还是要到物体渲染里进行。
WebGLShadowMap的render方法,设置了WebGL的状态,然后创建阴影贴图,最后还是使