[PloobsEngine] Tutorial 4 – Lights and Cameras


This tutorial will teach you about the PloobsEngine Lights and Camera System. (tutorials series here)

It is very important to say that in this version the Light system is exclusive of the Deferred Rendering technich. We implemented lights for Forward Render also, but it is not included in the PLoobsEngine (performance issues >.<), we plan in the near future to make a tutorial about Phong Shading using that code as example.

Camera System

The PloobsEngine camera system is quite simple and intuitive. In few words: we have an interface called ICamera where all cameras extends. The engine provides some build in implementation for convenience but everyone can make yours as needed. All IScenes must have at least one camera active. You add, remove, interpolate, change …  cameras using the IWorld property called CameraManger.

Avaliable build-in Cameras:

  • CameraFirstPerson (classic FPS camera without restriction, use mouse and keyboard WASD QZ to controls it)
  • CameraFollowObject (camera that follows a IObject)
  • CameraFollowPath (Camera that follows a previous recorded path)
  • CameraStatic (Camera that does not change its location, normally used as base camera when building others (instead of extending from ICamera, sometimes is easier to extend from CameraStatic))

You can have more than one camera added to the current IWorld’s CameraManager, but only one is active at time (=P)

The following example shows how to add more than one camera in the IWorld and smoothly navigate between them: (this part is very intutive, so we wont bother you with obvious comments)

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using PloobsEngine;
using PloobsEngine.Cameras;
using PloobsEngine.Commands;
using PloobsEngine.DataStructure;
using PloobsEngine.Input;
using PloobsEngine.Light;
using PloobsEngine.Material;
using PloobsEngine.Modelo;
using PloobsEngine.Physics;
using PloobsEngine.Physics.Bepu;
using PloobsEngine.SceneControl;
using PloobsEngine.Utils;
using PloobsEngine.Engine;

