My graphics engine.

When I started studying OpenGL back in December it was mostly for fun and with very little interest in going deeper in the realm of graphical programming. But now, I find myself spending more and more time digging into OpenGL details or in how to sculpt meshes with Blender.

There are a lot of things to do and even more to learn, the topic is humongous and pretty complicated. At this moment, what I’m doing is writing a simple but complete graphics engine able to handle models rendering, input processing and some basic light/shadow calculation. I started with online courses and still I’m mostly dependent on what I learn from sources like this, but the more I study this topic the more I feel the need for a more advanced source of information, perhaps some book about OpenGL, for sure something about the OpenGL shading language.

Don’t get me wrong, I still spent plenty of time on algorithms! I’m deep into the combinatorics book I got for my birthday and I’m enjoying it, the problem is that I do not have free time anymore.. But I guess that’s the price to pay for my passion, until is fun I’ll not care about the amount of time I spent on it.

What I was able to do..

If you’re following my crowded YouTube channel then you probably already know that one of the things I was working on is a star trek style space game (well, let’s call it game even if it’s not a game..). It was a test of basic functionalities related with OpenGL, rendering models, handle light and handle input from the user which was translated in the movement of the spaceship model. This test demo in working and I’m pretty satisfied about it even if there are some glitches (many of them solved in the past weeks)

For example In the last video of the series about the spaceship game I talked about the artifacts which appeared on the spaceship when I moved it far away from the origin of the scene (0,0,0), that problem had a name: z-fighting, and I solved it by reducing the far/near plane ration in the prospective matrix, and now looks nice in every position of the scene.

z-fighting problem on my spaceship in my spaceship game..

I made some other minor modification to the spaceship game, mostly allowing the random creation of Borg cube and some performance tweaks. If you want to have a look at the code checkout this branch from my github.

This is how looks like the spaceship game engine now, for details checkout the code from the repo.

The NEW Civilization!

In the past weeks I decided to work on a little different format of game, something in the style of Civilization, age of empire or Starcraft.

Everything rotate around a 3D map visible from an high perspective (like a flying eagle see the terrain under him.. I guess you understood what I mean in the first place, but maybe with this smart eagle example it is even clearer! [clearer?] ) on which I can build stuff and move units, I would like to build a classic resource management game. This is completely different from the spaceship game where the player can move the unit everywhere and eventually hit other spaceships, with this latter kind of engine I can build stuff like space exploring adventure or some sort of first person shooter based on space fights..

After some struggles I was able to obtain a working demo of the very basic engine, where I can build map with different terrain types, move over this map and potentially do some actions.. Well.. Actually no action is possible at the moment, but I’m working on it..

A random generated map with three terrains: Mountain, Forest and plains..

There are some cool features in the engine!

First of all the code is able to load many different models and create maps using those models; I can have mountains, forests, deserts or whatever else I might like to add. The only limit are my blender skills which for now are very limited, but I hope to fix this in the upcoming weeks. Each map is made of square lots, each lot is of a certain kind and might have certain properties which can influence the game, for example a forest can be used to collect wood, a mountain to collect stone &c, you know what I mean, the classic resource collecting and construction game.

This is how a mountain looks like if I close up the camera to it. Is not very detailed I know, but considering that I have maybe ten hours of Blender experience I consider this not that bad.. The quality of the models change on the base of the amount of polygons that the engine need to render.

Creating a map is very simple and is required only to load the models and to provide a random (or handmade) map that the engine will use as pattern:

    game_terrain = terrains::terrains::create(&model_shader);
    game_terrain->load_terrain("../models/Grass/grass.obj",
                               glm::vec3(1.0),
                               1);

    game_terrain->load_terrain("../models/Grass/grass2.obj",
                               glm::vec3(1.0),
                               2);

    long mountain_id = game_terrain->load_terrain("../models/Mountain/mountain.obj",
                               glm::vec3(1.0),
                               3);
    game_terrain->load_highres_terrain("../models/Mountain/mountain_highres.obj",
                               mountain_id);

    long forest_id = game_terrain->load_terrain("../models/Forest/Forest.obj",
                               glm::vec3(1.2),
                               4);

    game_terrain->load_highres_terrain("../models/Forest/Forest_complex.obj",
                               forest_id);


    //Generate random terrain map
    const int map_size_x{ 40 };
    const int map_size_y{ 40 };

    std::random_device rd;
    std::mt19937_64 eng( rd() );
    std::uniform_int_distribution<long> dist(1,4);

    terrains::terrain_map_t terrain_map;
    terrain_map.resize( map_size_y );
    for( int y{ 0 } ; y < map_size_y ; ++y ) {
        terrain_map[ y ].resize( map_size_x );
        for( int x{ 0 } ; x < map_size_x ; ++x ) { 
            terrain_map[ y ][ x ] = dist( eng ); 
        } 
    } 
    game_terrain->load_terrain_map( terrain_map,
                                    2,
                                    glm::vec2(map_size_x / 2,
                                              map_size_y / 2) );

Polygons and engine improvements.

The engine will attempt to not draw lot of terrains which are outside the camera view, in this way it save some computational power and attempt to maintain an high frame rate. Since I’m not very good at modelling I had some issues with the amount of vertices in my models, one of the first mountains I created had more and two hundred thousand polygons… Which is a massive amount! Considering that a map might contain dozen of mountains then you can image what trouble my graphics card had to handle such a huge workload. At a certain point my computer was not able to manage more and ten or fifteen frames per second, a very poor result I solved by reducing drastically the amount of polygons in each model.

Sadly there are still a little bit too much of them, so I’ll need to recreate them all after I grow my Blender skills. But, the engine is attempting to help me with those complex models, in fact it can load two types of models for every lot: One high resolution model and one low resolution model, when the amount of polygons which are being rendered is over a certain threshold the engine switch to the lowres models which are way easier to handle.

When the user move the camera away from the terrain the amount of visible lots increase, the engine will then eventually switch to lowres models. That is a cool feature, I mean, it looks cool for me since I’ve never implemented anything similar! And it’s a lot of fun!

This is how a forest looks like in Blender, is still too much complex, having 13000 vertices, 22000 tris.. I guess with some experience I’ll learn how to reduce the complexity of my models.

One more thing I’m very proud of is the ray casting algorithm I’ve implemented to be able to manage the mouse movement over the map, if you notice on the pictures above one of the lots is highlights, that is the result of ray cast from the mouse position on the plane, this allow to select lots, units or in FPS to select a target to shop! To learn how to implement a basic ray casting algorithm I’ve been reading this very interesting page, you might want to have a look at it for some details.

What’s next?

For sure I need to work on the performance, my models are too complex and sometime the frame rate drop under 60 fps, which is very bad considering how simple those tech demo are now. I would like to have also a very basic playable example, a tech demo able to handle units movement and very simple constructions, this is probably the next milestone for my New Civilization game.

Of course, a lot of learning! I’m not sure from where I’ll take the free time to study this fascinating topic, the sprint is coming quickly and presumably I’ll have to spent some time in the outdoor during the weekends, which is going to shrink even more the available time for learning and programming, we’ll see..

Thanks for reading!

Leave a Reply