Index: /code/branches/shaders/src/orxonox/RenderQueueListener.cc
===================================================================
--- /code/branches/shaders/src/orxonox/RenderQueueListener.cc	(revision 9447)
+++ /code/branches/shaders/src/orxonox/RenderQueueListener.cc	(revision 9448)
@@ -37,12 +37,40 @@
 #include <OgreRoot.h>
 #include <OgreRenderQueueListener.h>
+#include <OgreHardwareOcclusionQuery.h>
 
 namespace orxonox
 {
+    RenderQueueListener::RenderQueueListener() : pixelCount_(0), pixelState_(RenderQueueListener::READY_FOR_RENDER)
+    {
+        hardwareOcclusionQuery_ = Ogre::Root::getSingleton().getRenderSystem()->createHardwareOcclusionQuery(); //create a new HOQ for the scene this listener is used in
+    }
+    
+    RenderQueueListener::~RenderQueueListener()
+    {
+        Ogre::Root::getSingleton().getRenderSystem()->destroyHardwareOcclusionQuery(hardwareOcclusionQuery_); //destroy the created HOQ
+    }
+    
+    /**
+    @brief
+    This function is returning the current pixel count and resets the pixel state if we're ready to do another Hardware Occlusion Query
+    
+    @return
+    current pixel count taken from the last Hardware Occlusion Query
+    */
+    unsigned int RenderQueueListener::getPixelCount()
+    {
+        if(this->pixelState_==RenderQueueListener::READY_FOR_ACCESS)
+        {
+            this->hardwareOcclusionQuery_->pullOcclusionQuery(&(this->pixelCount_));
+            this->pixelState_=RenderQueueListener::READY_FOR_RENDER;
+        }
+        return this->pixelCount_;
+    }
+    
     /**
     @brief
     This function is called just before a RenderQueueGroup is rendered, this function is called by Ogre automatically with the correct parameters.
 
-    In this case we use it to set the stencil buffer parameters of the render system
+    In this case we use it to set the stencil buffer parameters of the render system and issue a Hardware Occlusion Query
     */
     void RenderQueueListener::renderQueueStarted(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& skipThisInvocation)
@@ -60,9 +88,15 @@
         if (queueGroupId == RENDER_QUEUE_STENCIL_GLOW)
         { 
-              Ogre::RenderSystem * renderSystem = Ogre::Root::getSingleton().getRenderSystem(); 
-              renderSystem->setStencilCheckEnabled(true); 
-              renderSystem->setStencilBufferParams(Ogre::CMPF_NOT_EQUAL,
-                  STENCIL_VALUE_FOR_GLOW, STENCIL_FULL_MASK, 
-                  Ogre::SOP_KEEP,Ogre::SOP_KEEP,Ogre::SOP_REPLACE,false);       
+            Ogre::RenderSystem * renderSystem = Ogre::Root::getSingleton().getRenderSystem(); 
+            renderSystem->setStencilCheckEnabled(true); 
+            renderSystem->setStencilBufferParams(Ogre::CMPF_NOT_EQUAL,
+                STENCIL_VALUE_FOR_GLOW, STENCIL_FULL_MASK, 
+                Ogre::SOP_KEEP,Ogre::SOP_KEEP,Ogre::SOP_REPLACE,false);       
+        }
+        if (queueGroupId == RENDER_QUEUE_HOQ && this->pixelState_==RenderQueueListener::READY_FOR_RENDER)
+        { 
+            this->hardwareOcclusionQuery_->beginOcclusionQuery();
+            this->pixelState_=RenderQueueListener::QUERY_STARTED;
+            //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
         }
     }
@@ -82,4 +116,9 @@
             renderSystem->setStencilBufferParams(); 
         }
+        if (queueGroupId == RENDER_QUEUE_HOQ && this->pixelState_==RenderQueueListener::QUERY_STARTED)
+        {
+            this->hardwareOcclusionQuery_->endOcclusionQuery();
+            this->pixelState_=RenderQueueListener::READY_FOR_ACCESS;
+        }
     }
 }
Index: /code/branches/shaders/src/orxonox/RenderQueueListener.h
===================================================================
--- /code/branches/shaders/src/orxonox/RenderQueueListener.h	(revision 9447)
+++ /code/branches/shaders/src/orxonox/RenderQueueListener.h	(revision 9448)
@@ -39,4 +39,5 @@
 
 #include <OgreRenderQueueListener.h>
+#include <OgreHardwareOcclusionQuery.h>
 
 namespace orxonox
@@ -47,5 +48,6 @@
         RENDER_QUEUE_STENCIL_OBJECTS = RENDER_QUEUE_MAIN+1,
         RENDER_QUEUE_STENCIL_GLOW = RENDER_QUEUE_MAIN+2,
-        RENDER_QUEUE_STENCIL_LAST = RENDER_QUEUE_STENCIL_GLOW //this is a reference to the last render queue to be affected by stencil glow effects
+        RENDER_QUEUE_STENCIL_LAST = RENDER_QUEUE_STENCIL_GLOW, //this is a reference to the last render queue to be affected by stencil glow effects
+        RENDER_QUEUE_HOQ = RENDER_QUEUE_STENCIL_LAST+1 //this is where we render the objects for occlusion queries (use transparent material)
     };
 
