物理学中,光是电磁波。
1.光由太远或者其他光源被发射出来
2.与场景中的对象相交 ==>吸收、散射
3.最后光线被一个感应器(眼睛)吸收成像

  • 基础光照
    光线与物体相交的结果

光线方向

光线颜色

结果

吸收

由于光被转化成了其他能量

不改变

改变密度和颜色

散射

改变

不改变

折射、反射

物体表面重新发射出光线

自发光

散射方向

光照模型

定义

反射

高光反射

物体表面是如何反射的

折射

漫反射

有多少光线会被折射、吸收和散射出表面

  • 标准光照模型

只关心直接光照,即那些直接从光源发射处理照射到物体表面后,经过物体表面的一次反射直接进入摄像机的光线

描述

unity表示

自发光

当给定一个方向时,一个表面本身会向该方向发射多少辐射量

材质的自发光颜色

高光反射

光线照射到模型表面时,表面会在完全镜面反射方向散射多少辐射量

Phong 模型1 Blinn模型2

漫反射

光线照射到模型表面时, 表面会向每个方向散射多少辐射量

兰伯特定律3

环境光

其他所有的间接光照4

UNITY_LIGHTMODEL_AMBIENT.xyz

在硬件实现中,如果摄像机和光源距离模型足够远的话,Blinn模型会快于Phong模型

  • UnityShader中实现漫反射光照模型
/**********************************
* 逐顶点光照的漫反射效果
***********************************/
Shader "Unit/VertexLight" {
	Properties{
  		_Diffuse("Diffuse", Color) = (1.0,1.0,1.0,1.0) //声明一个Color类型的属性
 	}
 	SubShader{
 		Pass{
 			Tags{"LightMode" = "ForwardBase"}
 			CGPROGRMA
 			#pragma vertex vert
 			#pragma fragment frag
 			#include "Lighting.cginc"
 			struct a2v{
 				float4 vertext:POSITION;
 				float3 normal:NORMAL;
 			};
 			struct v2f{
 				float4 pos:SV_POSITION;
 				float3 color:COLOR;
 			};
 			float4 _Diffuse;
			v2f vert(a2v v){
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				//环境光
				float3 ambient = UNITY_LIGHTMODEL_AMBINET.xyz;
				//光线方向
				float3 worldlight = normalize(_WorldSpaceLightPos0.xyz);
				//法线==>世界空间中的法线 
				float3 worldNormal = UnityObjectToWorldNormal(v.normal);
				float3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldlight));
				//把所有的颜色相加
				o.color= ambient + diffuse ;
				return o;
			}	
			fixed4 frag(v2f i):SV_Target{
				fixed3 color = i.color;
				return fixed4(color, 1.0);		
			}

 			ENDCG
 		}
 	}
 	Fallback "Diffuse"
}

Unity shaderUV流光效果 unity shader 光照_光照模型

名词解析:
saturate(x)
/// < summary>
/// 防止点积结果为负值
/// < /summary>
/// < param name=“x”> 用于操作的标量或矢量
/// < returns>在[0,1]范围内

/**********************************
*逐像素光照实现漫反射效果
***********************************/
Shader "Unit/PixDiffuseLight" {
 Properties{
    _Diffuse("Diffuse", Color) = (1.0,1.0,1.0,1.0) //声明一个Color类型的属性
  }
  SubShader{
  	Pass{
		Tags{"LightMode" = "ForwardBase"}
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#include "Lighting.cginc"
		
		struct a2v{
		  float4  vertex:POSITION;
		  float3 normal:NORMAL;
		};
		struct v2f{
		  float4 pos:SV_POSITION;
		  float3 worldNormal:TEXCOORD0;
		};
		fixed4 _Diffuse;
		//顶点函数
		v2f vert(av2 v){
		  v2f o;
		  o.pos = UnityObjectToClipPos(v.vertex);
		  o.worldNormal= UnityObjectToWorldNormal(v.normal);
		  return o;
		}
		//片元函数
		fixed4 frag(v2f i):SV_Target{
		   fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
		   fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
		   fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(i.worldNormal, worldLightDir ));
		   fixed3 color = ambient + diffuse;
    		   return fixed4(color,1.0);
		}
		ENDCG
	}
    }
    Fallback "Diffuse"
 }

