C++

allRGB Rainbow Fractal

The challenge was simple: create an image containing all 16777216 RGB colours in a single image with not one colour missing or duplicated!

Rainbow Fractal

At the time there weren’t many mandelbrot fractal examples so I decided to try and find a way to create an all RGB image of the mandelbrot set. The resulting image is a 4096x4096 48.1Mb in PNG format. A compressed thumbnail is below; go to allRGB.com if you want to see the full image.

The code I wrote to create the image is available here. It works by first calculating a color mapping representing every RGB color, which is then sorted by Hue.

Next we generate a grayscale mandelbrot image whilst generating a histogram of the range of values in this grayscale image. The histogram is then converted into a cumulative histogram which gives us an offset into the color map. This in effect means we have a bucket of colours to choose from for each grayscale value representing the mandelbrot image.

We can now generate the image at this point by looping through the grayscale mandelbrot image, looking up which histogram bucket the gray pixel is in, use up one of those RGB colours in the bucket and use that colour in the final image.

This simple algorithm does have a drawback of producing weird shapes due to the hue sorting so we randomise the colours contained within each histogram bucket to produce a more pleasing image when viewed from a distance!

I hope that all made sense! It certainly was a fun challenge to do; I can highly recommend giving this challenge a go!

Modern Open GL Drawing a Triangle

So. Let’s talk about OpenGL. What a mess when you compare it with how DirectX has evolved over the years. I first learnt the intricacies of the DirectX API with the XNA framework which I used to create some simple games. This messing led me to start experimenting with shaders, ultimately leading to my work on Detour which had lots of fancy things like local point lights, realtime shadows, water reflection, particle systems and postprocessing effects.

One of the major problems with the DirectX API is that it only works on Windows. Microsoft no longer has the massive monopoly that it used to have and people expect games these days to run on every flavour of platform (Windows, Linux, OSX to name a few). So in practical terms this means you have to use OpenGL; an API that is supposed to work on every platform. What a brilliant idea! So.. how hard can it be to use OpenGL?

Drawing a Triangle to the Screen

Lets try something simple, like drawing a triangle to the screen. Sounds good!

First we need to open a window. This part is platform specific, and people usually resort to a libraries like GLFW, GLEW and GLUT to handle things like creating a window, loading the OpenGL functions and handling mouse and keyboard input. For this post I’ll be using my own library I’ve cooked up called GLWT, the OpenGL Window Toolkit! The toolkit is very much a work in progress but enough stuff is working for me to be able to write this post. It only works for Macs at the moment, but I plan to make it work on Windows and Linux eventually.

Next we need to think about which version of the OpenGL API to use. OpenGL has a long history and a lot of old applications use the old, immediate mode API. These are the functions that pop up everywhere whenever you type ‘OpenGL tutorial’ into Google. For example, this is the old way of drawing a triangle to a screen:

void Draw()
{
    glBegin(GL_TRIANGLE_STRIP);
    glVertex2f(0.0f, 0.75f);
    glVertex2f(-0.5f, 0.25f);
    glVertex2f(0.5f, 0.25f);
    glEnd();
}

The code above, whilst simple, is innefficient since you have to copy the triangles from the CPU to GPU every single frame. You also get loads of function calls and User -> Kernel mode switches. You can’t do cool things with this setup like vertex and pixel/fragment shaders, or geometry shaders, or render to a texture, or add realtime shadows, etc. Ouch.

So what’s the solution? OpenGL Core Profile! This removes all of the old fixed pipeline calls and replaces them with buffer objects which you only update when you need to. It is a lot more complicated, but you can do way more cool stuff. Here’s how you draw a triangle to the screen:

struct Vertex
{
    float x, y, z;
};

GLuint vertexBuffer, indexBuffer, vertexLayout;

bool Game::Setup(int argc, const char** argv)
{
    Window::Open(800, 600, false, "Hello World!");

    GL::ClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    Vertex verts[] =
    {
        { 0.0f, 0.75f, 0.0f },
        { -0.5f, 0.25f, 0.0f },
        { 0.5f, 0.25f, 0.0f }
    };
    unsigned short inds[] =
    {
        0, 1, 2
    };

    //Create the vertex buffer object, then set it as the current buffer, then copy the vertex data onto it.
    GL::GenBuffers(1, &vertexBuffer);
    GL::BindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    GL::BufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts, GL_STATIC_DRAW);

    //Create the index buffer object, set it as the current index buffer, then copy index data to it.
    GL::GenBuffers(1, &indexBuffer);
    GL::BindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
    GL::BufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(inds), &inds, GL_STATIC_DRAW);

    //Create the vertex layout
    GL::GenVertexArrays(1, &vertexLayout);
    GL::BindVertexArray(vertexLayout);

    //The vertex layout has 3 floats for position
    GL::VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), BUFFER_OFFSET(0));
    GL::EnableVertexAttribArray(0);

    return true;
}

void Game::Draw(float deltaTime)
{
    GL::Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    GL::BindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
    GL::BindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    GL::DrawRangeElements(GL_TRIANGLES, 0, 3, 3, GL_UNSIGNED_SHORT, NULL);
}

