Cg入门17:Fragment shader - 片段级光照(添加阴影)

Posted Potter

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cg入门17:Fragment shader - 片段级光照(添加阴影)相关的知识,希望对你有一定的参考价值。

投射阴影
方法一:添加一个单独的pass通道
pass
{
     Tags{"LightMode" = "ShadowCaster"}
}
ShadowCaster:阴影投射器,可以投射阴影

方法二:添加物体默认阴影投射
FallBack "Diffuse"

然后给光线开启阴影:
技术分享
技术分享
效果如下:(效果图为添加平行光)
技术分享
技术分享
如果要让我们的shader支持点光源阴影投射,就添加 FallBack "Diffuse"
技术分享
添加点光源后效果:
技术分享
技术分享
接收阴影:让我们的球平面接受阴影

源代码:
Shader "Sbin/MyDiffuse_Shadow" {
	SubShader {
	
//		pass{
//			tags{"lightmode" = "shadowcaster"}
//		}
		
		pass{
			tags{"lightmode" = "ForwardBase"}   //现实一个平行光按像素计算		
			
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"
			#include "Lighting.cginc"
			#pragma multi_compile_fwdbase		//多版本编译
			#include "autolight.cginc"

			struct v2f{
				float4 pos : POSITION;
				float4 color : COLOR;
				LIGHTING_COORDS(0,1)
			};

			v2f vert(appdata_base v){
				v2f o;
				o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
				
				float3 N = normalize(v.normal);
				float3 L = normalize(_WorldSpaceLightPos0);
				
				N = mul(float4(N,0),_World2Object).xyz;
				N = normalize(N);
				
				float ndot = saturate(dot(N,L));
				o.color = _LightColor0 * ndot;
				
				//点光源
				float3 wpos = mul(_Object2World,v.vertex).xyz;
				o.color.rgb += Shade4PointLights(unity_4LightPosX0,unity_4LightPosY0,unity_4LightPosZ0
							,unity_LightColor[0].rgb,unity_LightColor[1].rgb,unity_LightColor[2].rgb,unity_LightColor[3].rgb,
							unity_4LightAtten0,wpos,N);
							
				TRANSFER_VERTEX_TO_FRAGMENT(o);	//传送阴影
				
				return o;
			}
			
			fixed4 frag(v2f v):COLOR
			{
				float atten = LIGHT_ATTENUATION(v);//光照衰减
				
				fixed4 col = (v.color + UNITY_LIGHTMODEL_AMBIENT);
				col.rgb *= atten;

				return col;
			}

			ENDCG
		}
		
		//--------------------------------------------------------------------------
		
		pass{
			tags{"lightmode" = "ForwardAdd"}	//平行光和顶点光全部按像素计算,是像素光就调用一次这个pass
			
			blend one one 	//叠加上一个pass的颜色值
			
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"
			#include "Lighting.cginc"
			#pragma multi_compile_fwdadd_fullshadows
			#include "autolight.cginc"

			struct v2f{
				float4 pos : POSITION;
				float4 color : COLOR;
				LIGHTING_COORDS(0,1)
			};

			float4 _MainColor;
			float4 _SpecalarColor;
			float _Shininess; 

			v2f vert(appdata_base v){
				v2f o;
				o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
				
				float3 N = normalize(v.normal);
				float3 L = normalize(_WorldSpaceLightPos0);
				
				N = mul(float4(N,0),_World2Object).xyz;
				N = normalize(N);
				
				float ndot = saturate(dot(N,L));
				o.color = _LightColor0 * ndot;
				
				//点光源
				float3 wpos = mul(_Object2World,v.vertex).xyz;
				o.color.rgb += Shade4PointLights(unity_4LightPosX0,unity_4LightPosY0,unity_4LightPosZ0
							,unity_LightColor[0].rgb,unity_LightColor[1].rgb,unity_LightColor[2].rgb,unity_LightColor[3].rgb,
							unity_4LightAtten0,wpos,N);
							
				TRANSFER_VERTEX_TO_FRAGMENT(o);
				
				return o;
			}
			
			fixed4 frag(v2f v):COLOR
			{
				float atten = LIGHT_ATTENUATION(v);
				
				fixed4 col = v.color;
				col.rgb *= atten;

				return col;
			}

			ENDCG
		}
	} 
	
	fallback "Diffuse"
}


技术分享

总结:
1.设置支持多版本编译:
#pragma multi_compile_fwdbase        //多版本编译
2.pass 与pass 叠加
blend one one     //叠加上一个pass的颜色值
3.添加tags
tags{"lightmode" = "ForwardBase"} //现实一个平行光按像素计算    
tags{"lightmode" = "ForwardAdd //平行光和顶点光全部按像素计算,是像素光就调用一次这个pass
技术分享

以上是关于Cg入门17:Fragment shader - 片段级光照(添加阴影)的主要内容,如果未能解决你的问题,请参考以下文章

Cg入门25: Fragment shader – UV动画(模糊)

Cg入门24: Fragment shader – UV动画(波纹)

Cg入门21:Fragment shader - 2D纹理采样

Cg入门16:Fragment shader - 片段级光照

Cg入门20:Fragment shader - 片段级模型动态变色(实现汽车动态换漆)

Cg入门19:Fragment shader - 片段级模型动态变色