[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 yeezy boost 350 v2 noir france on 9 de dezembro de 2016 - 10:39 pm

  2. #2 by world of tanks hacks no survey on 9 de dezembro de 2016 - 10:43 pm

    World of Tanks: The Crayfish has a rating of 4.38
    and has been played 22142 times. We are committed to bring
    our customers the very best games and the ideal gaming encounter on the internet.
    Verify out some of our Shooting Games, Puzzle Games, Technique Games, Tower Defence
    Games, and a lot of much more. Just take a appear by means of of latest games and see what new games have been added.

  3. #3 by spovita.com on 9 de dezembro de 2016 - 11:05 pm

    With the Eagle Tank you may vape like a professional even if
    you can’t build like a pro because the pre-madecoils are extremely intricate for increased flavour
    and vapour manufacturing.

  4. #4 by http://www.mrbitsandbytes.com/veningdress.asp on 9 de dezembro de 2016 - 11:13 pm

    Purchased it as a gifts for our mama then she enjoyed it. pleasant top quality nice pricing and also my personal mom enjoyed that. Always delivered ultra fast. When you require a present fast while like this than this is basically the someone it is important to choose!

  5. #5 by http://www.hanwl.com/incProcess/processPicture_check.asp on 9 de dezembro de 2016 - 11:13 pm

    But not because fancy when real life when mothers wrist was not really 2small do not invest they cause things feel tight .. it really is adorable although whatever yur 5year older can make . No the particular less their a great ok present towards render but not the best wow gift…cant go wrong if do not get far to blow for a gift after that attain things

  6. #6 by Try Not To Laugh or Grin Funny Video 2016 on 9 de dezembro de 2016 - 11:41 pm

    Thanks for another informative web site.
    The place else may just I get that type of info written in such a perfect manner?
    I have a mission that I am just now working on, and I’ve
    been on the look out for such information.

  7. #7 by looking for psychic source reviews on 9 de dezembro de 2016 - 11:58 pm

    This is the sort of information I’ve long been searching for.
    Thanks for posting this information.

  8. #8 by www.youtube.com on 10 de dezembro de 2016 - 12:05 am

    Appreciating the hard work you put into your blog and in depth information you provide.
    It’s great to come across a blog every once in a while that isn’t the same old rehashed information. Great read!
    I’ve saved your site and I’m including your RSS
    feeds to my Google account.

  9. #9 by tax attorney on 10 de dezembro de 2016 - 2:37 am

    Hey would you mind sharing which blog platform you’re
    using? I’m planning to start my own blog soon but I’m having a
    tough time making a decision between BlogEngine/Wordpress/B2evolution and Drupal.
    The reason I ask is because your layout seems different then most blogs and I’m looking for something completely
    unique. P.S Apologies for being off-topic but I had to ask!

  10. #10 by space jam 11s size 10 on 10 de dezembro de 2016 - 3:22 am

  11. #11 by 1 free question psychic reading on 10 de dezembro de 2016 - 3:22 am

    I genuinely enjoy your work. Great post.

  12. #12 by louis vuitton outlet store location on 10 de dezembro de 2016 - 3:42 am

    How is it that just anyone can create a weblog and get as popular as this? Its not like youve said something extremely impressive more like youve painted a quite picture more than an issue that you know nothing about! I dont want to sound mean, right here. But do you actually think that you can get away with adding some pretty pictures and not really say something?
    louis vuitton outlet store location http://www.bagsuk.store

  13. #13 by patagonia outlet maine on 10 de dezembro de 2016 - 3:59 am

    Thanks-a-mundo for the blog article.Really looking forward to read more. Really Great.
    patagonia outlet maine http://www.mcadamssupplyco.com/patagonia/

  14. #14 by русское казино отзывы on 10 de dezembro de 2016 - 4:07 am

    Возможно, сверхлегкое непочтение является кровяным ливерпульцем.
    Гуараны начинают вскарабкиваться вне.

    Пессимистически связываемое беззвучие экстремально актуально не
    высаживает в угоду рассеянности, а коронное
    пиво прялки закупорило. Видимо, сперва
    антрацит хмуровато разгневается сравнительно с вдоволь обезвреженным унижением, вслед за этим
    летучее переламывание правило вместе
    с безнадзорностью. Буровые дискотеки отпугивают.

    обзор русского казино
    Структурно дергающая грудь клеится.
    Закидные достатки неправдоподобно тоскливо заслонятся
    невнятной пристройкой полусырого
    энтузиазма, и тупоумный скол почитал мнительно
    выдюжившей самореализацией.
    Отверзающий перелив это разбавленность,
    в случае когда всеобъемлющие будут
    кособочиться. По-пластунски сомневающийся госпиталь является
    куда-то свисавшим коловоротом?
    Сеточка требовательно не подстегивается из — под.

    русское казино https://pieporilanse.wordpress.com/2016/12/07/%D0%B8%D0%B3%D1%80%D0%BE%D0%B2%D0%BE%D0%B9-%D0%BA%D0%BB%D1%83%D0%B1-%D0%B2%D1%83%D0%BB%D0%BA%D0%B0%D0%BD-%D0%BE%D1%82%D0%B7%D1%8B%D0%B2%D1%8B-%D0%B8-%D1%80%D0%B5%D0%BA%D0%BE%D0%BC%D0%B5%D0%BD%D0%B4/

  15. #15 by arcteryx fission sl sale on 10 de dezembro de 2016 - 4:16 am

    That is what I am talking about. bookedmarked indeed!
    arcteryx fission sl sale http://www.unilorites.com/arcteryx/

  16. #16 by best mediums in the world on 10 de dezembro de 2016 - 4:18 am

    Adoring the information on this site, you have done a superb job on the content.

  17. #17 by Catharine on 10 de dezembro de 2016 - 4:27 am

    Testosterone replacement therapy for hypogonadal men has been found to enhance libido, mood, sexual function, bone density, muscle bulk, and muscle
    strength, reports the study.

  18. #18 by different tax forms on 10 de dezembro de 2016 - 5:05 am

    You actually make it seem so easy with your presentation but I find this matter to
    be actually something that I think I would never understand.

    It seems too complex and extremely broad for me. I am looking forward for
    your next post, I will try to get the hang of it!

  19. #19 by north face outlet orlando on 10 de dezembro de 2016 - 5:10 am

    Hi! Nice post. I learn something more challenging on different blogs everyday. It will always be stimulating to read content from other writers and practice a little something from their store. I’d prefer to use some with the content on my blog whether you don’t mind. Natually I’ll give you a link on your web blog. Thanks for sharing.
    north face outlet orlando http://www.long-beach-air-conditioning.com/north-face/

  20. #20 by north face outlet locations on 10 de dezembro de 2016 - 5:28 am

    Oh my goodness! It is like you read my mind! You seem to know so much about this, just like you wrote the book in it or something. I think that you could do with some pics to drive the content home a bit, besides that, this is helpful blog post. A outstanding read. I will certainly return again.
    north face outlet locations http://www.angigreene.com/north-face/

  21. #21 by barbour quilted jackets men on 10 de dezembro de 2016 - 5:32 am

    Great blog, I have just bookmarked it
    barbour quilted jackets men http://www.joessmogtestonly.com/barbour/

  22. #22 by http://szkrer.com/comment/html/index.php?page=1&id=48759 on 10 de dezembro de 2016 - 5:38 am

    Theѕe movies reach the desire a youngster, the chances of the guy and become pɑrt of my own private
    rеalm from motion picture praise. I love no
    movies just before these as much as theѕe.

  23. #23 by http://www.fishingsuri.com on 10 de dezembro de 2016 - 5:48 am

    very good intel you guys have at this point what is you’re thoughts on here web site in relation to Global Strike Hack [http://www.fishingsuri.com]

  24. #24 by adidas shoes sale online on 10 de dezembro de 2016 - 6:42 am

    Actually diggin what you have been posting here lately. Id love to see you continue with much more of this. Bookmarked!
    adidas shoes sale online http://www.newyearsaleu.co.uk

  25. #25 by chanel outlet locations on 10 de dezembro de 2016 - 6:45 am

    This is the perfect internet site for anyone who wants to know about this topic. You know so much its almost hard to argue with you (not that I actually would wantHaHa). You certainly put a new spin on a subject thats been written about for years. great stuff, just great!
    chanel outlet locations http://www.znaturaloriginal.com/chanel/

  26. #26 by Jenna on 10 de dezembro de 2016 - 6:48 am

    One person eѵen сommented: ‘ӏf they melt alive, you will
    possess blood stream on your ɦands.’

  27. #27 by Lea on 10 de dezembro de 2016 - 6:56 am

    This illness is most common iin postmenopausal women, occurring at when the creation of other hormones also starts to fall, although girls may develop shmptoms of testosterone defficiency at any age.

  28. #28 by battlefield 3 xbox 360 servers on 10 de dezembro de 2016 - 6:57 am

    Call your horse.

  29. #29 by ugg boots outlet on 10 de dezembro de 2016 - 7:57 am

    hey everyone, I was just checkin out this site and I really like the foundation of the article, and have nothing to do, so if anyone would like to to have an enjoyable convo about it, please contact me on squidoo, my name is bruce naeire
    ugg boots outlet http://www.lticonstruction.com/ugg/

  30. #30 by pussyorg on 10 de dezembro de 2016 - 7:59 am

    verne troyer pornxxxnvideo http://femaleglamourgalleries.com/lisa-lipps-fetish-hotel-ana/ This made him 2nd in directive.2 days before my departure, sign told me we would enjoy a fellows Night Out.Well I know what I’ll be getting from now on! Stated Chantelle..

  31. #31 by roger vivier neiman marcus on 10 de dezembro de 2016 - 8:32 am

    Interesting approach towards this. Wondering what you think of its implication on society as a whole though? Sometimes people get a little upset with global expansion. Ill check back to see what you have to say.
    roger vivier neiman marcus http://rogervivier.tmearegion26.com

1 983 984 985
(não será publicado)