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
}
}
}
简单的头发
最新推荐文章于 2024-09-21 21:28:38 发布
该Shader代码是用于Unity的UniversalRenderPipeline的头发材质实现,包括颜色、纹理、偏移、法线贴图等参数,支持额外灯光和阴影处理,涉及PBR(物理渲染)相关计算,如分布、几何和菲涅尔方程。
摘要由CSDN通过智能技术生成