Advertisement

I'm building my first game engine, any book recommendations?

Started by September 09, 2021 07:52 AM
9 comments, last by Wyntyress 3 years, 2 months ago

I've been using freeglut for graphics and writing compute shaders in OpenCL for a bit now and have a solid grasp on both (this being in C++ of course). I'm wanting to make a game engine that has minimal overhead but is easily scalable and manageable (you know, the dream). Basically I want it to be high performance and also have it run on anything that supports OpenGL and OpenCL. My knowledge gaps are primarily in the physics maths area and the more high level parts of a game engine (i.e. entity mangement systems and such). Are there any books that will help me specifically. I have access to anything on Orielly for free (because of my University/College) so it would be nice if it was on there but that isn't a necessity. Also, general advice is welcome.

Thanks to anyone who responds ?

P.S. Also, how feasible is it to add support for smart toasters that have embedded OpenGL support? I like the idea of making something run on a literal toaster.

10 seconds of google search brought this http://index-of.co.uk/Various/3D%20Game%20Programming%20All%20In%20One.pdf

by the way, You wrote you miss some important componets of a game engine. Physics itself is a big topic , and usually is twritten by a group of programmers coding this huge topic alone, so my advice is to use a third party library if you want to write an engine, but if you want to write it all, then math should be the first thing you should learn.

Entity management is a rather finite scope, very easy to accomplish, my biggest concern are your lacking of math concepts, which might hinder your pursue to write a complete engine.

But nothing is lost, for a game engine you need to understand how 3d math works, start with 2d , move to 3d , learn vectors , and matrices (sp ?? )

Advertisement

@Programmer71 Sorry, I should've been clearer. I do have a basic understanding of Quarternions, Lerps, Line Segments and Vectors but I am aware it's not enough. I've also dones stuff with both tensors and matrices but no serious physics computations with them (I've done this stuff in my CS degree). I do have, I guess, somewhere between the best high school math education (in Australia we can do matrix multiplication, imaginary numbers, vectors etc. in high school if you choose the right subject) and a first/second year Engineering students understanding of physics math. I'll probably use bullet for physics I'm thinking and then replace it with my own OpenCL compute kernels as I gain a better understanding, based on your answer.

Also, that google search isn't really what I'm looking for. I do like its 3D modelling stuff which I think I'll find useful but I'm specifically looking for something that focuses on performance and/or low overhead. Thanks anyway for the help though.

@spleesh , do you have a copy of Jason Gregory's Game Engine Architecture?

-- Tom Sloper -- sloperama.com

Do you like 3d modelling or 3d programming, ? it seems to me that you are jumping from two different topics.

Start with opengl , then move to vulkan, because in my opinion, in 2 or 3 years the dominant pipeline will be ray tracing.

I am starting to see also clever algorithms for physycs using signed distance fields and volumetric computations , so i belive that the trend will be to move more and more algorithms in hardware rather than software

Spleesh said:
I'm wanting to make a game engine that has minimal overhead but is easily scalable and manageable

How did you (plan to) achieve that?

You must first understand that a game engine is not made by taking a bunch of third-party libraries to skip the annoying part and start with graphics programming fun. Is the usual mistake people make when they start “making their game engine”. Especially if you write you want to have something small, scalable and with high performance!

Doing something visual is great, that's no question but you should tackle the project from two sites, have something that motivates you and the base architecture. It lasted some years (spare time + a stressfull job in an indie studio) before I had a plan how I'd like to have my projects managed. Writing a game engine is also thinking about the tools you need and before writing even a single line of code, how you want your project to be managed.

I started setting up a Visual Studio project when I began to get into the topic and moved that project around to different workstations from a USB stick. It turned out to be sometimes quiet difficult when those workstations had different version sof the IDE installed, so it took some time to adapt my project for not loosing backwards compatibility with my home setup. Later on I tried build scripts like make/nmake but also had a look at alternatives like ninja. Maybe I didn't handle them properly but it turned out to be kind of a hussle to keep the project up to date all the time, recreating the Visual Studio solution, adjast scripts. A few years ago I read an article on Gamasutra (which I can't find anymore), anyways, that article lead me to the first version of the tool we're currently using for our game (engine) SDK project. It is however also heavy insipred from Unreal's UBT which you also have a look at on GitHub but with a different approach. First, there are no projects, everything can be a project and second, it comes with a custom package manager which uses the vanilla NPM interface offered by GitHub (but could also use any standard NPM service).

