表面着色器分析。
ok这个视频来分析一下表面着色器的实力。这个会做一个小人的模型的膨胀,对模型进行膨胀。这是这个模型,拖动它就会让它膨胀,就是模型的膨胀。这种效果实现就是在顶点修改函数中沿着顶点法线方向扩张顶点位置。
为了分析表面着色其中四个可定性自定义函数顶点修改函数,表面函数光照函数和最后的颜色修改函数的原理,接下来这个函数全部采用自定义的实现,来看一下它的代码。
这个就是首先partitis定义面板的属性还有subsider,对结构体。然后在顶点修改函数中,使用顶点法线对顶点位置进行膨胀。表面函数使用主纹理设置了表面属性中的反射率,并使用法线纹理设置了表面法线方向,光照函数实现了简单的兰博特反射函数。
光照模型在最后的颜色修改函数中,简单使用了颜色参数对输出颜色进行调整。终于除了四个函数外,在program surface的编译指令中还指出了一个额外的参数。在这里由于修改了定电位置,因此要对其物体产生正确的阴影效果,并不能直接依赖 fourbag中找到的阴影阴影投射奖pass。
而色素参数可以告诉我们,因为题要生成一个该表面着色器对应的阴影同时 pass。默认情况下应体会为支撑所支持的渲染路径生成相应的 pass。为了缩小自动生成的代码量,使用了include pass deferred和 include passpropass来告诉应用体不要为延迟渲染路径生成相应的 pass。
最后使用nomait参数取消,采取元素原数据的 pass 的生成。当在该表面着色器的导入面板中单击so jerryt 的 code 按钮后就可以看到应用体生成的顶点片缘着色器元素的生成。
接下来来需要看一下在不一样的用体版本中会生成的代码有许多不同。然后接下来来看一下这个。首先来看第一个方向渲染,在用体中生成前向渲染 pass的分析。
·首先看第一点,这里这里是顶点着色器word serve和片缘着色器 frank serve都是自动生成的这些。然后之后出现的是一些自动生成的注视,就是这些注视。
·接下来就是这一个,看unity会定义一些红来辅助计算。在这里实际上就是这些红并没有被用。用到这些红是为了在修改了表面法线的情况下辅助计算得到世界空间下的反射方向和法线方向与之对应的是input结构体中的一些变量。
·接着unt把表面着色器编译的 c g 代码复制过来,作为 pass 的一部分,方便后续调用。
unt定义了顶点着色器到片缘着色器的差值结构及顶点着色器的输出结构。r f aux在定义之前 unt 使用仅isif语句来判断是否生成。使用光照纹理并为不同的情况生成不同的结构体,主要的区别是如果没有使用光照纹理,就需要定义一个存储竹顶点和 s h光照的变量。下边是这个,除了它的结构体之外,就看它的光照变亮。
在这里边有很多变量看起来比较陌生,但实际上大部分变量的含义在之前有碰到过,只是在这里使用了不同的名称而已。
比如说在下面看到b big 0中,实际上存储的就是主纹理和法线纹里的采样坐标。而e 1cm space 0.2cm存储了从切线空间到世界空间的变换。矩阵一个比较陌生的变量是be light,应用题会把主顶点和 s h光照的结果存储到该变量里,并在片缘着色器中中和云光照结果进行叠加。
随后用题定义了真正的顶点着色器。顶点着色器首先会调用自定义的顶点修改函数来修改一些属性,也是他的顶点着色器。顶点着色器用于计算vrf stag中各个变量的值。
比如说计算经过x v difference变化的顶点坐标使用 light v 内置红,计算两个纹理的采样坐标并分别存储在o 点 source x y 分和z w分量中。计算从倾斜空间到世界空间的变换矩阵,并把矩阵的每一行分别存储在o 点 t space 0.o 点 t space 一 o 点 t space 2变量中。
判断是否使用了光照映射和动态光照映射,并在需要时把两种光照纹理的采样坐标计算结果存储在o 点 lamp x y和o 点 l lamp z w分两种判断。
是否使用了光照映射,如果没有就计算该顶点的 sh光照,它是一种快速计算光照的方法,把结果存储在o v light中。判断是否开启了主顶点光照,如果是就计算最重要的四个主顶点光照的光照结果,把结果叠加到o v light中这部分代码。
可以在后面看,然后接下来看起阴影坐标传递给片圆着色器,接下来是会在pass的最后用题定义了真正的片圆着色器。
用题是首先利用叉指后的结构体vrs 裸来初始化input结构体的变量。这一块,随后 unit 声明了一个 surface output结构体的变量,并对其中的表面属性进行了初始化,再调用了表面函数。在这些代码中unit 会使用了井 eve deface这个语句判断当前的编译语言类型是否是h s l ver 意思。
如果是用更严格的声明方式来表示就是surface output结构体。因为斡平台往往有更加严格的语音要求,当对各个表面属性进行初始化后,用体要用了表面函数 self来填充这些表面属性之后用题进行了真正的光照计算。
首先计算得到光照衰减和世界空间下的法线坐标,在这里计算了光照衰竭和世界空间下的法线坐标,其中这里的变量c是用于存储最终的输出颜色,此时被初始化为零。随后应题判断是否关闭光照映射,如果关闭就把主顶点的光照结果叠加到输出颜色中。后边就是这个井ifdiff如果需要使用光照映射unt就会使用之前计算的光照纹理,采样坐标对光照纹理进行采样并解码,得到光照纹理中的光照结果这部分代码读者可以在生成的代码中找到这里不再做饱腹。
如果如果没有光照映射,这意味着他需要使用自定义的光照模型计算。这个是自定义的光照模型。
·而如果使用光照映射,用体会根据之前有光照纹理得到的结果,得到颜色值并叠加到输出颜色c中。如果还开启了动态光照画中画,用体还会计算对动态光照纹理的采样结果,同样把结果叠加到输出颜色c中这部分。
·然后最后我们unity shader要用自定义的颜色修改函数对输出颜色 c进行最后的修改。就是这样返回一个c,在这个代码中unit 还使用了那只红unit sau queen 跟a player就是这个。
这一个来重置片状圆的通透明通道。在默认情况下,所有不透明类型的表面着色器的透明通道都会被重置为一点零。而不管我们是否在光照函数中改变了它。
如上所述,如果我们想要保留它的透明通道,可以在表面着色器的编辑指令中添加keep keep up,保持透明。所以说到底forward pass就结束了接下来forward and pass和上面的forward pass基本类似,只是简代码会更简单一些。
最后一个重要的 pass 是山东casterpass,相对于之前的两个 pass 的代码更比较简单胆小。短小它的生成原理也很简单,就是通过调用自定义的顶点修改函数来保证计算阴影时使用的是和之前一致的顶点坐标。
然后这些就是讲了一个液体shader里的表面着色器的实力的分析。
最后补充一下unity shader 的缺点。缺点主要是三点。
·第一:如果你需要和各种光源打交道,尤其是想要使用应体重的全局光照,你可能更喜欢使用表面着,但需要小心它的性能。
·第二:如果你需要处理的光源数目非常少,只需要一盏平行光使用顶点偏远着色器是更好的选择。最重要的是如果你有很多自定义的渲染效果,请选择顶点偏远着色器,否则会非常非常的浪费。