Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/objecthierarchy2/src/orxonox/tools/Shader.cc @ 2350

Last change on this file since 2350 was 2350, checked in by landauf, 16 years ago
  • Added support for postprocessing shaders (bloom, motion blur, …). Shaders are only visible if Plugin_CgProgramManager is included in bin/Plugins.cfg.
  • Added class GlobalShader which is visible on all clients and can be activated or deactivated by triggers or other events.
  • Added RadialBlur shader to the SpaceShip's engine. The strength of the RadialBlur depends on the SpaceShip's velocity.
  • Property svn:eol-style set to native
File size: 24.0 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29#include "OrxonoxStableHeaders.h"
30#include "Shader.h"
31
32#include <OgreCompositorManager.h>
33#include <OgreCompositorInstance.h>
34#include <OgreSceneManager.h>
35#include <OgreRoot.h>
36#include <OgrePlugin.h>
37
38#include "core/Core.h"
39#include "core/CoreIncludes.h"
40#include "core/Executor.h"
41#include "GraphicsEngine.h"
42#include "util/Exception.h"
43
44#include <OgreMaterial.h>
45#include <OgreTechnique.h>
46#include <OgrePass.h>
47#include <OgreMaterialManager.h>
48
49namespace orxonox
50{
51    bool Shader::bLoadedCgPlugin_s = false;
52    Shader::MaterialMap Shader::parameters_s;
53
54    Shader::Shader(Ogre::SceneManager* scenemanager)
55    {
56        RegisterObject(Shader);
57
58        this->scenemanager_ = scenemanager;
59        this->compositorInstance_ = 0;
60        this->bVisible_ = true;
61        this->bLoadCompositor_ = Core::showsGraphics() && GraphicsEngine::getInstancePtr();
62        this->bViewportInitialized_ = false;
63        this->compositor_ = "";
64        this->oldcompositor_ = "";
65//        this->parameter_ = 0;
66
67        if (this->bLoadCompositor_ && Ogre::Root::getSingletonPtr())
68        {
69            Shader::bLoadedCgPlugin_s = false;
70            const Ogre::Root::PluginInstanceList& plugins = Ogre::Root::getSingleton().getInstalledPlugins();
71            for (size_t i = 0; i < plugins.size(); ++i)
72            {
73                if (plugins[i]->getName() == "Cg Program Manager")
74                {
75                    Shader::bLoadedCgPlugin_s = true;
76                    break;
77                }
78            }
79        }
80
81        this->bLoadCompositor_ &= Shader::bLoadedCgPlugin_s;
82    }
83
84    Shader::~Shader()
85    {
86/*
87        if (this->isInitialized() && this->bLoadCompositor_ && this->compositor_ != "")
88        {
89            Ogre::Viewport* viewport = GraphicsEngine::getInstance().getViewport();
90            assert(viewport);
91            Ogre::CompositorManager::getSingleton().removeCompositor(viewport, this->compositor_);
92        }
93*/
94    }
95
96    void Shader::setSceneManager(Ogre::SceneManager* scenemanager)
97    {
98        this->scenemanager_ = scenemanager;
99        this->bViewportInitialized_ = false;
100    }
101
102    void Shader::tick(float dt)
103    {
104        if (this->bLoadCompositor_ && !this->bViewportInitialized_ && this->scenemanager_ && this->scenemanager_->getCurrentViewport())
105        {
106            this->bViewportInitialized_ = true;
107            this->updateVisibility();
108        }
109
110/*
111        COUT(0) << std::endl << "GpuPrograms:" << std::endl;
112        Ogre::GpuProgramManager::ResourceMapIterator iterator = Ogre::GpuProgramManager::getSingleton().getResourceIterator();
113        while (iterator.hasMoreElements())
114            COUT(0) << iterator.getNext()->getName() << std::endl;
115*/
116/*
117        Ogre::Resource* resource = Ogre::GpuProgramManager::getSingleton().getByName("Radial_Blur_ps_cg").get();
118        if (resource)
119        {
120            COUT(0) << std::endl << "Resource parameters:" << std::endl;
121            const Ogre::ParameterList& resourceparameters = resource->getParameters();
122            for (size_t i = 0; i < resourceparameters.size(); ++i)
123                COUT(0) << resourceparameters[i].name << std::endl;
124
125            COUT(0) << std::endl << "GpuProgram:" << std::endl;
126            Ogre::GpuProgram* gpuprogram = (Ogre::GpuProgram*)resource;
127            COUT(0) << gpuprogram << std::endl;
128
129            COUT(0) << std::endl << "GpuProgram default parameters:" << std::endl;
130            Ogre::GpuProgramParameters* defaultparams = gpuprogram->getDefaultParameters().get();
131            COUT(0) << defaultparams << std::endl;
132            if (defaultparams)
133            {
134//                defaultparams->setNamedConstant("sampleStrength", 2.0f);
135
136                const Ogre::GpuConstantDefinitionMap& constantdefinitions = defaultparams->getConstantDefinitions().map;
137                for (Ogre::GpuConstantDefinitionMap::const_iterator it = constantdefinitions.begin(); it != constantdefinitions.end(); ++it)
138                    COUT(0) << it->first << " / " << it->second.physicalIndex << " / " << it->second.isFloat() << " / " << (float)((it->second.isFloat()) ? (*defaultparams->getFloatPointer(it->second.physicalIndex)) : (*defaultparams->getIntPointer(it->second.physicalIndex))) << std::endl;
139
140                Ogre::GpuConstantDefinitionMap::const_iterator it = constantdefinitions.find("sampleStrength");
141                if (it != constantdefinitions.end())
142                {
143                    if (it->second.isFloat())
144                    {
145                        COUT(0) << (defaultparams->getFloatPointer(it->second.physicalIndex)) << std::endl;
146                        COUT(0) << (*defaultparams->getFloatPointer(it->second.physicalIndex)) << std::endl;
147                        (*defaultparams->getFloatPointer(it->second.physicalIndex)) = 10.0f;
148                    }
149                    else
150                    {
151                        COUT(0) << (defaultparams->getIntPointer(it->second.physicalIndex)) << std::endl;
152                        COUT(0) << (*defaultparams->getIntPointer(it->second.physicalIndex)) << std::endl;
153                        (*defaultparams->getIntPointer(it->second.physicalIndex)) = 10;
154                    }
155                    // doesn't work because it's "manually loaded":
156                    //
157                    // Ogre: Creating viewport on target 'rtt/166241248', rendering from camera '140', relative
158                    // dimensions L: 0.00 T: 0.00 W: 1.00 H: 1.00 ZOrder: 0
159                    //
160                    // Ogre: WARNING: Texture instance 'CompositorInstanceTexture0' was defined as manually
161                    // loaded, but no manual loader was provided. This Resource will be lost if it has to be
162                    // reloaded.
163                    //
164//                    gpuprogram->reload();
165                }
166
167            }
168
169            COUT(0) << "end" << std::endl;
170        }
171*/
172/*
173        if (this->parameter_ && this->bViewportInitialized_)
174        {
175            (*this->parameter_) += dt;
176
177            if (this->compositorInstance_ && this->isVisible())
178            {
179                this->compositorInstance_->setEnabled(false);
180                this->compositorInstance_->setEnabled(true);
181            }
182        }
183*/
184
185//        this->setParameter("Ogre/Compositor/Radial_Blur", 0, 0, "sampleStrength", Shader::getParameter("Ogre/Compositor/Radial_Blur", 0, 0, "sampleStrength") + dt / 3.0f);
186//        this->setParameter("Ogre/Compositor/Tiling", 0, 0, "NumTiles", Shader::getParameter("Ogre/Compositor/Tiling", 0, 0, "NumTiles") + dt);
187    }
188
189    void Shader::changedCompositor()
190    {
191        if (this->bLoadCompositor_)
192        {
193            Ogre::Viewport* viewport = GraphicsEngine::getInstance().getViewport();
194            assert(viewport);
195            if (this->oldcompositor_ != "")
196            {
197                Ogre::CompositorManager::getSingleton().removeCompositor(viewport, this->oldcompositor_);
198                this->compositorInstance_ = 0;
199            }
200            if (this->compositor_ != "")
201            {
202                this->compositorInstance_ = Ogre::CompositorManager::getSingleton().addCompositor(viewport, this->compositor_);
203                if (!this->compositorInstance_)
204                    COUT(2) << "Warning: Couldn't load compositor with name \"" << this->compositor_ << "\"." << std::endl;
205                else
206                {
207/*
208                    COUT(0) << std::endl << "GpuPrograms:" << std::endl;
209                    Ogre::GpuProgramManager::ResourceMapIterator gpuprogramiterator = Ogre::GpuProgramManager::getSingleton().getResourceIterator();
210                    while (gpuprogramiterator.hasMoreElements())
211                        COUT(0) << gpuprogramiterator.getNext()->getName() << std::endl;
212*/
213/*
214                    COUT(0) << std::endl << "compositor:" << std::endl;
215                    Ogre::Compositor* compositor = this->compositorInstance_->getCompositor();
216                    COUT(0) << compositor << std::endl;
217
218                    if (!compositor)
219                        return;
220
221                    COUT(0) << std::endl << "compositor parameters:" << std::endl;
222                    const Ogre::ParameterList& compparameters = compositor->getParameters();
223                    for (size_t i = 0; i < compparameters.size(); ++i)
224                        COUT(0) << compparameters[i].name << std::endl;
225
226                    COUT(0) << std::endl << "compositor technique:" << std::endl;
227                    Ogre::CompositionTechnique* comptechnique = compositor->getSupportedTechnique(0);
228                    COUT(0) << comptechnique << std::endl;
229
230                    if (!comptechnique)
231                        return;
232
233                    COUT(0) << std::endl << "compositor target pass:" << std::endl;
234                    Ogre::CompositionTargetPass* comptargetpass = comptechnique->getTargetPass(0);
235                    COUT(0) << comptargetpass << std::endl;
236
237                    if (!comptargetpass)
238                        return;
239
240                    COUT(0) << std::endl << "compositor pass:" << std::endl;
241                    Ogre::CompositionPass* comppass = comptargetpass->getPass(0);
242                    COUT(0) << comppass << std::endl;
243
244                    if (!comppass)
245                        return;
246
247                    COUT(0) << std::endl << "material:" << std::endl;
248                    Ogre::Material* material = comppass->getMaterial().get();
249                    COUT(0) << material << std::endl;
250*/
251/*
252                    COUT(0) << std::endl << "Materials:" << std::endl;
253                    Ogre::MaterialManager::ResourceMapIterator iterator = Ogre::MaterialManager::getSingleton().getResourceIterator();
254                    Ogre::Material* material = 0;
255                    while (iterator.hasMoreElements())
256                    {
257                        Ogre::Resource* resource = iterator.getNext().get();
258                        COUT(0) << resource->getName() << std::endl;
259                        if (resource->getName() == "Ogre/Compositor/Radial_Blur")
260                        {
261                            material = (Ogre::Material*)resource;
262                            COUT(0) << "found it!" << std::endl;
263                        }
264                    }
265
266                    if (!material)
267                        return;
268
269                    COUT(0) << std::endl << "material parameters:" << std::endl;
270                    const Ogre::ParameterList& materialparameters = material->getParameters();
271                    for (size_t i = 0; i < materialparameters.size(); ++i)
272                        COUT(0) << materialparameters[i].name << std::endl;
273
274                    COUT(0) << std::endl << "technique:" << std::endl;
275                    Ogre::Technique* technique = material->getTechnique(0);
276                    COUT(0) << technique << std::endl;
277
278                    if (!technique)
279                        return;
280
281                    COUT(0) << std::endl << "pass:" << std::endl;
282                    Ogre::Pass* pass = technique->getPass(0);
283                    COUT(0) << pass << std::endl;
284
285                    if (!pass)
286                        return;
287
288                    COUT(0) << std::endl << "fragment program parameters:" << std::endl;
289                    Ogre::GpuProgramParameters* fragmentparams = pass->getFragmentProgramParameters().get();
290                    COUT(0) << fragmentparams << std::endl;
291                    if (fragmentparams)
292                    {
293                        const Ogre::GpuConstantDefinitionMap& constantdefinitions = fragmentparams->getConstantDefinitions().map;
294                        for (Ogre::GpuConstantDefinitionMap::const_iterator it = constantdefinitions.begin(); it != constantdefinitions.end(); ++it)
295                            COUT(0) << it->first << " / " << it->second.physicalIndex << " / " << it->second.isFloat() << " / " << (float)((it->second.isFloat()) ? (*fragmentparams->getFloatPointer(it->second.physicalIndex)) : (*fragmentparams->getIntPointer(it->second.physicalIndex))) << std::endl;
296
297                        Ogre::GpuConstantDefinitionMap::const_iterator it = constantdefinitions.find("sampleStrength");
298
299                        if (it != constantdefinitions.end())
300                        {
301                            if (it->second.isFloat())
302                            {
303                                COUT(0) << (fragmentparams->getFloatPointer(it->second.physicalIndex)) << std::endl;
304                                COUT(0) << (*fragmentparams->getFloatPointer(it->second.physicalIndex)) << std::endl;
305                                (*fragmentparams->getFloatPointer(it->second.physicalIndex)) = 0.0f;
306                                this->parameter_ = fragmentparams->getFloatPointer(it->second.physicalIndex);
307                            }
308                            else
309                            {
310                                COUT(0) << (fragmentparams->getIntPointer(it->second.physicalIndex)) << std::endl;
311                                COUT(0) << (*fragmentparams->getIntPointer(it->second.physicalIndex)) << std::endl;
312                                (*fragmentparams->getIntPointer(it->second.physicalIndex)) = 0;
313                            }
314                        }
315                    }
316
317                    COUT(0) << std::endl << "fragment program:" << std::endl;
318                    COUT(0) << (&pass->getFragmentProgram()) << std::endl;
319
320                    COUT(0) << std::endl << "fragment program name:" << std::endl;
321                    COUT(0) << pass->getFragmentProgramName() << std::endl;
322
323                    COUT(0) << std::endl << "GpuProgram default parameters:" << std::endl;
324                    Ogre::GpuProgramParameters* defaultparams = pass->getFragmentProgram().get()->getDefaultParameters().get();
325                    COUT(0) << defaultparams << std::endl;
326                    if (defaultparams)
327                    {
328                        const Ogre::GpuConstantDefinitionMap& constantdefinitions = defaultparams->getConstantDefinitions().map;
329                        for (Ogre::GpuConstantDefinitionMap::const_iterator it = constantdefinitions.begin(); it != constantdefinitions.end(); ++it)
330                            COUT(0) << it->first << " / " << it->second.physicalIndex << " / " << it->second.isFloat() << " / " << (float)((it->second.isFloat()) ? (*defaultparams->getFloatPointer(it->second.physicalIndex)) : (*defaultparams->getIntPointer(it->second.physicalIndex))) << std::endl;
331                    }
332
333                    COUT(0) << std::endl << "end" << std::endl;
334*/
335                }
336                Ogre::CompositorManager::getSingleton().setCompositorEnabled(viewport, this->compositor_, this->bViewportInitialized_ && this->isVisible());
337            }
338            this->oldcompositor_ = this->compositor_;
339        }
340    }
341
342    void Shader::updateVisibility()
343    {
344        if (this->compositorInstance_ && this->scenemanager_)
345            this->compositorInstance_->setEnabled(this->scenemanager_->getCurrentViewport() && this->isVisible());
346    }
347
348    void Shader::setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, float value)
349    {
350        if (Shader::_setParameter(material, technique, pass, parameter, value))
351        {
352            if (this->bViewportInitialized_ && this->compositorInstance_ && this->isVisible())
353            {
354                this->compositorInstance_->setEnabled(false);
355                this->compositorInstance_->setEnabled(true);
356            }
357        }
358    }
359
360    void Shader::setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, int value)
361    {
362        if (Shader::_setParameter(material, technique, pass, parameter, value))
363        {
364            if (this->bViewportInitialized_ && this->compositorInstance_ && this->isVisible())
365            {
366                this->compositorInstance_->setEnabled(false);
367                this->compositorInstance_->setEnabled(true);
368            }
369        }
370    }
371
372    bool Shader::_setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, float value)
373    {
374        ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
375        if (pointer)
376        {
377            if (pointer->first)
378            {
379                if ((*((float*)pointer->second)) != value)
380                {
381                    (*((float*)pointer->second)) = value;
382                    return true;
383                }
384            }
385            else
386            {
387                if ((*((int*)pointer->second)) != (int)value)
388                {
389                    (*((int*)pointer->second)) = (int)value;
390                    return true;
391                }
392            }
393        }
394        return false;
395    }
396
397    bool Shader::_setParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter, int value)
398    {
399        ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
400        if (pointer)
401        {
402            if (pointer->first)
403            {
404                if ((*((float*)pointer->second)) != (float)value)
405                {
406                    (*((float*)pointer->second)) = (float)value;
407                    return true;
408                }
409            }
410            else
411            {
412                if ((*((int*)pointer->second)) != value)
413                {
414                    (*((int*)pointer->second)) = value;
415                    return true;
416                }
417            }
418        }
419        return false;
420    }
421
422    float Shader::getParameter(const std::string& material, size_t technique, size_t pass, const std::string& parameter)
423    {
424        ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
425        if (pointer)
426        {
427            if (pointer->first)
428                return (*((float*)pointer->second));
429            else
430                return (*((int*)pointer->second));
431        }
432        else
433            return 0;
434    }
435
436    bool Shader::getParameterIsFloat(const std::string& material, size_t technique, size_t pass, const std::string& parameter)
437    {
438        ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
439        if (pointer)
440            return pointer->first;
441        else
442            return false;
443    }
444
445    bool Shader::getParameterIsInt(const std::string& material, size_t technique, size_t pass, const std::string& parameter)
446    {
447        ParameterPointer* pointer = Shader::getParameterPointer(material, technique, pass, parameter);
448        if (pointer)
449            return (!pointer->first);
450        else
451            return false;
452    }
453
454    Shader::ParameterPointer* Shader::getParameterPointer(const std::string& material, size_t technique, size_t pass, const std::string& parameter)
455    {
456        if (!Core::showsGraphics() || !Shader::bLoadedCgPlugin_s)
457            return 0;
458
459        MaterialMap::iterator material_iterator = Shader::parameters_s.find(material);
460        if (material_iterator != Shader::parameters_s.end())
461        {
462            TechniqueVector& technique_vector = material_iterator->second;
463            if (technique < technique_vector.size())
464            {
465                PassVector& pass_vector = technique_vector[technique];
466                if (pass < pass_vector.size())
467                {
468                    ParameterMap& parameter_map = pass_vector[pass];
469                    ParameterMap::iterator parameter_iterator = parameter_map.find(parameter);
470
471                    if (parameter_iterator != parameter_map.end())
472                        return (&parameter_iterator->second);
473                    else
474                        COUT(2) << "Warning: No shader parameter \"" << parameter << "\" in pass " << pass << " in technique " << technique << " in material \"" << material << "\"." << std::endl;
475                }
476                else
477                    COUT(2) << "Warning: No pass " << pass << " in technique " << technique << " in material \"" << material << "\" or pass has no shader." << std::endl;
478            }
479            else
480                COUT(2) << "Warning: No technique " << technique << " in material \"" << material << "\" or technique has no pass with shader." << std::endl;
481        }
482        else
483        {
484            bool foundAtLeastOneShaderParameter = false;
485            Ogre::MaterialManager::ResourceMapIterator iterator = Ogre::MaterialManager::getSingleton().getResourceIterator();
486            Ogre::Material* material_pointer = 0;
487
488            while (iterator.hasMoreElements())
489            {
490                Ogre::Resource* resource = iterator.getNext().get();
491                if (resource->getName() == material)
492                    material_pointer = (Ogre::Material*)resource;
493            }
494
495            if (!material_pointer)
496            {
497                COUT(2) << "Warning: No material with name \"" << material << "\" found." << std::endl;
498                return 0;
499            }
500
501            for (unsigned int t = 0; t < material_pointer->getNumTechniques(); ++t)
502            {
503                Ogre::Technique* technique_pointer = material_pointer->getTechnique(t);
504                if (!technique_pointer)
505                    continue;
506
507                for (unsigned int p = 0; p < technique_pointer->getNumPasses(); ++p)
508                {
509                    Ogre::Pass* pass_pointer = technique_pointer->getPass(p);
510                    if (!pass_pointer)
511                        continue;
512
513                    if (pass_pointer->getFragmentProgramName() != "")
514                    {
515                        Ogre::GpuProgramParameters* parameter_pointer = pass_pointer->getFragmentProgramParameters().get();
516                        if (!parameter_pointer)
517                            continue;
518
519                        const Ogre::GpuConstantDefinitionMap& constant_definitions = parameter_pointer->getConstantDefinitions().map;
520                        for (Ogre::GpuConstantDefinitionMap::const_iterator definition_iterator = constant_definitions.begin(); definition_iterator != constant_definitions.end(); ++definition_iterator)
521                        {
522                            void* temp = (definition_iterator->second.isFloat())
523                                            ? (void*)parameter_pointer->getFloatPointer(definition_iterator->second.physicalIndex)
524                                            : (void*)parameter_pointer->getIntPointer(definition_iterator->second.physicalIndex);
525                            ParameterPointer parameter_pointer = ParameterPointer(definition_iterator->second.isFloat(), temp);
526
527                            TechniqueVector& technique_vector = Shader::parameters_s[material];
528                            technique_vector.resize(technique + 1);
529                            PassVector& pass_vector = technique_vector[technique];
530                            pass_vector.resize(pass + 1);
531                            pass_vector[pass][definition_iterator->first] = parameter_pointer;
532                            foundAtLeastOneShaderParameter = true;
533                        }
534                    }
535                }
536            }
537
538            // recursive call if the material was added to the map
539            if (foundAtLeastOneShaderParameter)
540                return Shader::getParameterPointer(material, technique, pass, parameter);
541        }
542        return 0;
543    }
544}
Note: See TracBrowser for help on using the repository browser.