Unity shaderUV流光效果 unity shader 光照_d3_02

/************************************
逐像素光照效果
*半伯兰特光照模型--Half Lambert
*************************************/
Shader "Unit/HalfLambertLight" {	
	 Properties{
	   _Diffuse("Diffuse", Color) = (1,1,1,1)
	 }
	 SubShader{
           Pass{
	  	Tags{"LightMode" = "ForwardBase"}
	  	CGPROGRAM
	  	#pragma vertex vert
	  	#pragma fragment frag
	  	#include "Lighting.cginc"
	  	struct a2v{
	  	   float4 vertex:POSITION;
	  	   float3 normal:NORMAL;
	  	};
	  	struct v2f{
	  	  float4 pos:SV_POSITION;
	  	  float3 worldNormal:TEXCOORD0;
	  	}; 
	  	float4 _Diffuse;
	  	v2f vert(a2v v){
	  	  v2f o;
	  	  o.pos = UnityObjectToClipPos(v.vertex);
	  	  o.worldNormal = UnityObjectToWorldNormal(v.normal);
	  	  return o;
	  	}
	  	fixed4 frag(v2f i) : SV_Target{
	  	  fixed3 ambient = UNITY_LIGHTMODEL_AMBINET.xyz;
	  	  fixed3 worldLightDir = Normalize(_WorldSpaceLightPos0.xyz);
	  	  //半兰伯特光照计算替换了直接 dot(法线方向,光线方向)
	  	  fixed3 halfLambert = dot(i.worldNormal , worldLightDir )*0.5 + 0.5;
	  	  fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * halfLambert ;
	  	  fixed3 color = diffuse + ambient;	
	          return fixed4(color, 1.0);
	  	}
	  	ENDCG
	   }
         }
         Fallback "Diffuse"
}

Unity shaderUV流光效果 unity shader 光照_#pragma_03


总结

特点

缺陷

计算公式

计算位置

逐顶点光照

细分程度高的模型,可以得到比较好的效果

背光面与向光交界有锯齿

diffuse = light * diffuse * max(0,dot(法线方向,光线方向))

顶点着色器–高洛德着色

逐像素光照

平滑的光照效果

在光照无法到达的区域,模型外观为黑色,没有明暗变化

同上

片元着色器–Phong着色

半兰伯特光照

背光面也有明暗变化

diffuse = light * diffuse * (dot(法线方向,光线方向)*0.5+0.5))

片元着色器

  • 高光反射光照模型
/********************************************
逐顶点实现高光反射效果
*********************************************/
Shader"VertexSpecular"
{ 
 	Properties {
 		_Diffuse("Diffuse", Color) = (1,1,1,1)
 		_Specular("Specular", Color) = (1,1,1,1)
 		_Glosss("Gloss", Range(8,256)) = 10
 	}
 	Pass {
 		Tags{"LightMode" = "ForwardBase"}
 		CGPROGRAM
 		#pragma vertex vert
 		#pragma fragment frag
 		
 		#include "Lighting.cginc"
 		struct a2v{
 		  float4 vertex:POSITION;
 		  float3 normal:NORMAL;
 		};
 		struct v2f{
 		  float4 pos:SV_POSITION;
 		  float3 color:COLOR;
 		};
 		float4 _Diffuse;
 		float4 _Specular;
 		float _Glosss;
		
		v2f vert(a2v v){
		  v2f o;
		  o.pos = UnityObjectToClipPos(v.vertex);
		  //法线方向==>转换到世界空间中
		  float3 worldNormal = UnityObjectToWorldNormal(v.normal);
		  //光线方向归一化
		  float3 worldLightdir = normalize(UnityWorldSpaceLightDir(mul(unity_ObjectToWorld, v.vertex).xyz));
		  //环境光
		  float3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
		  //漫反射--半兰伯特光照模型
		  float3 diffuse = _LightColor0.rgb * _Diffuse.rgb * (dot(worldNormal, worldLightdir)*0.5 +0.5);
		  //反射方向
		  fixed3 relfdir = normalize(reflect(-worldLightDir, worldNormal));
		  //视角方向==>世界空间中
		  fixed3 viewDir = normalize(UnityWorldSpaceViewDir(mul(unity_ObjectToWorld, v.vertex).xyz));
		  float3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(relfdir, viewDir )), _Glosss);
		  //环境光+漫反射+高光反射
		  o.color = ambient + diffuse + specular;	
		  return o;
		}
		fixed4 frag(v2f i):SV_Target{
			return fixed4(i.color, 1);
		}
 		ENDCG
 	}
	Fallback "Specular"
}

