// 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