Unity_Shader_1

1基础篇 
2-4基础篇 为初学者普及基本的理论知识以及必要的数学基础 
5-8初级篇 从最简单的shader开始,讲解Shader中基础的光照模型、纹理和透明效果等初级渲染效果。 
9-16中极篇 讲解Unity中的渲染路径、如何计算光照衰减和阴影、如何使用高级纹理和动画等一系列内容。 
17-22扩展篇 进一步扩展读者的视野。

2渲染流水线 
渲染流水线的最终目的在于生成或者说是渲染一张二维纹理,即我们在电脑屏幕上看到的所有效果。他的输入是一个虚拟摄影机、一些光源、一些Shader以及纹理等。

《Render-Time Rending,Third Edition》书中将渲染流程分为3个阶段: 
应用阶段(CPU 绝对控制权)(输出渲染图元)、 
几何阶段(GPU)(输出屏幕空间的顶点信息)、 
光栅化阶段(GPU)

Tessellation Shader 是一个可选着色器,

顶点着色器是完全可编程的,它通常用于实现定点的空间变换、定点着色的等功能。

曲面细分着色器是一个可选的着色器,它用于细分图元。

几何着色器是一个可选的着色器,它可以用于执行逐图元的着色操作,或者被用于产生更多的图元。

顶点着色器的处理单位是顶点,输入进来的每个顶点都会调用一次顶点着色器。工作主要有:坐标变换和逐顶点光照。

屏幕映射 OpenGL(左下Unity) DirectX(左上微软)

三角形遍历(检查像素是否被三角网格所覆盖,覆盖生成一个片元)(扫描变换)

片元着色器在DirectX中又被称为像素着色器,它仅可以影响单个片元,但是可以访问到导数信息。

模板测试和深度测试

GLSL使用显卡驱动的着色器编译器, 
HLSL只有微软平台可以使用且要求版本一致。 
CG是真正意义上的跨平台,但缺点是可能无法完全发挥出OpenGL的最新特性。

3Unity Shader基础

材质(Material)和Unity Shader共同作用才能达到需要的效果

Unity Shader定义了渲染所需的各种代码(如顶点着色器和片元着色器)、属性(如使用那些纹理等)和指令(渲染和标签设置等),而材质则允许我们调节这些属性,并将其最终付给相应的模型。

材质需要结合一个GameObject的Mesh(网格)或者Particle Systems(粒子特效)组件来工作。

