DPE - Boilerplate code

Boilerplate code

To get started with the Dreaded Portal Engine I present some simple boilerplate code here. This code can be found in "DPE demo" directory. The code creates a scene with a number of cubes and a Camera that can be controlled.

boilerplate.png

We will ignore all the includes in this code example.

We support both Windows and Linux (amonst others), so we check the flags to determine the main function.

/**
* Start the main function.
*/
#ifdef _WIN32
int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR cmdLine,
    int cmdShow)
{
    int argc = 0;
    char** argv = NULL;
#else
int main(int argc, char** argv)
{
#endif

 We start by creating a window with a 1024 x 768 resolution. If creating the window fails then we stop the application immediately.

    // Open our window we want to use for rendering.
    DreadedPE::Window* window = DreadedPE::Window::createWindow(1024, 768, "", false);
    if (window == NULL)
    {
        glfwTerminate();
        return 1;
    }

We start by initialising the textures, this creates the internal datastructures to handle textures. The root of the engine is the SceneManager, this contains the root scene node under which all lights, models, etc. are placed. The first item we add to this tree is a FreeMovingCamera. Next we tell the engine that the camera needs to receive updates every tick.

Then we create the CameraRenderer that takes the scene manager to render and the camera from which to render it from as parameters. The rendering is handled completely by this class. Finally we create a Game instance, this constains the game loop. It is possibe to create a program with your own game loop, but that is not part of this tutorial.

   /**
     * Setup the DPEngine, we use the Camera Renderer.
     */
    DreadedPE::SceneManager scene_manager;
    DreadedPE::FreeMovingCamera camera(scene_manager, &scene_manager.getRoot(), glm::mat4(1.0f), 90, 1024, 768, 0.1f, 60.0f);
    scene_manager.addUpdateableEntity(camera);
    DreadedPE::CameraRenderer* camera_renderer = new DreadedPE::CameraRenderer(scene_manager, camera);
    DreadedPE::Game game(0.05f);

We created a Material for the skybox that is added to the camera; We load the textures and lighting properties. Finally we create an inverted cube and add this cube to the camera node. This will show a landscape and always follows the camera.

    /**
     * We create a skybox for the camera.
     */
    DreadedPE::MaterialLightProperty skybox_ambient(0.2f, 0.2f, 0.2f, 1.0f);
    DreadedPE::MaterialLightProperty skybox_diffuse(0.8f, 0.8f, 0.8f, 1.0f);
    DreadedPE::MaterialLightProperty skybox_specular(0.0f, 0.0f, 0.0f, 1.0f);
    DreadedPE::MaterialLightProperty skybox_emmisive(0.7f, 0.7f, 0.7f, 1.0f);

    std::shared_ptr<DreadedPE::Material> skybox_material(std::make_shared<DreadedPE::Material>(skybox_ambient, skybox_diffuse, skybox_specular, skybox_emmisive));
    DreadedPE::Texture* skybox_texture = DreadedPE::TargaTexture::loadTexture("data/textures/skybox/sp3left.tga", "data/textures/skybox/sp3right.tga", "data/textures/skybox/sp3top.tga", "data/textures/skybox/sp3bot.tga", "data/textures/skybox/sp3back.tga", "data/textures/skybox/sp3front.tga");

    // Initialise the sky box to render.
    skybox_material->addCubeTexture(*skybox_texture);

    std::shared_ptr<DreadedPE::SkyBox> inverted_cube(std::make_shared<DreadedPE::SkyBox>(5.0f));
    new DreadedPE::SkyBoxLeaf(camera, inverted_cube, DreadedPE::SkyBoxShader::getShader(), skybox_material);

With the camera in place, we can now create the scene we want to showcase. In this example we create 125 cubes with a water texture to render. As with the sky box, we create the Material and subsequently we create the cubes. Every cube is a leaf of a seperate node that dictates its position (the cube_entity).

    /**
     * Add a few cubes to showcase.
     */
    DreadedPE::Texture* wfl_texture = DreadedPE::TargaTexture::loadTexture("data/textures/water.tga");

    // Initialise the texture to use.
    DreadedPE::MaterialLightProperty wfl_ambient(0.4f, 0.4f, 0.4f, 1.0f);
    DreadedPE::MaterialLightProperty wfl_diffuse(0.8f, 0.8f, 0.8f, 1.0f);
    DreadedPE::MaterialLightProperty wfl_specular(0.3f, 0.3f, 0.3f, 1.0f);
    DreadedPE::MaterialLightProperty wfl_emmisive(0.6f, 0.6f, 0.6f, 1.0f);

    std::shared_ptr<DreadedPE::Material> wfl_material(std::make_shared<DreadedPE::Material>(wfl_ambient, wfl_diffuse, wfl_specular, wfl_emmisive));
    wfl_material->add2DTexture(*wfl_texture);

    /**
     * Create the shapes.
     */
    std::shared_ptr<DreadedPE::Cube> cube(std::make_shared<DreadedPE::Cube>(1, 1, 1));

    for (int x = -2; x < 3; ++x)
    {
        for (int y = -2; y < 3; ++y)
        {
            for (int z = -2; z < 3; ++z)
            {
                DreadedPE::Entity* cube_entity = new DreadedPE::Entity(scene_manager, &scene_manager.getRoot(), glm::translate(glm::mat4(1.0f), glm::vec3(x * 3, y * 3, z * 3)), DreadedPE::OBSTACLE, "Cube");
                new DreadedPE::SceneLeafModel(*cube_entity, NULL, cube, wfl_material, DreadedPE::BasicShadowShader::getShader(), false, false);
            }
        }
    }

We have created the full scene now.  Finally we add the scene_manager as a game component to the game so it gets updated every tick and rendered as well.

    /**
     * Input handler.
     */
    InputHandler input_handler(game);

    // Start the game.
    game.addGameComponent(scene_manager);
    game.addGameComponent(input_handler);
    game.run();
    
    glfwTerminate();
    return EXIT_SUCCESS;
}

If you run and compile this you should see a scene that is identical to the image at the top of this article and you can use the WASD keys and your mouse to move the camera.

Read how we can add moving lights to this scene in the follow up article: Lights.

Read how we can render millions of cubes in the follow up article: Instance rendering.