Support for radial fog (feature #4708)

pull/2721/head
Andrei Kortunov 4 years ago
parent f603daecdc
commit 02444add2a

@ -225,6 +225,7 @@
Feature #4544: Actors movement deceleration
Feature #4673: Weapon sheathing
Feature #4675: Support for NiRollController
Feature #4708: Radial fog support
Feature #4730: Native animated containers support
Feature #4784: Launcher: Duplicate Content Lists
Feature #4812: Support NiSwitchNode

@ -82,6 +82,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat
defines["forcePPL"] = "0"; // Don't force per-pixel lighting
defines["clamp"] = "1"; // Clamp lighting
defines["preLightEnv"] = "0"; // Apply environment maps after lighting like Morrowind
defines["radialFog"] = "0";
for (const auto& define : shadowDefines)
defines[define.first] = define.second;
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(defines);

@ -217,7 +217,9 @@ namespace MWRender
{
resourceSystem->getSceneManager()->setParticleSystemMask(SceneUtil::Mask_ParticleSystem);
resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders");
resourceSystem->getSceneManager()->setForceShaders(Settings::Manager::getBool("force shaders", "Shaders") || Settings::Manager::getBool("enable shadows", "Shadows")); // Shadows have problems with fixed-function mode
// Shadows and radial fog have problems with fixed-function mode
bool forceShaders = Settings::Manager::getBool("radial fog", "Shaders") || Settings::Manager::getBool("force shaders", "Shaders") || Settings::Manager::getBool("enable shadows", "Shadows");
resourceSystem->getSceneManager()->setForceShaders(forceShaders);
// FIXME: calling dummy method because terrain needs to know whether lighting is clamped
resourceSystem->getSceneManager()->setClampLighting(Settings::Manager::getBool("clamp lighting", "Shaders"));
resourceSystem->getSceneManager()->setAutoUseNormalMaps(Settings::Manager::getBool("auto use object normal maps", "Shaders"));
@ -254,6 +256,7 @@ namespace MWRender
globalDefines["forcePPL"] = Settings::Manager::getBool("force per pixel lighting", "Shaders") ? "1" : "0";
globalDefines["clamp"] = Settings::Manager::getBool("clamp lighting", "Shaders") ? "1" : "0";
globalDefines["preLightEnv"] = Settings::Manager::getBool("apply lighting to environment maps", "Shaders") ? "1" : "0";
globalDefines["radialFog"] = Settings::Manager::getBool("radial fog", "Shaders") ? "1" : "0";
// It is unnecessary to stop/start the viewer as no frames are being rendered yet.
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(globalDefines);

@ -135,3 +135,14 @@ apply lighting to environment maps
Normally environment map reflections aren't affected by lighting, which makes environment-mapped (and thus bump-mapped objects) glow in the dark.
Morrowind Code Patch includes an option to remedy that by doing environment-mapping before applying lighting, this is the equivalent of that option.
Affected objects will use shaders.
radial fog
----------
:Type: boolean
:Range: True/False
:Default: False
By default, the fog becomes thicker proportionally to your distance from the clipping plane set at the clipping distance, which causes distortion at the edges of the screen.
This setting makes the fog use the actual eye point distance (or so called Euclidean distance) to calculate the fog, which makes the fog look less artificial, especially if you have a wide FOV.
Note that the rendering will act as if you have 'force shaders' option enabled with this on, which means that shaders will be used to render all objects and the terrain.

@ -350,6 +350,10 @@ terrain specular map pattern = _diffusespec
# Affected objects use shaders.
apply lighting to environment maps = false
# Determine fog intensity based on the distance from the eye point.
# This makes fogging independent from the viewing angle. Shaders will be used to render all objects.
radial fog = false
[Input]
# Capture control of the cursor prevent movement outside the window.

@ -49,7 +49,8 @@ uniform vec2 envMapLumaBias;
uniform mat2 bumpMapMatrix;
#endif
varying float depth;
varying float euclideanDepth;
varying float linearDepth;
#define PER_PIXEL_LIGHTING (@normalMap || @forcePPL)
@ -146,7 +147,7 @@ void main()
#endif
float shadowing = unshadowedLightRatio(depth);
float shadowing = unshadowedLightRatio(linearDepth);
#if !PER_PIXEL_LIGHTING
@ -178,8 +179,11 @@ void main()
#endif
gl_FragData[0].xyz += getSpecular(normalize(viewNormal), normalize(passViewPos.xyz), shininess, matSpec) * shadowing;
float fogValue = clamp((depth - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0);
#if @radialFog
float fogValue = clamp((euclideanDepth - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0);
#else
float fogValue = clamp((linearDepth - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0);
#endif
gl_FragData[0].xyz = mix(gl_FragData[0].xyz, gl_Fog.color.xyz, fogValue);
applyShadowDebugOverlay();

@ -37,7 +37,8 @@ varying vec2 bumpMapUV;
varying vec2 specularMapUV;
#endif
varying float depth;
varying float euclideanDepth;
varying float linearDepth;
#define PER_PIXEL_LIGHTING (@normalMap || @forcePPL)
@ -57,10 +58,12 @@ varying vec3 passNormal;
void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
depth = gl_Position.z;
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
gl_ClipVertex = viewPos;
euclideanDepth = length(viewPos.xyz);
linearDepth = gl_Position.z;
vec3 viewNormal = normalize((gl_NormalMatrix * gl_Normal).xyz);
#if @envMap

@ -12,7 +12,8 @@ uniform sampler2D normalMap;
uniform sampler2D blendMap;
#endif
varying float depth;
varying float euclideanDepth;
varying float linearDepth;
#define PER_PIXEL_LIGHTING (@normalMap || @forcePPL)
@ -66,7 +67,7 @@ void main()
gl_FragData[0].a *= texture2D(blendMap, blendMapUV).a;
#endif
float shadowing = unshadowedLightRatio(depth);
float shadowing = unshadowedLightRatio(linearDepth);
#if !PER_PIXEL_LIGHTING
@ -90,7 +91,11 @@ void main()
gl_FragData[0].xyz += getSpecular(normalize(viewNormal), normalize(passViewPos), shininess, matSpec) * shadowing;
float fogValue = clamp((depth - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0);
#if @radialFog
float fogValue = clamp((euclideanDepth - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0);
#else
float fogValue = clamp((linearDepth - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0);
#endif
gl_FragData[0].xyz = mix(gl_FragData[0].xyz, gl_Fog.color.xyz, fogValue);
applyShadowDebugOverlay();

@ -1,7 +1,8 @@
#version 120
varying vec2 uv;
varying float depth;
varying float euclideanDepth;
varying float linearDepth;
#define PER_PIXEL_LIGHTING (@normalMap || @forcePPL)
@ -21,10 +22,11 @@ varying vec3 passNormal;
void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
depth = gl_Position.z;
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
gl_ClipVertex = viewPos;
euclideanDepth = length(viewPos.xyz);
linearDepth = gl_Position.z;
vec3 viewNormal = normalize((gl_NormalMatrix * gl_Normal).xyz);

@ -124,7 +124,7 @@ vec2 normalCoords(vec2 uv, float scale, float speed, float time, float timer1, f
varying vec3 screenCoordsPassthrough;
varying vec4 position;
varying float depthPassthrough;
varying float linearDepth;
uniform sampler2D normalMap;
@ -160,7 +160,7 @@ void main(void)
vec2 UV = worldPos.xy / (8192.0*5.0) * 3.0;
UV.y *= -1.0;
float shadow = unshadowedLightRatio(depthPassthrough);
float shadow = unshadowedLightRatio(linearDepth);
vec2 screenCoords = screenCoordsPassthrough.xy / screenCoordsPassthrough.z;
screenCoords.y = (1.0-screenCoords.y);
@ -203,11 +203,17 @@ void main(void)
float ior = (cameraPos.z>0.0)?(1.333/1.0):(1.0/1.333); // air to water; water to air
float fresnel = clamp(fresnel_dielectric(vVec, normal, ior), 0.0, 1.0);
#if @radialFog
float radialDepth = distance(position.xyz, cameraPos);
float radialize = radialDepth / linearDepth;
#else
float radialize = 1.0;
#endif
vec2 screenCoordsOffset = normal.xy * REFL_BUMP;
#if REFRACTION
float depthSample = linearizeDepth(texture2D(refractionDepthMap,screenCoords).x);
float depthSampleDistorted = linearizeDepth(texture2D(refractionDepthMap,screenCoords-screenCoordsOffset).x);
float surfaceDepth = linearizeDepth(gl_FragCoord.z);
float depthSample = linearizeDepth(texture2D(refractionDepthMap,screenCoords).x) * radialize;
float depthSampleDistorted = linearizeDepth(texture2D(refractionDepthMap,screenCoords-screenCoordsOffset).x) * radialize;
float surfaceDepth = linearizeDepth(gl_FragCoord.z) * radialize;
float realWaterDepth = depthSample - surfaceDepth; // undistorted water depth in view direction, independent of frustum
screenCoordsOffset *= clamp(realWaterDepth / BUMP_SUPPRESS_DEPTH,0,1);
#endif
@ -246,7 +252,11 @@ void main(void)
#endif
// fog
float fogValue = clamp((depthPassthrough - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0);
#if @radialFog
float fogValue = clamp((radialDepth - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0);
#else
float fogValue = clamp((linearDepth - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0);
#endif
gl_FragData[0].xyz = mix(gl_FragData[0].xyz, gl_Fog.color.xyz, fogValue);
applyShadowDebugOverlay();

@ -2,7 +2,7 @@
varying vec3 screenCoordsPassthrough;
varying vec4 position;
varying float depthPassthrough;
varying float linearDepth;
#include "shadows_vertex.glsl"
@ -20,7 +20,7 @@ void main(void)
position = gl_Vertex;
depthPassthrough = gl_Position.z;
linearDepth = gl_Position.z;
setupShadowCoords(gl_ModelViewMatrix * gl_Vertex, normalize((gl_NormalMatrix * gl_Normal).xyz));
}

Loading…
Cancel
Save