LensFlareSceneNode with occlusion query

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
tbw
Posts: 59
Joined: Sat Jan 15, 2011 9:51 am
Location: Germany

LensFlareSceneNode with occlusion query

Post by tbw »

Hi,

for my tech demo I needed a sun with lensflare. Though there is a lensflare scene node in irrExt I was a little bit unhappy with it.
For large camera far values the flares are hopping (I assume that this is a rounding issue in getRayFromScreenCoordinates).
So I decided to create a new one. Here is the result.
sample download with sources
http://www.van-helsing-band.de/irrlicht/lensflare.zip

Image

you are able to custimize the flares:

Code: Select all

        // enum with different flare types (used by SFlareData)
        enum E_FLARE_TYPE
        {
                EFT_SUN = 0,
                EFT_GLOW,
                EFT_LENS,
                EFT_STREAKS,
                EFT_RING,
                EFT_HALO,
                EFT_CIRCLE,
                EFT_POLY,
                EFT_COUNT
        };
 
        // struct holding the flare specification
        struct SFlareData
        {
        public:
                // constructor
                SFlareData(E_FLARE_TYPE type, float position, float scale, video::SColor& color)
                {
                        Type = type;
                        Position = position;
                        Scale = scale;
                        Color = color;
                }
 
                // flare type
                E_FLARE_TYPE Type;
                // position
                f32 Position;
                // flare scale
                f32 Scale;
                // flare color
                video::SColor Color;
        };
Intances of SFlareData are stored in an array

Code: Select all

        protected:
                // flare data array
                core::array<SFlareData> FlareData;
with the corresponding accessor method

Code: Select all

                // returns the flare data array
                core::array<SFlareData>& getFlareData();
you can modify the flares from outside the class.

the render method is straight forward

Code: Select all

void CLensFlareSceneNode::render()
{
        // get the videodriver and the active camera
        video::IVideoDriver* driver = SceneManager->getVideoDriver();
        ICameraSceneNode* camera = SceneManager->getActiveCamera();
 
        // return if we don't have a valid driver or a valid camera 
        // or if we have no texture attached to the material
        if (!camera || !driver || !Material.getTexture(0))
                return;
 
        // get screencenter
        const core::vector2d<s32> screenCenter = core::vector2d<s32>(
                SceneManager->getVideoDriver()->getScreenSize().Width, 
                SceneManager->getVideoDriver()->getScreenSize().Height)/2;
        
        // get screencoordinates of the node
        const core::vector2d<s32> lightPos = SceneManager->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(
                getAbsolutePosition(), 
                camera);
 
        // store old projection matrix 
        core::matrix4 oldProjMat = driver->getTransform(video::ETS_PROJECTION);
        
        // store old view matrix 
        core::matrix4 oldViewMat = driver->getTransform(video::ETS_VIEW); 
 
        // clear the projection matrix 
        driver->setTransform(video::ETS_PROJECTION, core::IdentityMatrix); 
        
        // clear the view matrix 
        driver->setTransform(video::ETS_VIEW, core::IdentityMatrix); 
        
        // set the transform
        driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); 
        
        // set the material
        driver->setMaterial(Material);
        
        // calculate some handy constants
        f32 texPos = 1.0f/EFT_COUNT;
        s32 texHeight = s32(Material.getTexture(0)->getSize().Height*0.5f);
        f32 screenWidth = f32(driver->getScreenSize().Width);
        f32 screenHeight = f32(driver->getScreenSize().Height);
        
        // render the flares
        for (u32 i=0; i<FlareData.size(); ++i)
        {
                // get the flare element
                SFlareData& flare = FlareData[i];
 
                // calculate center of the flare
                core::vector2d<s32>flarePos = screenCenter.getInterpolated(lightPos, -2.0*flare.Position);
 
                // calculate flareposition in vertex coordinates using the scalefactor of the flare
                s32 flareScale = s32((texHeight*flare.Scale));
                core::rect<f32> flareRect = core::rect<f32>(
                        -1.f + 2.f * f32(flarePos.X-flareScale) / screenWidth, 
                        -1.f + 2.f * f32(screenHeight-flarePos.Y-flareScale) / screenHeight, 
                        -1.f + 2.f * f32(flarePos.X+flareScale) / screenWidth, 
                        -1.f + 2.f * f32(screenHeight-flarePos.Y+flareScale) / screenHeight);
                
                // calculate flarecolor in dependence of occlusion
                f32 flareAlpha = f32(flare.Color.getAlpha()) / 255.f;
                video::SColor flareColor(255,
                        (u32)(Strength * flareAlpha * flare.Color.getRed()),
                        (u32)(Strength * flareAlpha * flare.Color.getGreen()),
                        (u32)(Strength * flareAlpha * flare.Color.getBlue()));
                
                // set vertex colors
                Vertices[0].Color = flareColor;
                Vertices[1].Color = flareColor;
                Vertices[2].Color = flareColor;
                Vertices[3].Color = flareColor;
                
                // set texture coordinates
                Vertices[0].TCoords.set(    flare.Type * texPos, 1.0f);
                Vertices[1].TCoords.set(    flare.Type * texPos, 0.0f);
                Vertices[2].TCoords.set((flare.Type+1) * texPos, 0.0f);
                Vertices[3].TCoords.set((flare.Type+1) * texPos, 1.0f);
 
                // set vertex positions
                Vertices[0].Pos.set(flareRect.UpperLeftCorner.X, flareRect.UpperLeftCorner.Y, 0);
                Vertices[1].Pos.set(flareRect.UpperLeftCorner.X, flareRect.LowerRightCorner .Y, 0);
                Vertices[2].Pos.set(flareRect.LowerRightCorner.X, flareRect.LowerRightCorner.Y, 0);
                Vertices[3].Pos.set(flareRect.LowerRightCorner.X, flareRect.UpperLeftCorner.Y, 0);
 
                //draw the mesh
                driver->drawIndexedTriangleList(Vertices, 4, Indices, 2);
        }
        
        // restore view matrix 
        driver->setTransform(video::ETS_VIEW, oldViewMat); 
        
        // restore projection matrix 
        driver->setTransform(video::ETS_PROJECTION, oldProjMat); 
}
using

