Unity高级开发-Shader开发(3)-Shader编程

Unity高级开发-Shader开发(3)-Shader编程_第1张图片
01.png

1、什么是shader程序:

一段规定好输入(颜色,贴图),输出(渲染器能够读懂的点和颜色的对应关系)的程序。

shader分类:
  • 1、表面着色器:
    为你做了大部分的工作,只需要简单的技巧即可实现很多不错的效果。(本篇介绍这个)
  • 2、片断着色器:
    可以做的事情更多,比较难写。
    使用片段着色器的主要目的是可以在比较低的层级上进行更复杂(或者针对目标设备更高效)的开发。

2、shader的结构:

着色器:本身就是一段代码,专业性非常强的代码。就是指着色器有哪些输入。这些子着色器由运行的平台选择。它包含:1.属性定义、2.多个或者至少一个子着色器、3.还有一个处理后的结果即回滚。而回滚就是计算着色时,用来处理所有的子着色器不能运行的情况。

3、关于Shader脚本

3-1、创建一个自己的shader脚本
Unity高级开发-Shader开发(3)-Shader编程_第2张图片
02.png
3-2、如何选择我们创建的shader
Unity高级开发-Shader开发(3)-Shader编程_第3张图片
04.png

4、shader脚本介绍

Unity高级开发-Shader开发(3)-Shader编程_第4张图片
03.png
4-1、Properties : 属性
Unity高级开发-Shader开发(3)-Shader编程_第5张图片
05.png
  • 数值和范围
name(“display name”, Range(min,max)) = number
name(“display name”, Float) = number
name(“display name”, Int) = number
name("display name", Rect) = "name"{ options }

这些定义一些数值属性,每个等号后面表示默认的取值,name是给开发者给这个值起的可以在代码中访问的名字,display name则是在材质面板上显示的名字

  • 颜色和向量
name(“display name”,Color) = (number,number,number,number)
name(“display name”, Vector) =  (number,number,number,number)

定义颜色值RGBA和向量值(xyzw),在Shader的数学中,是一样的。Color会在属性面板上出现一个可供用户使用的调色面板按钮。Vector则是在面板上出现可以填写数字的栏

  • 贴图
name(“display name”, 2D) = number
name(“display name”, Cube) = number
name(“display name”, 3D) = number
 // 后面texGen 是纹理生成模式(ObjectLinear , SphereMap,CubeReflect,CubeNormal),一般自定义的shader不会使用这些模式
name(“display name”, 3D) = "white"{ texGen Eyeliner }

定义2D贴图,CubeMap和3D贴图,等号后面都是默认的图,都是空字符串或者是Unity定义的“white”,"black","gray","bump".

  • 补充
    Unity内定的一些属性列表:
    [HideInInspector] 不显示对应的属性值
    [NoScaleOffset] 默认贴图面板带有tiling和offset属性,这个让它们不显示
    [Normal] 该帖图放进来是法线图
    [HDR] 该帖图期望是HDR的图 ,HDR:高动态光照渲染(High-Dynamic Range,简称HDR)图像
4-2、SubShader - 子着色器的实现

一个Shader中可以有多个SubShader(子着色器)实现,子着色器定义了一个渲染通道的列表,并可选是否为所有通道初始化所需要的通用状态。

SubShader
{
    Cull off // 双面显示
Blend One One
     Tags{"TagName1" = "Value1"
              "TagName2" = "Value2"
        }
  // 每一个SubShader必须要有一个Pass,可以有多个Pass,用来控制被渲染的几何体对象
  Pass{   // Pass里面就是整段渲染过程的实现
     
        }
}
  • RenderState 渲染状态
    通道设置显示硬件的各种状态,例如能打开alpha混合,使用雾等
    Cull off/Back/Front // 双面显示/背面不显示/正面不显示
    设置多边形剔除模式
    ZTest(Less/Greater/LEqual/GEqual/Equal/NotEqual/Always)默认Lequal
    设置深度写模式,是否次物体的像素深度会被记录(默认记录),半透明物体默认不记录
    ZWrite On/off
    开启alpha测试
    AlphaTest(Less/Greater/LEqual/GEqual/Equal/NotEqual/Always)
    设置alpha混合模式 ()
    Blend SourceBlendMode DestBlendMode
    • Blend SourceBlendMode DestBlendMode 混合模式

Unity高级开发-Shader开发(3)-Shader编程_第6张图片
编辑查看混合原理

Unity高级开发-Shader开发(3)-Shader编程_第7张图片
右键显示源文件查看混合原理

