set the correct program link parameters (#3110)

* shadermanager.hpp setProgramTemplate

* shadermanager.hpp

* shadermanager.cpp setProgramTemplate

* shadervisitor.hpp setProgramTemplate

* shadervisitor.cpp setProgramTemplate

* scenemanager.cpp setProgramTemplate

* scenemanager.hpp setProgramTemplate

* renderingmanager.cpp

* groundcover.cpp setProgramTemplate

* groundcover.hpp

* groundcover.cpp

* shadervisitor.cpp

* util.cpp

* lightmanager.cpp

* scenemanager.cpp

* scenemanager.hpp

* lightmanager.cpp

* lightmanager.cpp

* lightmanager.cpp

* scenemanager.hpp [ci skip]

* water.cpp

* groundcover.cpp

* shadermanager.hpp
pull/3135/head
Bo Svensson 3 years ago committed by GitHub
parent 1109cc3ac7
commit 8358418555
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,6 +7,7 @@
#include <components/esm/esmreader.hpp>
#include <components/sceneutil/lightmanager.hpp>
#include <components/shader/shadermanager.hpp>
#include "apps/openmw/mwworld/esmstore.hpp"
#include "apps/openmw/mwbase/environment.hpp"
@ -150,6 +151,10 @@ namespace MWRender
mStateset->setRenderBinDetails(0, "RenderBin", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS);
mStateset->setAttribute(new osg::VertexAttribDivisor(6, 1));
mStateset->setAttribute(new osg::VertexAttribDivisor(7, 1));
mProgramTemplate = mSceneManager->getShaderManager().getProgramTemplate() ? static_cast<osg::Program*>(mSceneManager->getShaderManager().getProgramTemplate()->clone(osg::CopyOp::SHALLOW_COPY)) : new osg::Program;
mProgramTemplate->addBindAttribLocation("aOffset", 6);
mProgramTemplate->addBindAttribLocation("aRotation", 7);
}
void Groundcover::collectInstances(InstanceMap& instances, float size, const osg::Vec2f& center)
@ -219,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);
mSceneManager->recreateShaders(group, "groundcover", false, true, mProgramTemplate);
mSceneManager->shareState(group);
group->getBound();
return group;