Code: Select all

                // sets the strength (visibility) of the flares
                void setStrength(f32 strength) { Strength = core::clamp(strength, 0.0f, 1.0f); }
gives the possibility to use an occlusion query result to set the strength of the flares.
In the example I included a SceneNodeAnimatorFollowCamera class that keeps the relative position of the sun constant.
The sample is compiled against a newer trunk of irrlicht (which includes the occlusion query feature)
Thats it, I hope you enjoy it.
Last edited by tbw on Mon Apr 09, 2012 6:31 pm, edited 1 time in total.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: LensFlareSceneNode with occlusion query

Post by hybrid »

Sounds really cool. Can we add this to irrExt or even Irrlicht core?
tbw
Posts: 59
Joined: Sat Jan 15, 2011 9:51 am
Location: Germany

Re: LensFlareSceneNode with occlusion query

Post by tbw »

yes, of course! :D
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: LensFlareSceneNode with occlusion query

Post by Granyte »

wow your stuff is awsome as always
Justei
Posts: 47
Joined: Fri Aug 20, 2010 11:20 am

Re: LensFlareSceneNode with occlusion query

Post by Justei »

This is a REALLY neat looking thing you have got here!
I have a problem though, when I try this out on my project I get the following:
error: 'class irr::video::IVideoDriver' has no member named 'addOcclusionQuery'|

Which is the line
driver->addOcclusionQuery(sunMeshNode, sunMeshNode->getMesh());

Any ideas? :(
Image
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: LensFlareSceneNode with occlusion query

Post by hybrid »

That's a feature of the upcoming Irrlicht 1.8. Maybe just remove any occurences of these methods, and set the flag which checks the occlusion to always succeeding.
ACE247
Posts: 704
Joined: Tue Mar 16, 2010 12:31 am

Re: LensFlareSceneNode with occlusion query

Post by ACE247 »

Thanks for the nice code! Copy pasting into my project. :)
Justei
Posts: 47
Joined: Fri Aug 20, 2010 11:20 am

Re: LensFlareSceneNode with occlusion query

Post by Justei »

hybrid wrote:That's a feature of the upcoming Irrlicht 1.8. Maybe just remove any occurences of these methods, and set the flag which checks the occlusion to always succeeding.
Huh, I see... How different is 1.8 from 1.7.1? I use that and haven't updated in quite a while, but would love to, however don't want to break my whole project lol. Too much work put into it ^^. And are the general changes big or pretty much the same? :)
Image
ACE247
Posts: 704
Joined: Tue Mar 16, 2010 12:31 am

Re: LensFlareSceneNode with occlusion query

Post by ACE247 »

Very similar changes, mainly just added features and bug fixes. But yeah update now while you still can do so easily and update regularly, else it becomes very difficult bringing something made with 1.7 to say version 2.
Justei
Posts: 47
Joined: Fri Aug 20, 2010 11:20 am

Re: LensFlareSceneNode with occlusion query

Post by Justei »

I just updated to 1.7.2, however this still doesn't seem to work, is there a newer version of irrlicht I should try using to get this to work properly? :/
If there is could sum1 link me to a sdk or something like that?
Image
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: LensFlareSceneNode with occlusion query

Post by hybrid »

You can use the latest development version of Irrlicht only by compiling the engine on your own from code in SVN. There's also a nightly build usually, but it might worth switching to SVN anyway if you want to keep up with the development branch.
blackMasoon
Posts: 149
Joined: Wed Sep 09, 2009 4:57 pm
Contact:

Re: LensFlareSceneNode with occlusion query

Post by blackMasoon »

I have compiled the latest version of Irrlicht from SVN and two interesting things happened:

1) Occlusion queries didn't make the lensFlareNode hiding behind other nodes like buildings.

2) Suddenly all collisions (triangle selectors etc.) stopped working thanks to new Irrlicht o.O

Why is that happening?
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: LensFlareSceneNode with occlusion query

Post by Granyte »

hey i'm trying to use your lensflare in a 3d context where the sun position cannot be abstracted to a constant position i tryed adapting by adapting your position detection code but until now i havent had any sucess
tbw
Posts: 59
Joined: Sat Jan 15, 2011 9:51 am
Location: Germany

Re: LensFlareSceneNode with occlusion query

Post by tbw »

...the sun position cannot be abstracted to a constant position i tryed adapting by adapting your position detection code ...
Hey Granyte,
can you give me a little bit of code, so I can have a deeper look into it?
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: LensFlareSceneNode with occlusion query

Post by Granyte »

at first i tryed making the node a child of a sun node i position at (0,0,0) with the camera at an arbitrary (149598,6371,0) the lensflare is not aligned with the node and behave wierd after a while i tryed to update the render() function without sucess
Post Reply