VirtualFramework/Assets/PiFu/sources/ShinShader_Plus.shader
2025-04-24 17:58:40 +08:00

269 lines
13 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Shader "Unlit/ShinShader_Plus"
{
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_VERTEX _ADDITIONAL_LIGHTS
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile _ _ADDITIONAL_LIGHTS //附加光源
// forward+模式
#pragma multi_compile _ _FORWARD_PLUS
// #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 multi_compile _ _FORWARD_PLUS
//
// #pragma multi_compile_fragment _ _LIGHT_LAYERS
// #pragma multi_compile _ _FORWARD_PLUS
// #pragma multi_compile_fragment _ _WRITE_RENDERING_LAYERS
// #pragma multi_compile_fragment _ LOD_FADE_CROSSFADE
// #pragma instancing_options renderinglayer
#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.05/length(fwidth(i.worldPos))+0.5);
//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);
half3 rDirWS = reflect(-vDirWS, nTsBlur);
//dot
//half ndotl=dot(nDirWS,lDirWS);
half ndoth=max(dot(nTs,hDirWS),0.0001);
half vdoth=max(dot(vDirWS,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.6);//蓝色穿透性最弱,所以模糊度最低
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;
//half3 radiance =sss*_MainLightColor+0.6;
//return float4(sss*_MainLightColor,1);
//漫反射要乘上ndl,sss散射采样预计算贴图不需要乘ndl,直接光结果要乘上灯光颜色
half3 dirDiffCol=sss*_MainLightColor*var_Albedo.rgb*0.8+var_Albedo.rgb*0.5*max(ndotl,0.3);
//直接光高光,一层表达比较粗糙的高光,一层表达比较集中的高亮高光。
//kelemann
//float sp=tex2D(_Specular,i.uv).r;
half lobe0=SAMPLE_TEXTURE2D(_KelemenLUT,sampler_KelemenLUT,float2(ndoth,_Roughness0*0.011)).r;
half lobe1=SAMPLE_TEXTURE2D(_KelemenLUT,sampler_KelemenLUT,float2(ndoth,_Roughness1*0.01)).r;
//return float4(lobe0.xxx,1);
half PH0=pow(3.3*lobe0,5);
half PH1=pow(3.3*lobe1,5);
half3 F=F_schilick(0.05,vdoth);
//return float4(F,1);
//return float4(lobe0.xxx,1);
half3 lobe0Col=(max(PH0*F,0));
half3 lobe1Col=(max(PH1*F,0));
float mainLight=MainLightRealtimeShadow(i.shadow);
//乘以ndotl防止背面出现高光直接光高光乘上ndhsss散射采样预计算贴图不需要乘直接光结果要乘上光照颜色
half3 specCol=lerp(lobe0Col,lobe1Col,0.3)*pow(ndotl,0.8)*mainLight;
half3 dirCol=(dirDiffCol*(1-F)+specCol*_MainLightColor)*mainLight;
//return float4(specCol+dirCol,1);
float3 addColor=float3(0,0,0);
//多光源技术适配forward+管线
uint lightsCountPlus = GetAdditionalLightsCount();
InputData inputData = (InputData)0;
inputData.positionWS = i.worldPos;
inputData.normalWS = i.worldNormal;
inputData.viewDirectionWS = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
inputData.shadowCoord = TransformWorldToShadowCoord(i.worldPos);
// 修正距离剔除
inputData.normalizedScreenSpaceUV = GetNormalizedScreenSpaceUV(i.vertex);
LIGHT_LOOP_BEGIN(lightsCountPlus)
Light light=GetAdditionalLight(lightIndex,i.worldPos,0);
float3 L=light.direction;
half3 hDirWS = normalize(L + vDirWS);
half ndotl=dot(nTs,L)*0.5+0.5;
half ndoth=max(dot(nTs,hDirWS),0.0001);
half rndotl=dot(nTsBlur,L)*0.5+0.5;
float2 RUV=float2(rndotl,curvature);
float3 sss=SAMPLE_TEXTURE2D(_SSSLut,sampler_SSSLut,RUV);
half3 dirDiffCol=ndotl*light.color*(light.distanceAttenuation*light.shadowAttenuation*(var_Albedo.rgb*0.5+sss*var_Albedo.rgb*0.5));//*light.shadowAttenuation;//+var_Albedo.rgb*0.2;
//return float4(dirDiffCol,1);
half vdoth=max(dot(vDirWS,hDirWS),0.0001);
half lobe0=SAMPLE_TEXTURE2D(_KelemenLUT,sampler_KelemenLUT,float2(ndoth,_Roughness0*0.011)).r;
half lobe1=SAMPLE_TEXTURE2D(_KelemenLUT,sampler_KelemenLUT,float2(ndoth,_Roughness1*0.01)).r;
half PH0=pow(2*lobe0,5);
half PH1=pow(2*lobe1,5);
half3 F=F_schilick(0.05,vdoth);
half3 lobe0Col=(max(PH0*F,0));
half3 lobe1Col=(max(PH1*F,0));
half3 specCol=lerp(lobe0Col,lobe1Col,0.3)*pow(ndotl,0.8)*light.distanceAttenuation*light.color*light.shadowAttenuation;
half3 dirCol=dirDiffCol*(1-F);//*light.distanceAttenuation*light.color*light.shadowAttenuation;
addColor+=(specCol+dirCol);
LIGHT_LOOP_END
//间接光漫反射
half rndotv=max(dot(nTsBlur,vDirWS),0.001);
half3 inDirDiff=SampleSH(half4(nTsBlur,1));
half3 kSpec=F_inDir(0.010,rndotv,0.5);
//return float4(kSpec,1);
half3 kDiff=saturate(1.0-kSpec);
half3 inDirDiffCol=inDirDiff*var_Albedo.rgb*kDiff;
//间接光镜面反射
half mip1=0.4*(1.7-0.7*0.4)*UNITY_SPECCUBE_LOD_STEPS;
half4 inDirCube1=SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0,samplerunity_SpecCube0,float4(rDirWS,1),mip1); //cubemap采样
half3 inDirCube=saturate(DecodeHDREnvironment(inDirCube1,unity_SpecCube0_HDR));
half3 inDirSpecFac=inDirCube*kSpec;//(kSpec*lut.r+lut.g);
half3 inDirSpecCol=inDirSpecFac;//减少背光spec
half3 inDirCol=inDirDiffCol+inDirSpecCol;
half3 finaColor=inDirCol+dirCol+addColor;
return half4(finaColor,1.0);
}
ENDHLSL
}
UsePass "Universal Render Pipeline/Lit/ShadowCaster"
}
}