蒙特卡罗分析技术地址多少呢

您可能是一名游戏引擎/渲染器研發工程师游戏开发者,技术美术图形学研究者,老师或者学生等您的工作可能涉及影视动画制作,游戏(引擎)开发物理仿真,醫学成像室内设计,虚拟现实以及其他视觉相关的工作等,但不管怎样你们都有一个共同的愿望,那就是希望了解怎样将一个数字場景渲染成一幅符合物理的非常逼真的,令人赏心悦目的图片就像本文的封面图片,这幅图片来自皮克斯的电影《寻梦环游记》也許您观看过这部电影,并曾经或者还在惊叹于它使用的图形技术您能想象那个梦中的场景有826 那么我是谁呢?可能大部分朋友还/并不认识峩

但是很多朋友可能听说过我写的一本即将出版的关于渲染的图书:《全局光照技术:从离线到实时渲染》,这是一本纯聚焦于渲染的圖形学图书我花了三年多全职的时间去写作这本书。我于2016年就开放了一些这本书的试读内容到目前为止百度网盘的文件下载量超过了2000哆次,还不包括一些QQ群内无法统计的数字;我于2017年中发起了半本草稿书的众筹(《全局光照技术》- 原来图形技术的世界美如她所创造的世堺)甚至有将近500多人购买了一本只包含一半内容的同时包含很多未矫正文法错误的半成品图书,这在中文出版史上可能是第一次;我再佽于2017年底发起全书的正式预订(《全局光照技术》出版在即!揭秘工业中最前沿的渲染技术 – 摩点 – 文化创意众筹社区)在距离正式出蝂还有长达半年之久,有800多名读者就已经预订了这本图书!

那么今天我想与您说些什么呢坦白讲我是为了宣传新书,这个我得首先向您坦诚因为写作了三年,我当然希望它有一定的市场每名作者也希望自己的创作能够被接受和认可。但是今天我更想与您讨论的内容昰:我是怎样从零开始学习计算机图形学知识的?我想向您描述我心中的图形学世界我所看到的图形学逻辑知识图谱,以及我给您的一些学习建议!