Unity shaderUV流光效果 unity shader 光照_d3_04

reflect(i,n)
/// <summary>
/// 获取顶点的反射方向
/// < /summary>
/// <param name="i">入射方向</param>
/// <param name="n">法线方向</param>
/*******************************************
逐像素实现高光效果 -- Phong模型
********************************************/
Shader"PiexSpecular"
{ 
   Properties{
	_Diffuse("Diffuse", Color) = (1,1,1,1)
	_Speculr("Specular", Color) = (1,1,1,1)
	_Gloss("Gloss", Range(8,256)) = 10
    }
    Pass{
	Tags{"LightMode" = "ForwardBase"}
	CGPROGRAM
	#pragma vertex vert
	#pragma fargment frag
	#include "Lighting.cginc"
	struct a2v{
		float4 vertex : POSITION;
		float3 normal:NORMAL;
	};
	struct v2f{
		float4 pos:SV_POSITION;
		float3 worldNormal:TEXCOORD0;
		float3 worldPos:TEXCOORD1;
	};
	float4 _Diffuse;
	float4 _Speculr;
	float _Gloss;
	v2f vert(a2v v){
	   v2f o;
	   o.pos = UnityObjectToClipPos(v.vertex);
	   o.worldNormal = UnityObjectToWorldNormal(v.normal);	
	   o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
	   return o;
	}
	fixed4 frag(v2f i):SV_Target{
	  //法线
	  fixed3 worldNormal = i.worldNormal;
	  //光线方向
	  fixed3 worldLightDir =  normalize(UnityWorldSpaceLightDir(i.worldPos));
	  //视角方向
	  fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
	  //反射方向
	  fixed3 reflDir = normalize(reflect(-worldLightDir , worldNormal));
	  //环境光
	  fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
	  //漫反射
	  fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir ));
	  //高光反射
	  fixed3 specular = _LughtColor0.rgb * _Speculr.rgb * pow(max(0, dot(worldNormal, reflDir )), _Gloss);
	  fixed3 color = ambient + diffuse +  specular ;
	  return fixed4(color, 1);
	}
	ENDCG
    }
	Fallback"Specular"
}

Unity shaderUV流光效果 unity shader 光照_d3_05

