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背后的 ...
随机推荐
- options.parse === void 0
if (options.parse === void 0) options.parse = true; https://developer.mozilla.org/zh-CN/docs/Web/Jav ...
- 获得WIN7管理员权限(可通过修改注册表,或者组策略改变)
在使用WIN7过程中,常常会再出现没有管理员权限而不能正常运行软件(有的软件直接就是打不开,有的软件不能正常运行(比如如果没有管理员权限,keil就不能注册成功))....也许你会说,我的电脑里只有一 ...
- c语言学习笔记(10)——结构体
------------------------------------------------------------------ # include <stdio.h> struct ...
- Scripting web services
A process performed on a server includes configuring the server to enable script for a Web service t ...
- OpenCV 图像白平衡算法(相机自动白平衡)
彩色相机内部有三个CCD电子耦合元件,分别用来感受红绿蓝三中颜色的光线,默认情况下,三个颜色的感光电路信号的放大比例是1:1:1的.在理想的拍摄环境下,纯白色的RGB分量按照1:1:1的比例放大之后, ...
- 创建一个显示所有预定义系统颜色的ListBox
原文 Creating a ListBox that Shows All Predefined System Colors 该System.Windows.SystemColors类包含了一系列揭露当 ...
- MySQL第五个学习笔记 该数据表的操作
MySQL在创建表,创建.frm文件保存表和列定义.索引存储在一个.MYI(MYindex)且数据存储在有.MYD(MYData)扩展名的文件里. 一.用SHOW/ DESCRIBE语句显示数据表 ...
- WPF - 善用路由事件
原文:WPF - 善用路由事件 在原来的公司中,编写自定义控件是常常遇到的任务.但这些控件常常拥有一个不怎么好的特点:无论是内部还是外部都没有使用路由事件.那我们应该怎样宰自定义控件开发中使用路由事件 ...
- WPF与缓动(一) N次缓动
原文:WPF与缓动(一) N次缓动 WPF与缓动(一) N次缓动 ...
- This problem will occur when running in 64 bit mode with the 32 bit Oracle client components installed.
Attempt to load Oracle client libraries threw BadImageFormatException. This problem will occur when ...