《Unity Shader入门精要》FAQ


说明:本页面是书籍《Unity Shader入门精要》的读者问答集锦,也包含了一些读者的建议,我们可能会据此来更新下一版中的相关内容,欢迎读者反馈。
作者:冯乐乐
邮箱:lelefeng1992@gmail.com
更新日期:2016年7月25日


Q1:关于Unity Shader中_WorldSpaceLightPos0的意义。在漫反射的计算公式中,光源方向I被定义成一个指向光源的向量,也就是说,相对于某一顶点,是由该顶点指向光源,我将之理解成了光源的反方向不知是否正确。我不是很清楚光源方向是如何由_WorldSpaceLightPos0来得到的。

A1:光照模型里面的光源方向的确是由顶点指向光源的,而且需要归一化。在Unity中,如果是平行光,_WorldSpaceLightPos0存的就是这个光源方向了,Unity传进来的已经是根据这个角度计算而得的方向值了。此时光源方向跟顶点位置没有任何关系,因为它的方向是固定的。我们可以尝试自己在C#里根据平行光的Rotation计算一个角度,这个方向可以理解是把模型空间下的Z轴经过Rotation变换后的世界空间下的一个单位矢量,再对该方向取反得到。如果是其他光源类型,那么这个值就是世界空间里的位置,那么光源方向自然就是该位置值减去顶点位置,再归一化。

Q2:在第一版的P34页中写到“表面着色器不需要开发者关心使用多少个Pass,每个Pass如何渲染等问题”,表面着色器不可以支持自定义的多Pass吗?

A2:实际上,利用一些dirty trick我们的确可以在表面着色器中实现自定义多个Pass。我们既可以定义多个表面着色器,还可以把表面着色器和顶点/片元着色器混用,但我们认为这样的Shader不易阅读和管理。

参考:
* http://answers.unity3d.com/questions/354774/multiple-pass-surface-shader.html
* http://answers.unity3d.com/questions/610316/multipass-surface-shader-or-equivalent.html

Q3:我感觉法线贴图那里讲的有点不清楚,我觉得这篇文章不错,希望可以借鉴一些。

A3:书的7.2节的确缺少一些关于法线纹理的起因、原理等方面的讲解,会在后续版本中加强。

Q4:我不理解下图红框中的内容,是如何由左侧的式子变换过来的?

image_1aog7fo441ui816jvobc1lan141f9.png-102.1kB

A4:该行的第一个公式是矢量点乘,读者可以注意到中间有个黑点。然后,为了推导到矩阵计算中,我们把矢量运算替换成了等价的矩阵乘法。因为本书默认矢量可以当成是列矩阵,所以第二个公式就是把它们当成列矩阵进行矩阵乘法,这样一来两个矢量就都被当成是n x 1的列矩阵。转置是因为矩阵乘法有行列规则,不转置的话这个乘法是没法进行的,不符合矩阵乘法定义。读者可以在纸上画一画,红框内的矩阵乘法结果也是一个标量,和第一个矢量点乘的结果是相同的。

Q5:书中第四章中说观察空间是右手坐标系,但是我在Unity中看到的“观察空间”是左手坐标系,如何理解?

A5:读者在Unity中并不能直观地看到观察空间。读者这里所谓的“观察空间”应该是点击场景中的Camera物体后、在Scene视图下看到的坐标轴,这个坐标轴表示的并不是观察空间,而是Camera这个物体作为一个普通的Gameobject的模型空间,它当然是左手坐标系。观察空间是无法在Unity中通过可视化的方式看到的,读者会在调用Camera.worldToCameraMatrix等API计算观察空间下的坐标时体会到该空间是右手坐标系的。