mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-06 06:45:35 +00:00
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
This commit is contained in:
parent
1109cc3ac7
commit
8358418555
12 changed files with 53 additions and 51 deletions
|
@ -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…
Reference in a new issue