mirror of
https://github.com/OpenMW/openmw.git
synced 2025-04-13 22:06:44 +00:00
Add optional shadow map max distance and fading
This commit is contained in:
parent
b700c98e8f
commit
b6ed2f1718
9 changed files with 67 additions and 6 deletions
|
@ -843,6 +843,11 @@ void SceneUtil::MWShadowTechnique::setPolygonOffset(float factor, float units)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneUtil::MWShadowTechnique::setShadowFadeStart(float shadowFadeStart)
|
||||||
|
{
|
||||||
|
_shadowFadeStart = shadowFadeStart;
|
||||||
|
}
|
||||||
|
|
||||||
void SceneUtil::MWShadowTechnique::enableFrontFaceCulling()
|
void SceneUtil::MWShadowTechnique::enableFrontFaceCulling()
|
||||||
{
|
{
|
||||||
_useFrontFaceCulling = true;
|
_useFrontFaceCulling = true;
|
||||||
|
@ -1493,6 +1498,9 @@ void MWShadowTechnique::createShaders()
|
||||||
osg::ref_ptr<osg::Uniform> baseTextureUnit = new osg::Uniform("baseTextureUnit",(int)_baseTextureUnit);
|
osg::ref_ptr<osg::Uniform> baseTextureUnit = new osg::Uniform("baseTextureUnit",(int)_baseTextureUnit);
|
||||||
_uniforms.push_back(baseTextureUnit.get());
|
_uniforms.push_back(baseTextureUnit.get());
|
||||||
|
|
||||||
|
_uniforms.push_back(new osg::Uniform("maximumShadowMapDistance", (float)settings->getMaximumShadowMapDistance()));
|
||||||
|
_uniforms.push_back(new osg::Uniform("shadowFadeStart", (float)_shadowFadeStart));
|
||||||
|
|
||||||
for(unsigned int sm_i=0; sm_i<settings->getNumShadowMapsPerLight(); ++sm_i)
|
for(unsigned int sm_i=0; sm_i<settings->getNumShadowMapsPerLight(); ++sm_i)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|
|
@ -76,6 +76,8 @@ namespace SceneUtil {
|
||||||
|
|
||||||
virtual void setPolygonOffset(float factor, float units);
|
virtual void setPolygonOffset(float factor, float units);
|
||||||
|
|
||||||
|
virtual void setShadowFadeStart(float shadowFadeStart);
|
||||||
|
|
||||||
virtual void enableFrontFaceCulling();
|
virtual void enableFrontFaceCulling();
|
||||||
|
|
||||||
virtual void disableFrontFaceCulling();
|
virtual void disableFrontFaceCulling();
|
||||||
|
@ -257,6 +259,8 @@ namespace SceneUtil {
|
||||||
|
|
||||||
bool _useFrontFaceCulling = true;
|
bool _useFrontFaceCulling = true;
|
||||||
|
|
||||||
|
float _shadowFadeStart = 0.0;
|
||||||
|
|
||||||
class DebugHUD : public osg::Referenced
|
class DebugHUD : public osg::Referenced
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -27,6 +27,14 @@ namespace SceneUtil
|
||||||
mShadowSettings->setNumShadowMapsPerLight(numberOfShadowMapsPerLight);
|
mShadowSettings->setNumShadowMapsPerLight(numberOfShadowMapsPerLight);
|
||||||
mShadowSettings->setBaseShadowTextureUnit(8 - numberOfShadowMapsPerLight);
|
mShadowSettings->setBaseShadowTextureUnit(8 - numberOfShadowMapsPerLight);
|
||||||
|
|
||||||
|
const float maximumShadowMapDistance = Settings::Manager::getFloat("maximum shadow map distance", "Shadows");
|
||||||
|
if (maximumShadowMapDistance > 0)
|
||||||
|
{
|
||||||
|
const float shadowFadeStart = std::min(std::max(0.f, Settings::Manager::getFloat("shadow fade start", "Shadows")), 1.f);
|
||||||
|
mShadowSettings->setMaximumShadowMapDistance(maximumShadowMapDistance);
|
||||||
|
mShadowTechnique->setShadowFadeStart(maximumShadowMapDistance * shadowFadeStart);
|
||||||
|
}
|
||||||
|
|
||||||
mShadowSettings->setMinimumShadowMapNearFarRatio(Settings::Manager::getFloat("minimum lispsm near far ratio", "Shadows"));
|
mShadowSettings->setMinimumShadowMapNearFarRatio(Settings::Manager::getFloat("minimum lispsm near far ratio", "Shadows"));
|
||||||
if (Settings::Manager::getBool("compute tight scene bounds", "Shadows"))
|
if (Settings::Manager::getBool("compute tight scene bounds", "Shadows"))
|
||||||
mShadowSettings->setComputeNearFarModeOverride(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
|
mShadowSettings->setComputeNearFarModeOverride(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
|
||||||
|
@ -117,6 +125,8 @@ namespace SceneUtil
|
||||||
|
|
||||||
definesWithShadows["shadowNormalOffset"] = std::to_string(Settings::Manager::getFloat("normal offset distance", "Shadows"));
|
definesWithShadows["shadowNormalOffset"] = std::to_string(Settings::Manager::getFloat("normal offset distance", "Shadows"));
|
||||||
|
|
||||||
|
definesWithShadows["limitShadowMapDistance"] = Settings::Manager::getFloat("maximum shadow map distance", "Shadows") > 0 ? "1" : "0";
|
||||||
|
|
||||||
return definesWithShadows;
|
return definesWithShadows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,6 +148,8 @@ namespace SceneUtil
|
||||||
|
|
||||||
definesWithoutShadows["shadowNormalOffset"] = "0.0";
|
definesWithoutShadows["shadowNormalOffset"] = "0.0";
|
||||||
|
|
||||||
|
definesWithoutShadows["limitShadowMapDistance"] = "0";
|
||||||
|
|
||||||
return definesWithoutShadows;
|
return definesWithoutShadows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ Unlike in the original Morrowind engine, 'Shadow Mapping' is used, which can hav
|
||||||
Bear in mind that this will force OpenMW to use shaders as if :ref:`force shaders` was enabled.
|
Bear in mind that this will force OpenMW to use shaders as if :ref:`force shaders` was enabled.
|
||||||
A keen developer may be able to implement compatibility with fixed-function mode using the advice of `this post <https://github.com/OpenMW/openmw/pull/1547#issuecomment-369657381>`_, but it may be more difficult than it seems.
|
A keen developer may be able to implement compatibility with fixed-function mode using the advice of `this post <https://github.com/OpenMW/openmw/pull/1547#issuecomment-369657381>`_, but it may be more difficult than it seems.
|
||||||
|
|
||||||
|
|
||||||
number of shadow maps
|
number of shadow maps
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
@ -28,6 +27,28 @@ Control how many shadow maps to use - more of these means each shadow map texel
|
||||||
Using too many shadow maps will lead to them overriding texture slots used for other effects, producing unpleasant artefacts.
|
Using too many shadow maps will lead to them overriding texture slots used for other effects, producing unpleasant artefacts.
|
||||||
A value of three is recommended in most cases, but other values may produce better results or performance.
|
A value of three is recommended in most cases, but other values may produce better results or performance.
|
||||||
|
|
||||||
|
maximum shadow map distance
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
:Type: float
|
||||||
|
:Range: The whole range of 32-bit floating point
|
||||||
|
:Default: 8192
|
||||||
|
|
||||||
|
The maximum distance from the camera shadows cover, limiting their overall area coverage
|
||||||
|
and improving their quality and performance at the cost of removing shadows of distant objects or terrain.
|
||||||
|
Set this to a non-positive value to remove the limit.
|
||||||
|
|
||||||
|
shadow fade start
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
:Type: float
|
||||||
|
:Range: 0.0-1.0
|
||||||
|
:Default: 0.9
|
||||||
|
|
||||||
|
The fraction of the maximum shadow map distance at which the shadows will begin to fade away.
|
||||||
|
Tweaking it will make the transition proportionally more or less smooth.
|
||||||
|
This setting has no effect if the maximum shadow map distance is non-positive (infinite).
|
||||||
|
|
||||||
allow shadow map overlap
|
allow shadow map overlap
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
@ -213,4 +234,4 @@ minimum lispsm near far ratio
|
||||||
|
|
||||||
Controls the minimum near/far ratio for the Light Space Perspective Shadow Map transformation.
|
Controls the minimum near/far ratio for the Light Space Perspective Shadow Map transformation.
|
||||||
Helps prevent too much detail being brought towards the camera at the expense of detail further from the camera.
|
Helps prevent too much detail being brought towards the camera at the expense of detail further from the camera.
|
||||||
Increasing this pushes detail further away by moving the frustum apex further from the near plane.
|
Increasing this pushes detail further away by moving the frustum apex further from the near plane.
|
||||||
|
|
|
@ -746,6 +746,12 @@ enable shadows = false
|
||||||
# How many shadow maps to use - more of these means each shadow map texel covers less area, producing better looking shadows, but may decrease performance.
|
# How many shadow maps to use - more of these means each shadow map texel covers less area, producing better looking shadows, but may decrease performance.
|
||||||
number of shadow maps = 3
|
number of shadow maps = 3
|
||||||
|
|
||||||
|
# The distance from the camera at which shadows fade away completely. Set to 0 to make the distance infinite.
|
||||||
|
maximum shadow map distance = 8192
|
||||||
|
|
||||||
|
# Fraction of the maximum distance at which shadows begin to gradually fade away.
|
||||||
|
shadow fade start = 0.9
|
||||||
|
|
||||||
# If true, allow shadow maps to overlap. Counter-intuitively, will produce better results when the light is behind the camera. When enabled, OpenMW uses Cascaded Shadow Maps and when disabled, it uses Parallel Split Shadow Maps.
|
# If true, allow shadow maps to overlap. Counter-intuitively, will produce better results when the light is behind the camera. When enabled, OpenMW uses Cascaded Shadow Maps and when disabled, it uses Parallel Split Shadow Maps.
|
||||||
allow shadow map overlap = true
|
allow shadow map overlap = true
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ void main()
|
||||||
gl_FragData[0].xyz = mix(gl_FragData[0].xyz, decalTex.xyz, decalTex.a);
|
gl_FragData[0].xyz = mix(gl_FragData[0].xyz, decalTex.xyz, decalTex.a);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float shadowing = unshadowedLightRatio();
|
float shadowing = unshadowedLightRatio(depth);
|
||||||
|
|
||||||
#if !PER_PIXEL_LIGHTING
|
#if !PER_PIXEL_LIGHTING
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#define SHADOWS @shadows_enabled
|
#define SHADOWS @shadows_enabled
|
||||||
|
|
||||||
#if SHADOWS
|
#if SHADOWS
|
||||||
|
uniform float maximumShadowMapDistance;
|
||||||
|
uniform float shadowFadeStart;
|
||||||
@foreach shadow_texture_unit_index @shadow_texture_unit_list
|
@foreach shadow_texture_unit_index @shadow_texture_unit_list
|
||||||
uniform sampler2DShadow shadowTexture@shadow_texture_unit_index;
|
uniform sampler2DShadow shadowTexture@shadow_texture_unit_index;
|
||||||
varying vec4 shadowSpaceCoords@shadow_texture_unit_index;
|
varying vec4 shadowSpaceCoords@shadow_texture_unit_index;
|
||||||
|
@ -11,10 +13,15 @@
|
||||||
@endforeach
|
@endforeach
|
||||||
#endif // SHADOWS
|
#endif // SHADOWS
|
||||||
|
|
||||||
float unshadowedLightRatio()
|
float unshadowedLightRatio(float distance)
|
||||||
{
|
{
|
||||||
float shadowing = 1.0;
|
float shadowing = 1.0;
|
||||||
#if SHADOWS
|
#if SHADOWS
|
||||||
|
#if @limitShadowMapDistance
|
||||||
|
float fade = clamp((distance - shadowFadeStart) / (maximumShadowMapDistance - shadowFadeStart), 0.0, 1.0);
|
||||||
|
if (fade == 1.0)
|
||||||
|
return shadowing;
|
||||||
|
#endif
|
||||||
#if @shadowMapsOverlap
|
#if @shadowMapsOverlap
|
||||||
bool doneShadows = false;
|
bool doneShadows = false;
|
||||||
@foreach shadow_texture_unit_index @shadow_texture_unit_list
|
@foreach shadow_texture_unit_index @shadow_texture_unit_list
|
||||||
|
@ -41,6 +48,9 @@ float unshadowedLightRatio()
|
||||||
shadowing = min(shadow2DProj(shadowTexture@shadow_texture_unit_index, shadowSpaceCoords@shadow_texture_unit_index).r, shadowing);
|
shadowing = min(shadow2DProj(shadowTexture@shadow_texture_unit_index, shadowSpaceCoords@shadow_texture_unit_index).r, shadowing);
|
||||||
@endforeach
|
@endforeach
|
||||||
#endif
|
#endif
|
||||||
|
#if @limitShadowMapDistance
|
||||||
|
shadowing = mix(shadowing, 1.0, fade);
|
||||||
|
#endif
|
||||||
#endif // SHADOWS
|
#endif // SHADOWS
|
||||||
return shadowing;
|
return shadowing;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ void main()
|
||||||
gl_FragData[0].a *= texture2D(blendMap, blendMapUV).a;
|
gl_FragData[0].a *= texture2D(blendMap, blendMapUV).a;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float shadowing = unshadowedLightRatio();
|
float shadowing = unshadowedLightRatio(depth);
|
||||||
|
|
||||||
#if !PER_PIXEL_LIGHTING
|
#if !PER_PIXEL_LIGHTING
|
||||||
|
|
||||||
|
|
|
@ -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();
|
float shadow = unshadowedLightRatio(depthPassthrough);
|
||||||
|
|
||||||
vec2 screenCoords = screenCoordsPassthrough.xy / screenCoordsPassthrough.z;
|
vec2 screenCoords = screenCoordsPassthrough.xy / screenCoordsPassthrough.z;
|
||||||
screenCoords.y = (1.0-screenCoords.y);
|
screenCoords.y = (1.0-screenCoords.y);
|
||||||
|
|
Loading…
Reference in a new issue