庄懂老师https://space.bilibili.com/6373917?spm_id_from=333.788.b_765f7570696e666f.1
先分析资源
通用的cubemap和fresnel。把透贴放到贴图的alpha里,把R:高光强度,G:边缘光强度,B:高光染色,A高光次幂放到一起
分析光照模型
最终效果和代码
Shader "Unlit/NewUnlitShader" {
Properties {
[Header(TEX)]
_MainTex ("RGB:颜色,A透明贴图",2d)="white"{}
_MaskTex ("R:高光强度,G:边缘光强度,B:高光染色,A高光次幂",2d)="black"{}
_NormalTex ("RGB:法线贴图",2d)="bump"{}
_MatelnessMask ("金属度贴图",2d)="balck"{}
_EmissionMask ("自发光遮罩",2d)="black"{}
_DiffWarpMask ("颜色Warp",2d)="gray"{}
_FresWarpTex ("菲涅尔Warp",2d)="gray"{}
_CubeMap ("环境球",cube)="_Skybox"{}
[Header(Dirdiff)]
_LightCol ("光颜色",color)=(1,1,1,1)
_EnvCol ("环境光颜色",color)=(1,1,1,1)
_EnvInt ("环境漫反射强度",range(0,5))=0.5
[Header(Dirspec)]
_SpecPow ("高光次幂",range(1,90))=90
_SpecInt ("高光强度",range(1,10))=10
_EnvSpecInt ("环境镜面反射强度",range(0,10))=1
[Header(otherl)]
[HDR]_RimCOl ("轮廓光强度",color)=(1,1,1,1)
_EmitInt ("自发光强度",range(0,10))=1
[HideInInspector]
_Cutoff ("Alpha cutoff",range(0,1))=0.5
_Color ("Main Color",color)=(1,1,1,1)
}
SubShader {
Tags {
"RenderType"="Opaque"
}
LOD 100
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
Cull off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "AutoLight.cginc"
#include "Lighting.cginc"
#pragma multi_compile_fwdbase_fullshadows
#pragma multi_compile_fog
#pragma target 3.0
//输入参数
//Texture
uniform sampler2D _MainTex;
uniform sampler2D _MaskTex;
uniform sampler2D _NormalTex;
uniform sampler2D _MatelnessMask;
uniform sampler2D _EmissionMask;
uniform sampler2D _DiffWarpMask;
uniform sampler2D _FresWarpTex;
uniform samplerCUBE _CubeMap;
//Dirdiff
uniform half3 _LightCol;
uniform half3 _EnvCol;
uniform half _EnvInt;
//Dirspec
uniform half _SpecPow;
uniform half _SpecInt;
uniform half _EnvSpecInt;
//自发光和轮廓光
uniform half3 _RimCOl;
uniform half _EmitInt;
uniform half _Cutoff;
//输入结构
struct VertexInput {
float4 vertex : POSITION; //输入模型顶点信息
float2 uv:TEXCOORD0;
float4 tangent:TANGENT;
float3 normal : NORMAL; //输入模型法线信息
};
//输出结构
struct VertexOutput {
float4 pos : SV_POSITION; //由模型顶点信息换算的顶点屏幕位置
float4 posWS : TEXCOORD1;//由模型顶点信息换算的世界顶点信息(vDir =归一化(摄像机位置- posWS))
float3 nDirWS : TEXCOORD0; //由模型法线信息换算来的世界空间法线信息
float2 uv:TEXCOORD2;
float3 bDirWS :TEXCOORD3;
float3 tDirWS :TEXCOORD4;
LIGHTING_COORDS(5, 6)
};
//输入结构>>>顶点Shader>>>输出结构
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput)0; //新建输出结构
o.pos = UnityObjectToClipPos( v.vertex ); //
o.posWS = mul(unity_ObjectToWorld, v.vertex);
o.nDirWS = UnityObjectToWorldNormal(v.normal); //把模型法线转换成世界空间法线信息
o.tDirWS = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz, 0.0)).xyz);
o.bDirWS = normalize(cross(o.nDirWS, o.tDirWS) * v.tangent.w);
o.uv = v.uv;
TRANSFER_VERTEX_TO_FRAGMENT(o)
return o;
}
//输出结构>>>像素
float4 frag(VertexOutput i) : COLOR {
//向量准备
half3 nDirTS = UnpackNormal(tex2D(_NormalTex, i.uv));
half3x3 TBN = half3x3(i.tDirWS,i.bDirWS,i.nDirWS);
half3 nDirWS = normalize(mul(nDirTS,TBN));
half3 lDirWS= _WorldSpaceLightPos0.xyz;
half3 lrDirWS=reflect(-lDirWS,nDirWS);
half3 vDirWS=normalize(_WorldSpaceCameraPos.xyz - i.posWS);
half3 vrDirWS=reflect(-vDirWS,nDirWS);
//中间量准备
half ndotl =dot(nDirWS,lDirWS);
half lrdotv=dot(lrDirWS,vDirWS);
half ndotv=dot(nDirWS,vDirWS);
//采样纹理
float4 var_MainTex=tex2D(_MainTex,i.uv);
float4 var_MaskTex=tex2D(_MaskTex,i.uv);
float var_MatelnessMask=tex2D(_MatelnessMask,i.uv).r;
float var_EmissionMask=tex2D(_EmissionMask,i.uv).r;
float3 var_FresWarpTex=tex2D(_FresWarpTex,ndotv).rgb;//菲涅尔reamtex
half3 var_CubeMap = texCUBElod(_CubeMap, float4(vrDirWS, lerp(8.0, 0.0, var_MaskTex.a))).rgb;
//提取信息
half3 baseCol =var_MainTex.rgb;
half opacity =var_MainTex.a;
half specInt =var_MaskTex.r;
half rimInt =var_MaskTex.g;
half specTint=var_MaskTex.b;
half specPow =var_MaskTex.a;
half matellic=var_MatelnessMask;
half emitInt=var_EmissionMask;
half3 envCube=var_CubeMap;
half shadow = LIGHT_ATTENUATION(i);//投影
//光照模型
//漫反射颜色
half3 diffCol =lerp(baseCol,half3(0,0,0),matellic);//以金属度作为遮罩
//镜面反射颜色
half3 specCol =lerp(baseCol,half3(0.3,0.3,0.3),specTint)*specInt;//高光染色做遮罩,再用高光强度叠加
//菲涅尔
half3 fresnel =lerp(var_FresWarpTex,0,matellic);//考虑金属,非金属的菲涅尔特性,用金属度做遮罩对Fresnel值做Lerp操作;削弱金属部分Fresnel;
half fresnelCol =fresnel.r;//无实际用途
half fresnelRim =fresnel.g;//轮廓光用Fresnel
half fresnelSpec=fresnel.b;//镜面反射用Fresnel
//光源漫反射
half halfLambert =ndotl*0.5+0.5;//半兰伯特
half3 var_DiffWarpTex =tex2D(_DiffWarpMask,half2(halfLambert,0.2));//半兰伯特构造rampuv,采样ramptex
half3 dirDiff =diffCol*var_DiffWarpTex*_LightCol;//混合漫反射颜色主光颜色和ramp结果
//主光镜面反射
half phone =pow(max(0,lrdotv),specPow*_SpecPow);//高光次幂贴图范围0-1,power使其效果更明显
half spec =phone*max(0,ndotl);//让兰伯特黑色部分镜面反射也弱一点
spec =max(spec,fresnelSpec);//和菲涅尔的高光取最大
spec=spec*_SpecInt;//乘以整体镜面反射强度
half3 dirSpec=spec*specCol*_LightCol;//和镜面反射颜色(金属染色其余几乎不染色)相乘最后乘光颜色
//环境漫反射
half3 envDiff=_EnvCol*_EnvInt*diffCol;//单色环境漫反射*强度*漫反射颜色
//环境镜面反射
half reflect =max(fresnelSpec,matellic)*specInt;//用菲涅尔高光和金属度计算整体反射度*镜面反射的遮罩
half3 envSpec=specCol*reflect*envCube*_EnvSpecInt;//镜面反射颜色*反射度*环境球*环境反射强度
//轮廓光
half3 rimLight =_RimCOl*fresnelRim*rimInt*max(0,nDirWS.g);//轮廓光颜色*菲涅尔轮廓光*轮廓光强度*法线的上下遮罩(只取上半部分)
//自发光
half3 emission =_EmitInt*diffCol*emitInt;//自发光强度*漫反射颜色*自发光遮罩
//混合
half3 finalRGB =(dirDiff+dirSpec)*shadow+envDiff+envSpec+rimLight+emission;//主光部分相加,乘以投影,再依次加上环境光部分,轮廓光,自发光;
//透明剪切
clip(opacity-_Cutoff);
return float4(finalRGB, 1.0);
}
ENDCG
}
}
//申明回退Shader
FallBack "Legacy Shaders/Transparent/Cutout/VertexLit"
}