ShaderLab - 第一天 - Shader基础知识

本文为ShaderLab系列学习文章,文中内容为Unity5.X游戏开发技术详解和典型案例,希望对正在学习或者想要学习ShaderLab的人有所帮助,如文章有任何错误还请读者帮忙指正,谢谢!


第一天:ShaderLab基础

1.Shader

什么是Shader:Shader是一个着色器程序的跟命令,每一个着色器程序都必须定义唯一一个Shader,其中定义了材质如何使用这个着色器渲染对象。Shader命令语法如下。

Shader "ShaderName"{
        [Properties]
        SubShader{......}
        [Fallback]
}

1:Shader为关键字,定义这是一个Shader着色器, ShaderName为自己定义的Shader的名称, Properties为材质的属性列表,后面紧跟随着SubShader列表,最后面可以添加Fallback代码块。

2:着色器拥有一个Properties的列表。任何定义在着色器程序中的属性都会显示在属性查看器中,典型的有颜色、纹理或者任何被着色器所使用的数据。

3:着色器程序中包含至少一个子着色器,即SubShader,当加载一个着色器程序时,unity将遍历这个列表,获取第一个能够被用户机器支持的子着色器,如果没有一个着色器被支持,unity将尝试降级着色器,即Fallback操作。


2:着色器的三种形态

1:固定管线着色器

固定管线着色器是在老一代GPU能力有限是,对着色器的约束性比较高的一种形态。为了市场占有率,新一代的显卡仍然对齐有所选择的支持,但是未来将逐渐淘汰。

示例:

Shader "Custom/BaseForm1"{
	Properties{	//定义的属性快
		_Color ("MainColor", Color) = (1,1,1,0.5) 		//定义主颜色数值
		_SpecColor("Sec Color", Color) = (1,1,1,1)		//定义高光颜色数值
		_Emission("Emission Color", Color) = (0,0,0,0)		//定义自发光颜色数值
		_Shininess("Shininess", Range(0.01, 1)) = 0.7		//定义高光系数数值
		_MainTex("Base (RGB)", 2D) = "White" {}			//定义纹理数值
	}
	SubShader{
		Pass{
			Material{					//材质块
				Diffuse[_Color]				//漫反射
				Ambient[_Color]				//环境光
				Shininess[_Shininess]			//高光系数
				Specular[_SpecColor]			//高光
				Emission[_Emission]			//自发光
			}
			Lighting On					//开启光照
			SeparateSpecular On				//允许高光使用不同于主颜色的颜色

			SetTexture[_MainTex]{				//处理纹理块
				constantColor[_Color]			//定义颜色值
				Combine texture * primary DOUBLE, texture * constant	//计算最终颜色
			}
		}
	}
}

从以上代码我们可以看出一些关于Shader代码的格式,因为我们主要不是用这个所以这里不多介绍,有兴趣的可以自己查看一些资料学习。


2:顶点片元着色器

顶点片元着色器为可编程着色器,相对于固定管线着色器可以给开发人员更大的发挥空间,但是缺点为不能直接和光照交互。着色器程序用CG或HLSL语言编写,嵌入在着色器的渲染通道块中。Cg程序代码片段被编写在CGPROGRAM和ENDCG之间。

顶点着色器中顶点数据必须以一个结构体的形式提交给Cg/HLSL顶点程序,几个常用的顶点结构体在"UnityCG.cginc"文件中,大多数情况下使用它们就足够了,当然也可以自己定义结构体。


下面以一个水的波纹效果制作来加深对顶点片元着色器的理解。

