UnityShader学习之旅--光照

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

  • 基础光照
    光线与物体相交的结果
光线方向光线颜色结果
吸收由于光被转化成了其他能量不改变改变密度和颜色
散射改变不改变折射、反射
物体表面重新发射出光线
自发光
散射方向光照模型定义
反射高光反射物体表面是如何反射的
折射漫反射有多少光线会被折射、吸收和散射出表面
  • 标准光照模型

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

描述unity表示
自发光当给定一个方向时,一个表面本身会向该方向发射多少辐射量材质的自发光颜色
高光反射光线照射到模型表面时,表面会在完全镜面反射方向散射多少辐射量Phong 模型1 Blinn模型2
漫反射光线照射到模型表面时, 表面会向每个方向散射多少辐射量兰伯特定律3
环境光其他所有的间接光照4UNITY_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"
}

在这里插入图片描述

名词解析:
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"
 }

在这里插入图片描述

/************************************
逐像素光照效果
*半伯兰特光照模型--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"
}

在这里插入图片描述
总结

特点缺陷计算公式计算位置
逐顶点光照细分程度高的模型,可以得到比较好的效果背光面与向光交界有锯齿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"
}

 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"
}

/******************************************
逐像素实现高光效果 --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
	}

}


总结

缺陷
逐顶点高光反射高光部分不平滑
高光反射计算是非线性的,顶点计算光照再插值也是线性,破坏了原非线性
逐像素高光反射高光部分更加平滑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的光照衰减
  • 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"
}

在这里插入图片描述

透明度物体的阴影

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

透明度测试
透明度混合
/*********************************************************
透明度物体的阴影
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"
}

在这里插入图片描述

/*********************************************************
透明度物体的阴影
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中,所有内置的半透明Shader是不会产生任何阴影效果

Lighting面板

2018版本

Scene设置适用于整体场景,而不是个别游戏对象。控制光照效果和优化选项Environment
Realtime Lighting
Mixed Lighting
Lightmapping Settings
DebugSettings
Other Setting
Global maps显示 GI 光照过程生成的所有光照贴图资源文件
Object maps显示当前所选游戏对象的 GI 光照贴图纹理(包括阴影遮罩)的预览
Auto GenerateUnity 将在您编辑场景时更新光照贴图数据非立即完成
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. Blinn模型
    在这里插入图片描述
    h是V与I ↩︎

  3. 兰伯特定律 ↩︎

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值