/* This file is part of Caelum. See http://www.ogre3d.org/wiki/index.php/Caelum Copyright (c) 2006-2007 Caelum team. See Contributors.txt for details. Caelum is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Caelum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with Caelum. If not, see . */ // Return fogging through a layer of fog which drops exponentially by height. // Foginess at a certain point is exp(-verticalDecay * (h - fogLevel)); // A fogLevel from the ground fogginess is 1. float ExpGroundFog (float invSinView, float h1, float h2, float density, float verticalDecay, float fogLevel) { // Integrate fog on a vertical line from h1 to h2. float vFog = (-1 / verticalDecay) * (exp (-verticalDecay * (h2 - fogLevel)) - exp (-verticalDecay * (h1 - fogLevel))); return 1 - exp (-density * invSinView * vFog); } // Just like ExpGroundFog with infinite h2 float ExpGroundFogInf (float invSinView, float h1, float density, float verticalDecay, float fogLevel) { // Integrate fog on a vertical line from h1 to h2. float vFog = exp (-verticalDecay * (h1 - fogLevel)) / verticalDecay; return 1 - exp (-density * invSinView * vFog); } // Entry point for GroundFog vertex program. void GroundFog_vp ( float4 position : POSITION, out float4 oPosition : POSITION, out float4 worldPos : TEXCOORD0, uniform float4x4 worldViewProj, uniform float4x4 world ) { oPosition = mul(worldViewProj, position); worldPos = mul(world, position); } // Entry point for GroundFog fragment program. void GroundFog_fp ( float3 worldPos : TEXCOORD0, uniform float3 camPos, uniform float4 fogColour, uniform float fogDensity, uniform float fogVerticalDecay, uniform float fogGroundLevel, out float4 oCol : COLOR ) { float h1 = camPos.y; float h2 = worldPos.y; float invSinView = length(camPos - worldPos) / (h2 - h1); float fog = ExpGroundFog(invSinView, h1, h2, fogDensity, fogVerticalDecay, fogGroundLevel); oCol.rgb = fogColour.rgb; oCol.a = fog; } // Entry point for GroundFogDome vertex program. void GroundFogDome_vp ( in float4 position : POSITION, out float4 oPosition : POSITION, out float3 relPosition : TEXCOORD0, uniform float4x4 worldViewProj ) { oPosition = mul(worldViewProj, position); relPosition = normalize(position); } // Entry point for the GroundFogDome fragment program. void GroundFogDome_fp ( in float3 relPosition : TEXCOORD0, uniform float cameraHeight, uniform float4 fogColour, uniform float fogDensity, uniform float fogVerticalDecay, uniform float fogGroundLevel, out float4 oCol : COLOR ) { // Fog magic. float invSinView = 1 / (relPosition.y); float h1 = cameraHeight; float aFog; if (invSinView < 0) { // Gazing into the abyss aFog = 1; } else { aFog = saturate (ExpGroundFogInf ( invSinView, h1, fogDensity, fogVerticalDecay, fogGroundLevel)); } oCol.a = aFog; oCol.rgb = fogColour.rgb; }