Unity 通用透明物体漫反射Shader(双面渲染&多光源&光照衰减&法线贴图&凹凸透明度控制)
Shader "MyUnlit/AlphaBlendDiffuse"
{
Properties
{
_Color("Color Tint(贴图染色)",Color)=(1,1,1,1)
_MainTex ("Texture(主贴图)", 2D) = "white" {}
//bump为unity内置的法线纹理,当未配置任何法线纹理时,bump对应模型自带的法线信息
_NormalMap("Normal Map(法线贴图)",2D)="bump"{}
_BumpScale("Bump Scale(凹凸程度)",float) = 1.0
_Cutoff("Alpha(整体透明度)",range(0,1)) = 0.5
}
SubShader
{
//透明度混合需要定义的标签
Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } //1.Base Pass背面(顺序,透明物体先渲染背面再渲染正面)
Pass
{
//提示此Pass为前向渲染中的Base Pass,计算环境光,自发光,平行光中的阴影,不计算其他叠加光照效果
Tags{ "LightMode" = "ForwardBase" }
//透明度混合需要关闭深度写入
ZWrite Off
//开启混合操作并设置混合类型,此处类型为透明度混合
Blend SrcAlpha OneMinusSrcAlpha
//透明物体要考虑双面渲染,第一个Pass只渲染背面,剔除正面
Cull Front CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//Base Pass指令,用于得到对应的光照变量
#pragma multi_compile_fwdbase #include "UnityCG.cginc"
//包含接收阴影的宏
#include "AutoLight.cginc"
#include "Lighting.cginc" fixed4 _Color;
sampler2D _MainTex;
//用于控制对应纹理的缩放和偏移,格式固定为xx_ST
float4 _MainTex_ST;
sampler2D _NormalMap;
float4 _NormalMap_ST;
float _BumpScale;
fixed _Cutoff;//[0,1]范围内用fixed struct appdata
{
float4 vertex : POSITION;
float3 normal:NORMAL;
float4 tangent:TANGENT;//与法线不同,w需要用于控制朝向
float2 uv : TEXCOORD0;
}; struct v2f
{
//节约空间,xy分量存主贴图uv;zw存法线贴图的
float4 uv : TEXCOORD0;
float4 pos : SV_POSITION;//变量名为pos,有关阴影计算的宏中使用了此变量
//寄存器中没法存矩阵,所以分别存矩阵的每一行
float4 TtoW0 : TEXCOORD1;
float4 TtoW1 : TEXCOORD2;
float4 TtoW2 : TEXCOORD3;
SHADOW_COORDS(4)//此阴影纹理坐标存储在TEXCOORD4中
}; //此处采用在世界空间中计算法线
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
//用两个分量分别存储贴图的缩放和偏移
o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
o.uv.zw = TRANSFORM_TEX(v.uv, _NormalMap); float3 worldPos= mul(unity_ObjectToWorld, v.vertex).xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
//叉积计算第三个标准正交基轴向,w指示朝向的正负
fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
//节约空间,顺便将世界空间中的顶点位置存在w分量中
o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
//计算阴影纹理坐标
TRANSFER_SHADOW(o); return o;
} fixed4 frag (v2f i) : SV_Target
{
//还原世界坐标
float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
//还原出矩阵,用于将纹理从顶点空间(切线空间)变为世界空间,统一计算
float3x3 TtoW= float3x3(i.TtoW0.xyz, i.TtoW1.xyz, i.TtoW2.xyz);
//得到世界空间中的光源方向和视线方向
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
//从zw分量中采样出法线并进行凹凸程度的缩放,但此时法线依然处于顶点空间(切线空间)
fixed3 tanNormal = UnpackNormalWithScale(tex2D(_NormalMap, i.uv.zw), _BumpScale);
//通过之前构造的变换矩阵将法线从顶点空间变换到世界空间
fixed3 worldNormal = mul(TtoW, tanNormal);
//采样主纹理并染色,得到反射率
fixed4 col = tex2D(_MainTex, i.uv);
fixed3 albedo = col.rgb*_Color.rgb;
//计算环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
//计算漫反射
fixed3 diffuse = _LightColor0.rgb*albedo*saturate(dot(lightDir, worldNormal));
//计算光照和阴影衰减值,结果为第一个参数
UNITY_LIGHT_ATTENUATION(atten, i, worldPos); //返回计算结果
return fixed4(ambient + diffuse * atten, col.a * _Cutoff);
}
ENDCG
}
//2.Base Pass正面
Pass
{
Tags{ "LightMode" = "ForwardBase" } ZWrite Off
Blend SrcAlpha OneMinusSrcAlpha
//透明物体要考虑双面渲染,此Pass只渲染正面,剔除背面
Cull Back CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase #include "UnityCG.cginc"
#include "AutoLight.cginc"
#include "Lighting.cginc" fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _NormalMap;
float4 _NormalMap_ST;
float _BumpScale;
fixed _Cutoff; struct appdata
{
float4 vertex : POSITION;
float3 normal:NORMAL;
float4 tangent:TANGENT;
float2 uv : TEXCOORD0;
}; struct v2f
{
float4 uv : TEXCOORD0;
float4 pos : SV_POSITION; float4 TtoW0 : TEXCOORD1;
float4 TtoW1 : TEXCOORD2;
float4 TtoW2 : TEXCOORD3;
SHADOW_COORDS(4)
}; v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
o.uv.zw = TRANSFORM_TEX(v.uv, _NormalMap); float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz); fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w; o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); TRANSFER_SHADOW(o); return o;
} fixed4 frag(v2f i) : SV_Target
{ float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w); float3x3 TtoW = float3x3(i.TtoW0.xyz, i.TtoW1.xyz, i.TtoW2.xyz); fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos)); fixed3 tanNormal = UnpackNormalWithScale(tex2D(_NormalMap, i.uv.zw), _BumpScale); fixed3 worldNormal = mul(TtoW, tanNormal); fixed4 col = tex2D(_MainTex, i.uv);
fixed3 albedo = col.rgb*_Color.rgb; fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo; fixed3 diffuse = _LightColor0.rgb*albedo*saturate(dot(lightDir, worldNormal)); UNITY_LIGHT_ATTENUATION(atten, i, worldPos); return fixed4(ambient + diffuse * atten, col.a * _Cutoff);
}
ENDCG
}
//3.Add Pass正常渲染
Pass
{
//提示此Pass为前向渲染中的Add Pass,计算其他叠加光照效果,每个光源计算一次
Tags{ "LightMode" = "ForwardAdd" } ZWrite Off
Blend SrcAlpha One
Cull Back CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//Add Pass指令,用于得到对应的光照变量
//#pragma multi_compile_fwdadd
//阴影情况下使用:
#pragma multi_compile_fwdadd_fullshadows #include "UnityCG.cginc"
#include "AutoLight.cginc"
#include "Lighting.cginc" fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
sampler2D _NormalMap;
float4 _NormalMap_ST;
float _BumpScale;
fixed _Cutoff; struct appdata
{
float4 vertex : POSITION;
float3 normal:NORMAL;
float4 tangent:TANGENT;
float2 uv : TEXCOORD0;
}; struct v2f
{
float4 uv : TEXCOORD0;
float4 pos : SV_POSITION; float4 TtoW0 : TEXCOORD1;
float4 TtoW1 : TEXCOORD2;
float4 TtoW2 : TEXCOORD3;
SHADOW_COORDS(4)
}; v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
o.uv.zw = TRANSFORM_TEX(v.uv, _NormalMap); float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz); fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w; o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z); TRANSFER_SHADOW(o); return o;
} fixed4 frag(v2f i) : SV_Target
{ float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w); float3x3 TtoW = float3x3(i.TtoW0.xyz, i.TtoW1.xyz, i.TtoW2.xyz); fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos)); fixed3 tanNormal = UnpackNormalWithScale(tex2D(_NormalMap, i.uv.zw), _BumpScale); fixed3 worldNormal = mul(TtoW, tanNormal); fixed4 col = tex2D(_MainTex, i.uv);
fixed3 albedo = col.rgb*_Color.rgb; fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo; fixed3 diffuse = _LightColor0.rgb*albedo*saturate(dot(lightDir, worldNormal)); UNITY_LIGHT_ATTENUATION(atten, i, worldPos); return fixed4(ambient + diffuse * atten, col.a * _Cutoff);
}
ENDCG
}
}
//无阴影
//FallBack "Transparent/VertexLit"
//强制产生阴影
FallBack "VertexLit"
}
对于至今为止Shader学习内容的一个总结,算是一个比较综合通用的shader了,因为是漫反射所以暂时没有计算高光部分,之后再出一个带高光版本的。
备注都有比较详细的说明,基本思路是利用多个Pass分别进行正反面的渲染,再结合前向渲染的分光照渲染来实现。
最后摆出效果图w~