/******************************************
逐像素实现高光效果 --Blinn-Phong光照模型
******************************************/
Shader"BlinnPhongSpecular"
{
	Properties{
	   _Diffuse("Diffuse", Color) = (1,1,1,1)
 	   _Speculr("Specular", Color) = (1,1,1,1)
 	   _Gloss("Gloss", Range(8,256)) = 10
	}
	Pass{
	  Tags{"LightMode" = "ForwardBase"}
	  CGPROGRAM
	  #progam vertex vert
	  #progam fragment frag
	  #include "Lighting.cginc"
	  struct a2v{
		float4 vertex:POSITION;
		float3 normal:NORMAL;
	  };
	  struct v2f{
	   	float4 pos:SV_POSITION;
	   	float3 worldNormal:TEXCOORD0;
	   	float3 worldPos:TEXCOORD1;
	  };
	   float4 _Diffuse;
 	   float4 _Speculr;
 	   float _Gloss;
 
	  v2f vert(a2v v){
	      v2f o;
	      o.pos = UnityObjectToClipPos(v.vertex);
	      o.worldNormal = UnityObjectToWorldNoraml(v.normal);
	      o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
	      return o;
	  }
	 fixed4 frag(v2f i):SV_Target{
	 	//法线
		fixed3 worldNormal = i.worldNormal;
		//光照方向
		fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
		//视角方向
		fixed3 worldViewDir  = normalize(UnityWorldSpaceViewDir(i.worldPos));
		//反射方向
		fixed3 reflDir = normalize(reflect(-worldLightDir, worldNormal));
		//环境光
		fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
		//漫反射
		fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir ));
		//Blinn光照 ==>视角方向与光照方向归一化
		fixed3 halfDir = normalize(worldLightDir + worldViewDir );
		//高光反射
		fixed3 specular = _LightColor0.rgb * _Speculr.rgb * pow(saturate(dot(worldNormal, halfDir )), _Gloss);
		fixed3 color = ambient  + diffuse  + specular ;
		return fixed4(color, 1);
	 }
	  ENDCG
	}

}

Unity shaderUV流光效果 unity shader 光照_#pragma_06


总结

缺陷

逐顶点高光反射

高光部分不平滑

高光反射计算是非线性的,顶点计算光照再插值也是线性,破坏了原非线性

逐像素高光反射

高光部分更加平滑

Phong光照模型

Blinn-Phong高光反射

高光反射部分更大更亮

Blinn-Phong光照模型

  • 光源类型

光源类型

几何定义

方向

位置

颜色

强度

例子

放置

平行光

照亮的范围是无限的

只有方向,到场景中所有点的方向一样

没有唯一的位置

不发生改变

太阳

光线方向略微向下,与场景中的对象形成一个小角度。

点光源

有限的空间,球体

方向=点光源的位置-某点的位置

由Position定义

Light面板

中心–>边缘减小

模拟火花或爆炸照亮周围环境

场景对象决定

聚光灯

有限的空间,锥形区域

方向=聚光灯的位置-某点的位置

由Position定义

中心–>边缘减小

人造光源,例如手电筒、汽车前照灯和探照灯

场景对象决定

面光源

通过空间中的矩形来定义

表面区域上均匀地向所有方向上发射,但仅从矩形的所在的面发射

无法手动控制面光源的范围

远离光源时,强度将按照距离的平方呈反比衰减

计算对处理器性能消耗较大,不能实时处理,仅烘培的时才可发挥作用,路灯、室内光照

发光材质

发光材质在其表面区域发光

以方差速率衰减

自发光材质产生氖灯或其他可见光源之类的效果

环境光

场景周围存在的光,并且不来自任何特定的光源对象

  • 前向渲染中处理不同的光源类型
