1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-15 22:49:48 +00:00

Ensure shader requirements are pushed at least once for subgraph

Shaders, if deemed necessary, get attached to the node mentioned by the
top of the requirements stack. Previously an empty stack was incorrectly
assumed to mean no shaders were required, but we found out that was
wrong. We need to put shaders *somewhere*, and the root of the subgraph
we're modifying should be the best place.
This commit is contained in:
AnyOldName3 2023-03-08 00:28:48 +00:00
parent aee1edaf9e
commit ccdb1bf6b7

View File

@ -212,15 +212,17 @@ namespace Shader
void ShaderVisitor::apply(osg::Node& node) void ShaderVisitor::apply(osg::Node& node)
{ {
if (node.getStateSet()) bool needPop = false;
if (node.getStateSet() || mRequirements.empty())
{ {
needPop = true;
pushRequirements(node); pushRequirements(node);
applyStateSet(node.getStateSet(), node); if (node.getStateSet())
traverse(node); applyStateSet(node.getStateSet(), node);
popRequirements();
} }
else traverse(node);
traverse(node); if (needPop)
popRequirements();
} }
osg::StateSet* getWritableStateSet(osg::Node& node) osg::StateSet* getWritableStateSet(osg::Node& node)
@ -865,12 +867,12 @@ namespace Shader
void ShaderVisitor::apply(osg::Geometry& geometry) void ShaderVisitor::apply(osg::Geometry& geometry)
{ {
bool needPop = (geometry.getStateSet() != nullptr); bool needPop = geometry.getStateSet() || mRequirements.empty();
if (geometry.getStateSet()) // TODO: check if stateset affects shader permutation before pushing it if (needPop)
{
pushRequirements(geometry); pushRequirements(geometry);
if (geometry.getStateSet()) // TODO: check if stateset affects shader permutation before pushing it
applyStateSet(geometry.getStateSet(), geometry); applyStateSet(geometry.getStateSet(), geometry);
}
if (!mRequirements.empty()) if (!mRequirements.empty())
{ {
@ -889,7 +891,7 @@ namespace Shader
void ShaderVisitor::apply(osg::Drawable& drawable) void ShaderVisitor::apply(osg::Drawable& drawable)
{ {
bool needPop = drawable.getStateSet(); bool needPop = drawable.getStateSet() || mRequirements.empty();
if (needPop) if (needPop)
{ {
@ -899,36 +901,31 @@ namespace Shader
applyStateSet(drawable.getStateSet(), drawable); applyStateSet(drawable.getStateSet(), drawable);
} }
if (!mRequirements.empty()) const ShaderRequirements& reqs = mRequirements.back();
{ createProgram(reqs);
const ShaderRequirements& reqs = mRequirements.back();
createProgram(reqs);
if (auto rig = dynamic_cast<SceneUtil::RigGeometry*>(&drawable)) if (auto rig = dynamic_cast<SceneUtil::RigGeometry*>(&drawable))
{
osg::ref_ptr<osg::Geometry> sourceGeometry = rig->getSourceGeometry();
if (sourceGeometry && adjustGeometry(*sourceGeometry, reqs))
rig->setSourceGeometry(sourceGeometry);
}
else if (auto morph = dynamic_cast<SceneUtil::MorphGeometry*>(&drawable))
{
osg::ref_ptr<osg::Geometry> sourceGeometry = morph->getSourceGeometry();
if (sourceGeometry && adjustGeometry(*sourceGeometry, reqs))
morph->setSourceGeometry(sourceGeometry);
}
else if (auto osgaRig = dynamic_cast<SceneUtil::RigGeometryHolder*>(&drawable))
{
osg::ref_ptr<SceneUtil::OsgaRigGeometry> sourceOsgaRigGeometry = osgaRig->getSourceRigGeometry();
osg::ref_ptr<osg::Geometry> sourceGeometry = sourceOsgaRigGeometry->getSourceGeometry();
if (sourceGeometry && adjustGeometry(*sourceGeometry, reqs))
{ {
osg::ref_ptr<osg::Geometry> sourceGeometry = rig->getSourceGeometry(); sourceOsgaRigGeometry->setSourceGeometry(sourceGeometry);
if (sourceGeometry && adjustGeometry(*sourceGeometry, reqs)) osgaRig->setSourceRigGeometry(sourceOsgaRigGeometry);
rig->setSourceGeometry(sourceGeometry);
}
else if (auto morph = dynamic_cast<SceneUtil::MorphGeometry*>(&drawable))
{
osg::ref_ptr<osg::Geometry> sourceGeometry = morph->getSourceGeometry();
if (sourceGeometry && adjustGeometry(*sourceGeometry, reqs))
morph->setSourceGeometry(sourceGeometry);
}
else if (auto osgaRig = dynamic_cast<SceneUtil::RigGeometryHolder*>(&drawable))
{
osg::ref_ptr<SceneUtil::OsgaRigGeometry> sourceOsgaRigGeometry = osgaRig->getSourceRigGeometry();
osg::ref_ptr<osg::Geometry> sourceGeometry = sourceOsgaRigGeometry->getSourceGeometry();
if (sourceGeometry && adjustGeometry(*sourceGeometry, reqs))
{
sourceOsgaRigGeometry->setSourceGeometry(sourceGeometry);
osgaRig->setSourceRigGeometry(sourceOsgaRigGeometry);
}
} }
} }
else
ensureFFP(drawable);
if (needPop) if (needPop)
popRequirements(); popRequirements();