Welcome to the first article in my series A Simple Triangle, or AST for short, which is the brain dump of my learning journey into how to author a very simple cross platform graphics engine using C++ and a variety of software toolkits. I picked the name A Simple Triangle because triangles are one of the fundamental structures that we end up rendering in a graphics system.
By the end of this series I hope to have documented my knowledge about how to do the following things:
They are for me - ok and people like me, who have a fascination with learning software SDKs, programming languages and build systems - particularly for authoring mobile and graphics applications. I found during my research into this area there were fairly few sources of information about how to do 3D graphics programming using a Mac - most resources assume you are on a Windows platform.
On a personal level, I am using this series as a way to motivate (aka force) myself to learn these technologies enough to be able to write about them. I’ll be honest - there were many times when I felt like rage quitting and wondered why am I even doing this - on one occasion while trying to learn Vulkan, I did indeed throw my hands in the air and give up in disgust for a few months (when you start doing Vulkan you will understand…). However due to some strange personality trait I seem to possess, I refused to let these things beat me, so eventually returned to conquer them - at least to a basic level that I was satisifed with.
I figured that by documenting my findings I could use them as a reference for my own hobby projects as well as giving this knowledge back to the developer community - if other developers find this information useful that would also be really awesome! It may take me a while to publish all the articles I’d like to cover in this series due to my limited available spare time, but I’ll try as hard as can!
As a contextual note, I have been a professional mobile application developer since around 2011, mostly doing Android and iOS development (I’ve done a splash of Windows Phone too). I don’t do 3D graphics programming or C++ day to day in my full time job and I’ve only previously done a couple of my own hobby C++ projects in recent years - Mockifer and BoppleTap with Cocos2d-x - so these articles will also cover my journey to try and learn and apply some more contemporary parts of the C++ language.
Here is a list of a few common mobile game engines / SDKs available in the wild for doing cross platform mobile game development. We will not be using any of these, though in my travels I have used most of them to some degree or another:
Instead of using one of these third party engines, we will use some of the following technologies to craft our own:
Thematically we will have a preference to use Vulkan over OpenGL as it seems to be gathering momentum as a viable alternative to OpenGL - especially since Apple announced that it has deprecated OpenGL on their platforms leading to many discussions such as this one. Vulkan can be run on Apple hardware via the MoltenVK integration which supplies us with a Vulkan programmed interface to Apple’s native Metal APIs.
Although Vulkan will become our preferred rendering system, implementing even a basic Vulkan renderer is colossally more difficult than implementing a basic OpenGL renderer. Therefore, the first parts of this series will focus on getting the OpenGL implementation up and running, with Vulkan being introduced in later articles once the foundational dust of our engine has settled a bit.
Note: At the time I authored the first 10 or so articles in this series I had only written from a Mac centric development work flow as it is how I normally write software. In April 2019 I bought myself an Acer Predator Helios 500 Windows gaming laptop - GSync is so unbelievably sweet! - so before publishing these articles I went back and introduced Windows into the mix starting in Part 5 showing how to compile our Android platform on Windows and part 7 which shows how to build our code base as a Windows desktop application using Visual Studio with CMake. I’ll keep a strong focus on how to use a Mac workflow because I feel there are a lot of information gaps around how to do this, but I’ll also cover how to do everything on Windows as well. If you are a Windows only user you will still benefit from following through the initial few articles.
We should end up with the following application types, all compiled from a shared C++ source set:
Our file system will basically end up looking like this:
: root + project-folder + android: Android application and libs + console: MacOS console application + emscripten: Emscripten browser application + ios: iOS application + macos: MacOS application + main: C/C++ source code and assets + windows: Windows desktop application + third-party: Libraries not written by us
As much as possible, we will not commit into our project folder any libraries from external sources. Instead we will author setup scripts that will download and configure third party libraries into the
third-party folder and a couple of other locations. Our project targets will then refer to the libraries in those folders.
main source folder will be linked and included into each of the project targets via mechanisms appropriate to those targets.
We will be using the SDL2 library to provide us with some core cross platform window management and event systems. We will also use some SDL2 addons for things like image loading.
The main reason to use SDL2 is that it is compatible with mobile platforms as well as desktop platforms, and can help us with some of the conditional boilerplate for bootstrapping a graphical application. I found that many Vulkan tutorials only talked about using GLFW on Microsoft Windows. GLFW doesn’t support mobile platforms whereas SDL2 does, so …. our choice is SDL2!
The main graphics systems we will be using are OpenGL/OpenGL ES and Vulkan with MoltenVK for Apple Metal integration.
Specifically, here is the matrix of the platforms that interest me and what they can support:
|Android 5 - 6||-||ES2/ES3||-|
|Android >= 7||-||ES2/ES3||Vulkan|
|iPhone <= 5
iPad <= 4
iPad Mini <= 1
|iPhone >= 5s
iPad >= 5
iPad Mini >= 2
|-||ES2/ES3||Vulkan via MoltenVK|
|Mac < 2012||~3.2+||-||-|
|Mac >= 2012||~3.2+||-||Vulkan via MoltenVK|
So based on this information, our lowest targets can use OpenGL ES2, then from a reasonable pivot point can use Vulkan/Metal. It wouldn’t appear to be worth investing in an OpenGL ES3 path as there is only a tiny slice of our eco system that is capable of ES3 but NOT Vulkan.
So, we will only be implementing our code to work successfully on the following graphics systems:
By the way, the matrix I am presenting here interests me because I still have an old Macbook Pro 2010 along with an original iPad Mini and iPad 2, and my development machine is a Macbook Air 2012 which sits right on the cusp of being Metal capable (thankfully!). I am also not going to target Android 4.x and below, as they have known problems with OpenGL, so our Android minimum will be 5 (Lollipop) which frankly is pretty old anyway. If you didn’t care about the older generation devices that can only do ES2, you could possibly target ES3 as the default OpenGL for mobile though we will stick with ES2 compatible OpenGL in this series.
Links for further reading can be found here:
Before getting into the next article, you should setup your Mac with a few developer tools. Some of these will be very familiar if you do any mobile development.
I’ll be doing a reasonable amount of stuff in these articles using
Terminal and shell scripts, so hopefully that doesn’t scare you off too much.
To begin, you will need to:
Note: It should be possible to run the code in this series for the Mac Console, MacOS and iOS simulator platform targets without an Apple Developer subscripion. Your milage may vary though and if eventually if you want to continue doing Mac and iOS development you will find yourself needing to contribute to Apple’s bank account though an annual Apple Developer subscription.
New Terminal at Folder
We will spend a fair amount of time in
Terminal, often needing to open new Terminal windows in a specific folder. Navigating to a folder in a new Terminal session is tedious and annoying, but there is a MacOS feature you can enable which helps us tremendously.
Servicesitem in the left hand panel.
Files and Folders / New Terminal at Folderoption.
Now whenever you have a Finder window open, you can click the small cog icon and a new option named
New Terminal at Folder will be displayed. Click it and a new Terminal window will open, already navigated to the folder you were looking at.
Show hidden files in Finder
Quite frequently we will want to see all files when looking at a folder in Finder. By default, MacOS will hide any files that start with the period
. character - they are considered to be
hidden files. To show these hidden files, simply press the following keys at the same time:
You will see that any files or folders starting with a period character will appear. Press the key combination again to toggle them to be hidden again.
If you are working in Terminal, you would probably use the
ls command a lot to show what files are in the folder. By default, the hidden files won’t be listed. Add the
-a flag to show them, for example
ls -a. For a nicer list view I often use
Show the directory tree in Terminal
Someone I worked with once showed me the
tree command which when run in a folder, shows all the files and sub folders like this:
To install the
tree command, use Homebrew with the following command:
brew install tree
Easy searching for text in Terminal
The same person also showed me the
ack tool which can be used to easily search for occurances of text within files. For example, if I run the
ack command in the same folder shown in the
tree example, looking for the keyword
platform we would get the following results:
To install the
ack command, use Homebrew with the following command:
brew install ack
Other tools will be installed as we go.
When you have those tools installed, we can begin setting up the foundation of our engine.
End of part 1