找回密码
 立即注册
查看: 329|回复: 2

技术美术成长之路——Games101图形学篇(三)、着色及 ...

[复制链接]
发表于 2022-7-29 15:55 | 显示全部楼层 |阅读模式
本文参考Games101课程,文章链接:
如果想要系统从头看的话,文章汇总如下:有问题欢迎留言!
回顾我们已经学到的东西:


其实我们现在能把模型很好的摆放好,然后投影出来,映射到屏幕上,但是再着色的时候,好像我们的一个个像素都还是一些简单的颜色,都是一些手动RGB输入的颜色,所以在这方面上我们还差点东西,也就是我们接下来的主要任务。




对比之后,上边纯色的视觉效果的真实度上并不如下面,这种不同角度看每个面的时候,颜色是有差异的。


其实核心就是着色技术——shading。
其实就是对于物体上有不同材质,材质和光照之间来作用得到最终的效果,这其实就是着色。
Blinn-Phong 着色模型



从图上来看可以把物体上的点分成三类:一个是没有光的,按理来说这个本该是黑色的,它能够亮,是因为Ambient lighting,环境光,是一种间接光,多次反射后接收到的光,这个光很复杂,但是效果上可以简化,不同点收到的这种光都差不多,可以认为恒定值。
还有一个你从任何角度来看都是一样的颜色,他也像第三种那么亮。这种就是漫反射的部分,Diffuse reflection,各个角度都是一样的效果,漫反射。
对于那些非常亮的高光部分,就是因为材质上更加接近镜子,产生的镜面反射,这个就是特定的角度上来看才会显示出高亮的效果。
那么我们怎么模拟这一效果呢?


对于输入:我们需要知道法线,光源,观察方向,以及此处表面本身的颜色,还有他的shininess,这个可以认为是光滑程度反光程度相关的一个量。
这里说的shading is local的意思:就是我们shading计算显示的颜色,就只是针对这个点进行计算,不管其他的像素给这一点的影响,只考虑该点以及光和视线再该点的情况。不考虑其他影响,就比如,不考虑阴影,不考虑别的地方的阴影是否投影到了该点上。




另外这里光照的方向会影响最终的亮度:


考虑周围一个单位面积接收到的能量。夏天和冬天冷暖的区别,就是夹角的变化,单位面积接收到的能量不一样。
这里的接收到的能量具体是多少呢?就是和光照法线夹角余弦成正比。这是关于接受光。
下面来说发射光:


有一个点光源,他是不停的向外发射能量的,那么在某一时刻发出的那一份能量,由于各个角度平均发射,所以我们可以看作是一个球形发射出去。而我们把观察对象放在这个球上,随着时间的推移,光线往外传播,也就是球不断在扩大。
但是由于能量守恒,我们那一刻发射出去的能量,总数是不变的。所以考虑到一个点上的能量就会变小,也就是intensity会变小,假设我们在半径为1的球上,intensity为I,而到了半径为r的球上,intensity就是I/r^2.(用面积公式进行推导就行了,这里说点有点不太恰当,单位面积更好理解。)
那么我们对于点光源,我们能够知道有多少光传到了某一个shading point上,同时还知道有多少光被他吸收,从而就能算出关于diffuse的表示:


这里的I表示点光源出来的能量总能量,然后到达shading point之后的是需要除以r^2,然后由于到达的时候时有倾角的,所以不是完全到达,需要打折扣,也就是这里乘以一个余弦。
那么我们考虑物体的颜色是怎么来的,其实是白光到达物体表面,他会吸收除了他本身颜色以外的光,那么剩下的它本身颜色的光不被吸收,就给反射出去了,所以呈现出的颜色就是它本身的颜色。
那么这里我们也是可以模拟这一点的,从能量角度来说上边这一点,就是发射过来到达我这一点有很多能量,但是我只吸收其中的一部分。那么我们就可以在我们刚刚的基础上再乘以一个系数Kd,表示最终吸收的能量。
而实际情况的吸收具有选择性,也就是吸收特定的光,发射特定颜色的光。这一点我们怎么处理?其实就可以把Kd系数给改成一个向量,变成具有rgb分量的一个颜色,那这样就可以实现选择了。
所以从能量的角度先进行模拟,然后得到带有系数的形式,然后再根据光照射过程的颜色效果,进行对系数改造成一个向量,就得到了最终的表达式。(其实这也是为啥之前老有说diffuse系数就是颜色,终于明白了。)
补充一下,这里由于各个方向都反射出去,那么最前面是否需要一个系数呢?按理说是的,但是这个模型本身就是一个近似,所以就没有了。
这里是漫反射,各个方向都是一样的结果,得到的都是一样的强度,一样的颜色。


