Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Feb 27, 2011, 1:05:59 AM (14 years ago)
Author:
landauf
Message:

rewrote parameter changing implementation of Shader
added documentation

Location:
code/branches/usability/src/libraries/tools
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/branches/usability/src/libraries/tools/Shader.cc

    r7972 r7976  
    3030
    3131#include <OgreCompositorManager.h>
    32 #include <OgreCompositorInstance.h>
    33 #include <OgreSceneManager.h>
    3432#include <OgreRoot.h>
    3533#include <OgrePlugin.h>
    36 #include <OgreMaterial.h>
    37 #include <OgreTechnique.h>
    38 #include <OgrePass.h>
    39 #include <OgreMaterialManager.h>
    4034
    4135#include "core/CoreIncludes.h"
     
    4539namespace orxonox
    4640{
    47     bool Shader::bLoadedCgPlugin_s = false;
    48     Shader::MaterialMap Shader::parameters_s;
    49 
     41    /**
     42        @brief Initializes the values and sets the scene manager.
     43    */
    5044    Shader::Shader(Ogre::SceneManager* scenemanager) : compositorInstance_(0)
    5145    {
     
    5549        this->bVisible_ = true;
    5650        this->bLoadCompositor_ = GameMode::showsGraphics();
     51        this->registeredAsListener_ = false;
    5752
    5853        static bool hasCgProgramManager = Shader::hasCgProgramManager();
    59         Shader::bLoadedCgPlugin_s = hasCgProgramManager;
    60 
    61         this->bLoadCompositor_ &= Shader::bLoadedCgPlugin_s;
    62     }
    63 
     54
     55        this->bLoadCompositor_ &= hasCgProgramManager;
     56    }
     57
     58    /**
     59        @brief Removes the compositor and frees the resources.
     60    */
    6461    Shader::~Shader()
    6562    {
     
    6865    }
    6966
     67    /**
     68        @brief Inherited from ViewportEventListener - called if the camera changes.
     69
     70        Since the new camera could be in a different scene, the shader has to make sure
     71        it deactivates or activates itself accordingly.
     72
     73        Additionally the shader has to be turned off and on even if the camera stays in
     74        the same scene to fix a weird behavior of Ogre.
     75    */
    7076    void Shader::cameraChanged(Ogre::Viewport* viewport, Ogre::Camera* oldCamera)
    7177    {
     
    95101    }
    96102
     103    /**
     104        @brief Changes the compositor - default viewport.
     105    */
    97106    void Shader::changedCompositorName()
    98107    {
     
    103112    }
    104113
     114    /**
     115        @brief Changes the compositor.
     116    */
    105117    void Shader::changedCompositorName(Ogre::Viewport* viewport)
    106118    {
     
    108120        {
    109121            assert(viewport);
    110             if (!this->oldcompositorName_.empty())
     122            if (this->compositorInstance_)
    111123            {
     124                // remove the old compositor, remove the listener
    112125                Ogre::CompositorManager::getSingleton().removeCompositor(viewport, this->oldcompositorName_);
     126                this->compositorInstance_->removeListener(this);
    113127                this->compositorInstance_ = 0;
    114128            }
    115129            if (!this->compositorName_.empty())
    116130            {
     131                // add the new compositor
    117132                this->compositorInstance_ = Ogre::CompositorManager::getSingleton().addCompositor(viewport, this->compositorName_);
    118                 if (!this->compositorInstance_)
     133                if (this->compositorInstance_)
     134                {
     135                    // register as listener if required
     136                    if (this->registeredAsListener_)
     137                        this->compositorInstance_->addListener(this);
     138                    // set visibility according to the isVisible() and the camera/viewport
     139                    if (viewport->getCamera())
     140                        Ogre::CompositorManager::getSingleton().setCompositorEnabled(viewport, this->compositorName_, this->isVisible() && viewport->getCamera() && this->scenemanager_ == viewport->getCamera()->getSceneManager());
     141                }
     142                else
    119143                    COUT(2) << "Warning: Couldn't load compositor with name \"" << this->compositorName_ << "\"." << std::endl;
    120                 else if (viewport->getCamera())
    121                     Ogre::CompositorManager::getSingleton().setCompositorEnabled(viewport, this->compositorName_, this->isVisible() && viewport->getCamera() && this->scenemanager_ == viewport->getCamera()->getSceneManager());
    122144            }
    123145            this->oldcompositorName_ = this->compositorName_;
     
    125147    }
    126148
     149    /**
     150        @brief Changes the visibility of the shader. Doesn't free any resources if set to invisible.
     151    */
    127152    void Shader::updateVisibility()
    128153    {
     
    131156    }
    132157
    133     void Shader::setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, float value)
    134     {
    135         if (Shader::_setParameter(material, technique, pass, parameter, value))
    136         {
    137             if (this->compositorInstance_ && this->isVisible())
     158    /**
     159        @brief Defines a new integer value for a given parameter. The parameter will be updated if the compositor is rendered the next time.
     160    */
     161    void Shader::setParameter(size_t technique, size_t pass, const std::string& parameter, int value)
     162    {
     163        ParameterContainer container = {technique, pass, parameter, value, 0.0f, MT_Type::Int};
     164        this->parameters_.push_back(container);
     165        this->addAsListener();
     166    }
     167
     168    /**
     169        @brief Defines a new float value for a given parameter. The parameter will be updated if the compositor is rendered the next time.
     170    */
     171    void Shader::setParameter(size_t technique, size_t pass, const std::string& parameter, float value)
     172    {
     173        ParameterContainer container = {technique, pass, parameter, 0, value, MT_Type::Float};
     174        this->parameters_.push_back(container);
     175        this->addAsListener();
     176    }
     177
     178    /**
     179        @brief Registers the shader as CompositorInstance::Listener at the compositor. Used to change parameters.
     180    */
     181    void Shader::addAsListener()
     182    {
     183        if (!this->registeredAsListener_)
     184        {
     185            this->registeredAsListener_ = true;
     186            if (this->compositorInstance_)
     187                this->compositorInstance_->addListener(this);
     188        }
     189    }
     190
     191    /**
     192        @brief Inherited by Ogre::CompositorInstance::Listener, called whenever the material is rendered. Used to change parameters.
     193    */
     194    void Shader::notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr& materialPtr)
     195    {
     196        // iterate through the list of parameters
     197        for (std::list<ParameterContainer>::iterator it = this->parameters_.begin(); it != this->parameters_.end(); ++it)
     198        {
     199            Ogre::Technique* techniquePtr = materialPtr->getTechnique(it->technique_);
     200            if (techniquePtr)
    138201            {
    139                 Ogre::CompositorManager::getSingleton().setCompositorEnabled(GraphicsManager::getInstance().getViewport(), this->compositorName_, false);
    140                 Ogre::CompositorManager::getSingleton().setCompositorEnabled(GraphicsManager::getInstance().getViewport(), this->compositorName_, true);
    141             }
    142         }
    143     }
    144 
    145     void Shader::setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, int value)
    146     {
    147         if (Shader::_setParameter(material, technique, pass, parameter, value))
    148         {
    149             if (this->compositorInstance_ && this->isVisible())
    150             {
    151                 Ogre::CompositorManager::getSingleton().setCompositorEnabled(GraphicsManager::getInstance().getViewport(), this->compositorName_, false);
    152                 Ogre::CompositorManager::getSingleton().setCompositorEnabled(GraphicsManager::getInstance().getViewport(), this->compositorName_, true);
    153             }
    154         }
    155     }
    156 
    157     /* static */ bool Shader::_setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, float value)
    158     {
    159         ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
    160         if (pointer)
    161         {
    162             if (pointer->first)
    163             {
    164                 if ((*static_cast<float*>(pointer->second)) != value)
     202                Ogre::Pass* passPtr = techniquePtr->getPass(it->pass_);
     203                if (passPtr)
    165204                {
    166                     (*static_cast<float*>(pointer->second)) = value;
    167                     return true;
     205                    // change the value of the parameter depending on its type
     206                    switch (it->valueType_)
     207                    {
     208                        case MT_Type::Int:
     209                            passPtr->getFragmentProgramParameters()->setNamedConstant(it->parameter_, it->valueInt_);
     210                            break;
     211                        case MT_Type::Float:
     212                            passPtr->getFragmentProgramParameters()->setNamedConstant(it->parameter_, it->valueFloat_);
     213                            break;
     214                        default:
     215                            break;
     216                    }
    168217                }
     218                else
     219                    COUT(2) << "Warning: No pass " << it->pass_ << " in technique " << it->technique_ << " in compositor \"" << this->compositorName_ << "\" or pass has no shader." << std::endl;
    169220            }
    170221            else
    171             {
    172                 if ((*static_cast<int*>(pointer->second)) != static_cast<int>(value))
    173                 {
    174                     (*static_cast<int*>(pointer->second)) = static_cast<int>(value);
    175                     return true;
    176                 }
    177             }
    178         }
    179         return false;
    180     }
    181 
    182     /* static */ bool Shader::_setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, int value)
    183     {
    184         ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
    185         if (pointer)
    186         {
    187             if (pointer->first)
    188             {
    189                 if ((*static_cast<float*>(pointer->second)) != static_cast<float>(value))
    190                 {
    191                     (*static_cast<float*>(pointer->second)) = static_cast<float>(value);
    192                     return true;
    193                 }
    194             }
    195             else
    196             {
    197                 if ((*static_cast<int*>(pointer->second)) != value)
    198                 {
    199                     (*static_cast<int*>(pointer->second)) = value;
    200                     return true;
    201                 }
    202             }
    203         }
    204         return false;
    205     }
    206 
    207     /* static */ float Shader::getParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter)
    208     {
    209         ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
    210         if (pointer)
    211         {
    212             if (pointer->first)
    213                 return (*static_cast<float*>(pointer->second));
    214             else
    215                 return static_cast<float>(*static_cast<int*>(pointer->second));
    216         }
    217         else
    218             return 0;
    219     }
    220 
    221     /* static */ bool Shader::getParameterIsFloat(const std::string& material, size_t technique, size_t pass, const std::string& parameter)
    222     {
    223         ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
    224         if (pointer)
    225             return pointer->first;
    226         else
    227             return false;
    228     }
    229 
    230     /* static */ bool Shader::getParameterIsInt(const std::string& material, size_t technique, size_t pass, const std::string& parameter)
    231     {
    232         ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
    233         if (pointer)
    234             return (!pointer->first);
    235         else
    236             return false;
    237     }
    238 
    239     /* static */ Shader::ParameterPointer* Shader::getParameterPointer(const std::string& material, size_t technique, size_t pass, const std::string& parameter)
    240     {
    241         if (!GameMode::showsGraphics() || !Shader::bLoadedCgPlugin_s)
    242             return 0;
    243 
    244         MaterialMap::iterator material_iterator = Shader::parameters_s.find(material);
    245         if (material_iterator != Shader::parameters_s.end())
    246         {
    247             TechniqueVector& technique_vector = material_iterator->second;
    248             if (technique < technique_vector.size())
    249             {
    250                 PassVector& pass_vector = technique_vector[technique];
    251                 if (pass < pass_vector.size())
    252                 {
    253                     ParameterMap& parameter_map = pass_vector[pass];
    254                     ParameterMap::iterator parameter_iterator = parameter_map.find(parameter);
    255 
    256                     if (parameter_iterator != parameter_map.end())
    257                         return (&parameter_iterator->second);
    258                     else
    259                         COUT(2) << "Warning: No shader parameter \"" << parameter << "\" in pass " << pass << " in technique " << technique << " in material \"" << material << "\"." << std::endl;
    260                 }
    261                 else
    262                     COUT(2) << "Warning: No pass " << pass << " in technique " << technique << " in material \"" << material << "\" or pass has no shader." << std::endl;
    263             }
    264             else
    265                 COUT(2) << "Warning: No technique " << technique << " in material \"" << material << "\" or technique has no pass with shader." << std::endl;
    266         }
    267         else
    268         {
    269             bool foundAtLeastOneShaderParameter = false;
    270             Ogre::MaterialManager::ResourceMapIterator iterator = Ogre::MaterialManager::getSingleton().getResourceIterator();
    271             Ogre::Material* material_pointer = 0;
    272 
    273             while (iterator.hasMoreElements())
    274             {
    275                 Ogre::Resource* resource = iterator.getNext().get();
    276                 if (resource->getName() == material)
    277                     material_pointer = (Ogre::Material*)resource;
    278             }
    279 
    280             if (!material_pointer)
    281             {
    282                 COUT(2) << "Warning: No material with name \"" << material << "\" found." << std::endl;
    283                 return 0;
    284             }
    285 
    286             for (unsigned int t = 0; t < material_pointer->getNumTechniques(); ++t)
    287             {
    288                 Ogre::Technique* technique_pointer = material_pointer->getTechnique(t);
    289                 if (!technique_pointer)
    290                     continue;
    291 
    292                 for (unsigned int p = 0; p < technique_pointer->getNumPasses(); ++p)
    293                 {
    294                     Ogre::Pass* pass_pointer = technique_pointer->getPass(p);
    295                     if (!pass_pointer)
    296                         continue;
    297 
    298                     if (!pass_pointer->getFragmentProgramName().empty())
    299                     {
    300                         Ogre::GpuProgramParameters* parameter_pointer = pass_pointer->getFragmentProgramParameters().get();
    301                         if (!parameter_pointer)
    302                             continue;
    303 
    304                         const Ogre::GpuConstantDefinitionMap& constant_definitions = parameter_pointer->getConstantDefinitions().map;
    305                         for (Ogre::GpuConstantDefinitionMap::const_iterator definition_iterator = constant_definitions.begin(); definition_iterator != constant_definitions.end(); ++definition_iterator)
    306                         {
    307                             void* temp = (definition_iterator->second.isFloat())
    308                                             ? static_cast<void*>(parameter_pointer->getFloatPointer(definition_iterator->second.physicalIndex))
    309                                             : static_cast<void*>(parameter_pointer->getIntPointer(definition_iterator->second.physicalIndex));
    310                             ParameterPointer parameter_pointer = ParameterPointer(definition_iterator->second.isFloat(), temp);
    311 
    312                             TechniqueVector& technique_vector = Shader::parameters_s[material];
    313                             technique_vector.resize(technique + 1);
    314                             PassVector& pass_vector = technique_vector[technique];
    315                             pass_vector.resize(pass + 1);
    316                             pass_vector[pass][definition_iterator->first] = parameter_pointer;
    317                             foundAtLeastOneShaderParameter = true;
    318                         }
    319                     }
    320                 }
    321             }
    322 
    323             // recursive call if the material was added to the map
    324             if (foundAtLeastOneShaderParameter)
    325                 return Shader::getParameterPointer(material, technique, pass, parameter);
    326         }
    327         return 0;
    328     }
    329 
     222                COUT(2) << "Warning: No technique " << it->technique_ << " in compositor \"" << this->compositorName_ << "\" or technique has no pass with shader." << std::endl;
     223        }
     224        this->parameters_.clear();
     225    }
     226
     227    /**
     228        @brief Detects if the Cg program manager plugin is active.
     229    */
    330230    /* static */ bool Shader::hasCgProgramManager()
    331231    {
  • code/branches/usability/src/libraries/tools/Shader.h

    r7972 r7976  
    3636#include <vector>
    3737
     38#include <OgreCompositorInstance.h>
     39
    3840#include "util/OgreForwardRefs.h"
    3941#include "core/ViewportEventListener.h"
     
    4143namespace orxonox
    4244{
    43     class _ToolsExport Shader : public ViewportEventListener
     45    /**
     46        @brief Shader is a wrapper class around Ogre::CompositorInstance. It provides some
     47        functions to easily change the visibility and parameters for shader programs.
     48    */
     49    class _ToolsExport Shader : public ViewportEventListener, public Ogre::CompositorInstance::Listener
    4450    {
    45         typedef std::pair<bool, void*>                  ParameterPointer;
    46         typedef std::map<std::string, ParameterPointer> ParameterMap;
    47         typedef std::vector<ParameterMap>               PassVector;
    48         typedef std::vector<PassVector>                 TechniqueVector;
    49         typedef std::map<std::string, TechniqueVector>  MaterialMap;
    50 
    5151        public:
    5252            Shader(Ogre::SceneManager* scenemanager = 0);
    5353            virtual ~Shader();
    5454
     55            /// Defines if the shader is visible or not.
    5556            inline void setVisible(bool bVisible)
    5657            {
     
    6162                }
    6263            }
     64            /// Returns whether or not the shader is visible.
    6365            inline bool isVisible() const
    6466                { return this->bVisible_; }
    6567            void updateVisibility();
    6668
     69            /// Defines the compositor's name (located in a .compositor file).
    6770            inline void setCompositorName(const std::string& name)
    6871            {
     
    7376                }
    7477            }
     78            /// Returns the compositor's name.
    7579            inline const std::string& getCompositorName() const
    7680                { return this->compositorName_; }
     
    7882            void changedCompositorName(Ogre::Viewport* viewport);
    7983
     84            /// Sets the scenemanager (usually provided in the constructor, but can be set later). Shouldn't be changed once it's set.
    8085            inline void setSceneManager(Ogre::SceneManager* scenemanager)
    8186                { this->scenemanager_ = scenemanager; }
     87            /// Returns the scene manager.
    8288            inline Ogre::SceneManager* getSceneManager() const
    8389                { return this->scenemanager_; }
     
    8591            virtual void cameraChanged(Ogre::Viewport* viewport, Ogre::Camera* oldCamera);
    8692
    87             void setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, float value);
    88             void setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, int value);
     93            void setParameter(size_t technique, size_t pass, const std::string& parameter, float value);
     94            void setParameter(size_t technique, size_t pass, const std::string& parameter, int value);
    8995
    90             static bool _setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, float value);
    91             static bool _setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, int value);
    92             static float getParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter);
    93             static bool  getParameterIsFloat(const std::string& material, size_t technique, size_t pass, const std::string& parameter);
    94             static bool  getParameterIsInt  (const std::string& material, size_t technique, size_t pass, const std::string& parameter);
    95             static ParameterPointer* getParameterPointer(const std::string& material, size_t technique, size_t pass, const std::string& parameter);
     96            virtual void notifyMaterialRender(Ogre::uint32 pass_id, Ogre::MaterialPtr& materialPtr);
    9697
    9798        private:
    9899            static bool hasCgProgramManager();
    99100
    100             Ogre::SceneManager* scenemanager_;
    101             Ogre::CompositorInstance* compositorInstance_;
    102             bool bVisible_;
    103             bool bLoadCompositor_;
    104             std::string compositorName_;
    105             std::string oldcompositorName_;
     101            Ogre::SceneManager* scenemanager_;              ///< The scenemanager for which the shader is active
     102            Ogre::CompositorInstance* compositorInstance_;  ///< The compositor instance representing the wrapped compositor
     103            bool bVisible_;                                 ///< True if the shader should be visible
     104            bool bLoadCompositor_;                          ///< True if the compositor should be loaded (usually false if no graphics)
     105            std::string compositorName_;                    ///< The name of the current compositor
     106            std::string oldcompositorName_;                 ///< The name of the previous compositor (used to unregister)
    106107
    107             static MaterialMap parameters_s;
    108             static bool bLoadedCgPlugin_s;
     108        private:
     109            void addAsListener();
     110
     111            /// Helper struct to store parameters for shader programs.
     112            struct ParameterContainer
     113            {
     114                size_t technique_;          ///< The ID of the technique
     115                size_t pass_;               ///< The ID of the pass
     116                std::string parameter_;     ///< The name of the parameter
     117
     118                int valueInt_;              ///< The desired int value of the parameter
     119                float valueFloat_;          ///< The desired float value of the parameter
     120
     121                MT_Type::Value valueType_;  ///< The type of the parameter (currently only int or float)
     122            };
     123
     124            std::list<ParameterContainer> parameters_;  ///< The list of parameters that should be set on the next update
     125            bool registeredAsListener_;                 ///< True if the shader should register itself as listener at the compositor
    109126    };
    110127}
Note: See TracChangeset for help on using the changeset viewer.