Unity Shader(一)基础知识和语法

  • 1.Shader程序的基本架构
  • 1.文件声明
  • 2.简单的UV理解
  • 3.属性声明语法(properties)
  • 4.子着色器代码语法


1.Shader程序的基本架构

unity shader入门精要pdf2020版 unity shader基础_Unity Shader

1.文件声明

下面展示一些 内联代码片

/*首行声明了一个Shader,命名为MyFirstShader,存放在路径Study2下(这个路径在哪里不是重点,它归类在自定义中)*/
Shader "Study2/MyFirstShader"

2.简单的UV理解

/*
   UV纹理。简单来说:A是一张图片(称A为纹理),B是一张坐标信息(称B为UV),用B来取A就是纹理贴图的精髓了,简单的例子:
   A的色彩如下:
   红 黄
   蓝 绿

   B的坐标信息如下:
   (0,0) (1,1)
   (1,1) (0,1)

   那么取出来得到的纹理贴图就是:
   红 绿
   绿 黄
   */

3.属性声明语法(properties)

/*第一块:属性声明*/
   //属性,用于展示在Unity Inspectors中,可以通过调整属性来事实看到效果的变化
	properties{
		//定义属性的语法↓↓↓
		//_Name("Display Name", type) = defaultValue[{options}]
		//属性名("Inspector上展示的名字", 类型关键字) = 默认值
		//

		//颜色关键字:Color
		
		_Color("Tint", Color) = (1,1,1,1)	//一种颜色,由RGBA(红绿蓝和透明度)四个量来定义
		
		//贴图关键字:2D/Rect/Cube    
		//默认值可以是代表默认tint颜色的字符串,也可是空的字符串
		//或"white","black","gray","bump"中的一个,后面要强制带{}
		// “”{option}  option: ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal
		// 多个同时选择用逗号隔开
		_MainTex("MainText", 2D) = "White"{}  //一张2的阶数大小(256,512之类)的贴图
		//这张贴图将在采样后被转为对应基于模型UV的每个像素的颜色,最终被显示出来;	
		_RectTex("RectTex", Rect) = "White"{}	//一张非2阶数大小的贴图
		_Cube("Cube", Cube) = "White"{}	//即Cube map texture(立方体纹理)
		//简单说就是6张有联系的2D贴图的组合,主要用来做反射效果(比如天空盒和动态反射)
		//也会被转换为对应点的采样

		//浮点数关键字:Float/Range	
		_Float("Float", Float) = 0.1	//任意一个浮点数
		_Range("Range", Range(0, 1)) = 0 //Range(min, max) - 一个介于最小值和最大值之间的浮点数
		//一般用来当作调整Shader某些特性的参数(比如透明度渲染的截止值可以是从0至1的值等)                
		
		//四维数关键字:Vector	
		_MainTex_ST("Vector", Vector) = (1,1,1,1)    //请看默认值(1,1,1,1),形如(g,b,a,A)
		//其中的透明度A为0时,表示透明,为1时,表示完全不透明,所以应该称之为不透明度
	}

4.子着色器代码语法