上边都是漫反射的部分,下面我们来加入高光的计算!
首先怎么去定义什么时候才会产生高光。其实就是反射方向接近镜面反射,也就是对于一些非常光滑的表面发生的反射。
这里说的反射方向接近镜面反射,可以对比漫反射的来进行理解。我们说漫反射反射的角度是各个方向的,而这里只是集中在一小片区域,所以他能量更集中,更强,显示出高光。
集中在哪一小片区域呢?就是先作为镜面反射算出反射光线,就是集中在反射光线附近。那么意味着我们只有在反射光线附近观察的时候,才会看到高光。


也就是其中的v和R方向接近的时候。其实针对这一点判断v和R的接近程度来衡量光照强度就是phong模型,而bliin-phong有啥升级呢?


就是我们刚刚用来衡量高光强度的v和r接近程度,他和另外一个接近程度是正比的,就是上图中的n和h的接近程度。h是啥呢?就是v和I的角平分线,叫做半程向量。
半程向量和法线之间的夹角其实就是v和r之间角度的一半,怎么理解?看两个角,i和v形成的角,i和r形成的角,他俩角的差值是v和r夹角β。而i和v形成的角,i和r形成的角,各取一半就是i和h,i和n,那么这俩之间的夹角就是β的一半,也就是α。而这里为啥说是升级呢?其实就是因为在计算上,半程向量非常容易,俩向量相加规范化就行了。
但是如果想要算反射方向r,计算量会很大!
所以看上边的公式,对于I/r^2,还是用来表示到达这里的光,然后用夹角余弦来衡量强弱,同时类似的,我们的系数也会是一个颜色,而对于高光,经常考虑是白色的,所以镜面反射系数Ks一般考虑为白色。
注意你会发现这里并没有考虑多少能量照射到了表面,只是除以r^2,表示这个距离处的能量,但是具体到达表面多少是和照射的倾角有关的,也就是那个Lambert余弦。
这确实是需要的,但是没有写还是因为她只是一个经验模型,进行了简化,主要关注高光的部分。另外你会发现这里有一个指数p在这里,其实在之前软光栅也接触过这种指数,目的是为了放大差异性。就是降低容忍度!


我们按照上图,如果直接用余弦,那么都45度了,还有一个明显的高光存在,这就不合理了。范围应该是非常集中的。所以加上指数可以解决这个问题。
正常情况下,会把次数放到100~200.


下面是漫反射和高光共同作用的情况,同时对Ks和P进行一个变化的效果。
接下来是环境光项:


因为环境光本身很复杂,所以简化为任何一个点都一样,都是Ia的强度。然后给他配上系数,这里就搞成颜色。这里La不受入射反射观察等等的影响,是一个常数。
那么他其实就是一个常数的颜色,也就保证了任何一个物体都具有一个常数颜色,让场景中物体都有这么一个基础的颜色亮度,不是纯黑的。这个颜色会很平。


第一个颜色很平,第二个和光照角度有关系有明暗,第三个就是突出一些部分亮度。
最后三个加起来之后的结果,就是blinn phong模型的最终结果了。
着色模型,我们考虑的是一个shading point的研究,那么下一步就是我们要对所有的点都考虑一遍,整个模型场景就完成了着色。
就是我们一直没考虑物体和观察点之间的距离对结果的影响,其实这个是没有影响的,这个以后解释,先作为结论。
接下来说的是着色频率。


