1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-03 15:39:41 +00:00

use StateSet define for translucentFramebuffer (#3138)

With this PR we test out osg's shader define system for a somewhat harmless feature. As we can see, our code becomes more concise and efficient in this case. Most importantly, we no longer create unneeded vertex shader objects.
This commit is contained in:
Bo Svensson 2021-10-05 12:37:08 +00:00 committed by GitHub
parent b2af81bc18
commit 4b1c009ffd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 20 additions and 40 deletions

View file

@ -91,7 +91,7 @@ namespace MWRender
class SetUpBlendVisitor : public osg::NodeVisitor
{
public:
SetUpBlendVisitor(): osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), mNoAlphaUniform(new osg::Uniform("noAlpha", false))
SetUpBlendVisitor(): osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
{
}
@ -130,7 +130,7 @@ namespace MWRender
}
// Disable noBlendAlphaEnv
newStateSet->setTextureMode(7, GL_TEXTURE_2D, osg::StateAttribute::OFF);
newStateSet->addUniform(mNoAlphaUniform);
newStateSet->setDefine("FORCE_OPAQUE", "0", osg::StateAttribute::ON);
}
if (SceneUtil::getReverseZ() && stateset->getAttribute(osg::StateAttribute::DEPTH))
{
@ -172,8 +172,6 @@ namespace MWRender
}
traverse(node);
}
private:
osg::ref_ptr<osg::Uniform> mNoAlphaUniform;
};
CharacterPreview::CharacterPreview(osg::Group* parent, Resource::ResourceSystem* resourceSystem,
@ -216,6 +214,7 @@ namespace MWRender
osg::ref_ptr<SceneUtil::LightManager> lightManager = new SceneUtil::LightManager(ffp);
lightManager->setStartLight(1);
osg::ref_ptr<osg::StateSet> stateset = lightManager->getOrCreateStateSet();
stateset->setDefine("FORCE_OPAQUE", "1", osg::StateAttribute::ON);
stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON);
stateset->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
@ -253,7 +252,6 @@ namespace MWRender
dummyTexture->setShadowCompareFunc(osg::Texture::ShadowCompareFunc::ALWAYS);
stateset->setTextureAttributeAndModes(7, dummyTexture, osg::StateAttribute::ON);
stateset->setTextureAttribute(7, noBlendAlphaEnv, osg::StateAttribute::ON);
stateset->addUniform(new osg::Uniform("noAlpha", true));
osg::ref_ptr<osg::LightModel> lightmodel = new osg::LightModel;
lightmodel->setAmbientIntensity(osg::Vec4(0.0, 0.0, 0.0, 1.0));
@ -328,7 +326,6 @@ namespace MWRender
void CharacterPreview::setBlendMode()
{
mResourceSystem->getSceneManager()->recreateShaders(mNode, "objects", true);
SetUpBlendVisitor visitor;
mNode->accept(visitor);
}

View file

@ -224,7 +224,7 @@ namespace MWRender
group->setNodeMask(Mask_Groundcover);
if (mSceneManager->getLightingMethod() != SceneUtil::LightingMethod::FFP)
group->setCullCallback(new SceneUtil::LightListCallback);
mSceneManager->recreateShaders(group, "groundcover", false, true, mProgramTemplate);
mSceneManager->recreateShaders(group, "groundcover", true, mProgramTemplate);
mSceneManager->shareState(group);
group->getBound();
return group;

View file

@ -331,9 +331,9 @@ namespace Resource
return mForceShaders;
}
void SceneManager::recreateShaders(osg::ref_ptr<osg::Node> node, const std::string& shaderPrefix, bool translucentFramebuffer, bool forceShadersForNode, const osg::Program* programTemplate)
void SceneManager::recreateShaders(osg::ref_ptr<osg::Node> node, const std::string& shaderPrefix, bool forceShadersForNode, const osg::Program* programTemplate)
{
osg::ref_ptr<Shader::ShaderVisitor> shaderVisitor(createShaderVisitor(shaderPrefix, translucentFramebuffer));
osg::ref_ptr<Shader::ShaderVisitor> shaderVisitor(createShaderVisitor(shaderPrefix));
shaderVisitor->setAllowedToModifyStateSets(false);
shaderVisitor->setProgramTemplate(programTemplate);
if (forceShadersForNode)
@ -871,7 +871,7 @@ namespace Resource
stats->setAttribute(frameNumber, "Node", mCache->getCacheSize());
}
Shader::ShaderVisitor *SceneManager::createShaderVisitor(const std::string& shaderPrefix, bool translucentFramebuffer)
Shader::ShaderVisitor *SceneManager::createShaderVisitor(const std::string& shaderPrefix)
{
Shader::ShaderVisitor* shaderVisitor = new Shader::ShaderVisitor(*mShaderManager.get(), *mImageManager, shaderPrefix);
shaderVisitor->setForceShaders(mForceShaders);
@ -882,7 +882,6 @@ namespace Resource
shaderVisitor->setSpecularMapPattern(mSpecularMapPattern);
shaderVisitor->setApplyLightingToEnvMaps(mApplyLightingToEnvMaps);
shaderVisitor->setConvertAlphaTestToAlphaToCoverage(mConvertAlphaTestToAlphaToCoverage);
shaderVisitor->setTranslucentFramebuffer(translucentFramebuffer);
return shaderVisitor;
}
}

View file