As you can see this is much more complicated, however the code above is not enough for the triangle to appear on the screen. We need to write a vertex shader and a fragment shader first. Blimey. Lets see how to do that.

Shaders!

OpenGL shaders are written in a language called GLSL, the OpenGL Shading Language.

Vertex shaders are basically a function that gets executed by your graphics card for every vertex, and it is usually where you do things like multiply it by a world view projection matrix to get the 2D position on the screen. Here is an example which just returns the vertex position without doing any processing:

in vec3 inVertex;
void main()
{
    gl_Position = vec4(inVertex, 1.0);
}

Fragment shaders are a function that gives the colour for each pixel in the triangle being drawn. The example shown here gives the triangle a nice blue colour. Yum:

out vec4 FragColor;
void main()
{
    FragColor = vec4(0.0, 0.0, 1.0, 1.0);
}

Putting it all Together

So we now have some GLSL code that will put the triangles onto the screen in a nice blue colour. We now need to tell OpenGL to load all of that shader code, turn it into a single shader object and apply it to the triangle we will draw to the screen. This code will load and compile the vertex and fragment shader, then put them into a shader program object:

//Create the shader program
shaderProgram = GL::CreateProgram();

//Create the vertex and fragment shader
vertexShader = GL::CreateShader(GL_VERTEX_SHADER);
fragmentShader = GL::CreateShader(GL_FRAGMENT_SHADER);
int vertexCodeLen = (int)strlen(vertexShaderCode);
int fragmentCodeLen = (int)strlen(fragmentShaderCode);

//Load the shader source code and compile it
GL::ShaderSource(vertexShader, 1, &vertexShaderCode, &vertexCodeLen);
GL::ShaderSource(fragmentShader, 1, &fragmentShaderCode, &fragmentCodeLen);
GL::CompileShader(vertexShader);
GL::CompileShader(fragmentShader);

char log[255];
int len;
bool hadError = false;
GL::GetShaderInfoLog(vertexShader, 255, &len, (char*)&log);
if (len > 0) {
    std::cout << "Vertex Compile error:" << std::endl << log << std::endl;
    hadError = true;
}
GL::GetShaderInfoLog(fragmentShader, 255, &len, (char*)&log);
if (len > 0) {
    std::cout << "Fragment Compile error:" << std::endl << log << std::endl;
    hadError = true;
}

if (hadError)
    return false;

GL::AttachShader(shaderProgram, fragmentShader);
GL::AttachShader(shaderProgram, vertexShader);

//Bind the vertex position to the inVertex variable in the vertex shader
GL::BindAttribLocation(shaderProgram, 0, "inVertex");

//Link the shader program
GL::LinkProgram(shaderProgram);
GL::UseProgram(shaderProgram);

Putting this code into the Game::Setup() function will cause a nice blue triangle to draw on the screen.

A Blue Triangle drawn to the screen

So obviously this is a teeny tiny first step into the exciting world of graphics programming. Now that the low-level faffing is finished with we can get into more interesting stuff like lighting models, shadows and so on to get a more accurate image. I hope to cover this sort of stuff in future articles!

Kinect Sports: Season Two

Kinect Sports: Season Two was a Xbox 360 game developed by Rare and Big Park for the Kinect as a direct sequel to the BAFTA award winning Kinect Sports title. I worked on the game at Rare as an intern software engineer between my second and third year of University.

Kinect Sports: Season Two Logo

I arrived at the studio during the final few weeks of Kinect Sports bug testing before release, so I was pulled in to assist with some of the servers that would support the final game when launched. After that I was put onto the pre production tools team helping to prepare Kinect Sports: Season Two for production. This involved fixing bugs and improving the art content, localisation and performance metrics reporting pipelines working mainly in C++ and C#.

Golf

After this the game moved into production and I was moved onto the core engine team working in C++ where I wrote a new GPU and CPU profiler for the internal game engine. I was then put on the multiplayer team where I worked directly with Artists and Designers on the ‘Challenge Play’ gameplay mode. This mode glued all of the various game modes together into a new mode which allowed you to challenge your Xbox Live friends and local profiles on the same Xbox asynchronously.

Challenge Gameplay Mode

Implementing this feature involved modifying the game code for each game to support async challenges and implementing the user interface using a combination of C++ and Actionscript since Scaleform was used for the UI. Each game mode was implemented differently and in some cases by a team working from a remote office so this presented a challenge at times. There was also an online server component that delivered notifications of a challenge from an Xbox Live friend directly from the main menu screen.

Tennis

PlayWithYourPeas

PlayWithYourPeas was a game protoype design challenge posted by Daniel Cook on his Lost Garden blog. He provided the design and art assets and all you had to do was implement it so I had a go! You can either download the installer (windows only) or take a look at the source code.

The design is pretty awesome - you place peas who are convinced they are ninjas on a dinner plate assualt course of your own design. The ninja peas will climb to the top of your towers and jump. The longer they jump and the higher they fall (without squishing themselves) the bigger the score. Score the most points to win!

I implemented the design in C++ using the DirectX 9.0 and Win32 APIs for Window and Mouse Input as well as the Box2D library to do physics collisions and response and the irrKlang library to play the sound effects and music. The sounds effect were recorded and processed by myself using Audacity and the music was from incompetech - a fantastic source of gameplay music.