Ogre 3D: Double Buffering

0
55
4 min read

 

OGRE 3D 1.7 Beginner’s Guide

OGRE 3D 1.7 Beginner's Guide

Create real time 3D applications using OGRE 3D from scratch

  • Easy-to-follow introduction to OGRE 3D
  • Create exciting 3D applications using OGRE 3D
  • Create your own scenes and monsters, play with the lights and shadows, and learn to use plugins
  • Get challenged to be creative and make fun and addictive games on your own
  • A hands-on do-it-yourself approach with over 100 examples

Images

        Read more about this book      

(For more resources on this subject, see here.)

Introduction

When a scene is rendered, it isn’t normally rendered directly to the buffer, which is displayed on the monitor. Normally, the scene is rendered to a second buffer and when the rendering is finished, the buffers are swapped. This is done to prevent some artifacts, which can be created if we render to the same buffer, which is displayed on the monitor. The FrameListener function, frameRenderingQueued, is called after the scene has been rendered to the back buffer, the buffer which isn’t displayed at the moment. Before the buffers are swapped, the rendering result is already created but not yet displayed. Directly after the frameRenderingQueued function is called, the buffers get swapped and then the application gets the return value and closes itself. That’s the reason why we see an image this time.

Now, we will see what happens when frameRenderingQueued also returns true.

Time for action – returning true in the frameRenderingQueued function

Once again we modify the code to test the behavior of the Frame Listener

  1. Change frameRenderingQueued to return true:

    bool frameRenderingQueued (const Ogre::FrameEvent& evt)
    {
    std::cout << «Frame queued» << std::endl;
    return true;
    }

  2. Compile and run the application. You should see Sinbad for a short period of time before the application closes, and the following three lines should be in the console output:
    Frame started
    Frame queued
    Frame ended

What just happened?

Now that the frameRenderingQueued handler returns true, it will let Ogre 3D continue to render until the frameEnded handler returns false.

Like in the last example, the render buffers were swapped, so we saw the scene for a short period of time. After the frame was rendered, the frameEnded function returned false, which closes the application and, in this case, doesn’t change anything from our perspective.

Time for action – returning true in the frameEnded function

Now let’s test the last of three possibilities.

  1. Change frameRenderingQueued to return true:

    bool frameEnded (const Ogre::FrameEvent& evt)
    {
    std::cout << «Frame ended» << std::endl;
    return true;
    }

  2. Compile and run the application. You should see the scene with Sinbad and an endless repetition of the following three lines:
    Frame started
    Frame queued
    Frame ended

What just happened?

Now, all event handlers returned true and, therefore, the application will never be closed; it would run forever as long as we aren’t going to close the application ourselves.

Adding input

We have an application running forever and have to force it to close; that’s not neat. Let’s add input and the possibility to close the application by pressing Escape.

Time for action – adding input

Now that we know how the FrameListener works, let’s add some input.

  1. We need to include the OIS header file to use OIS:

    #include "OISOIS.h"

  2. Remove all functions from the FrameListener and add two private members to store the InputManager and the Keyboard:

    OIS::InputManager* _InputManager;
    OIS::Keyboard* _Keyboard;

  3. The FrameListener needs a pointer to the RenderWindow to initialize OIS, so we need a constructor, which takes the window as a parameter:

    MyFrameListener(Ogre::RenderWindow* win)
    {

  4. OIS will be initialized using a list of parameters, we also need a window handle in string form for the parameter list; create the three needed variables to store the data:

    OIS::ParamList parameters;
    unsigned int windowHandle = 0;
    std::ostringstream windowHandleString;

  5. Get the handle of the RenderWindow and convert it into a string:

    win->getCustomAttribute("WINDOW", &windowHandle);
    windowHandleString << windowHandle;

  6. Add the string containing the window handle to the parameter list using the key “WINDOW”:

    parameters.insert(std::make_pair("WINDOW", windowHandleString.
    str()));

  7. Use the parameter list to create the InputManager:

    _InputManager = OIS::InputManager::createInputSystem(parameters);

  8. With the manager create the keyboard:

    _Keyboard = static_cast<OIS::Keyboard*>(_InputManager-
    >createInputObject( OIS::OISKeyboard, false ));

  9. What we created in the constructor, we need to destroy in the destructor:

    ~MyFrameListener()
    {
    _InputManager->destroyInputObject(_Keyboard);
    OIS::InputManager::destroyInputSystem(_InputManager);
    }

  10. Create a new frameStarted function, which captures the current state of the keyboard, and if Escape is pressed, it returns false; otherwise, it returns true:

    bool frameStarted(const Ogre::FrameEvent& evt)
    {
    _Keyboard->capture();
    if(_Keyboard->isKeyDown(OIS::KC_ESCAPE))
    {
    return false;
    }
    return true;
    }

  11. The last thing to do is to change the instantiation of the FrameListener to use a pointer to the render window in the startup function:

    _listener = new MyFrameListener(window);
    _root->addFrameListener(_listener);

  12. Compile and run the application. You should see the scene and now be able to close it by pressing the Escape key.

What just happened?

We added input processing capabilities to our FrameListener but we didn’t use any example classes, except our own versions.

LEAVE A REPLY

Please enter your comment!
Please enter your name here