[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 pelinegras voluptuosas on 22 de outubro de 2016 - 1:51 pm

    Hey there! I know this is kind of off topic but I was wondering which blog platform are you using for this website? I’m getting sick and tired of WordPress because I’ve had issues with hackers and I’m looking at options for another platform. I would be great if you could point me in the direction of a good platform.

  2. #2 by Valentine’s Day Gift Ideas for Men on 22 de outubro de 2016 - 1:54 pm

    Hi, this weekend is good in favor of me, for the reason that this time i am reading
    this fantastic educational article here at my residence.

  3. #3 by iamsport.org on 22 de outubro de 2016 - 1:57 pm

    Excellent job, cheers.

  4. #4 by Labouring Jobs Birmingham on 22 de outubro de 2016 - 1:57 pm

    Hey there are using WordPress for your site platform? I’m new to the blog world but I’m trying to get started and create my own. Do you need any coding expertise to make your own blog? Any help would be greatly appreciated!

  5. #5 by Valentines Gifts ideas for him on 22 de outubro de 2016 - 1:59 pm

    Link exchange is nothing else however it is only
    placing the other person’s blog link on your page at suitable
    place and other person will also do similar for you.

  6. #6 by Veronique on 22 de outubro de 2016 - 2:01 pm

    By blocking this process, Garcinia Cambogia works against
    the creation of fat.

  7. #7 by Labouring Jobs Birmingham on 22 de outubro de 2016 - 2:01 pm

    I am always thought about this, appreciate it for putting up.

  8. #8 by gifts for boaters on 22 de outubro de 2016 - 2:05 pm

    Hi there! I’m at work surfing around your blog from my new apple iphone!
    Just wanted to say I love reading through your blog and look forward to all your posts!
    Carry on the outstanding work!

  9. #9 by Edmund on 22 de outubro de 2016 - 2:11 pm

    A number of these products use stimulants and herbs for
    example pyruvate, kola, yerba mate, garcinia cambogia, bitter orange and guaraná
    to reach the thermogenic effect.

  10. #10 by Adelaide on 22 de outubro de 2016 - 2:11 pm

    A lot of these brands truly offer garcinia cambogia free trials but
    before you jump on the bandwagon of natural weight loss, you must equip yourself with the essential knowledge about what the nutritional supplement is, what it does, and
    how to choose the best quality brands for your body.

  11. #11 by http://www.seattleplumbingcompanies2016.org on 22 de outubro de 2016 - 2:18 pm

    Good post. I learn something new and challenging on sites I stumbleupon everyday. It’s always helpful to read content from other writers and use something from their websites. |

  12. #12 by comedy writing on 22 de outubro de 2016 - 2:21 pm

    Hi there just wanted to give you a quick heads up.
    The text in your content seem to be running off the screen in Internet explorer.
    I’m not sure if this is a formatting issue or something to do with
    internet browser compatibility but I figured I’d post to let
    you know. The layout look great though! Hope you
    get the issue fixed soon. Cheers

  13. #13 by cartas antiguas pokemon on 22 de outubro de 2016 - 2:22 pm

    It’s an amazing piece of writing in favor of all the online people; they
    will get advantage from it I am sure.

  14. #14 by serovital hgh on 22 de outubro de 2016 - 2:22 pm

    Hello there. great job. I didn’t anticipate this. This is a striking article.
    Many thanks!

  15. #15 by Heater Plumbing on 22 de outubro de 2016 - 2:48 pm

    After getting this details, they will likely guide you to the clinic best-suited to assist you.

  16. #16 by best golf nets on 22 de outubro de 2016 - 2:57 pm

    OMG! a fantastic article man. Thanks for sharing it.

  17. #17 by what illnesses Do bed Bugs carry on 22 de outubro de 2016 - 2:58 pm

    I am curіous to find out what blog system you happen to Ƅe working wіth?
    I’m еxρeriencing some small secuгity issues with my latest site
    and I’d ⅼike to fіnd somеthing more ѕafeguardᥱd. Do үou have any recommendatіons?

  18. #18 by intarsia pictures on 22 de outubro de 2016 - 3:06 pm

    I don’t know whether it’s just me or if everybody else
    experiencing issues with your site. It appears like some of the written text in your content are running off the screen. Can someone
    else please comment and let me know if this is happening to them
    too? This may be a issue with my web browser because I’ve had this happen before.
    Many thanks

  19. #19 by chiropractors uk on 22 de outubro de 2016 - 3:10 pm

    If you wish for to improve your know-how just keep visiting this
    web page and be updated with the newest news posted here.

  20. #20 by video ads mobile on 22 de outubro de 2016 - 3:18 pm

    Hi there! I know this is kinda off topic nevertheless I’d figured I’d ask.
    Would you be interested in exchanging links or maybe
    guest writing a blog post or vice-versa? My website
    discusses a lot of the same topics as yours and I believe we could greatly benefit from each other.

    If you might be interested feel free to send me an e-mail.

    I look forward to hearing from you! Fantastic blog by the way!

  21. #21 by Fast Plumbing Service on 22 de outubro de 2016 - 3:20 pm

    A Methadone facility supplies the substance abuse
    Methadone to take in area of taking, say Vicodin, Oxycontin, Percocet or perhaps

  22. #22 by serovital-hgh on 22 de outubro de 2016 - 3:20 pm

    We are a group of volunteers and starting a brand new scheme
    in our community. Your web site provided us with valuable information to focus on. You have done an outstanding job and our entire community will be grateful to

  23. #23 by go fund system scam on 22 de outubro de 2016 - 3:29 pm

    Hello there! Do you know if they make any plugins to
    protect against hackers? I’m kinda paranoid about losing everything I’ve worked hard on. Any tips?

  24. #24 by local church groups on 22 de outubro de 2016 - 3:38 pm

    It is the best time to make a few plans for the future and it’s time
    to be happy. I have read this publish and if I may I want to counsel you some fascinating things or tips.
    Maybe you could write subsequent articles referring to this article.
    I desire to read more things about it!

  25. #25 by Carmon on 22 de outubro de 2016 - 3:39 pm

    Hello colleagues, pleasant post annd fastidious arguments commented here, I am actually enjoying by these.

  26. #26 by Escorts in Delhi on 22 de outubro de 2016 - 3:45 pm

    Wonderful beat ! I would like to apprentice while you amend your website, how can i subscribe for a blog site? The account helped me a acceptable deal. I had been a little bit acquainted of this your broadcast provided bright clear idea

  27. #27 by Www.Iamsport.org on 22 de outubro de 2016 - 3:51 pm

    I got what you necessarily mean, many thanks for posting.
    I’m blissful to find this website through google.

  28. #28 by shoes on 22 de outubro de 2016 - 3:54 pm

    Why users still make use of to read news papers when in this technological globe everything is available on web?

  29. #29 by apply pr on 22 de outubro de 2016 - 3:59 pm

    Thank you!

  30. #30 by agen poker online on 22 de outubro de 2016 - 4:04 pm

    I gotta favorite this internet site it seems very helpful extremely

  31. #31 by http://toiletrepairpros.bitbucket.org/ on 22 de outubro de 2016 - 4:15 pm

    Methadone has not been shown to trigger abnormality,
    nevertheless your youngster could experience some side effects such as neonatal
    withdrawal disorder at the time of birth.

  32. #32 by Levi on 22 de outubro de 2016 - 5:06 pm

    What’s up, I wish for to subscribe for this website to obtain most up-to-date updates,
    thus where can i do it please help.

1 814 815 816
(não será publicado)