简单的头发

该Shader代码是用于Unity的UniversalRenderPipeline的头发材质实现,包括颜色、纹理、偏移、法线贴图等参数,支持额外灯光和阴影处理,涉及PBR(物理渲染)相关计算,如分布、几何和菲涅尔方程。
摘要由CSDN通过智能技术生成
Shader "JZ/Hair"
{
    Properties
    {   
        //MainHair
       [Header(_________________________Hair Tex___________________________)]
       [HDR]_MainColor("MainColor",Color)=(1,1,1,1)
       _MainTex("MainTex",2D)="white"{}
       _MainScale("MainScale",float)=1
       _PbrScale("PbrScale",Range(0,1))=0
       _Metallic("Metallic",Range(0,1))=0
       _Smoothness("Smoothness",Range(0,1))=0
       [HDR]_DarkColor("DarkColor",Color)=(1,1,1,1)
       _DarkRange("DarkRange",Range(0,1))=0
       _AoSpecular("AoSpecular",Range(0,1))=0
       _AoDiffuse("AoDiffuse",Range(0,1))=0
       _FrenselPow("RangePow",float)=1.5
        
       [Header(_________________________Hair Offset___________________________)]
       _HairOffset("HairOffset",2D)="white"{}
       _Roffset("Roffset",float)=0
       _Goffset("Goffset",float)=0
       [HDR]_Range1Color("Range1Color",Color)=(1,1,1,1)
       _AnisoRange1("AnisoRange1",Range(0.1,10))=1
       [HDR]_Range2Color("Range2Color",Color)=(1,1,1,1)
       _AnisoRange2("AnisoRange2",Range(0.1,10))=1

       [Header(_________________________Hair Normal___________________________)]
       _NormalTex("HairNormal",2D)="bump"{}
       _NormalScale("NormalScale",float)=1

      
       
       
 
 
    }
        SubShader
    {
        Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline"}
        LOD 100
 
        HLSLINCLUDE
 
        #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"
        #pragma shader_feature _ADDITIONALLIGHTS
        
        #pragma multi_compile _ _MAIN_LIGHT_SHADOWS                    
        #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE           
        #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS                         
        #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS     
        #pragma multi_compile _ _SHADOWS_SOFT         
       
        CBUFFER_START(UnityPerMaterial)
        half4 _MainTex_ST;
        half4 _MainColor;
        half4 _HairOffset_ST;
        half4 _NormalTex_ST;
        half _NormalScale;
        half _Roffset;
        half _Goffset;
        half _AnisoRange1;
        half _AnisoRange2;
        half4 _Range1Color;
        half4 _Range2Color;
        half _AoSpecular;
        half  _FrenselPow;
        half4  _DarkColor;
        half  _DarkRange;
        half _Metallic;
        half _Smoothness;
        half _AoDiffuse;
        
        half _PbrScale;
        half _MainScale;
        //----------------
        TEXTURE2D(_MainTex);SAMPLER(sampler_MainTex);
        TEXTURE2D(_HairOffset);SAMPLER(sampler_HairOffset);
        TEXTURE2D(_NormalTex);SAMPLER(sampler_NormalTex);

        CBUFFER_END
 
        struct appdata
        {
            half4 positionOS : POSITION;                   
            half4 normalOS : NORMAL;                         
            half2 texcoord : TEXCOORD0;                     
            half4 tangentOS : TANGENT;                       
        };
 
        struct v2f
        {
                                
            half4 positionCS : SV_POSITION;                
           
            half4 uv : TEXCOORD0;     
            half4 uv1: TEXCOORD1;
            half4 normalWS : TEXCOORD2;                       
            half4 tangentWS : TEXCOORD3;
            half4 btangentWS : TEXCOORD4;         
            half4 shadowCoord: TEXCOORD5;
        };  

        ENDHLSL
 
 
 
 
        Pass
        {
            Tags{ "LightMode" = "UniversalForward" }
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
          
            half Distribution(half roughness, half nh)
            {
                half lerpSquareRoughness = pow(lerp(0.01,1, roughness),2);                     
                half D = lerpSquareRoughness / (pow((pow(nh,2) * (lerpSquareRoughness - 1) + 1), 2) * PI);
                return D;
			}
           
            inline real G_subSection(half dot, half k)
            {
                return dot / lerp(dot, 1, k);
            }
          
            half Geometry(half roughness, half nl, half nv)
            {
                
 
                half k = pow(1 + roughness, 2) / 0.5;
 
                half GLeft = G_subSection(nl,k);                   
                half GRight = G_subSection(nv,k);                  
                half G = GLeft * GRight;
                return G;
			}
          
            half3 IndirF_Function(half NdotV, half3 F0, half roughness)
            {
                half Fre = exp2((-5.55473 * NdotV - 6.98316) * NdotV);
                return F0 + Fre * saturate(1 - roughness - F0);
            }
            
            half3 FresnelEquation(half3 F0,half lh)
            {
                half3 F = F0 + (1 - F0) * exp2((-5.55473 * lh - 6.98316) * lh);
                return F;
			}
           
            real3 IndirectSpeCube(half3 normalWS, half3 viewWS, half roughness, half AO)
            {
                half3 reflectDirWS = reflect(-viewWS, normalWS);                                               
                roughness = roughness * (1.7 - 0.7 * roughness);                                                
                half MidLevel = roughness * 6;                                                                    
                half4 speColor = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectDirWS, MidLevel);
                #if !defined(UNITY_USE_NATIVE_HDR)
                    return DecodeHDREnvironment(speColor, unity_SpecCube0_HDR) * AO;
                return speColor.xyz*AO;
            #endif
            }
            half3 IndirectSpeFactor(half roughness, half smoothness, half3 BRDFspe, half3 F0, half NdotV)
            {
                #ifdef UNITY_COLORSPACE_GAMMA
                half SurReduction = 1 - 0.28 * roughness * roughness;
                #else
                half SurReduction = 1 / (roughness * roughness + 1);
                #endif
                #if defined(SHADER_API_GLES) 
                half Reflectivity = BRDFspe.x;
                #else
                half Reflectivity = max(max(BRDFspe.x, BRDFspe.y), BRDFspe.z);
                #endif
                half GrazingTSection = saturate(Reflectivity + smoothness);
                half fre = Pow4(1 - NdotV);
                return lerp(F0, GrazingTSection, fre) * SurReduction;
            }
            real3 SH_IndirectionDiff(half3 normal)
            {
                real4 SHCoefficients[7];
                SHCoefficients[0] = unity_SHAr;
                SHCoefficients[1] = unity_SHAg;
                SHCoefficients[2] = unity_SHAb;
                SHCoefficients[3] = unity_SHBr;
                SHCoefficients[4] = unity_SHBg;
                SHCoefficients[5] = unity_SHBb;
                SHCoefficients[6] = unity_SHC;
                half3 Color = SampleSH9(SHCoefficients, normal);
                return max(0, Color);
            }
            half3 PBRDirectLightResult(Light light, half3 view,half3 normal, half3 albedo, half rough, half metal)
            {
                half4 lightColor = half4(light.color,1);                                 
                half3 viewDir   = normalize(view);
                half3 normalDir = normalize(normal);
                half3 lightDir  = normalize(light.direction);                            
                half3 halfDir   = normalize(viewDir + lightDir);
 
                half nh = max(saturate(dot(normalDir, halfDir)), 0.001);
                half nl = max(saturate(dot(normalDir, lightDir)),0.001);
                half nv = max(saturate(dot(normalDir, viewDir)),0.01);
              
                half hl = max(saturate(dot(halfDir, lightDir)), 0.0001);
 
                half3 F0 = lerp(0.04,albedo.rgb,metal);
 
                half D = Distribution(rough, nh);
                half G = Geometry(rough,nl,nv);
                half3 F = FresnelEquation(F0,hl);
 
                half3 ks = F;
                half3 kd = (1- ks) * (1 - metal);                   
 
 
                half3 SpecularResult = (D * G * F) / (nv * nl * 4);
 
                half3 DirectSpeColor = saturate(SpecularResult * lightColor.rgb * nl * PI );
                half3 DirectDiffColor = kd * albedo.rgb * lightColor.rgb * nl;
 
                half3 directLightResult = DirectDiffColor + DirectSpeColor;
                return directLightResult;
            } 

            v2f vert(appdata v)
            {
                v2f o=(v2f) 0;
                o.uv.xy = v.texcoord*_MainTex_ST.xy+_MainTex_ST.zw;
                o.uv.zw = v.texcoord*_HairOffset_ST.xy+_HairOffset_ST.zw;

              
              
                VertexPositionInputs  PositionInputs = GetVertexPositionInputs(v.positionOS.xyz);
                o.positionCS = PositionInputs.positionCS;                          
                half3 positionWS = PositionInputs.positionWS;                          
                VertexNormalInputs NormalInputs = GetVertexNormalInputs(v.normalOS.xyz,v.tangentOS);
                o.normalWS   =half4 (NormalInputs.normalWS.xyz,positionWS.x);                                
                o.tangentWS  =half4 (NormalInputs.tangentWS.xyz,positionWS.y);                              
                o.btangentWS =half4 (NormalInputs.bitangentWS.xyz,positionWS.z);
               
                o.shadowCoord=TransformWorldToShadowCoord( PositionInputs.positionWS);

                return o;
            }
 
            half4 frag(v2f i) : SV_Target
            {   
                //BaseMessage
                Light mainLight = GetMainLight(i.shadowCoord);      
                half atten = mainLight.shadowAttenuation * mainLight.distanceAttenuation;
                half3 light_color = mainLight.color;   
                half3 world_pos=half3(i.normalWS.w,i.tangentWS.w,i.btangentWS.w);
                half3 view_dir=half3(SafeNormalize(GetCameraPositionWS() - world_pos));
                half3 light_dir=normalize(mainLight.direction);
                half3 H_dir= normalize(view_dir + light_dir);
                float3x3 TBN=float3x3 (i.tangentWS.xyz, i.btangentWS.xyz, i.normalWS.xyz);  
                TBN=transpose(TBN);
            
                half metallic = _Metallic;
                half smoothness = _Smoothness; 
                half roughness = pow((1 - smoothness),2);
                half3 main_tex=SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.uv.xy).xyz*_MainScale;
                main_tex*=_MainColor.xyz;
                half3 unlit_color=main_tex;
                half4 hair_offset=SAMPLE_TEXTURE2D(_HairOffset,sampler_HairOffset,i.uv.zw);
                half3 hair_normal=UnpackNormalScale(SAMPLE_TEXTURE2D(_NormalTex,sampler_NormalTex,i.uv.xy),_NormalScale);
                half3 world_normal=NormalizeNormalPerPixel(mul(TBN,hair_normal));
                half r_offset=hair_offset.r*_Roffset;
                half g_offset=hair_offset.g*_Goffset;
                half hair_ao=hair_offset.b;
                
                half3 btangent_offset=i.btangentWS.xyz+(g_offset+r_offset)*world_normal;
                half base_anisotropy=sqrt(1-pow(dot(btangent_offset,H_dir),2));
                half3 anisotropy_range1=pow(base_anisotropy,_AnisoRange1*100)*_Range1Color.xyz;
                half3 anisotropy_range2=pow(base_anisotropy,_AnisoRange2*100)*_Range2Color.xyz;
                anisotropy_range1+=anisotropy_range2;
                anisotropy_range1=anisotropy_range1*lerp(1,hair_ao,_AoSpecular);
                anisotropy_range1*=dot(world_normal,view_dir);
                anisotropy_range1=pow(max(anisotropy_range1,0),_FrenselPow);
                half3 hair_dark=anisotropy_range1*_DarkColor.xyz;
                half lerp_dark=lerp(1,atten,_DarkRange);
               
                anisotropy_range1*=light_color;
                anisotropy_range1=lerp(hair_dark,anisotropy_range1,lerp_dark);
               
                

                //PBR Message
                half nh = max(saturate(dot(world_normal, H_dir)), 0.0001);
                half nl = max(saturate(dot(world_normal, light_dir)),0.01);
                half nv = max(saturate(dot(world_normal, view_dir)),0.01);
                half hl = max(saturate(dot(H_dir, light_dir)), 0.0001);
                half3 F0 = lerp(0.04,main_tex.rgb,metallic);
                half D = Distribution(roughness,nh);
                half G = Geometry(roughness,nl,nv);
                half3 F = FresnelEquation(F0,hl);
                half3 SpecularResult = (D * G * F) / (nv * nl * 4);
                half3 SpecColor = saturate(SpecularResult * light_color.xyz * nl*lerp(1,hair_ao,_AoDiffuse)*PI);                    // 这里可以AO
                half3 ks = F;
                half3 kd = (1- ks) * (1 - metallic);                   
                half3 diffColor = kd * main_tex.xyz * light_color.xyz * nl*lerp(1,hair_ao,_AoDiffuse)*atten;                                  // 这里增加自发光

                //直接光
                half3 directLightResult=diffColor;
                
                //间接光

                half3 shcolor = SH_IndirectionDiff(world_normal)*lerp(1,hair_ao,_AoDiffuse);                                         // 这里可以AO
                half3 indirect_ks = IndirF_Function(nv,F0,roughness);                          
                half3 indirect_kd = (1 - indirect_ks) * (1 - metallic);                        
                half3 indirectDiffColor = shcolor * indirect_kd * main_tex.xyz;

                half3 IndirectSpeCubeColor = IndirectSpeCube(world_normal   , view_dir, roughness, lerp(1,hair_ao,_AoDiffuse));
                half3 IndirectSpeCubeFactor = IndirectSpeFactor(roughness, smoothness, SpecularResult, F0, nv);
 
                half3 IndirectSpeColor = IndirectSpeCubeColor * IndirectSpeCubeFactor;
                
                half3 IndirectColor = IndirectSpeColor + indirectDiffColor;


                half3 finalCol = IndirectColor  + directLightResult;
                
             
                finalCol=lerp(unlit_color.xyz,finalCol.xyz,_PbrScale) +anisotropy_range1;
                //finalCol=lerp(,finalCol,mainLight.shadowAttenuation);
                return half4(finalCol,1);
             
            }
            ENDHLSL
        }     
         Pass
		{
			Name "ShadowCaster"
			Tags { "LightMode"="ShadowCaster" }

			HLSLPROGRAM
			
			#pragma vertex vert
			#pragma fragment frag

			#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

			struct a2v
			{
				float4 vertex : POSITION;
				float3 normal : NORMAL;
			};

			struct vf
			{
				float4 clipPos : SV_POSITION;
			};

			float3 _LightDirection;

			vf vert( a2v v )
			{
				vf o;

				float3 positionWS = TransformObjectToWorld(v.vertex.xyz);
				float3 normalWS = TransformObjectToWorldDir(v.normal);
				float4 clipPos = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _LightDirection));
				o.clipPos = clipPos;
				return o;
			}

			half4 frag(vf i) : SV_TARGET
			{
				return 0;
			}
			ENDHLSL
		}



    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值