首先声明以下素材和shader代码都来自Kerry佬,我只做整理和学习之用,写此随笔是为了做个笔记方便以后查阅。
关于各向异性头发高光,效果可参考:
首先弄清以下知识点:
1. KK高光模型,即 Kajiya-Kay Model
传统的Phong高光模型使用 NdotH做为因子,这里采用 TsinH,即 sqrt(1 - TdotH * TdotH),注意这里是假设切线方向与发丝方向一致。
即高光公式改为如下:
half dirH = normalize(viewDir + lightDir);
half TdotH = dot(worldTangent, dirH);
half TsinH = sqrt(1 - TdotH * TdotH);
half3 specCol = pow(TsinH, _Gloss) * lightCol;
我们来用一个Sphere来做测试,由于sphere的切线方向是水平的,副法线方向是垂直分布的,所以这里我们用副法线方向来代替切线。
看下sphere的切线(绿色),副法线(红色),法线(蓝色)分布
修改高光公式之后效果如下
2. 这里还需要实现发丝的效果,即高光区域,使用如下图来对切线沿法线方向做扰动
具体公式如下,我们修改上面公式中的worldTangent值,即完整代码如下:
half shiftnoise = SAMPLE_TEXTURE2D(_ShiftMap, sampler_ShiftMap, uv);
half3 newWorldTanget = worldTangent + shiftnoise * worldNormal;
half dirH = normalize(viewDir + lightDir);
half TdotH = dot(newWorldTanget, dirH);
half TsinH = sqrt(1 - TdotH * TdotH);
half3 specCol = pow(TsinH, _Gloss) * lightCol;
最终效果如下:
shader代码如下:
1 Shader "MyURP/Kerry/Lit/KKAniso" 2 { 3 Properties 4 { 5 _Shininess("Shininess",Range(0.01,1000)) = 1.0 6 _ShiftOffset("_ShiftOffset",Range(-1,1)) = 0 7 _ShiftMap("ShitfMap",2D) = "white"{} 8 _FlowMap("_FlowMap",2D) = "gray"{} 9 } 10 SubShader 11 { 12 Tags 13 { 14 "RenderType" = "Opaque" 15 "RenderPipeline" = "UniversalPipeline" 16 } 17 LOD 100 18 19 Pass 20 { 21 Tags 22 { 23 "LightMode" = "UniversalForward" 24 } 25 HLSLPROGRAM 26 #pragma vertex vert 27 #pragma fragment frag 28 #pragma multi_compile_fwdbase 29 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" 30 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" 31 32 struct appdata 33 { 34 float4 vertex : POSITION; 35 float2 texcoord : TEXCOORD0; 36 float3 normal : NORMAL; 37 float4 tangent : TANGENT; 38 }; 39 40 struct v2f 41 { 42 float4 pos : SV_POSITION; 43 float2 uv : TEXCOORD0; 44 float3 normal_dir : TEXCOORD1; 45 float3 tangent_dir : TEXCOORD2; 46 float3 binormal_dir : TEXCOORD3; 47 float3 pos_world : TEXCOORD4; 48 }; 49 50 TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); 51 float4 _MainTex_ST; 52 float4 _LightColor0; 53 float _Shininess; 54 float _ShiftOffset; 55 TEXTURE2D(_ShiftMap); SAMPLER(sampler_ShiftMap); 56 float4 _ShiftMap_ST; 57 TEXTURE2D(_FlowMap); SAMPLER(sampler_FlowMap); 58 59 60 v2f vert(appdata v) 61 { 62 v2f o; 63 o.pos = TransformObjectToHClip(v.vertex.xyz); 64 o.uv = v.texcoord; 65 o.normal_dir = normalize(mul(float4(v.normal, 0.0), unity_WorldToObject).xyz); 66 o.tangent_dir = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz, 0.0)).xyz); 67 o.binormal_dir = normalize(cross(o.normal_dir, o.tangent_dir)) * v.tangent.w; 68 o.pos_world = mul(unity_ObjectToWorld, v.vertex).xyz; 69 return o; 70 } 71 72 half4 frag(v2f i) : SV_Target 73 { 74 Light mainLight = GetMainLight(); 75 half3 light_dir = mainLight.direction; 76 half3 view_dir = GetWorldSpaceNormalizeViewDir(i.pos_world); 77 half3 normal_dir = normalize(i.normal_dir); 78 half3 tangent_dir = normalize(i.tangent_dir); 79 half3 binormal_dir = normalize(i.binormal_dir); 80 81 half3 dirH = normalize(view_dir + light_dir); 82 half2 uv_shift = i.uv * _ShiftMap_ST.xy + _ShiftMap_ST.zw; 83 half shiftnoise = SAMPLE_TEXTURE2D(_ShiftMap, sampler_ShiftMap, uv_shift).r; 84 half3 offsetBinormal = binormal_dir + (shiftnoise + _ShiftOffset) * normal_dir; 85 half TdotH = dot(offsetBinormal, dirH); 86 half sinTH = sqrt(1 - TdotH * TdotH); 87 half3 specCol = pow(sinTH, _Shininess) * mainLight.color; 88 89 return half4(specCol, 1); 90 } 91 ENDHLSL 92 } 93 } 94 FallBack "Hidden/Universal Render Pipeline/FallbackError" 95 }
3. 双层高光
转载请注明出处:https://www.cnblogs.com/jietian331/p/17029603.html
标签:高光,KK,Shader,TdotH,half3,ShiftMap,half,dir From: https://www.cnblogs.com/jietian331/p/17029603.html