首先说明,博主是一位Shader的初学者,在大学里也是菜鸟一枚,只是对游戏有着热情才开始学习Shader,若有写的不好地方,望各位见谅。。。哈哈哈,废话不多说,开始正题。O(∩_∩)O

效果展示

unity转URP材质 unity换材质_Shader


一、基本概念了解

1.学过计算机图形学的同学都知道,计算机图形学中的渲染管线一共有两种:

1)固定功能渲染管线
2)可编程渲染管线

ps:渲染管线就是计算机绘制图形的过程:
   局部坐标系->世界坐标系->观察坐标系->背面消除->光照->裁剪->投影->计算视口->光栅化
  无论是固定渲染管线还是可编程管线,大致都需要经过这九个步骤

那么什么叫固定功能渲染管线和可编程渲染管线呢?

可编程渲染管线,从名字上就可以看出来了,可编程,所谓的可编程就是自己可以控制了嘛,就像API函数封装前的样子,可以自己随意修改达到自己想要的效果
   这是博主自己的理解,若有说的不好地方,希望大家指出。。。

   Shader,即着色器,着色器分为顶点着色器和像素着色器。
    顶点着色器是在进行坐标变换和光照计算时工作
    像素着色器是在光栅化环节工作

    人们对着色器进行自定义编程时,这个流水线就叫做 **可编程管线**
    当游戏或应用程序完全使用默认着色器程序时,这个流水线就叫做 **固定管线**

按照这两个管线来进行分类的话,unity中的shader大致也可分为三类:

1.固定功能着色器

2.表面着色器

3.顶点着色器&片段着色器

顾名思义

固定功能着色器便是我们所说的固定功能渲染管线的具体表现
表面着色器、顶点着色器以及片段着色器便属于可编程渲染管线。

表面着色器这个概念更多的只是在Unity中听说,可以说是Unity自己发扬光大的一项使Shader的书写门槛降低和更易用的技术。

   顶点着色器和片段着色器,应该很多学过DirectX和OpenGL的同学都不陌生:

   顶点着色器:产生纹理坐标,颜色,点大小,雾坐标,然后把它们传递给裁剪阶段。
   片段着色器:进行纹理查找,决定什么时候执行纹理查找,是否进行纹理查找,及把什么作为纹理坐标

那么,在unity中如何区分这三类Shader呢?

  • 没有嵌套CG语言,也就是代码段中没有CGPROGARAM和ENDCG关键字的,就是固定功能着色器。
  • 嵌套了CG语言,代码段中有surf函数的,就是表面着色器。
  • 嵌套了CG语言,代码段中有#pragma vertex name和 #pragma fragment frag声明的,就是顶点着色器&片段着色器。

二、Unity中Shader和Material的关系

Shader实际上就是一小段程序,它负责将输入的Mesh以指定的方式和输入的贴图或者颜色等组合作用,然后输出。绘图单元可以依据这个输出来将图像绘制到屏幕上。输入的贴图或者颜色等,加上对应的Shader,以及对Shader的特定的参数设置,将这些内容(Shader及输入参数)打包存储在一起,得到的一个就是Material。
   之后,我们便可以将材质赋予给合适的render来渲染输出了。。。所以说,Shader就是规定好输入和输出的程序。而shader的开发者就是要做根据输入,进行计算变换,产生输出而已。

三、Unity中基本Shader框架学习

先来看一段代码:

Shader "Custom/Lighting_Material" {

Properties
       {
          _MainColor("主颜色",Color) = (1,.1,.5,1)
       }
    SubShader
    {

      Pass
      {
         Material
         {
            Diffuse[_MainColor]
            Ambient[_MainColor]
         }
         Lighting On
      }
    }

   //备胎设为Unity自带的普通漫反射  
       Fallback" Diffuse "  
}

大致的框架为:

1.着色器通过properties来可选的定义一个可通过材质设定界面来自定义的列表。具体到上述代码中写的Properties,就是定义了一个基本属性,参数名叫做_MainColor,在编辑器中显示的名称叫做“主颜色”
2.后面紧跟着核心部分子着色器SubShader,里面的一个Pass里面设置了颜色为我们属性中定义的那个_ MainColor
3.添加一句Fallback代码用于应对我们Shader中的SubShader不能正确运行的情况,类似我们switch里面最后的default,当所有的通道都不能满足时就执行这个

四、Properties属性 相关写法列举

Properties { Property [Property ...] }

定义属性块,其中可包含多个属性,其定义如下:

name (“display name”, Range (min, max)) =number
定义浮点数属性,在检视器中可通过一个标注最大最小值的滑条来修改。

name (“display name”, Color) =(number,number,number,number) 定义颜色属性

name (“display name”, 2D) = “name” {options }
定义2D纹理属性

此处博主只列举部分,需要其他功能的请自行查阅

示例:

Shader "Custom/Lighting_Material_Beat" {
    Properties
    {
       _MainColor("主颜色",Color) = (1,1,1,0)
       _SpecColor("反射高光",Color) = (1,1,1,0)
       _Emission("自发光",Color) = (0,0,0,0)
       _Shininess("光泽度",Range(0.1,2)) = 0.7
       _MainTex("主纹理",2D) = "white"{}
    }
}

五、用于通道Pass中的代码写法列举