namespace IntroductionDemo4._0
    /// Camera Screen
    public class CameraScreens : IScene
        BindKeyCommand bk;

        /// Circular list that holds the cameras (Circular list is a PloobsEngine build in data structure, we will talk about all of them in other tutorial)
        private CircularList camerasNames = new CircularList(3);

        protected override void SetWorldAndRenderTechnich(out IRenderTechnic renderTech, out IWorld world)
            world = new IWorld(new BepuPhysicWorld(-9.8f, true), new SimpleCuller());

            DeferredRenderTechnicInitDescription desc = DeferredRenderTechnicInitDescription.Default();
            desc.UseFloatingBufferForLightMap = true;
            desc.BackGroundColor = Color.CornflowerBlue;
            renderTech = new DeferredRenderTechnic(desc);

        protected override void LoadContent(PloobsEngine.Engine.GraphicInfo GraphicInfo, PloobsEngine.Engine.GraphicFactory factory, IContentManager contentManager)
            base.LoadContent(GraphicInfo, factory, contentManager);                        

            #region Models

            ///Cria uma textura 1x1 com a cor branca
            Texture2D white = factory.CreateTexture2DColor(1,1, Color.White);
                SimpleModel sm = new SimpleModel(factory, "..\\Content\\Model\\cubo");
                sm.SetTexture(white, TextureType.DIFFUSE);

                BoxObject pi = new BoxObject(new Vector3(100, 20, 0), 1,1,1, 5,new Vector3(100, 5, 100),Matrix.Identity,MaterialDescription.DefaultBepuMaterial());
                DeferredNormalShader shader = new DeferredNormalShader();
                ///Setando alguns parametros do material
                shader.SpecularIntensity = 0.01f;
                shader.SpecularPower = 50;
                IMaterial mat = new DeferredMaterial(shader);
                IObject obj3 = new IObject(mat, sm, pi);

                SimpleModel sm = new SimpleModel(factory,"..\\Content\\Model\\cubo");
                sm.SetTexture(white, TextureType.DIFFUSE);

                BoxObject pi = new BoxObject(new Vector3(90, 30, 0), 1,1,1, 10,new Vector3(1),Matrix.Identity,MaterialDescription.DefaultBepuMaterial());
                DeferredNormalShader shader = new DeferredNormalShader();                

                IMaterial mat = new DeferredMaterial(shader);
                IObject obj3 = new IObject(mat, sm, pi);

                SimpleModel sm = new SimpleModel(factory,"..\\Content\\Model\\cenario");
                IPhysicObject pi = new TriangleMeshObject(sm,Vector3.Zero,Matrix.Identity,Vector3.One,MaterialDescription.DefaultBepuMaterial());
                DeferredNormalShader shader = new DeferredNormalShader();
                IMaterial mat = new DeferredMaterial(shader);
                IObject obj3 = new IObject(mat, sm, pi);


            #region NormalLight
            ///Conjunto de luzes direcionais
            DirectionalLightPE ld1 = new DirectionalLightPE(Vector3.Left, Color.White);
            DirectionalLightPE ld2 = new DirectionalLightPE(Vector3.Right, Color.White);
            DirectionalLightPE ld3 = new DirectionalLightPE(Vector3.Backward, Color.White);
            DirectionalLightPE ld4 = new DirectionalLightPE(Vector3.Forward, Color.White);
            DirectionalLightPE ld5 = new DirectionalLightPE(Vector3.Down, Color.White);
            float li = 0.4f;
            ld1.LightIntensity = li;
            ld2.LightIntensity = li;
            ld3.LightIntensity = li;
            ld4.LightIntensity = li;
            ld5.LightIntensity = li;

            ///Creating the first Static Camera
            CameraStatic camx = new CameraStatic(new Vector3(130, 100, 700), Vector3.Zero);
            ///Naming it (To recover later)
            camx.Name = "default";
            camx.FarPlane = 3000;
            ///Adding to the manager (ITS NOT BEING ACTIVATED, JUST ADDED)
            this.World.CameraManager.AddCamera(camx, camx.Name);
            ///NOW ACTIVATING=P (If we add a camera using World.AddCamera(cam) we automatically set this camera as active)
            ///Add to the circular list
            camerasNames.Value = camx.Name;

            ///Same for the second camera (this is not activated)
            CameraStatic cam2 = new CameraStatic(new Vector3(100, 100, 100), Vector3.Zero);
            cam2.Name = "StaticCamera";
            cam2.FarPlane = 3000;
            this.World.CameraManager.AddCamera(cam2, cam2.Name);
            camerasNames.Value = cam2.Name;

            ///Again ...
            CameraStatic cam3 = new CameraStatic(new Vector3(500, 300, 300), Vector3.Zero);
            cam3.Name = "StaticCamera3";
            cam3.FarPlane = 3000;
            this.World.CameraManager.AddCamera(cam3, cam3.Name);
            camerasNames.Value = cam3.Name;
            ///When pressing SPACE, a function will be called, WE COULD use the screen binding (but we did not ... no specific reason ....)
            SimpleConcreteKeyboardInputPlayable ikp = new SimpleConcreteKeyboardInputPlayable(StateKey.PRESS, Keys.Space, KeyStateChange);
            bk = new BindKeyCommand(ikp, BindAction.ADD);

        protected override void Draw(GameTime gameTime, RenderHelper render)
            base.Draw(gameTime, render);
            render.RenderTextComplete("Demo: Preset Cameras", new Vector2(GraphicInfo.Viewport.Width - 315, 15), Color.White,Matrix.Identity);
            render.RenderTextComplete("Space = Move to next camera", new Vector2(GraphicInfo.Viewport.Width - 315, 40), Color.White, Matrix.Identity);

        /// When Escape is pressed
        void KeyStateChange(InputPlayableKeyBoard ipk)
            //if (mundo.CameraManager.ActiveCameraType != State.INTERPOLATING)
                //mundo.CameraManager.SetActiveCamera(camerasNames.Value,InterpolationType.BYSTEP, 0.005f);
                //mundo.CameraManager.SetActiveCamera(camerasNames.Value, InterpolationType.BYTIME, 3);

            ///Advance on position in the circular list
            ///Activate the current camera in the circular list
            ///There are two types of interpolator (take care of the camera transition smoothly). The first takes a fixed time (BYTIME( to make the transition and the second use a fixed speed (BYSTEP))
            this.World.CameraManager.SetActiveCamera(camerasNames.Value, InterpolationType.BYTIME, 3);

        protected override void CleanUp(EngineStuff engine )
            bk.BindAction = BindAction.REMOVE;