Unity高级开发-Shader开发(3)-Shader编程_第8张图片
image.png
  • Fog{ Fog Block} 设置雾参数
    Fog{Fog Commands}
    Mode Off/Global/Linear/Exp/Exp2
    Color ColorValue
    Density FloatValue
    Range FloatValue
fog{
  Mode Linear
  Color(1,1,1,1)
  Density 1000
}

RenderState

  • ColorMask RGB/A/0 设置颜色遮罩,0就是关闭所有颜色通道的渲染

  • Offset offsetFactor ,offsetUnits ,设置深度偏移

  • Color Color value 设置当顶点关照关闭时所使用的颜色

  • SeparateSpecular On/Off 开启或关闭顶点光照相关的平行高光颜色

  • ColorMaterial/AmbientAndDiffuse/Emission 当计算顶点光照时使用顶点颜色。

  • Material{Material Block} 定义一个使用顶点光照管线的材质

  • Lighting On/Off 开启或关闭顶点光照

  • Tags 标签
    标签主要是告诉硬件什么时候调用该着色器,比如操作手册,2:30后执行什么步骤,这就是标签。

    • 标签属性

      • 1:Rendering Order - Queue tag : 渲染队列,就是渲染顺序
        • Queue有四种选择
          1-Background : 最早被调用,用来渲染天空盒或者背景
          2-Geometry : 默认值,用来渲染非透明物体(普通情况下,场景中的大部分物体就是非透明的)
          3-Transparent :用于渲染透明物体(从后往前的顺序渲染)
          4-Overlay : 最后渲染,用来渲染叠加效果(如镜头光晕等)
    • 2:RenderType tag : 渲染类型 主要告诉系统什么类型要怎么显示?
      Opaque: 不透明,最常用(带法线贴图的,自发光的,反射,地形)
      Transparent:半透明物体(粒子,字体)
      TransparentCutout:透明遮罩shader
      Background:天空Shaders
      Overlay:GUITexture,Helo,Flare shaders
      TreeOpaque:枝干
      TreeTransparentCutout:树叶
      TreeBillboard: 树的面片,效果会好一些
      Grass:草
      GrassBillboard:草的面片

    • 3:其他标签
      ForceNoShadowCasting tag 不产生阴影
      IgnoreProjector tag 不被Projectors影响


      Unity高级开发-Shader开发(3)-Shader编程_第9张图片
      06.png

我们在Unity中可以通过相机方法:
RenderWithShader Render the camera with shader replacement.设置渲染shader
SetReplacementShader Make the camera render with shader replacement. 设置渲染替换shader

4-3、SubShader - LOD 着色器的设定值

LOD:调整根据设备图形性能来调整画质时可以进行比较精确的控制。

07.png
关于
VertexLit及其系列 = 100
Decal, Reflective VertexLit = 150
Diffuse = 200
Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250
Bumped, Specular = 300
Bumped Specular = 400
Parallax = 500
Parallax Specular = 600

如何进行质量设定?
http://www.ceeger.com/Components/class-QualitySettings.html

4-4、Input

Input其实是需要我们去定义的结构,这给我们提供了一个机会,可以把所需要参与计算的数据都放到这个Input结构中,传入surf函数使用;


Unity高级开发-Shader开发(3)-Shader编程_第10张图片
16.png

UV mapping的作用是将一个2D贴图上的点按照一定规则映射到3D模型上,是3D渲染中最常见的一种顶点处理手段。
变量前面加一个uv_MainTex:
就代表提取它的uv值(其实就是两个代表贴图上点的二维坐标 ), surf程序中直接通过访问uv_MainTex来取得这张贴图当前需要计算的点的坐标值了

4-5、surf
Unity高级开发-Shader开发(3)-Shader编程_第11张图片
21.png

SurfaceOutput是已经定义好了里面类型输出结构,但是一开始的时候内容暂时是空白的,我们需要向里面填写输出,这样就可以完成着色了。先仔细看看INPUT吧,现在可以跳回来看上面定义的INPUT结构体了:

Unity高级开发-Shader开发(3)-Shader编程_第12张图片
17.png
4-6、FallBack
Fallback Off    明确表示没有后援的shader
Fallback "name" 指定后援名字

4-7、Pass(通道)