Shader: 
Standard Surface Shader会产生一个包含了标准光照模型的表面着色器模板。 
Unlit Shader则会产生一个不包含光照的基本的顶点/片元着色器。 
Image Effect Shader则为我们实现各种屏幕后处理效果提供了一个基本模块。 
Compute Shader会产生一种特殊的Shader文件,这类Shader旨在利用GPU的并行性来进行一些与常规渲染流水线无关的计算。(http://docs.unity3d.com/Manual/ComputeShaders.html) 
Unity Shader的导入面板还可以方便地查看其使用的渲染列队(Render queue)、是否关闭批处理(Disable batching)、属性列表(Properties)等信息。 
ShaderLab类似CgFX和.FX语言。他们都定义了要是显示一个材质所需的所有东西,而不仅仅是着色器代码。

Shader的结构:

Shader “Custom/Test” 
Test是材质选择使用Shader时,出现在材质面板的下拉列表里的名称。

Properties 
Properties { 
Name(”display name”, PropertType) = DefaultValue 
Name(”display name”, PropertType) = DefaultValue 
//更多属性 

开发者声明这些属性是为了在材质面板中能够方便地调整各种材质属性。如果需要在Shader中访问它们,就需要使用每个属性的姓名(Name)。在Unity中,这些属性的姓名通常由一个下划线开始。显示的名称(display name)则是出现在材质面板上的名字。需要为每个属性指定他的类型(PropertType),常见的属性类型如下表: 


对于 Int、Float、Range这些数字类型的属性,其默认值就是一个单独的数字;对于Color和Vector这类属性,默认值是用圆括号包围的一个四维向量;对于2D、Cube、3D这三类纹理类型,默认值的定义稍微复杂,他们的默认值是通过一个字符串后跟一个花括号来指定的,其中,字符串要么是空的,要么是内置的纹理名称,如“white”“black”“gray”或者“bump”。花括号的用处原本是用于指定一些纹理属性的,在5.0以前的版本中,可以通过TexGenCubeReflect、TexGen CubeNormal等选项来控制固定管线的纹理坐标的生成。5.0以后的版本中,这些选项被移除了,如果需要类似的功能,就需要自己再定点着色器中编写计算相应纹理坐标的代码。

Unity允许我们重载默认的材质编辑面板,以提供更多自定义的数据类型。 
官方手册(http://docs.unity3d.com/Manual/Sl-CustomShaderGUI.html) 
Properties语义快的作用仅仅是为了让这些属性可以出现在材质面板中。

SubShader:

SubShader{ 
//可选的 
[Tags]

//可选的 
[RenderSetup]

Pass{ 

// Other Passes 
}

SubShader中定义了一系列Pass以及可选的状态([RenderSetup])和标签([Tags])设置。每个Pass定义了一次完整的渲染流程,但如果Pass的数目过多,往往会造成渲染性能的下降。因此,我们应尽量使用最小数目的Pass。状态和标签同样可以在Pass声明。不同的是,SubShader中的一些标签设置是特定的。也就是说,这些标签设置和Pass中使用的标签是不一样的。而对于状态设置来说,其使用的语法是相同的。但是,如果我们在SubShader进行了这些设置,那么将会用于所有的Pass。

当在SubShader快中设置了上述渲染状态时,将会应用到所有的Pass。如果我们不想这样(例如在双面渲染中,我们希望在第一个Pass中剔除正面来背面进行渲染,在第二个Pass中剔除背面来对正面进行渲染),可以在Pass语义快中单独进行上面的设置。 


SubShader的标签 
SubShader的标签(Tags)是一个键值对,他的建和值都是字符串类型。这些键值对是SubShader和渲染引擎之间的沟通桥梁。他们用来告诉Unity的渲染引擎:SubShader我希望怎样以及何时渲染这个对象。 
标签结构如下:

Tags { “TagName1” = “Value1” “TagName2” = “Value2”}


Pass语义块 
Pass{ 
[Name] 
[Tags] 
[RenderSetup] 
// Other code 

首先,我们可以在Pass中定义该Pass的名称,例如:Name “MyPassName” 
通过这个名称,我们可以使用ShadrLab的UsePass命令来直接使用其他Unity Shadr中的Pass。例如: 
UsePass “MyShader/MYPASSNAME” 
这样可以提高代码的复用性。需要注意的是,由于Unity内部会把所有Pass的名称转换成大写字母的表示,因此,在使用UsePass命令时必须使用大写形式的名字。 
其次,我们可以对Pass设置渲染状态。SubShader的状态设置同样适用于Pass。除了上面提到的状态设置外,在Pass中我们还可以使用固定管线的着色器命令。 
Pass同样可以设置标签,但他的标签不同于SubShader的标签。这些标签也是用于告诉渲染引擎我们希望怎样来渲染该物体。 


除了上面普通的Pass定义外,Unity Shadr 还支持一些特殊的Pass,以便进行代码复用或实现更复杂的效果。 
UsePass:如我们之前提到的一样,可以使用该命令来复用其他Unity Shadr中的Pass; 
GrabPass:该Pass负责抓取屏幕并将结果储存在一张纹理中,以用于后续的Pass处理

Fallback 
紧跟在各个SubShader语义块后面的,可以是一个Fallback指令。它用于告诉Unity,“如果上面所有的Subshader在这块显卡上都不能运行,那么就使用这个最低级的Shader吧!”

语义如下: 
Fallback “name” 
//或者 
Fallback Off

事实上,Fallback还会影响阴影的投射。在渲染阴影纹理时,Unity会在每个Unity Shader中寻找一个阴影投射的Pass。通常情况下,我们不需要自己专门实现一个Pass,这是因为Fallback使用的内置Shader中包含了这样一个通用的Pass。因此,为每个Unity Shader 正确设置Fallback 是非常重要的。9.4

其他语义 
使用CustomEditor语义来扩展编辑界面。我们还可以使用Category语义来对UnityShader中的命令进行分组。这些命令很少用到。

尽管Unity Shader可以做的事情非常多(例如设置渲染状态等),但其最重要的任务还是制定各种着色器所需的代码。这些着色器代码可以写在SubShader语义快中(表面着色器的做法),也可以写在pass语义快中(顶点/片元着色器和固定函数着色器的做法)。 
在Unity中,我们可以使用下面3种形式来编写Unity Shader 。而不管使用那种形式,真正意义上的Shader代码都需要包含在ShaderLab语义快中,如下所示: 
Shader “MyShader” 
Properties{ 
//所需的各种属性 

SubShader{ 
//真正意义上的Shader代码会出现在这里 
//表面着色器(Surface Shader)或者 
//顶点/片元着色器(Vertex/Fragment Shader或者 
//固定函数着色器(Fixed Function Shader)


SubShader{ 
//和上一个SubShader类似 
}

表面着色器(Surface Shader)(Unity的宠儿)(需要光源,但是小心它在移动平台的性能表现)

Shader "Custom/Simple Surface Shader"{
   SubShader{
      Tags{"RenderType" = "Opaque"}
      CGPROGRAM
      #pragma surface surf Lambert
      struct Input {

          float4 color : COLOR;
      };
      void surf (Input IN, inout SurfaceOutputStandard o) {
      o.Albedo = 1;
    }
    ENDCG
  }
  Fallback "Diffuse"
}

顶点/片元着色器(Vertex/Fragment Shafer)(最聪明的孩子)更加复杂,单灵活性也很高(如果你需要使用的光照数目非常少,例如只有一个平行光,那么使用顶点/片元着色器,如果你有很多自定义的渲染效果,那么请选择顶点/片元着色器)

Shader "Custom/Simple VertexFragment Shader"{
   SubShader{
       Pass{
          CGPROGRAM 

          #pragma vertex vert
      #pragma fragment frag   

        float4 vert(float4 v : POSITION) : SV_POSITIO{
         return mul (UNITY_MATRIX_MVP, v);
         }
        fixed4 frag() : SV_Target {
                return fixed4 (1.0,0.0,0.0,1.0);
         }

            ENDCG
      }
   }  
}
Unity Shader的官方文档 
(http://docs.unity3d.com/Manual/SL_Reference.html) 
(http://docs.unity3d.com/Manual/ShaderTur1.html,http://docs.unity3d.com/Manual/ShaderTut2.html) 
CG文档(http://http.developer.nvidia.com/CGTutorial/cG_tutorial_chapter01.html)
--------------------- 
作者:wy小骑士 
来源:CSDN 
原文:https://blog.csdn.net/qq_39710961/article/details/79558478 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/alone_ws/article/details/85337794