/***********************************************
使用平行光和一个点光源共同照亮物体
前向渲染、Blinn-Phong 光照模型
***********************************************/
Shader "ForwardRendering"
{
	Properties{
	  _Diffuse("Diffuse", Color) = (1,1,1,1)
	  _Specular("Specular", Color) = (1,1,1,1)
	  _Gloss("Gloss", Range(8,256)) = 10
	}
	Pass{
	  Tags{"LightMode" = "ForwardBase"}
	  CGPROGRAM
	  #pragma vertex vert
	  #pragma fragment frag
	  //正确使用光照衰减等光照
	  #pragma multi_compile_fwdbase
	  #include "Lighting.cginc"
	  struct a2v{
	    float4 vertex:POSITION;
	    float3 normal:NORMAL;	
	  };
	  struct v2f{
	    float4 pos:SV_POSITION;
	    float3 worldNormal:TEXCOORD0;
	    float3 worldPos:TEXCOORD1;	
	  };
	  float4 _Diffuse;
          float4 _Specular;
          float _Gloss;
	  v2f vert(a2v v){
	    v2f o;
	    o.pos = UnityObjectToClipPos(v.vertex);
	    o.worldNormal = UnityObjectToWorldNormal(v.normal);
	    o.worldPos = mul(unity_objectToWorld, v.vertex).xyz;
	    return o;
	  }
	  //计算平行光
	  fixed4 frag(v2f i):SV_Target{
	   //法线
	   fixed3 wnormal = normalize(i.worldNormal);
	   //光照方向
	   fixed3 wlightdir = normalize(_WorldSpaceLightPos0.xyz);
	   //视角方向
	   fixed3 wViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
	   //half
	   fixed3 halfView = normalize(wlightdir  + wViewDir );
	   //环境光
	   fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; 
	   //漫反射
	   fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(wnormal,  wlightdir ));
	   //高光反射
	   fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(wnormal, halfView)), _Gloss);
	   fixed3 color = ambient  + diffuse +specular ;
	   fixed3 atten = 1.0;//平行光无衰减
	   return fixed4(color * atten, 1);
	  } 
	  ENDCG	
	}
	Pass{
	 	Tags{"LightMode" = "ForwardAdd"}
	 	CGPROGRAM
	 	#pragma vertex vert
	 	#pragma fragment frag
	 	#pragma multi_compile_fwdadd
	 	#include "Lighting.cginc"
	 	#include "Autolight.cginc"
	 	struct a2v{
     			float4 vertex:POSITION;
     			float3 normal:NORMAL; 
   		};
   		struct v2f{
     			float4 pos:SV_POSITION;
     			float3 worldNormal:TEXCOORD0;
     			float3 worldPos:TEXCOORD1; 
   		};
   		float4 _Diffuse;
          	float4 _Specular;
          	float _Gloss;
   		v2f vert(a2v v){
     			v2f o;
     			o.pos = UnityObjectToClipPos(v.vertex);
     			o.worldNormal = UnityObjectToWorldNormal(v.normal);
     			o.worldPos = mul(unity_objectToWorld, v.vertex).xyz;
     			return o;
   		}
		fixed4 frag(v2f i):SV_Target{
		 	fixed3 wnormal = normalize(i.worldNormal);
		 	fixed3 tarantLightDir = UnityWorldSpaceLightDir(i.worldPos);
		 	fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(tarantNormal, tarantLightDir));
			fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(tarantNormal, halfDir)), _Gloss);	
			//平行光没由衰减 
    			#ifdef USING_DIRECTIONAL_LIGHT
     				fixed atten = 1.0;
    			#else
     				//光源在空间中的位置
     				float3 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1)).xyz;
     				//对_LightTexture0纹理采样得到定点到该光源的衰减值
     				fixed atten = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;//获取衰减纹理中衰减值的分量
    			#endif
    			fixed3 color = (diffuse + specular) * atten;
    			return fixed4(color, 1.0);
		}
		ENDCG
	}
	Fallback"Specular"
}

Unity shaderUV流光效果 unity shader 光照_#pragma_07

  • Unity的光照衰减
  • Unity的阴影

为了让场景看起来更加真实,具有深度信息。
判断距离的表面位置?

方法

缺陷


1.摄像机处于光源处

2.按正常的渲染流程更新深度信息

3.得到阴影映射纹理

性能浪费

只需要深度信息,但却计算了光照模型

二 使用额外的Pass专门更新光源的阴影映射纹理

1…摄像机处于光源处

2.调用ShadowCaster Pass

3. 顶点变换到光源空间下

4.输出深度信息到阴影映射纹理

过程

结果

实现

物体接收其他物体的阴影

shader中对阴影映射纹理采样

采样结果*光照结果 = 产生阴影效果

向其他物体投射阴影

把物体加入到光源的阴影映射纹理的计算中

