mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-30 21:45:33 +00:00
Switch shadow map rendering to a specialised, simplified shader.
This commit is contained in:
parent
ce15369bbd
commit
474770eca8
10 changed files with 81 additions and 3 deletions
|
@ -239,7 +239,7 @@ namespace MWRender
|
||||||
if (Settings::Manager::getBool("object shadows", "Shadows"))
|
if (Settings::Manager::getBool("object shadows", "Shadows"))
|
||||||
shadowCastingTraversalMask |= Mask_Object;
|
shadowCastingTraversalMask |= Mask_Object;
|
||||||
|
|
||||||
mShadowManager.reset(new SceneUtil::ShadowManager(sceneRoot, mRootNode, shadowCastingTraversalMask, indoorShadowCastingTraversalMask));
|
mShadowManager.reset(new SceneUtil::ShadowManager(sceneRoot, mRootNode, shadowCastingTraversalMask, indoorShadowCastingTraversalMask, mResourceSystem->getSceneManager()->getShaderManager()));
|
||||||
|
|
||||||
Shader::ShaderManager::DefineMap shadowDefines = mShadowManager->getShadowDefines();
|
Shader::ShaderManager::DefineMap shadowDefines = mShadowManager->getShadowDefines();
|
||||||
Shader::ShaderManager::DefineMap globalDefines = mResourceSystem->getSceneManager()->getShaderManager().getGlobalDefines();
|
Shader::ShaderManager::DefineMap globalDefines = mResourceSystem->getSceneManager()->getShaderManager().getGlobalDefines();
|
||||||
|
|
|
@ -1249,6 +1249,7 @@ namespace NifOsg
|
||||||
boundTextures.clear();
|
boundTextures.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this loop is changed such that the base texture isn't guaranteed to end up in texture unit 0, the shadow casting shader will need to be updated accordingly.
|
||||||
for (int i=0; i<Nif::NiTexturingProperty::NumTextures; ++i)
|
for (int i=0; i<Nif::NiTexturingProperty::NumTextures; ++i)
|
||||||
{
|
{
|
||||||
if (texprop->textures[i].inUse)
|
if (texprop->textures[i].inUse)
|
||||||
|
|
|
@ -820,6 +820,16 @@ void SceneUtil::MWShadowTechnique::setSplitPointDeltaBias(double bias)
|
||||||
_splitPointDeltaBias = bias;
|
_splitPointDeltaBias = bias;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneUtil::MWShadowTechnique::setupCastingShader(Shader::ShaderManager & shaderManager)
|
||||||
|
{
|
||||||
|
// This can't be part of the constructor as OSG mandates that there be a trivial constructor available
|
||||||
|
|
||||||
|
_castingProgram = new osg::Program();
|
||||||
|
|
||||||
|
_castingProgram->addShader(shaderManager.getShader("shadowcasting_vertex.glsl", Shader::ShaderManager::DefineMap(), osg::Shader::VERTEX));
|
||||||
|
_castingProgram->addShader(shaderManager.getShader("shadowcasting_fragment.glsl", Shader::ShaderManager::DefineMap(), osg::Shader::FRAGMENT));
|
||||||
|
}
|
||||||
|
|
||||||
MWShadowTechnique::ViewDependentData* MWShadowTechnique::createViewDependentData(osgUtil::CullVisitor* /*cv*/)
|
MWShadowTechnique::ViewDependentData* MWShadowTechnique::createViewDependentData(osgUtil::CullVisitor* /*cv*/)
|
||||||
{
|
{
|
||||||
return new ViewDependentData(this);
|
return new ViewDependentData(this);
|
||||||
|
@ -1480,6 +1490,14 @@ void MWShadowTechnique::createShaders()
|
||||||
_fallbackShadowMapTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
|
_fallbackShadowMapTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!_castingProgram)
|
||||||
|
OSG_NOTICE << "Shadow casting shader has not been set up. Remember to call setupCastingShader(Shader::ShaderManager &)" << std::endl;
|
||||||
|
|
||||||
|
_shadowCastingStateSet->setAttributeAndModes(_castingProgram, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||||
|
// The casting program uses a sampler, so to avoid undefined behaviour, we must bind a dummy texture in case no other is supplied
|
||||||
|
_shadowCastingStateSet->setTextureAttributeAndModes(0, _fallbackBaseTexture.get(), osg::StateAttribute::ON);
|
||||||
|
_shadowCastingStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Polytope MWShadowTechnique::computeLightViewFrustumPolytope(Frustum& frustum, LightData& positionedLight)
|
osg::Polytope MWShadowTechnique::computeLightViewFrustumPolytope(Frustum& frustum, LightData& positionedLight)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include <osgShadow/ShadowTechnique>
|
#include <osgShadow/ShadowTechnique>
|
||||||
|
|
||||||
|
#include <components/shader/shadermanager.hpp>
|
||||||
#include <components/terrain/quadtreeworld.hpp>
|
#include <components/terrain/quadtreeworld.hpp>
|
||||||
|
|
||||||
namespace SceneUtil {
|
namespace SceneUtil {
|
||||||
|
@ -73,6 +74,8 @@ namespace SceneUtil {
|
||||||
|
|
||||||
virtual void setSplitPointDeltaBias(double bias);
|
virtual void setSplitPointDeltaBias(double bias);
|
||||||
|
|
||||||
|
virtual void setupCastingShader(Shader::ShaderManager &shaderManager);
|
||||||
|
|
||||||
class ComputeLightSpaceBounds : public osg::NodeVisitor, public osg::CullStack
|
class ComputeLightSpaceBounds : public osg::NodeVisitor, public osg::CullStack
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -265,6 +268,7 @@ namespace SceneUtil {
|
||||||
};
|
};
|
||||||
|
|
||||||
osg::ref_ptr<DebugHUD> _debugHud;
|
osg::ref_ptr<DebugHUD> _debugHud;
|
||||||
|
osg::ref_ptr<osg::Program> _castingProgram;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace SceneUtil
|
||||||
stateset->setTextureAttributeAndModes(i, fakeShadowMapTexture, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED);
|
stateset->setTextureAttributeAndModes(i, fakeShadowMapTexture, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
ShadowManager::ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask) : mShadowedScene(new osgShadow::ShadowedScene),
|
ShadowManager::ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, Shader::ShaderManager &shaderManager) : mShadowedScene(new osgShadow::ShadowedScene),
|
||||||
mShadowTechnique(new MWShadowTechnique),
|
mShadowTechnique(new MWShadowTechnique),
|
||||||
mOutdoorShadowCastingMask(outdoorShadowCastingMask),
|
mOutdoorShadowCastingMask(outdoorShadowCastingMask),
|
||||||
mIndoorShadowCastingMask(indoorShadowCastingMask)
|
mIndoorShadowCastingMask(indoorShadowCastingMask)
|
||||||
|
@ -81,6 +81,8 @@ namespace SceneUtil
|
||||||
mShadowSettings = mShadowedScene->getShadowSettings();
|
mShadowSettings = mShadowedScene->getShadowSettings();
|
||||||
setupShadowSettings();
|
setupShadowSettings();
|
||||||
|
|
||||||
|
mShadowTechnique->setupCastingShader(shaderManager);
|
||||||
|
|
||||||
enableOutdoorMode();
|
enableOutdoorMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace SceneUtil
|
||||||
public:
|
public:
|
||||||
static void disableShadowsForStateSet(osg::ref_ptr<osg::StateSet> stateSet);
|
static void disableShadowsForStateSet(osg::ref_ptr<osg::StateSet> stateSet);
|
||||||
|
|
||||||
ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask);
|
ShadowManager(osg::ref_ptr<osg::Group> sceneRoot, osg::ref_ptr<osg::Group> rootNode, unsigned int outdoorShadowCastingMask, unsigned int indoorShadowCastingMask, Shader::ShaderManager &shaderManager);
|
||||||
|
|
||||||
virtual ~ShadowManager() = default;
|
virtual ~ShadowManager() = default;
|
||||||
|
|
||||||
|
|
|
@ -215,6 +215,13 @@ namespace Shader
|
||||||
mRequirements.back().mShaderRequired = true;
|
mRequirements.back().mShaderRequired = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (diffuseMap)
|
||||||
|
{
|
||||||
|
if (!writableStateSet)
|
||||||
|
writableStateSet = getWritableStateSet(node);
|
||||||
|
writableStateSet->addUniform(new osg::Uniform("useDiffuseMapForShadowAlpha", true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const osg::StateSet::AttributeList& attributes = stateset->getAttributeList();
|
const osg::StateSet::AttributeList& attributes = stateset->getAttributeList();
|
||||||
|
|
|
@ -20,6 +20,8 @@ set(SHADER_FILES
|
||||||
s360_vertex.glsl
|
s360_vertex.glsl
|
||||||
shadows_vertex.glsl
|
shadows_vertex.glsl
|
||||||
shadows_fragment.glsl
|
shadows_fragment.glsl
|
||||||
|
shadowcasting_vertex.glsl
|
||||||
|
shadowcasting_fragment.glsl
|
||||||
)
|
)
|
||||||
|
|
||||||
copy_all_resource_files(${CMAKE_CURRENT_SOURCE_DIR} ${OPENMW_SHADERS_ROOT} ${DDIRRELATIVE} "${SHADER_FILES}")
|
copy_all_resource_files(${CMAKE_CURRENT_SOURCE_DIR} ${OPENMW_SHADERS_ROOT} ${DDIRRELATIVE} "${SHADER_FILES}")
|
||||||
|
|
17
files/shaders/shadowcasting_fragment.glsl
Normal file
17
files/shaders/shadowcasting_fragment.glsl
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
uniform sampler2D diffuseMap;
|
||||||
|
varying vec2 diffuseMapUV;
|
||||||
|
|
||||||
|
varying float alphaPassthrough;
|
||||||
|
|
||||||
|
uniform bool useDiffuseMapForShadowAlpha;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_FragData[0].rgb = vec3(1.0);
|
||||||
|
if (useDiffuseMapForShadowAlpha)
|
||||||
|
gl_FragData[0].a = texture2D(diffuseMap, diffuseMapUV).a * alphaPassthrough;
|
||||||
|
else
|
||||||
|
gl_FragData[0].a = alphaPassthrough;
|
||||||
|
}
|
27
files/shaders/shadowcasting_vertex.glsl
Normal file
27
files/shaders/shadowcasting_vertex.glsl
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#version 120
|
||||||
|
|
||||||
|
varying vec2 diffuseMapUV;
|
||||||
|
|
||||||
|
varying float alphaPassthrough;
|
||||||
|
|
||||||
|
uniform int colorMode;
|
||||||
|
uniform bool useDiffuseMapForShadowAlpha;
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||||
|
|
||||||
|
vec4 viewPos = (gl_ModelViewMatrix * gl_Vertex);
|
||||||
|
gl_ClipVertex = viewPos;
|
||||||
|
|
||||||
|
if (useDiffuseMapForShadowAlpha)
|
||||||
|
diffuseMapUV = (gl_TextureMatrix[0] * gl_MultiTexCoord0).xy;
|
||||||
|
else
|
||||||
|
diffuseMapUV = vec2(0.0); // Avoid undefined behaviour if running on hardware predating the concept of dynamically uniform expressions
|
||||||
|
|
||||||
|
if (colorMode == 2)
|
||||||
|
alphaPassthrough = gl_Color.a;
|
||||||
|
else
|
||||||
|
// This is uniform, so if it's too low, we might be able to put the position/clip vertex outside the view frustum and skip the fragment shader and rasteriser
|
||||||
|
alphaPassthrough = gl_FrontMaterial.diffuse.a;
|
||||||
|
}
|
Loading…
Reference in a new issue