基于物理的渲染

作者: 东汉书院 | 来源:发表于2019-04-07 03:33 被阅读11次

    基于物理的渲染和光线追踪算法

    基于物理模型的渲染的目的是为了渲染出一张跟某个真实的3D场景一模一样的图片,就仿佛你站在什么地方对这现实场景拍了一张照片一样。

    然而实际上,在这里说渲染出一张跟真实的3D场景一模一样的画面是不够精确的,因为在每个人的眼睛里,世界本来就是不一样的。有的人心里只有妹子,有的人心里只有代码。基于物理的渲染实际上只是在做在确定参数下,进行鲁棒性比较高的现实世界的模拟。鲁棒性这个词可能一般的工人阶层很少接触,如果你是读了硕士或者博士的,应该很熟悉。我们需要根据物理光和与物理光反应的物质,基于我们知道的显示技术,来呈现出最好的视觉效果。

    基本上大部分基于物理渲染的系统都是基于光线追踪算法的。为什么大家都这么偏好光线追踪,是因为光线追踪是最简单的算法,所以不要抛出一个光线追踪就觉得自己很牛逼,这没什么值得骄傲的,你掌握的只是一个最简单的算法。光线追踪算法主要依据的是光线在场景中与物体产生交互然后反射出来的路径来对整个画面进行渲染。

    虽然我们有很多种方式可以去实现光线追踪器,但无论你怎么实现,至少都会需要处理一下几个主题:摄像机、射线相交、光源、可见性检测、表面散射、间接的光线照射、光线的传播。

    摄像机

    跟着我们撸完了OpenGL知识点的人,肯定都是接触了摄像机的,摄像机的目的就是在你想拍照的位置用你最想看的角度去看一个东西。基本上各大计算机图形学的书籍一说到摄像机都会提到小孔成像的概念,其实我们也不知道他们提这种古董出来是个什么意思。我们现在都是用手机拍照的好吗。很多书籍引出小孔成像原理来企图使得对摄像机的说明变得更加清晰,但我们要说的是,时代变了,我们这代人压根不知道小孔成像的那些东西,我们见过的更多的是肾6。所以你完全可以忽略掉小孔成像这一段。

    摄像机最重要的功能就是定义一个你看3D场景的视野,也就是定义了什么东西能被你看到。当别人跟你说小孔成像的时候,你想起来我们的视椎体就可以了,他说了半天不过是想告诉你那些显而易见的东西。我们非常确认,直接画出视椎体,比讲一大堆小孔成像更能让人理解。

    摄像机的一个重要作用就是计算在你所看到的一个画面中的某一个像素点,所有光线对这一点的亮度所作出的贡献。当然我们目前只是在的镜头只有一个的情况下。实际上我们的拍照的时候,镜头可能是多层的,有可能是多个的。不过这些都不关我们的事。我们只考虑一个,因为一个就非常耗时了。当有超过1个镜头(凸透镜什么的),你再去想小孔成像的问题。不过那时候你肯定碰到的是具体的现实问题,所以也不需要去考虑小孔成像。你只需要想起来视椎体就够了。

    我们将在后面再介绍关于摄像机的更多信息,你实现一个摄像机的时候,就可以支持多个摄像机。

    我们现在应该知道的是,我们通过摄像机可以获得一个画面中的某个点与为这个贡献了颜色的光线之间的关系。剩下的就是光线如何在场景中传播和衰减,最后到达这个像素点的时候,它到底是个什么颜色,能量有多强的问题。

    写代码就是要逻辑清晰,要不然就是乱七八糟的。

    射线与物体的相交检测

    当我们去计算光线的时候,我们需要解决的第一个问题就是:光线与哪个物体第一次相交,交点在哪里。此时的这个交点对于光线来说就可以可见的一个点,此时我们就需要去模拟光线与物体在那一点的交互。为了找到谁与光线产生了交互,我们必须使用射线相交检测,来看看谁是第一个与我们的光线产生相交的那个。

    这样一来我们就需要一些几何库,几何库的目的主要是定义基本的几何形体,比如:射线、球、包围盒、胶囊、三角形等等。然后我们还需要实现射线与各种基本几何形体的相交检测算法,如果相交,则返回相交的点的坐标。这里为什么只需要和基本的几何形体进行相交检测就可以了呢?因为复杂的物体就是由这些简单的物体组成的嘛。当然,当射线与某个乖乖相交之后,你只知道交点的坐标是不够的,一般的渲染算法还需要知道这个点的法线以及材质,才能知道该点最终的亮度。在我们基于物理的渲染算法里,我们还需要更多的信息,比如说,我们还需要知道这个点的各种偏导数(偏导数宏观上来说是描述了某一点的变化的速度)、局部参数描述下的表面法线。(法克,全是一些晦涩的概念)

    最后,我们的场景当然是有很多个物体构成的,不是一个。所以到这时候,那些小学没读完的写代码就已经写不下去了,因为他们不会组织描述一套复杂系统鲁棒性较高的代码。不过即便你能写出来正确的代码,比如我们要知道哪个点是光线射出去后,第一个相交的点,我们最屌丝的做法是用光纤跟场景里的物体全部玩一遍,然后找出离光源最近的相交点。但你的场景稍微复杂一点,你的这套系统就顶不住了。当然,如果你是做电影渲染的,没问题。如果你是做实时渲染,那么你就麻烦大了。当然,我们介绍的方法岂能如此屌丝。我们知道即便我们说出方法,仍然有大量的玩家看不懂。

    光照强度

    在上一个阶段,我们已经得到了某一个被着色的点的几何信息以及如何去着色的一些附加信息。但我们的最终任务是计算在某一个视角下,某一点有多少光线跟它发生了关系,并且我们还要调查处,光线与这个点到底发生了什么关系,到底见不见的人。这样我们就需要触及两个概念,第一个就是光源的几何描述信息,另一个就是光在这一点作用后是如何辐射出来的。比如对于简单的光源,光源的几何描述信息是比较简单的,比如说点光源,现实世界是没有这家伙的,谁跟我说有点光源的!所以我们通常使用其他的几何模型去模拟。(那我们进阶课学的点光源是啥?)。我们在物理渲染里的光源稍微会复杂一点,我们的光源不仅具备几何模型,而且光源通过几何模型的表面往外辐射光线。

    我们假设一个光源的光照强度为I,我们假设有个球套在点光源上,点光源刚好位于球的中心,假设球的半径是1,那么球表面某一点的光照强度是多少呢?答案是:I/4PI。其实你只要知道这一点,就可以大致知道后面光照怎么算了。俗话说,万事就差一个带你入门的。

    可见性检测

    在我们之前介绍的那些奇奇怪怪的玩意里,我们其实没有讲一个东西,那就是:阴影。每一个光线只对点亮物体做了贡献,那么那些没被点亮的东西咋办呢?我们在后面的内容中会详细介绍这部分玩法。实际上是非常简单的。

    表面的反射

    现在我们已经算出了两个对于着色来说非常重要的信息了:被着色点的位置和光照强度。现在我们需要知道,光线射完了之后,会有多少倍反射出来,因为这些光线最终是要进入我们的氪金狗眼的。没有进入我们的眼镜的光线,我们是看不见的。所以我们还需要之后,反射的时候有多少能量被反射出来了。每个物体都有一个材质,用来描述所有点的光照反射方面的属性。实际上就是BRDF。这个算法告诉我们,有多少能量被反射出来了。现在我们计算一个光线L有多少能量被反射出来就变得明鸟了。这里计算出来的这个强度跟我们之前讲的那个辐射强度有一点点区别,我们后面再说。

    在我们的基于物理渲染的光照反射算法里,其实可以用的有很多种,比如:BRDF、BTDF、BSDF,最复杂的可能是:BSSRDF了,我们同学里有很多变态一定会去研究BSSRDF,因为这些人是抖M倾向的。

    image

    间接的光线照射

    间接的光线照射就是那些通过其他物体反射过来照亮了某一点的光线。我们在opengl课程里面只介绍了被光直接照亮如何计算,如果是被间接照亮的该怎么办呢?所以这个部分主要是来计算间接光线照射对某一个像素点最终产生了多少颜色贡献。这里介绍的技术还可以用来渲染透明物体。

    光线的传播

    目前,我们所讨论的所有东西都是假设我们的光线在真空中传播的状态,但是事实上,大部分情况下,我们的光线不是在真空中传播,除非你模仿宇宙中的东西。所以我们还需要根据光线所处的环境,来让光的传播变得更真实,比如说有雾的时候,该怎么模拟光线,光线的穿透力如何。

    总结

    我们在这里讲完了基于物理渲染的整个大的逻辑主干,以及要处理的问题大致有哪些。这每个系统中又涉及到很多细节,所以不要以为我们讲的很多东西没有用,我们只是没介绍怎么用她们而已,随着你的实践的增多,会发现他们的用处。如果你没什么经历,或许永远不会发现,我们opengl基础课中那些例子是用来干嘛的。最简单的边缘检测,这是我们在每个进阶课里都讲了的。它是干哈的呢?举个例子:FXAA就是基于边缘检测的算法。所以说,我们介绍的很多知识点都是关键知识点。我们为同学们掰开了一个缝,同学们能走多远看同学们自己了。不是我们不讲,是因为每个缝里面的东西都太复杂,都是综合实力的体现。所以那些抖M的差不多都已经进到缝隙里面去了。

    相关文章

      网友评论

        本文标题:基于物理的渲染

        本文链接:https://www.haomeiwen.com/subject/fokjiqtx.html