mac os driver workaround and shadervisitor fixes

librecast_all_the_things
glassmancody.info 3 years ago
parent 3d381bf0d3
commit 9389cfaa42

@ -102,8 +102,15 @@ namespace
: mOpaqueDepthFbo(new osg::FrameBufferObject)
, mSourceFbo(sourceFbo)
, mOpaqueDepthTex(opaqueDepthTex)
, mColorAttached(false)
{
mOpaqueDepthFbo->setAttachment(osg::FrameBufferObject::BufferComponent::DEPTH_BUFFER, osg::FrameBufferAttachment(opaqueDepthTex));
#ifdef __APPLE__
// Mac OS drivers complain that a FBO is incomplete if it has no color attachment
mOpaqueDepthFbo->setAttachment(osg::FrameBufferObject::BufferComponent::COLOR_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(mOpaqueDepthTex->getTextureWidth(), mOpaqueDepthTex->getTextureHeight(), GL_RGB)));
mColorAttached = true;
#endif
}
void drawImplementation(osgUtil::RenderBin* bin, osg::RenderInfo& renderInfo, osgUtil::RenderLeaf*& previous) override
@ -114,7 +121,10 @@ namespace
osg::GLExtensions* ext = state.get<osg::GLExtensions>();
mSourceFbo->apply(state, osg::FrameBufferObject::READ_FRAMEBUFFER);
postBindOperation(state);
mOpaqueDepthFbo->apply(state, osg::FrameBufferObject::DRAW_FRAMEBUFFER);
postBindOperation(state);
ext->glBlitFramebuffer(0, 0, mOpaqueDepthTex->getTextureWidth(), mOpaqueDepthTex->getTextureHeight(), 0, 0, mOpaqueDepthTex->getTextureWidth(), mOpaqueDepthTex->getTextureHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
@ -124,9 +134,20 @@ namespace
bin->drawImplementation(renderInfo, previous);
}
private:
void postBindOperation(osg::State& state)
{
if (mColorAttached)
return;
#if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GLES3_AVAILABLE)
state.glDrawBuffer(GL_NONE);
state.glReadBuffer(GL_NONE);
#endif
}
osg::ref_ptr<osg::FrameBufferObject> mOpaqueDepthFbo;
osg::ref_ptr<osg::FrameBufferObject> mSourceFbo;
osg::ref_ptr<osg::Texture2D> mOpaqueDepthTex;
bool mColorAttached;
};
}

@ -316,6 +316,7 @@ namespace MWRender
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
// Shadows and radial fog have problems with fixed-function mode
bool forceShaders = Settings::Manager::getBool("radial fog", "Shaders")
|| Settings::Manager::getBool("soft particles", "Shaders")
|| Settings::Manager::getBool("force shaders", "Shaders")
|| Settings::Manager::getBool("enable shadows", "Shadows")
|| lightingMethod != SceneUtil::LightingMethod::FFP

@ -636,7 +636,6 @@ namespace MWRender
mParticleNode = new osg::PositionAttitudeTransform;
mParticleNode->addCullCallback(mUnderwaterSwitch);
mParticleNode->setNodeMask(Mask_WeatherParticles);
mParticleNode->getOrCreateStateSet();
mRootNode->addChild(mParticleNode);
}
@ -668,7 +667,6 @@ namespace MWRender
ps->getParticle(particleIndex)->update(0, true);
}
ps->getOrCreateStateSet();
ps->setUserValue("simpleLighting", true);
}

@ -1049,7 +1049,6 @@ namespace NifOsg
void handleParticleSystem(const Nif::Node *nifNode, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite, int animflags)
{
osg::ref_ptr<ParticleSystem> partsys (new ParticleSystem);
partsys->getOrCreateStateSet();
partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT);
const Nif::NiParticleSystemController* partctrl = nullptr;

