diff --git a/apps/openmw_test_suite/fx/technique.cpp b/apps/openmw_test_suite/fx/technique.cpp index 3273d69eb2..8277b80ae0 100644 --- a/apps/openmw_test_suite/fx/technique.cpp +++ b/apps/openmw_test_suite/fx/technique.cpp @@ -105,6 +105,7 @@ TestingOpenMW::VFSTestFile repeated_shared_block{R"( , mImageManager(mVFS.get()) { Settings::Manager::setBool("radial fog", "Fog", true); + Settings::Manager::setBool("exponential fog", "Fog", false); Settings::Manager::setBool("stereo enabled", "Stereo", false); } @@ -201,4 +202,4 @@ TestingOpenMW::VFSTestFile repeated_shared_block{R"( Log(Debug::Error) << output; EXPECT_THAT(output, HasSubstr("repeated 'shared' block")); } -} \ No newline at end of file +} diff --git a/components/fx/pass.cpp b/components/fx/pass.cpp index b32dd2e0b1..27d6f6ef0a 100644 --- a/components/fx/pass.cpp +++ b/components/fx/pass.cpp @@ -71,6 +71,7 @@ namespace fx #define OMW_REVERSE_Z @reverseZ #define OMW_RADIAL_FOG @radialFog +#define OMW_EXPONENTIAL_FOG @exponentialFog #define OMW_HDR @hdr #define OMW_NORMALS @normals #define OMW_USE_BINDINGS @useBindings @@ -190,6 +191,49 @@ mat4 omw_InvProjectionMatrix() #endif } + vec3 omw_GetWorldPosFromUV(vec2 uv) + { + float depth = omw_GetDepth(uv); +#if (OMW_REVERSE_Z == 1) + float flippedDepth = 1.0 - depth; +#else + float flippedDepth = omw_Texture2D(omw_SamplerDepth, uv).r * 2.0 - 1.0; +#endif + vec4 clip_space = vec4(uv * 2.0 - 1.0, flippedDepth, 1.0); + vec4 world_space = omw.invViewMatrix * (omw.invProjectionMatrix * clip_space); + return world_space.xyz / world_space.w; + } + + float omw_GetLinearDepth(vec2 uv) + { +#if (OMW_REVERSE_Z == 1) + float depth = omw_GetDepth(uv); + float dist = omw.near * omw.far / (omw.far + depth * (omw.near - omw.far)); +#else + float depth = omw_GetDepth(uv) * 2.0 - 1.0; + float dist = 2.0 * omw.near * omw.far / (omw.far + omw.near - depth * (omw.far - omw.near)); +#endif + + return dist; + } + +float omw_EstimateFogCoverageFromUV(vec2 uv) + { +#if OMW_RADIAL_FOG + vec3 uvPos = omw_GetWorldPosFromUV(uv); + float dist = length(uvPos - omw.eyePos.xyz); +#else + float dist = omw_GetLinearDepth(uv); +#endif +#if OMW_EXPONENTIAL_FOG + float fogValue = 1.0 - exp(-2.0 * max(0.0, dist - omw.fogNear/2.0) / (omw.fogFar - omw.fogNear/2.0)); +#else + float fogValue = clamp((dist - omw.fogNear) / (omw.fogFar - omw.fogNear), 0.0, 1.0); +#endif + + return fogValue; + } + #if OMW_HDR uniform sampler2D omw_EyeAdaptation; #endif @@ -220,6 +264,7 @@ mat4 omw_InvProjectionMatrix() {"@normals", technique.getNormals() ? "1" : "0"}, {"@reverseZ", SceneUtil::AutoDepth::isReversed() ? "1" : "0"}, {"@radialFog", Settings::Manager::getBool("radial fog", "Fog") ? "1" : "0"}, + {"@exponentialFog", Settings::Manager::getBool("exponential fog", "Fog") ? "1" : "0"}, {"@hdr", technique.getHDR() ? "1" : "0"}, {"@in", mLegacyGLSL ? "varying" : "in"}, {"@out", mLegacyGLSL ? "varying" : "out"}, diff --git a/docs/source/reference/postprocessing/omwfx.rst b/docs/source/reference/postprocessing/omwfx.rst index 4168399daa..04b6735d2f 100644 --- a/docs/source/reference/postprocessing/omwfx.rst +++ b/docs/source/reference/postprocessing/omwfx.rst @@ -120,39 +120,45 @@ Builtin Uniforms Builtin Macros ############## -+------------------+----------------+---------------------------------------------------------------------------+ -| Macro | Definition | Description | -+==================+================+===========================================================================+ -|``OMW_REVERSE_Z`` | ``0`` or ``1`` | Whether a reversed depth buffer is in use. | -| | | | -| | | ``0`` Depth sampler will be in range [1, 0] | -| | | | -| | | ``1`` Depth sampler will be in range [0, 1] | -+------------------+----------------+---------------------------------------------------------------------------+ -|``OMW_RADIAL_FOG``| ``0`` or ``1`` | Whether radial fog is in use. | -| | | | -| | | ``0`` Fog is linear | -| | | | -| | | ``1`` Fog is radial | -+------------------+----------------+---------------------------------------------------------------------------+ -| ``OMW_HDR`` | ``0`` or ``1`` | Whether average scene luminance is computed every frame. | -| | | | -| | | ``0`` Average scene luminance is not computed | -| | | | -| | | ``1`` Average scene luminance is computed | -+------------------+----------------+---------------------------------------------------------------------------+ -| ``OMW_NORMALS`` | ``0`` or ``1`` | Whether normals are available as a sampler in the technique. | -| | | | -| | | ``0`` Normals are not available | -| | | | -| | | ``1`` Normals are available. | -+------------------+----------------+---------------------------------------------------------------------------+ -| ``OMW_MULTIVIEW``| ``0`` or ``1`` | Whether multiview rendering is in use. | -| | | | -| | | ``0`` Multiview not in use | -| | | | -| | | ``1`` Multiview in use. | -+------------------+----------------+---------------------------------------------------------------------------+ ++-----------------------+----------------+----------------------------------------------------------------------+ +| Macro | Definition | Description | ++=======================+================+======================================================================+ +|``OMW_REVERSE_Z`` | ``0`` or ``1`` | Whether a reversed depth buffer is in use. | +| | | | +| | | ``0`` Depth sampler will be in range [1, 0] | +| | | | +| | | ``1`` Depth sampler will be in range [0, 1] | ++-----------------------+----------------+----------------------------------------------------------------------+ +|``OMW_RADIAL_FOG`` | ``0`` or ``1`` | Whether radial fog is in use. | +| | | | +| | | ``0`` Fog is linear | +| | | | +| | | ``1`` Fog is radial | ++-----------------------+----------------+----------------------------------------------------------------------+ +|``OMW_EXPONENTIAL_FOG``| ``0`` or ``1`` | Whether exponential fog is in use. | +| | | | +| | | ``0`` Fog is linear | +| | | | +| | | ``1`` Fog is exponential | ++-----------------------+----------------+----------------------------------------------------------------------+ +| ``OMW_HDR`` | ``0`` or ``1`` | Whether average scene luminance is computed every frame. | +| | | | +| | | ``0`` Average scene luminance is not computed | +| | | | +| | | ``1`` Average scene luminance is computed | ++-----------------------+----------------+----------------------------------------------------------------------+ +| ``OMW_NORMALS`` | ``0`` or ``1`` | Whether normals are available as a sampler in the technique. | +| | | | +| | | ``0`` Normals are not available | +| | | | +| | | ``1`` Normals are available. | ++-----------------------+----------------+----------------------------------------------------------------------+ +| ``OMW_MULTIVIEW`` | ``0`` or ``1`` | Whether multiview rendering is in use. | +| | | | +| | | ``0`` Multiview not in use | +| | | | +| | | ``1`` Multiview in use. | ++-----------------------+----------------+----------------------------------------------------------------------+ Builtin Functions @@ -160,27 +166,35 @@ Builtin Functions The following functions can be accessed in any fragment or vertex shader. -+----------------------------------------+-------------------------------------------------------------------------------+ -| Function | Description | -+========================================+===============================================================================+ -| ``float omw_GetDepth(vec2)`` | Returns the depth value from a sampler given a uv coordinate. | -| | | -| | Reverses sampled value when ``OMW_REVERSE_Z`` is set. | -+----------------------------------------+-------------------------------------------------------------------------------+ -| ``float omw_GetEyeAdaptation()`` | Returns the average scene luminance in range [0, 1]. | -| | | -| | If HDR is not in use, this returns `1.0` | -| | | -| | Scene luminance is always calculated on original scene texture. | -+----------------------------------------+-------------------------------------------------------------------------------+ -| ``vec4 omw_GetLastShader(vec2 uv)`` | Returns RGBA color output of the last shader | -+----------------------------------------+-------------------------------------------------------------------------------+ -| ``vec4 omw_GetLastPass(vec2 uv)`` | Returns RGBA color output of the last pass | -+----------------------------------------+-------------------------------------------------------------------------------+ -| ``vec3 omw_GetNormals(vec2 uv)`` | Returns normalized worldspace normals [-1, 1] | -| | | -| | The values in sampler are in [0, 1] but are transformed to [-1, 1] | -+----------------------------------------+-----------------------+-------------------------------------------------------+ ++--------------------------------------------------+-------------------------------------------------------------------------------+ +| Function | Description | ++==================================================+===============================================================================+ +| ``float omw_GetDepth(vec2)`` | Returns the depth value from a sampler given a uv coordinate. | +| | | +| | Reverses sampled value when ``OMW_REVERSE_Z`` is set. | ++--------------------------------------------------+-------------------------------------------------------------------------------+ +| ``float omw_GetEyeAdaptation()`` | Returns the average scene luminance in range [0, 1]. | +| | | +| | If HDR is not in use, this returns `1.0` | +| | | +| | Scene luminance is always calculated on original scene texture. | ++--------------------------------------------------+-------------------------------------------------------------------------------+ +| ``vec4 omw_GetLastShader(vec2 uv)`` | Returns RGBA color output of the last shader | ++--------------------------------------------------+-------------------------------------------------------------------------------+ +| ``vec4 omw_GetLastPass(vec2 uv)`` | Returns RGBA color output of the last pass | ++--------------------------------------------------+-------------------------------------------------------------------------------+ +| ``vec3 omw_GetNormals(vec2 uv)`` | Returns normalized worldspace normals [-1, 1] | +| | | +| | The values in sampler are in [0, 1] but are transformed to [-1, 1] | ++--------------------------------------------------+-----------------------+-------------------------------------------------------+ +| ``vec3 omw_GetWorldPosFromUV(vec2 uv)`` | Returns world position for given uv coordinate. | ++--------------------------------------------------+-----------------------+-------------------------------------------------------+ +| ``float omw_GetLinearDepth(vec2 uv)`` | Returns the depth in game units for given uv coordinate. | ++--------------------------------------------------+-----------------------+-------------------------------------------------------+ +| ``float omw_EstimateFogCoverageFromUV(vec2 uv)`` | Returns a fog coverage in the range from 0.0 (no fog) and 1.0 (full fog) | +| | | +| | Calculates an estimated fog coverage for given uv coordinate. | ++--------------------------------------------------+-----------------------+-------------------------------------------------------+ Special Attributes diff --git a/files/data/shaders/displaydepth.omwfx b/files/data/shaders/displaydepth.omwfx index 3ea1b4c54d..b20b5208e7 100644 --- a/files/data/shaders/displaydepth.omwfx +++ b/files/data/shaders/displaydepth.omwfx @@ -13,10 +13,7 @@ fragment main { void main() { - float depth = omw_GetDepth(omw_TexCoord); - float zNear = omw.near; - float zFar = omw.far; - omw_FragColor = vec4(vec3((2.0 * zNear) / (zFar + zNear - depth * (zFar - zNear))) * uFactor, 1.0); + omw_FragColor = vec4(vec3(omw_GetLinearDepth(omw_TexCoord) / omw.far * uFactor), 1.0); } }