diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 7a37a69a3d..c850c1ad8a 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -232,6 +232,7 @@ namespace camera->setReferenceFrame(osg::Camera::RELATIVE_RF); camera->setName("SkyCamera"); camera->setNodeMask(MWRender::Mask_RenderToTexture); + camera->setCullMask(MWRender::Mask_Sky); camera->addChild(mEarlyRenderBinRoot); SceneUtil::ShadowManager::disableShadowsForStateSet(camera->getOrCreateStateSet()); } @@ -283,25 +284,26 @@ namespace MWRender if (!mSceneManager->getForceShaders()) skyroot->getOrCreateStateSet()->setAttributeAndModes(new osg::Program(), osg::StateAttribute::OVERRIDE|osg::StateAttribute::PROTECTED|osg::StateAttribute::ON); SceneUtil::ShadowManager::disableShadowsForStateSet(skyroot->getOrCreateStateSet()); - - skyroot->setNodeMask(Mask_Sky); parentNode->addChild(skyroot); - mRootNode = skyroot; - mEarlyRenderBinRoot = new osg::Group; // render before the world is rendered mEarlyRenderBinRoot->getOrCreateStateSet()->setRenderBinDetails(RenderBin_Sky, "RenderBin"); // Prevent unwanted clipping by water reflection camera's clipping plane mEarlyRenderBinRoot->getOrCreateStateSet()->setMode(GL_CLIP_PLANE0, osg::StateAttribute::OFF); - mRootNode->addChild(mEarlyRenderBinRoot); if (enableSkyRTT) { mSkyRTT = new SkyRTT(Settings::Manager::getVector2("sky rtt resolution", "Fog"), mEarlyRenderBinRoot); - mRootNode->addChild(mSkyRTT); + skyroot->addChild(mSkyRTT); + mRootNode = new osg::Group; + skyroot->addChild(mRootNode); } + else + mRootNode = skyroot; + mRootNode->setNodeMask(Mask_Sky); + mRootNode->addChild(mEarlyRenderBinRoot); mUnderwaterSwitch = new UnderwaterSwitchCallback(skyroot); } diff --git a/components/shader/shadervisitor.cpp b/components/shader/shadervisitor.cpp index b1b657daa1..9896879fec 100644 --- a/components/shader/shadervisitor.cpp +++ b/components/shader/shadervisitor.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -195,6 +196,8 @@ namespace Shader , mAlphaFunc(GL_ALWAYS) , mAlphaRef(1.0) , mAlphaBlend(false) + , mBlendFuncOverridden(false) + , mAdditiveBlending(false) , mNormalHeight(false) , mTexStageRequiringTangents(-1) , mSoftParticles(false) @@ -517,6 +520,18 @@ namespace Shader mRequirements.back().mAlphaRef = alpha->getReferenceValue(); } } + else if (it->first.first == osg::StateAttribute::BLENDFUNC) + { + if (!mRequirements.back().mBlendFuncOverridden || it->second.second & osg::StateAttribute::PROTECTED) + { + if (it->second.second & osg::StateAttribute::OVERRIDE) + mRequirements.back().mBlendFuncOverridden = true; + + const osg::BlendFunc* blend = static_cast(it->second.first.get()); + mRequirements.back().mAdditiveBlending = + blend->getSource() == osg::BlendFunc::SRC_ALPHA && blend->getDestination() == osg::BlendFunc::ONE; + } + } } } @@ -604,6 +619,8 @@ namespace Shader defineMap["alphaFunc"] = std::to_string(reqs.mAlphaFunc); + defineMap["additiveBlending"] = reqs.mAdditiveBlending ? "1" : "0"; + osg::ref_ptr removedState; if ((removedState = getRemovedState(*writableStateSet)) && !mAllowedToModifyStateSets) removedState = new osg::StateSet(*removedState, osg::CopyOp::SHALLOW_COPY); diff --git a/components/shader/shadervisitor.hpp b/components/shader/shadervisitor.hpp index 3ddcd9815f..68deef6586 100644 --- a/components/shader/shadervisitor.hpp +++ b/components/shader/shadervisitor.hpp @@ -102,6 +102,9 @@ namespace Shader float mAlphaRef; bool mAlphaBlend; + bool mBlendFuncOverridden; + bool mAdditiveBlending; + bool mNormalHeight; // true if normal map has height info in alpha channel // -1 == no tangents required diff --git a/files/shaders/fog.glsl b/files/shaders/fog.glsl index d327d6a345..7a56179399 100644 --- a/files/shaders/fog.glsl +++ b/files/shaders/fog.glsl @@ -17,12 +17,21 @@ vec4 applyFogAtDist(vec4 color, float euclideanDist, float linearDist) #else float fogValue = clamp((dist - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0); #endif +#ifdef ADDITIVE_BLENDING + color.xyz *= 1 - fogValue; +#else color.xyz = mix(color.xyz, gl_Fog.color.xyz, fogValue); +#endif #if @skyBlending && !@useOVR_multiview float fadeValue = clamp((far - dist) / (far - skyBlendingStart), 0.0, 1.0); + fadeValue *= fadeValue; +#ifdef ADDITIVE_BLENDING + color.xyz *= fadeValue; +#else vec3 skyColor = texture2D(sky, gl_FragCoord.xy / screenRes).xyz; - color.xyz = mix(skyColor, color.xyz, fadeValue * fadeValue); + color.xyz = mix(skyColor, color.xyz, fadeValue); +#endif #endif return color; diff --git a/files/shaders/objects_fragment.glsl b/files/shaders/objects_fragment.glsl index 6ebc7cbd62..613785fdd8 100644 --- a/files/shaders/objects_fragment.glsl +++ b/files/shaders/objects_fragment.glsl @@ -77,6 +77,10 @@ uniform float specStrength; varying vec3 passViewPos; varying vec3 passNormal; +#if @additiveBlending +#define ADDITIVE_BLENDING +#endif + #include "vertexcolors.glsl" #include "shadows_fragment.glsl" #include "lighting.glsl" @@ -188,7 +192,7 @@ void main() #endif - float shadowing = unshadowedLightRatio(passViewPos.z); + float shadowing = unshadowedLightRatio(-passViewPos.z); vec3 lighting; #if !PER_PIXEL_LIGHTING lighting = passLighting + shadowDiffuseLighting * shadowing;