其他物体对阴影映射纹理采样时可以得到物体的相关信息

LightMode = ShadowCaster 的Pass

/******************************************
//不透明物体的阴影
//Light组件开启阴影->让物体接收阴影
统一管理光照衰减和阴影
******************************************/
Shader "Shadow"
{
	Properties{
	 _Diffuse("Diffuse", Color) = (1,1,1,1)
	 _Specular("Specular", Color) = (1,1,1,1)
	 _Gloss("Gloss", Range(8,256)) = 10
	}
	Pass{
	  Tags{"LightMode" = "ForwardBase"}
	  CGPROGRAM
	  #pragma vertex vert
	  #pragma fragment frag
	  #include "Lighting.cginc"
	  #include "AutoLight.cginc"
	  
	  struct a2v{
           float4 vertex:POSITION;
           float3 normal:NORMAL;          };
	  
	  struct v2f{
	   float4 pos:SV_POSITION;
	   float3 worldNormal:TEXCOORD0;
	   float3 worldPos:TEXCOORD1;
	   SHADOW_COORDS(2); //宏:声明一个用于对阴影纹理采样的坐标。参数:占用插值寄存器的索引
	  };
	  float4 _Diffuse;
	  float4 _Specular;
	  float _Gloss;
 	  v2f vert(a2v v){
 	     v2f o;
 	     o.pos = UnityObjectToClipPos(v.vertex);
 	     o.worldNormal = UnityObjectToWorldNormal(v.normal);
 	     o.worldPos = mul(unity_objectToWorld, v.vertex).xyz;
 	     TRANSFER_SHADOW(o); //宏:用于计算上一步中声明的阴影纹理坐标
 	  }
 	  fixed4 frag(v2f i):SV_Target{
 	     //fixed shadow = SHADOW_ATTENUATION(i);//宏:计算阴影值
 	     SHADOW_LIGHT_ATTENUATION(atten, i, i.worldPos); //宏:内置计算光照衰减和阴影
 	     fixed3 wNormal = normalize(i.worldNormal);
 	     fixed3 wLightdir = normalize(UnityWorldSpaceLightDir(i.worldPos));
 	     fixed3 wViewdir = normalize(UnityWorldSpaceViewDir(i.worldPos));
	     fixed3 halfdir = normalize(wLightdir + wViewdir ); 
	     fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
	     fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(wNormal, wLightdir));
	     fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(wNormal, halfdir)), _Gloss);
	     fixed3 color = ambient +(diffuse + specular)* atten;
	     return fixed4(color, 1);
	  }
	  ENDCG	
	}
	Pass{
	  Tags{"LightMode" = "ForwardAdd"}
	  Blend One One
	  CGPROGRAM
	  #pragma vertex vert
	  #pragma fragment frag
	  #include "Lighting.cginc"
	  #include "AutoLight.cginc"
	  struct a2v{
		float4 vertex : POSITION;
		float3 normal:NORMAL;
	  };
	  struct v2f{
	   	float4 pos:SV_POSITION;
	   	float3 worldNormal:TEXCOORD0;
	   	float3 worldPos:TEXCOORD1;
	  	SHADOW_COORD(2)
	  };
	  float4 _Diffuse;
	  float4 _Specular;
	  float  _Gloss;
	  v2f vert(a2v v){
	  	v2f o;
	  	o.pos = UnityObjectToClipPos(v.vertex);
	  	o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
	  	o.worldNormal = UnityObjectToWorldNormal(v.normal);
	  	TRANFER_SHADOW(o);
	  	return o;
	  }
	  fixed4 frag(v2f i):SV_Target{
	  	fixed3 wNormal = normalize(i.worldNormal);
	  	fixed3 wLightdir = normalize(UnityWorldSpaceLightDir(i.worldPos));
	  	fixed3 wViewdir = normalize(UnityWorldSpaceViewDir(i.worldPos));
	  	fixed3 halfdir = normaize(wLightdir + wViewdir);
	  	fixed3 diffuse = _LightColor0.rgb * _Diffus.rgb * saturate(dot(wNormal , wLightdir ));
	  	fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(wNormal, halfdir)),_Gloss);
	  	UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
	  	fixed3 color = (diffuse + specular)*atten;
	  	return fixed4(color, 1);
	  }
	  ENDCG
	}
	Fallback "Specular"
}