注意这仨图是完全一样的几何表示,也就是模型是一样的。从边界可以看出来。但是着色之后的结果为啥不同呢?其实就是和要说的着色频率有关系,也就是把shading应用到谁身上,也就是选谁作为shading point。
第一个就是一个平面做一次shading,算三角形的法线。第二个就是每个平面的顶点进行shading,而内部的像素,通过插值得到最终的颜色。最后一个就是针对每一个像素有自己的一次shading,计算顶点法线,通过插值计算像素的法线。
所以:平面——顶点——像素。他仨有自己的名字:


通过两边叉积求平面法线。


这个算顶点的法线,然后对顶点shading,得到顶点颜色,最后进行像素颜色插值。


这里区分Phong着色模型,而这里的Phong是一种着色频率。


其实这个针对效果并没有绝对谁好,她一定程度上取决于模型,当模型三角形非常小,模型足够复杂时,这时候就不一定了。
我们现在有俩问题,就是顶点的法线。
针对一些特殊的你知道模型表示的是啥,比如球,那么顶点法线肯定是过圆心的,但是这种情况并不常见。多数的情况怎么来求呢?


就是拿面的法线来做一个平均。针对直接求平均可能有点草率,考虑一些很大的三角形和一些小三角形共用的时候,大三角形贡献可能更多一些,更有决定性的。
所以可以进行一个加权平均,权可以根据面积来确定。
对于逐像素着色的,我们要获取逐像素的法线,也就是通过插值来获得,这里是用重心坐标来进行插值。


其实到现在,我们已经把着色模型介绍了,然后拿着着色模型怎么使用,关于着色频率相关的也都说了,也就是说,我们从最开始的模型三角形,现在已经能够得到完整的图像了。
那么把我们从头到尾所有的东西放在一块就是图形管线了,这也叫实时渲染管线。


这里注意一下,我们在刚开始,只是对顶点进行一个投影,然后投影之后再进行三角形的建立。其实这就是索引的做法,好处体现,就是我们只需要对顶点进行变换,变换完成之后我们在进行三角形的构建,这样绝对不会出现重复操作顶点,而如果以三角形来进行投影,那么就会出现顶点的重复投影。








这里注意,shading在顶点和像素过程中都有涉及,这是因为考虑到不同的着色频率。 比如对于每一个顶点进行着色的操作,这时候就是着色发生在顶点上。
而Phong shading这种就是像素着色中进行了,你得先栅格化成像素才ok啊。
那么最主要的就是针对像素和顶点是怎么着色的,所以现在对于现在GPU的管线中,这俩是完全可编程的。而变成的东西就是shader,控制顶点和像素是如何进行着色的。


写Shader,其实是能够在硬件上执行的语言,每一个像素都会去跑一遍像素shade的程序,顶点同理。
上边给出了一个像素着色的示例,作用是给出我们一个颜色。
其实到此,整个成像过程,实时渲染,到此都已经涵盖到了。现在这个基础上就可以去学习一些图形API了,去写一些真正的实时渲染的代码了。
这里推荐了一个shadertoy,就是只关心shader,免去了其他的部分。
这个例子是用几何形体来定义的,几何形体形体是通过数学的方式来描述的,隐式几何形体,并没有用任何的三角形。所有几何形体都是数学方法定义的。


shader,很牛逼,千变万化。
自己可以没事去shadertoy,写一些shader。


随着GPU硬件发展,高度并行(比如很多像素同时着色操作)快速处理。所以目标就是超复杂的场景的实时玩法。


硬件发展,GPU的可编程shader等等的。计算着色器,她可进行任何形式的计算,不一定是图形学内部的计算,通用的计算。叫general purpose GPU,即GPGPU。


GPU是一个高度并行化的处理器,cpu的有48核,64核,核心的数量也就是并行线程的数量。 而GPU的核心很多,超级多,但是他每个计算力比较弱,所以非常适合图形方面的计算。
至此,基本上关于图形管线和着色的内容就完了。
下一篇再见,大家加油~~

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
发表于 2022-7-29 15:58 | 显示全部楼层
nb,你这看的够勤快的
发表于 2022-7-29 16:08 | 显示全部楼层
哈哈,一起加油啊~
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-25 11:46 , Processed in 0.093722 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表