Shader "Unlit/ShinShader" { Properties { _MainTex ("Texture", 2D) = "white" {} _SSSLut("SSSLut",2D)="white"{} _KelemenLUT("KelemenLUT",2D)="white"{} _Roughness0("Roughness0",float)=0.1 _Roughness1("Roughness1",float)=0.8 _Normal("Normal",2D)="bump"{} _NormalScale("NormalScale",float)=1 _DetailNormal("DetailNormal",2D)="bump"{} _DetailNormalScale("DetailNormalScale",float)=1 _NormalBlend("NormalBlend",range(0,1))=0.5 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { HLSLPROGRAM #pragma multi_compile _ _MAIN_LIGHT_SHADOWS //接受主光源阴影 #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE //投射主光源的阴影 #pragma multi_compile _ _SHADOWS_SOFT //软阴影 #pragma multi_compile _ _ADDITIONAL_LIGHTS //附加光源 #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS #pragma shader_feature _ALPHATEST_ON #pragma vertex vert #pragma fragment frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl" //#include "UnityCG.cginc" //#include "Lighting.cginc" //#include "AutoLight.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float3 normal:NORMAL; float4 tangent:TANGENT; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float3 worldNormal:TEXCOORD1; float3 worldPos:TEXCOORD2; float3 TtW0:TEXCOORD3; float3 TtW1:TEXCOORD4; float3 TtW2:TEXCOORD5; float4 shadow:TEXCOORD6; }; TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); float4 _MainTex_ST; float3 _SSSColor; float _SSSY; TEXTURE2D(_SSSLut);SAMPLER(sampler_SSSLut); TEXTURE2D(_KelemenLUT);SAMPLER(sampler_KelemenLUT); //sampler2D _KelemenLUT; TEXTURE2D(_Normal);SAMPLER(sampler_Normal); //sampler2D _Normal; float _NormalScale; float4 _Normal_TexSize; TEXTURE2D(_DetailNormal);SAMPLER(sampler_DetailNormal); //sampler2D _DetailNormal; float _DetailNormalScale; sampler2D _Roughness; float _Roughness0; float _Roughness1; //直接光的菲尼尔 half3 F_schilick(float F0,float VdH) { return F0 + (1 - F0) * pow( 1 - saturate(VdH), 5); } //间接光的菲尼尔 half F_inDir(float F0,float NdV ,float roughness) { return F0 + (max(1.0 - roughness, F0) - F0) * pow(1.0 - NdV, 5.0); } v2f vert (appdata v) { v2f o; o.vertex = TransformObjectToHClip(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); o.worldPos=mul(UNITY_MATRIX_M,v.vertex); o.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject); float3 worldTangent=TransformObjectToWorldDir(v.tangent.xyz); float3 worldBinormal=cross(o.worldNormal,worldTangent)*v.tangent.w; o.TtW0=float3(worldTangent.x,worldBinormal.x,o.worldNormal.x); o.TtW1=float3(worldTangent.y,worldBinormal.y,o.worldNormal.y); o.TtW2=float3(worldTangent.z,worldBinormal.z,o.worldNormal.z); o.shadow=TransformWorldToShadowCoord(o.worldPos); return o; } float4 frag (v2f i) : SV_Target { //曲率 float curvature=saturate(length(fwidth(i.worldNormal))*0.001/length(fwidth(i.worldPos))+0.4); //return float4(curvature.xxx,1); float3 nTs=UnpackNormalScale(SAMPLE_TEXTURE2D(_Normal,sampler_Normal,i.uv),_NormalScale); float3 nTsM=UnpackNormalScale(SAMPLE_TEXTURE2D(_DetailNormal,sampler_DetailNormal,i.uv*4),_DetailNormalScale); nTsM=normalize(float3(dot(i.TtW0.xyz,nTsM),dot(i.TtW1.xyz,nTsM),dot(i.TtW2.xyz,nTsM))); nTs=normalize(float3(dot(i.TtW0.xyz,nTs),dot(i.TtW1.xyz,nTs),dot(i.TtW2.xyz,nTs))); float3 nTsBlur=UnpackNormalScale(SAMPLE_TEXTURE2D_LOD(_Normal,sampler_Normal, i.uv,5),_NormalScale); float3 nTsMBlur=UnpackNormalScale(SAMPLE_TEXTURE2D_LOD(_DetailNormal,sampler_DetailNormal, i.uv*4,5),_DetailNormalScale); nTsMBlur=normalize(float3(dot(i.TtW0.xyz,nTsMBlur),dot(i.TtW1.xyz,nTsMBlur),dot(i.TtW2.xyz,nTsMBlur))); nTsBlur=normalize(float3(dot(i.TtW0.xyz,nTsBlur),dot(i.TtW1.xyz,nTsBlur),dot(i.TtW2.xyz,nTsBlur))); //得到正常法线和模糊后的发线 nTs=normalize(lerp(nTs,nTsM,0.5)); nTsBlur=normalize(lerp(nTsBlur,nTsMBlur,0.5)); half3 vDirWS = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz); half3 lDirWS = normalize(_MainLightPosition); half3 hDirWS = normalize(lDirWS + vDirWS); //dot //half ndotl=dot(nDirWS,lDirWS); half ndoth=max(dot(nTs,hDirWS),0.0001); half ndotl=max(dot(nTs,lDirWS),0.0001); //Texture sample half4 var_Albedo=SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.uv.xy); //return float4(var_Albedo*0.03); //直接光漫反射,对rgb三个方向的ndl进行模糊,分别采样rgb的SSS颜色 half rndotl=dot(nTsBlur,lDirWS)*0.5+0.5;//红色穿透性最高,所以模糊度最高 half gndotl=lerp(rndotl,dot(nTs,lDirWS)*0.5+0.5,0.3); half bndotl=lerp(rndotl,dot(nTs,lDirWS)*0.5+0.5,0.7);//蓝色穿透性最弱,所以模糊度最低 float2 RUV=float2(rndotl,curvature); float2 GUV=float2(gndotl,curvature); float2 BUV=float2(bndotl,curvature); //sss就是通过采样Lut得到的漫反射颜色 float3 sss; sss.r=SAMPLE_TEXTURE2D(_SSSLut,sampler_SSSLut,RUV).r; sss.g=SAMPLE_TEXTURE2D(_SSSLut,sampler_SSSLut,GUV).g; sss.b=SAMPLE_TEXTURE2D(_SSSLut,sampler_SSSLut,BUV).b; float ndl=dot(nTs,hDirWS)*0.5+0.5; //漫反射要乘上ndl,sss散射采样预计算贴图不需要乘ndl,直接光结果要乘上灯光颜色 half3 dirDiffCol=sss*_MainLightColor*var_Albedo.rgb*ndl;//+var_Albedo.rgb*0.5*max(ndotl,0.3); //float3 diff=sss*DisneyDiffuse(ndotv,ndl,ldotv,sqrt(0.1))*ndl*var_Albedo.rgb*_MainLightColor*PI; //直接光高光,一层表达比较粗糙的高光,一层表达比较集中的高亮高光。 half lobe0=SAMPLE_TEXTURE2D(_KelemenLUT,sampler_KelemenLUT,float2(ndoth,_Roughness0*0.01)).r; half lobe1=SAMPLE_TEXTURE2D(_KelemenLUT,sampler_KelemenLUT,float2(ndoth,_Roughness1*0.01)).r; half PH0=pow(1*lobe0,5); half PH1=pow(1*lobe1,5); //f是为了遵循能量守恒,高光大的地方漫反射少 float f=lerp(PH0,PH1,0.45)*PI; half3 lobe0Col=(max(PH0,0)); half3 lobe1Col=(max(PH1,0)); float mainLight=MainLightRealtimeShadow(i.shadow); //乘以ndotl防止背面出现高光,直接光高光乘上ndh,sss散射采样预计算贴图不需要乘,直接光结果要乘上光照颜色 half3 specCol=lerp(lobe0Col,lobe1Col,0.45)*pow(ndotl,0.5)*PI; half3 dirCol=(dirDiffCol*(1-f)+specCol)*mainLight; //return float4((f).xxx,1); float3 addColor=float3(0,0,0); int addCount=GetAdditionalLightsCount(); //点光源漫反射和高光 for (int k=0;k