Unity阴影采用的是 shadow map 的技术,即把摄像机放到光源位置上,看不到的地方就有阴影。

前向渲染中,若一光源开启了阴影,Unity会计算它的阴影映射纹理(shadow map),它其实是一张深度图,记录了从光源位置出发,能看到的场景中距离它最近的表面位置的深度信息。

Unity中采用LightMode为ShadowCaster的Pass来生成这张 shadow map,首先会从本shader中找这个pass,若没有就从fallback的shader中层层寻找。

然后在fragment shader中,比较该点与shadow map中对应的点的深度,若大于,则处在阴影区域,否则不在阴影区域。

阴影包括投射阴影和接收阴影2个部分。

投射阴影,则需将该物体加入到光源的shadow map的计算中。

接收阴影,则需要对shadow map进行采样,把采样结果和最后的光照结果相乘来产生阴影效果。

shader如下:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/Forward Rendering"
{
Properties
{
_MainTex("Main Texture", 2D) = "white" {}
_Specular("Specular", Color) = (,,,)
_Gloss("Gloss", Range(,)) =
} SubShader
{
Pass
{
Tags
{
"LightMode" = "ForwardBase"
} CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase #include "UnityCg.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc" sampler2D _MainTex;
fixed4 _Specular;
float _Gloss; struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
}; struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldNormal : TEXCOORD1;
float4 worldPos: TEXCOORD2;
SHADOW_COORDS()
}; v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
TRANSFER_SHADOW(o);
return o;
} fixed4 frag(v2f i) : SV_TARGET
{
fixed4 albedo = tex2D(_MainTex, i.uv);
fixed4 ambient = albedo * UNITY_LIGHTMODEL_AMBIENT; float3 worldLight = normalize(UnityWorldSpaceLightDir(i.worldPos.xyz));
float3 worldView = normalize(UnityWorldSpaceViewDir(i.worldPos.xyz));
fixed4 diff = albedo * _LightColor0 * max(, dot(i.worldNormal, worldLight)); float3 halfDir = normalize(worldView + worldLight);
fixed4 spec = albedo * _Specular * pow(max(, dot(halfDir, i.worldNormal)), _Gloss); float shadow = SHADOW_ATTENUATION(i);
fixed4 col = ambient + (diff + spec) * shadow;
return col;
} ENDCG
} Pass
{
Tags
{
"LightMode" = "ForwardAdd"
}
Blend One One CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdadd #include "UnityCg.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc" sampler2D _MainTex;
fixed4 _Specular;
float _Gloss; struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
}; struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float3 worldNormal : TEXCOORD1;
float4 worldPos: TEXCOORD2;
SHADOW_COORDS()
}; v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
TRANSFER_SHADOW(o);
return o;
} fixed4 frag(v2f i) : SV_TARGET
{
fixed4 albedo = tex2D(_MainTex, i.uv); float3 worldLight = normalize(UnityWorldSpaceLightDir(i.worldPos.xyz));
float3 worldView = normalize(UnityWorldSpaceViewDir(i.worldPos.xyz));
fixed4 diff = albedo * _LightColor0 * max(, dot(i.worldNormal, worldLight)); float3 halfDir = normalize(worldView + worldLight);
fixed4 spec = albedo * _Specular * pow(max(, dot(halfDir, i.worldNormal)), _Gloss); // 参考 AutoLight.cginc
float atten;
#ifdef USING_DIRECTIONAL_LIGHT
atten = ;
#else
float4 lightCoord = mul(unity_WorldToLight, i.worldPos);
#ifdef POINT
atten = tex2D(_LightTexture0, dot(lightCoord.xyz,lightCoord.xyz).xx).UNITY_ATTEN_CHANNEL;
#elif SPOT
atten = (lightCoord.z > ) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).xx).UNITY_ATTEN_CHANNEL;
#endif
#endif float shadow = SHADOW_ATTENUATION(i); fixed4 col = (diff + spec) * atten * shadow;
return col;
} ENDCG
}
} Fallback "VertexLit"
}

效果如下:

Unity shader学习之阴影的更多相关文章

  1. Unity shader学习之阴影,衰减统一处理

    使用unity AutoLight.cginc文件里的内置函数 UNITY_LIGHT_ATTENUATION shader如下: // Upgrade NOTE: replaced 'mul(UNI ...

  2. Unity Shader 学习之旅

    Unity Shader 学习之旅 unityshader图形图像 纸上学来终觉浅,绝知此事要躬行 美丽的梦和美丽的诗一样 都是可遇而不可求的——席慕蓉 一.渲染流水线 示例图 Tips:什么是 GP ...

  3. Unity Shader 学习之旅之SurfaceShader

    Unity Shader 学习之旅之SurfaceShader unity shader 图形图像  如果大地的每个角落都充满了光明 谁还需要星星,谁还会 在夜里凝望 寻找遥远的安慰——江河 官方文档 ...

  4. 第四章 开始Unity Shader学习之旅(2)

    目录 1. 强大的援手:Unity提供的内置文件和变量 1.1 内置的包含文件 1.2 内置的变量 2. Unity提供的Cg/HLSL语义 2.1 什么是语义 2.2 Unity支持的语义 2.3 ...

  5. Unity Shader学习笔记-1

    本篇文章是对Unity Shader入门精要的学习笔记,插图大部分来自冯乐乐女神的github 如果有什么说的不正确的请批评指正 目录 渲染流水线 流程图 Shader作用 屏幕映射 三角形遍历 两大 ...

  6. 第四章 开始Unity Shader学习之旅(1)

    1. 一个最简单的顶点/片元着色器 现在,我们正式开始学习如何编写Unity Shader,更准确的说是,学习如何编写顶点/片元着色器 2.顶点/片元着色器的基本结构 我们在以前已经讲过了Unity ...

  7. 【Unity Shader学习笔记】Unity基础纹理-单张纹理

    1 单张纹理 1.1 纹理 使用纹理映射(Texture Mapping)技术,我们把一张图片逐纹素(Texel)地控制模型的颜色. 美术人员建模时,会在建模软件中利用纹理展开技术把纹理映射坐标(Te ...

  8. Unity shader学习之屏幕后期处理效果之高斯模糊

    高斯模糊,见 百度百科. 也使用卷积来实现,每个卷积元素的公式为: 其中б是标准方差,一般取值为1. x和y分别对应当前位置到卷积中心的整数距离. 由于需要对高斯核中的权重进行归一化,即使所有权重相加 ...

  9. Unity Shader入门精要学习笔记 - 第5章 开始 Unity Shader 学习之旅

    一个顶点/片元 着色器的结构大概如下: Shader "MyShaderName" { Properties { //属性 } SubShader { //针对显卡A的SubSha ...

随机推荐

  1. Artistic Style 3.1 A Free, Fast, and Small Automatic Formatter for C, C++, C++/CLI, Objective‑C, C#, and Java Source Code

    Artistic Style - Index http://astyle.sourceforge.net/ Artistic Style 3.1 A Free, Fast, and Small Aut ...

  2. Ubuntu16.04LTS卸载软件的命令

    写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...

  3. [python2] python 打印表格 prettytable

    rpm包: [root@D129 cli]# yum info python-prettytable Loaded plugins: fastestmirror Loading mirror spee ...

  4. 读书笔记-iOS核心动画高级技巧

    如果不使用+imageNamed:,那么把整张图片绘制到CGContext可能是最佳的方式了. 这里我们利用了CALayer的KVC来存储和检索任意的值,将图层和索引打标签. 使用KVC打标签

  5. 20165336 预备作业3 Linux安装及学习

    Linux 安装及学习 一.VirtualBox和Ubuntu的安装 依照老师所给的步骤下载了VirtualBox 5.2.6和Ubuntu 16.04.3. 按照步骤一步一步进行了安装,出现的问题有 ...

  6. SpringBoot-整合多数据源

    整合多数据源 这里有两种,分包数据源和注解数据源,这里讲分包数据源 配置文件中新增两个数据源 spring.datasource.test1.driverClassName = com.mysql.j ...

  7. python-面向对象-13_文件

    文件 目标 文件的概念 文件的基本操作 文件/文件夹的常用操作 文本文件的编码方式 01. 文件的概念 1.1 文件的概念和作用 计算机的 文件,就是存储在某种 长期储存设备 上的一段 数据 长期存储 ...

  8. pymongo模块 目录

    MongoDB pymongo模块 MongoDB pymongo模块 查询 MongoDB pymongo模块 插入数据 MongoDB pymongo模块 更新数据 MongoDB pymongo ...

  9. Wi-Fi 协议和数率?

    IEEE 802.11Wi-Fi 协议摘要 协议 频率 信号 最大数据速率 传统 802.11 2.4GHz FHSS 或 DSSS 2Mbps 802.11A 5GHz OFDM 54Mbps 80 ...

  10. freespace_evidence

    根据视点计算点云的freespace_evidence 参考资料: Bresenham's line algorithm:https://en.wikipedia.org/wiki/Bresenham ...