Pass{[Name and Tags] [RenderSetup][TextureSetup]}
Pass{[名字和设定标签][渲染设定][贴图设定]}
SubShader里面的Tags是针对SubShader进行设定,而这里面的Tags是针对Pass(通道)做一些设定

  • Tags 用来控制光照管道(环境光照,顶点光照和像素光照)中Pass的任务和一些其他选项。
    LightMode tag 光照模式标签
    Always:总是渲染,没有光照应用
    ForwardBase:用于正向渲染,环境主要方向灯和电光/SH等的应用
    ForwardAdd:用于正向渲染,附加的像素光被应用,每个光照一个Pass
    PrepassBase:用于延迟光照,渲染法线/镜面指数
    PrepassFinal:用于延迟光照,通过结合纹理,光照和自发光渲染最终颜色。
    Vertex:用于顶点光照渲染,当物体没有光照映射时,所有顶点光照被应用
    VertexLMRGBM:用于顶点光照渲染,当物体有光照映射的时候使用顶点光照渲染。
    VertexLM:用于顶点光照渲染,当物体有光照映射的时候使用顶点光照渲染
    ShadowCaster:将物体当作阴影产生者来渲染
    ShadowCollector:正向渲染对象的路径,将对象阴影收集到屏幕空间缓冲区中。

顶点着色器与片段着色器所有的代码要写在CGPROGRAM 与 ENDCG里面,顶点着色器返回的就是一个顶点信息,而像素着色器返回的就是一个Color值

Pass{
CGPROGRAM
#pragma vertex vert   //预编译指令 表示是一个顶点光照的名字, vert是顶点光照方法的名字,下方的代码有这个函数
#pragma fragment frag // 预编译指令,表示是一个片段着色器名字,frag是片段着色器方法的名字,下面有这个函数的实现
ENDCG
}
  • 预编译指令

Unity高级开发-Shader开发(3)-Shader编程_第13张图片
08.png

为什么再次申明这个属性:
我们用来实例的这个shader其实是由两个相对独立的块组成的,外层的属性声明,回滚等等是Unity可以直接使用和编译的ShaderLab;而现在我们是在CGPROGRAM...ENDCG
这样一个代码块中,这是一段CG程序。对于这段CG程序,要想访问在Properties
中所定义的变量的话, 必须使用和之前变量相同的名字进行声明。于是其实sampler2D _MainTex;
做的事情就是再次声明并链接了_MainTex,使得接下来的CG程序能够使用这个变量。

  • Pragma Target 2.0 与Target 3.0,Target 3.5的区别
    如果想让我们写的着色器代码在不同的GPU运行,那么使用2.0就好,这是通用的。
#pragma target 2.0
Works on all platforms supported by Unity. DX9 shader model 2.0.
Limited amount of arithmetic & texture instructions; 8 interpolators; no vertex texture sampling; no derivatives in fragment shaders; no explicit LOD texture sampling.

较高的着色器编译目标允许使用更现代的GPU功能
具体参考文档Unity User Manual (5.6)/Graphics/Graphics Reference/Shader Reference/Writing vertex and fragment shaders/Shader Compilation Target Levels
Unity跨平台中,Shader可以通过根据平台来进行,不指定那么就会支持所有平台

Unity高级开发-Shader开发(3)-Shader编程_第14张图片
image.png

属性中的Color和Vector对应CG中的float4类型
属性中的Range和Float对应CG中的Float类型
属性中的2D纹理对应CG中Sampler2D类型
属性中的CUBE和Rect纹理对应CG中SamplerCUBE 和 Sampler RECT类型
顶点数据的获取:
appdata_base :包含顶点位置,法线和纹理坐标
appdata_tan:包含顶点位置,切线,法线和纹理坐标
appdata_full:包含顶点位置,法线,两张贴图和纹理坐标,顶点颜色

Name    Value
UNITY_MATRIX_MVP    Current model * view * projection matrix. // 模型坐标系 * 观察坐标系 * 投影坐标系
UNITY_MATRIX_MV Current model * view matrix.
UNITY_MATRIX_V  Current view matrix.
UNITY_MATRIX_P  Current projection matrix.
UNITY_MATRIX_VP Current view * projection matrix.
UNITY_MATRIX_T_MV   Transpose of model * view matrix.
UNITY_MATRIX_IT_MV  Inverse transpose of model * view matrix.
_Object2World   Current model matrix.
_World2Object   Inverse of current world matrix.

5、参考文档

https://docs.unity3d.com/Manual/SL-SurfaceShaderExamples.html
https://onevcat.com/2013/08/shader-tutorial-2/
http://www.tuicool.com/articles/JvYJ3em
http://www.itnose.net/detail/6143450.html

你可能感兴趣的:(Unity高级开发-Shader开发(3)-Shader编程)