Our philosophy is quiet similar to what you mentioned here, instead of a huge monolythic piece of software, we offer a fast and scalable solution system which you can configure however you need it and don't ave to maintain any project files or build scipts; everything is done from our build tool with a single command

Advertisement

David Eberly's books were pretty good back in the days. They still have a loot of good basics in them.

There's also the “Game Engine Gems” series.

When it comes to physics, that's a HUGE area – easily as big as rendering – so you'll probably want to use something pre-existing like the Open Dynamics Engine or Bullet or perhaps PhysX.

enum Bool { True, False, FileNotFound };

@Shaarigan So, to answer your question on how I plan to achieve my goals. I'm basically making wrapper classes (and some procedural stuff too where necessary) for boilerplate code to start with and then I'll go from there.

TLDR: I started with a logger so dw, I'm not just looking to start with ‘graphics fun’. Your project looks cool - although I can't say I'm a huge C# fan - and physics… yeah. I like your build system although I'll be using templates and macros to manage my version of essentially the same thing (at least goal wise).

These interfaces are not exactly going to be necessarily easy to use though. For instance my logger class uses templates to make some logger::log executions get (mostly) compiled out. So, if you define TOAST_RELEASE the function body is empty for logger::log<DEBUG>() calls (but not FATAL and such). I can understand that is annoying syntax for some people, but I like how its both typesafe (unlike macro functions), and allows me to drastically change the program with a single line (i.e. TOAST_RELEASE).

What I'm working on now is essentially wrapping platform specifics in one set of procedures so games don't have to be made explicitly multiplatform (who likes having the #ifdef _WIN32 … all through their code). I did the logger code in a class because OOP allows for easier maintainability etc. but i don't see how the platform code could be efficiently wrapped in a class so I'm using a namespace.

For my current uses the above and a wrapper for rendering boilerplate is all I really need, I'll probably write some OpenCL wrappers with some pre-written kernels and see what affect that has on speed but I need to test that stuff first. Once I have a significant amount of interfaces (i.e. logger, platform, window, renderer etc.) I'll make a class with a start and update method which will be something like this:

class engine
{
protected:
	Logger logger;
	Window win;
	...	
public:
	void start();
	void update();
}

and then I can inherit from it but that's only an intermediate version since inheritance tends to have some unwanted overhead that I want to avoid. Issue is managing all these individual components yourself would be kind of a pain. Once I've got all this I'll probably use wxWidgets - or the engine itself? - to create an editor that would be a mildly scaled down version of hammer or some other primative editor (using xml or json files to manage level formats).

You'll notice I haven't covered physics and that's because I intend to do some more reading before I make decisions about it - but bullet still looks like a good option. I've been reading through the bullet source code to get a better idea as well.

Spleesh said:
These interfaces are not exactly going to be necessarily easy to use though. For instance my logger class uses templates to make some logger::log executions get (mostly) compiled out. So, if you define TOAST_RELEASE the function body is empty for logger::log() calls (but not FATAL and such). I can understand that is annoying syntax for some people, but I like how its both typesafe (unlike macro functions), and allows me to drastically change the program with a single line (i.e. TOAST_RELEASE).

We're doing something similar for logging and profiling our code. I described it ind etail some time ago in this post https://gamedev.net/forums/topic/710402-looking-for-recommendations-on-profiling-tools/5440829/

Spleesh said:
What I'm working on now is essentially wrapping platform specifics in one set of procedures so games don't have to be made explicitly multiplatform (who likes having the #ifdef _WIN32 … all through their code)

We have a couple of compiler/platform specific headers which are used by our wrapper classes. The “System” namespace contains everything platform specific and we can extend that by simply adding more packages to it. This is due to how our build tool manages those packages, paths are added to the project/compilation for each package root directory. Then we have a convention of naming code files, for example maht is placed in a Math package and a Math subdirectory. This leads to unified include paths like

#include <Common/Array.h>
#include <Math/Vector3.h>
...

… eh, ah, so we defined a unified interface to cover common parameter pairs in our system headers and implemented those in the corresponding code files. I did some reasearch and finally got everything to only include that parts of the OS which are really needed, that's why our code looks somehow weird at some places and we have declared our own windows types and alias structs for example. The benefits are that we don't polute our code base with windows header stuff except for what we really need.

Spleesh said:
I did the logger code in a class because OOP allows for easier maintainability etc. but i don't see how the platform code could be efficiently wrapped in a class so I'm using a namespace.

This may be true but we ended up with more static functions which look like classes than really OOP based code. You're free to declare global static functions in C++ which isn't possible in for example C# or Java, that's a benefit ?

namespace Log
{
    api void Write(const char*);
}

leads for example to a call like

Log::Write("Hello World");

Spleesh said:
and then I can inherit from it but that's only an intermediate version since inheritance tends to have some unwanted

I don't see a reason to strictly use OOP, add a macro and then have people write their own game loop is absolutely fine. I took this idea from Urho3D

// Define a platform-specific main function, which in turn executes the user-defined function

// MSVC debug mode: use memory leak reporting
#if defined(_MSC_VER) && defined(_DEBUG) && !defined(URHO3D_WIN32_CONSOLE)
#define URHO3D_DEFINE_MAIN(function) \
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd) \
{ \
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); \
    Urho3D::ParseArguments(GetCommandLineW()); \
    return function; \
}
// MSVC release mode: write minidump on crash
#elif defined(_MSC_VER) && defined(URHO3D_MINIDUMPS) && !defined(URHO3D_WIN32_CONSOLE)
#define URHO3D_DEFINE_MAIN(function) \
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd) \
{ \
    Urho3D::ParseArguments(GetCommandLineW()); \
    int exitCode; \
    __try \
    { \
        exitCode = function; \
    } \
    __except(Urho3D::WriteMiniDump("Urho3D", GetExceptionInformation())) \
    { \
    } \
    return exitCode; \
}
// Other Win32 or minidumps disabled: just execute the function
#elif defined(_WIN32) && !defined(URHO3D_WIN32_CONSOLE)
#define URHO3D_DEFINE_MAIN(function) \
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd) \
{ \
    Urho3D::ParseArguments(GetCommandLineW()); \
    return function; \
}
// Android or iOS or tvOS: use SDL_main
#elif defined(__ANDROID__) || defined(IOS) || defined(TVOS)
#define URHO3D_DEFINE_MAIN(function) \
extern "C" __attribute__((visibility("default"))) int SDL_main(int argc, char** argv); \
int SDL_main(int argc, char** argv) \
{ \
    Urho3D::ParseArguments(argc, argv); \
    return function; \
}
// Linux or OS X: use main
#else
#define URHO3D_DEFINE_MAIN(function) \
int main(int argc, char** argv) \
{ \
    Urho3D::ParseArguments(argc, argv); \
    return function; \
}
#endif