@@ -65,4 +67,16 @@
     {
         public:
+            RenderQueueListener();
+            ~RenderQueueListener();
+    
+            /**
+            @brief
+            This function is returning the current pixel count and resets the pixel state if we're ready to do another Hardware Occlusion Query
+            
+            @return
+            current pixel count taken from the last Hardware Occlusion Query
+            */
+            unsigned int getPixelCount();
+            
             /**
             @brief
@@ -79,4 +93,17 @@
             */
             virtual void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation);
+            
+        private:
+            Ogre::HardwareOcclusionQuery* hardwareOcclusionQuery_; //!< this stores the current instance of the HOQ used in the render system
+            unsigned int pixelCount_; //!< this stores the last pixel count returned by the last HOQ in the corresponding render group
+            
+            enum PixelState //!< enum to distinguish the several HOQ pixel count states
+            {
+                READY_FOR_RENDER,
+                QUERY_STARTED,
+                READY_FOR_ACCESS
+            };
+            
+            PixelState pixelState_; //!< this stores the current state of the Hardware Occlusion Query
     };
 }
Index: /code/branches/shaders/src/orxonox/Scene.cc
===================================================================
--- /code/branches/shaders/src/orxonox/Scene.cc	(revision 9447)
+++ /code/branches/shaders/src/orxonox/Scene.cc	(revision 9448)
@@ -78,6 +78,6 @@
             this->sceneManager_ = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC);
             this->rootSceneNode_ = this->sceneManager_->getRootSceneNode();
-            RenderQueueListener* renderQueueListener = new RenderQueueListener();
-            this->sceneManager_->addRenderQueueListener(renderQueueListener);//add our own renderQueueListener
+            this->renderQueueListener_ = new RenderQueueListener();
+            this->sceneManager_->addRenderQueueListener(this->renderQueueListener_);//add our own renderQueueListener
 
             this->radar_ = new Radar();
Index: /code/branches/shaders/src/orxonox/Scene.h
===================================================================
--- /code/branches/shaders/src/orxonox/Scene.h	(revision 9447)
+++ /code/branches/shaders/src/orxonox/Scene.h	(revision 9448)
@@ -69,4 +69,6 @@
             inline Ogre::SceneNode* getRootSceneNode() const
                 { return this->rootSceneNode_; }
+            inline RenderQueueListener* getRenderQueueListener() const
+                { return this->renderQueueListener_; }
 
             void setSkybox(const std::string& skybox);
@@ -107,4 +109,5 @@
             Ogre::SceneManager*      sceneManager_; //!< This is a pointer to the Ogre SceneManager we're using to render the Scene
             Ogre::SceneNode*         rootSceneNode_; //!< This is a pointer to the root node of the Scene tree
+            RenderQueueListener*     renderQueueListener_; //!< this is a pointer to the RenderQueueListener we're using for this Scene
 
             std::string              skybox_; //!< This string holds information about the skybox we're using
Index: /code/branches/shaders/src/orxonox/graphics/Billboard.cc
===================================================================
--- /code/branches/shaders/src/orxonox/graphics/Billboard.cc	(revision 9447)
+++ /code/branches/shaders/src/orxonox/graphics/Billboard.cc	(revision 9448)
@@ -171,3 +171,12 @@
         }
     }
+    
+    void Billboard::setRenderQueueGroup(unsigned char groupID)
+    {
+        Ogre::BillboardSet* bSet = this->billboard_.getBillboardSet();
+        if( bSet != NULL )
+        {
+            bSet->setRenderQueueGroup(groupID);
+        }
+    }
 }
Index: /code/branches/shaders/src/orxonox/graphics/Billboard.h
===================================================================
--- /code/branches/shaders/src/orxonox/graphics/Billboard.h	(revision 9447)
+++ /code/branches/shaders/src/orxonox/graphics/Billboard.h	(revision 9448)
@@ -81,4 +81,6 @@
             
             void setDefaultDimensions(float width, float height);
+            
+            void setRenderQueueGroup(unsigned char groupID);
 
 
Index: /code/branches/shaders/src/orxonox/graphics/LensFlare.cc
===================================================================
--- /code/branches/shaders/src/orxonox/graphics/LensFlare.cc	(revision 9447)
+++ /code/branches/shaders/src/orxonox/graphics/LensFlare.cc	(revision 9448)
@@ -38,4 +38,8 @@
 #include "graphics/Billboard.h"
 #include "CameraManager.h"
+#include "RenderQueueListener.h"
+
+#include <OgreSphere.h>
+#include <OgreRenderWindow.h>
 
 namespace orxonox
@@ -43,5 +47,5 @@
     CreateFactory(LensFlare);
     
