Sync extern/shiny, set memory budgets for texture and mesh managers (however this has no effect yet and depends on changes in Ogre being made)

actorid
scrawl 12 years ago
parent 28ef4d97da
commit 75dcf52552

@ -14,6 +14,7 @@
#include <OgreCompositionPass.h>
#include <OgreHardwarePixelBuffer.h>
#include <OgreControllerManager.h>
#include <OgreMeshManager.h>
#include <extern/shiny/Main/Factory.hpp>
#include <extern/shiny/Platforms/Ogre/OgrePlatform.hpp>
@ -120,13 +121,11 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
MaterialManager::getSingleton().setDefaultTextureFiltering(tfo);
MaterialManager::getSingleton().setDefaultAnisotropy( (filter == "anisotropic") ? Settings::Manager::getInt("anisotropy", "General") : 1 );
//ResourceGroupManager::getSingleton ().declareResource ("GlobalMap.png", "Texture", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
Ogre::TextureManager::getSingleton().setMemoryBudget(126*1024*1024);
Ogre::MeshManager::getSingleton().setMemoryBudget(64*1024*1024);
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
// causes light flicker in opengl when moving..
//mRendering.getScene()->setCameraRelativeRendering(true);
// disable unsupported effects
if (!Settings::Manager::getBool("shaders", "Objects"))
Settings::Manager::setBool("enabled", "Shadows", false);
@ -236,6 +235,7 @@ void RenderingManager::toggleWater()
void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store)
{
sh::Factory::getInstance().unloadUnreferencedMaterials();
mObjects.buildStaticGeometry (*store);
mDebugging->cellAdded(store);
if (store->mCell->isExterior())
@ -306,7 +306,6 @@ void RenderingManager::update (float duration, bool paused)
int blind = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Blind)).mMagnitude;
mRendering.getFader()->setFactor(1.f-(blind / 100.f));
setAmbientMode();
// player position

