Merge pull request #2721 from akortunov/radial_fog

Support for radial fog
pull/2725/head
Alexei Dobrohotov 5 years ago committed by GitHub
commit e80fbf4786
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -225,6 +225,7 @@
Feature #4544: Actors movement deceleration Feature #4544: Actors movement deceleration
Feature #4673: Weapon sheathing Feature #4673: Weapon sheathing
Feature #4675: Support for NiRollController Feature #4675: Support for NiRollController
Feature #4708: Radial fog support
Feature #4730: Native animated containers support Feature #4730: Native animated containers support
Feature #4784: Launcher: Duplicate Content Lists Feature #4784: Launcher: Duplicate Content Lists
Feature #4812: Support NiSwitchNode 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["forcePPL"] = "0"; // Don't force per-pixel lighting
defines["clamp"] = "1"; // Clamp lighting defines["clamp"] = "1"; // Clamp lighting
defines["preLightEnv"] = "0"; // Apply environment maps after lighting like Morrowind defines["preLightEnv"] = "0"; // Apply environment maps after lighting like Morrowind
defines["radialFog"] = "0";
for (const auto& define : shadowDefines) for (const auto& define : shadowDefines)
defines[define.first] = define.second; defines[define.first] = define.second;
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(defines); mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(defines);

@ -218,7 +218,9 @@ namespace MWRender
{ {
resourceSystem->getSceneManager()->setParticleSystemMask(SceneUtil::Mask_ParticleSystem); resourceSystem->getSceneManager()->setParticleSystemMask(SceneUtil::Mask_ParticleSystem);
resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders"); 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 // FIXME: calling dummy method because terrain needs to know whether lighting is clamped
resourceSystem->getSceneManager()->setClampLighting(Settings::Manager::getBool("clamp lighting", "Shaders")); resourceSystem->getSceneManager()->setClampLighting(Settings::Manager::getBool("clamp lighting", "Shaders"));
resourceSystem->getSceneManager()->setAutoUseNormalMaps(Settings::Manager::getBool("auto use object normal maps", "Shaders")); resourceSystem->getSceneManager()->setAutoUseNormalMaps(Settings::Manager::getBool("auto use object normal maps", "Shaders"));
@ -255,6 +257,7 @@ namespace MWRender
globalDefines["forcePPL"] = Settings::Manager::getBool("force per pixel lighting", "Shaders") ? "1" : "0"; globalDefines["forcePPL"] = Settings::Manager::getBool("force per pixel lighting", "Shaders") ? "1" : "0";
globalDefines["clamp"] = Settings::Manager::getBool("clamp 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["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. // It is unnecessary to stop/start the viewer as no frames are being rendered yet.
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(globalDefines); 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. 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. 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. 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. # Affected objects use shaders.
apply lighting to environment maps = false 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] [Input]
# Capture control of the cursor prevent movement outside the window. # Capture control of the cursor prevent movement outside the window.

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

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

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

@ -1,7 +1,8 @@
#version 120 #version 120
varying vec2 uv; varying vec2 uv;
varying float depth; varying float euclideanDepth;
varying float linearDepth;
#define PER_PIXEL_LIGHTING (@normalMap || @forcePPL) #define PER_PIXEL_LIGHTING (@normalMap || @forcePPL)
@ -21,10 +22,11 @@ varying vec3 passNormal;
void main(void) void main(void)
{ {
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
depth = gl_Position.z;
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex); vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
gl_ClipVertex = viewPos; gl_ClipVertex = viewPos;
euclideanDepth = length(viewPos.xyz);
linearDepth = gl_Position.z;
vec3 viewNormal = normalize((gl_NormalMatrix * gl_Normal).xyz); 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 vec3 screenCoordsPassthrough;
varying vec4 position; varying vec4 position;
varying float depthPassthrough; varying float linearDepth;
uniform sampler2D normalMap; uniform sampler2D normalMap;
@ -160,7 +160,7 @@ void main(void)
vec2 UV = worldPos.xy / (8192.0*5.0) * 3.0; vec2 UV = worldPos.xy / (8192.0*5.0) * 3.0;
UV.y *= -1.0; UV.y *= -1.0;
float shadow = unshadowedLightRatio(depthPassthrough); float shadow = unshadowedLightRatio(linearDepth);
vec2 screenCoords = screenCoordsPassthrough.xy / screenCoordsPassthrough.z; vec2 screenCoords = screenCoordsPassthrough.xy / screenCoordsPassthrough.z;
screenCoords.y = (1.0-screenCoords.y); 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 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); 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; vec2 screenCoordsOffset = normal.xy * REFL_BUMP;
#if REFRACTION #if REFRACTION
float depthSample = linearizeDepth(texture2D(refractionDepthMap,screenCoords).x); float depthSample = linearizeDepth(texture2D(refractionDepthMap,screenCoords).x) * radialize;
float depthSampleDistorted = linearizeDepth(texture2D(refractionDepthMap,screenCoords-screenCoordsOffset).x); float depthSampleDistorted = linearizeDepth(texture2D(refractionDepthMap,screenCoords-screenCoordsOffset).x) * radialize;
float surfaceDepth = linearizeDepth(gl_FragCoord.z); float surfaceDepth = linearizeDepth(gl_FragCoord.z) * radialize;
float realWaterDepth = depthSample - surfaceDepth; // undistorted water depth in view direction, independent of frustum float realWaterDepth = depthSample - surfaceDepth; // undistorted water depth in view direction, independent of frustum
screenCoordsOffset *= clamp(realWaterDepth / BUMP_SUPPRESS_DEPTH,0,1); screenCoordsOffset *= clamp(realWaterDepth / BUMP_SUPPRESS_DEPTH,0,1);
#endif #endif
@ -246,7 +252,11 @@ void main(void)
#endif #endif
// fog // 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); gl_FragData[0].xyz = mix(gl_FragData[0].xyz, gl_Fog.color.xyz, fogValue);
applyShadowDebugOverlay(); applyShadowDebugOverlay();

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

Loading…
Cancel
Save