Shader "Custom/MyWater" {						//定义了一个着色器,名称为MyWater
	Properties {								//属性列表,用来指定这段代码将有哪些输入				
		_MainTex ("Base (RGB)", 2D) = "white" {}//定义一个2D纹理属性,默认白色
		_Aim1("Aim1",Vector) = ( 3, 0, 3, -2.5) //波源位置
		_Aim2("Aim2",Vector) = ( 5, 0, -5, 2.0)      
		_Aim3("Aim3",Vector) = (-3, 0, -3, 1.0)      
		_Aim4("Aim4",Vector) = (-5, 0, 5,  0.5)
		_High("High",Float) = 1
	}
	SubShader {									//子着色器
		Pass{									//通道

			CGPROGRAM							//开始标记
			#pragma vertex verf					//定义顶点着色器
			#pragma fragment frag				//定义片元着色器
			
			#include "UnityCG.cginc"			//引用Unity自带的函数库

			sampler2D _MainTex;					//2D纹理属性
			float4 _Aim1;
			float4 _Aim2;
			float4 _Aim3;
			float4 _Aim4;
			float4 _MainTex_ST;
			float _High;

			struct v2f {						//定义一个结构体
				float4 pos:POSITION;			//声明顶点位置
				float2 uv:TEXCOORD0;		//声明纹理
			};
			v2f verf(appdata_base v)			//顶点着色器
			{
				v2f o;							//声明一个结构体对象
				//计算当前顶点与_Aim1、_Aim2、_Aim3、_Aim4的距离
				float dis1 = distance(v.vertex.xyz,_Aim1.xyz);
				float dis2 = distance(v.vertex.xyz,_Aim2.xyz);
				float dis3 = distance(v.vertex.xyz,_Aim3.xyz);
				float dis4 = distance(v.vertex.xyz,_Aim4.xyz);
				//计算当前顶点的高度
				float H = sin(dis1*_Aim1.w+_Time.z *_High)/5;	//计算正弦波的高度
				H += sin(dis2*_Aim2.w + _Time.z*_High)/10;	//叠加正弦波的高度
				H += sin(dis3*_Aim3.w + _Time.z*_High)/15;	//叠加正弦波的高度
				H += sin(dis4*_Aim4.w + _Time.z*_High)/10;	//叠加正弦波的高度
				o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);	

				o.pos = mul(_Object2World,v.vertex);			//将顶点转换到世界坐标的矩阵
				o.pos.y = H;									//顶点的Y值赋为H
				o.pos = mul(_World2Object,o.pos);				//将顶点转换到自身坐标的矩阵
				o.pos = mul(UNITY_MATRIX_MVP,o.pos);			//计算顶点位置
				
				return o;										//返回顶点着色器对象
			}
			fixed4 frag(v2f i):COLOR
			{
				float4 texCol = tex2D(_MainTex,i.uv);	//获取顶点对应UV的染色
				
				return texCol;						//返回顶点染色
			}
			ENDCG									//着色器结束标志
		} 
	} 
	FallBack "Diffuse"								//降级着色器(备用的着色器)
}


3:表面着色器

因为顶点片元着色器缺点是不能直接和光照交互,为了能让开发人员方便的处理光照,unity提供了表面着色器,表面着色器代码也是使用CG或者HLSL语言编写的。下面将通过在Unity中之间新建的着色器来看一下表面着色器的结构。


Shader "Custom/BaseForm2" {
  Properties {											//定义属性块
    _Color ("Color", Color) = (1,1,1,1) 							//定义主颜色数值
    _MainTex ("Albedo (RGB)", 2D) = "white" {}						//定义纹理数值
    _Glossiness ("Smoothness", Range(0,1)) = 0.5						//定义高光系数数值
    _Metallic ("Metallic", Range(0,1)) = 0.0							//定义金属材质系数数值
  }
  SubShader {
    Tags { "RenderType"="Opaque" }								//标签
    LOD 200											//LOD数值
    CGPROGRAM
    #pragma surface surf Standard fullforwardshadows					//表面着色器编译指令
    #pragma target 3.0								//着色器编译目标
    sampler2D _MainTex;								//2D纹理属性
    struct Input {									//定义输入参数结构体
      float2 uv_MainTex;								//纹理UV坐标
    };
    half _Glossiness;									//定义高光系数属性
    half _Metallic;									//定义金属材质系数属性
    fixed4 _Color;									//定义主颜色属性
    void surf (Input IN, inout SurfaceOutputStandard o) {				//表面着色器函数
      fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;				//根据UV坐标从纹理提取颜色
      o.Albedo = c.rgb;								//设置颜色
      o.Metallic = _Metallic;							//设置金属材质系数
      o.Smoothness = _Glossiness;							//设置高光系数
      o.Alpha = c.a;									//设置透明度
    }
    ENDCG
  } 
  FallBack "Diffuse"									//降级着色器
}

今天先学到这里了,明天继续吧~

你可能感兴趣的:(Shader)