You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
7.1 KiB
Plaintext
254 lines
7.1 KiB
Plaintext
//
|
|
// This file is part of Caelum.
|
|
// See http://www.ogre3d.org/wiki/index.php/Caelum
|
|
//
|
|
// Copyright (c) 2008 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 <http://www.gnu.org/licenses/>.
|
|
//
|
|
|
|
#ifdef EXP_GROUND_FOG
|
|
|
|
// Returns (exp(x) - 1) / x; avoiding division by 0.
|
|
// lim when x -> 0 is 1.
|
|
float expdiv(float x) {
|
|
if (abs(x) < 0.0001) {
|
|
return 1;
|
|
} else {
|
|
return (exp(x) - 1) / x;
|
|
}
|
|
}
|
|
|
|
// Return fogging through a layer of fog which drops exponentially by height.
|
|
//
|
|
// Standard exp fog with constant density would return (1 - exp(-density * dist)).
|
|
// This function assumes a variable density vd = exp(-verticalDecay * h - baseLevel)
|
|
// Full computation is exp(density * dist / (h2 - h1) * int(h1, h2, exp(-verticalDecay * (h2 - h1)))).
|
|
//
|
|
// This will gracefully degrade to standard exp fog in verticalDecay is 0; without throwing NaNs.
|
|
float ExpGroundFog (
|
|
float dist, float h1, float h2,
|
|
float density, float verticalDecay, float baseLevel)
|
|
{
|
|
float deltaH = (h2 - h1);
|
|
return 1 - exp (-density * dist * exp(verticalDecay * (baseLevel - h1)) * expdiv(-verticalDecay * deltaH));
|
|
}
|
|
|
|
#endif // EXP_GROUND_FOG
|
|
|
|
#ifdef SKY_DOME_HAZE
|
|
|
|
float bias (float b, float x)
|
|
{
|
|
return pow (x, log (b) / log (0.5));
|
|
}
|
|
|
|
float4 sunlightInscatter
|
|
(
|
|
float4 sunColour,
|
|
float absorption,
|
|
float incidenceAngleCos,
|
|
float sunlightScatteringFactor
|
|
)
|
|
{
|
|
float scatteredSunlight = bias (sunlightScatteringFactor * 0.5, incidenceAngleCos);
|
|
|
|
sunColour = sunColour * (1 - absorption) * float4 (0.9, 0.5, 0.09, 1);
|
|
|
|
return sunColour * scatteredSunlight;
|
|
}
|
|
|
|
float fogExp (float z, float density) {
|
|
return 1 - clamp (pow (2.71828, -z * density), 0, 1);
|
|
}
|
|
|
|
uniform sampler1D atmRelativeDepth : register(HAZE_DEPTH_TEXTURE);
|
|
|
|
float4 CalcHaze
|
|
(
|
|
float3 worldPos,
|
|
float3 worldCamPos,
|
|
float3 hazeColour,
|
|
float3 sunDirection
|
|
)
|
|
{
|
|
float haze = length (worldCamPos - worldPos);
|
|
float incidenceAngleCos = dot (-sunDirection, normalize (worldPos - worldCamPos));
|
|
float y = -sunDirection.y;
|
|
|
|
float4 sunColour = float4 (3, 2.5, 1, 1);
|
|
|
|
// Factor determining the amount of light lost due to absorption
|
|
float atmLightAbsorptionFactor = 0.1;
|
|
float fogDensity = 15;
|
|
|
|
haze = fogExp (haze * 0.005, atmLightAbsorptionFactor);
|
|
|
|
// Haze amount calculation
|
|
float invHazeHeight = 100;
|
|
float hazeAbsorption = fogExp (pow (1 - y, invHazeHeight), fogDensity);
|
|
|
|
if (incidenceAngleCos > 0) {
|
|
// Factor determining the amount of scattering for the sun light
|
|
float sunlightScatteringFactor = 0.1;
|
|
// Factor determining the amount of sun light intensity lost due to scattering
|
|
float sunlightScatteringLossFactor = 0.3;
|
|
|
|
float4 sunlightInscatterColour = sunlightInscatter (
|
|
sunColour,
|
|
clamp ((1 - tex1D (atmRelativeDepth, y).r) * hazeAbsorption, 0, 1),
|
|
clamp (incidenceAngleCos, 0, 1),
|
|
sunlightScatteringFactor) * (1 - sunlightScatteringLossFactor);
|
|
hazeColour =
|
|
hazeColour * (1 - sunlightInscatterColour.a) +
|
|
sunlightInscatterColour.rgb * sunlightInscatterColour.a * haze;
|
|
}
|
|
|
|
return float4(hazeColour.rgb, haze);
|
|
}
|
|
|
|
#endif // SKY_DOME_HAZE
|
|
|
|
void MainFP
|
|
(
|
|
in float2 screenPos : TEXCOORD0,
|
|
|
|
uniform float4x4 invViewProjMatrix,
|
|
uniform float4 worldCameraPos,
|
|
|
|
#if EXP_GROUND_FOG
|
|
uniform float groundFogDensity,
|
|
uniform float groundFogVerticalDecay,
|
|
uniform float groundFogBaseLevel,
|
|
uniform float4 groundFogColour,
|
|
#endif // EXP_GROUND_FOG
|
|
|
|
#if SKY_DOME_HAZE
|
|
uniform float3 hazeColour,
|
|
uniform float3 sunDirection,
|
|
#endif // SKY_DOME_HAZE
|
|
|
|
sampler screenTexture: register(s0),
|
|
sampler depthTexture: register(s1),
|
|
|
|
out float4 outColor : COLOR
|
|
)
|
|
{
|
|
float4 inColor = tex2D(screenTexture, screenPos);
|
|
float inDepth = tex2D(depthTexture, screenPos).r;
|
|
|
|
// Build normalized device coords; after the perspective divide.
|
|
//float4 devicePos = float4(1 - screenPos.x * 2, screenPos.y * 2 - 1, inDepth, 1);
|
|
//float4 devicePos = float4(screenPos.x * 2 - 1, 1 - screenPos.y * 2, 2 * inDepth - 1, 1);
|
|
float4 devicePos = float4(screenPos.x * 2 - 1, 1 - screenPos.y * 2, inDepth, 1);
|
|
|
|
// Go back from device to world coordinates.
|
|
float4 worldPos = mul(invViewProjMatrix, devicePos);
|
|
|
|
// Now undo the perspective divide and go back to "normal" space.
|
|
worldPos /= worldPos.w;
|
|
|
|
float4 color = inColor;
|
|
|
|
#if DEBUG_DEPTH_RENDER
|
|
//color = abs(float4(inDepth, inDepth, inDepth, 1));
|
|
color = worldPos * float4(0.001, 0.01, 0.001, 1);
|
|
#endif // DEBUG_DEPTH_RENDER
|
|
|
|
#if EXP_GROUND_FOG
|
|
// Ye olde ground fog.
|
|
float h1 = worldCameraPos.y;
|
|
float h2 = worldPos.y;
|
|
float dist = length(worldCameraPos - worldPos);
|
|
float fogFactor = ExpGroundFog(
|
|
dist, h1, h2,
|
|
groundFogDensity, groundFogVerticalDecay, groundFogBaseLevel);
|
|
color = lerp(color, groundFogColour, fogFactor);
|
|
#endif // EXP_GROUND_FOG
|
|
|
|
#if SKY_DOME_HAZE
|
|
float4 hazeValue = CalcHaze (
|
|
worldPos.xyz,
|
|
worldCameraPos.xyz,
|
|
hazeColour,
|
|
sunDirection);
|
|
color.rgb = lerp(color.rgb, hazeValue.rgb, hazeValue.a);
|
|
#endif // SKY_DOME_HAZE
|
|
|
|
outColor = color;
|
|
}
|
|
|
|
void DepthRenderVP
|
|
(
|
|
float4 inPos : POSITION,
|
|
|
|
uniform float4x4 wvpMatrix,
|
|
|
|
out float4 magic : TEXCOORD0,
|
|
out float4 outPos : POSITION
|
|
)
|
|
{
|
|
// Standard transform.
|
|
outPos = mul(wvpMatrix, inPos);
|
|
|
|
// Depth buffer is z/w.
|
|
// Let the GPU lerp the components of outPos.
|
|
magic = outPos;
|
|
}
|
|
|
|
void DepthRenderFP
|
|
(
|
|
in float4 magic : TEXCOORD0,
|
|
out float4 output : COLOR
|
|
)
|
|
{
|
|
output = float4(magic.z / magic.w);
|
|
//output = float4(magic.xy / magic.w, 1, 1);
|
|
}
|
|
|
|
void DepthRenderAlphaRejectionVP
|
|
(
|
|
float4 inPos : POSITION,
|
|
float4 inTexcoord : TEXCOORD0,
|
|
|
|
uniform float4x4 wvpMatrix,
|
|
|
|
out float4 outTexcoord : TEXCOORD0,
|
|
out float4 magic : TEXCOORD1,
|
|
out float4 outPos : POSITION
|
|
)
|
|
{
|
|
// Standard transform.
|
|
outPos = mul(wvpMatrix, inPos);
|
|
|
|
// Depth buffer is z/w.
|
|
// Let the GPU lerp the components of outPos.
|
|
magic = outPos;
|
|
|
|
outTexcoord = inTexcoord;
|
|
}
|
|
|
|
void DepthRenderAlphaRejectionFP
|
|
(
|
|
in float4 texcoord : TEXCOORD0,
|
|
in float4 magic : TEXCOORD1,
|
|
sampler mainTex: register(s0),
|
|
out float4 output : COLOR
|
|
)
|
|
{
|
|
float4 texvalue = tex2D(mainTex, texcoord.xy);
|
|
// texvalue.a = sin(100 * texcoord.x) + sin(100 * texcoord.y);
|
|
output = float4(float3(magic.z / magic.w), texvalue.a);
|
|
}
|