欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

简单的认识一下-Shader

程序员文章站 2022-04-11 18:54:49
...

**

一.

**Shader的三种语言

1 余弦值和角度成(0-180度)负相关
点积值和角度成(0-180度)负相关

2.三种着色器区别
1.Fixed function Shader: 固定管线着色器:比较老的一种着色器,针对高级shader在老显卡上兼容性不很友好的时候 使用固定管线
2.Vertex and Fragment Shader :顶点片段着色器:相对来说比较难的着色器,可以实现复杂的视觉效果
3.Surface Shader: 表面着色器:unity推荐使用的着色器,底层是顶点片段着色器,unity在基础上进行封装,使用起来比较简单,
并且官方处理以一些光照效果。

3.着色器书写格式
Shader “着色器名称”//给当前着色器命名
{
Properties
{
//颜色 贴图 颜色区域
} //属性定义

	SubShader{
	
	}	//子着色器1		
	SubShader{}	//子着色器2
	...
	
	
	FallBack "备用着色器名称"
}

4.子着色器和FallBack的关系
程序在执行到第一个子着色器的时候,
如果第一个子着色器兼容当前显卡,那么执行第一个子着色器内部代码。
后面的子着色器不再执行。
如果第一个子着色器不兼容,检查第二个,依次类推。。。直到有一个子着色器可以使用。
如果都不兼容 执行FallBack
5.固定管线属性定义
Properties
{
名称 (“显示名称”, Vector) = (.34, .85, .92, 1) // 四维向量值
名称 (“显示名称”, Float) = 0.1// 浮点属性
名称(“显示名称”, Range (0.02,0.15)) = 0.07 // 范围
名称 (“显示名称”, Color) = (.34, .85, .92, 1) // 颜色
名称 (“显示名称”, 2D) = “” {} // 2D纹理
名称 ("显示名称 ", Rect) = “”{}//矩形纹理
}
6.表面着色器属性
float:float2 float3 float4
half:浮点型
int:整型
fixed:定点型
bool:
Sampler2D:纹理类型
string:
7.模型上颜色的叠加用的是乘法,环境光的叠加用加法

8.边缘高光(描边)
视角和物体的视角向量,观察位置点的法线向量
视角向量 和 法线向量的夹角 越接近0 越接近中心 越接近90度 越靠近边缘

余弦值
视角向量 和 法线向量的余弦值 越接近1,夹角越接近0 余弦值越接近0 夹角越接近90
余弦值和 夹角成负相关 余弦值越小的话 越接近边缘

点积
视角向量 和 法线向量的点积 点积值接近1的话 越接近1,夹角越接近0 点积值越接近0 夹角越接近90
余弦值和 夹角成负相关 点积值越小的话 越接近边缘

9.高光Pong光照模型
原理:
计算光的反射向量 和 视角向量的夹角, 光照强度和点积值 是 正相关
夹角越小(余弦值越大,点积值越大,越接近1),当前像素点的光越强
夹角越大(余弦值越小,点积值越小,越接近0),当前像素点的光越弱
10.顶点片段着色器语义
提前约定好的字符(关键字),程序检测到当前字符(关键字) 会把指定数据填充到 变量中

--------------学习之后的认知
shader学习笔记
自定义光照模型
漫反射:法线与光源方向的 点乘
高光:视线(归一化)与光源方向(归一化)的 相加 再与法线的 点乘
**

二.脚本示范

**
1.Fixed function Shader:

Shader "VR180701Zk/FixedFunctionShader001"
{
	//属性
	Properties
	{
		//定义一个名称为Main Color属性
		_Color("MainColor", Color) =(0.5,0.8,0.3,1)
		_SpecularColor("高光颜色",Color)= (1,0.5,0.5,1)
		_EmissionColor("自发光颜色",Color)= (1,0.5,0.5,1)
		_Shininess("光泽度",Range(0.01,1))=0.5
		_MainTex("主纹理",2D) = "" {}
	}

	SubShader//子着色器
	{
		pass//通道
		{
			// SetTexture[_MainTex]{}
			// Color(0.6,0.5,0.4)
			Material
			{
				//漫反射
				//Diffuse(0.6,0.5,0.4)
				//DIFFUSE(0.6,0.5,0.4)
				diffuse(0.5,0.8,0.3)				
				// DIFFUSE[_Color]
				// //环境光
				Ambient(0.5,0.8,0.3)	
				// Ambient[_Color]	
				// //自发光
				// Emission[_EmissionColor]
				// //高光颜色
				// SPECULAR[_SpecularColor]	
				// //光泽度
				// Shininess[_Shininess]	
			}

			//开启光照
			Lighting On
			//开启高光
			SeparateSpecular On
		}

	}

}

2.Vertex and Fragment Shader

Shader "VR180701Zk/FragmentSpecularShader001"
{
	Properties
	{
		
	}
	SubShader
	{
		//设置前向渲染
		Tags { "RenderType"="Opaque" "LightMode"="ForwardBase"}
		Pass
		{
			CGPROGRAM
			//顶点函数  vert为顶点操作方法的主入口
			#pragma vertex vert
			//片段函数  frag为片段操作方法的主方法
			#pragma fragment frag
		
			//引入命名空间 对应的库函数 相当于C#中的using  lua中的require
			#include "UnityCG.cginc"
			#include "Lighting.cginc"

			//appdata 结构体  类似于surface中的Input结构体
			struct appdata
			{
				float4 vertex : POSITION;//需要光照点  到   顶点的向量
				float3 normal: NORMAL;				
			};
			//2:to  vert--->fragment
			//传输的数据
			struct v2f
			{
				//必须有的
				float4 vertex : SV_POSITION;
				float3 worldNormal:TEXCOORD0;
				float3 worldLightDir:TEXCOORD1;
				float3 worldViewDir:TEXCOORD2;


				//fixed3 color:Color;
			};
		
			//顶点函数 计算一些数据 比如可以计算光照
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);//必不可少 把模型空间下的顶点坐标通过矩阵转换  转到裁剪空间  才能被显示出来 
				//传入一个  模型空间下的顶点位置 返回世界空间下的  光照到当前顶点的向量
				o.worldLightDir =normalize(WorldSpaceLightDir(v.vertex));//1.v.vertex模型空间坐标变成世界坐标   2.v.vertex编程世界坐标-光源位置的世界坐标
				//转换  法线模型空间---->世界空间的转化
				o.worldNormal = mul(unity_ObjectToWorld, v.normal) ;//法线从模型空间转化到的世界空间	
				o.worldViewDir = normalize(WorldSpaceViewDir(v.vertex));;//视角 到  模型顶点的向量				

				//o.color= diffuse+ambient;			
				return o;
			}
			//片段函数 处理片段中的数据  颜色
			//SV_Target 会把返回的颜色暂存颜色缓冲区,颜色缓冲区的颜色为模型显示的最后颜色
			fixed4 frag (v2f i) : SV_Target
			{			
				//计算h向量
				fixed3 h = normalize(i.worldViewDir+i.worldLightDir);

				//高光的系数
				float nh = saturate(dot(i.worldNormal,h));
				float speNh = pow(nh,48);
				//高光颜色
				fixed3 specular = _LightColor0.rgb*speNh;
				//环境光
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;

				//diff漫反射系数
				float diff =saturate(dot(i.worldNormal,i.worldLightDir));
				//每个点的漫反射颜色值
				fixed3 diffuse = _LightColor0.rgb*diff;
				
				fixed3 color = diffuse+ambient+specular;
				return fixed4(color,1);
			}
			ENDCG
		}
	}
}

3.Surface Shader:
1.Lambert光照模式