@ -1,6 +1,7 @@
#include "shadervisitor.hpp"
#include <unordered_set>
#include <unordered_map>
#include <set>
#include <osg/AlphaFunc>
@ -37,12 +38,14 @@ namespace Shader
, mUniforms(rhs.mUniforms)
, mModes(rhs.mModes)
, mAttributes(rhs.mAttributes)
, mTextureModes(rhs.mTextureModes)
{
}
void addUniform(const std::string& name) { mUniforms.emplace(name); }
void setMode(osg::StateAttribute::GLMode mode) { mModes.emplace(mode); }
void setAttribute(osg::StateAttribute::TypeMemberPair typeMemberPair) { mAttributes.emplace(typeMemberPair); }
void setTextureMode(int unit, osg::StateAttribute::GLMode mode) { mTextureModes[unit].emplace(mode); }
void setAttribute(const osg::StateAttribute* attribute)
{
@ -64,12 +67,20 @@ namespace Shader
bool hasMode(osg::StateAttribute::GLMode mode) { return mModes.count(mode); }
bool hasAttribute(const osg::StateAttribute::TypeMemberPair &typeMemberPair) { return mAttributes.count(typeMemberPair); }
bool hasAttribute(osg::StateAttribute::Type type, unsigned int member) { return hasAttribute(osg::StateAttribute::TypeMemberPair(type, member)); }
bool hasTextureMode(int unit, osg::StateAttribute::GLMode mode)
{
auto it = mTextureModes.find(unit);
if (it == mTextureModes.cend())
return false;
return it->second.count(mode);
}
const std::set<osg::StateAttribute::TypeMemberPair>& getAttributes() { return mAttributes; }
bool empty()
{
return mUniforms.empty() && mModes.empty() && mAttributes.empty();
return mUniforms.empty() && mModes.empty() && mAttributes.empty() && mTextureModes.empty();
}
META_Object(Shader, AddedState)
@ -86,9 +97,12 @@ namespace Shader
AddedState* mTracker;
};
using ModeSet = std::unordered_set<osg::StateAttribute::GLMode>;
std::unordered_set<std::string> mUniforms;
std::unordered_set<osg::StateAttribute::GLMode> mModes;
ModeSet mModes;
std::set<osg::StateAttribute::TypeMemberPair> mAttributes;
std::unordered_map<int, ModeSet> mTextureModes;
};
ShaderVisitor::ShaderRequirements::ShaderRequirements()
@ -102,6 +116,8 @@ namespace Shader
, mAlphaBlend(false)
, mNormalHeight(false)
, mTexStageRequiringTangents(-1)
, mSoftParticles(false)
, mSoftParticleSize(0.f)
, mNode(nullptr)
{
}
@ -213,6 +229,8 @@ namespace Shader
if (node.getUserValue("shaderRequired", shaderRequired) && shaderRequired)
mRequirements.back().mShaderRequired = true;
osg::ref_ptr<AddedState> addedState = getAddedState(*stateset);
if (!texAttributes.empty())
{
const osg::Texture* diffuseMap = nullptr;
@ -224,6 +242,9 @@ namespace Shader
const osg::StateAttribute *attr = stateset->getTextureAttribute(unit, osg::StateAttribute::TEXTURE);
if (attr)
{
if (addedState && addedState->hasTextureMode(unit, GL_TEXTURE_2D))
continue;
const osg::Texture* texture = attr->asTexture();
if (texture)
{
@ -350,7 +371,6 @@ namespace Shader
osg::StateSet::AttributeList removedAttributes;
if (osg::ref_ptr<osg::StateSet> removedState = getRemovedState(*stateset))
removedAttributes = removedState->getAttributeList();
osg::ref_ptr<AddedState> addedState = getAddedState(*stateset);
for (const auto* attributeMap : std::initializer_list<const osg::StateSet::AttributeList*>{ &attributes, &removedAttributes })
{
@ -545,6 +565,25 @@ namespace Shader
updateRemovedState(*writableUserData, removedState);
}
if (reqs.mSoftParticles)
{
osg::ref_ptr<osg::Depth> depth = new SceneUtil::AutoDepth;
depth->setWriteMask(false);
writableStateSet->setAttributeAndModes(depth, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
addedState->setAttribute(depth);
writableStateSet->addUniform(new osg::Uniform("particleSize", reqs.mSoftParticleSize));
addedState->addUniform("particleSize");
writableStateSet->addUniform(new osg::Uniform("opaqueDepthTex", 2));
addedState->addUniform("opaqueDepthTex");
writableStateSet->setTextureAttributeAndModes(2, mOpaqueDepthTex, osg::StateAttribute::ON);
addedState->setTextureMode(2, GL_TEXTURE_2D);
}
defineMap["softParticles"] = reqs.mSoftParticles ? "1" : "0";
if (!addedState->empty())
{
// user data is normally shallow copied so shared with the original stateset
@ -557,27 +596,6 @@ namespace Shader
updateAddedState(*writableUserData, addedState);
}
bool softParticles = false;
if (mOpaqueDepthTex)
{
auto partsys = dynamic_cast<osgParticle::ParticleSystem*>(&node);
if (partsys)
{
softParticles = true;
auto depth = new SceneUtil::AutoDepth;
depth->setWriteMask(false);
writableStateSet->setAttributeAndModes(depth, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
writableStateSet->addUniform(new osg::Uniform("particleSize", partsys->getDefaultParticleTemplate().getSizeRange().maximum));
writableStateSet->addUniform(new osg::Uniform("opaqueDepthTex", 2));
writableStateSet->setTextureAttributeAndModes(2, mOpaqueDepthTex, osg::StateAttribute::ON);
}
}
defineMap["softParticles"] = softParticles ? "1" : "0";
std::string shaderPrefix;
if (!node.getUserValue("shaderPrefix", shaderPrefix))
shaderPrefix = mDefaultShaderPrefix;
@ -719,13 +737,22 @@ namespace Shader
void ShaderVisitor::apply(osg::Drawable& drawable)
{
// non-Geometry drawable (e.g. particle system)
bool needPop = (drawable.getStateSet() != nullptr);
auto partsys = dynamic_cast<osgParticle::ParticleSystem*>(&drawable);
bool needPop = drawable.getStateSet() || partsys;
if (drawable.getStateSet())
if (needPop)
{
pushRequirements(drawable);
applyStateSet(drawable.getStateSet(), drawable);
if (partsys && mOpaqueDepthTex)
{
mRequirements.back().mSoftParticles = true;
mRequirements.back().mSoftParticleSize = partsys->getDefaultParticleTemplate().getSizeRange().maximum;
}
if (drawable.getStateSet())
applyStateSet(drawable.getStateSet(), drawable);
}
if (!mRequirements.empty())
@ -831,6 +858,12 @@ namespace Shader
for (const auto& attribute : removedState->getAttributeList())
writableStateSet->setAttribute(attribute.second.first, attribute.second.second);
for (unsigned int unit = 0; unit < removedState->getTextureModeList().size(); ++unit)
{
for (const auto&[mode, value] : removedState->getTextureModeList()[unit])
writableStateSet->setTextureMode(unit, mode, value);
}
}
}

@ -101,6 +101,9 @@ namespace Shader
// -1 == no tangents required
int mTexStageRequiringTangents;
bool mSoftParticles;
float mSoftParticleSize;
// the Node that requested these requirements
osg::Node* mNode;
};

@ -282,3 +282,6 @@ intersection between individual particles and other opaque geometry by blending
between them. Note, this relies on overriding specific properties of particle
systems that potentially differ from the source content, this setting may change
the look of some particle systems.
Note that the rendering will act as if you have 'force shaders' option enabled.
This means that shaders will be used to render all objects and the terrain.

@ -226,7 +226,7 @@ void main()
#endif
gl_FragData[0].xyz = mix(gl_FragData[0].xyz, gl_Fog.color.xyz, fogValue);
#if @softParticles
#if !defined(FORCE_OPAQUE) && @softParticles
gl_FragData[0].a *= calcSoftParticleFade();
#endif

Loading…
Cancel
Save