Skip to content

Hello World

Simon Tippe edited this page Jul 11, 2020 · 17 revisions

Hello World

In this chapter of the tutorial series we will set up the engine and all dependencies. We will compile the project for the first time and display our first text using the text renderer. In this series we will use the Clion IDE to demonstrate the code because it is available on all major platforms.

Set up

We first need to clone the repository. We will then download all the dependencies with the scripts in the dependencies folder. Scripts After we've done that we can finally open the project with Clion. Clion Open Just select the Git repository in the dialog box. If CMake is already installed then Clion should configure the project. Afterwards it will look like this: Clion Configure On Windows Clion might display that it's not possible to retrieve compiler information. In that case either install a suitable compiler (MSVC) or change the build settings in Clion to detect an already installed compiler.

Compile

We should now be able to compile the project. Note that Clions build configuration might be set to Debug. In that case the engine will be significantly slower compared to release mode (to change the configuration go to Settings->Build, Excecution, Deployment->CMake, and click on + to add a configuration). The first time compiling the project might take a few minutes because of the dependencies. Afterwards a small window should open. Hurray, our first window!

App overview

We will now continue to explore the project. In the src folder there is a class called App. This is our main program.

#ifndef AE_APP_H
#define AE_APP_H

#include <EngineInstance.h>
#include <input/Mouse.h>
#include <input/Keyboard.h>
#include <input/Controller.h>
#include <input/Touch.h>

#define WINDOW_FLAGS AE_WINDOW_RESIZABLE | AE_WINDOW_HIGH_DPI

class App : public Atlas::EngineInstance {

public:
	App() : EngineInstance("Atlas Engine", 1280, 720, WINDOW_FLAGS) {}

	virtual void LoadContent() final;

	virtual void UnloadContent() final;

	virtual void Update(float deltaTime) final;

	virtual void Render(float deltaTime) final;

};

#endif

As we examine the code of the header we can see that there are five methods.

  • Contructor: Is used to set up the main window. If you want to learn more about the Window class have a look at the documentation.
  • LoadContent(): Will be called at the startup of the application, after the constructor. Should be used to set up all important classes and to load the app data.
  • UnloadContent(): Will be called when the app shuts down. Should be used to free all memory and to save important stuff to the harddrive.
  • Update(): Will be called every frame. Is always called before the Render() method. The time paramter is in seconds.
  • Render(): Will be called every frame. Is always called after the Update() method. The time paramter is in seconds. We will now take a look at the source file of the app, where the methods are implemented.
#include "App.h"

std::string Atlas::EngineInstance::assetDirectory = "../data";
std::string Atlas::EngineInstance::shaderDirectory = "shader";

void App::LoadContent() {



}

void App::UnloadContent() {



}

void App::Update(float deltaTime) {



}

void App::Render(float deltaTime) {



}

Atlas::EngineInstance* GetEngineInstance() {

	return new App();

}

Additionally to the methods we also find two strings and a functions that returns an instance of the App class. This is absolutely important because otherwise the App object wouldn't be created. The two strings must be declared somewhere in the codebase. They point the engine to the asset and shader folder location. The shader folder location is always expected to be relative to the asset folder. This means that the shaders should be stored in the folder "../data/shader" relative to the application.

Creating our own Hello World

We now want to add two private members to the header of the App class.

private:
    Atlas::Viewport viewport;

    Atlas::Font font;

The viewport is responsible which part of the window we can render to. It can be understood as a renderable window inside the window. With the font class it is possible to load a true type font and render it as signed distance fields. This should allow us to scale the font however we like. The only notable limitations are scaling it to small, where artifacts might show up. The next changes will be made to the LoadContent() method:

    // Initialize the viewport and the font
    viewport = Atlas::Viewport(0, 0, window.GetWidth(), window.GetHeight());

    font = Atlas::Font("font/roboto.ttf", 88, 5);

Here we just initialize both classes. The second paramter of the font is the pixel size at which the font at a scale of 1 will be rendered, while the third parameter is the padding between the edge of a glyph and the texture border. A larger padding allows for a larger distance field. The last change will be made to the Render() method:

    // Update the viewport in case the window size has changed
    viewport.Set(0, 0, window.GetWidth(), window.GetHeight());

    std::string text = "Hello World!";

    // We want to compute the text dimensions at a scale of 1.0
    float width, height;
    font.ComputeDimensions(text, 1.0f, &width, &height);

    // We want to center the text horizontally and vertically
    auto x = (float)window.GetWidth() / 2.0f - width / 2.0f;
    auto y = (float)window.GetHeight() / 2.0f - height / 2.0f;

    // Render the text using the text renderer
    masterRenderer.textRenderer.Render(&viewport, &font, text,
            x, y);

You might have noticed that there are several classes already present. This is the case because the App class is derived from the EngineInstance class. This gives us an easy access to some important functionality, e.g. the master renderer and the window. Afterwards we can compile again and should see the text being rendered in the center of the window: Hello World