SubShader
		{
			/*Tags { "RenderType"="Opaque" }*/
			/*Tags规定了混合模型*/
			/*
			* 1.RenderType = "Opaque" 渲染非透明物体
			* 2.RenderType = "Transparent" 渲染含有透明效果的物体
			* 3."IgnoreProjector" = "true" 不被projectors影响
			* 4."ForceNoShaderCasting" = "true" 不产生阴影
			* 5."Queue" = "XXX" 指定渲染顺序队列
			*/
			/*  预定义的Queue
			Background - 最早被调用的渲染,用来渲染天空盒或者背景
			Geometry - 这是默认值,用来渲染非透明物体(普通情况下,场景中的绝大多数物体应该是非透明的)
			AlphaTest - 用来渲染经过Alpha Test的像素,单独为AlphaTest设定一个Queue是出于对效率的考虑
			Transparent - 以从后往前的顺序渲染透明物体
			Overlay - 用来渲染叠加的效果,是渲染的最后阶段(比如镜头光晕等特效)
			(这些预定义本质上是一组定义的数组,Background = 1000,Geometry = 2000,AlphaTest = 2450,Transparent = 3000,Overlay = 4000
				定义自己的Queue值时,可以写成这样"Queue" = "Transparent + 100",表示在Transparent之后的100Queue上使用)

			*/
			Tags { "RenderType" = "Opaque" }

			/*LOD (Level Of Detail)表示细节呈现级别(也即是画质,即粗糙/细腻程度)
			当机器很差的时候,差到其评估值小于200时,本材质无效(也就是本shader罢工)。当机器的性能不错,大于200时,本shader继续工作。
			*/
			LOD 200

			/*这是一个标记:CGPROGRAM,表示这是一段computer graph编程*/
			CGPROGRAM

			/*函数声明:
			  #pragma surface表面着色器 surffunction着色器的代码(下面的Standard) lightModel(光照模型) [可选参数]
			*/
			#pragma surface surf Standard fullforwardshadows

			// Use shader model 3.0 target, to get nicer looking lighting
			#pragma target 3.0

			 /*
				接下来一句sampler2D _MainTex;,sampler2D是个啥?
				其实在CG中,sampler2D就是和texture所绑定的一个数据容器接口。
				等等..这个说法还是太复杂了,简单理解的话,所谓加载以后的texture(贴图)说白了不过是一块内存存储的,
				使用了RGB(也许还有A)通道,且每个通道8bits的数据。而具体地想知道像素与坐标的对应关系,以及获取这些数据,
				我们总不能一次一次去自己计算内存地址或者偏移,因此可以通过sampler2D来对贴图进行操作。
				更简单地理解,sampler2D就是GLSL中的2D贴图的类型,相应的,
				还有sampler1D,sampler3D,samplerCube等等格式。

				解释通了sampler2D是什么之后,
				还需要解释下为什么在这里需要一句对_MainTex的声明,
				之前我们不是已经在Properties里声明过它是贴图了么。
				答案是我们用来实例的这个shader其实是由两个相对独立的块组成的,
				外层的属性声明,回滚等等是Unity可以直接使用和编译的ShaderLab;
				而现在我们是在CGPROGRAM...ENDCG这样一个代码块中,这是一段CG程序。
				对于这段CG程序,要想访问在Properties中所定义的变量的话,必须使用和之前变量相同的名字进行声明!【注意这里!!!】
				于是其实sampler2D _MainTex;做的事情就是再次声明并链接了_MainTex,
				使得接下来的CG程序能够使用这个变量。*/
			sampler2D _MainTex;

		/*这是一个非常简单的结构体,称为Input,其中有一个float2数据类型,这是一个二维float矢量,也就是(a,b)这样的。*/
		struct Input
		{
			float2 uv_MainTex;
		};

		/*
			half类型的两个,fixed4类型的一个,
			half类型表示半精度浮点数,计算性能好但是精度低,和float和double是同类型的浮点数;
			fixed4不详,但是大意是四维的矢量
		*/
		half _Glossiness;
		half _Metallic;
		fixed4 _Color;

			/*
			* 核心的处理函数:surf,输入一张二维浮点信息,也即是上面的uv_MainTex,
			* 输出一个o表示材质(inout像c++里面的按照引入传入,虽说没有返回,但是也有信息传出的效果)
			*/
			/* inout SurfaceOutputStandard o
			这个结构有哪些包含的变量呢:
			struct SurfaceOutput {
				half3 Albedo;     //像素的颜色
				half3 Normal;     //像素的法向值
				half3 Emission;   //像素的发散颜色
				half Specular;    //像素的镜面高光
				half Gloss;       //像素的发光强度
				half Alpha;       //像素的透明度
			};
			*/
		void surf(Input IN, inout SurfaceOutputStandard o)
		{
			// Albedo comes from a texture tinted by color
			/*
			 * tex2D就是前面说的"利用UV去取图片获得纹理贴图"的做法,然后再乘以_Color
			*/
			fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = c.rgb;
			// Metallic and smoothness come from slider variables
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
			o.Alpha = c.a;
		}
		/*结束CG编码*/
		ENDCG