UnityShader-阴影的原理介绍及实现过程

阴影形成的原理

在这里插入图片描述

2.阴影投射原理详解

  • 因为三维的示意图不好画,所以这里的讲解都在二维空间中,但是不影响最终结果
  • 首先有一个大前提,上图的数值全部在一个坐标空间中,这里选取的是被投影的Plane片自身的模型空间,大家先不要管坐标系转换,先知道一点,他们现在在一个坐标空间下就可以了
  • ly和lx是光照方向归一化之后的方向,可以理解为光照方向的单位向量
  • 三角形ABC和三角形ADE近似,则有: A C A E = B C D E \frac{AC}{AE}=\frac{BC}{DE} AEAC=DEBC,得到 A E = A C ∗ D E B C = l x ∗ l y y AE=AC*\frac{DE}{BC}=lx * \frac{ly}{y} AE=ACBCDE=lxyly
  • 我们要求的就是A点的横坐标,已知E的横坐标坐标为x,则 A x = x − A E = x − l x ∗ l y y Ax=x-AE=x-lx * \frac{ly}{y} Ax=xAE=xlxyly
  • 同样换算到三维空间中求A的z坐标, A z = z − A E = z − l z ∗ l y y Az=z-AE=z-lz * \frac{ly}{y} Az=zAE=zlzyly

3.阴影的实现过程

  • 先将物体正常渲染一遍,得到正常的模型显示
  • 在按第2步中的过程,将顶点投射到响应顶点的面片上,再渲染一遍,即可得到影子

4.Shader详解

  • 第一个pass正常渲染
pass {    
	//使用内置的Diffuse材质进行渲染  
    Tags { "LightMode" = "ForwardBase" }
    Material{Diffuse(1,1,1,1)}
    Lighting On
}
  • 渲染阴影
 pass {   
     Tags { "LightMode" = "ForwardBase" } 
     Blend DstColor SrcColor
     Offset -1,-1
     CGPROGRAM
     #pragma vertex vert 
     #pragma fragment frag
     #include "UnityCG.cginc"
     //接收阴影平面的world to local 矩阵
     float4x4 _World2Ground;
     //接收阴影平面的local to world 矩阵
     float4x4 _Ground2World;
     float4 vert(float4 vertex: POSITION) : SV_POSITION
     {	
         float3 litDir;
         //计算模型顶点在世界空间中的光照方向
         litDir=WorldSpaceLightDir(vertex); 
         //将世界空间中顶点的光照方向转换到接收阴影平面的模型空间中
         litDir=mul(_World2Ground,float4(litDir,0)).xyz;
         //归一化得到单位向量
         litDir=normalize(litDir);
         float4 vt;
         //将模型的顶点从模型空间转换到世界空间中
         vt= mul(unity_ObjectToWorld, vertex);
         //将模型顶点从世界空间转换到接收阴影平面的坐标空间中
         vt=mul(_World2Ground,vt);
         //计算偏移后的顶点x,y轴位置
         vt.x=vt.x-(vt.y/litDir.y)*litDir.x;
         vt.z=vt.z-(vt.y/litDir.y)*litDir.z;
         //阴影应该在接收阴影的平面上,即y轴坐标为0
         vt.y=0;
         // 将已经转换到接收阴影平面的模型空间中的顶点,转换到世界空间中去
         vt=mul(_Ground2World,vt);
         //将世界空间中的顶点转换到自己的模型空间下
         vt=mul(unity_WorldToObject,vt);
         //转换到裁剪空间中,交给片元着色器处理
         return UnityObjectToClipPos(vt);
     }

     float4 frag(void) : COLOR 
     {
         return float4(0.3,0.3,0.3,1);
     }
     ENDCG 
}

5.效果图
在这里插入图片描述
6.总结

  • 这个例子是为了讲述阴影的形成过程,实用起来会有很多不符合实际的地方, 但是知道这个原理,我们可以真正的作出一些很好看的效果。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值