Unity shaderUV流光效果 unity shader 光照_#pragma_08

透明度物体的阴影

透明物体的实现会使用透明度测试或透明度混合

透明度测试

透明度混合

/*********************************************************
透明度物体的阴影
1.透明度测试 + 阴影
**********************************************************/
Shader "AlphaTestAtten"{
	Properties{
	_Color("Color Tint", Color) = (1,1,1,1)
	_MainTex("Main Tex", 2D) = "white"{}
	_Cutoff("Cut Off", Range(0,1)) = 0.5
	}
	SubShader{
		Tags{"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType"="TransparentCutout"}
		Pass{
			Tags{"LightMode" = "ForwardBase"}
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "Lighting.cginc"
			#include "AutoLight.cginc"
			struct a2v{
			  float4 vertex:POSITION;
			  float3 normal:NORMAL;
			  float4 texcoord:TEXCOORD0;
			};
			struct v2f{
			  float4 pos:SV_POSITION;
			  float2 uv:TEXCOORD0;
			  float3 worldNormal:TEXCOORD1;
			  float4 worldPos:TEXCOORD2;
			  SHADOW_COORDS(3)
			};
			float4 _Color;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			half _Cutoff;
			v2f vert(a2v v){
			  v2f o;
			  o.pos = UnityObjectToClipPos(v.vertex);
			  o.worldNormal = UnityObjectToWorldNormal(v.normal);
			  o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
			  o.worldPos = mul(unity_ObjetToWorld, v.vertex).xyz;
			  TRANSFER_SHADOW(o);
			  return o;
			}
			fixed4 frag(v2f i):SV_Target{
			 fixed3 wNormal = normalize(i.worldNormal);
			 fixed3 wLightdir = normalize(UnityWorldLightDir(i.worldPos));
			 fixed4 texcoord = tex2D(_MainTex, i.uv);
			 clip(texcoord.a - _Cutoff);
			 fixed3 albedo = texcoord.rgb * _Color.rgb;
			 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
			 fixed3 diffuse = _LightColor0.rgb * albedo * saturate(dot(wNormal, wLightdir));
			 UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
			 fixed3 color = ambient + diffuse * atten;
			 return fixed4(color, 1.0);
			}
			ENDCG
		}
	}
	FallBack "VertexLit"
}

Unity shaderUV流光效果 unity shader 光照_d3_09

/*********************************************************
透明度物体的阴影
1.透明度混合 + 阴影
**********************************************************/
Shader "AlphaBlendAtten"{
	Properties{
		_Color("Color Tint", Color) = (1,1,1,1)
		_MainTex("Main Tex",2D) = "white"{}
		_AlphaScale("Alpha Scale", Range(0,1)) = 1.0
	}	
	SubShader{
		Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
		Pass{
			Tags{"LightMode" = "ForwardBase"}
			ZWrite Off //深度写入关闭
			Blend SrcAlpha OneMinusSrcAlpha //混合开启
			CGPROGRAM
			#pragma multi_compile_fwdbase //前向渲染
			#pragma vertex vert
			#pragma fragment frag
			#include "Lighting.cginc"
			#include "AutoLight.cginc"
			struct a2v {
			 float4 vertex : POSITION;
			 float3 normal:NORMAL;
			 float4 texcoord:TEXCOORD0;
			};
			struct v2f {
			 float4 pos:SV_POSITION;
			 float3 worldPos:TEXCOORD0;
			 float3 worldNormal:TEXCOORD1;
			 float2 uv:TEXCOORD2;
			 SHADOW_COORDS(3)
			};
			float4 _Color;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed _AlphaScale;
			v2f vert(a2v v){
			  v2f o;
			  o.pos = UnityObjectToClipPos(v.vertex);
			  o.worldNormal = UnityObjectToWorldNormal(v.normal);
			  o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
			  TRANSFER_SHADOW(o);
			  return o;
			}
			fixed4 frag(v2f i):SV_Target{
				fixed3 wNormal = normalize(i.worldNormal);
				fixed3 wLightdir = normalize(UnityWorldSpaceLightDir(i.worldPos));
				fixed4 texcoord = tex2D(_MainTex, i.uv);
				fixed3 albedo = texcoord.rgb * _Color.rgb;
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
				fixed3 diffuse = _LightColor0.rgb * albedo * saturate(dot(wNormal, wLightdir));
				UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);
				fixed3 color = ambient + diffuse * atten;
				return fixed4(color, texcoord.a * _AlphaScale);
			}
			ENDCG
		}
	}
	Fallback "VertexLit" //透明物体可以显示阴影强制生成阴影
	//"Transparent/VertexLit" 不会投射阴影,也不会接收阴影
}

