#ifndef POI_LIGHTING #define POI_LIGHTING int _LightingType; float _ForceLightDirection; float _ShadowStrength; float _OutlineShadowStrength; float _ShadowOffset; float3 _LightDirection; float _ForceShadowStrength; float _CastedShadowSmoothing; float _LightingIndirectContribution; float _AttenuationMultiplier; float _EnableLighting; float _LightingControlledUseLightColor; fixed _LightingStandardSmoothness; fixed _LightingStandardControlsToon; fixed _LightingMinLightBrightness; float _LightingUseShadowRamp; UNITY_DECLARE_TEX2D(_ToonRamp); fixed _LightingMonochromatic; uint _LightingNumRamps; UNITY_DECLARE_TEX2D_NOSAMPLER(_ToonRamp1); UNITY_DECLARE_TEX2D_NOSAMPLER(_ToonRamp2); half _LightingShadowStrength1; half _LightingShadowStrength2; half _ShadowOffset1; half _ShadowOffset2; fixed _LightingGradientStart; fixed _LightingGradientEnd; float3 _LightingStartColor; float3 _LightingEndColor; float _AOStrength; fixed _LightingDetailStrength; fixed _LightingAdditiveDetailStrength; fixed _LightingNoIndirectMultiplier; fixed _LightingNoIndirectThreshold; uint _LightingAdditiveType; fixed _LightingAdditiveGradientStart; fixed _LightingAdditiveGradientEnd; fixed _LightingAdditivePassthrough; /* UNITY_DECLARE_TEX2D_NOSAMPLER(_ToonRamp3); half _LightingShadowStrength3; half _ShadowOffset3; */ POI_TEXTURE_NOSAMPLER(_LightingDetailShadows); POI_TEXTURE_NOSAMPLER(_LightingAOTex); POI_TEXTURE_NOSAMPLER(_LightingShadowMask); /* * Standard stuff Start */ UnityLight CreateLight(float3 normal) { UnityLight light; light.dir = poiLight.direction; light.color = saturate(_LightColor0.rgb * lerp(1, poiLight.attenuation, _AttenuationMultiplier)); light.ndotl = DotClamped(normal, poiLight.direction); return light; } float FadeShadows(float attenuation) { #if HANDLE_SHADOWS_BLENDING_IN_GI || ADDITIONAL_MASKED_DIRECTIONAL_SHADOWS // UNITY_LIGHT_ATTENUATION doesn't fade shadows for us. #if ADDITIONAL_MASKED_DIRECTIONAL_SHADOWS attenuation = lerp(1, poiLight.attenuation, _AttenuationMultiplier); #endif float viewZ = dot(_WorldSpaceCameraPos - poiMesh.worldPos, UNITY_MATRIX_V[2].xyz); float shadowFadeDistance = UnityComputeShadowFadeDistance(poiMesh.worldPos, viewZ); float shadowFade = UnityComputeShadowFade(shadowFadeDistance); float bakedAttenuation = UnitySampleBakedOcclusion(poiMesh.lightmapUV.xy, poiMesh.worldPos); attenuation = UnityMixRealtimeAndBakedShadows( attenuation, bakedAttenuation, shadowFade ); #endif return attenuation; } void ApplySubtractiveLighting(inout UnityIndirect indirectLight) { #if SUBTRACTIVE_LIGHTING poiLight.attenuation = FadeShadows(lerp(1, poiLight.attenuation, _AttenuationMultiplier)); float ndotl = saturate(dot(i.normal, _WorldSpaceLightPos0.xyz)); float3 shadowedLightEstimate = ndotl * (1 - poiLight.attenuation) * _LightColor0.rgb; float3 subtractedLight = indirectLight.diffuse - shadowedLightEstimate; subtractedLight = max(subtractedLight, unity_ShadowColor.rgb); subtractedLight = lerp(subtractedLight, indirectLight.diffuse, _LightShadowData.x); indirectLight.diffuse = min(subtractedLight, indirectLight.diffuse); #endif } UnityIndirect CreateIndirectLight(float3 normal) { UnityIndirect indirectLight; indirectLight.diffuse = 0; indirectLight.specular = 0; #if defined(FORWARD_BASE_PASS) #if defined(LIGHTMAP_ON) indirectLight.diffuse = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, poiMesh.lightmapUV.xy)); #if defined(DIRLIGHTMAP_COMBINED) float4 lightmapDirection = UNITY_SAMPLE_TEX2D_SAMPLER( unity_LightmapInd, unity_Lightmap, poiMesh.lightmapUV.xy ); indirectLight.diffuse = DecodeDirectionalLightmap( indirectLight.diffuse, lightmapDirection, normal ); #endif ApplySubtractiveLighting(indirectLight); #endif #if defined(DYNAMICLIGHTMAP_ON) float3 dynamicLightDiffuse = DecodeRealtimeLightmap( UNITY_SAMPLE_TEX2D(unity_DynamicLightmap, poiMesh.lightmapUV.zw) ); #if defined(DIRLIGHTMAP_COMBINED) float4 dynamicLightmapDirection = UNITY_SAMPLE_TEX2D_SAMPLER( unity_DynamicDirectionality, unity_DynamicLightmap, poiMesh.lightmapUV.zw ); indirectLight.diffuse += DecodeDirectionalLightmap( dynamicLightDiffuse, dynamicLightmapDirection, normal ); #else indirectLight.diffuse += dynamicLightDiffuse; #endif #endif #if !defined(LIGHTMAP_ON) && !defined(DYNAMICLIGHTMAP_ON) #if UNITY_LIGHT_PROBE_PROXY_VOLUME if (unity_ProbeVolumeParams.x == 1) { indirectLight.diffuse = SHEvalLinearL0L1_SampleProbeVolume( float4(normal, 1), poiMesh.worldPos ); indirectLight.diffuse = max(0, indirectLight.diffuse); #if defined(UNITY_COLORSPACE_GAMMA) indirectLight.diffuse = LinearToGammaSpace(indirectLight.diffuse); #endif } else { indirectLight.diffuse += max(0, ShadeSH9(float4(normal, 1))); } #else indirectLight.diffuse += max(0, ShadeSH9(float4(normal, 1))); #endif #endif float3 reflectionDir = reflect(-poiCam.viewDir, normal); Unity_GlossyEnvironmentData envData; envData.roughness = 1 - _LightingStandardSmoothness; envData.reflUVW = BoxProjection( reflectionDir, poiMesh.worldPos.xyz, unity_SpecCube0_ProbePosition, unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax ); float3 probe0 = Unity_GlossyEnvironment( UNITY_PASS_TEXCUBE(unity_SpecCube0), unity_SpecCube0_HDR, envData ); envData.reflUVW = BoxProjection( reflectionDir, poiMesh.worldPos.xyz, unity_SpecCube1_ProbePosition, unity_SpecCube1_BoxMin, unity_SpecCube1_BoxMax ); #if UNITY_SPECCUBE_BLENDING float interpolator = unity_SpecCube0_BoxMin.w; UNITY_BRANCH if(interpolator < 0.99999) { float3 probe1 = Unity_GlossyEnvironment( UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1, unity_SpecCube0), unity_SpecCube0_HDR, envData ); indirectLight.specular = lerp(probe1, probe0, interpolator); } else { indirectLight.specular = probe0; } #else indirectLight.specular = probe0; #endif float occlusion = lerp(1, POI2D_SAMPLER_PAN(_LightingAOTex, _MainTex, poiMesh.uv[_LightingAOTexUV], _LightingAOTexPan), _AOStrength); indirectLight.diffuse *= occlusion; indirectLight.diffuse = max(indirectLight.diffuse, _LightingMinLightBrightness); indirectLight.specular *= occlusion; #endif return indirectLight; } /* * Standard stuff End */ half PoiDiffuse(half NdotV, half NdotL, half LdotH) { half fd90 = 0.5 + 2 * LdotH * LdotH * SmoothnessToPerceptualRoughness(.5); // Two schlick fresnel term half lightScatter = (1 + (fd90 - 1) * Pow5(1 - NdotL)); half viewScatter = (1 + (fd90 - 1) * Pow5(1 - NdotV)); return lightScatter * viewScatter; } float3 ShadeSH9Indirect() { return ShadeSH9(half4(0.0, -1.0, 0.0, 1.0)); } float3 ShadeSH9Direct() { return ShadeSH9(half4(0.0, 1.0, 0.0, 1.0)); } float3 ShadeSH9Normal(float3 normalDirection) { return ShadeSH9(half4(normalDirection, 1.0)); } half3 GetSHLength() { half3 x, x1; x.r = length(unity_SHAr); x.g = length(unity_SHAg); x.b = length(unity_SHAb); x1.r = length(unity_SHBr); x1.g = length(unity_SHBg); x1.b = length(unity_SHBb); return x + x1; } float3 calculateRealisticLighting(float4 colorToLight) { return UNITY_BRDF_PBS(1, 0, 0, _LightingStandardSmoothness, poiMesh.normals[1], poiCam.viewDir, CreateLight(poiMesh.normals[1]), CreateIndirectLight(poiMesh.normals[1])); } void calculateBasePassLighting() { #ifdef SIMPLE _LightingType = 1; _LightingIndirectContribution = 0.2; #endif float AOMap = 1; float3 lightColor = poiLight.color; #ifndef OUTLINE AOMap = POI2D_SAMPLER_PAN(_LightingAOTex, _MainTex, poiMesh.uv[_LightingAOTexUV], _LightingAOTexPan); #ifdef FORWARD_BASE_PASS //poiLight.color = saturate(_LightColor0.rgb) + saturate(ShadeSH9(normalize(unity_SHAr + unity_SHAg + unity_SHAb))); float3 magic = saturate(ShadeSH9(normalize(unity_SHAr + unity_SHAg + unity_SHAb))); float3 normalLight = saturate(_LightColor0.rgb); lightColor = saturate(magic * lerp(1, AOMap, _AOStrength) + normalLight); #endif #endif float3 grayscale_vector = float3(.33333, .33333, .33333); float3 ShadeSH9Plus = GetSHLength(); float3 ShadeSH9Minus = ShadeSH9(float4(0, 0, 0, 1)); poiLight.directLighting = saturate(lerp(ShadeSH9Plus, lightColor, 1 - _LightingIndirectContribution)); poiLight.indirectLighting = saturate(ShadeSH9Minus); float3 directLighting = lerp(poiLight.directLighting, dot(poiLight.directLighting, float3(0.299, 0.587, 0.114)), _LightingMonochromatic); float3 indirectLighting = lerp(poiLight.indirectLighting, dot(poiLight.indirectLighting, float3(0.299, 0.587, 0.114)), _LightingMonochromatic); if (max(max(indirectLighting.x, indirectLighting.y), indirectLighting.z) <= _LightingNoIndirectThreshold && max(max(directLighting.x, directLighting.y), directLighting.z) >= 0) { indirectLighting = directLighting * _LightingNoIndirectMultiplier; } half4 shadowStrength = 1; #ifndef OUTLINE #ifndef SIMPLE shadowStrength = POI2D_SAMPLER_PAN(_LightingShadowMask, _MainTex, poiMesh.uv[_LightingShadowMaskUV], _LightingShadowMaskPan); #endif shadowStrength *= half4(_ShadowStrength, _LightingShadowStrength1, _LightingShadowStrength2, 0); #else shadowStrength = _OutlineShadowStrength; #endif float bw_lightColor = dot(lightColor, grayscale_vector); float bw_directLighting = (((poiLight.nDotL * 0.5 + 0.5) * bw_lightColor * lerp(1, poiLight.attenuation, _AttenuationMultiplier)) + dot(ShadeSH9Normal(poiMesh.normals[1]), grayscale_vector)); float bw_bottomIndirectLighting = dot(ShadeSH9Minus, grayscale_vector); float bw_topIndirectLighting = dot(ShadeSH9Plus, grayscale_vector); float lightDifference = ((bw_topIndirectLighting + bw_lightColor) - bw_bottomIndirectLighting); fixed detailShadow = lerp(1, POI2D_SAMPLER_PAN(_LightingDetailShadows, _MainTex, poiMesh.uv[_LightingDetailShadowsUV], _LightingDetailShadowsPan), _LightingDetailStrength).r; poiLight.lightMap = smoothstep(0, lightDifference, bw_directLighting - bw_bottomIndirectLighting); poiLight.lightMap *= detailShadow; poiLight.rampedLightMap = lerp(1, UNITY_SAMPLE_TEX2D(_ToonRamp, poiLight.lightMap + _ShadowOffset), shadowStrength.r); UNITY_BRANCH if(_LightingNumRamps >= 2) { poiLight.rampedLightMap *= lerp(1, UNITY_SAMPLE_TEX2D_SAMPLER(_ToonRamp1, _ToonRamp, poiLight.lightMap + _ShadowOffset1), shadowStrength.g); } UNITY_BRANCH if(_LightingNumRamps >= 3) { poiLight.rampedLightMap *= lerp(1, UNITY_SAMPLE_TEX2D_SAMPLER(_ToonRamp2, _ToonRamp, poiLight.lightMap + _ShadowOffset2), shadowStrength.b); } UNITY_BRANCH if(_LightingStandardControlsToon) { float3 realisticLighting = calculateRealisticLighting(1); poiLight.rampedLightMap = UNITY_SAMPLE_TEX2D(_ToonRamp, (.5 + dot(realisticLighting, float3(.33333, .33333, .33333)) * .5) + _ShadowOffset); return; } UNITY_BRANCH if(_LightingType == 0) { poiLight.finalLighting = lerp(indirectLighting * lerp(1, AOMap, _AOStrength), directLighting, poiLight.rampedLightMap); } UNITY_BRANCH if(_LightingType == 1) { poiLight.finalLighting = lerp(poiLight.rampedLightMap * directLighting * lerp(1, AOMap, _AOStrength), directLighting, poiLight.rampedLightMap); } UNITY_BRANCH if(_LightingType == 3) { poiLight.finalLighting = lerp(saturate(directLighting * _LightingStartColor), saturate(indirectLighting * _LightingEndColor * lerp(1, AOMap, _AOStrength)), smoothstep(_LightingGradientStart, _LightingGradientEnd, 1 - poiLight.lightMap)); } } float3 calculateNonImportantLighting(float attenuation, float attenuationDotNL, float3 albedo, float3 lightColor, half dotNL) { UNITY_BRANCH if(_LightingAdditiveType == 0) { return lightColor * attenuationDotNL; } else { fixed detailShadow = lerp(1, POI2D_SAMPLER_PAN(_LightingDetailShadows, _MainTex, poiMesh.uv[_LightingDetailShadowsUV], _LightingDetailShadowsPan), _LightingAdditiveDetailStrength).r; return lerp(lightColor * attenuation, lightColor * _LightingAdditivePassthrough * attenuation, smoothstep(_LightingAdditiveGradientStart, _LightingAdditiveGradientEnd, dotNL)) * detailShadow; } } float3 calculateLighting(float3 albedo) { #ifdef SIMPLE _LightingType = 1; #endif #ifdef FORWARD_BASE_PASS calculateBasePassLighting(); #ifdef VERTEXLIGHT_ON poiLight.vFinalLighting = 0; for (int index = 0; index < 4; index ++) { poiLight.vFinalLighting += calculateNonImportantLighting(poiLight.vAttenuation[index], poiLight.vAttenuationDotNL[index], albedo, poiLight.vColor[index], poiLight.vCorrectedDotNL[index]); } #endif #else #if defined(POINT) || defined(SPOT) #ifndef SIMPLE fixed detailShadow = lerp(1, POI2D_SAMPLER_PAN(_LightingDetailShadows, _MainTex, poiMesh.uv[_LightingDetailShadowsUV], _LightingDetailShadowsPan), _LightingAdditiveDetailStrength).r; UNITY_BRANCH if(_LightingAdditiveType == 0) { return poiLight.color * poiLight.attenuation * max(0, poiLight.nDotL) * detailShadow; } else { return lerp(poiLight.color * max(poiLight.additiveShadow, _LightingAdditivePassthrough), poiLight.color * _LightingAdditivePassthrough, smoothstep(_LightingAdditiveGradientStart, _LightingAdditiveGradientEnd, 1 - (.5 * poiLight.nDotL + .5))) * poiLight.attenuation * detailShadow; } #else poiLight.finalLighting = poiLight.color * poiLight.attenuation; #endif #endif #endif #ifdef FORWARD_BASE_PASS UNITY_BRANCH if(_LightingType == 2) { float3 realisticLighting = calculateRealisticLighting(finalColor).rgb; return lerp(realisticLighting, dot(realisticLighting, float3(0.299, 0.587, 0.114)), _LightingMonochromatic); } else { return max(poiLight.finalLighting, _LightingMinLightBrightness); } #else return max(poiLight.finalLighting, _LightingMinLightBrightness); #endif } #endif