From 5d1c941f67a67adef29437d78240ecb9a8cb476e Mon Sep 17 00:00:00 2001 From: tibor Date: Fri, 1 Aug 2014 11:20:14 +0200 Subject: [PATCH] Support fading into fog (all Unity fog modes supported, using shader keywords to optimize shader runtime) Added 'Draw distance' parameter to stop the effect from rendering after a certain distance from the camera. Hardcoded fade out at the final 10% of the range for now. --- FinalInterpolation.shader | 24 +++++++++++++++++++++++- LightShafts.Resources.cs | 2 ++ LightShafts.cs | 27 +++++++++++++++++++++++---- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/FinalInterpolation.shader b/FinalInterpolation.shader index c2dc7a6..c44617d 100644 --- a/FinalInterpolation.shader +++ b/FinalInterpolation.shader @@ -19,6 +19,7 @@ CGPROGRAM #pragma multi_compile QUAD_SHAFTS FRUSTUM_SHAFTS #pragma multi_compile DIRECTIONAL_SHAFTS SPOT_SHAFTS #pragma multi_compile FLIP_WORKAROUND_OFF FLIP_WORKAROUND_ON +#pragma multi_compile LS_FOG_OFF LS_FOG_LINEAR LS_FOG_EXP LS_FOG_EXP2 #include "UnityCG.cginc" #include "Shared.cginc" @@ -38,6 +39,10 @@ float4 _ScreenTexDim; float _DepthThreshold; float _ShowSamplesBackgroundFade; +half4 unity_FogDensity; +half4 unity_FogEnd; +half4 unity_FogStart; + inline void FixFlip(inout float x) { // Flip upside-down on DX-like platforms, if the buffer @@ -187,7 +192,19 @@ float4 frag(v2f i) : COLOR half depth = UNITY_SAMPLE_DEPTH(tex2D (_CameraDepthTexture, uv)); depth = Linear01Depth(depth); - + + // Fog fadeout based on sample depth + float dephtInWorldUnits = depth * _ProjectionParams.z; // _ProjectionParams.z = camera far plane + #if defined(LS_FOG_LINEAR) + half fogAmount = saturate((unity_FogEnd.x - dephtInWorldUnits) / (unity_FogEnd.x - unity_FogStart.x)); + #elif defined(LS_FOG_EXP) + half fogAmount = dephtInWorldUnits * unity_FogDensity; + fogAmount = saturate(1 / exp(fogAmount)); + #elif defined(LS_FOG_EXP2) + half fogAmount = dephtInWorldUnits * unity_FogDensity; + fogAmount = saturate(1 / exp(fogAmount*fogAmount)); + #endif + float near, far, rayLength; float3 rayN; IntersectVolume(uv, near, far, rayN, rayLength); @@ -203,6 +220,11 @@ float4 frag(v2f i) : COLOR float4 c = step(near/rayLength, depth); c *= SampleLighting(unwrapped, depth).xyzz; #endif + + // Fade out with fog after + #if defined(LS_FOG_LINEAR) || defined(LS_FOG_EXP) || defined(LS_FOG_EXP2) + c.xyz *= fogAmount; + #endif #if defined(SHOW_SAMPLES_ON) float4 sample = tex2D(_SamplePositions, uv); diff --git a/LightShafts.Resources.cs b/LightShafts.Resources.cs index 4596313..00943bb 100644 --- a/LightShafts.Resources.cs +++ b/LightShafts.Resources.cs @@ -68,6 +68,8 @@ public partial class LightShafts : MonoBehaviour LightType m_LightType = LightType.Directional; bool m_DX11Support = false; bool m_MinRequirements = false; + + public float m_DrawDistance = 100.0f; void InitLUTs () { diff --git a/LightShafts.cs b/LightShafts.cs index b3d37ce..fbb24a4 100644 --- a/LightShafts.cs +++ b/LightShafts.cs @@ -163,7 +163,7 @@ void ShowSamples(int width, int height, Vector4 lightPos) m_FinalInterpolationMaterial.SetFloat("_ShowSamplesBackgroundFade", m_ShowSamplesBackgroundFade); } - void Raymarch(int width, int height, Vector4 lightPos) + void Raymarch(int width, int height, Vector4 lightPos, float fade) { SetFrustumRays(m_RaymarchMaterial); @@ -177,7 +177,7 @@ void Raymarch(int width, int height, Vector4 lightPos) m_RaymarchMaterial.SetTexture("_Shadowmap", m_Shadowmap); float brightness = m_Colored ? m_BrightnessColored/m_ColorBalance : m_Brightness; brightness *= light.intensity; - m_RaymarchMaterial.SetFloat("_Brightness", brightness); + m_RaymarchMaterial.SetFloat("_Brightness", brightness*fade); m_RaymarchMaterial.SetFloat("_Extinction", -m_Extinction); m_RaymarchMaterial.SetVector("_ShadowmapDim", new Vector4(shadowmapWidth, shadowmapHeight, 1.0f / shadowmapWidth, 1.0f / shadowmapHeight)); m_RaymarchMaterial.SetVector("_ScreenTexDim", new Vector4(width, height, 1.0f / width, 1.0f / height)); @@ -218,6 +218,12 @@ public void OnRenderObject () m_CurrentCamera = Camera.current; if (!m_MinRequirements || !CheckCamera() || !IsVisible()) return; + + // Distance based cutoff (fade out @ last 10%) + // NOTE: Fade is passed into Raymarch to fade out the result in the shader + float fade = Mathf.Clamp01((1.0f - (Vector3.Distance(transform.position,m_CurrentCamera.transform.position) / m_DrawDistance))*10.0f); + if( fade <= 0.0f ) + return; // Prepare RenderBuffer depthBuffer = Graphics.activeDepthBuffer; @@ -234,12 +240,25 @@ public void OnRenderObject () SetKeyword(directional, "DIRECTIONAL_SHAFTS", "SPOT_SHAFTS"); RenderCoords(width, height, lightPos); RenderInterpolationTexture(lightPos); - Raymarch(width, height, lightPos); + Raymarch(width, height, lightPos, fade); InterpolateAlongRays(lightPos); ShowSamples(width, height, lightPos); - // Final interpolation and blending onto the screen + // Fill fog shader keywords + Shader.DisableKeyword("LS_FOG_LINEAR"); + Shader.DisableKeyword("LS_FOG_EXP"); + Shader.DisableKeyword("LS_FOG_EXP2"); + if( RenderSettings.fog ) + { + switch( RenderSettings.fogMode ) { + case FogMode.Linear: Shader.EnableKeyword("LS_FOG_LINEAR"); break; + case FogMode.Exponential: Shader.EnableKeyword("LS_FOG_EXP"); break; + case FogMode.ExponentialSquared: Shader.EnableKeyword("LS_FOG_EXP2"); break; + }; + } + + // Final interpolation and blending onto the screen FlipWorkaround(); SetFrustumRays(m_FinalInterpolationMaterial); m_FinalInterpolationMaterial.SetTexture("_InterpolationEpi", m_InterpolationEpi);