这些代码一般是写在Pass{ }中的:

Color Color
设定对象的纯色。颜色即可以是括号中的四值(RGBA),也可以是被方框包围的颜色属性名。

Material { Material Block }
材质块被用于定义对象的材质属性。

Lighting On | Off
开启光照,也就是定义材质块中的设定是否有效。想要有效的话必须使用Lighting On命令开启光照,而颜色则通过Color命令直接给出。

SeparateSpecular On | Off
开启独立镜面反射。这个命令会添加高光光照到着色器通道的末尾,因此贴图对高光没有影响。只在光照开启时有效。

ColorMaterial AmbientAndDiffuse | Emission
使用每顶点的颜色替代材质中的颜色集。AmbientAndDiffuse 替代材质的阴影光和漫反射值;Emission 替代材质中的光发射值。

示例:

Pass
       {
         Material
         {
           Diffuse[_MainColor]
           Ambient[_MainColor]
           //光泽度
           Shininess[_Shininess]
           //反射高光
           Specular[_SpecColor]
           //自发光
           Emission[_Emission]
         }
         //开启光照
         Lighting On
         //开启镜面反射
         SeparateSpecular On
       }

[]中的定义详见前面属性Properties中的定义

六、材质块Material Block 中相关写法列举

Diffuse Color(R,G,B,A)
漫反射颜色构成。这是对象的基本颜色。
Ambient Color(R,G,B,A)
环境色颜色构成.这是当对象被RenderSettings.中设定的环境色所照射时对象所表现的颜色。
`Specular Color(R,G,B,A) 
对象反射高光的颜色。(R,G,B,A)四个分量分别代表红绿蓝和Alpha,取值为0到1之间。`
Shininess Number
加亮时的光泽度,在0和1之间。0的时候你会发现更大的高亮也看起来像漫反射光照,1的时候你会获得一个细微的亮斑。
Emission Color 
自发光颜色,也就是当不被任何光照所照到时,对象的颜色。(R,G,B,A)四个分量分别代表红绿蓝和Alpha,取值为0到1之间。

示例:

Material
         {
           Diffuse[_MainColor]
           Ambient[_MainColor]
           //光泽度
           Shininess[_Shininess]
           //反射高光
           Specular[_SpecColor]
           //自发光
           Emission[_Emission]
         }

[]中参数的定义详见前面Properties中的定义,属性中的定义

七、Shader实战

1.纯色的shader

1)首先,我们打开Unity创建工程,创建几个文件夹分别是Material,Shader,Texture 这就不需要多说了吧

2)在Shader文件夹上点击右键Create->Shader->Standard Surface Shader,取名。。。

unity转URP材质 unity换材质_unity转URP材质_02


3)打开所创建的shader文件,删除原本的代码,输入以下代码

Shader "Custom/SingleColor" {
    //---------------------------------【子着色器】----------------------------------  
    SubShader  
    {  
        //----------------通道---------------  
        Pass  
        {  
            //设为蓝色单色  
            Color(0,0,0.5,0)  
        }  
    }  

    //FallBack "Diffuse"
}

4)保存shader文件,返回unity中,在Material上点击右键创建材质,将Shader文件拖到材质文件上

unity转URP材质 unity换材质_Shader_03

5)然后在场景中创建一个Cube,将材质赋予此Cube

unity转URP材质 unity换材质_渲染管线_04

是不是很激动呢,嘿嘿,毕竟这是自己写的第一个shader

2.光照&材质shader
一样的方法,在这里,博主就不多说啦。。。

Shader "Custom/Lighting_Material" {

Properties
       {
          _MainColor("主颜色",Color) = (1,.1,.5,1)
       }
    SubShader
    {

      Pass
      {
         Material
         {
            Diffuse[_MainColor]
            Ambient[_MainColor]
         }
         Lighting On
      }
    }
}

效果:

unity转URP材质 unity换材质_Shader_05


unity转URP材质 unity换材质_渲染管线_06

3.光照&材质&贴图

Shader "Custom/Lighting_Material_Beat" {
    Properties
    {
       _MainColor("主颜色",Color) = (1,1,1,0)
       _SpecColor("反射高光",Color) = (1,1,1,0)
       _Emission("自发光",Color) = (0,0,0,0)
       _Shininess("光泽度",Range(0.1,2)) = 0.7
       _MainTex("主纹理",2D) = "white"{}
    }

    SubShader
    {
       Pass
       {
         Material
         {
           Diffuse[_MainColor]
           Ambient[_MainColor]
           //光泽度
           Shininess[_Shininess]
           //反射高光
           Specular[_SpecColor]
           //自发光
           Emission[_Emission]
         }
         //开启光照
         Lighting On
         //开启镜面反射
         SeparateSpecular On

         SetTexture[_MainTex]
         {
           Combine texture * primary DOUBLE ,texture * primary
         }
       }
    }
}

在贴图属性中,shader赋予给材质以后,材质可选择什么纹理

unity转URP材质 unity换材质_unity转URP材质_07

unity转URP材质 unity换材质_unity_08

大家是不是都做完了呢。。。。。。好啦,今天就写到这里,谢谢大家的关注,时间不早了,写了一下午,吃饭去咯,希望能帮到大家,同时也是对我自己的一种鞭策吧,加油,骚年