@ -9,8 +9,6 @@ set(SHINY_LIBRARY "shiny")
set(SHINY_OGREPLATFORM_LIBRARY "shiny.OgrePlatform")
# Sources
file(GLOB SOURCE_FILES Main/*.cpp )
set(SOURCE_FILES
Main/Factory.cpp
Main/MaterialInstance.cpp
@ -57,12 +55,20 @@ file(GLOB OGRE_PLATFORM_SOURCE_FILES Platforms/Ogre/*.cpp)
add_library(${SHINY_LIBRARY} STATIC ${SOURCE_FILES})
set(SHINY_LIBRARIES ${SHINY_LIBRARY})
if (SHINY_BUILD_OGRE_PLATFORM)
add_library(${SHINY_OGREPLATFORM_LIBRARY} STATIC ${OGRE_PLATFORM_SOURCE_FILES})
set(SHINY_LIBRARIES ${SHINY_LIBRARIES} ${SHINY_OGREPLATFORM_LIBRARY})
endif()
set(SHINY_LIBRARY ${SHINY_LIBRARY} PARENT_SCOPE)
link_directories(${CMAKE_CURRENT_BINARY_DIR})
if (DEFINED SHINY_BUILD_MATERIAL_EDITOR)
add_subdirectory(Editor)
set(SHINY_LIBRARY ${SHINY_LIBRARY} PARENT_SCOPE)
set(SHINY_OGREPLATFORM_LIBRARY ${SHINY_OGREPLATFORM_LIBRARY} PARENT_SCOPE)
set(SHINY_BUILD_EDITOR_FLAG ${SHINY_BUILD_EDITOR_FLAG} PARENT_SCOPE)
endif()
link_directories(${CMAKE_CURRENT_BINARY_DIR})
set(SHINY_LIBRARIES ${SHINY_LIBRARIES} PARENT_SCOPE)

@ -21,7 +21,7 @@
}
\endcode
\note You may also create configurations using sh::Factory::registerConfiguration.
\note You may also create configurations using sh::Factory::createConfiguration.
The active Configuration is controlled by the active material scheme in Ogre. So, in order to use the configuration "reflection_targets" for your reflection renders, simply call
\code

@ -51,8 +51,6 @@ namespace sh
{
assert(mCurrentLanguage != Language_None);
bool removeBinaryCache = false;
if (boost::filesystem::exists (mPlatform->getCacheFolder () + "/lastModified.txt"))
{
std::ifstream file;
@ -86,8 +84,9 @@ namespace sh
break;
}
PropertySetGet newConfiguration;
Configuration newConfiguration;
newConfiguration.setParent(&mGlobalSettings);
newConfiguration.setSourceFile (it->second->mFileName);
std::vector<ScriptNode*> props = it->second->getChildren();
for (std::vector<ScriptNode*>::const_iterator propIt = props.begin(); propIt != props.end(); ++propIt)
@ -137,82 +136,7 @@ namespace sh
}
// load shader sets
{
ScriptLoader shaderSetLoader(".shaderset");
ScriptLoader::loadAllFiles (&shaderSetLoader, mPlatform->getBasePath());
std::map <std::string, ScriptNode*> nodes = shaderSetLoader.getAllConfigScripts();
for (std::map <std::string, ScriptNode*>::const_iterator it = nodes.begin();
it != nodes.end(); ++it)
{
if (!(it->second->getName() == "shader_set"))
{
std::cerr << "sh::Factory: Warning: Unsupported root node type \"" << it->second->getName() << "\" for file type .shaderset" << std::endl;
break;
}
if (!it->second->findChild("profiles_cg"))
throw std::runtime_error ("missing \"profiles_cg\" field for \"" + it->first + "\"");
if (!it->second->findChild("profiles_hlsl"))
throw std::runtime_error ("missing \"profiles_hlsl\" field for \"" + it->first + "\"");
if (!it->second->findChild("source"))
throw std::runtime_error ("missing \"source\" field for \"" + it->first + "\"");
if (!it->second->findChild("type"))
throw std::runtime_error ("missing \"type\" field for \"" + it->first + "\"");
std::vector<std::string> profiles_cg;
boost::split (profiles_cg, it->second->findChild("profiles_cg")->getValue(), boost::is_any_of(" "));
std::string cg_profile;
for (std::vector<std::string>::iterator it2 = profiles_cg.begin(); it2 != profiles_cg.end(); ++it2)
{
if (mPlatform->isProfileSupported(*it2))
{
cg_profile = *it2;
break;
}
}
std::vector<std::string> profiles_hlsl;
boost::split (profiles_hlsl, it->second->findChild("profiles_hlsl")->getValue(), boost::is_any_of(" "));
std::string hlsl_profile;
for (std::vector<std::string>::iterator it2 = profiles_hlsl.begin(); it2 != profiles_hlsl.end(); ++it2)
{
if (mPlatform->isProfileSupported(*it2))
{
hlsl_profile = *it2;
break;
}
}
std::string sourceAbsolute = mPlatform->getBasePath() + "/" + it->second->findChild("source")->getValue();
std::string sourceRelative = it->second->findChild("source")->getValue();
ShaderSet newSet (it->second->findChild("type")->getValue(), cg_profile, hlsl_profile,
sourceAbsolute,
mPlatform->getBasePath(),
it->first,
&mGlobalSettings);
int lastModified = boost::filesystem::last_write_time (boost::filesystem::path(sourceAbsolute));
mShadersLastModifiedNew[sourceRelative] = lastModified;
if (mShadersLastModified.find(sourceRelative) != mShadersLastModified.end())
{
if (mShadersLastModified[sourceRelative] != lastModified)
{
// delete any outdated shaders based on this shader set
if (removeCache (it->first))
removeBinaryCache = true;
}
}
else
{
// if we get here, this is either the first run or a new shader file was added
// in both cases we can safely delete
if (removeCache (it->first))
removeBinaryCache = true;
}
mShaderSets.insert(std::make_pair(it->first, newSet));
}
}
bool removeBinaryCache = reloadShaders();
// load materials
{
@ -315,6 +239,8 @@ namespace sh
Factory::~Factory ()
{
mShaderSets.clear();
if (mPlatform->supportsShaderSerialization () && mWriteMicrocodeCache)
{
std::string file = mPlatform->getCacheFolder () + "/" + mBinaryCacheName;
@ -367,15 +293,16 @@ namespace sh
while (i>0)
{
--i;
m->createForConfiguration (configuration, i);
if (mListener)
if (m->createForConfiguration (configuration, i) && mListener)
mListener->materialCreated (m, configuration, i);
else
return NULL;
}
m->createForConfiguration (configuration, lodIndex);
if (mListener)
if (m->createForConfiguration (configuration, lodIndex) && mListener)
mListener->materialCreated (m, configuration, lodIndex);
else
return NULL;
}
return m;
}
@ -439,6 +366,12 @@ namespace sh
ShaderSet* Factory::getShaderSet (const std::string& name)
{
if (mShaderSets.find(name) == mShaderSets.end())
{
std::stringstream msg;
msg << "Shader '" << name << "' not found";
throw std::runtime_error(msg.str());
}
return &mShaderSets.find(name)->second;
}
@ -466,6 +399,14 @@ namespace sh
}
}
void Factory::notifyConfigurationChanged()
{
for (MaterialMap::iterator it = mMaterials.begin(); it != mMaterials.end(); ++it)
{
it->second.destroyAll();
}
}
MaterialInstance* Factory::getMaterialInstance (const std::string& name)
{
return findInstance(name);
@ -493,17 +434,21 @@ namespace sh
return "";
}
PropertySetGet* Factory::getConfiguration (const std::string& name)
Configuration* Factory::getConfiguration (const std::string& name)
{
return &mConfigurations[name];
}
void Factory::registerConfiguration (const std::string& name, PropertySetGet configuration)
void Factory::createConfiguration (const std::string& name)
{
mConfigurations[name] = configuration;
mConfigurations[name].setParent (&mGlobalSettings);
}
void Factory::destroyConfiguration(const std::string &name)
{
mConfigurations.erase(name);
}
void Factory::registerLodConfiguration (int index, PropertySetGet configuration)
{
mLodConfigurations[index] = configuration;
@ -571,17 +516,93 @@ namespace sh
return p;
}
void Factory::saveMaterials (const std::string& filename)
void Factory::saveAll ()
{
std::ofstream file;
file.open (filename.c_str ());
std::map<std::string, std::ofstream*> files;
for (MaterialMap::iterator it = mMaterials.begin(); it != mMaterials.end(); ++it)
{
if (it->second.getSourceFile().empty())
continue;
if (files.find(it->second.getSourceFile()) == files.end())
{
/// \todo check if this is actually the same file, since there can be different paths to the same file
std::ofstream* stream = new std::ofstream();
stream->open (it->second.getSourceFile().c_str());
files[it->second.getSourceFile()] = stream;
}
it->second.save (*files[it->second.getSourceFile()]);
}
for (std::map<std::string, std::ofstream*>::iterator it = files.begin(); it != files.end(); ++it)
{
delete it->second;
}
files.clear();
for (ConfigurationMap::iterator it = mConfigurations.begin(); it != mConfigurations.end(); ++it)
{
if (it->second.getSourceFile().empty())
continue;
if (files.find(it->second.getSourceFile()) == files.end())
{
/// \todo check if this is actually the same file, since there can be different paths to the same file
std::ofstream* stream = new std::ofstream();
stream->open (it->second.getSourceFile().c_str());
files[it->second.getSourceFile()] = stream;
}
it->second.save (it->first, *files[it->second.getSourceFile()]);
}
for (std::map<std::string, std::ofstream*>::iterator it = files.begin(); it != files.end(); ++it)
{
delete it->second;
}
}
void Factory::listMaterials(std::vector<std::string> &out)
{
for (MaterialMap::iterator it = mMaterials.begin(); it != mMaterials.end(); ++it)
{
it->second.save(file);
out.push_back(it->first);
}
}
void Factory::listGlobalSettings(std::map<std::string, std::string> &out)
{
const PropertyMap& properties = mGlobalSettings.listProperties();
file.close();
for (PropertyMap::const_iterator it = properties.begin(); it != properties.end(); ++it)
{
out[it->first] = retrieveValue<StringValue>(mGlobalSettings.getProperty(it->first), NULL).get();
}
}
void Factory::listConfigurationSettings(const std::string& name, std::map<std::string, std::string> &out)
{
const PropertyMap& properties = mConfigurations[name].listProperties();
for (PropertyMap::const_iterator it = properties.begin(); it != properties.end(); ++it)
{
out[it->first] = retrieveValue<StringValue>(mConfigurations[name].getProperty(it->first), NULL).get();
}
}
void Factory::listConfigurationNames(std::vector<std::string> &out)
{
for (ConfigurationMap::const_iterator it = mConfigurations.begin(); it != mConfigurations.end(); ++it)
{
out.push_back(it->first);
}
}
void Factory::listShaderSets(std::vector<std::string> &out)
{
for (ShaderSetMap::const_iterator it = mShaderSets.begin(); it != mShaderSets.end(); ++it)
{
out.push_back(it->first);
}
}
void Factory::_ensureMaterial(const std::string& name, const std::string& configuration)
@ -630,4 +651,146 @@ namespace sh
}
return ret;
}
bool Factory::reloadShaders()
{
mShaderSets.clear();
notifyConfigurationChanged();
bool removeBinaryCache = false;
ScriptLoader shaderSetLoader(".shaderset");
ScriptLoader::loadAllFiles (&shaderSetLoader, mPlatform->getBasePath());
std::map <std::string, ScriptNode*> nodes = shaderSetLoader.getAllConfigScripts();
for (std::map <std::string, ScriptNode*>::const_iterator it = nodes.begin();
it != nodes.end(); ++it)
{
if (!(it->second->getName() == "shader_set"))
{
std::cerr << "sh::Factory: Warning: Unsupported root node type \"" << it->second->getName() << "\" for file type .shaderset" << std::endl;
break;
}
if (!it->second->findChild("profiles_cg"))
throw std::runtime_error ("missing \"profiles_cg\" field for \"" + it->first + "\"");
if (!it->second->findChild("profiles_hlsl"))
throw std::runtime_error ("missing \"profiles_hlsl\" field for \"" + it->first + "\"");
if (!it->second->findChild("source"))
throw std::runtime_error ("missing \"source\" field for \"" + it->first + "\"");
if (!it->second->findChild("type"))
throw std::runtime_error ("missing \"type\" field for \"" + it->first + "\"");
std::vector<std::string> profiles_cg;
boost::split (profiles_cg, it->second->findChild("profiles_cg")->getValue(), boost::is_any_of(" "));
std::string cg_profile;
for (std::vector<std::string>::iterator it2 = profiles_cg.begin(); it2 != profiles_cg.end(); ++it2)
{
if (mPlatform->isProfileSupported(*it2))
{
cg_profile = *it2;
break;
}
}
std::vector<std::string> profiles_hlsl;
boost::split (profiles_hlsl, it->second->findChild("profiles_hlsl")->getValue(), boost::is_any_of(" "));
std::string hlsl_profile;
for (std::vector<std::string>::iterator it2 = profiles_hlsl.begin(); it2 != profiles_hlsl.end(); ++it2)
{
if (mPlatform->isProfileSupported(*it2))
{
hlsl_profile = *it2;
break;
}
}
std::string sourceAbsolute = mPlatform->getBasePath() + "/" + it->second->findChild("source")->getValue();
std::string sourceRelative = it->second->findChild("source")->getValue();
ShaderSet newSet (it->second->findChild("type")->getValue(), cg_profile, hlsl_profile,
sourceAbsolute,
mPlatform->getBasePath(),
it->first,
&mGlobalSettings);
int lastModified = boost::filesystem::last_write_time (boost::filesystem::path(sourceAbsolute));
mShadersLastModifiedNew[sourceRelative] = lastModified;
if (mShadersLastModified.find(sourceRelative) != mShadersLastModified.end())
{
if (mShadersLastModified[sourceRelative] != lastModified)
{
// delete any outdated shaders based on this shader set
if (removeCache (it->first))
removeBinaryCache = true;
mShadersLastModified[sourceRelative] = lastModified;
}
}
else
{
// if we get here, this is either the first run or a new shader file was added
// in both cases we can safely delete
if (removeCache (it->first))
removeBinaryCache = true;
mShadersLastModified[sourceRelative] = lastModified;
}
mShaderSets.insert(std::make_pair(it->first, newSet));
}
return removeBinaryCache;
}
void Factory::doMonitorShaderFiles()
{
bool reload=false;
ScriptLoader shaderSetLoader(".shaderset");
ScriptLoader::loadAllFiles (&shaderSetLoader, mPlatform->getBasePath());
std::map <std::string, ScriptNode*> nodes = shaderSetLoader.getAllConfigScripts();
for (std::map <std::string, ScriptNode*>::const_iterator it = nodes.begin();
it != nodes.end(); ++it)
{
std::string sourceAbsolute = mPlatform->getBasePath() + "/" + it->second->findChild("source")->getValue();
std::string sourceRelative = it->second->findChild("source")->getValue();
int lastModified = boost::filesystem::last_write_time (boost::filesystem::path(sourceAbsolute));
if (mShadersLastModified.find(sourceRelative) != mShadersLastModified.end())
{
if (mShadersLastModified[sourceRelative] != lastModified)
{
reload=true;
break;
}
}
}
if (reload)
reloadShaders();
}
void Factory::logError(const std::string &msg)
{
mErrorLog << msg << '\n';
}
std::string Factory::getErrorLog()
{
std::string errors = mErrorLog.str();
mErrorLog.str("");
return errors;
}
void Factory::unloadUnreferencedMaterials()
{
for (MaterialMap::iterator it = mMaterials.begin(); it != mMaterials.end(); ++it)
{
if (it->second.getMaterial()->isUnreferenced())
it->second.destroyAll();
}
}
void Configuration::save(const std::string& name, std::ofstream &stream)
{
stream << "configuration " << name << '\n';
stream << "{\n";
PropertySetGet::save(stream, "\t");
stream << "}\n";
}
}

@ -3,6 +3,7 @@
#include <map>
#include <string>
#include <sstream>
#include "MaterialInstance.hpp"
#include "ShaderSet.hpp"
@ -12,9 +13,21 @@ namespace sh
{
class Platform;
class Configuration : public PropertySetGet
{
public:
void setSourceFile (const std::string& file) { mSourceFile = file ; }
std::string getSourceFile () { return mSourceFile; }
void save(const std::string& name, std::ofstream &stream);
private:
std::string mSourceFile;
};
typedef std::map<std::string, MaterialInstance> MaterialMap;
typedef std::map<std::string, ShaderSet> ShaderSetMap;
typedef std::map<std::string, PropertySetGet> ConfigurationMap;
typedef std::map<std::string, Configuration> ConfigurationMap;
typedef std::map<int, PropertySetGet> LodConfigurationMap;
typedef std::map<std::string, int> LastModifiedMap;
@ -81,8 +94,8 @@ namespace sh
/// Get a MaterialInstance by name
MaterialInstance* getMaterialInstance (const std::string& name);
/// Register a configuration, which can then be used by switching the active material scheme
void registerConfiguration (const std::string& name, PropertySetGet configuration);
/// Create a configuration, which can then be altered by using Factory::getConfiguration
void createConfiguration (const std::string& name);
/// Register a lod configuration, which can then be used by setting up lod distance values for the material \n
/// 0 refers to highest lod, so use 1 or higher as index parameter
@ -125,8 +138,48 @@ namespace sh
/// \note The default is off (no cache reading)
void setReadMicrocodeCache(bool read) { mReadMicrocodeCache = read; }
/// Saves all the materials that were initially loaded from the file with this name
void saveMaterials (const std::string& filename);
/// Lists all materials currently registered with the factory. Whether they are
/// loaded or not does not matter.
void listMaterials (std::vector<std::string>& out);
/// Lists current name & value of all global settings.
void listGlobalSettings (std::map<std::string, std::string>& out);
/// Lists configuration names.
void listConfigurationNames (std::vector<std::string>& out);
/// Lists current name & value of settings for a given configuration.
void listConfigurationSettings (const std::string& name, std::map<std::string, std::string>& out);
/// Lists shader sets.
void listShaderSets (std::vector<std::string>& out);
/// \note This only works if microcode caching is disabled, as there is currently no way to remove the cache
/// through the Ogre API. Luckily, this is already fixed in Ogre 1.9.
bool reloadShaders();
/// Calls reloadShaders() if shader files have been modified since the last reload.
/// \note This only works if microcode caching is disabled, as there is currently no way to remove the cache
/// through the Ogre API. Luckily, this is already fixed in Ogre 1.9.
void doMonitorShaderFiles();
/// Unloads all materials that are currently not referenced. This will not unload the textures themselves,
/// but it will let go of the SharedPtr's to the textures, so that you may unload them if you so desire. \n
/// A good time to call this would be after a new level has been loaded, but just calling it occasionally after a period
/// of time should work just fine too.
void unloadUnreferencedMaterials();
void destroyConfiguration (const std::string& name);
void notifyConfigurationChanged();
/// Saves all materials and configurations, by default to the file they were loaded from.
/// If you wish to save them elsewhere, use setSourceFile first.
void saveAll ();
/// Returns the error log as a string, then clears it.
/// Note: Errors are also written to the standard error output, or thrown if they are fatal.
std::string getErrorLog ();
static Factory& getInstance();
///< Return instance of this class.
@ -137,11 +190,13 @@ namespace sh
/// You will probably never have to use this.
void _ensureMaterial(const std::string& name, const std::string& configuration);
Configuration* getConfiguration (const std::string& name);
private:
MaterialInstance* requestMaterial (const std::string& name, const std::string& configuration, unsigned short lodIndex);
ShaderSet* getShaderSet (const std::string& name);
PropertySetGet* getConfiguration (const std::string& name);
Platform* getPlatform ();
PropertySetGet* getCurrentGlobalSettings();
@ -163,6 +218,8 @@ namespace sh
std::map<TextureUnitState*, std::string> mTextureAliasInstances;
void logError (const std::string& msg);
friend class Platform;
friend class MaterialInstance;
friend class ShaderInstance;
@ -179,6 +236,7 @@ namespace sh
bool mWriteMicrocodeCache;
bool mReadSourceCache;
bool mWriteSourceCache;
std::stringstream mErrorLog;
MaterialMap mMaterials;
ShaderSetMap mShaderSets;

@ -1,6 +1,7 @@
#include "MaterialInstance.hpp"
#include <stdexcept>
#include <iostream>
#include "Factory.hpp"
#include "ShaderSet.hpp"
@ -12,6 +13,7 @@ namespace sh
, mShadersEnabled(true)
, mFactory(f)
, mListener(NULL)
, mFailedToCreate(false)
{
}
@ -46,6 +48,7 @@ namespace sh
return;
mMaterial->removeAll();
mTexUnits.clear();
mFailedToCreate = false;
}
void MaterialInstance::setProperty (const std::string& name, PropertyValuePtr value)
@ -54,118 +57,136 @@ namespace sh
destroyAll(); // trigger updates
}
void MaterialInstance::createForConfiguration (const std::string& configuration, unsigned short lodIndex)
bool MaterialInstance::createForConfiguration (const std::string& configuration, unsigned short lodIndex)
{
bool res = mMaterial->createConfiguration(configuration, lodIndex);
if (!res)
return; // listener was false positive
if (mListener)
mListener->requestedConfiguration (this, configuration);
mFactory->setActiveConfiguration (configuration);
mFactory->setActiveLodLevel (lodIndex);
bool allowFixedFunction = true;
if (!mShadersEnabled && hasProperty("allow_fixed_function"))
{
allowFixedFunction = retrieveValue<BooleanValue>(getProperty("allow_fixed_function"), NULL).get();
}
if (mFailedToCreate)
return false;
try{
mMaterial->ensureLoaded();
bool res = mMaterial->createConfiguration(configuration, lodIndex);
if (!res)
return false; // listener was false positive
if (mListener)
mListener->requestedConfiguration (this, configuration);
mFactory->setActiveConfiguration (configuration);
mFactory->setActiveLodLevel (lodIndex);
bool allowFixedFunction = true;
if (!mShadersEnabled && hasProperty("allow_fixed_function"))
{
allowFixedFunction = retrieveValue<BooleanValue>(getProperty("allow_fixed_function"), NULL).get();
}
bool useShaders = mShadersEnabled || !allowFixedFunction;
bool useShaders = mShadersEnabled || !allowFixedFunction;
// get passes of the top-most parent
PassVector passes = getPasses();
if (passes.size() == 0)
throw std::runtime_error ("material \"" + mName + "\" does not have any passes");
// get passes of the top-most parent
PassVector* passes = getParentPasses();
if (passes->empty())
throw std::runtime_error ("material \"" + mName + "\" does not have any passes");
for (PassVector::iterator it = passes.begin(); it != passes.end(); ++it)
{
boost::shared_ptr<Pass> pass = mMaterial->createPass (configuration, lodIndex);
it->copyAll (pass.get(), this);
for (PassVector::iterator it = passes->begin(); it != passes->end(); ++it)
{
boost::shared_ptr<Pass> pass = mMaterial->createPass (configuration, lodIndex);
it->copyAll (pass.get(), this);
// texture samplers used in the shaders
std::vector<std::string> usedTextureSamplersVertex;
std::vector<std::string> usedTextureSamplersFragment;
// texture samplers used in the shaders
std::vector<std::string> usedTextureSamplersVertex;
std::vector<std::string> usedTextureSamplersFragment;
PropertySetGet* context = this;
PropertySetGet* context = this;
// create or retrieve shaders
bool hasVertex = it->hasProperty("vertex_program");
bool hasFragment = it->hasProperty("fragment_program");
if (useShaders)
{
it->setContext(context);
it->mShaderProperties.setContext(context);
if (hasVertex)
// create or retrieve shaders
bool hasVertex = it->hasProperty("vertex_program")
&& !retrieveValue<StringValue>(it->getProperty("vertex_program"), context).get().empty();
bool hasFragment = it->hasProperty("fragment_program")
&& !retrieveValue<StringValue>(it->getProperty("fragment_program"), context).get().empty();
if (useShaders)
{
ShaderSet* vertex = mFactory->getShaderSet(retrieveValue<StringValue>(it->getProperty("vertex_program"), context).get());
ShaderInstance* v = vertex->getInstance(&it->mShaderProperties);
if (v)
it->setContext(context);
it->mShaderProperties.setContext(context);
if (hasVertex)
{
pass->assignProgram (GPT_Vertex, v->getName());
v->setUniformParameters (pass, &it->mShaderProperties);
std::vector<std::string> sharedParams = v->getSharedParameters ();
for (std::vector<std::string>::iterator it = sharedParams.begin(); it != sharedParams.end(); ++it)
ShaderSet* vertex = mFactory->getShaderSet(retrieveValue<StringValue>(it->getProperty("vertex_program"), context).get());
ShaderInstance* v = vertex->getInstance(&it->mShaderProperties);
if (v)
{
pass->addSharedParameter (GPT_Vertex, *it);
}
pass->assignProgram (GPT_Vertex, v->getName());
v->setUniformParameters (pass, &it->mShaderProperties);
std::vector<std::string> sharedParams = v->getSharedParameters ();
for (std::vector<std::string>::iterator it2 = sharedParams.begin(); it2 != sharedParams.end(); ++it2)
{
pass->addSharedParameter (GPT_Vertex, *it2);
}
std::vector<std::string> vector = v->getUsedSamplers ();
usedTextureSamplersVertex.insert(usedTextureSamplersVertex.end(), vector.begin(), vector.end());
std::vector<std::string> vector = v->getUsedSamplers ();
usedTextureSamplersVertex.insert(usedTextureSamplersVertex.end(), vector.begin(), vector.end());
}
}
}
if (hasFragment)
{
ShaderSet* fragment = mFactory->getShaderSet(retrieveValue<StringValue>(it->getProperty("fragment_program"), context).get());
ShaderInstance* f = fragment->getInstance(&it->mShaderProperties);
if (f)
if (hasFragment)
{
pass->assignProgram (GPT_Fragment, f->getName());
f->setUniformParameters (pass, &it->mShaderProperties);
std::vector<std::string> sharedParams = f->getSharedParameters ();
for (std::vector<std::string>::iterator it = sharedParams.begin(); it != sharedParams.end(); ++it)
ShaderSet* fragment = mFactory->getShaderSet(retrieveValue<StringValue>(it->getProperty("fragment_program"), context).get());
ShaderInstance* f = fragment->getInstance(&it->mShaderProperties);
if (f)
{
pass->addSharedParameter (GPT_Fragment, *it);
}
pass->assignProgram (GPT_Fragment, f->getName());
f->setUniformParameters (pass, &it->mShaderProperties);
std::vector<std::string> vector = f->getUsedSamplers ();
usedTextureSamplersFragment.insert(usedTextureSamplersFragment.end(), vector.begin(), vector.end());
std::vector<std::string> sharedParams = f->getSharedParameters ();
for (std::vector<std::string>::iterator it2 = sharedParams.begin(); it2 != sharedParams.end(); ++it2)
{
pass->addSharedParameter (GPT_Fragment, *it2);
}
std::vector<std::string> vector = f->getUsedSamplers ();
usedTextureSamplersFragment.insert(usedTextureSamplersFragment.end(), vector.begin(), vector.end());
}
}
}
}
// create texture units
std::vector<MaterialInstanceTextureUnit> texUnits = it->getTexUnits();
int i=0;
for (std::vector<MaterialInstanceTextureUnit>::iterator texIt = texUnits.begin(); texIt != texUnits.end(); ++texIt )
{
// only create those that are needed by the shader, OR those marked to be created in fixed function pipeline if shaders are disabled
bool foundVertex = std::find(usedTextureSamplersVertex.begin(), usedTextureSamplersVertex.end(), texIt->getName()) != usedTextureSamplersVertex.end();
bool foundFragment = std::find(usedTextureSamplersFragment.begin(), usedTextureSamplersFragment.end(), texIt->getName()) != usedTextureSamplersFragment.end();
if ( (foundVertex || foundFragment)
|| (((!useShaders || (!hasVertex || !hasFragment)) && allowFixedFunction) && texIt->hasProperty("create_in_ffp") && retrieveValue<BooleanValue>(texIt->getProperty("create_in_ffp"), this).get()))
// create texture units
std::vector<MaterialInstanceTextureUnit>* texUnits = &it->mTexUnits;
int i=0;
for (std::vector<MaterialInstanceTextureUnit>::iterator texIt = texUnits->begin(); texIt != texUnits->end(); ++texIt )
{
boost::shared_ptr<TextureUnitState> texUnit = pass->createTextureUnitState ();
texIt->copyAll (texUnit.get(), context);
// only create those that are needed by the shader, OR those marked to be created in fixed function pipeline if shaders are disabled
bool foundVertex = std::find(usedTextureSamplersVertex.begin(), usedTextureSamplersVertex.end(), texIt->getName()) != usedTextureSamplersVertex.end();
bool foundFragment = std::find(usedTextureSamplersFragment.begin(), usedTextureSamplersFragment.end(), texIt->getName()) != usedTextureSamplersFragment.end();
if ( (foundVertex || foundFragment)
|| (((!useShaders || (!hasVertex || !hasFragment)) && allowFixedFunction) && texIt->hasProperty("create_in_ffp") && retrieveValue<BooleanValue>(texIt->getProperty("create_in_ffp"), this).get()))
{
boost::shared_ptr<TextureUnitState> texUnit = pass->createTextureUnitState (texIt->getName());
texIt->copyAll (texUnit.get(), context);
mTexUnits.push_back(texUnit);
mTexUnits.push_back(texUnit);
// set texture unit indices (required by GLSL)
if (useShaders && ((hasVertex && foundVertex) || (hasFragment && foundFragment)) && mFactory->getCurrentLanguage () == Language_GLSL)
{
pass->setTextureUnitIndex (foundVertex ? GPT_Vertex : GPT_Fragment, texIt->getName(), i);
// set texture unit indices (required by GLSL)
if (useShaders && ((hasVertex && foundVertex) || (hasFragment && foundFragment)) && mFactory->getCurrentLanguage () == Language_GLSL)
{
pass->setTextureUnitIndex (foundVertex ? GPT_Vertex : GPT_Fragment, texIt->getName(), i);
++i;
++i;
}
}
}
}
}
if (mListener)
mListener->createdConfiguration (this, configuration);
if (mListener)
mListener->createdConfiguration (this, configuration);
return true;
} catch (std::runtime_error& e)
{
destroyAll();
mFailedToCreate = true;
std::stringstream msg;
msg << "Error while creating material " << mName << ": " << e.what();
std::cerr << msg.str() << std::endl;
mFactory->logError(msg.str());
return false;
}
}
Material* MaterialInstance::getMaterial ()
@ -180,12 +201,23 @@ namespace sh
return &mPasses.back();
}
PassVector MaterialInstance::getPasses()
void MaterialInstance::deletePass(unsigned int index)
{
assert(mPasses.size() > index);
mPasses.erase(mPasses.begin()+index);
}
PassVector* MaterialInstance::getParentPasses()
{
if (mParent)
return static_cast<MaterialInstance*>(mParent)->getPasses();
return static_cast<MaterialInstance*>(mParent)->getParentPasses();
else
return mPasses;
return &mPasses;
}
PassVector* MaterialInstance::getPasses()
{
return &mPasses;
}
void MaterialInstance::setShadersEnabled (bool enabled)
@ -206,7 +238,7 @@ namespace sh
if (mParent)
{
stream << "\t" << static_cast<MaterialInstance*>(mParent)->getName() << "\n";
stream << "\t" << "parent " << static_cast<MaterialInstance*>(mParent)->getName() << "\n";
}
const PropertyMap& properties = listProperties ();
@ -215,6 +247,14 @@ namespace sh
stream << "\t" << it->first << " " << retrieveValue<StringValue>(getProperty(it->first), NULL).get() << "\n";
}
for (PassVector::iterator it = mPasses.begin(); it != mPasses.end(); ++it)
{
stream << "\tpass" << '\n';
stream << "\t{" << '\n';
it->save(stream);
stream << "\t}" << '\n';
}
stream << "}\n";
}
}

@ -41,8 +41,12 @@ namespace sh
MaterialInstance (const std::string& name, Factory* f);
virtual ~MaterialInstance ();
PassVector* getParentPasses(); ///< gets the passes of the top-most parent
PassVector* getPasses(); ///< get our passes (for derived materials, none)
MaterialInstancePass* createPass ();
PassVector getPasses(); ///< gets the passes of the top-most parent
void deletePass (unsigned int index);
/// @attention Because the backend material passes are created on demand, the returned material here might not contain anything yet!
/// The only place where you should use this method, is for the MaterialInstance given by the MaterialListener::materialCreated event!
@ -55,25 +59,25 @@ namespace sh
virtual void setProperty (const std::string& name, PropertyValuePtr value);
void setSourceFile(const std::string& sourceFile) { mSourceFile = sourceFile; }
std::string getSourceFile() { return mSourceFile; }
///< get the name of the file this material was read from, or empty if it was created dynamically by code
private:
void setParentInstance (const std::string& name);
std::string getParentInstance ();
void create (Platform* platform);
void createForConfiguration (const std::string& configuration, unsigned short lodIndex);
bool createForConfiguration (const std::string& configuration, unsigned short lodIndex);
void destroyAll ();
void setShadersEnabled (bool enabled);
void setSourceFile(const std::string& sourceFile) { mSourceFile = sourceFile; }
std::string getSourceFile() { return mSourceFile; }
///< get the name of the file this material was read from, or empty if it was created dynamically by code
void save (std::ofstream& stream);
///< this will only save the properties, not the passes and texture units, and as such
/// is only intended to be used for derived materials
bool mFailedToCreate;
friend class Factory;

@ -1,5 +1,7 @@
#include "MaterialInstancePass.hpp"
#include <fstream>
namespace sh
{
@ -9,8 +11,25 @@ namespace sh
return &mTexUnits.back();
}
std::vector <MaterialInstanceTextureUnit> MaterialInstancePass::getTexUnits ()
void MaterialInstancePass::save(std::ofstream &stream)
{
return mTexUnits;
if (mShaderProperties.listProperties().size())
{
stream << "\t\t" << "shader_properties" << '\n';
stream << "\t\t{\n";
mShaderProperties.save(stream, "\t\t\t");
stream << "\t\t}\n";
}
PropertySetGet::save(stream, "\t\t");
for (std::vector <MaterialInstanceTextureUnit>::iterator it = mTexUnits.begin();
it != mTexUnits.end(); ++it)
{
stream << "\t\ttexture_unit " << it->getName() << '\n';
stream << "\t\t{\n";
it->save(stream, "\t\t\t");
stream << "\t\t}\n";
}
}
}

@ -18,10 +18,10 @@ namespace sh
public:
MaterialInstanceTextureUnit* createTextureUnit (const std::string& name);
void save (std::ofstream& stream);
PropertySetGet mShaderProperties;
std::vector <MaterialInstanceTextureUnit> getTexUnits ();
private:
std::vector <MaterialInstanceTextureUnit> mTexUnits;
};
}

@ -18,6 +18,7 @@ namespace sh
public:
MaterialInstanceTextureUnit (const std::string& name);
std::string getName() const;
void setName (const std::string& name) { mName = name; }
private:
std::string mName;
};

@ -9,7 +9,7 @@ namespace sh
Platform::Platform (const std::string& basePath)
: mBasePath(basePath)
, mCacheFolder("./")
, mShaderCachingEnabled(false)
, mFactory(NULL)
{
}
@ -57,11 +57,6 @@ namespace sh
mCacheFolder = folder;
}
void Platform::setShaderCachingEnabled (bool enabled)
{
mShaderCachingEnabled = enabled;
}
std::string Platform::getCacheFolder() const
{
return mCacheFolder;

@ -24,6 +24,7 @@ namespace sh
class GpuProgram
{
public:
virtual ~GpuProgram() {}
virtual bool getSupported () = 0; ///< @return true if the compilation was successful
/// @param name name of the uniform in the shader
@ -35,8 +36,7 @@ namespace sh
class TextureUnitState : public PropertySet
{
public:
virtual ~TextureUnitState();
virtual ~TextureUnitState();
virtual void setTextureName (const std::string& textureName) = 0;
protected:
@ -46,7 +46,7 @@ namespace sh
class Pass : public PropertySet
{
public:
virtual boost::shared_ptr<TextureUnitState> createTextureUnitState () = 0;
virtual boost::shared_ptr<TextureUnitState> createTextureUnitState (const std::string& name) = 0;
virtual void assignProgram (GpuProgramType type, const std::string& name) = 0;
/// @param type gpu program type
@ -68,6 +68,9 @@ namespace sh
virtual bool createConfiguration (const std::string& name, unsigned short lodIndex) = 0; ///< @return false if already exists
virtual void removeAll () = 0; ///< remove all configurations
virtual bool isUnreferenced() = 0;
virtual void ensureLoaded() = 0;
virtual void setLodLevels (const std::string& lodLevels) = 0;
virtual void setShadowCasterMaterial (const std::string& name) = 0;
@ -79,8 +82,6 @@ namespace sh
Platform (const std::string& basePath);
virtual ~Platform ();
void setShaderCachingEnabled (bool enabled);
/// set the folder to use for shader caching
void setCacheFolder (const std::string& folder);
@ -93,6 +94,8 @@ namespace sh
const std::string& name, const std::string& profile,
const std::string& source, Language lang) = 0;
virtual void destroyGpuProgram (const std::string& name) = 0;
virtual void setSharedParameter (const std::string& name, PropertyValuePtr value) = 0;
virtual bool isProfileSupported (const std::string& profile) = 0;
@ -105,6 +108,7 @@ namespace sh
friend class Factory;
friend class MaterialInstance;
friend class ShaderInstance;
friend class ShaderSet;
protected:
/**
@ -131,9 +135,6 @@ namespace sh
std::string mCacheFolder;
Factory* mFactory;
protected:
bool mShaderCachingEnabled;
private:
void setFactory (Factory* factory);

@ -6,6 +6,8 @@
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <fstream>
namespace sh
{
@ -39,8 +41,9 @@ namespace sh
mValue = false;
else
{
std::cerr << "sh::BooleanValue: Warning: Unrecognized value \"" << in << "\" for property value of type BooleanValue" << std::endl;
mValue = false;
std::stringstream msg;
msg << "sh::BooleanValue: Warning: Unrecognized value \"" << in << "\" for property value of type BooleanValue";
throw std::runtime_error(msg.str());
}
}
@ -183,12 +186,16 @@ namespace sh
void PropertySet::setProperty (const std::string& name, PropertyValuePtr &value, PropertySetGet* context)
{
if (!setPropertyOverride (name, value, context))
std::cerr << "sh::PropertySet: Warning: No match for property with name '" << name << "'" << std::endl;
{
std::stringstream msg;
msg << "sh::PropertySet: Warning: No match for property with name '" << name << "'";
throw std::runtime_error(msg.str());
}
}
bool PropertySet::setPropertyOverride (const std::string& name, PropertyValuePtr &value, PropertySetGet* context)
{
// if we got here, none of the sub-classes was able to make use of the property
// if we got here, none of the sub-classes were able to make use of the property
return false;
}
@ -226,6 +233,11 @@ namespace sh
mProperties [name] = value;
}
void PropertySetGet::deleteProperty(const std::string &name)
{
mProperties.erase(name);
}
PropertyValuePtr& PropertySetGet::getProperty (const std::string& name)
{
bool found = (mProperties.find(name) != mProperties.end());
@ -241,7 +253,7 @@ namespace sh
return mProperties[name];
}
bool PropertySetGet::hasProperty (const std::string& name)
bool PropertySetGet::hasProperty (const std::string& name) const
{
bool found = (mProperties.find(name) != mProperties.end());
@ -256,13 +268,35 @@ namespace sh
return true;
}
void PropertySetGet::copyAll (PropertySet* target, PropertySetGet* context)
void PropertySetGet::copyAll (PropertySet* target, PropertySetGet* context, bool copyParent)
{
if (mParent)
if (mParent && copyParent)
mParent->copyAll (target, context);
for (PropertyMap::iterator it = mProperties.begin(); it != mProperties.end(); ++it)
{
target->setProperty(it->first, it->second, context);
}
}
void PropertySetGet::copyAll (PropertySetGet* target, PropertySetGet* context, bool copyParent)
{
if (mParent && copyParent)
mParent->copyAll (target, context);
for (PropertyMap::iterator it = mProperties.begin(); it != mProperties.end(); ++it)
{
std::string val = retrieveValue<StringValue>(it->second, this).get();
target->setProperty(it->first, sh::makeProperty(new sh::StringValue(val)));
}
}
void PropertySetGet::save(std::ofstream &stream, const std::string& indentation)
{
for (PropertyMap::iterator it = mProperties.begin(); it != mProperties.end(); ++it)
{
if (typeid( *(it->second) ) == typeid(LinkedValue))
stream << indentation << it->first << " " << "$" + static_cast<LinkedValue*>(&*(it->second))->_getStringValue() << '\n';
else
stream << indentation << it->first << " " << retrieveValue<StringValue>(it->second, this).get() << '\n';
}
}
}

@ -133,6 +133,7 @@ namespace sh
class PropertySet
{
public:
virtual ~PropertySet() {}
void setProperty (const std::string& name, PropertyValuePtr& value, PropertySetGet* context);
protected:
@ -151,18 +152,26 @@ namespace sh
virtual ~PropertySetGet() {}
void copyAll (PropertySet* target, PropertySetGet* context); ///< call setProperty for each property/value pair stored in \a this
void save (std::ofstream& stream, const std::string& indentation);
void copyAll (PropertySet* target, PropertySetGet* context, bool copyParent=true);
///< call setProperty for each property/value pair stored in \a this
void copyAll (PropertySetGet* target, PropertySetGet* context, bool copyParent=true);
///< call setProperty for each property/value pair stored in \a this
void setParent (PropertySetGet* parent);
PropertySetGet* getParent () { return mParent; }
void setContext (PropertySetGet* context);
PropertySetGet* getContext();
virtual void setProperty (const std::string& name, PropertyValuePtr value);
PropertyValuePtr& getProperty (const std::string& name);
void deleteProperty (const std::string& name);
const PropertyMap& listProperties() { return mProperties; }
bool hasProperty (const std::string& name);
bool hasProperty (const std::string& name) const;
private:
PropertyMap mProperties;
@ -225,7 +234,7 @@ namespace sh
template <typename T>
/// Create a property of any type
/// Example: sh::makeProperty\<sh::Vector4\> (new sh::Vector4(1, 1, 1, 1))
/// Example: sh::makeProperty (new sh::Vector4(1, 1, 1, 1))
inline PropertyValuePtr makeProperty (T* p)
{
return PropertyValuePtr ( static_cast<PropertyValue*>(p) );

@ -24,6 +24,10 @@ namespace sh
}
ScriptLoader::ScriptLoader(const std::string& fileEnding)
: mLoadOrder(0)
, mToken(TOKEN_NewLine)
, mLastToken(TOKEN_NewLine)
{
mFileEnding = fileEnding;
}
@ -36,7 +40,7 @@ namespace sh
void ScriptLoader::clearScriptList()
{
std::map <std::string, ScriptNode *>::iterator i;
for (i = m_scriptList.begin(); i != m_scriptList.end(); i++)
for (i = m_scriptList.begin(); i != m_scriptList.end(); ++i)
{
delete i->second;
}
@ -293,7 +297,7 @@ namespace sh
{
//Delete all children
std::vector<ScriptNode*>::iterator i;
for (i = mChildren.begin(); i != mChildren.end(); i++)
for (i = mChildren.begin(); i != mChildren.end(); ++i)
{
ScriptNode *node = *i;
node->mRemoveSelf = false;
@ -323,15 +327,24 @@ namespace sh
ScriptNode *ScriptNode::findChild(const std::string &name, bool recursive)
{
int indx, prevC, nextC;
int indx;
int childCount = (int)mChildren.size();
if (mLastChildFound != -1)
{
//If possible, try checking the nodes neighboring the last successful search
//(often nodes searched for in sequence, so this will boost search speeds).
prevC = mLastChildFound-1; if (prevC < 0) prevC = 0; else if (prevC >= childCount) prevC = childCount-1;
nextC = mLastChildFound+1; if (nextC < 0) nextC = 0; else if (nextC >= childCount) nextC = childCount-1;
int prevC = mLastChildFound-1;
if (prevC < 0)
prevC = 0;
else if (prevC >= childCount)
prevC = childCount-1;
int nextC = mLastChildFound+1;
if (nextC < 0)
nextC = 0;
else if (nextC >= childCount)
nextC = childCount-1;
for (indx = prevC; indx <= nextC; ++indx)
{
ScriptNode *node = mChildren[indx];

@ -37,6 +37,14 @@ namespace sh
parse();
}
ShaderSet::~ShaderSet()
{
for (ShaderInstanceMap::iterator it = mInstances.begin(); it != mInstances.end(); ++it)
{
sh::Factory::getInstance().getPlatform()->destroyGpuProgram(it->second.getName());
}
}
void ShaderSet::parse()
{
std::string currentToken;

@ -21,6 +21,7 @@ namespace sh
public:
ShaderSet (const std::string& type, const std::string& cgProfile, const std::string& hlslProfile, const std::string& sourceFile, const std::string& basePath,
const std::string& name, PropertySetGet* globalSettingsPtr);
~ShaderSet();
/// Retrieve a shader instance for the given properties. \n
/// If a \a ShaderInstance with the same properties exists already, simply returns this instance. \n

@ -15,6 +15,7 @@ namespace sh
OgreMaterial::OgreMaterial (const std::string& name, const std::string& resourceGroup)
: Material()
{
mName = name;
assert (Ogre::MaterialManager::getSingleton().getByName(name).isNull() && "Material already exists");
mMaterial = Ogre::MaterialManager::getSingleton().create (name, resourceGroup);
mMaterial->removeAllTechniques();
@ -22,9 +23,22 @@ namespace sh
mMaterial->compile();
}
void OgreMaterial::ensureLoaded()
{
if (mMaterial.isNull())
mMaterial = Ogre::MaterialManager::getSingleton().getByName(mName);
}
bool OgreMaterial::isUnreferenced()
{
// Resource system internals hold 3 shared pointers, we hold one, so usecount of 4 means unused
return (!mMaterial.isNull() && mMaterial.useCount() <= Ogre::ResourceGroupManager::RESOURCE_SYSTEM_NUM_REFERENCE_COUNTS+1);
}
OgreMaterial::~OgreMaterial()
{
Ogre::MaterialManager::getSingleton().remove(mMaterial->getName());
if (!mMaterial.isNull())
Ogre::MaterialManager::getSingleton().remove(mMaterial->getName());
}
boost::shared_ptr<Pass> OgreMaterial::createPass (const std::string& configuration, unsigned short lodIndex)
@ -34,6 +48,8 @@ namespace sh
void OgreMaterial::removeAll ()
{
if (mMaterial.isNull())
return;
mMaterial->removeAllTechniques();
mMaterial->createTechnique()->setSchemeName (sDefaultTechniqueName);
mMaterial->compile();

@ -18,6 +18,9 @@ namespace sh
virtual boost::shared_ptr<Pass> createPass (const std::string& configuration, unsigned short lodIndex);
virtual bool createConfiguration (const std::string& name, unsigned short lodIndex);
virtual bool isUnreferenced();
virtual void ensureLoaded();
virtual void removeAll ();
Ogre::MaterialPtr getOgreMaterial();
@ -30,6 +33,7 @@ namespace sh
private:
Ogre::MaterialPtr mMaterial;
std::string mName;
std::string mShadowCasterMaterial;
};

@ -20,9 +20,9 @@ namespace sh
mPass = t->createPass();
}
boost::shared_ptr<TextureUnitState> OgrePass::createTextureUnitState ()
boost::shared_ptr<TextureUnitState> OgrePass::createTextureUnitState (const std::string& name)
{
return boost::shared_ptr<TextureUnitState> (new OgreTextureUnitState (this));
return boost::shared_ptr<TextureUnitState> (new OgreTextureUnitState (this, name));
}
void OgrePass::assignProgram (GpuProgramType type, const std::string& name)
@ -105,7 +105,17 @@ namespace sh
else if (type == GPT_Fragment)
params = mPass->getFragmentProgramParameters();
params->addSharedParameters (name);
try
{
params->addSharedParameters (name);
}
catch (Ogre::Exception& e)
{
std::stringstream msg;
msg << "Could not create a shared parameter instance for '"
<< name << "'. Make sure this shared parameter has a value set (via Factory::setSharedParameter)!";
throw std::runtime_error(msg.str());
}
}
void OgrePass::setTextureUnitIndex (int programType, const std::string& name, int index)

@ -14,7 +14,7 @@ namespace sh
public:
OgrePass (OgreMaterial* parent, const std::string& configuration, unsigned short lodIndex);
virtual boost::shared_ptr<TextureUnitState> createTextureUnitState ();
virtual boost::shared_ptr<TextureUnitState> createTextureUnitState (const std::string& name);
virtual void assignProgram (GpuProgramType type, const std::string& name);
Ogre::Pass* getOgrePass();

@ -4,6 +4,7 @@
#include <OgreDataStream.h>
#include <OgreGpuProgramManager.h>
#include <OgreHighLevelGpuProgramManager.h>
#include <OgreRoot.h>
#include "OgreMaterial.hpp"
@ -76,6 +77,11 @@ namespace sh
return boost::shared_ptr<Material> (material);
}
void OgrePlatform::destroyGpuProgram(const std::string &name)
{
Ogre::HighLevelGpuProgramManager::getSingleton().remove(name);
}
boost::shared_ptr<GpuProgram> OgrePlatform::createGpuProgram (
GpuProgramType type,
const std::string& compileArguments,
@ -122,6 +128,7 @@ namespace sh
if (mSharedParameters.find(name) == mSharedParameters.end())
{
params = Ogre::GpuProgramManager::getSingleton().createSharedParameters(name);
Ogre::GpuConstantType type;
if (typeid(*value) == typeid(Vector4))
type = Ogre::GCT_FLOAT4;

@ -47,6 +47,8 @@ namespace sh
const std::string& name, const std::string& profile,
const std::string& source, Language lang);
virtual void destroyGpuProgram (const std::string& name);
virtual void setSharedParameter (const std::string& name, PropertyValuePtr value);
friend class ShaderInstance;

@ -6,10 +6,11 @@
namespace sh
{
OgreTextureUnitState::OgreTextureUnitState (OgrePass* parent)
OgreTextureUnitState::OgreTextureUnitState (OgrePass* parent, const std::string& name)
: TextureUnitState()
{
mTextureUnitState = parent->getOgrePass()->createTextureUnitState("");
mTextureUnitState->setName(name);
}
bool OgreTextureUnitState::setPropertyOverride (const std::string &name, PropertyValuePtr& value, PropertySetGet* context)

@ -12,7 +12,7 @@ namespace sh
class OgreTextureUnitState : public TextureUnitState
{
public:
OgreTextureUnitState (OgrePass* parent);
OgreTextureUnitState (OgrePass* parent, const std::string& name);
virtual void setTextureName (const std::string& textureName);

Loading…
Cancel
Save