Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Nov 14, 2012, 9:16:18 PM (12 years ago)
Author:
davidsa
Message:

Added Hardware Occlusion Query Capabilities for use in dynamic flare effects, this is still a pretty static implemenation, meaning it will fail with mutltiple HOQ objects on screen, also needs some tidying up and documentation at a later point

Location:
code/branches/shaders/src/orxonox
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • code/branches/shaders/src/orxonox/RenderQueueListener.cc

    r9420 r9448  
    3737#include <OgreRoot.h>
    3838#include <OgreRenderQueueListener.h>
     39#include <OgreHardwareOcclusionQuery.h>
    3940
    4041namespace orxonox
    4142{
     43    RenderQueueListener::RenderQueueListener() : pixelCount_(0), pixelState_(RenderQueueListener::READY_FOR_RENDER)
     44    {
     45        hardwareOcclusionQuery_ = Ogre::Root::getSingleton().getRenderSystem()->createHardwareOcclusionQuery(); //create a new HOQ for the scene this listener is used in
     46    }
     47   
     48    RenderQueueListener::~RenderQueueListener()
     49    {
     50        Ogre::Root::getSingleton().getRenderSystem()->destroyHardwareOcclusionQuery(hardwareOcclusionQuery_); //destroy the created HOQ
     51    }
     52   
     53    /**
     54    @brief
     55    This function is returning the current pixel count and resets the pixel state if we're ready to do another Hardware Occlusion Query
     56   
     57    @return
     58    current pixel count taken from the last Hardware Occlusion Query
     59    */
     60    unsigned int RenderQueueListener::getPixelCount()
     61    {
     62        if(this->pixelState_==RenderQueueListener::READY_FOR_ACCESS)
     63        {
     64            this->hardwareOcclusionQuery_->pullOcclusionQuery(&(this->pixelCount_));
     65            this->pixelState_=RenderQueueListener::READY_FOR_RENDER;
     66        }
     67        return this->pixelCount_;
     68    }
     69   
    4270    /**
    4371    @brief
    4472    This function is called just before a RenderQueueGroup is rendered, this function is called by Ogre automatically with the correct parameters.
    4573
    46     In this case we use it to set the stencil buffer parameters of the render system
     74    In this case we use it to set the stencil buffer parameters of the render system and issue a Hardware Occlusion Query
    4775    */
    4876    void RenderQueueListener::renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& skipThisInvocation)
     
    6088        if (queueGroupId == RENDER_QUEUE_STENCIL_GLOW)
    6189        {
    62               Ogre::RenderSystem * renderSystem = Ogre::Root::getSingleton().getRenderSystem();
    63               renderSystem->setStencilCheckEnabled(true);
    64               renderSystem->setStencilBufferParams(Ogre::CMPF_NOT_EQUAL,
    65                   STENCIL_VALUE_FOR_GLOW, STENCIL_FULL_MASK,
    66                   Ogre::SOP_KEEP,Ogre::SOP_KEEP,Ogre::SOP_REPLACE,false);       
     90            Ogre::RenderSystem * renderSystem = Ogre::Root::getSingleton().getRenderSystem();
     91            renderSystem->setStencilCheckEnabled(true);
     92            renderSystem->setStencilBufferParams(Ogre::CMPF_NOT_EQUAL,
     93                STENCIL_VALUE_FOR_GLOW, STENCIL_FULL_MASK,
     94                Ogre::SOP_KEEP,Ogre::SOP_KEEP,Ogre::SOP_REPLACE,false);       
     95        }
     96        if (queueGroupId == RENDER_QUEUE_HOQ && this->pixelState_==RenderQueueListener::READY_FOR_RENDER)
     97        {
     98            this->hardwareOcclusionQuery_->beginOcclusionQuery();
     99            this->pixelState_=RenderQueueListener::QUERY_STARTED;
     100            //TODO: Skip this rendering step altogheter if we haven't requested the pixel count yet, not sure if this is possible without a custom SceneManager
    67101        }
    68102    }
     
    82116            renderSystem->setStencilBufferParams();
    83117        }
     118        if (queueGroupId == RENDER_QUEUE_HOQ && this->pixelState_==RenderQueueListener::QUERY_STARTED)
     119        {
     120            this->hardwareOcclusionQuery_->endOcclusionQuery();
     121            this->pixelState_=RenderQueueListener::READY_FOR_ACCESS;
     122        }
    84123    }
    85124}
  • code/branches/shaders/src/orxonox/RenderQueueListener.h

    r9419 r9448  
    3939
    4040#include <OgreRenderQueueListener.h>
     41#include <OgreHardwareOcclusionQuery.h>
    4142
    4243namespace orxonox
     
    4748        RENDER_QUEUE_STENCIL_OBJECTS = RENDER_QUEUE_MAIN+1,
    4849        RENDER_QUEUE_STENCIL_GLOW = RENDER_QUEUE_MAIN+2,
    49         RENDER_QUEUE_STENCIL_LAST = RENDER_QUEUE_STENCIL_GLOW //this is a reference to the last render queue to be affected by stencil glow effects
     50        RENDER_QUEUE_STENCIL_LAST = RENDER_QUEUE_STENCIL_GLOW, //this is a reference to the last render queue to be affected by stencil glow effects
     51        RENDER_QUEUE_HOQ = RENDER_QUEUE_STENCIL_LAST+1 //this is where we render the objects for occlusion queries (use transparent material)
    5052    };
    5153
     
    6567    {
    6668        public:
     69            RenderQueueListener();
     70            ~RenderQueueListener();
     71   
     72            /**
     73            @brief
     74            This function is returning the current pixel count and resets the pixel state if we're ready to do another Hardware Occlusion Query
     75           
     76            @return
     77            current pixel count taken from the last Hardware Occlusion Query
     78            */
     79            unsigned int getPixelCount();
     80           
    6781            /**
    6882            @brief
     
    7993            */
    8094            virtual void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation);
     95           
     96        private:
     97            Ogre::HardwareOcclusionQuery* hardwareOcclusionQuery_; //!< this stores the current instance of the HOQ used in the render system
     98            unsigned int pixelCount_; //!< this stores the last pixel count returned by the last HOQ in the corresponding render group
     99           
     100            enum PixelState //!< enum to distinguish the several HOQ pixel count states
     101            {
     102                READY_FOR_RENDER,
     103                QUERY_STARTED,
     104                READY_FOR_ACCESS
     105            };
     106           
     107            PixelState pixelState_; //!< this stores the current state of the Hardware Occlusion Query
    81108    };
    82109}
  • code/branches/shaders/src/orxonox/Scene.cc

    r9420 r9448  
    7878            this->sceneManager_ = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
    7979            this->rootSceneNode_ = this->sceneManager_->getRootSceneNode();
    80             RenderQueueListener* renderQueueListener = new RenderQueueListener();
    81             this->sceneManager_->addRenderQueueListener(renderQueueListener);//add our own renderQueueListener
     80            this->renderQueueListener_ = new RenderQueueListener();
     81            this->sceneManager_->addRenderQueueListener(this->renderQueueListener_);//add our own renderQueueListener
    8282
    8383            this->radar_ = new Radar();
  • code/branches/shaders/src/orxonox/Scene.h

    r9420 r9448  
    6969            inline Ogre::SceneNode* getRootSceneNode() const
    7070                { return this->rootSceneNode_; }
     71            inline RenderQueueListener* getRenderQueueListener() const
     72                { return this->renderQueueListener_; }
    7173
    7274            void setSkybox(const std::string& skybox);
     
    107109            Ogre::SceneManager*      sceneManager_; //!< This is a pointer to the Ogre SceneManager we're using to render the Scene
    108110            Ogre::SceneNode*         rootSceneNode_; //!< This is a pointer to the root node of the Scene tree
     111            RenderQueueListener*     renderQueueListener_; //!< this is a pointer to the RenderQueueListener we're using for this Scene
    109112
    110113            std::string              skybox_; //!< This string holds information about the skybox we're using
  • code/branches/shaders/src/orxonox/graphics/Billboard.cc

    r8706 r9448  
    171171        }
    172172    }
     173   
     174    void Billboard::setRenderQueueGroup(unsigned char groupID)
     175    {
     176        Ogre::BillboardSet* bSet = this->billboard_.getBillboardSet();
     177        if( bSet != NULL )
     178        {
     179            bSet->setRenderQueueGroup(groupID);
     180        }
     181    }
    173182}
  • code/branches/shaders/src/orxonox/graphics/Billboard.h

    r8706 r9448  
    8181           
    8282            void setDefaultDimensions(float width, float height);
     83           
     84            void setRenderQueueGroup(unsigned char groupID);
    8385
    8486
  • code/branches/shaders/src/orxonox/graphics/LensFlare.cc

    r9445 r9448  
    3838#include "graphics/Billboard.h"
    3939#include "CameraManager.h"
     40#include "RenderQueueListener.h"
     41
     42#include <OgreSphere.h>
     43#include <OgreRenderWindow.h>
    4044
    4145namespace orxonox
     
    4347    CreateFactory(LensFlare);
    4448   
    45     LensFlare::LensFlare(BaseObject* creator) : StaticEntity(creator)
     49    LensFlare::LensFlare(BaseObject* creator) : StaticEntity(creator), scale_(1.0f)
    4650    {
    4751        RegisterObject(LensFlare);
     
    5963    {
    6064        SUPER(LensFlare, XMLPort, xmlelement, mode);
     65        XMLPortParam(LensFlare, "scale", setScale, getScale, xmlelement, mode).defaultValues(1.0f);
    6166    }
    6267   
    6368    void LensFlare::registerVariables()
    6469    {
    65      
     70        registerVariable(this->scale_, VariableDirection::ToClient, new NetworkCallback<LensFlare>(this, &LensFlare::updateBillboardPositions));
    6671    }
    6772   
    6873    void LensFlare::createBillboards()
    6974    {
     75        this->occlusionBillboard_ = new Billboard(this);
     76        this->occlusionBillboard_->setMaterial("lensflare/hoq");
     77        this->occlusionBillboard_->setPosition(this->getPosition());
     78        this->occlusionBillboard_->setVisible(false);
     79        this->occlusionBillboard_->setRenderQueueGroup(RENDER_QUEUE_HOQ);
     80        this->attach(this->occlusionBillboard_);
     81       
    7082        Billboard* burst = new Billboard(this);
    7183        burst->setMaterial("lensflare/burst");
     
    7991        Ogre::Camera* camera=CameraManager::getInstance().getActiveCamera()->getOgreCamera(); //get active Ogre Camera Instance, so we can check whether the light source is visible
    8092        bool lightIsVisible=camera->isVisible(this->getPosition()); //is the light source visible from our point of view?
    81         int scale=camera->getPosition().distance(this->getPosition());
     93        this->cameraDistance_=camera->getPosition().distance(this->getPosition());
     94        unsigned int dimension=this->cameraDistance_*this->scale_;
    8295       
    83         Billboard* burst=static_cast<Billboard*>(getAttachedObject(0));
     96        this->occlusionBillboard_->setPosition(this->getPosition());
     97        this->occlusionBillboard_->setVisible(lightIsVisible);
     98        this->occlusionBillboard_->setDefaultDimensions(dimension,dimension);
     99       
     100        Billboard* burst=static_cast<Billboard*>(getAttachedObject(1));
    84101        burst->setPosition(this->getPosition());
    85102        burst->setVisible(lightIsVisible);
    86         burst->setDefaultDimensions(scale,scale);
     103        burst->setDefaultDimensions(dimension,dimension);
    87104    }
    88105
     
    92109        {
    93110            updateBillboardPositions();
     111            if(this->occlusionBillboard_->isVisible()) {
     112                unsigned int dimension=this->cameraDistance_*this->scale_;
     113                Ogre::Sphere* sphere=new Ogre::Sphere(this->getPosition(),dimension*0.25);
     114                Ogre::Camera* camera=CameraManager::getInstance().getActiveCamera()->getOgreCamera();
     115                float left, right, top, bottom;
     116                camera->projectSphere(*sphere,&left,&top,&right,&bottom);//approximate maximum pixel count of billboard with a sphere
     117                delete sphere;
     118               
     119                Ogre::RenderWindow* window = GraphicsManager::getInstance().getRenderWindow();
     120                float maxCount=(right-left)*(top-bottom)*window->getWidth()*window->getHeight()*0.25;
     121                float pixelCount=this->getScene()->getRenderQueueListener()->getPixelCount();//get pixel count
     122                float ratio=pixelCount/maxCount;
     123                //orxout() << "maxCount: " << maxCount << " HOQ: " << pixelCount << " ratio: " << ratio << std::endl;
     124                ColourValue* colour = new ColourValue(1.0f,1.0f,1.0f,ratio); //adjust alpha of billboard
     125               
     126                Billboard* burst=static_cast<Billboard*>(getAttachedObject(1));
     127                burst->setColour(*colour);
     128                delete colour;
     129            }
    94130        }
    95131    }
  • code/branches/shaders/src/orxonox/graphics/LensFlare.h

    r9445 r9448  
    4040#include "OgreBillboardSet.h"
    4141
     42#include "core/GraphicsManager.h"
    4243#include "util/Math.h"
    4344#include "worldentities/StaticEntity.h"
     
    5455        David 'davidsa' Salvisberg
    5556    */
     57    //TODO: The Hardware Occlusion only works properly for a single Flare on the screen,
     58    // if we have multiple strong lights it'll become way more complicated to determine how much of every object is occluded individually
     59    // there's below a 100 render queue groups, so maybe we should take turns for each object to be tested, so we only have one of the objects rendered at a time
     60    // obviously we shouldn't use too much of these effects anyways, since they use a lot of performance, so not sure whether it's worth implementing a solution that works for multiple lens flares on screen
    5661    class _OrxonoxExport LensFlare : public StaticEntity, public Tickable
    5762    {
     
    5964            LensFlare(BaseObject* creator);
    6065            virtual ~LensFlare();
     66           
     67            inline void setScale(float scale)
     68                { this->scale_=scale; }
     69            inline float getScale()
     70                { return this->scale_; }
    6171
    6272            virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
     
    7282           
    7383            void updateBillboardPositions();
     84           
     85            Billboard* occlusionBillboard_;
     86            unsigned int cameraDistance_;
     87            float scale_;
    7488    };
    7589}
Note: See TracChangeset for help on using the changeset viewer.