Unity 通用透明物体漫反射Shader(双面渲染&多光源&光照衰减&法线贴图&凹凸透明度控制)的更多相关文章
- [转]解读Unity中的CG编写Shader系列8——多光源漫反射
前文中完成最简单的漫反射shader只是单个光源下的漫反射,而往往场景中不仅仅只有一个光源,那么多个光源的情况下我们的物体表面的漫反射强度如何叠加在一起呢?前文打的tag "LightMod ...
- unity给子物体添加Shader
分享两个自制Shader:http://pan.baidu.com/s/1nuRcF2L Shader存放路径:\Assets\Resources\Shader\ 定义Shader类型: public ...
- shader复杂与深入:Normal Map(法线贴图)1
转自:http://www.zwqxin.com/archives/shaderglsl/review-normal-map-bump-map.htmlNormal Map法线贴图,想必每个学习计算机 ...
- 解读Unity中的CG编写Shader系列八(多光源漫反射)
转自http://www.itnose.net/detail/6117338.html 前文中完成最简单的漫反射shader只是单个光源下的漫反射,而往往场景中不仅仅只有一个光源,那么多个光源的情况下 ...
- 【Unity Shader】七、透明的Transparent Shader
学习资料: http://www.sikiedu.com/course/37/task/459/show# 本例的代码基于上一篇文章,添加透明效果.为了便于区分新增的部分,该部分使用和红色加粗字体. ...
- [转]解读Unity中的CG编写Shader系列7——漫反射
如果前面几个系列文章的内容过于冗长缺乏趣味着实见谅,由于时间原因前面的混合部分还没有写完,等以后再补充,现在开始关于反射的内容了.折射与反射在物理世界中,光的反射与折射往往是同时存在的,光源由真空或者 ...
- Unity Shader 之 渲染流水线
Unity Shader 之渲染流水线 什么是渲染流水线 一个渲染流程分成3个步骤: 应用阶段(Application stage) 几何阶段(Geometry stage) 光栅化阶段(Raster ...
- [Unity Shader笔记]渲染路径--Forward渲染路径
[Unity Shader笔记]渲染路径--Forward渲染路径 (2014-04-22 20:08:25) 转载▼ 标签: shader unity renderingpath forward 游 ...
- 【Unity Shaders】初探Surface Shader背后的机制
转载请注明出处:http://blog.csdn.net/candycat1992/article/details/39994049 写在前面 一直以来,Unity Surface Shader背后的 ...
随机推荐
- VAssist 使用技巧(函数声明定位,比VS的还要强大)
1. 有了VAX可以关掉C++导航栏,快捷键ALT+M,显示当前打开文档的所有符号,而且可以输入进行过滤 2. 查找文件,shift+alt+o (直接定位) 3. 查找符号shift+alt+s 4 ...
- WPF 窗体基类实现的体验及实现回车到下一控件
原文:WPF 窗体基类实现的体验及实现回车到下一控件 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/jsyhello/article/details ...
- 矩阵十点【两】 poj 1575 Tr A poj 3233 Matrix Power Series
poj 1575 Tr A 主题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1575 题目大意:A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的 ...
- poj 3390 Print Words in Lines 动态规划
意甲冠军: 给n每行长度和字符可放置最大数量字m,每一行产生值至(m-x)^2,x是一个字符上线人数(包含空话之间格).为了让所有的完成,产生的话值最小和. 分析: 动态规划非常重要的就是状态的定义, ...
- NLP(paper + code)
0. 开源的库 genism keras wrapper of theano/TensorFlow 1. CNN for NLP Convolutional Neural Networks for S ...
- 分享一下Oracle 10g和Toad for Oracle的安装步骤
三年前用过Oracle,单纯的“用过”,主要就是说对数据库的一些操作,还不包含创建一些存储过程之类的,所以对Oracle仅仅只是了解一点儿,因为当时那家公司里面,数据库里面的东西都是那些顾问负责的,再 ...
- NS2网络模拟(4)-吞吐率图
1: #NS2_有线部分\ForGnuplot.plot 2: 3: #gnuplot> 4: #set xtics 0, 1, 10 5: set grid 6: set xrange [0: ...
- eclise配置tomcat出现服务Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4 and Java EE 5 Web modules
当部署项目Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, 1.5 and Java EE 5 Web modules错;解决方案,如下面: 空 ...
- JSONObject 解析
前解析json已使用get方法,但是,假设抛出将解决很烦人中断. 今天发现JSONObject还提供了一个更好用的方法opt.看来以后文档还是要更加认真的读的.以下是文档中的原文. A JSONObj ...
- Android 混淆代码汇总
为了防止别人对自己被盗的劳动,混淆代码可以被反编译可以有效地防止,以下在下面的代码混乱总结的步骤: 1. 大家可能已经注意到一个新的项目将在下面看到的物品都有这个proguard-project.tx ...