第二章 表面着色器和纹理贴图

在这一章节,我们将会探索表面着色器的使用。我们会用一个非常简单的磨砂材质开始讲起,然后会在后面讲解全息投影和高级的地形混合。 我们将能够使用纹理制作动画效果,混合等,或者用着色器去驱动我们想要的属性。在这一章你将会学习下面一些表面着色器的使用方法:

  • 漫反射的着色处理
  • 使用包组
  • 向着色器添加纹理
  • 通过改变UV值来移动纹理
  • 法线贴图
  • 创建一个带透明度的材质
  • 创建一个有全息效果的着色器
  • 纹理的压缩和混合
  • 在地形的表面绘制一个圆

介绍

我们在第一章创建你的第一个着色器 已经介绍了表面着色器,这是Unity引擎中的主要着色器类型。在这一章我们将更详细的向你展示它到底是什么以及它具体是如何工作的。通常来说,每个表面着色器都有两个重要的步骤。 首先,你需要在材质中描述你想指定的物理属性,比如漫反射的颜色,光滑度和透明度等。 这些属性将会在一个叫表面函数 surface function的函数中初始化并且保存在一个叫表面输出 surface output的结构体中。其次,表面输出 surface output结构体传入到一个光照模型 lighting model中。这是一个特殊的函数,这个函数会获取场景周围的光照信息。所有获得的这些信息将会被用于去计算你的模型最终在每一个像素点上最终呈现出来的颜色。这个光照函数就是着色器真正进行计算的地方,而正是这部分代码,决定了使用这个着色器材质的光照表现。下面的示意图简单的总结了表面着色器时如何工作的。在第三章理解光照模型 将探索自定义光照模型,当学习到第五章顶点函数 会着重讲解顶点修改器:

漫反射的着色处理

在我们开始学习纹理贴图之前,了解漫反射材质时如何工作的显得尤为重要。具体的一些物体也许会有统一的光照和光滑的表面,但是可以还是不够光滑来反射光线。磨砂材质是漫反射着色器使用的一个典型代表 。然而我们现实世界中,完全漫反射材质是不存在的;漫反射着色器是一种成本相对比较低的实现方式并且在低多边形风格中有着大量的应用。


  • 始前准备

    有好几种方式来创建你自己的漫反射着色器。最快的一个方式是在Unity5中创建一个表面着色器然后编辑它,移除所有的纹理,跟我们前面学习的第一章创建你的第一个着色器 类似。


  • 操作步骤

    让我们开始创建我们的标准着色器,首先在Unity中新建一个标准着色器,然后按照下面的步骤进行修改:

    1. 首先在着色器的属性列表移除除**_Color**之外的所有属性:
    _Color ("Color", Color) = (1,1,1,1)
    
    1. SubShader{}代码块中,移除_MainTex_Glossiness和**_Metallic这三个变量。但是你不能删除uv_MainTex** 这个变量,因为Cg着色器语言不允许输入结构体为空。这个值会被Unity简单的忽略。
    2. 删除**surf()**函数内代码内容并且把下面代码放在里面:
    o.Albedo = _Color.rgb;
    
    1. 最终,你的着色器代码应该如下所示:
    Shader "CookbookShaders/Diffuse" 
    {
        Properties 
        {
            Color ("Color", Color) = (1,1,1,1)
        }
        SubShader 
        {
          Tags { "RenderType"="Opaque" }
          LOD 200
          CGPROGRAM
          #pragma surface surf Standard fullforwardshadows
          #pragma target 3.0
          struct Input 
          {
              float2 uv_MainTex;
          };
          fixed4 _Color;
          void surf (Input IN, inout SurfaceOutputStandard o) 
          {
              o.Albedo = _Color.rgb;
          }
          ENDCG
        }
        FallBack "Diffuse"
    }
    

    当这个着色器从标准着色器修改调整之后,那么这个着色器将会使用基于物理原理的渲染去模拟光在模型表面的表现。如果你想试着获得一个看起来不那么真实表现的话,你可以直接修改**#pragma部分,这样着色器就可以使用Lambert而不是Standard**。如果你这样修改了的话,那么你还应该用SurfaceOutput替换掉**SurfaceOutputStandard **。 按照书上的意思,应该是改成下图所示:


  • 原理介绍

    通过表面输出surface output,着色器可以让你材质的渲染属性跟光照模型lighting model进行沟通。 它基本封装了光照模型需要的所有参数。很明显,不同的关照模型肯定有着不同的表面输出结构。下表列出了在Unity中使用的三种主要的输出结构以及它们能如何使用:

    Type of shadersUnity 4Unity 5
    DiffuseAny Surface Shader:SurfaceOutputStandard:SurfaceOutputStandard
    SpecularAny Surface Shader:SurfaceOutputStandard (Specular setup):SurfaceOutputStandardSpecular

    表面输出SurfaceOutput结构体所包含的属性如下:

    • fixed3 Albedo: 材质的漫反射颜色

    • fixed3 Normal: 空间中法线的切线,如果有法线的话

    • fixed3 Emission:这是材质指定的光的颜色 (如果是标准着色器Standard Shaders的话,它会被定义为half3类型)

    • fixed Alpha: 这是材质的透明度

    • half Specular: 这是高光反射度【就是看起来多像高光?】,值的变化是从0到1

    • fixed Gloss: 这是高光强度

    标准表面输出SurfaceOutputStandard结构体包含以下的属性:

    • fixed3 Albedo: 这是材质的基本颜色(不管是高光反射还是漫反射)
    • fixed3 Normal:空间中法线的切线,如果有法线的话
    • half3 Emission: 跟表面输出结构体一样的意思,不过在这里定义为half3类型,而在表面输出结构体中定义为fixed3类型。
    • fixed Alpha:同表面输出结构体
    • half Occlusion: 这个是遮挡(默认是1)
    • half Smoothness: 这个是光滑度 (0 = 粗糙, 1 = 光滑)
    • half Metallic:金属质感 0 = 无金属质感, 1= 金属

    标准高光表面输出SurfaceOutputStandardSpecular结构拥有如下属性:

    • fixed3 Albedo:同上
    • fixed3 Normal:同上
    • half3 Emission:同上
    • fixed Alpha:同上
    • half Occlusion:同上
    • half Smoothness:同上
    • fixed3 Specular: 这个是高光反射的颜色,这个跟表面叔叔结构体中的高光反射有很大的不同,因为这里是用颜色表示,而在表面输出结构体中只是一个简单的值

    正确的给表面输出结构体赋值,初始化,是使用表面着色器的前提。