Shader "VR180701Zk/SurfaceShader001"  
{  
	Properties
	{
		_MainColor("主颜色",Color) = (1,1,1,1)
		_MainTex("主纹理",2D) = ""{}
		_NormalTex("法线纹理",2D) = ""{}
		_RimColor("边缘高管",Color) = (1,1,1,1)  
        _RimPower("边缘高光可调节强度",Range(0.1,9.0))=3.0     

	}
    //--------------------------------【子着色器】----------------------------------  
    SubShader   
    {  
        //-----------子着色器标签----------  
        Tags { "RenderType" = "Opaque" }  //标签:渲染非透明物体  
        //-------------------开始CG着色器编程语言段-----------------    
        CGPROGRAM   //表面着色器的代码段必须放在CGPROGRAM ENDCG中
          
        //【1】光照模式声明:使用兰伯特光照模式  
		//shader入口  surf入口函数   Lambert光照模式
        #pragma surface surf Lambert   
        //【2】输入结构   可以通过Input输入结构 把模型的一些数据传送shader语言中
		//C# 声明struct  new 
		//input就这一个改变结构体会改变输入
        struct Input   
        {  
            //四元素的颜色值(RGBA)  
            float4 color : COLOR;  
			float2 uv_MainTex;
			float2 uv_NormalTex;
            float3 viewDir;
        };  
		
		float4 _MainColor;
		float4 _RimColor;
		float _RimPower;

		sampler2D _MainTex;//主纹理
		sampler2D _NormalTex;//法线纹理
        //【3】表面着色函数的编写  
		//IN 是输入的模型的数据     inout (C#中out) SurfaceOutput系统内置的结构体 
        void surf (Input IN, inout SurfaceOutput o)   
        {  
            //反射率  
           	// o.Albedo = float3(0.5,0.8,0.3);//(0.5,0.8,0.3)分别对应于RGB分量  
            //o.Albedo = _MainColor.rgb;//(0.5,0.8,0.3)分别对应于RGB分量  
            //而o.Albedo = 0.6;等效于写o.Albedo = float3(0.6,0.6,0.6);  

			//贴图
			o.Albedo = tex2D(_MainTex,IN.uv_MainTex).rgb*_MainColor.rgb;
			//法线
			o.Normal = UnpackNormal(tex2D(_NormalTex,IN.uv_NormalTex));
            //自发光  边缘高光(描边)
            float rim = 1-saturate(dot(normalize(IN.viewDir),o.Normal));
            o.Emission = _RimColor*pow(rim,_RimPower);
        }  
        //-------------------结束CG着色器编程语言段------------------    
        ENDCG  

        
    }  
    //“备胎”为普通漫反射    
    Fallback "Diffuse"  
}

2.自定义光照模式

Shader "VR180701Zk/SurfaceShaderSpecular" {
	Properties {
		_Color ("Color", Color) = (1,1,1,1)
		_MainTex ("Albedo (RGB)", 2D) = "white" {}		
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		
		CGPROGRAM
		//声明使用CustomSpecular光照模式
		#pragma surface surf CustomSpecular	

		sampler2D _MainTex;

		struct Input {
			float2 uv_MainTex;
		};
	
		fixed4 _Color;

		void surf (Input IN, inout SurfaceOutput o) {
			// Albedo comes from a texture tinted by color
			//fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = _Color.rgb;
			
		}

		half4 LightingCustomSpecular (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten)
		{
			half3 h = normalize(viewDir+lightDir);

			half diff =max(0,dot(s.Normal,lightDir));//漫反射系数    s.Normal模型点的法线
			//高光的系数
			float nh = saturate(dot(s.Normal,h));

			float speNh = pow(nh,48);

			half4 c;

			c.rgb =s.Albedo *_LightColor0.rgb*diff + _LightColor0.rgb*speNh;//_LightColor0 内置变量 存储当前的光照颜色和强度

			return c;
		}

		ENDCG
	}
	FallBack "Diffuse"
}