- Moved video screen into its own separate movie tent. - Adjusted stable post-processing volume. - Chickens are now at full volume. - Added button to toggle chickens off and on.
207 lines
8.6 KiB
HLSL
207 lines
8.6 KiB
HLSL
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
|
|
|
|
#ifndef UNITY_GLOBAL_ILLUMINATION_INCLUDED
|
|
#define UNITY_GLOBAL_ILLUMINATION_INCLUDED
|
|
|
|
// Functions sampling light environment data (lightmaps, light probes, reflection probes), which is then returned as the UnityGI struct.
|
|
|
|
#include "UnityImageBasedLighting.cginc"
|
|
#include "UnityStandardUtils.cginc"
|
|
#include "UnityShadowLibrary.cginc"
|
|
|
|
inline half3 DecodeDirectionalSpecularLightmap (half3 color, half4 dirTex, half3 normalWorld, bool isRealtimeLightmap, fixed4 realtimeNormalTex, out UnityLight o_light)
|
|
{
|
|
o_light.color = color;
|
|
o_light.dir = dirTex.xyz * 2 - 1;
|
|
o_light.ndotl = 0; // Not use;
|
|
|
|
// The length of the direction vector is the light's "directionality", i.e. 1 for all light coming from this direction,
|
|
// lower values for more spread out, ambient light.
|
|
half directionality = max(0.001, length(o_light.dir));
|
|
o_light.dir /= directionality;
|
|
|
|
#ifdef DYNAMICLIGHTMAP_ON
|
|
if (isRealtimeLightmap)
|
|
{
|
|
// Realtime directional lightmaps' intensity needs to be divided by N.L
|
|
// to get the incoming light intensity. Baked directional lightmaps are already
|
|
// output like that (including the max() to prevent div by zero).
|
|
half3 realtimeNormal = realtimeNormalTex.xyz * 2 - 1;
|
|
o_light.color /= max(0.125, dot(realtimeNormal, o_light.dir));
|
|
}
|
|
#endif
|
|
|
|
// Split light into the directional and ambient parts, according to the directionality factor.
|
|
half3 ambient = o_light.color * (1 - directionality);
|
|
o_light.color = o_light.color * directionality;
|
|
|
|
// Technically this is incorrect, but helps hide jagged light edge at the object silhouettes and
|
|
// makes normalmaps show up.
|
|
ambient *= saturate(dot(normalWorld, o_light.dir));
|
|
return ambient;
|
|
}
|
|
|
|
inline void ResetUnityLight(out UnityLight outLight)
|
|
{
|
|
outLight.color = half3(0, 0, 0);
|
|
outLight.dir = half3(0, 1, 0); // Irrelevant direction, just not null
|
|
outLight.ndotl = 0; // Not used
|
|
}
|
|
|
|
inline half3 SubtractMainLightWithRealtimeAttenuationFromLightmap (half3 lightmap, half attenuation, half4 bakedColorTex, half3 normalWorld)
|
|
{
|
|
// Let's try to make realtime shadows work on a surface, which already contains
|
|
// baked lighting and shadowing from the main sun light.
|
|
half3 shadowColor = unity_ShadowColor.rgb;
|
|
half shadowStrength = _LightShadowData.x;
|
|
|
|
// Summary:
|
|
// 1) Calculate possible value in the shadow by subtracting estimated light contribution from the places occluded by realtime shadow:
|
|
// a) preserves other baked lights and light bounces
|
|
// b) eliminates shadows on the geometry facing away from the light
|
|
// 2) Clamp against user defined ShadowColor.
|
|
// 3) Pick original lightmap value, if it is the darkest one.
|
|
|
|
|
|
// 1) Gives good estimate of illumination as if light would've been shadowed during the bake.
|
|
// Preserves bounce and other baked lights
|
|
// No shadows on the geometry facing away from the light
|
|
half ndotl = LambertTerm (normalWorld, _WorldSpaceLightPos0.xyz);
|
|
half3 estimatedLightContributionMaskedByInverseOfShadow = ndotl * (1- attenuation) * _LightColor0.rgb;
|
|
half3 subtractedLightmap = lightmap - estimatedLightContributionMaskedByInverseOfShadow;
|
|
|
|
// 2) Allows user to define overall ambient of the scene and control situation when realtime shadow becomes too dark.
|
|
half3 realtimeShadow = max(subtractedLightmap, shadowColor);
|
|
realtimeShadow = lerp(realtimeShadow, lightmap, shadowStrength);
|
|
|
|
// 3) Pick darkest color
|
|
return min(lightmap, realtimeShadow);
|
|
}
|
|
|
|
inline void ResetUnityGI(out UnityGI outGI)
|
|
{
|
|
ResetUnityLight(outGI.light);
|
|
outGI.indirect.diffuse = 0;
|
|
outGI.indirect.specular = 0;
|
|
}
|
|
|
|
inline UnityGI UnityGI_Base(UnityGIInput data, inout half occlusion, half3 normalWorld)
|
|
{
|
|
UnityGI o_gi;
|
|
ResetUnityGI(o_gi);
|
|
|
|
// Base pass with Lightmap support is responsible for handling ShadowMask / blending here for performance reason
|
|
#if defined(HANDLE_SHADOWS_BLENDING_IN_GI)
|
|
half bakedAtten = UnitySampleBakedOcclusion(data.lightmapUV.xy, data.worldPos);
|
|
float zDist = dot(_WorldSpaceCameraPos - data.worldPos, UNITY_MATRIX_V[2].xyz);
|
|
float fadeDist = UnityComputeShadowFadeDistance(data.worldPos, zDist);
|
|
data.atten = UnityMixRealtimeAndBakedShadows(data.atten, bakedAtten, UnityComputeShadowFade(fadeDist));
|
|
#endif
|
|
|
|
o_gi.light = data.light;
|
|
o_gi.light.color *= data.atten;
|
|
|
|
#if UNITY_SHOULD_SAMPLE_SH
|
|
o_gi.indirect.diffuse = ShadeSHPerPixel(normalWorld, data.ambient, data.worldPos);
|
|
#endif
|
|
|
|
#if defined(LIGHTMAP_ON)
|
|
// Baked lightmaps
|
|
half4 bakedColorTex = UNITY_SAMPLE_TEX2D(unity_Lightmap, data.lightmapUV.xy);
|
|
half3 bakedColor = DecodeLightmap(bakedColorTex);
|
|
|
|
// Derive specular occlusion
|
|
|
|
half bakedOcclusion = saturate(dot(bakedColor * 3.0, 1.0));
|
|
occlusion *= bakedOcclusion;
|
|
|
|
#ifdef DIRLIGHTMAP_COMBINED
|
|
fixed4 bakedDirTex = UNITY_SAMPLE_TEX2D_SAMPLER (unity_LightmapInd, unity_Lightmap, data.lightmapUV.xy);
|
|
o_gi.indirect.diffuse += DecodeDirectionalLightmap (bakedColor, bakedDirTex, normalWorld);
|
|
|
|
#if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
|
|
ResetUnityLight(o_gi.light);
|
|
o_gi.indirect.diffuse = SubtractMainLightWithRealtimeAttenuationFromLightmap (o_gi.indirect.diffuse, data.atten, bakedColorTex, normalWorld);
|
|
#endif
|
|
|
|
#else // not directional lightmap
|
|
o_gi.indirect.diffuse += bakedColor;
|
|
|
|
#if defined(LIGHTMAP_SHADOW_MIXING) && !defined(SHADOWS_SHADOWMASK) && defined(SHADOWS_SCREEN)
|
|
ResetUnityLight(o_gi.light);
|
|
o_gi.indirect.diffuse = SubtractMainLightWithRealtimeAttenuationFromLightmap(o_gi.indirect.diffuse, data.atten, bakedColorTex, normalWorld);
|
|
#endif
|
|
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef DYNAMICLIGHTMAP_ON
|
|
// Dynamic lightmaps
|
|
fixed4 realtimeColorTex = UNITY_SAMPLE_TEX2D(unity_DynamicLightmap, data.lightmapUV.zw);
|
|
half3 realtimeColor = DecodeRealtimeLightmap (realtimeColorTex);
|
|
|
|
#ifdef DIRLIGHTMAP_COMBINED
|
|
half4 realtimeDirTex = UNITY_SAMPLE_TEX2D_SAMPLER(unity_DynamicDirectionality, unity_DynamicLightmap, data.lightmapUV.zw);
|
|
o_gi.indirect.diffuse += DecodeDirectionalLightmap (realtimeColor, realtimeDirTex, normalWorld);
|
|
#else
|
|
o_gi.indirect.diffuse += realtimeColor;
|
|
#endif
|
|
#endif
|
|
|
|
o_gi.indirect.diffuse *= occlusion;
|
|
return o_gi;
|
|
}
|
|
|
|
|
|
inline half3 UnityGI_IndirectSpecular(UnityGIInput data, half occlusion, Unity_GlossyEnvironmentData glossIn)
|
|
{
|
|
half3 specular;
|
|
|
|
#ifdef UNITY_SPECCUBE_BOX_PROJECTION
|
|
// we will tweak reflUVW in glossIn directly (as we pass it to Unity_GlossyEnvironment twice for probe0 and probe1), so keep original to pass into BoxProjectedCubemapDirection
|
|
half3 originalReflUVW = glossIn.reflUVW;
|
|
glossIn.reflUVW = BoxProjectedCubemapDirection (originalReflUVW, data.worldPos, data.probePosition[0], data.boxMin[0], data.boxMax[0]);
|
|
#endif
|
|
|
|
#ifdef _GLOSSYREFLECTIONS_OFF
|
|
specular = unity_IndirectSpecColor.rgb;
|
|
#else
|
|
half3 env0 = Unity_GlossyEnvironment (UNITY_PASS_TEXCUBE(unity_SpecCube0), data.probeHDR[0], glossIn);
|
|
#ifdef UNITY_SPECCUBE_BLENDING
|
|
const float kBlendFactor = 0.99999;
|
|
float blendLerp = data.boxMin[0].w;
|
|
UNITY_BRANCH
|
|
if (blendLerp < kBlendFactor)
|
|
{
|
|
#ifdef UNITY_SPECCUBE_BOX_PROJECTION
|
|
glossIn.reflUVW = BoxProjectedCubemapDirection (originalReflUVW, data.worldPos, data.probePosition[1], data.boxMin[1], data.boxMax[1]);
|
|
#endif
|
|
|
|
half3 env1 = Unity_GlossyEnvironment (UNITY_PASS_TEXCUBE_SAMPLER(unity_SpecCube1,unity_SpecCube0), data.probeHDR[1], glossIn);
|
|
specular = lerp(env1, env0, blendLerp);
|
|
}
|
|
else
|
|
{
|
|
specular = env0;
|
|
}
|
|
#else
|
|
specular = env0;
|
|
#endif
|
|
#endif
|
|
|
|
return specular * occlusion;
|
|
}
|
|
|
|
inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half3 normalWorld)
|
|
{
|
|
return UnityGI_Base(data, occlusion, normalWorld);
|
|
}
|
|
|
|
inline UnityGI UnityGlobalIllumination (UnityGIInput data, half occlusion, half3 normalWorld, Unity_GlossyEnvironmentData glossIn)
|
|
{
|
|
UnityGI o_gi = UnityGI_Base(data, occlusion, normalWorld);
|
|
o_gi.indirect.specular = UnityGI_IndirectSpecular(data, occlusion, glossIn);
|
|
return o_gi;
|
|
}
|
|
|
|
#endif |