Index: code/branches/shaders/src/orxonox/graphics/LensFlare.cc
===================================================================
--- code/branches/shaders/src/orxonox/graphics/LensFlare.cc	(revision 9448)
+++ code/branches/shaders/src/orxonox/graphics/LensFlare.cc	(revision 9461)
@@ -47,5 +47,5 @@
     CreateFactory(LensFlare);
     
-    LensFlare::LensFlare(BaseObject* creator) : StaticEntity(creator), scale_(1.0f)
+    LensFlare::LensFlare(BaseObject* creator) : StaticEntity(creator), scale_(1.0f), fadeOnViewBorder_(true), fadeResolution_(7), fadeExponent_(2.0f)
     {
         RegisterObject(LensFlare);
@@ -64,17 +64,28 @@
         SUPER(LensFlare, XMLPort, xmlelement, mode);
         XMLPortParam(LensFlare, "scale", setScale, getScale, xmlelement, mode).defaultValues(1.0f);
+        XMLPortParam(LensFlare, "fadeOnViewBorder", setFadeOnViewBorder, isFadeOnViewBorder, xmlelement, mode).defaultValues(true);
+        XMLPortParam(LensFlare, "fadeResolution", setFadeResolution, getFadeResolution, xmlelement, mode).defaultValues(7);
+        XMLPortParam(LensFlare, "fadeExponent", setFadeExponent, getFadeExponent, xmlelement, mode).defaultValues(2.0f);
     }
     
     void LensFlare::registerVariables()
     {
-        registerVariable(this->scale_, VariableDirection::ToClient, new NetworkCallback<LensFlare>(this, &LensFlare::updateBillboardPositions));
-    }
-    
+        registerVariable(this->scale_, VariableDirection::ToClient);
+        registerVariable(this->fadeOnViewBorder_, VariableDirection::ToClient);
+        registerVariable(this->fadeResolution_, VariableDirection::ToClient);
+    }
+
+    /**
+    @brief
+        This function creates all the billboards needed for the flare effect
+    */
     void LensFlare::createBillboards()
     {
+        //TODO: add more billboards, possibly do some cleaning up, by using a loop
         this->occlusionBillboard_ = new Billboard(this);
         this->occlusionBillboard_->setMaterial("lensflare/hoq");
         this->occlusionBillboard_->setPosition(this->getPosition());
         this->occlusionBillboard_->setVisible(false);
+        this->occlusionBillboard_->disableFrustumCulling();
         this->occlusionBillboard_->setRenderQueueGroup(RENDER_QUEUE_HOQ);
         this->attach(this->occlusionBillboard_);
@@ -83,23 +94,73 @@
         burst->setMaterial("lensflare/burst");
         burst->setPosition(this->getPosition());
-        burst->setVisible(false);
+        burst->disableFrustumCulling();
+        burst->setVisible(true);
         this->attach(burst);
     }
+
+    /**
+    @brief
+        This function updates the states of all the billboards, i.e. their positions, visibilty and dimensions
+    @param dimension
+        the current dimension of the main billboard, we're always using square billboards
+    */
+    void LensFlare::updateBillboardStates(unsigned int dimension, bool lightIsVisible)
+    { 
+        //TODO: position and dimensions need to be calculated for everything but the main burst of the flare
+        for(std::set<WorldEntity*>::const_iterator it = this->getAttachedObjects().begin(); it != this->getAttachedObjects().end(); it++) {
+            Billboard* billboard=static_cast<Billboard*>(*it);
+            billboard->setPosition(this->getPosition());
+            billboard->setVisible(lightIsVisible);
+            billboard->setDefaultDimensions(dimension,dimension);
+        }
+    }
+
+    /**
+    @brief
+        This function updates the alpha values for all billboards except for the one used for Hardware Occlusion Querying
+    @param alpha
+        the new alpha value all visible billboards should use
+    */
+    void LensFlare::updateBillboardAlphas(float alpha)
+    {
+        ColourValue* colour = new ColourValue(1.0f,1.0f,1.0f,alpha);
+        std::set<WorldEntity*>::const_iterator it = this->getAttachedObjects().begin();
+        it++;
+        for(;it!=this->getAttachedObjects().end(); it++) {
+            Billboard* billboard=static_cast<Billboard*>(*it);
+            billboard->setColour(*colour);
+        }
+        delete colour;
+    }
     
-    void LensFlare::updateBillboardPositions()
-    {
-        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?
-        this->cameraDistance_=camera->getPosition().distance(this->getPosition());
-        unsigned int dimension=this->cameraDistance_*this->scale_;
-        
-        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(dimension,dimension);
+    /**
+    @brief
+        This function generates point samples of the main burst billboard according to the fadeResolution and returns how many of them are in the view port
+    @param dimension
+        the current dimension of the main billboard, we're always using square billboards
+    @return
+        the absolute amount of point samples that are currently captured by the camera of the view port
+    */
+    unsigned int LensFlare::getPointCount(unsigned int dimension) const
+    {
+        Ogre::Camera* camera=CameraManager::getInstance().getActiveCamera()->getOgreCamera();
+        Vector3 position = this->getPosition();
+        Vector3 nX = camera->getOrientation().xAxis().normalisedCopy();
+        Vector3 nY = camera->getOrientation().yAxis().normalisedCopy();
+        int halfRes=fadeResolution_/2;
+        int resDim=dimension/fadeResolution_;
+        unsigned int count=0;
+        for(int i=-halfRes;i<=halfRes;i++)
+        {
+            for(int j=-halfRes;j<=halfRes;j++)
+            {
+                Vector3 point=position+(i*resDim)*nX+(j*resDim)*nY;//generate point samples
+                if(camera->isVisible(point))
+                {
+                    count++;
+                }
+            }
+        }
+        return count;
     }
 
@@ -108,9 +169,15 @@
         if(this->isVisible())
         {
-            updateBillboardPositions();
-            if(this->occlusionBillboard_->isVisible()) {
-                unsigned int dimension=this->cameraDistance_*this->scale_;
+            Ogre::Camera* camera=CameraManager::getInstance().getActiveCamera()->getOgreCamera(); //get active Ogre Camera Instance, so we can check whether the light source is visible
+            this->cameraDistance_=camera->getPosition().distance(this->getPosition());
+            unsigned int dimension=this->cameraDistance_*this->scale_;
+            if(!this->fadeOnViewBorder_)
+            {
+                this->fadeResolution_=3;//this is so we can still determine when the billboard has left the screen
+            }
+            unsigned int pointCount=this->getPointCount(dimension);
+            updateBillboardStates(dimension,pointCount>0);
+            if(pointCount>0) {
                 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
@@ -120,11 +187,13 @@
                 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
+                float ratio=(maxCount==0)?0:(pixelCount/maxCount);//prevent division by zero
+                float borderRatio=1.0f;
+                if(this->fadeOnViewBorder_)
+                {
+                    borderRatio=((float) pointCount)/(((float) fadeResolution_)*((float) fadeResolution_));//ratio for the border fade
+                }
                 
-                Billboard* burst=static_cast<Billboard*>(getAttachedObject(1));
-                burst->setColour(*colour);
-                delete colour;
+                //update alpha values of all billboards except the HOQ billboard
+                this->updateBillboardAlphas(std::min(1.0f,std::pow(std::min(ratio,borderRatio),2.0f)));
             }
         }
@@ -133,4 +202,5 @@
     void LensFlare::changedVisibility()
     {
+      
     }
 }
