以前工作中的一个案例,使用两个Pass , 都使用Fresnel,来表现外发光效果
然后最后的效果:
/*
UnityShader - 5.3
星球Shader
两个Pass
1 做星球表面 Diff/Norm/Spec/Rim
2 做星球外发光环, Rim + Transparent
*/
Shader "TAShaders/TEST/Planet"
{
Properties
{
_Color ("Color", Color) = (1, 1, 1, 1)
_MainTex ("Main Tex", 2D) = "grey" {}
// Specular
_Specular ("Specular", Color) = (1, 1, 1, 1)
_Gloss ("Gloss", Range(0.1, 256)) = 20
// Normal
_BumpMap ("Normal Map", 2D) = "bump" {}
//_BumpScale ("Bump Scale", Float) = 1.0
// Rim
_RimColor ("RimColor", Color) = (1, 1, 1, 1)
_RimPower ("RimPower", Range(0, 15)) = 10
_RimMulitpiler ("RimMultipiler", Range(0, 15)) = 10
// Extrusion
_Extrusion ("Extrusion", Range(0, 10)) = 1
// Panner
_PannerXSpeed ("PanX Speed", Float) = 0
}
SubShader
{
// 第1个Pass,做基本的Diff/Norm/Spec/ + Rim
Pass
{
Cull Back
Tags { "RenderType"="Opaque" "LightMode"="ForwardBase" }
CGPROGRAM
#pragma multi_compile_fwdbase
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
//#include "AutoLight.cginc"
// Fog
//#pragma multi_compile_fog
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
// Specular
fixed4 _Specular;
float _Gloss;
// Normal
sampler2D _BumpMap;
// Rim
fixed4 _RimColor;
fixed _RimPower;
fixed _RimMulitpiler;
// Extrusion
float _Extrusion;
// UVAnimSpeed
float _PannerXSpeed;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent : TANGENT;
float4 texcoord : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
// FogCoord
UNITY_FOG_COORDS(3)
// Normal
float3 lightDir: TEXCOORD1;
float3 viewDir : TEXCOORD2;
};
v2f vert(appdata v)
{
v2f o;
// 做UV动画?,也许另写脚本旋转球体比较理智,UV动画会像是一张皮在球体上滑动
v.texcoord.x += _Time * _PannerXSpeed;
// 投射空间的顶点位置
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
// Fog
//UNITY_TRANSFER_FOG(o,o.pos);
TANGENT_SPACE_ROTATION;
// 视图向量与灯光向量转到 切线空间
o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;
o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)).xyz;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
// 在切线空间计算法线
fixed3 tangentLightDir = normalize(i.lightDir);
fixed3 tangentViewDir = normalize(i.viewDir);
fixed4 packedNormal = tex2D(_BumpMap, i.uv);
fixed3 tangentNormal;
tangentNormal = UnpackNormal(packedNormal);
tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy))); // Diffuse贴图采样
fixed3 diff = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
// Lambert
fixed LM_Lambert = saturate(dot(tangentNormal, tangentLightDir));
// Ambient颜色
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
// Rim
fixed rim = saturate(dot(tangentNormal, tangentViewDir));
fixed rimPow = (15 - _RimPower);
// 取了RimPower最大值反向
fixed rimMulti = _RimMulitpiler * 0.2;
//
fixed3 rimColor = pow((1- rim),rimPow) * _RimColor * rimMulti;
// Specular
fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(tangentNormal, halfDir)), _Gloss);
// Final颜色混合
fixed3 final = (_LightColor0.rgb * diff * LM_Lambert) + (diff * ambient) + specular + rimColor;
fixed4 finalColor = fixed4(final,1.0);
// Fog
//UNITY_APPLY_FOG(i.fogCoord, finalColor);
return fixed4(finalColor);
}
ENDCG
}
// 第2个Pass,用作外轮廓发光
pass
{
// 使用Transparent排序,不使用ZWrite,
Tags { "LightMode" = "Always" "Queue"="Transparent" "IgnoreProjector"="True"}
ZWrite Off
Lighting Off
// 剔除前面的面
Cull Front
// 使用 Soft Additive混合
Blend OneMinusDstColor One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
fixed _Color;
fixed4 _RimColor;
fixed _RimPower;
fixed _RimMulitpiler;
fixed _Extrusion;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uvMatCap : TEXCOORD0;
float3 worldNormal : TEXCOORD1;
float3 worldPos : TEXCOORD2;
};
v2f vert (appdata v)
{
// 将顶点沿着法线方向向外推
v.vertex.xyz += v.normal * (_RimPower * 0.01) * _Extrusion;
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.worldNormal = mul(v.normal, (float3x3)_World2Object);
o.worldPos = mul(_Object2World, v.vertex).xyz;
return o;
}
float4 frag (v2f i) : COLOR
{
// N 世界空间法线
fixed3 worldNormal = normalize(i.worldNormal);
// V 视图向量
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
// Rim
fixed rimMulti = _RimMulitpiler * 0.001f;
// 这里对Rim倍乘做了调整,否则Rim会显得非常亮
fixed fresnel = 1 - dot(worldNormal, viewDir);
fixed3 fresnelColor = pow(fresnel,_RimPower) * _RimColor.rgb * rimMulti;
// Final
fixed3 final = fresnelColor;
return fixed4(final,1.0);
}
ENDCG
}
}
FallBack "Specular"
}
当然这也能用来表现角色,只是由于角色的模型非球形那么规则,所以沿法线挤出后总会有折叠的部分,但是也能简单的表现一下外发光效果
作者:TAZORN
著作权归作者所有
【相关阅读】:
Maxscript_基础_回调函数:http://tk.v5cg.com/help/246.html
Maxscript_基础_材质处理:http://tk.v5cg.com/help/247.html
Maxscript_基础_修改器操作:http://tk.v5cg.com/help/248.html
Maxscript_基础_创建窗口:http://tk.v5cg.com/help/249.html
Maxscript_基础_遍历与递归:http://tk.v5cg.com/help/250.html
Maxscript_与DotNet交互:http://tk.v5cg.com/help/251.html
【上传发布插件】:
编写3DMAX插件到发布上线全流程:http://tk.v5cg.com/help/147.html
代码上传与工具发布:http://tk.v5cg.com/help/99.html
代码发布,部署实例参考:http://tk.v5cg.com/help/140.html
PS【动作库】代码部署指南:http://tk.v5cg.com/help/141.html
CG云盘 - 开发者使用说明:http://tk.v5cg.com/help/34.html