@ -76,7 +76,7 @@ namespace Resource
Shader::ShaderManager& getShaderManager();
/// Re-create shaders for this node, need to call this if alpha testing, texture stages or vertex color mode have changed.
void recreateShaders(osg::ref_ptr<osg::Node> node, const std::string& shaderPrefix = "objects", bool translucentFramebuffer = false, bool forceShadersForNode = false, const osg::Program* programTemplate = nullptr);
void recreateShaders(osg::ref_ptr<osg::Node> node, const std::string& shaderPrefix = "objects", bool forceShadersForNode = false, const osg::Program* programTemplate = nullptr);
/// Applying shaders to a node may replace some fixed-function state.
/// This restores it.
@ -188,7 +188,7 @@ namespace Resource
private:
Shader::ShaderVisitor* createShaderVisitor(const std::string& shaderPrefix = "objects", bool translucentFramebuffer = false);
Shader::ShaderVisitor* createShaderVisitor(const std::string& shaderPrefix = "objects");
std::unique_ptr<Shader::ShaderManager> mShaderManager;
bool mForceShaders;

View file

@ -111,7 +111,6 @@ namespace Shader
, mAutoUseSpecularMaps(false)
, mApplyLightingToEnvMaps(false)
, mConvertAlphaTestToAlphaToCoverage(false)
, mTranslucentFramebuffer(false)
, mShaderManager(shaderManager)
, mImageManager(imageManager)
, mDefaultShaderPrefix(defaultShaderPrefix)
@ -266,7 +265,7 @@ namespace Shader
mRequirements.back().mShaderRequired = true;
}
}
else if (!mTranslucentFramebuffer)
else
Log(Debug::Error) << "ShaderVisitor encountered unknown texture " << texture;
}
}
@ -547,8 +546,6 @@ namespace Shader
updateAddedState(*writableUserData, addedState);
}
defineMap["translucentFramebuffer"] = mTranslucentFramebuffer ? "1" : "0";
std::string shaderPrefix;
if (!node.getUserValue("shaderPrefix", shaderPrefix))
shaderPrefix = mDefaultShaderPrefix;
@ -764,11 +761,6 @@ namespace Shader
mConvertAlphaTestToAlphaToCoverage = convert;
}
void ShaderVisitor::setTranslucentFramebuffer(bool translucent)
{
mTranslucentFramebuffer = translucent;
}
ReinstateRemovedStateVisitor::ReinstateRemovedStateVisitor(bool allowedToModifyStateSets)
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
, mAllowedToModifyStateSets(allowedToModifyStateSets)

View file

@ -45,8 +45,6 @@ namespace Shader
void setConvertAlphaTestToAlphaToCoverage(bool convert);
void setTranslucentFramebuffer(bool translucent);
void apply(osg::Node& node) override;
void apply(osg::Drawable& drawable) override;
@ -72,8 +70,6 @@ namespace Shader
bool mConvertAlphaTestToAlphaToCoverage;
bool mTranslucentFramebuffer;
ShaderManager& mShaderManager;
Resource::ImageManager& mImageManager;

View file

@ -1,4 +1,5 @@
#version 120
#pragma import_defines(FORCE_OPAQUE)
#if @useUBO
#extension GL_ARB_uniform_buffer_object : require
@ -24,8 +25,6 @@ varying vec2 normalMapUV;
varying vec4 passTangent;
#endif
uniform bool noAlpha;
varying float euclideanDepth;
varying float linearDepth;
@ -95,9 +94,9 @@ void main()
#endif
gl_FragData[0].xyz = mix(gl_FragData[0].xyz, gl_Fog.color.xyz, fogValue);
#if @translucentFramebuffer
if (noAlpha)
gl_FragData[0].a = 1.0;
#if FORCE_OPAQUE
// having testing & blending isn't enough - we need to write an opaque pixel to be opaque
gl_FragData[0].a = 1.0;
#endif
applyShadowDebugOverlay();

View file

@ -1,4 +1,5 @@
#version 120
#pragma import_defines(FORCE_OPAQUE)
#if @useGPUShader4
#extension GL_EXT_gpu_shader4: require
@ -9,8 +10,6 @@ uniform sampler2D diffuseMap;
varying vec2 diffuseMapUV;
#endif
uniform bool noAlpha;
#if @radialFog
varying float euclideanDepth;
#else
@ -46,9 +45,8 @@ void main()
float fogValue = clamp((linearDepth - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0);
#endif
#if @translucentFramebuffer
if (noAlpha)
gl_FragData[0].a = 1.0;
#if FORCE_OPAQUE
gl_FragData[0].a = 1.0;
#endif
gl_FragData[0].xyz = mix(gl_FragData[0].xyz, gl_Fog.color.xyz, fogValue);

View file

@ -1,4 +1,5 @@
#version 120
#pragma import_defines(FORCE_OPAQUE)
#if @useUBO
#extension GL_ARB_uniform_buffer_object : require
@ -58,7 +59,6 @@ uniform mat2 bumpMapMatrix;
#endif
uniform bool simpleWater;
uniform bool noAlpha;
varying float euclideanDepth;
varying float linearDepth;
@ -220,10 +220,9 @@ void main()
#endif
gl_FragData[0].xyz = mix(gl_FragData[0].xyz, gl_Fog.color.xyz, fogValue);
#if @translucentFramebuffer
#if FORCE_OPAQUE
// having testing & blending isn't enough - we need to write an opaque pixel to be opaque
if (noAlpha)
gl_FragData[0].a = 1.0;
gl_FragData[0].a = 1.0;
#endif
applyShadowDebugOverlay();