Pretty easy =P In the IntroductionDemos you can find this sample and another one showing how to record a path and play it after.


As said in the beggining, Lights are only avaliable if you choose the DeferredRenderTechnich. We have the following Light Types avaliable: (we wont explain what each light is, good reference for this are: http://robertokoci.com/basics-of-light-in-3d-computer-graphics/ and in this marvelous book http://www.realtimerendering.com/book.html)

  • DirectionalLightPE
  • PointLightPE
  • SpotLightPE

The silly name DirectionalLightPE is used because in XNA 4.0, the xna already has a class called DirectionalLight, so to avoid confusion we changed the name (PE = Ploobs Engine =P)

We use Phong Equation to calculate each light contribuition. This blog post from Catalin Zilma shows some implementation details (if you want to play with any deferred rending light code, first look at that post) , we used a slightly diferent aproach.

The Directional Light and the SpotLight can cast Shadow (we will talk about it in the future =P).

You can create your own lights, but it is not simple, you need to extend ILight,extend IDeferredLightMap and create a shader that procces you light and create the light map for it. (we will talk about this in other tutorial).

The Introduction packages has some samples explaining how to add, remove and customize the behavior of the lights. We wont show them here cause this is very straightforward, instead we will show a simple but very interesting sample that integrates lights and physics.

Ball Throw Example

We will build a sample with the following behavior:

  • When left mouse button is clicked, a ball with a point light attached to it will be throw in the direction of the camera target vector
  • When right mouse button is clicked, a point light is placed in the current cameras position

This sample with show lots of things we already seen in last tutorials.

To begin, we need to extend the Point Light, cause we need to update its position every frame according to the Ball. The implementation is show bellow:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine.Light;
using PloobsEngine.Physics;

namespace AdvancedDemo4._0
    /// Point light that follow an object
    public class MoveablePointLight : PointLightPE

        IPhysicObject ob;

        public MoveablePointLight(IPhysicObject obj, Color color, float lightRadius, float lightIntensity)
            : base(obj.Position, color, lightRadius, lightIntensity)
            this.ob = obj;

        public override Vector3 LightPosition
                return ob.Position;
                ob.Position = value;


We just overrided the LightPosition property, return the object position instead of the light static position.

The following code shows how to bind the mouse buttons, create the ball and the point light.

using System;
using PloobsEngine.SceneControl;
using PloobsEngine;
using PloobsEngine.Input;
using Microsoft.Xna.Framework;
using PloobsEngine.Physics.Bepu;
using PloobsEngine.Modelo;
using PloobsEngine.Material;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine.Utils;
using PloobsEngine.Commands;
using Microsoft.Xna.Framework.Input;
using PloobsEngine.Light;
using PloobsEngine.Engine;
using PloobsEngine.Physics;

namespace EngineTestes
    public class LightThrowBepu
        IWorld _mundo;
        Random rd = new Random();
        BindMouseCommand mm0 = null;
        BindMouseCommand mm1 = null;
        GraphicFactory factory;

        public void CleanUp()
            mm0.BindAction = BindAction.REMOVE;

            mm1.BindAction = BindAction.REMOVE;

        public LightThrowBepu(IWorld mundo,GraphicFactory factory)
            this.factory = factory;
            _mundo = mundo;
                ///Register a function to be called when the the mouse is pressed
                InputPlaybleMouseBottom ip1 = new SimpleConcreteMouseBottomInputPlayable(StateKey.PRESS, EntityType.IOBJECT, MouseButtons.LeftButton, mousebuttonteste);
                mm0 = new BindMouseCommand(ip1, BindAction.ADD);
                InputPlaybleMouseBottom ip = new SimpleConcreteMouseBottomInputPlayable(StateKey.PRESS, EntityType.IOBJECT, MouseButtons.RightButton, mousebuttontesteRight);
                mm1 = new BindMouseCommand(ip, BindAction.ADD);


        public void mousebuttontesteRight(MouseState ms)
            PointLightPE pl = new PointLightPE(_mundo.CameraManager.ActiveCamera.Position, StaticRandom.RandomColor(), 100, 5);
            pl.UsePointLightQuadraticAttenuation = true;

        int i = 0;
        public void mousebuttonteste(MouseState ms)
            ///Create an object
            IObject physObj = SpawnPrimitive(_mundo.CameraManager.ActiveCamera.Position, Matrix.CreateRotationX(0.5f));
            physObj.PhysicObject.Velocity = (_mundo.CameraManager.ActiveCamera.Target - _mundo.CameraManager.ActiveCamera.Position) * 15.0f;

            ///Create a light that follow an object
            MoveablePointLight mvp = new MoveablePointLight(physObj.PhysicObject as SphereObject, new Color((float)rd.NextDouble(),(float) rd.NextDouble(),(float) rd.NextDouble()),25, 5);
            mvp.UsePointLightQuadraticAttenuation = true;
            ///Add them to the world
            physObj.Name = "FlyingBall " + ++i;

        /// Create a simple Sphere object


        private IObject SpawnPrimitive(Vector3 pos, Matrix ori)
            ///Load a Model with a custom texture
            SimpleModel sm2 = new SimpleModel(factory,"Model\\ball");
            sm2.SetTexture(factory.CreateTexture2DColor(1,1,Color.White,false), TextureType.DIFFUSE);
            DeferredNormalShader nd = new DeferredNormalShader();
            IMaterial m = new DeferredMaterial(nd);
            SphereObject  pi2 = new SphereObject(pos, 1,0.5f,1,MaterialDescription.DefaultBepuMaterial());
            IObject o = new IObject(m,sm2,pi2);
            return o;


Nothing new here =P, just the same stuff we learned from previous tutorials.

The code for this demo can be found in our Introduction Demos package (called LightThrowBepu.cs and MoveablePointLight.cs), you can download it here. (there are lots of others demos in this package from the previous tutorials =P).

Any doubts, critics, suggestions, pls go to our forum or leave a comment here.

See you guys =P



, , , , , ,

  1. #1 by Tanto knife on 27 de setembro de 2016 - 5:10 pm

    Expédition rapide superbe ! Love it ! !

  2. #2 by singapore pr application on 27 de setembro de 2016 - 5:20 pm

    Great post!

  3. #3 by Samurai Katana Steel on 27 de setembro de 2016 - 5:21 pm

    perfect, fast shipper , communicates, item just as described I love it thank you

  4. #4 by extra resources on 27 de setembro de 2016 - 5:29 pm

    marriage counselor juneau alaska weather

  5. #5 by vitamin c serum 20% hyaluronic acid meera's Beauty on 27 de setembro de 2016 - 5:31 pm

    I have learn some excellent stuff here. Definitely value bookmarking for revisiting.
    I surprise how so much effort you place to make the sort of fantastic informative site.

  6. #6 by promoter on 27 de setembro de 2016 - 5:33 pm

    I always emailed this weblog post page to all my contacts, since if
    like to read it next my links will too.

  7. #7 by http://mustinlake.com/vetrazzo/388.html on 27 de setembro de 2016 - 5:37 pm

    Bought the as being a gifts towards the mother and she enjoyed they. terrific high quality wonderful rate as well as my mother loved it. And sent very accelerated. So if you require a gifts accelerated while like this versus this is actually the a person you need to go for!

  8. #8 by http://www.gamborgbygg.no/sollik/295.html on 27 de setembro de 2016 - 5:38 pm

    But not just as fancy when real life when moms wrist is maybe not 2small dont purchase information technology influence things make tight .. its pretty although whatever yur 5year existing makes . No the particular reduced it really is a great okay present to award yet not one wow gifts…cant get wrong if do not come with much to blow on a gift next take things

  9. #9 by Pixel Gun 3D Hack on 27 de setembro de 2016 - 5:52 pm

    Oh my goodness! Incredible article dude! Thank you so much,
    However I am encountering troubles with your RSS.
    I don’t know the reason why I cannot subscribe to it. Is
    there anybody else having the same RSS problems?
    Anybody who knows the solution can you kindly respond?


  10. #10 by case based on 27 de setembro de 2016 - 5:58 pm

    We are a gaggle of volunteers and opening a new scheme in our community.
    Your site provided us with useful info to work on. You’ve done a formidable activity and our whole group will be grateful
    to you.

  11. #11 by flight delay compensation eurowings on 27 de setembro de 2016 - 6:02 pm

    If it takes a situation after that it bills 27% of any kind
    of settlement gotten plus a EUR25 (₤ 20) administration cost – both consisting of VAT.

  12. #12 by free instagram followers on 27 de setembro de 2016 - 6:05 pm

    Thanks for every other informative site. Where else may just I
    am getting that type of information written in such a
    perfect approach? I’ve a venture that I’m
    just now operating on, and I’ve been at the glance out for such

  13. #13 by situs poker online on 27 de setembro de 2016 - 6:07 pm

    Awesome article.

  14. #14 by Vin home Quan 2 on 27 de setembro de 2016 - 6:08 pm

    Every weekend i used to pay a quick visit this website,
    because i want enjoyment, since this this site conations genuinely pleasant funny material too.

  15. #15 by how to imrove aim in fps on 27 de setembro de 2016 - 6:20 pm

    Howdy! I’m at work browsing your blog from my new apple iphone!

    Just wanted to say I love reading through your blog and
    look forward to all your posts! Keep up the outstanding work!

  16. #16 by situs poker online on 27 de setembro de 2016 - 6:45 pm

    Hi there, I read your blogs daily. Your story-telling style is awesome,
    keep doing what you’re doing!

  17. #17 by Tsuba For Sale on 27 de setembro de 2016 - 6:59 pm

    Great communication with seller.

  18. #18 by best sword on 27 de setembro de 2016 - 6:59 pm

    A+ Beautiful Great Seller just as described. Would use this seller again.

  19. #19 by Rae on 27 de setembro de 2016 - 7:17 pm

    Great info. Lucky me I came across your blog by chance (stumbleupon).

    I’ve saved as a favorite for later!

  20. #20 by Civil Law on 27 de setembro de 2016 - 7:42 pm

    although web sites we backlink to below are considerably not related to ours, we really feel they are basically really worth a go via, so possess a look

  21. #21 by Jon on 27 de setembro de 2016 - 8:00 pm

    I’m really enjoying the theme/design of your web site.
    Do you ever run into any internet browser compatibility
    issues? A number of my blog audience have complained about my website not operating correctly
    in Explorer but looks great in Firefox. Do you have any solutions to help fix this problem?

  22. #22 by mimis senapan angin paling akurat on 27 de setembro de 2016 - 8:11 pm

    Berburu adalah hobby bagi sebagian orang, bahkan sampai ada yang menjadikannya sebagai mata pencaharian.
    Ketika berburu, orang pasti membutuhkan senapan sebagai alat.
    Terlebih lagi di zaman yang serba modern ini. Alat berburu menjadi sesuatu
    yang penting dalam rangka untuk menghemat waktu dan mempermudah kegiatan berburu.

    Untuk melayani kebutuhan para pecinta berburu, pabrik senapan memproduksi bermacam-macam senapan. Mulai
    dari yang kualitas lokal hingga kualitas import. Sedang untuk
    memperlancar proses distribusi senapan sekaligus aksesorisnya, dibangunlah toko-toko senapan di berbagai daerah.

    Jika anda hendak mencari toko yang menjual senapan angin ,
    pastikan anda mengetahui toko senapan terdekat. Hal ini
    bertujuan agar anda tidak menghabiskan banyak uang dan tenaga ketika harus membeli di tempat yang cukup jauh.
    Toko-toko senapan yang dimaksud menyediakan berbagai
    produk senapan yang anda butuhkan. Jika stok
    habis pun anda bisa memesan di toko tersebut.
    Karena salah satu tujuan dibangunnya toko senapan di berbagai daerah adalah untuk memudahkan konsumen dalam mencari
    produk senapan yang diinginkan.

    Jual Senapan Angin Murah
    Senapan Angin Mini

    Senapan jenis ini adalah senapan yang ukurannya
    relatif kecil. Senapan ini memiliki berat 3 kg sehingga tidak begitu berat
    dan mudah dibawa. Panjang senapan 40 cm dengan bahan slombong yang terbuat dari kuningan asli.

    Popornya terbuat dari kayu Mahoni. Senapan jenis ini dapat dipompa dengan maksimal pompa kurang lebih 20 kali untuk penggunaan sekali
    tembak. Jarak tembak yang bisa ditempuh adalah 10 meter.
    Untuk mendapatkan senapan jenis ini, anda hanya cukup mengeluarkan uang sebanyak kurang lebih Rp.

    400.000 rupiah.

    Senapan Angin River Mini

    Senapan jenis ini juga merupakan senapan yang ukurannya relatif kecil.
    Panjang senapan ini adalah 40 cm. larasnya terbuat dari bahan kuningan dengan od 22.
    Senapan jenis ini dapat dipompa maksimal hingga 10 kali.
    Jarak tempuh tembakan antara 15 hingga 30 meter. Senapan ini memiliki alur 12 dan kaliber 4,5 mm.
    kelebihan dari senapan jenis ini adalah dilengkapi pula dengan dudukan teleskop, drat peredam dan pelindung picu.

    Harganya cukup murah, berkisar Rp. 450.000 rupiah.
    Demikian beberapa senapan murah yang bisa anda beli. Walaupun ukurannya relatif kecil dan harganya
    murah dibandingkan senapan yang lain, namun senapan di atas juga memiliki kelebihan tersendiri dan peminatnya pun juga banyak.

    Jika Anda Tertarik ingin membeli Produk salah satu produk diatas atau ingin melihat lihat koleksi senapan angin Anda bisa menghubungi kami melalu kontak dibawah ini
    Website : https://www.senapanangin.co.id/
    PINBBM : 2BE5DE50
    Telp : 0852-3010-2223

  23. #23 by Jack on 27 de setembro de 2016 - 8:46 pm

    I love it whenever people get together and share views.

    Great site, keep it up! http://bing.co.uk

  24. #24 by visiter on 27 de setembro de 2016 - 9:26 pm

    Hey utilisent WordPress ⲣoᥙr νotre Site Plate-forme?
    Јe suis nouveau dajs le mmonde Ԁu blog mais je suis en train de commencer et configurer mma
    propre. Αvez-vous besoіn nécessitent tоut codage HTML expertise ρour
    faire votde propre blog? Toute aide serait
    grandement vraiment appréϲіé!

  25. #25 by betterscooter.com on 27 de setembro de 2016 - 9:57 pm

    Fantastic customer service – extremely pleased and will invest in betterscooter.com http://adf.ly/6249830/banner/www.scamadviser.com/is-betterscooter.com-a-fake-site.html once again !

  26. #26 by situs poker online on 27 de setembro de 2016 - 10:32 pm

    This paragraph offers clear idea designed for the new viewers
    of blogging, that genuinely how to do blogging.

  27. #27 by sword in japan on 27 de setembro de 2016 - 11:12 pm

    Pristine item!! Thanks so much, can’t wait to use it!!!!!!

  28. #28 by Pokemon Go Coins Hack No Survey on 27 de setembro de 2016 - 11:43 pm

    Having read this I thought it was really informative.
    I appreciate you finding the time and effort to put this article together.
    I once again find myself spending way too much time both reading and commenting.
    But so what, it was still worth it!

  29. #30 by polres bojonegoro on 28 de setembro de 2016 - 12:20 am

    Do you have any video of that? I’d love to find out more details.

  30. #31 by poker online on 28 de setembro de 2016 - 1:11 am

    Hi there, just became alert to your blog through Google,
    and found that it is truly informative. I am going to watch out for brussels.
    I’ll be grateful if you continue this in future. A lot of people will be benefited from your
    writing. Cheers!

  31. #33 by how to do a top bun hairstyle on 28 de setembro de 2016 - 2:47 am

    naturally like your website however you have to test the spelling on quite a few of your posts.
    Several of them are rife with spelling issues and I in finding it very bothersome to tell
    the truth on the other hand I’ll certainly come back again.

  32. #35 by my response on 28 de setembro de 2016 - 3:25 am

    marriage counselor valparaiso indiana

1 728 729 730
(não será publicado)