首页 > 代码库 > 【Unity Shaders】使用CgInclude让你的Shader模块化——使用#define指令创建Shader

【Unity Shaders】使用CgInclude让你的Shader模块化——使用#define指令创建Shader

本系列主要參考《Unity Shaders and Effects Cookbook》一书(感谢原书作者),同一时候会加上一点个人理解或拓展。

这里是本书全部的插图。

这里是本书所需的代码和资源(当然你也能够从官网下载)。

========================================== 切割线 ==========================================



写在前面


我们已经看到怎样使用Unity内置的CgInclude文件。以及怎样创建我们自己的CgInclude去保存光照模型、变量和辅助函数。在这篇中,我们关注怎样更动态、有效地使用CgInclude文件,使得我们的Shader更加模块化,而且能够依据须要切换不同的状态。


因此,本篇中,我们将会改动上一节中创建的Half Lambert光照模型,为它加入一个定义(definition)。

这样,假设我们的Shader中定义了Half Lambert,那光照模型将会使用Half Lambert漫反射。否则就会使用标准的NdotL光照模型。


这节代码就3行,仅仅是个引子。



实现


我们首先再来看一下我们的CgInclude文件。

我们想要让该光照模型具有两个状态:

  1. 第一个状态。是正常的NdotL(Normal*LightDir)漫反射光照模型。而第二个状态,就是一个Half Lambert光照模型。改动我们的CgInclude文件去包括以下的两行代码:
    技术分享

  2. 然后,在我们的Shader中,更新CGPROGRAM块中的指令:
    技术分享

  3. 保存你的Shader,返回Unity编译。这时你不会看到不论什么变化。这是由于我们告诉Unity,去定义一个名为HalfLambert的指令,假设它在不论什么已包括的文件里找到了这个定义。它就会使用第一步中的代码。

  4. 返回Shader。然后凝视掉我们刚才新加的指令。

    保存后返回Unity查看:
    技术分享

这时就会发现。Unity没有使用Half Lambert,而是使用了标准的NdotL光照模型。

这时由于我们未定义HalfLambert,因此Unity在编译时将会跳过那段代码。这使得我们的Shader更加灵活有效,我们能够不再编写或删除大量反复的代码。




解释



如你所见,尽管这节代码仅仅有3行。但我们能够利用这些简单的技术来使得光照模型更加多变。通过使用#ifdef指令,我们告诉Unity去查找这个名称的定义,这里这个名字指的是HalfLambert

使用CgInclude来编写Shader。不仅能够帮助我们节省大量的代码,还能够存储大量的光照模型。

这使得我们更easy地去调用光照模型,或者使用多个状态去改动它。


这里讲到的这些技巧。事实上和C++里面的相关知识非常相似。而这些也是CG的知识内容。越学越感到。Unity尽管封装了非常多细节,但学习原始的Shader越显得重要啊。






【Unity Shaders】使用CgInclude让你的Shader模块化——使用#define指令创建Shader