@ -4,6 +4,7 @@
#include <components/terrain/quadtreeworld.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/esm/loadcell.hpp>
#include <osg/Program>
namespace MWRender
{
@ -33,6 +34,7 @@ namespace MWRender
Resource::SceneManager* mSceneManager;
float mDensity;
osg::ref_ptr<osg::StateSet> mStateset;
osg::ref_ptr<osg::Program> mProgramTemplate;
typedef std::map<std::string, std::vector<GroundcoverEntry>> InstanceMap;
osg::ref_ptr<osg::Node> createChunk(InstanceMap& instances, const osg::Vec2f& center);

@ -325,7 +325,6 @@ namespace MWRender
// Let LightManager choose which backend to use based on our hint. For methods besides legacy lighting, this depends on support for various OpenGL extensions.
osg::ref_ptr<SceneUtil::LightManager> sceneRoot = new SceneUtil::LightManager(lightingMethod == SceneUtil::LightingMethod::FFP);
resourceSystem->getSceneManager()->getShaderManager().setLightingMethod(sceneRoot->getLightingMethod());
resourceSystem->getSceneManager()->setLightingMethod(sceneRoot->getLightingMethod());
resourceSystem->getSceneManager()->setSupportedLightingMethods(sceneRoot->getSupportedLightingMethods());
mMinimumAmbientLuminance = std::clamp(Settings::Manager::getFloat("minimum interior brightness", "Shaders"), 0.f, 1.f);

@ -670,9 +670,6 @@ void Water::createShaderWaterStateSet(osg::Node* node, Reflection* reflection, R
normalMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
normalMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
auto method = mResourceSystem->getSceneManager()->getLightingMethod();
if (method == SceneUtil::LightingMethod::SingleUBO)
program->addBindUniformBlock("LightBufferBinding", static_cast<int>(Shader::UBOBinding::LightBuffer));
mRainIntensityUpdater = new RainIntensityUpdater();
node->setUpdateCallback(mRainIntensityUpdater);

@ -28,6 +28,7 @@
#include <components/sceneutil/controller.hpp>
#include <components/sceneutil/optimizer.hpp>
#include <components/sceneutil/visitor.hpp>
#include <components/sceneutil/lightmanager.hpp>
#include <components/shader/shadervisitor.hpp>
#include <components/shader/shadermanager.hpp>
@ -332,10 +333,11 @@ namespace Resource
return mForceShaders;
}
void SceneManager::recreateShaders(osg::ref_ptr<osg::Node> node, const std::string& shaderPrefix, bool translucentFramebuffer, bool forceShadersForNode)
void SceneManager::recreateShaders(osg::ref_ptr<osg::Node> node, const std::string& shaderPrefix, bool translucentFramebuffer, bool forceShadersForNode, const osg::Program* programTemplate)
{
osg::ref_ptr<Shader::ShaderVisitor> shaderVisitor(createShaderVisitor(shaderPrefix, translucentFramebuffer));
shaderVisitor->setAllowedToModifyStateSets(false);
shaderVisitor->setProgramTemplate(programTemplate);
if (forceShadersForNode)
shaderVisitor->setForceShaders(true);
node->accept(*shaderVisitor);
@ -410,6 +412,13 @@ namespace Resource
void SceneManager::setLightingMethod(SceneUtil::LightingMethod method)
{
mLightingMethod = method;
if (mLightingMethod == SceneUtil::LightingMethod::SingleUBO)
{
osg::ref_ptr<osg::Program> program = new osg::Program;
program->addBindUniformBlock("LightBufferBinding", static_cast<int>(UBOBinding::LightBuffer));
mShaderManager->setProgramTemplate(program);
}
}
SceneUtil::LightingMethod SceneManager::getLightingMethod() const

@ -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);
void recreateShaders(osg::ref_ptr<osg::Node> node, const std::string& shaderPrefix = "objects", bool translucentFramebuffer = false, bool forceShadersForNode = false, const osg::Program* programTemplate = nullptr);
/// Applying shaders to a node may replace some fixed-function state.
/// This restores it.
@ -111,6 +111,11 @@ namespace Resource
void setSupportedLightingMethods(const SceneUtil::LightManager::SupportedMethods& supported);
bool isSupportedLightingMethod(SceneUtil::LightingMethod method) const;
enum class UBOBinding
{
// If we add more UBO's, we should probably assign their bindings dynamically according to the current count of UBO's in the programTemplate
LightBuffer
};
void setLightingMethod(SceneUtil::LightingMethod method);
SceneUtil::LightingMethod getLightingMethod() const;

@ -11,6 +11,7 @@
#include <osgUtil/CullVisitor>
#include <components/sceneutil/util.hpp>
#include <components/resource/scenemanager.hpp>
#include <components/misc/hash.hpp>
#include <components/misc/stringops.hpp>
@ -294,9 +295,9 @@ namespace SceneUtil
osg::ref_ptr<osg::UniformBufferObject> ubo = new osg::UniformBufferObject;
buffer->getData()->setBufferObject(ubo);
#if OSG_VERSION_GREATER_OR_EQUAL(3,5,7)
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Shader::UBOBinding::LightBuffer), buffer->getData(), 0, buffer->getData()->getTotalDataSize());
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Resource::SceneManager::UBOBinding::LightBuffer), buffer->getData(), 0, buffer->getData()->getTotalDataSize());
#else
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Shader::UBOBinding::LightBuffer), ubo, 0, buffer->getData()->getTotalDataSize());
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Resource::SceneManager::UBOBinding::LightBuffer), ubo, 0, buffer->getData()->getTotalDataSize());
#endif
stateset->setAttributeAndModes(ubb, mode);
@ -676,9 +677,9 @@ namespace SceneUtil
auto bo = mLightManager->getLightBuffer(mLastFrameNumber);
#if OSG_VERSION_GREATER_OR_EQUAL(3,5,7)
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Shader::UBOBinding::LightBuffer), bo->getData(), 0, bo->getData()->getTotalDataSize());
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Resource::SceneManager::UBOBinding::LightBuffer), bo->getData(), 0, bo->getData()->getTotalDataSize());
#else
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Shader::UBOBinding::LightBuffer), bo->getData()->getBufferObject(), 0, bo->getData()->getTotalDataSize());
osg::ref_ptr<osg::UniformBufferBinding> ubb = new osg::UniformBufferBinding(static_cast<int>(Resource::SceneManager::UBOBinding::LightBuffer), bo->getData()->getBufferObject(), 0, bo->getData()->getTotalDataSize());
#endif
stateset->setAttributeAndModes(ubb, osg::StateAttribute::ON);
}
@ -736,7 +737,7 @@ namespace SceneUtil
// Needed to query the layout of the buffer object. The layout specifier needed to use the std140 layout is not reliably
// available, regardless of extensions, until GLSL 140.
mDummyProgram->addShader(new osg::Shader(osg::Shader::VERTEX, dummyVertSource));
mDummyProgram->addBindUniformBlock("LightBufferBinding", static_cast<int>(Shader::UBOBinding::LightBuffer));
mDummyProgram->addBindUniformBlock("LightBufferBinding", static_cast<int>(Resource::SceneManager::UBOBinding::LightBuffer));
}
LightManagerStateAttribute(const LightManagerStateAttribute& copy, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY)
@ -751,7 +752,7 @@ namespace SceneUtil
void initSharedLayout(osg::GLExtensions* ext, int handle) const
{
constexpr std::array<unsigned int, 1> index = { static_cast<unsigned int>(Shader::UBOBinding::LightBuffer) };
constexpr std::array<unsigned int, 1> index = { static_cast<unsigned int>(Resource::SceneManager::UBOBinding::LightBuffer) };
int totalBlockSize = -1;
int stride = -1;

@ -11,6 +11,9 @@
#include <osg/TexGen>
#include <osg/TexEnvCombine>
#include <osg/Version>
#include <osg/FrameBufferObject>
#include <osgUtil/RenderStage>
#include <osgUtil/CullVisitor>
#include <components/resource/imagemanager.hpp>
#include <components/resource/scenemanager.hpp>

@ -9,7 +9,6 @@
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/fstream.hpp>
#include <components/sceneutil/lightmanager.hpp>
#include <components/debug/debuglog.hpp>
#include <components/misc/stringops.hpp>
@ -17,7 +16,6 @@ namespace Shader
{
ShaderManager::ShaderManager()
: mLightingMethod(SceneUtil::LightingMethod::FFP)
{
}
@ -26,11 +24,6 @@ namespace Shader
mPath = path;
}
void ShaderManager::setLightingMethod(SceneUtil::LightingMethod method)
{
mLightingMethod = method;
}
bool addLineDirectivesAfterConditionalBlocks(std::string& source)
{
for (size_t position = 0; position < source.length(); )
@ -345,19 +338,16 @@ namespace Shader
return shaderIt->second;
}
osg::ref_ptr<osg::Program> ShaderManager::getProgram(osg::ref_ptr<osg::Shader> vertexShader, osg::ref_ptr<osg::Shader> fragmentShader)
osg::ref_ptr<osg::Program> ShaderManager::getProgram(osg::ref_ptr<osg::Shader> vertexShader, osg::ref_ptr<osg::Shader> fragmentShader, const osg::Program* programTemplate)
{
std::lock_guard<std::mutex> lock(mMutex);
ProgramMap::iterator found = mPrograms.find(std::make_pair(vertexShader, fragmentShader));
if (found == mPrograms.end())
{
osg::ref_ptr<osg::Program> program (new osg::Program);
if (!programTemplate) programTemplate = mProgramTemplate;
osg::ref_ptr<osg::Program> program = programTemplate ? static_cast<osg::Program*>(programTemplate->clone(osg::CopyOp::SHALLOW_COPY)) : new osg::Program;
program->addShader(vertexShader);
program->addShader(fragmentShader);
program->addBindAttribLocation("aOffset", 6);
program->addBindAttribLocation("aRotation", 7);
if (mLightingMethod == SceneUtil::LightingMethod::SingleUBO)
program->addBindUniformBlock("LightBufferBinding", static_cast<int>(UBOBinding::LightBuffer));
found = mPrograms.insert(std::make_pair(std::make_pair(vertexShader, fragmentShader), program)).first;
}
return found->second;

@ -8,29 +8,11 @@
#include <osg/ref_ptr>
#include <osg/Shader>
#include <osgViewer/Viewer>
#include <components/sceneutil/lightmanager.hpp>
namespace Resource
{
class SceneManager;
}
namespace SceneUtil
{
enum class LightingMethod;
}
#include <osg/Program>
namespace Shader
{
enum class UBOBinding
{
LightBuffer
};
/// @brief Reads shader template files and turns them into a concrete shader, based on a list of define's.
/// @par Shader templates can get the value of a define with the syntax @define.
class ShaderManager
@ -41,8 +23,6 @@ namespace Shader
void setShaderPath(const std::string& path);
void setLightingMethod(SceneUtil::LightingMethod method);
typedef std::map<std::string, std::string> DefineMap;
/// Create or retrieve a shader instance.
@ -53,7 +33,10 @@ namespace Shader
/// @note Thread safe.
osg::ref_ptr<osg::Shader> getShader(const std::string& templateName, const DefineMap& defines, osg::Shader::Type shaderType);
osg::ref_ptr<osg::Program> getProgram(osg::ref_ptr<osg::Shader> vertexShader, osg::ref_ptr<osg::Shader> fragmentShader);
osg::ref_ptr<osg::Program> getProgram(osg::ref_ptr<osg::Shader> vertexShader, osg::ref_ptr<osg::Shader> fragmentShader, const osg::Program* programTemplate=nullptr);
const osg::Program* getProgramTemplate() const { return mProgramTemplate; }
void setProgramTemplate(const osg::Program* program) { mProgramTemplate = program; }
/// Get (a copy of) the DefineMap used to construct all shaders
DefineMap getGlobalDefines();
@ -81,9 +64,9 @@ namespace Shader
typedef std::map<std::pair<osg::ref_ptr<osg::Shader>, osg::ref_ptr<osg::Shader> >, osg::ref_ptr<osg::Program> > ProgramMap;
ProgramMap mPrograms;
SceneUtil::LightingMethod mLightingMethod;
std::mutex mMutex;
osg::ref_ptr<const osg::Program> mProgramTemplate;
};
bool parseFors(std::string& source, const std::string& templateName);

@ -1,5 +1,8 @@
#include "shadervisitor.hpp"
#include <unordered_set>
#include <set>
#include <osg/AlphaFunc>
#include <osg/Geometry>
#include <osg/GLExtensions>
@ -553,7 +556,7 @@ namespace Shader
if (vertexShader && fragmentShader)
{
auto program = mShaderManager.getProgram(vertexShader, fragmentShader);
auto program = mShaderManager.getProgram(vertexShader, fragmentShader, mProgramTemplate);
writableStateSet->setAttributeAndModes(program, osg::StateAttribute::ON);
addedState->setAttributeAndModes(program);

@ -2,6 +2,7 @@
#define OPENMW_COMPONENTS_SHADERVISITOR_H
#include <osg/NodeVisitor>
#include <osg/Program>
namespace Resource
{
@ -19,6 +20,8 @@ namespace Shader
public:
ShaderVisitor(ShaderManager& shaderManager, Resource::ImageManager& imageManager, const std::string& defaultShaderPrefix);
void setProgramTemplate(const osg::Program* programTemplate) { mProgramTemplate = programTemplate; }
/// By default, only bump mapped objects will have a shader added to them.
/// Setting force = true will cause all objects to render using shaders, regardless of having a bump map.
void setForceShaders(bool force);
@ -109,6 +112,8 @@ namespace Shader
void createProgram(const ShaderRequirements& reqs);
void ensureFFP(osg::Node& node);
bool adjustGeometry(osg::Geometry& sourceGeometry, const ShaderRequirements& reqs);
osg::ref_ptr<const osg::Program> mProgramTemplate;
};
class ReinstateRemovedStateVisitor : public osg::NodeVisitor

Loading…
Cancel
Save