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.
436 lines
14 KiB
436 lines
14 KiB
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld' |
|
|
|
// Marmoset Skyshop |
|
// Copyright 2013 Marmoset LLC |
|
// http://marmoset.co |
|
|
|
#ifndef MARMOSET_SURF_CGINC |
|
#define MARMOSET_SURF_CGINC |
|
|
|
half3 blendedDiffuseIBL(float3 worldN) { |
|
float3 skyN = worldN; |
|
skyN = skyRotate(_SkyMatrix, skyN); |
|
skyN = normalize(skyN); |
|
|
|
#ifdef MARMO_DIFFUSE_SCATTER |
|
float3 band0, band1, band2; |
|
SHLookup(skyN, band0, band1, band2); |
|
float4 scatter = _Scatter * _ScatterColor; |
|
half3 diffIBL = SHConvolve(band0, band1, band2, scatter.rgb); |
|
#else |
|
half3 diffIBL = SHLookup(skyN); |
|
#endif |
|
|
|
#ifdef MARMO_SKY_BLEND |
|
skyN = skyRotate(_SkyMatrix1, worldN); |
|
skyN = normalize(skyN); |
|
half3 diffIBL1 = SHLookup1(skyN); |
|
diffIBL = lerp(diffIBL1, diffIBL, _BlendWeightIBL); |
|
#endif |
|
return diffIBL; |
|
} |
|
|
|
void MarmosetVert(inout appdata_full v, out Input o) { |
|
UNITY_INITIALIZE_OUTPUT(Input,o); |
|
o.texcoord.xy = v.texcoord.xy; |
|
#ifdef MARMO_OCCLUSION |
|
o.texcoord.zw = v.texcoord1.xy; |
|
#endif |
|
|
|
#if defined(MARMO_SPECULAR_IBL) || defined(MARMO_BOX_PROJECTION) |
|
o.worldP.xyz = mul(unity_ObjectToWorld, v.vertex); |
|
#endif |
|
|
|
|
|
#if defined(MARMO_VERTEX_COLOR) || defined(MARMO_VERTEX_LAYER_MASK) |
|
o.color = v.color; |
|
#elif defined(MARMO_VERTEX_OCCLUSION) |
|
o.color = v.color.rg; |
|
#endif |
|
|
|
#ifdef MARMO_PACKED_VERTEX_OCCLUSION |
|
o.texcoord.zw = v.color.rg; |
|
#endif |
|
|
|
#ifdef MARMO_PACKED_VERTEX_COLOR |
|
o.texcoord.zw = v.color.rg; |
|
o.worldP.w = v.color.b; |
|
#endif |
|
|
|
float3 worldN = normalize(mul((float3x3)unity_ObjectToWorld, SCALED_NORMAL)); |
|
//Doesn't matter, Unity will recompute this and without scale afterwards >_< |
|
//o.worldNormal.xyz = worldN; |
|
|
|
#ifdef MARMO_DIFFUSE_VERTEX_IBL |
|
o.vertexIBL = blendedDiffuseIBL(worldN); |
|
#endif |
|
} |
|
|
|
void MarmosetSurf(Input IN, inout MarmosetOutput OUT) { |
|
#ifdef MARMO_CUSTOM_TILING |
|
#define uv_diff (IN.texcoord.xy * _MainTexTiling.xy + _MainTexTiling.zw) |
|
#define uv_diff1 (IN.texcoord.xy * _MainTex1Tiling.xy + _MainTex1Tiling.zw) |
|
#define uv_diff2 (IN.texcoord.xy * _MainTex2Tiling.xy + _MainTex2Tiling.zw) |
|
#define uv_diff3 (IN.texcoord.xy * _MainTex3Tiling.xy + _MainTex3Tiling.zw) |
|
|
|
#define uv_spec (IN.texcoord.xy * _SpecTexTiling.xy + _SpecTexTiling.zw) |
|
#define uv_spec1 (IN.texcoord.xy * _SpecTex1Tiling.xy + _SpecTex1Tiling.zw) |
|
#define uv_spec2 (IN.texcoord.xy * _SpecTex2Tiling.xy + _SpecTex2Tiling.zw) |
|
#define uv_spec3 (IN.texcoord.xy * _SpecTex3Tiling.xy + _SpecTex3Tiling.zw) |
|
|
|
#define uv_bump (IN.texcoord.xy * _BumpMapTiling.xy + _BumpMapTiling.zw) |
|
#define uv_bump1 (IN.texcoord.xy * _BumpMap1Tiling.xy + _BumpMap1Tiling.zw) |
|
#define uv_bump2 (IN.texcoord.xy * _BumpMap2Tiling.xy + _BumpMap2Tiling.zw) |
|
#define uv_bump3 (IN.texcoord.xy * _BumpMap3Tiling.xy + _BumpMap3Tiling.zw) |
|
|
|
#ifdef MARMO_TEXTURE_LAYER_MASK_UV1 |
|
#define uv_mask (IN.texcoord.zw * _LayerMaskTiling.xy + _LayerMaskTiling.zw) |
|
#else |
|
#define uv_mask (IN.texcoord.xy * _LayerMaskTiling.xy + _LayerMaskTiling.zw) |
|
#endif |
|
|
|
#define uv_glow (IN.texcoord.xy * _IllumTiling.xy + _IllumTiling.zw) |
|
#define uv_occ (IN.texcoord.zw * _OccTexTiling.xy + _OccTexTiling.zw) |
|
#else |
|
|
|
#define uv_diff TRANSFORM_TEX(IN.texcoord.xy, _MainTex) |
|
#define uv_diff1 TRANSFORM_TEX(IN.texcoord.xy, _MainTex1) |
|
#define uv_diff2 TRANSFORM_TEX(IN.texcoord.xy, _MainTex2) |
|
#define uv_diff3 TRANSFORM_TEX(IN.texcoord.xy, _MainTex3) |
|
|
|
#define uv_spec TRANSFORM_TEX(IN.texcoord.xy, _SpecTex) |
|
#define uv_spec1 TRANSFORM_TEX(IN.texcoord.xy, _SpecTex1) |
|
#define uv_spec2 TRANSFORM_TEX(IN.texcoord.xy, _SpecTex2) |
|
#define uv_spec3 TRANSFORM_TEX(IN.texcoord.xy, _SpecTex3) |
|
|
|
#define uv_bump TRANSFORM_TEX(IN.texcoord.xy, _BumpMap) |
|
#define uv_bump1 TRANSFORM_TEX(IN.texcoord.xy, _BumpMap1) |
|
#define uv_bump2 TRANSFORM_TEX(IN.texcoord.xy, _BumpMap2) |
|
#define uv_bump3 TRANSFORM_TEX(IN.texcoord.xy, _BumpMap3) |
|
|
|
#define uv_glow TRANSFORM_TEX(IN.texcoord.xy, _Illum) |
|
#define uv_occ TRANSFORM_TEX(IN.texcoord.zw, _OccTex) |
|
|
|
#ifdef MARMO_TEXTURE_LAYER_MASK_UV1 |
|
#define uv_mask TRANSFORM_TEX(IN.texcoord.zw, _LayerMask) |
|
#else |
|
#define uv_mask TRANSFORM_TEX(IN.texcoord.xy, _LayerMask) |
|
#endif |
|
#endif |
|
|
|
#ifdef MARMO_SKY_BLEND |
|
float skyWeight = _BlendWeightIBL; |
|
#endif |
|
|
|
half4 exposureIBL = _ExposureIBL; |
|
#if LIGHTMAP_ON |
|
exposureIBL.xy *= _ExposureLM; |
|
#endif |
|
#ifdef MARMO_SKY_BLEND |
|
half4 exposureIBL1 = _ExposureIBL1; |
|
#if LIGHTMAP_ON |
|
exposureIBL1.xy *= _ExposureLM1; |
|
#endif |
|
exposureIBL = lerp(exposureIBL1, exposureIBL, skyWeight); |
|
#endif |
|
|
|
exposureIBL.xy *= _UniformOcclusion.xy; |
|
half4 baseColor = _Color; |
|
#ifdef MARMO_VERTEX_COLOR |
|
baseColor *= IN.color; |
|
#endif |
|
|
|
#ifdef MARMO_PACKED_VERTEX_COLOR |
|
baseColor.rg *= IN.texcoord.zw; |
|
baseColor.b *= IN.worldP.w; |
|
#endif |
|
|
|
#if defined(MARMO_VERTEX_LAYER_MASK) |
|
half4 layerWeight = IN.color; |
|
#elif defined(MARMO_TEXTURE_LAYER_MASK) |
|
half4 layerWeight = tex2D(_LayerMask, uv_mask); |
|
#else |
|
half4 layerWeight = half4(1.0,0.0,0.0,0.0); |
|
#endif |
|
|
|
#if defined(MARMO_VERTEX_LAYER_MASK) || defined(MARMO_TEXTURE_LAYER_MASK) |
|
half layerSum = dot(layerWeight, half4(1.0,1.0,1.0,1.0)); |
|
layerWeight /= max(1.0, layerSum); |
|
#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) |
|
//Layered diffuse |
|
#if defined(MARMO_DIFFUSE_4_LAYER) |
|
//TODO: per-pixel weight normalize here? |
|
half4 diff; |
|
diff = layerWeight.r * tex2D( _MainTex, uv_diff ) * baseColor; |
|
diff += layerWeight.g * tex2D( _MainTex1, uv_diff1 ) * _Color1; |
|
diff += layerWeight.b * tex2D( _MainTex2, uv_diff2 ) * _Color2; |
|
diff += layerWeight.a * tex2D( _MainTex3, uv_diff3 ) * _Color3; |
|
#elif defined(MARMO_DIFFUSE_2_LAYER) |
|
half4 diff; |
|
diff = layerWeight.r * tex2D( _MainTex, uv_diff ) * baseColor; |
|
diff += layerWeight.g * tex2D( _MainTex1, uv_diff1 ) * _Color1; |
|
#else |
|
half4 diff = tex2D( _MainTex, uv_diff ) * baseColor; |
|
#endif |
|
|
|
#ifdef MARMO_DIFFUSE_SPECULAR_COMBINED |
|
diffspec = diff.aaaa; |
|
#endif |
|
|
|
//NOTE: this was the old way of doing it to separate vertex and base color from combined diff-spec alpha |
|
//diff *= baseColor; |
|
|
|
//camera exposure is built into OUT.Albedo |
|
diff.rgb *= exposureIBL.w; |
|
#ifdef MARMO_SIMPLE_GLASS |
|
diff.rgb *= diff.a; |
|
#endif |
|
OUT.Albedo = diff.rgb; |
|
OUT.Alpha = diff.a; |
|
#else |
|
#ifdef MARMO_DIFFUSE_DIRECT |
|
OUT.Albedo = baseColor.rgb; |
|
#else |
|
// we don't want any lights if direct diffuse is turned off |
|
OUT.Albedo = half3(0.0,0.0,0.0); |
|
#endif |
|
OUT.Alpha = baseColor.a; |
|
#ifdef MARMO_SIMPLE_GLASS |
|
OUT.Albedo.rgb *= baseColor.a; |
|
#endif |
|
#endif |
|
|
|
#ifdef MARMO_ALPHA_CLIP |
|
clip(OUT.Alpha - _Cutoff); |
|
#endif |
|
|
|
//AMBIENT OCC |
|
#if defined(MARMO_VERTEX_OCCLUSION) || defined(MARMO_OCCLUSION) || defined(MARMO_PACKED_VERTEX_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 |
|
|
|
#ifdef MARMO_PACKED_VERTEX_OCCLUSION |
|
occ.rg *= IN.texcoord.zw; |
|
#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 |
|
|
|
//NORMALS |
|
#ifdef MARMO_NORMALMAP |
|
#if defined(MARMO_NORMALMAP_4_LAYER) |
|
half4 norm; |
|
norm = layerWeight.r * tex2D( _BumpMap, uv_bump ); |
|
norm += layerWeight.g * tex2D( _BumpMap1, uv_bump1 ); |
|
norm += layerWeight.b * tex2D( _BumpMap2, uv_bump2 ); |
|
norm += layerWeight.a * tex2D( _BumpMap3, uv_bump3 ); |
|
float3 localN = UnpackNormal(norm); |
|
localN = normalize(localN); |
|
#elif defined(MARMO_NORMALMAP_3_LAYER) |
|
half4 norm; |
|
norm = layerWeight.r * tex2D( _BumpMap, uv_bump ); |
|
norm += layerWeight.g * tex2D( _BumpMap1, uv_bump1 ); |
|
norm += layerWeight.b * tex2D( _BumpMap2, uv_bump2 ); |
|
float3 localN = UnpackNormal(norm); |
|
localN = lerp(localN, float3(0.0,0.0,1.0), layerWeight.a); |
|
localN = normalize(localN); |
|
#elif defined(MARMO_NORMALMAP_2_LAYER) |
|
half4 norm; |
|
norm = layerWeight.r * tex2D( _BumpMap, uv_bump ); |
|
norm += layerWeight.g * tex2D( _BumpMap1, uv_bump1 ); |
|
float3 localN = UnpackNormal(norm); |
|
localN = lerp(localN, float3(0.0,0.0,1.0), layerWeight.b + layerWeight.a); |
|
localN = normalize(localN); |
|
#else |
|
float3 localN = UnpackNormal(tex2D( _BumpMap, uv_bump )); |
|
#ifdef MARMO_HQ |
|
localN = normalize(localN); |
|
#endif |
|
#endif |
|
//localN and viewDir are in tangent-space |
|
OUT.Normal = localN; |
|
float3 worldN = WorldNormalVector(IN,localN); |
|
#else |
|
float3 worldN = IN.worldNormal.xyz; |
|
worldN = normalize(worldN); |
|
#if 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 |
|
#endif |
|
|
|
//SPECULAR |
|
#if defined(MARMO_SPECULAR_DIRECT) || defined(MARMO_SPECULAR_IBL) |
|
#ifdef MARMO_DIFFUSE_SPECULAR_COMBINED |
|
half4 spec = diffspec; |
|
#else |
|
#if defined(MARMO_SPECULAR_4_LAYER) |
|
half4 spec; |
|
spec = layerWeight.r * tex2D( _SpecTex, uv_spec ); |
|
spec += layerWeight.g * tex2D( _SpecTex1, uv_spec1 ); |
|
spec += layerWeight.b * tex2D( _SpecTex2, uv_spec2 ); |
|
spec += layerWeight.a * tex2D( _SpecTex3, uv_spec3 ); |
|
#elif defined(MARMO_SPECULAR_3_LAYER) |
|
half4 spec; |
|
spec = layerWeight.r * tex2D( _SpecTex, uv_spec ); |
|
spec += layerWeight.g * tex2D( _SpecTex1, uv_spec1 ); |
|
spec += layerWeight.b * tex2D( _SpecTex2, uv_spec2 ); |
|
#elif defined(MARMO_SPECULAR_2_LAYER) |
|
half4 spec; |
|
spec = layerWeight.r * tex2D( _SpecTex, uv_spec ); |
|
spec += layerWeight.g * tex2D( _SpecTex1, uv_spec1 ); |
|
#else |
|
half4 spec = tex2D( _SpecTex, uv_spec ); |
|
#endif |
|
#endif |
|
|
|
//fresnel layering |
|
#if defined(MARMO_SPECULAR_4_LAYER) |
|
half4 fresnelLayers = half4(_Fresnel, _Fresnel1, _Fresnel2, _Fresnel3); |
|
half _fresnel = dot(layerWeight, fresnelLayers); |
|
#elif defined(MARMO_SPECULAR_3_LAYER) |
|
half3 fresnelLayers = half3(_Fresnel, _Fresnel1, _Fresnel2); |
|
half _fresnel = dot(layerWeight.rgb, fresnelLayers.rgb); |
|
#elif defined(MARMO_SPECULAR_2_LAYER) |
|
half2 fresnelLayers = half2(_Fresnel, _Fresnel1); |
|
half _fresnel = dot(layerWeight.rg, fresnelLayers.rg); |
|
#else |
|
half _fresnel = _Fresnel; |
|
#endif |
|
|
|
float3 localE = IN.viewDir.xyz; |
|
#ifdef MARMO_HQ |
|
localE = normalize(localE); |
|
half fresnel = splineFresnel(localN, localE, _SpecInt, _fresnel); |
|
#else |
|
half fresnel = fastFresnel(localN, localE, _SpecInt, _fresnel); |
|
#endif |
|
|
|
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 |
|
|
|
//camera exposure is built into OUT.Specular |
|
spec.rgb *= fresnel * exposureIBL.w; |
|
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 (direct lighting only) |
|
OUT.SpecularRGB *= specEnergyScalar(OUT.Specular); |
|
OUT.Specular *= 0.00390625; // 1/256 |
|
#endif |
|
#endif |
|
|
|
//GLOW |
|
#ifdef MARMO_GLOW |
|
half4 glow = tex2D(_Illum, uv_glow); |
|
#ifdef MARMO_SIMPLE_GLASS |
|
glow *= OUT.Alpha; |
|
#endif |
|
glow.rgb *= _GlowColor.rgb; |
|
glow.rgb *= _GlowStrength; |
|
glow.rgb *= exposureIBL.w; |
|
glow.a *= _EmissionLM; |
|
//NOTE: camera exposure is already in albedo from above |
|
glow.rgb += OUT.Albedo * glow.a; |
|
OUT.Emission += glow.rgb; |
|
#endif |
|
|
|
#if defined(MARMO_SPECULAR_IBL) || defined(MARMO_BOX_PROJECTION) |
|
float3 worldP = IN.worldP.xyz; |
|
#else |
|
float3 worldP = float3(0.0,0.0,0.0); |
|
#endif |
|
|
|
//SPECULAR IBL |
|
#ifdef MARMO_SPECULAR_IBL |
|
float3 worldE = normalize(_WorldSpaceCameraPos - worldP); |
|
|
|
#ifdef MARMO_SPECULAR_REFRACTION |
|
float4 worldF = specularRefract(-worldE, worldN, fresnel); |
|
float3 skyR = worldF.xyz; |
|
|
|
//lerp reflection color to white and refraction color to specular RGB |
|
spec.rgb = lerp(half3(_SpecInt,_SpecInt,_SpecInt), spec.rgb, worldF.w); |
|
#else |
|
float3 skyR = reflect(-worldE, worldN); |
|
#endif |
|
|
|
#ifdef MARMO_SKY_BLEND |
|
float3 skyR1 = skyR; |
|
skyR1 = skyProject(_SkyMatrix1, _InvSkyMatrix1, _SkyMin1, _SkyMax1, worldP, skyR1); |
|
#endif |
|
|
|
skyR = skyProject(_SkyMatrix, _InvSkyMatrix, _SkyMin, _SkyMax, worldP, skyR); |
|
#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(_SpecCubeIBL1, skyR1, glossLod); |
|
#else |
|
half3 specIBL1 = specCubeLookup(_SpecCubeIBL1, skyR1)*spec.a; |
|
#endif |
|
specIBL = lerp(specIBL1, specIBL, skyWeight); |
|
#endif |
|
OUT.Emission += specIBL.rgb * spec.rgb * exposureIBL.y; |
|
#endif |
|
|
|
//PEACH-FUZZ |
|
#ifdef MARMO_DIFFUSE_FUZZ |
|
float eyeDP = dot(localE, localN); |
|
eyeDP = 1.0 - eyeDP; |
|
float dp4 = eyeDP * eyeDP; dp4 *= dp4; |
|
float fuzz = _Fuzz * lerp(dp4, eyeDP*0.4, _FuzzScatter); //0.4 is energy conserving integral |
|
|
|
//HACK: modify albedo and direct lighting gets fresnel also |
|
OUT.Albedo.rgb *= 1.0 + fuzz * _FuzzColor.rgb; |
|
#endif |
|
|
|
//DIFFUSE IBL |
|
#ifdef MARMO_DIFFUSE_VERTEX_IBL |
|
//diffuseIBL comes from vertex shader |
|
OUT.Emission += IN.vertexIBL * OUT.Albedo.rgb * exposureIBL.x; |
|
#else |
|
//per-fragment diffuse lookup |
|
half3 diffIBL = blendedDiffuseIBL(worldN); |
|
OUT.Emission += diffIBL * OUT.Albedo.rgb * exposureIBL.x; |
|
#endif |
|
|
|
#ifndef MARMO_ALPHA |
|
OUT.Alpha = 1.0; |
|
#endif |
|
} |
|
|
|
#endif |