diff --git a/CHANGELOG.md b/CHANGELOG.md index bd74e4e1d..1b3a3438a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ Bug #5370: Opening an unlocked but trapped door uses the key Bug #5384: openmw-cs: deleting an instance requires reload of scene window to show in editor Bug #5387: Move/MoveWorld don't update the object's cell properly + Bug #5391: Races Redone 1.2 bodies don't show on the inventory Bug #5397: NPC greeting does not reset if you leave + reenter area Bug #5400: Editor: Verifier checks race of non-skin bodyparts Bug #5403: Enchantment effect doesn't show on an enemy during death animation diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 89db3e5f4..14735050c 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -15,6 +16,8 @@ #include #include +#include +#include #include #include @@ -85,7 +88,7 @@ namespace MWRender class SetUpBlendVisitor : public osg::NodeVisitor { public: - SetUpBlendVisitor(): osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) + SetUpBlendVisitor(): osg::NodeVisitor(TRAVERSE_ALL_CHILDREN), mNoAlphaUniform(new osg::Uniform("noAlpha", false)) { } @@ -102,10 +105,17 @@ namespace MWRender newStateSet->setAttribute(newBlendFunc, osg::StateAttribute::ON); node.setStateSet(newStateSet); } - + if (stateset->getMode(GL_BLEND) & osg::StateAttribute::ON) + { + // Disable noBlendAlphaEnv + stateset->setTextureMode(7, GL_TEXTURE_2D, osg::StateAttribute::OFF); + stateset->addUniform(mNoAlphaUniform); + } } traverse(node); } + private: + osg::ref_ptr mNoAlphaUniform; }; CharacterPreview::CharacterPreview(osg::Group* parent, Resource::ResourceSystem* resourceSystem, @@ -164,6 +174,20 @@ namespace MWRender fog->setEnd(10000000); stateset->setAttributeAndModes(fog, osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE); + // Opaque stuff must have 1 as its fragment alpha as the FBO is translucent, so having blending off isn't enough + osg::ref_ptr noBlendAlphaEnv = new osg::TexEnvCombine(); + noBlendAlphaEnv->setCombine_Alpha(osg::TexEnvCombine::REPLACE); + noBlendAlphaEnv->setSource0_Alpha(osg::TexEnvCombine::CONSTANT); + noBlendAlphaEnv->setConstantColor(osg::Vec4(0.0, 0.0, 0.0, 1.0)); + noBlendAlphaEnv->setCombine_RGB(osg::TexEnvCombine::REPLACE); + noBlendAlphaEnv->setSource0_RGB(osg::TexEnvCombine::PREVIOUS); + osg::ref_ptr dummyTexture = new osg::Texture2D(); + dummyTexture->setInternalFormat(GL_RED); + dummyTexture->setTextureSize(1, 1); + stateset->setTextureAttributeAndModes(7, dummyTexture, osg::StateAttribute::ON); + stateset->setTextureAttribute(7, noBlendAlphaEnv, osg::StateAttribute::ON); + stateset->addUniform(new osg::Uniform("noAlpha", true)); + osg::ref_ptr lightmodel = new osg::LightModel; lightmodel->setAmbientIntensity(osg::Vec4(0.0, 0.0, 0.0, 1.0)); stateset->setAttributeAndModes(lightmodel, osg::StateAttribute::ON); @@ -227,6 +251,7 @@ namespace MWRender void CharacterPreview::setBlendMode() { + mResourceSystem->getSceneManager()->recreateShaders(mNode, "objects", true); SetUpBlendVisitor visitor; mNode->accept(visitor); } diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index e75fa4f74..d937b992b 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -247,9 +247,9 @@ namespace Resource return mForceShaders; } - void SceneManager::recreateShaders(osg::ref_ptr node, const std::string& shaderPrefix) + void SceneManager::recreateShaders(osg::ref_ptr node, const std::string& shaderPrefix, bool translucentFramebuffer) { - osg::ref_ptr shaderVisitor(createShaderVisitor(shaderPrefix)); + osg::ref_ptr shaderVisitor(createShaderVisitor(shaderPrefix, translucentFramebuffer)); shaderVisitor->setAllowedToModifyStateSets(false); node->accept(*shaderVisitor); } @@ -749,7 +749,7 @@ namespace Resource stats->setAttribute(frameNumber, "Node Instance", mInstanceCache->getCacheSize()); } - Shader::ShaderVisitor *SceneManager::createShaderVisitor(const std::string& shaderPrefix) + Shader::ShaderVisitor *SceneManager::createShaderVisitor(const std::string& shaderPrefix, bool translucentFramebuffer) { Shader::ShaderVisitor* shaderVisitor = new Shader::ShaderVisitor(*mShaderManager.get(), *mImageManager, shaderPrefix+"_vertex.glsl", shaderPrefix+"_fragment.glsl"); shaderVisitor->setForceShaders(mForceShaders); @@ -759,6 +759,7 @@ namespace Resource shaderVisitor->setAutoUseSpecularMaps(mAutoUseSpecularMaps); shaderVisitor->setSpecularMapPattern(mSpecularMapPattern); shaderVisitor->setApplyLightingToEnvMaps(mApplyLightingToEnvMaps); + shaderVisitor->setTranslucentFramebuffer(translucentFramebuffer); return shaderVisitor; } diff --git a/components/resource/scenemanager.hpp b/components/resource/scenemanager.hpp index e897566a8..a815a324f 100644 --- a/components/resource/scenemanager.hpp +++ b/components/resource/scenemanager.hpp @@ -76,7 +76,7 @@ namespace Resource Shader::ShaderManager& getShaderManager(); /// Re-create shaders for this node, need to call this if texture stages or vertex color mode have changed. - void recreateShaders(osg::ref_ptr node, const std::string& shaderPrefix = "objects"); + void recreateShaders(osg::ref_ptr node, const std::string& shaderPrefix = "objects", bool translucentFramebuffer = false); /// @see ShaderVisitor::setForceShaders void setForceShaders(bool force); @@ -173,7 +173,7 @@ namespace Resource private: - Shader::ShaderVisitor* createShaderVisitor(const std::string& shaderPrefix = "objects"); + Shader::ShaderVisitor* createShaderVisitor(const std::string& shaderPrefix = "objects", bool translucentFramebuffer = false); std::unique_ptr mShaderManager; bool mForceShaders; diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index e908b6aaa..9dec5522c 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -40,6 +40,7 @@ namespace Shader , mAutoUseNormalMaps(false) , mAutoUseSpecularMaps(false) , mApplyLightingToEnvMaps(false) + , mTranslucentFramebuffer(false) , mShaderManager(shaderManager) , mImageManager(imageManager) , mDefaultVsTemplate(defaultVsTemplate) @@ -146,7 +147,7 @@ namespace Shader mRequirements.back().mShaderRequired = true; } } - else + else if (!mTranslucentFramebuffer) Log(Debug::Error) << "ShaderVisitor encountered unknown texture " << texture; } } @@ -322,6 +323,8 @@ namespace Shader writableStateSet->addUniform(new osg::Uniform("colorMode", reqs.mColorMode)); + defineMap["translucentFramebuffer"] = mTranslucentFramebuffer ? "1" : "0"; + osg::ref_ptr vertexShader (mShaderManager.getShader(mDefaultVsTemplate, defineMap, osg::Shader::VERTEX)); osg::ref_ptr fragmentShader (mShaderManager.getShader(mDefaultFsTemplate, defineMap, osg::Shader::FRAGMENT)); @@ -474,4 +477,9 @@ namespace Shader mApplyLightingToEnvMaps = apply; } + void ShaderVisitor::setTranslucentFramebuffer(bool translucent) + { + mTranslucentFramebuffer = translucent; + } + } diff --git a/components/shader/shadervisitor.hpp b/components/shader/shadervisitor.hpp index 6031dbfe6..11b37c923 100644 --- a/components/shader/shadervisitor.hpp +++ b/components/shader/shadervisitor.hpp @@ -40,6 +40,8 @@ namespace Shader void setApplyLightingToEnvMaps(bool apply); + void setTranslucentFramebuffer(bool translucent); + void apply(osg::Node& node) override; void apply(osg::Drawable& drawable) override; @@ -63,6 +65,8 @@ namespace Shader bool mApplyLightingToEnvMaps; + bool mTranslucentFramebuffer; + ShaderManager& mShaderManager; Resource::ImageManager& mImageManager; diff --git a/files/shaders/objects_fragment.glsl b/files/shaders/objects_fragment.glsl index 78660685f..50bb77145 100644 --- a/files/shaders/objects_fragment.glsl +++ b/files/shaders/objects_fragment.glsl @@ -50,6 +50,7 @@ uniform mat2 bumpMapMatrix; #endif uniform bool simpleWater; +uniform bool noAlpha; varying float euclideanDepth; varying float linearDepth; @@ -208,5 +209,11 @@ void main() #endif gl_FragData[0].xyz = mix(gl_FragData[0].xyz, gl_Fog.color.xyz, fogValue); +#if @translucentFramebuffer + // having testing & blending isn't enough - we need to write an opaque pixel to be opaque + if (noAlpha) + gl_FragData[0].a = 1.0; +#endif + applyShadowDebugOverlay(); }