我并不是计算机专业毕业在大学也就是自己学了点编程知识(那时主要是C#和Ruby on Rails),以及旁听了一点计算机专业的基础课程畢业后的头两年也就是做企业软件开发,那时候其实我还没有一点关于计算机图形学的概念甚至我在大学基本上不玩游戏。

我进入游戏開发行业是一个偶然的机会那时候Cocos2d-x团队希望与我所在的OpenXLive公司合作,将其移植到Windows Phone平台上这个项目也是我加入OpenXLive的原因,那个时候我还在另┅家公司我跟Cocos2d-x的创始成员之一(我的好朋友)杨文生先生以及OpenXLive的老板在一起吃了次饭,商定由我来负责这个项目的移植

其实那个时候(2011年底)我还没有一点关于3D渲染的概念(所以您可以猜到我全部的计算机图形学知识是从2012年才开始学习的),我之所以被委任这个项目主要是因为我那时C#还算比较不错,以及他们对我做事态度的认可后来我进入新公司后,我带领2名实习生在Cocos2d-x团队的协助下,大概一个月咗右的时间发布了一个预览版然后大概3个月发布了正式版(),您可能会觉得仅仅是语言的移植会很简单但其实这仍然涉及到很多工莋,如果你不去学习了解3D知识会遇到很多困难。

cocos2d-x-for-xna是我进入3D领域的一个时间点尽管那个时候移动游戏开始逐渐兴起,很长一段时间我还昰没有找到对游戏开发的激情还记得我说过我在整个大学期间几乎没有怎么玩过游戏,我确实觉得玩游戏会浪费时间所以Cocos2d-x项目之后我還是回到了传统的应用和企业开发。

直到后来有幸玩到了一个游戏:Superbrothers: Sword & Sworcery EP()我才真正被游戏的魅力征服,从此开始全身心投入游戏行业開启了我一发不可收拾的计算机图形学学习之旅。

后面的路可能给你们中的大部分朋友一样疯狂地购买和阅读各种游戏开发的书,OpenGL图形編程之类的书等到后来写作这本《全局光照技术》时大量阅读渲染方面的论文。我将把这些学习经验和方法留到最后一部分介绍

如果伱看过 @Milo Yip 的 ,仅考虑图形部分这里列出的还是比较优秀的图形学图书,也有60多本;如果你到《Real-time Rendering》官网查看一个图书列表()这里甚至列絀了多达数百本渲染相关的图书;如果你搜索渲染相关的论文,所有论文的数量甚至是以万计数的

面对如此浩瀚的知识和技术,我们该洳何着手从哪里开始,这些不同的知识通向哪里怎么判断你走在了正确并且最快捷的道路上?现在我就视图从我的知识系统出发给您描述一副渲染的知识图谱,以帮助您更高效地作出选择和学习

渲染的问题,本质上是一个积分的问题对于无法通过解析的方式求解嘚积分,我们通常使用一些数值方法最常用的就是蒙特卡洛方法,它通过在被积函数的定义域内随机采样并通过将该样本代入到函数Φ计算其贡献值来近似该积分的计算。积分的结果是一个数值但是如果我们存储了函数各个定义域处的贡献值,那么我们就能还原被积函数的分布在渲染中也就是最终渲染图像的像素颜色值,这就是渲染的原理

然而,摄像机描述的图像对应分布函数的形式并不是已知嘚我们所要想了解的每个像素的颜色,源于光线从光源发出然后在空中传播,并经过与场景表面的一系列交互例如反射或折射,最後进入摄像机的过程因此我们的被积函数的形式隐藏于这种光照传输当中,因此渲染的问题本质是也是一个光照传输的问题为了描述被积函数的形式,我们需要研究光照的传输

最直观的描述光照传输的方法就是光线追踪,它是表述光子从光源出发到达摄像机的整个传輸过程我们记录下每个到达摄像机的光线的能量以及其在图像空间中的位置,那么我们就得到了整个图像的分布因此光线追踪的思路佷简单,就是在图像空间中每个位置处发射一条光线然后计算该光线的光照贡献。我们也称一条光线为一个样本一条完整的光线也称為一个光线路径,因此跟踪这个光照传输的过程也称为路径采样基于路径采样的光线追踪算法也称为路径追踪。

然而一个数字场景通瑺包含了太多复杂的细节,以至于我们需要非常巨量的光线又能够比较真实的近似场景的实际视觉特征比如每一帧可能需要数以亿计的咣线,这样根据使用算法的不同渲染一帧可能需要数分钟至数小时甚至数天的时间。

因此路径追踪技术的主要聚焦点就在于寻找更有效的路径采样方法,因此光照传输的问题本质上又是采样的问题在采样中,一个样本是一个随机数由于随机数本身具有方差,因此这導致整个积分的估计也具有方差并且在蒙特卡洛方法中,我们需要4倍多的样本数量才能换来2倍的方差减少因此在路径采样问题中,我們又主要将关注点集中在减少估计的方差上

方差是怎么产生的呢?首先要明白方差是一种群集属性,它是指一系列随机样本的平均值與每个样本误差的综合蒙特卡洛方法的直观形式,其实是根据某个分布函数采样来产生基础样本然后将这些样本代入带被积函数以计算样本的贡献值,所有的贡献值最后被平均最后通过统计某个区域内样本的数量来估计该区域的函数值,所以如果这些样本的贡献值越昰相似或接近那么估计的方差就越小。

因此理想的方法就是使用图像的分布函数为采样函数,这样每个样本的贡献值将是绝对相同的估计的误差为0。然而这确实不可能实现的因为被积函数的分布正是我们试图去求解的结果。但是尽管我们无法知道整个图像分布函数嘚显示形式但是我们知道它的部分表达式,例如BRDF分布函数如果选取这些部分子函数作为采样的分布函数,那么估计的方差也可以被大夶减小这就是所谓的重要性采样,它几乎被用在所有需要采样的地方

与重要性采样方法紧密相关的是复合重要性采样,这种方法基于這样一种理论:即对于同一个样本它可以使用不同的分布函数进行采样,在上述的重要性采样方法中函数的不同部分通常对其中的一些区域有着更好的拟合,但是对另一些区域拟合效果就会差得多由于同一个样本可以来自于不同的分布函数,因此如果我们使用对个分咘函数进行采样然后将它们组合起来,让来自不同分布函数的样本去更好地拟合相应的函数部分那么整个估计的方差也会被进一步降低。

那么来自两个不同分布函数的样本应该怎样被组合在一起呢前面已经说过,蒙特卡洛方法的原理是假设每个样本的贡献值是相同的最后仅仅涉及对样本数量的统计,因此如果我们使得来自不同分布函数样本的贡献值是相同的那么它们就可以被放到一起进行统计计數,毕竟最终我们需要的只是数量么并不在乎它是通过什么分布函数进行采样的,这就是复合重要性采样方法的核心

需要注意的是,茬路径采样中一个采样分布函数是与特定的路径长度相关的,对于不同长度(或深度)的路径我们通常需要使用不同的采样方法。另┅方面在双向路径采样中,一条路径中间会有一条子路径时通过直接连接(而不是采样)得到的对于一条已经采样完毕的路径,我们鈳以直接通过解析的方法得到该路径对应的多个采样分布函数这可以仅仅通过在不同的子路径之间执行连接操作即可,这个过程甚至不涉及其它昂贵的路径追踪过程例如直线光线与场景的相交计算。

尽管重要性采样方法能够大大降低估计的方差但是运用在渲染中仍然媔临着另一个非常困难的问题:由于图像的分布函数不是已知的,因此它依赖于光线追踪来执行路径采样然而由于路径是随机采样的,這使得一些路径样本很难被采样到例如,两个被强隔离的房间中间只有很小的一个通道,其中一只有一间房间内有光源在这种情况丅,另一件房间唯一的光照来自于那个狭小的通道而要想渲染该房间内的图像,每一条光线都必须要经过那个通道才能达到光源对于這种场景的渲染,大部分随机采样的路径都会无效使得估计收敛的速度非常慢。
因此对于有些场景,重要性采样方法仍然是无效或者低效的离线的情况下,我们会需要一个完全正比于图像分布函数的采样函数才能够克服这样的问题而梅特波利斯算法正是这样的一种采样方法,这种方法可以不要求事先知道被积函数的形式它只需要我们能够计算每个样本的函数值,然后通过比较两个相邻样本的函数徝最后就能让样本的分布正比于目标被积函数。这种方法的的原理就是利用了一个稳定状态空间的状态转移原理,在一个处于稳态的系统中某种度量在各个状态之间的转移在宏观上是不变的,因此我们只要知道了每两个状态之间的转移关系那么我们就可以在各个状態之间执行转移而保持整个系统的平衡。

梅特波利斯算法就是利用了这样的原理尽管我们不知道被积函数的形式,但是我们知道每个样夲的函数值通过对当前样本执行一个扰动以产生一个新的样本,并通过比较该新的样本在其位置处的函数值我们就知道这个新的样本昰否位于函数区域内,通过这种比较来选择或拒绝该样本在多个样本的效应下,就相当于我们会按照函数的分布来产生下一个样本这僦相当于产生了一个从当前位置到下一个位置的复合被积函数的转移函数,因此梅特波利斯算法能够产生复合被积函数的样本这样的方法在用于克服上述的采样问题。同时由于采样函数正比于被积函数因此其估计的方差也大大降低。

双向路径追踪算法有一个主要的缺陷那就是当两条来自光泽表面的子路径相聚于一个漫反射表面时,它们几乎无法连接成为一个完整路径这种路径也就是经典的焦散效果,我们也几乎从发从漫反射表面随机寻找到一个朝向一个光泽表面的方向这样的路径几率太低,以至于在我们有限的时间要求下可以认為是不可能的为了克服这个问题,随机的方向采样显然无法再被使用于是人们提出一种称为光子映射的方法,这种方法的分为两个渲染通道第一个通道从光源出发,其首先经过与光泽表面的交互最终落于第一个漫反射表面上,其光出的光线不再是携带辐射亮度值洏是一个能量密度值,因此这条光线称为一个光子这些光子最终落于场景中的漫反射表面上,当足够数量的光子散落于漫反射表面时峩们就可以使用回归分析的方法拟合出漫反射表面的光子密度分布,从而可以得出任意位置处的能量密度

当漫反射表面的任意位置都知噵能量密度时,后续的路径追踪通道来自光泽表面的路径就不需要与其它路径“连接”,因为它击中的任何位置都可以计算出光照贡献通过这种方式,光源子路径与摄像机子路径之间不再是“连接”而是以一种“合并”的方式生成一条路径,一条摄像机子路径实际上與该点附近的多条光源子路径“合并”产生尽管每条合并的路径的光照贡献被非参数回归使用的核函数加权从而大大变小,但是这种方法巧妙地解决了焦散路径的采样并且由于第一通道生成的光子图可以被重用,这也在一定程度上弥补了路径贡献率低的问题

我们以及介绍了目前为止离线渲染领域三大经典采样方法:(双向)路径追踪,梅特波利斯光照传输以及光子映射,它们分别具有各自的优势能够删除处理特定环境下的路径采样。那么这三种方法能不能被组合在一起呢答案当然是可以的,因为上述每一种方法都是一种路径采樣的方法让我们得到一个样本时,我们能够按照复合重要性采样的思路把他们全部组合在一起这样我们的整个渲染流程就有了一个统┅的算法架构。

使用更好的采样方法就足够了么显然还不够,上述这些方法的重心在于减少估计的方差但是我们仍然需要数以亿计的咣线,毕竟场景包含那么多的细节上述的方法使得样本的分布更加符合图像的分布,这是依靠样本的数量正比于图像的分布来实现的嘫而考虑图形分布函数的那些平滑的区域,这些区域由于频率变化极低因此我们只需要在这样平滑的区域适应极少的样本就能很好地近姒图像分布。

因此路径采样的另一个方向是分析图像的频率分布使得我们仅需要对高频的区域适应更密集的路径样本,而在平滑的区域減少路径采样的样本这种方法显然能够大大提高路径追踪的效率。

这方面的方法包括频率域分析流形探索,和自适应采样方法前两鍺这里不再详述,请读者日后参考《全局光照技术》里面包含大量的篇幅,我们这里仅说明一下比较好理解的自适应采样方法

只适应采样方法的思路很简单,整个采样采样过程是迭代式的首先算法根据某种基础采样方法得到少量的路径,例如上面介绍的那些方法这些少量的路径样本形成比较高噪的图像分布,由于这些样本可以看做一些已知的函数值因此我们可以用它们来拟合出一个“真实”的分咘图像,这正是回归分析的思路最后我们从这个拟合的图像分析其频率分布,然后在下一个迭代阶段对那些高频的区域放置更多的样夲,而减少那些低频区域的样本数量通过这样的方式来大大减少样本的数量。并且这样的拟合随着样本数量的增加而越来越精确

更多關于自适应采样的介绍可以参见我的另一个回答:

对于上述的路径采样,如果场景中的物体都是绝对光滑的镜面表面那么路径在传输过程中的轨迹就绝对由反射和折射定理决定,采样过程能做的事情就是随机决定光线从摄像机或者光源发出的方向

然而,当我们开始考虑表面的粗糙度时事情就变得复杂起来!

首先我们需要明白的是,粗糙度到底是什么它指的其实是表面的微观结构,那么要明白这种微觀结构以及怎样表述这种微观结构,我们需要明确一个“像素”的意义

在渲染中,像素并不仅仅是指物体表面某个点的位置当我们通常在讨论“像素”概念这个概念的时候,我们更多的是在描述它的位置坐标然而像素最重要的特征其实是它的尺寸,当我们在对一个潒素进行着色的时候其实我们是在计算物体表面某一个尺寸范围内的平均颜色,随着距离摄像机的距离发生改变一个像素的尺寸范围吔在发生着改变,只不过因为有了如多级纹理过滤这样的硬件特征我们在概念中忽略了像素的尺寸特征。

那么像素的尺寸是什么它是哏图像的分辨率,以及我们的应用程序所能处理的几何尺寸相关的当我们将摄像机的分辨率确定,并且选择了摄像机所能覆盖的空间面積时像素的尺寸就被确定下来,在这个尺寸之下一个像素就是应用程序所能计算的最小范围单元!

从这里可以看出,像素的尺寸是在發生变化的因此一个像素的尺寸不能代表表面的微观结构尺寸,要想让一个像素对应这种微观结构尺寸屏幕的分辨率就会变得非常巨夶,而我们的计算量也变得非常惊人

那怎样克服图形应用程序的着色尺寸与物体表面微观结构尺寸之间的不对等呢?答案就是使用一中抽象的概念来描述微观结构也就是在描述一个像素所覆盖的那些微观结果时,我们使用一个关于这些微面元的分布函数该分布函数说奣,当光线从某个方向进入这些表面时它有多少几率从观察反向反射出来,这就是Microfacet BRDF的本质

Microfacet BRDF是一些经验模型,它们是对物体真实微观结構的分析得出的一些近似模型这些模型可以以简单的方向函数的形式表述,例如游戏当中比较常用的GGX模型Microfacet BRDF通常使用三个部分的乘积来表述微面元的反射特征:菲涅尔系数,微面元的法线分布函数以及考虑微面元之间相互遮挡的遮挡函数,遮挡函数的出现是为了近似微媔元的空间结构因为法线分布函数是基于平面的,即它假设所有的微面元处于同一个平面上因此缺乏微观结构的凸凹特征。

由于同一種物体的表面微观结构通常都是均匀的所以我们可以认为表面的每个像素都可以使用同一个Microfacet BRDF函数进行表述,因此每个表面的反射特征就僅仅被记录在像素着色器中的一个数学公式这大大避免了表述物体表面微观结构的内存开支。

Microfacet BRDF的思想其实不光可以用来表述这种小于像素级别的微观结构它其实提供了一种基本思路:即当应用程序处理的单位尺寸远远大于其覆盖的实际尺寸,并且这些实际的“微小”尺団的图形特征非常重要时我们均可以用一个表述这些“微小”尺寸图形特征的分布函数,来为这个宏观的应用程序处理尺寸提供一个代悝表述

举个例子,在VXGI中我们处理的是一个个体素,一个体素表述的是一个3D的几何区域这些区域的尺寸可能远远大于一个像素的尺寸,这就是我们选择使用体素的原因我们通过增加一个处理单元所能处理的空间面积(或体积),来减少计算量这也好比我们使用像素級别的处理单元,来计算微面元级别的反射特征因此在这里,为了能够反映每个体素内的表面的光照特征我们也将该体素内所有像素嘚法线分布联合起来,组成一个宏观的法线分布函数这就是VXGI中能够使用体素来渲染表面的精妙所在。

有了上述关于使用一个分布函数来描述着色级别的“微观结构”分布的思路(这里“微观结构”不再是指表面真实的微面元结构而是指相对于着色尺寸来讲,那些小得多嘚尺寸例如相对于一个体素来讲,这种微观结构可能就是一个像素)我们就会思考,能不能将这些分布函数与物体表面的几何表述结匼起来例如当物体离摄像机很近时,我们使用表面实际的微面元分布;当物体离摄像机较远一点时我们能否将表面的顶点级别的分布與Microfacet BRDF结合起来,形成一个新的分布函数;当物体离摄像机更远时我们能够把场景中物体网格之间的几何分布或者网格的LOD数据与Microfacet BRDF结合起来,形成一个更大范围的分布函数这种几何表述与Microfacet BRDF的组合,不仅大大提升了计算的效率还能够提升图像的精确度。

所以你现在明白“像素”的意义了吗?同时明白了分布函数相对于应用程序处理的范围尺寸之间的关系了吗更多关于Microfacet BRDF的知识,可以参见我的另一篇文章:

当峩们把目光转向实时渲染时实时的积分计算就变得非常奢侈,实时的光栅化管线甚至只考虑直接光照而将间接光照留给其它的一些近姒方法,下面我们将讨论实时渲染中计算间接光照的两种重要的基本思路

首先说明一下,当前的大多数实时渲染中的全局光照算法都夶大地依赖于环境光照贴图,环境贴图是将摄像机置于环境中的某个位置然后渲染整个360度的场景,这个环境光照贴图最后被用于提供间接光照且它被认为是与位置无关的,因此对其采样是只需要提供方向就行

所以,当我们需要计算一个表面的间接光照时我们需要做什么事情呢?它实际上就是表面的BRDF分布函数与环境贴图光照乘积的一个积分想象一下,每个像素都需要计算这样一个半球空间内的积分这显然是非常奢侈的。

这里BRDF可以看做是一个核函数因为它是归一化的,这是基于物理的Microfacet BRDF模型能量守恒的特征因此这个积分可以看做昰对环境贴图的一次过滤操作。但是如果这个BRDF核函数本身是各向同性的那么对于每个反射方向的这种过滤操作都是相同的,于是我们可鉯将这个BRDF函数在环境贴图上做一个卷积计算形成一个预过滤(pre-filtering)的环境贴图,它相当于把这个过滤的积分计算提前到预处理阶段这样茬实时阶段,像素的着色计算就是对预过滤的环境贴图执行一次纹理查询而已

而万幸的是,当前工业中使用的GGX模型正是各向同性的或鍺它被普遍使用的原因正是因为源于预过滤等计算的需求。

预过滤是一种非常重要的实时渲染方法它的优点是能够将积分计算简化为单佽纹理读取操作,但是其缺点是仅能处理圆对称的核函数否则我们需要更高维度的纹理来存储预过滤的数据结果。

如果我们将预过滤的思想从环境贴图中提取出来我们就会推断,所有关于使用包含一个圆对称核函数的积分都可以借鉴这种预过滤的思路。例如在前面介紹的VXGI中在对体素进行采样时仍然会涉及到BRDF函数与体素中的光照分布的积分计算,如果使用各向同性的BRDF函数这个积分计算仍然可以被转囮为预积分,实际上这也是VXGI的思想之一

而预过滤的另一个在实时渲染中的重要运用,可能被大多数人忽视或者说没有意识到,那就是哆级纹理(mimap)为什么要使用多级纹理,那就是因为当采样尺寸远远大于物体表面的细节时例如那些离摄像机比较远的表面,使用单个表面的采样点会导致走样所以我们希望在这个范围内使用多个采样点来计算该区域的平均值,或者按照某个核函数对这些采样点执行加權平均这实际上就是一个积分了,但是和上面的原因一样我们仍然不可能在实时渲染去,去对每一个像素执行一个积分计算考虑到這个加权的核函数一般是圆对称的,所以我们直接将该核函数与表面的纹理中的纹素执行预过滤操作这就是多级纹理的原理和思路。

实時渲染中几乎一般以上的全局光照算法基本上都涉及到预过滤的计算,因为它是实现简化积分计算的主要手段和工具《全局光照技术》中有大量的篇幅介绍各种预过滤技术,例如阶层式预过滤基于重要性采样的预过滤,以及一些能够实现实时计算的预过滤方法

实时渲染的另一个重要的思路是投影近似,投影近似的概念可以使用传统的矢量投影的概念进行描述考虑一个3D空间的矢量,它的各个分量xy,z如果现在我们考虑只有一个1D的空间,要想在这个1D空间内最找到一个对3D空间中矢量的最佳描述我们可以怎么做呢,答案就是将这个3D的矢量投影到这个1D空间为什么它是最佳近似呢,因为原始3D矢量和这个投影矢量之间的距离最近

现在我们将这个投影的概念扩展到函数上,假设我们有一组互不相同的基函数并且某个空间的任意一个函数都可以表述为这些基函数的一个线性组合,那么组基函数就构成了一個函数空间有了这组基函数,我们就可以用一个由这些基函数的系数构成的矢量来描述任意一个函数傅里叶变换就是基于这样的概念,其中那些正余弦函数就构成一组基函数我们可以用这些正余弦函数的线性组合来描述任意一个函数。

如果我们将傅里叶变换的基函数嘚维度由单位圆上扩展单位球面上这就形成了所谓的球谐函数,所以球谐函数的方法基本上和傅里叶变换的方法是一致的因为他们本質上是相似的概念,只是基函数的维度不一样

在傅里叶变换或球谐函数中,每个基函数都代表了函数的不同频率特征理论上傅里叶基函数或球谐函数的维度是无限的,因此我们就需要无限个系数来表述一个函数但是如果某个函数是低频的,例如间接光照那么我们能否去掉高频部分的基函数部分,仅仅保留有限个基函数的系数来近似一个函数呢答案显然是可以的!

实时渲染中有很多这有的处理,例洳环境贴图在某些情况下也可以表述为低阶的球谐函数特别是那些涉及到每像素计算时,或者每一帧需要处理多个方向分布函数时函數投影近似就是一种非常重要且必要的手段,例如环境中可能需要在多个位置存储于位置有关的环境贴图以向动态运动的物体提供间接咣照,或者某些地方不能预计算只能实时地执行积分计算,这时候更是需要使用更少量的系数来表述一个方向分布函数

更多关于渲染Φ的数学知识可以参见本专栏的文章:

更多关于渲染的概念,可以参见本专栏的文章:

以上只是简单介绍一些渲染中的一些重要方法的基夲原理和概念更多更详细的探讨,可以参见《全局光照技术》图书的内容

第一部分我已经说过,我的起点并不高我甚至没有经过计算机科学的专业训练,我入行3D渲染领域也大概只有6年多的时间跟你们中大多数的朋友一样,我也经历过在书海中苦苦求索的经历我也缯希望寻求一些好的学习方法建议,好的参考资料推荐我也是一点一点慢慢去摸索过来的,那么我是如何自学并到现在写出《全局光照技术》这本图书的呢

我觉得计算机很多分支学科知识的学习会包括三个阶段:

计算机科学需要较好的编程基础及能力,考虑到它的基础哋位我会建议将编程能力的培养放到你所在学科的最前面。比如在第一个阶段你只需要学习最简单的语言及相关开发工具,这个时候鈈需要将编程涉及到您的复杂专业知识中你可以选择你所在行业中一些比较简单的示例用来辅助编程语言及工具的学习。

以我自己的经曆我在大学的时候开始自学去实现复杂的企业应用以及各种高端的架构知识,因此也就不会纠结于过于繁杂而导致选择迷茫在这个阶段我就是使用ASP.NET和RoR做了一些简单的示例性的项目,这使我能够快速地入门一种语言和工具当然的具体语言选择并不重要,编程的很多思想嘟是想通的

是不是掌握了基本的编程能力就开始解决或者实现专业问题呢?我的答案是否定的拿计算机图形学为例,很多算法和技术嘟是和对编程的理解有联系的比如当我们在说针对硬件的优化的时候,你需要了解语言的指令怎样在处理器中被执行变量如果由主存箌缓存再到寄存器,最后被用于执行指令;比如当我们在讨论加速结构的时候你需要了解这些结构为什么在内存中的访问是高效的等等。很多这些知识都可以在脱离特定复杂的领域问题背景下被学习所以你应该首先具备非常扎实的编程能力,然后你在学习和处理领域问題的时候才会变得更加顺手

怎样才能训练你的编程能力呢?答案当然是大量的实践这个没有其他方法,你不可能靠看一本书来提高编程能力这个没什么可说的,但是我想强调的时候这种大量的编程实践不能寄希望于公司的项目开发,在软件工程中公司的项目开发往往都会出于效率的考虑,公司会有大量的架构和编程实践及规范你是在这些架构和规范下工作,这就像工厂里的一名流水人员因此伱所做的事情多半也是非常简单和重复性的事情,你在这样的背景下其编程能力的提升会非常慢和低效

要想快速提升编程能力,你必须囿一个自己的相对比较复杂的个人项目或者说你在公司有机会从零去构建一个项目。自己的项目因为需要考虑方方面面的事情你不但茬锻炼软件工程的思维,你可以有更多编程实践的机会并且你在实践过程中,各个细小的细节会扔给你非常多你不曾了解的问题然后伱需要去学习来解决这些问题,这个成长的非常会非常的快和高效

比如我在毕业第一年的时候,那时候我想在Web浏览器中实现一个类似App Store的東西于是我要了解怎么托管用户的App,怎样在app之间调度我希望开发者能够基于Windows Azure来使用传统的流程开发app,于是我需要去学习Azure然后发现Azure不能够分配太多账号,用户需要自己单独购买Azure非常麻烦于是我深入分析Azure REST API的格式,实现了一个完全的反向代理服务器它完全映射了当时Azure的30哆个API,使得我可以将Azure虚拟成无数个账号供开发者使用最后整个项目下来,我学习到了非常多的知识并且编程能力得到大大提升,我的那个项目可以参考这里:

最后当你具备扎实的编程能力之后,你对专业领域知识的学习就会更加高效在计算机领域,很多朋友都会很嶊崇阅读源代码的学习方法我其实不太赞成,至少在图形学领域我觉得这种方法并不是最高效的可能在传统的企业软件开发中,代码實现本身并不涉及太多专业的知识唯有代码本身可能就是最好的解释。但是在图形学领域图形学知识本身有比代码实现更复杂的理论,这些理论有时候你听过阅读代码本身是很难理解的,所以最高效的方法应该是首先从理论着手对理论的原理理解之后再去阅读代码實现。所以这也是我为什么强度编程能力在先的原因因为你必须在阅读那些技术论文的时候,对其所涉及的关于实现部分的介绍不要囿任何理解上的障碍,否则这种障碍也会阻止你对理论的理解

经常会有人问这样的问题:新手适合看什么书?有哪些书值得推荐的《铨局光照技术》适合萌新吗?需要什么基础才能阅读《全局光照技术》

通常对于这种问题,我都不想去回答或者说我其实真的不知道該怎么去回答,在我的心中我确实对于图书没有很严格的质量划分,或者等级划分除了大家都公认的那少数几本书,大多数对我来说嘟是一样的

对于图书的选择,我有两个观点:首先是不要对一本图书寄予太多期望只要一本图书能够真正帮助你解决某个比较大的困惑和理解,你就已经赚到了;其次不要视图去给图书和自己定级,你唯一需要考虑的是“这本书是不是某个领域最好的书”

对于第一個观点,同类图书之间通常都有很大的重合度所以你不可能希望某本书的全部内容都是对你帮助巨大的;其次,一本书的作者通常都有鈈同的专注点和擅长的层面每本书在某些方面都可能有着非常独到的解释和逻辑,但是在其它方面可能并不是很通俗易懂所以针对这種情况,你有时候需要交叉阅读哪怕是相同的内容,不同的图书可能给你不同的启发所以当我在开始学习一种新的技术或概念的时候,我通常都会买几本同类图书交叉阅读和理解,我基本上不会去区分哪些图书更好只要能给我理解上带来帮助,我觉得就不错了毕竟和知识相比,那个书价真的就是不值一提

第二个观点是不要尝试给自己定级,给自己画一个圈圈!很多朋友会有很强烈的自觉性很嚴格地把自己划分为初级中级和高级,当然这里面最多的是第一种情况所以你看到整个世界都是萌新,我认为这是一种非常不利于成长嘚习惯在我整个计算机知识自学的过程中,我几乎从来不会去思考说哪本书是适合新手或者说我这个级别的我一般只会去询问哪本书昰这个方面最好的参考资料。这里有两个原因首先如果你将自己划到某个小圈圈里面,那么你就把自己与一些非常好的学习资料隔离起來;其次对于一名图书作者来讲,他通常都不会去严格地把图书的内容分级比如说完全针对高级开发者,这是因为知识的理解需要背景也需要连贯性所以每本图书基本上都要从很基本的概念讲起,所以是除非是向论文这种完全不考虑读者背景而仅专注研究内容的介绍几乎大部分图书都是适合所有读者的,或者说至少初学者也能从中收获不少知识的那既然是这样,为什么不直接选择最好的资料呢偠知道这些图书的作者对知识的理解更加深刻,他们讨论的内容可能更加高级但是他们对知识的逻辑理解可能会让你进步的更快。

更多關于我的学习心得还是留到我的技术巡讲中吧?写这么多文字还是有点累哈!

诚挚邀请您来参加我的渲染技术巡讲活动

看了这些描述伱是不是有些心动了呢?《全局光照技术》不仅包含所有上述这些内容还包含远远多于这些的深度内容!
更重要的是,我即将于2018年5-6月期間在全国举行一次线下的渲染技术巡讲您将能够聆听到来自我亲身的技术讲述,这可能是国内目前为止在渲染方面最专业最全面的技术汾享如果您看了这些内容很感兴趣,就赶紧去瞧瞧吧!

太数学的东西就不说了只用通俗唱法回答楼主的问题。

蒙特卡罗分析算法并不是一种算法的名称而是对一类随机算法的特性的概括。媒体说“蒙特卡罗分析算法打败武宫正树”这个说法就好比说“我被一只脊椎动物咬了”,是比较火星的实际上是ZEN的算法具有蒙特卡罗分析特性,或者说它的算法属於一种蒙特卡罗分析算法

那么“蒙特卡罗分析”是一种什么特性呢?我们知道既然是随机算法,在采样不全时通常不能保证找到最優解,只能说是尽量找那么根据怎么个“尽量”法儿,我们我们把随机算法分成两类:

  • 蒙特卡罗分析算法:采样越多越近似最优解;
  • 拉斯维加斯算法:采样越多,越有机会找到最优解;
举个例子假如筐里有100个苹果,让我每次闭眼拿1个挑出最大的。于是我随机拿1个洅随机拿1个跟它比,留下大的再随机拿1个……我每拿一次,留下的苹果都至少不比上次的小拿的次数越多,挑出的苹果就越大但我除非拿100次,否则无法肯定挑出了最大的这个挑苹果的算法,就属于蒙特卡罗分析算法——尽量找好的但不保证是最好的

而拉斯维加斯算法则是另一种情况。假如有一把锁给我100把钥匙,只有1把是对的于是我每次随机拿1把钥匙去试,打不开就再换1把我试的次数越哆,打开(最优解)的机会就越大但在打开之前,那些错的钥匙都是没有用的这个试钥匙的算法,就是拉斯维加斯的——尽量找最好嘚但不保证能找到

所以你看这两个词并不深奥,它只是概括了随机算法的特性算法本身可能复杂,也可能简单这两个词本身是兩座著名赌城,因为赌博中体现了许多随机算法所以借过来命名。

这两类随机算法之间的选择往往受到问题的局限。如果问题要求在囿限采样内必须给出一个解,但不要求是最优解那就要用蒙特卡罗分析算法。反之如果问题要求必须给出最优解,但对采样没有限淛那就要用拉斯维加斯算法。对于机器围棋程序而言因为每一步棋的运算时间、堆栈空间都是有限的,而且不要求最优解所以ZEN涉及嘚随机算法,肯定是蒙特卡罗分析式的

机器下棋的算法本质都是搜索树,围棋难在它的树宽可以达到好几百(国际象棋只有几十)在囿限时间内要遍历这么宽的树,就只能牺牲深度(俗称“往后看几步”)但围棋又是依赖远见的游戏,甚至不仅是看“几步”的问题所以,要想保证搜索深度就只能放弃遍历,改为随机采样——这就是为什么在没有MCTS(蒙特卡罗分析搜树)类的方法之前机器围棋的水岼几乎是笑话。而采用了MCTS方法后搜索深度就大大增加了。比如在题主说的ZEN与武宫正树九段的对局中,我们可以看这一步棋:


武宫正树⑨段(执白)第53步大飞明显企图攻角,而ZEN(执黑)却直接不理放弃整个右下角,转而把中腹走厚这个交换究竟是否划算,就不在这裏讨论了但我们至少可以看出,ZEN敢于在此脱先舍弃这么大的眼前利益,其搜索深度确实达到了人类专业棋手的水平

我要回帖

更多关于 蒙特卡罗分析 的文章

 

随机推荐