天津23维预案
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

377 lines
11 KiB

2 years ago
// Marmoset Skyshop
// Copyright 2013 Marmoset LLC
// http://marmoset.co
#ifndef MARMOSET_SKIN_CGINC
#define MARMOSET_SKIN_CGINC
inline float diffuseFresnel(float eyeDP, float scatter) {
eyeDP = 1.0 - eyeDP;
float dp4 = eyeDP * eyeDP; dp4 *= dp4;
return lerp(dp4, eyeDP*0.4, scatter); //0.4 is energy conserving integral
}
inline float3 wrapLighting(float DP, float3 scatter) {
scatter *= 0.5;
float3 integral = float3(1.0,1.0,1.0)-scatter*_ConserveEnergy;
float3 light = saturate(DP*integral + scatter);
float shadow = (DP*0.5+0.5);
shadow *= shadow;
return light * integral * shadow;
}
inline half4 LightingMarmosetSkinDirect( MarmosetSkinOutput s, half3 lightDir, half3 viewDir, half atten ) {
half4 frag = half4(0.0,0.0,0.0,s.Alpha);
#if defined(MARMO_DIFFUSE_DIRECT) || defined(MARMO_SPECULAR_DIRECT)
half3 L = lightDir;
half3 N = s.Normal;
#ifdef MARMO_HQ
L = normalize(L);
#endif
#endif
float selfShadow = 1.0;
#ifdef MARMO_DIFFUSE_DIRECT
half dp = dot(N,L);
half3 diff = wrapLighting(dp, s.Subdermis); //*2.0 to match Unity
diff *= s.Albedo.rgb * 2.0;
frag.rgb = diff;
selfShadow = saturate(10.0*dp);
#else
selfShadow = saturate(10.0*dot(N,L));
#endif
#ifdef MARMO_SPECULAR_DIRECT
half3 H = viewDir+L;
#ifdef MARMO_SPECULAR_ANISO
float theta = _AnisoDir * 3.14159 / 180.0;
float3 T = float3(cos(theta),sin(theta),0.0);
H = H - T*dot(H,T)*_Aniso;
#endif
H = normalize(H);
float specRefl = saturate(dot(N,H));
half3 spec = pow(specRefl, s.Specular*256.0);
#ifdef MARMO_HQ
spec *= selfShadow;
#endif
frag.rgb += (0.5 * spec) * s.SpecularRGB; //*0.5 to match Unity
#endif
diff *= s.Albedo.rgb * 2.0;
#ifdef MARMO_SKIN_DIRECT
#ifdef MARMO_TRANSLUCENCY_DIRECT
//TRANSLUCENCY
float transdp = dot(-N,L);
half3 trans = wrapLighting(transdp, float3(1.0,1.0,1.0)); //*2.0 to match Unity
trans *= s.Translucency;
#else
half3 trans = half3(0.0,0.0,0.0);
#endif
//PEACH-FUZZ
float fuzzdp = saturate(dp*_FuzzOcc + (1.0-_FuzzOcc));
trans += s.Fuzz * _FuzzColor.rgb * fuzzdp;
frag.rgb += trans * _ExposureIBL.w;
#endif
frag.rgb *= atten * _LightColor0.rgb;
return frag;
}
void MarmosetSkinVert (inout appdata_full v, out Input o) {
UNITY_INITIALIZE_OUTPUT(Input,o);
o.texcoord = v.texcoord.xy;
#ifdef MARMO_OCCLUSION
o.texcoord1 = v.texcoord1.xy;
#endif
#ifdef MARMO_VERTEX_COLOR
o.color = v.color;
#endif
}
void MarmosetSkinSurf(Input IN, inout MarmosetSkinOutput OUT) {
#define uv_diff TRANSFORM_TEX(IN.texcoord.xy, _MainTex)
#define uv_spec TRANSFORM_TEX(IN.texcoord.xy, _SpecTex)
#define uv_bump TRANSFORM_TEX(IN.texcoord.xy, _BumpMap)
#define uv_glow TRANSFORM_TEX(IN.texcoord.xy, _Illum)
#define uv_occ TRANSFORM_TEX(IN.texcoord1.xy, _OcclusionMap)
#define uv_detail TRANSFORM_TEX(IN.texcoord.xy, _DetailMap)
#define uv_trans TRANSFORM_TEX(IN.texcoord.xy, _TranslucencyMap)
#define uv_subdermis TRANSFORM_TEX(IN.texcoord.xy, _SubdermisTex)
#ifdef MARMO_SKY_BLEND
half4 exposureIBL = lerp(_ExposureIBL1, _ExposureIBL, _BlendWeightIBL);
#else
half4 exposureIBL = _ExposureIBL;
#endif
exposureIBL.xy *= _UniformOcclusion.xy;
#if LIGHTMAP_ON
exposureIBL.xy *= _ExposureLM;
#endif
half4 baseColor = _Color;
#ifdef MARMO_VERTEX_COLOR
baseColor *= IN.color;
#endif
#ifdef MARMO_DIFFUSE_SPECULAR_COMBINED
half4 diffspec = half4(1.0,1.0,1.0,1.0);
#endif
//DIFFUSE
#if defined(MARMO_DIFFUSE_DIRECT) || defined(MARMO_DIFFUSE_IBL)
half4 diff = tex2D( _MainTex, uv_diff );
#ifdef MARMO_DIFFUSE_SPECULAR_COMBINED
diffspec = diff.aaaa;
#endif
diff *= baseColor;
OUT.Albedo = diff.rgb;
OUT.Alpha = diff.a;
#ifdef MARMO_PREMULT_ALPHA
OUT.Albedo *= diff.a;
#endif
#else
OUT.Albedo = baseColor.rgb;
OUT.Alpha = 1.0;
#endif
//AMBIENT OCC
#if defined(MARMO_VERTEX_OCCLUSION) || defined(MARMO_OCCLUSION)
half4 occ = half4(1.0,1.0,1.0,1.0);
#ifdef MARMO_OCCLUSION
occ = tex2D(_OccTex, uv_occ);
#endif
#ifdef MARMO_VERTEX_OCCLUSION
occ.rg *= IN.color.rg;
#endif
occ = lerp(half4(1.0,1.0,1.0,1.0),occ, _OccStrength);
//TODO: occlude lightprobe SH by diffuse AO
exposureIBL.xy *= occ.rg;
#endif
//SKIN
#if defined(MARMO_SKIN_IBL) || defined(MARMO_SKIN_DIRECT)
//SUBDERMIS
float4 subdermis = _SubdermisColor;
#ifdef MARMO_SUBDERMIS_MAP
subdermis *= tex2D(_SubdermisTex, uv_subdermis);
subdermis.rgb *= _Subdermis;
float skinMask = subdermis.a;
#else
#define skinMask 1.0
#endif
OUT.Subdermis = subdermis.rgb * skinMask;
#endif
//NORMALS
#ifdef MARMO_NORMALMAP
float3 localN = UnpackNormal(tex2D(_BumpMap, uv_bump));
float bias = _NormalSmoothing * 4.0;
float4 uv_blurred = float4(uv_bump.x, uv_bump.y, bias, bias);
float3 smoothN = UnpackNormal(tex2Dbias(_BumpMap, uv_blurred));
#ifdef MARMO_DETAIL
bias = _DetailSmoothing * 8.0;
uv_blurred = float4(uv_detail.x, uv_detail.y, bias, bias);
float3 detailN = UnpackNormal(tex2D(_DetailMap, uv_detail.xy));
float3 smoothDetailN = UnpackNormal(tex2Dbias(_DetailMap, uv_blurred));
float detailOcc = dot(detailN, smoothDetailN) * dot(detailN, smoothN);
localN += detailN * _DetailWeight * skinMask;
smoothN.xy += smoothDetailN.xy * _DetailWeight;
#endif
//localN and viewDir are in tangent-space
localN = normalize(localN);
smoothN = normalize(smoothN);
float specOcc = dot(localN, smoothN);
#ifdef MARMO_DETAIL
specOcc *= detailOcc;
specOcc *= specOcc;
specOcc *= specOcc;
exposureIBL.y *= specOcc;
#endif
OUT.Normal = localN;
float3 worldN = WorldNormalVector(IN, localN);
smoothN = WorldNormalVector(IN, smoothN);
#else
float3 worldN = IN.worldNormal;
#ifdef MARMO_HQ
worldN = normalize(worldN);
#endif
#if !defined(MARMO_NORMALMAP) && defined(UNITY_PASS_PREPASSFINAL)
float3 localN = float3(0.0,0.0,1.0);
//localN and viewDir are in tangent-space
#else
float3 localN = worldN;
//localN and viewDir are in world-space
#endif
float3 smoothN = localN;
#endif
float3 localE = IN.viewDir;
#ifdef MARMO_HQ
localE = normalize(localE);
#endif
//SPECULAR
#if defined(MARMO_SPECULAR_DIRECT) || defined(MARMO_SPECULAR_IBL)
#ifdef MARMO_DIFFUSE_SPECULAR_COMBINED
half4 spec = diffspec;
#else
half4 spec = tex2D(_SpecTex, uv_spec);
#endif
#ifdef MARMO_HQ
half fresnel = splineFresnel(localN, localE, _SpecInt, _Fresnel);
#else
half fresnel = fastFresnel(localN, localE, _SpecInt, _Fresnel);
#endif
//camera exposure is built into OUT.Specular
spec.rgb *= _SpecColor.rgb;
//filter the light that reaches diffuse reflection by specular intensity
#ifdef MARMO_SPECULAR_FILTER
//Light reaching diffuse is filtered by 1-specColor*specIntensity
half3 specFilter = half3(1.0,1.0,1.0) - spec.rgb * _SpecInt;
//If the material exhibits strong fresnel, bias the filter some.
specFilter += _Fresnel.xxx*0.5;
//don't let it get t crazy, clamp 0-1 and apply
OUT.Albedo *= saturate(specFilter);
#endif
spec.rgb *= fresnel;
half glossLod = glossLOD(spec.a, _Shininess);
#ifdef MARMO_SPECULAR_DIRECT
OUT.SpecularRGB = spec.rgb;
OUT.Specular = glossExponent(glossLod);
//conserve energy by dividing out specular integral
OUT.SpecularRGB *= specEnergyScalar(OUT.Specular);
OUT.Specular *= 0.00390625; // 1/256
#endif
#endif
#if defined(MARMO_SKIN_IBL) || defined(MARMO_SKIN_DIRECT)
//TRANSLUCENCY
float3 trans = _TranslucencyColor.rgb;
#ifdef MARMO_TRANSLUCENCY_MAP
trans *= tex2D(_TranslucencyMap, uv_trans).rgb;
#endif
trans *= _Translucency;
OUT.Translucency = trans.rgb * skinMask;
//PEACH-FUZZ
float eyeDP = dot(localE, localN);
OUT.Fuzz = _Fuzz * diffuseFresnel(eyeDP, _FuzzScatter) * skinMask;
#ifdef MARMO_SPECULAR_IBL
OUT.Fuzz *= 1.0-saturate(OUT.Specular);
#endif
#endif
//SPECULAR IBL
#ifdef MARMO_SPECULAR_IBL
float3 skyR = WorldReflectionVector(IN, localN);
#ifdef MARMO_SKY_BLEND
float3 skyR1 = skyRotate(_SkyMatrix1, skyR); //per-fragment matrix multiply, expensive
#endif
skyR = skyRotate(_SkyMatrix,skyR); //per-fragment matrix multiply, expensive
#ifdef MARMO_MIP_GLOSS
half3 specIBL = glossCubeLookup(_SpecCubeIBL, skyR, glossLod);
#else
half3 specIBL = specCubeLookup(_SpecCubeIBL, skyR)*spec.a;
#endif
#ifdef MARMO_SKY_BLEND
#ifdef MARMO_MIP_GLOSS
half3 specIBL1 = glossCubeLookup(_SpecCubeIBL, skyR1, glossLod);
#else
half3 specIBL1 = specCubeLookup(_SpecCubeIBL, skyR1)*spec.a;
#endif
specIBL = lerp(specIBL1, specIBL, _BlendWeightIBL);
#endif
OUT.Emission += specIBL.rgb * spec.rgb * exposureIBL.y;
#endif
//DIFFUSE IBL
#ifdef MARMO_DIFFUSE_IBL
#ifdef MARMO_SKIN_IBL
worldN = lerp(worldN, smoothN, 0.5 * skinMask);
#endif
float3 skyN = skyRotate(_SkyMatrix,worldN); //per-fragment matrix multiply, expensive
skyN = normalize(skyN);
#ifdef MARMO_SKIN_IBL
//SH DIFFUSE
float3 band0, band1, band2;
float3 unity0, unity1, unity2;
SHLookup(skyN,band0,band1,band2);
#ifdef MARMO_SKY_BLEND
float3 skyN1 = skyRotate(_SkyMatrix1, worldN); //per-fragment matrix multiply, expensive
skyN1 = normalize(skyN1);
float3 band01, band11, band21;
SHLookup1(skyN1,band01,band11,band21);
band0 = lerp(band01, band0, _BlendWeightIBL);
band1 = lerp(band11, band1, _BlendWeightIBL);
band2 = lerp(band21, band2, _BlendWeightIBL);
#endif
SHLookupUnity(worldN,unity0,unity1,unity2);
band0 = (band0*exposureIBL.x) + unity0;
band1 = (band1*exposureIBL.x) + unity1;
band2 = (band2*exposureIBL.x) + unity2;
half3 diffIBL = SHConvolve(band0, band1, band2, subdermis.rgb*skinMask);
diffIBL *= OUT.Albedo;
//PEACH FUZZ
diffIBL += OUT.Fuzz * _FuzzColor.rgb * (band0 + band1 + band2);
#ifdef MARMO_TRANSLUCENCY_IBL
//TRANSLUCENCY
float3 diffSH = SHLookup(-smoothN);
#ifdef MARMO_SKY_BLEND
float3 diffSH1 = SHLookup1(-skyN1);
diffSH = lerp(diffSH1, diffSH, _BlendWeightIBL);
#endif
diffSH *= exposureIBL.x;
diffSH += SHLookupUnity(-worldN);
diffIBL += diffSH * OUT.Translucency * _TranslucencySky;
#endif
OUT.Emission += diffIBL;
#endif
#endif
//GLOW
#ifdef MARMO_GLOW
half4 glow = tex2D(_Illum, uv_glow);
glow.rgb *= _GlowColor.rgb;
glow.rgb *= _GlowStre4ngth;
glow.a *= _EmissionLM;
//NOTE: camera exposure is already in albedo from above
glow.rgb += OUT.Albedo * glow.a;
OUT.Emission += glow.rgb;
#endif
#ifndef MARMO_ALPHA
OUT.Alpha = 1.0;
#endif
//camera exposure is built into OUT.Albedo & SpecularRGB
OUT.Albedo *= exposureIBL.w;
OUT.Emission *= exposureIBL.w;
#ifdef MARMO_SPECULAR_DIRECT
OUT.SpecularRGB *= exposureIBL.w;
#endif
}
#endif