// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . // // Includes // #include #include #include #include #include #include #include #include #include "camera.h" #include "landscape.h" #include "snowballs_client.h" #include "mouse_listener.h" // // Namespaces // using namespace NLMISC; using namespace NL3D; using namespace std; namespace SBCLIENT { /// If axis segment is longer than this value then no lens flare is displayed static const float _MaxLensFlareLenght = 0.4f; // // Functions // /** * A lens-flare class * \author Stephane Coutelas * \author Nevrax France * \date 2000 */ class CLensFlare { float _AlphaCoef; /// flare struct _CFlare { NL3D::UMaterial Material; float Width; float Height; float Location; float Scale; _CFlare(NL3D::UTexture *texture, float width, float height, float location, float scale) { // -- -- nicely re-usable class, but why should it know about the snowballs specific driver global Material = Driver->createMaterial (); Material.initUnlit (); Material.setTexture (texture); Material.setBlendFunc (UMaterial::srcalpha, UMaterial::one); Material.setBlend(true); Material.setZFunc (UMaterial::always); Material.setZWrite (false); // quad dimension Width = width; Height = height; // location on the lens-flare ray Location = location; // texture scale Scale = scale; } ~_CFlare() { Driver->deleteMaterial(Material); } }; /// flares due to light std::vector<_CFlare *> _Flares; public: /// constructor CLensFlare() { _AlphaCoef = 1.0f; } ~CLensFlare() { for (std::vector<_CFlare *>::iterator it(_Flares.begin()), end(_Flares.end()); it != end; ++it) delete (*it); _Flares.clear(); } /// add a flare to the flare list void addFlare(NL3D::UTexture * texture, float width, float height, float location = 1.f, float scale = 1.f); void setAlphaCoef(float coef) { _AlphaCoef = coef; } // -- -- random note: show actually shows and is used within update /// lens flare display function void show(); }; /*********************************************************\ addFlare() \*********************************************************/ void CLensFlare::addFlare(UTexture * texture, float width, float height, float location, float scale) { _Flares.push_back(new _CFlare(texture, width, height, location, scale)); } /*********************************************************\ show() \*********************************************************/ void CLensFlare::show() { CMatrix mtx; mtx.identity(); nlassert(Driver!=NULL && !Camera.empty()); Driver->setMatrixMode2D11 (); // Determining axis "screen center - light" vector CMatrix cameraMatrix = Camera.getMatrix(); cameraMatrix.invert(); CVector light = (-100000 * SunDirection); light = cameraMatrix * light; light = Camera.getFrustum().project(light); CVector screenCenter(0.5f,0.5f,0); CVector axis = light - screenCenter; if(axis.norm()>_MaxLensFlareLenght) { return; } // rendering flares vector<_CFlare *>::iterator itflr; for(itflr = _Flares.begin(); itflr!=_Flares.end(); itflr++) { (*itflr)->Material.setColor(CRGBA(255,255,255,(uint8)(_AlphaCoef*255))); CQuadUV quad; float xCenterQuad = screenCenter.x + (*itflr)->Location * axis.x; float yCenterQuad = screenCenter.y + (*itflr)->Location * axis.y; float x,y; x = xCenterQuad - (*itflr)->Width * (*itflr)->Scale / 2.f; y = yCenterQuad - (*itflr)->Height * (*itflr)->Scale / 2.f; quad.V0.set (x, y, 0); x = xCenterQuad + (*itflr)->Width * (*itflr)->Scale / 2.f; y = yCenterQuad - (*itflr)->Height * (*itflr)->Scale / 2.f; quad.V1.set (x, y, 0); x = xCenterQuad + (*itflr)->Width * (*itflr)->Scale / 2.f; y = yCenterQuad + (*itflr)->Height * (*itflr)->Scale / 2.f; quad.V2.set (x, y, 0); x = xCenterQuad - (*itflr)->Width * (*itflr)->Scale / 2.f; y = yCenterQuad + (*itflr)->Height * (*itflr)->Scale / 2.f; quad.V3.set (x, y, 0); quad.Uv0.U = 0.0f; quad.Uv0.V = 1.0f; quad.Uv1.U = 1.0f; quad.Uv1.V = 1.0f; quad.Uv2.U = 1.0f; quad.Uv2.V = 0.0f; quad.Uv3.U = 0.0f; quad.Uv3.V = 0.0f; Driver->drawQuad (quad, (*itflr)->Material); } } static CLensFlare *LensFlare = NULL; static UTextureFile *flareTexture1 = NULL; static UTextureFile *flareTexture3 = NULL; static UTextureFile *flareTexture4 = NULL; static UTextureFile *flareTexture5 = NULL; static UTextureFile *flareTexture6 = NULL; static UTextureFile *flareTexture7 = NULL; void initLensFlare () { // -- -- getting this from a config file would be more re-usable LensFlare = new CLensFlare (); flareTexture1 = Driver->createTextureFile("flare01.tga"); flareTexture3 = Driver->createTextureFile("flare03.tga"); flareTexture4 = Driver->createTextureFile("flare04.tga"); flareTexture5 = Driver->createTextureFile("flare05.tga"); flareTexture6 = Driver->createTextureFile("flare06.tga"); flareTexture7 = Driver->createTextureFile("flare07.tga"); float w = 30/800.0f; float h = 30/600.0f; // shine LensFlare->addFlare (flareTexture3, w, h, 1.f, 16.f); LensFlare->addFlare (flareTexture1, w, h, 1.f, 6.f); LensFlare->addFlare (flareTexture6, w, h, 1.3f, 1.2f); LensFlare->addFlare (flareTexture7, w, h, 1.0f, 3.f); LensFlare->addFlare (flareTexture6, w, h, 0.5f, 4.f); LensFlare->addFlare (flareTexture5, w, h, 0.2f, 2.f); LensFlare->addFlare (flareTexture7, w, h, 0.0f, 0.8f); LensFlare->addFlare (flareTexture7, w, h, -0.25f, 2.f); LensFlare->addFlare (flareTexture1, w, h, -0.4f, 1.f); LensFlare->addFlare (flareTexture4, w, h, -1.0f, 12.f); LensFlare->addFlare (flareTexture5, w, h, -0.6f, 6.f); } void updateLensFlare () { // -- -- todo: see how much of this can be modified to depend on nel // things only, and moved into the lensflare class // vector to sun //============== CVector userLook = MouseListener->getViewDirection (); CVector sunDirection = (-100000 * SunDirection); // cosinus between the two previous vectors //========================================= float cosAngle = sunDirection*userLook/sunDirection.norm(); // alpha //====== float alphaf; if(cosAngle<0) { alphaf = 0; } else { alphaf = 255*(float)(pow(cosAngle,20)); } // landscape's masking sun ? //========================== CMatrix camMatrix; camMatrix = Camera.getMatrix(); camMatrix.setPos(CVector::Null); camMatrix.invert(); CVector tmp = camMatrix * sunDirection; tmp = Camera.getFrustum().project(tmp); uint32 w,h; Driver->getWindowSize(w,h); float sunRadius = 24; // -- -- why 24 CRect rect((uint32)(tmp.x*w)-(uint32)sunRadius,(uint32)(tmp.y*h)-(uint32)sunRadius,2*(uint32)sunRadius,2*(uint32)sunRadius); vector zbuff; Driver->getZBufferPart(zbuff, rect); float view = 0.f; float sum = 0; sint i; // -- -- signed? for(i=0; i<(sint)zbuff.size(); i++) { if(zbuff[i]>=0.99999f) sum ++; } view = sum/(sunRadius*2*sunRadius*2); Driver->setMatrixMode2D11 (); // quad for dazzle //================ uint8 alpha = (uint8)(alphaf*view/2.0f); if(alpha!=0) { Driver->drawQuad(0,0,1,1,CRGBA(255,255,255,alpha)); } // Display lens-flare LensFlare->setAlphaCoef( 1.f - (float)cos(alphaf*view*Pi/(2.f*255.f)) ); LensFlare->show(); } void releaseLensFlare () { delete LensFlare; LensFlare = NULL; Driver->deleteTextureFile(flareTexture1); flareTexture1 = NULL; Driver->deleteTextureFile(flareTexture3); flareTexture3 = NULL; Driver->deleteTextureFile(flareTexture4); flareTexture4 = NULL; Driver->deleteTextureFile(flareTexture5); flareTexture5 = NULL; Driver->deleteTextureFile(flareTexture6); flareTexture6 = NULL; Driver->deleteTextureFile(flareTexture7); flareTexture7 = NULL; } } /* namespace SBCLIENT */ /* end of file */