Spleesh said:
to create an editor that would be a mildly scaled down version of hammer or some other primative editor (using xml or json files to manage level formats).

As you might already know, I prefer C# for the tooling and so for the Editor as well. We're currently working on our own C# graphics API which will drive all our graphical tools. We'll then pass a handle to the C++ Engine code which the engine performs off-screen rendering into. That handle is pointing to C# managed byte[] memory which got pinned to the CLR (so it is never changed and could be exchanged to C++) and then put into a Bitmap object, so the engine renders everything into that array buffer, which is held from a C# Bitmap and finally copied to the screen using GDI+ on Windows and Linux as well.

It has some advantages, first and foremost the memory management is done by .NET except for engine specific stuff and debugging the editor will be easier. On the other hand we could also use the entire environment we already have for plugins and a ton of utility code, for example our Swarm package to achieve network wide cooperative development on a virtual file system.

Spleesh said:
I intend to do some more reading before I make decisions about it - but bullet still looks like a good option. I've been reading through the bullet source code to get a better idea as well.

Physics as well as graphics isn't essential to me so counts to the final things to be implemented at all. I guess we'll use a thirdparty physics solution as well (at least for now)

I would highly highly highly recommend Game Code Complete 4! It goes over many many aspects of game engine creation in C++ (Audio, Resource Cache, Rendering, Physics, Input, Scripting and then some). On top of that, it discusses making a game editor in C#. It's the best book I've seen for game engine development fundamentals. Like any game dev book, some of the code is left out of the print and you have to look at the sample code to connect the dots, but it should get you started.

https://www.amazon.ca/Game-Coding-Complete-Fourth-McShaffry/dp/1133776574

https://www.mcshaffry.com/GameCode/

This topic is closed to new replies.

Advertisement