-    LensFlare::LensFlare(BaseObject* creator) : StaticEntity(creator)
+    LensFlare::LensFlare(BaseObject* creator) : StaticEntity(creator), scale_(1.0f)
     {
         RegisterObject(LensFlare);
@@ -59,13 +63,21 @@
     {
         SUPER(LensFlare, XMLPort, xmlelement, mode);
+        XMLPortParam(LensFlare, "scale", setScale, getScale, xmlelement, mode).defaultValues(1.0f);
     }
     
     void LensFlare::registerVariables()
     {
-      
+        registerVariable(this->scale_, VariableDirection::ToClient, new NetworkCallback<LensFlare>(this, &LensFlare::updateBillboardPositions));
     }
     
     void LensFlare::createBillboards()
     {
+        this->occlusionBillboard_ = new Billboard(this);
+        this->occlusionBillboard_->setMaterial("lensflare/hoq");
+        this->occlusionBillboard_->setPosition(this->getPosition());
+        this->occlusionBillboard_->setVisible(false);
+        this->occlusionBillboard_->setRenderQueueGroup(RENDER_QUEUE_HOQ);
+        this->attach(this->occlusionBillboard_);
+        
         Billboard* burst = new Billboard(this);
         burst->setMaterial("lensflare/burst");
@@ -79,10 +91,15 @@
         Ogre::Camera* camera=CameraManager::getInstance().getActiveCamera()->getOgreCamera(); //get active Ogre Camera Instance, so we can check whether the light source is visible
         bool lightIsVisible=camera->isVisible(this->getPosition()); //is the light source visible from our point of view?
-        int scale=camera->getPosition().distance(this->getPosition());
+        this->cameraDistance_=camera->getPosition().distance(this->getPosition());
+        unsigned int dimension=this->cameraDistance_*this->scale_;
         
-        Billboard* burst=static_cast<Billboard*>(getAttachedObject(0));
+        this->occlusionBillboard_->setPosition(this->getPosition());
+        this->occlusionBillboard_->setVisible(lightIsVisible);
+        this->occlusionBillboard_->setDefaultDimensions(dimension,dimension);
+        
+        Billboard* burst=static_cast<Billboard*>(getAttachedObject(1));
         burst->setPosition(this->getPosition());
         burst->setVisible(lightIsVisible);
-        burst->setDefaultDimensions(scale,scale);
+        burst->setDefaultDimensions(dimension,dimension);
     }
 
@@ -92,4 +109,23 @@
         {
             updateBillboardPositions();
+            if(this->occlusionBillboard_->isVisible()) {
+                unsigned int dimension=this->cameraDistance_*this->scale_;
+                Ogre::Sphere* sphere=new Ogre::Sphere(this->getPosition(),dimension*0.25);
+                Ogre::Camera* camera=CameraManager::getInstance().getActiveCamera()->getOgreCamera();
+                float left, right, top, bottom;
+                camera->projectSphere(*sphere,&left,&top,&right,&bottom);//approximate maximum pixel count of billboard with a sphere
+                delete sphere;
+                
+                Ogre::RenderWindow* window = GraphicsManager::getInstance().getRenderWindow();
+                float maxCount=(right-left)*(top-bottom)*window->getWidth()*window->getHeight()*0.25;
+                float pixelCount=this->getScene()->getRenderQueueListener()->getPixelCount();//get pixel count
+                float ratio=pixelCount/maxCount;
+                //orxout() << "maxCount: " << maxCount << " HOQ: " << pixelCount << " ratio: " << ratio << std::endl;
+                ColourValue* colour = new ColourValue(1.0f,1.0f,1.0f,ratio); //adjust alpha of billboard
+                
+                Billboard* burst=static_cast<Billboard*>(getAttachedObject(1));
+                burst->setColour(*colour);
+                delete colour;
+            }
         }
     }
Index: /code/branches/shaders/src/orxonox/graphics/LensFlare.h
===================================================================
--- /code/branches/shaders/src/orxonox/graphics/LensFlare.h	(revision 9447)
+++ /code/branches/shaders/src/orxonox/graphics/LensFlare.h	(revision 9448)
@@ -40,4 +40,5 @@
 #include "OgreBillboardSet.h"
 
+#include "core/GraphicsManager.h"
 #include "util/Math.h"
 #include "worldentities/StaticEntity.h"
@@ -54,4 +55,8 @@
         David 'davidsa' Salvisberg
     */
+    //TODO: The Hardware Occlusion only works properly for a single Flare on the screen,
+    // if we have multiple strong lights it'll become way more complicated to determine how much of every object is occluded individually
+    // 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
+    // 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 
     class _OrxonoxExport LensFlare : public StaticEntity, public Tickable
     {
@@ -59,4 +64,9 @@
             LensFlare(BaseObject* creator);
             virtual ~LensFlare();
+            
+            inline void setScale(float scale)
+                { this->scale_=scale; }
+            inline float getScale()
+                { return this->scale_; }
 
             virtual void XMLPort(Element& xmlelement, XMLPort::Mode mode);
@@ -72,4 +82,8 @@
             
             void updateBillboardPositions();
+            
+            Billboard* occlusionBillboard_;
+            unsigned int cameraDistance_;
+            float scale_;
     };
 }
