Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/shaders/src/orxonox/graphics/LensFlare.cc @ 9464

Last change on this file since 9464 was 9464, checked in by davidsa, 11 years ago

Updated orxonox::LensFlare, the effect has been expanded by several layers, this needs a lot of tidying up and is only a rough implementation for demonstrative purposes

File size: 10.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 *      Reto Grieder (physics)
25 *   Co-authors:
26 *      ...
27 *
28 */
29
30/**
31  @file LensFlare.cc
32  @brief Implementation of the LensFlare class.
33*/
34
35#include "LensFlare.h"
36
37#include "core/XMLPort.h"
38#include "graphics/Billboard.h"
39#include "CameraManager.h"
40#include "RenderQueueListener.h"
41
42#include <OgreSphere.h>
43#include <OgreRenderWindow.h>
44
45namespace orxonox
46{
47    CreateFactory(LensFlare);
48   
49    LensFlare::LensFlare(BaseObject* creator) : StaticEntity(creator), scale_(1.0f), fadeOnViewBorder_(true), fadeResolution_(7), fadeExponent_(2.0f), colour_(new ColourValue(1.0f,0.9f,0.9f,0.0f))
50    {
51        RegisterObject(LensFlare);
52       
53        this->createBillboards();
54       
55        this->registerVariables();
56    }
57
58    LensFlare::~LensFlare()
59    {
60    }
61
62    void LensFlare::XMLPort(Element& xmlelement, XMLPort::Mode mode)
63    {
64        SUPER(LensFlare, XMLPort, xmlelement, mode);
65        XMLPortParam(LensFlare, "scale", setScale, getScale, xmlelement, mode).defaultValues(1.0f);
66        XMLPortParam(LensFlare, "fadeOnViewBorder", setFadeOnViewBorder, isFadeOnViewBorder, xmlelement, mode).defaultValues(true);
67        XMLPortParam(LensFlare, "fadeResolution", setFadeResolution, getFadeResolution, xmlelement, mode).defaultValues(7);
68        XMLPortParam(LensFlare, "fadeExponent", setFadeExponent, getFadeExponent, xmlelement, mode).defaultValues(2.0f);
69    }
70   
71    void LensFlare::registerVariables()
72    {
73        registerVariable(this->scale_, VariableDirection::ToClient);
74        registerVariable(this->fadeOnViewBorder_, VariableDirection::ToClient);
75        registerVariable(this->fadeResolution_, VariableDirection::ToClient);
76    }
77
78    /**
79    @brief
80        This function creates all the billboards needed for the flare effect
81    */
82    void LensFlare::createBillboards()
83    {
84        //TODO: add more billboards, possibly do some cleaning up, by using a loop
85        this->occlusionBillboard_ = new Billboard(this);
86        this->occlusionBillboard_->setMaterial("lensflare/hoq");
87        this->occlusionBillboard_->setPosition(this->getPosition());
88        this->occlusionBillboard_->setVisible(false);
89        this->occlusionBillboard_->disableFrustumCulling();
90        this->occlusionBillboard_->setRenderQueueGroup(RENDER_QUEUE_HOQ);
91        this->attach(this->occlusionBillboard_);
92       
93        Billboard* burst = new Billboard(this);
94        burst->setMaterial("lensflare/burst");
95        burst->setPosition(this->getPosition());
96        burst->disableFrustumCulling();
97        burst->setVisible(true);
98        this->attach(burst);
99       
100        Billboard* bursthalo = new Billboard(this);
101        bursthalo->setMaterial("lensflare/bursthalo");
102        bursthalo->setPosition(this->getPosition());
103        bursthalo->disableFrustumCulling();
104        bursthalo->setVisible(true);
105        this->attach(bursthalo);
106       
107        bursthalo = new Billboard(this);
108        bursthalo->setMaterial("lensflare/halo1");
109        bursthalo->setPosition(this->getPosition());
110        bursthalo->disableFrustumCulling();
111        bursthalo->setVisible(true);
112        this->attach(bursthalo);
113       
114        bursthalo = new Billboard(this);
115        bursthalo->setMaterial("lensflare/halo2");
116        bursthalo->setPosition(this->getPosition());
117        bursthalo->disableFrustumCulling();
118        bursthalo->setVisible(true);
119        this->attach(bursthalo);
120       
121        bursthalo = new Billboard(this);
122        bursthalo->setMaterial("lensflare/halo3");
123        bursthalo->setPosition(this->getPosition());
124        bursthalo->disableFrustumCulling();
125        bursthalo->setVisible(true);
126        this->attach(bursthalo);
127    }
128
129    /**
130    @brief
131        This function updates the states of all the billboards, i.e. their positions, visibilty and dimensions
132    @param viewDirection
133        normalised vector pointing from the current camera to the point light center
134    @param dimension
135        the current dimension of the main billboard, we're always using square billboards
136    @param lightIsVisible
137        is the (point-)light source currently visible
138    */
139    void LensFlare::updateBillboardStates(Vector3& viewDirection, unsigned int dimension, bool lightIsVisible)
140    { 
141        //TODO: develop a more sane method for determining positions and scale factors of the flare components
142        //A good solution would probably be to introduce a data structure which stores a lens flare configuration
143        int i=0;
144        float step=0.0f;
145        for(std::set<WorldEntity*>::const_iterator it = this->getAttachedObjects().begin(); it != this->getAttachedObjects().end(); it++) {
146            Billboard* billboard=static_cast<Billboard*>(*it);
147            billboard->setPosition(this->getPosition()-viewDirection*step);
148            billboard->setVisible(lightIsVisible);
149            billboard->setDefaultDimensions((i==0?0.5f:1.0f)*(i>2?0.25f:1.0f)*dimension*std::pow((1.0f-step),-1.0f),(i==0?0.5f:1.0f)*(i>2?0.25f:1.0f)*dimension*std::pow((1.0f-step),-1.0f));
150            step=0.25f*(i>2?(i-2):0);
151            i++;
152        }
153    }
154
155    /**
156    @brief
157        This function updates the alpha values for all billboards except for the one used for Hardware Occlusion Querying
158    @param alpha
159        the new alpha value all visible billboards should use
160    */
161    void LensFlare::updateBillboardAlphas(float alpha)
162    {
163        ColourValue* colour = new ColourValue(1.0f,1.0f,1.0f,alpha);
164        *colour+=*this->colour_;
165        std::set<WorldEntity*>::const_iterator it = this->getAttachedObjects().begin();
166        it++;
167        for(;it!=this->getAttachedObjects().end(); it++) {
168            Billboard* billboard=static_cast<Billboard*>(*it);
169            billboard->setColour(*colour);
170        }
171        delete colour;
172    }
173   
174    /**
175    @brief
176        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
177    @param dimension
178        the current dimension of the main billboard, we're always using square billboards
179    @return
180        the absolute amount of point samples that are currently captured by the camera of the view port
181    */
182    unsigned int LensFlare::getPointCount(unsigned int dimension) const
183    {
184        Ogre::Camera* camera=CameraManager::getInstance().getActiveCamera()->getOgreCamera();
185        Vector3 position = this->getPosition();
186        Vector3 nX = camera->getOrientation().xAxis().normalisedCopy();
187        Vector3 nY = camera->getOrientation().yAxis().normalisedCopy();
188        int halfRes=fadeResolution_/2;
189        int resDim=dimension/fadeResolution_;
190        unsigned int count=0;
191        for(int i=-halfRes;i<=halfRes;i++)
192        {
193            for(int j=-halfRes;j<=halfRes;j++)
194            {
195                Vector3 point=position+(i*resDim)*nX+(j*resDim)*nY;//generate point samples
196                if(camera->isVisible(point))
197                {
198                    count++;
199                }
200            }
201        }
202        return count;
203    }
204
205    void LensFlare::tick(float dt)
206    {
207        if(this->isVisible())
208        {
209            Ogre::Camera* camera=CameraManager::getInstance().getActiveCamera()->getOgreCamera(); //get active Ogre Camera Instance, so we can check whether the light source is visible
210            this->cameraDistance_=camera->getPosition().distance(this->getPosition());
211            unsigned int dimension=this->cameraDistance_*this->scale_;
212            if(!this->fadeOnViewBorder_)
213            {
214                this->fadeResolution_=3;//this is so we can still determine when the billboard has left the screen
215            }
216            unsigned int pointCount=this->getPointCount(dimension/2);
217            Vector3 viewDirection=this->getPosition()-camera->getPosition()-camera->getDerivedDirection()*this->cameraDistance_;
218            updateBillboardStates(viewDirection,dimension,pointCount>0);
219            if(pointCount>0) {
220                Ogre::Sphere* sphere=new Ogre::Sphere(this->getPosition(),dimension*0.25*0.5);//0.5 stems from the fact that we scaled down the occlusion billboard
221                float left, right, top, bottom;
222                camera->projectSphere(*sphere,&left,&top,&right,&bottom);//approximate maximum pixel count of billboard with a sphere
223                delete sphere;
224               
225                Ogre::RenderWindow* window = GraphicsManager::getInstance().getRenderWindow();
226                float maxCount=(right-left)*(top-bottom)*window->getWidth()*window->getHeight()*0.25;
227                float pixelCount=this->getScene()->getRenderQueueListener()->getPixelCount();//get pixel count
228                float ratio=(maxCount==0.0f)?0.0f:(pixelCount/maxCount);//prevent division by zero
229                float borderRatio=1.0f;
230                if(this->fadeOnViewBorder_)
231                {
232                    borderRatio=((float) pointCount)/(((float) fadeResolution_)*((float) fadeResolution_));//ratio for the border fade
233                }
234                //update alpha values of all billboards except the HOQ billboard
235                this->updateBillboardAlphas(std::min(1.0f,std::pow(std::min(ratio,borderRatio),this->fadeExponent_)));
236            }
237        }
238    }
239
240    void LensFlare::changedVisibility()
241    {
242     
243    }
244}
Note: See TracBrowser for help on using the repository browser.