Unity shaderUV流光效果 unity shader 光照_#pragma_10

在Unity中,所有内置的半透明Shader是不会产生任何阴影效果

Lighting面板

2018版本

Scene

设置适用于整体场景,而不是个别游戏对象。控制光照效果和优化选项

EnvironmentRealtime Lighting

Mixed Lighting

Lightmapping Settings

DebugSettings

Other Setting

Global maps

显示 GI 光照过程生成的所有光照贴图资源文件

Object maps

显示当前所选游戏对象的 GI 光照贴图纹理(包括阴影遮罩)的预览

Auto Generate

Unity 将在您编辑场景时更新光照贴图数据

非立即完成

Generate Lighting

需要的时候触发光照贴图更新

不清除 GI 缓存的情况下清除场景中的烘焙数据使用

面板统计信息:

Memory Usage

内存使用量

当前光照贴图所需的内存量

Occupied Texels

占用的纹理像素

在光照贴图 UV 空间中占用的纹理像素数量

Lightmaps in view

视图中的光照贴图

Scene 视图中的光照贴图数量

Lightmaps not in view
不在视图中的光照贴图

不在视图中的光照贴图数量

Converged

融合

光照贴图的所有计算都已完成

Not Converged

未融合

光照贴图的烘焙仍在进行中

Bake Performance:

每秒的射线数。 如果此值较低(即小于2),则应调整设置或硬件以一次处理更多光线

实时全局光照(Global Illumination, GI)流水线

场景中的物体不仅可以受直接光照的影响,还可以接受间接光照的影响。
全局光照:模拟光线是如何在场景中传播的考虑那些直接光照、间接光照
直接光照:直接把光照射到物体表面的光源
间接光照:那些被场景中其他物体反弹的光

光照贴图
Unity 采用了 Enlighten (2019已弃用) 和 渐进 CPU 光照贴图 (Progressive CPU Lightmapper)

渐进 CPU 光照贴图

一种基于路径追踪的光照贴图系统,提供了能在Edtior中逐渐刷新的烘焙光照贴图和光照探针


  1. Phong 模型
  2. Unity shaderUV流光效果 unity shader 光照_光照模型_11


  3. Unity shaderUV流光效果 unity shader 光照_Unity shaderUV流光效果_12


  4. Unity shaderUV流光效果 unity shader 光照_#pragma_13

  5. 为负数 ↩︎
  6. Blinn模型
  7. Unity shaderUV流光效果 unity shader 光照_Unity shaderUV流光效果_14


  8. Unity shaderUV流光效果 unity shader 光照_#pragma_15

  9. ↩︎
  10. 兰伯特定律
  11. Unity shaderUV流光效果 unity shader 光照_#pragma_16

  12. ↩︎
  13. 光线通常会在多个物体之间反射,最后进入摄像机。 ↩︎