本篇我们来实现场景图的计算。
首先我们需要重构一下我们的SceneNode和SceneObject,让我们的GraphicsManager能够比较方便地获取场景几何体的空间位置。
执行的效果如下:

上传视频封面
可以看到几何体不再重合在一起了。但是几何体的位置与我们在Blender里面设置的不同。这是因为我们没有采用Blender当中设置的相机进行渲染。(Blender采用的是右手坐标系且Z轴垂直向上)

上传视频封面
在执行这一步的时候,我遇到的主要的难关是Blender所导出的相机的矩阵是相机本身的平移与旋转矩阵(位置矩阵)。这个矩阵与View Matrix(就是将场景物体从世界坐标系变换到相机坐标系的矩阵)的关系是求逆的关系。因此我需要在我们之前写的数学库(GeomMath)当中添加矩阵求逆的函数。(参考引用*1)
在使用ispc进行矩阵求逆的函数编写的时候,遇到了下面这么一个问题:
在上面这段代码当中,foreach_tiled当中计算的inv[]矩阵,在foreach_tiled循环体当中看的时候(打印输出log)是正确的,但是到了下一个foreach当中,内容就变成随机的了。调查了一段时间之后,发现是因为inv[]矩阵未被申明为uniform类型。也就是说,按照上面这个写法,其实每个并行计算的instance都会有一个inv[16],其中只有一个数组成员会被赋值,其他的都是随机内容(未初始化)。而后面的foreach因为gang(就是单次并行运算所包括的instance数量)与前面的不同,这个inv似乎会重新分配,内容就更加不可预测了。
解决的方法很简单,因为我们实际是想让各个并行计算线程共享inv[],每个线程计算填写16个值当中的一个,所以只要把inv[]申明为uniform就可以了。
当然,如果觉得并列化计算不好理解或者不想用ispc,完全可以用纯粹的c/c++编写。方法参照(参考引用*2)
在编写数学相关的函数的时候,我们往往需要验证结果是否正确。这可以通过对比外部计算工具的结果来实现。矩阵相关的常用的有matlab,但是这个是个商业软件。Wolfram Alpha(参考引用*5)是一个强大的计算网站,如果你知道该怎么用英文描述你的数学问题,那么它能够帮你做完差不多所有的高数题,包括具体的解题步骤 ( ‘ω’ )
接下来是导入光照。我们这里首先导入经典的Phong全局照明模型。(参考引用*4)

下图是只有漫反射的效果:

上传视频封面
下图是加了高光的效果(高光因子0.01)

上传视频封面
(高光因子0.1)

上传视频封面
高光因子1.0

上传视频封面
可以看到有比较强烈的金属质感了。
漫反射系数0.5高光0.01

上传视频封面
比较强烈的橡胶质感。
对比题图(用Blender渲染),主要少了阴影,以及光的衰减。这是我们接下来的课题。
(注:所有截屏为macOS版,但是Windows/Linux版能够输出同样画面)
参考引用: