The Road To Graphics Mastery



After finding myself in a graphics team at Igalia, I need to learn what this is all about.

I bought the third edition of Computer Graphics, Principles and Practice since it came recommended on Stack Overflow. It uses a Microsoft-specific technology called WPF for its teaching. For me that's problematic. I would rather have a testbed I can experiment with from GNU/Linux and without leaving the comfort of my Emacs environment.

First problem: Mimic the corner-cutting subdivsion problem the book opens with. In it, I want to draw polygons in 2D, and have a "Subdivide" button that splits each line of the polygon into thirds, tosses away the start and end thirds, and joins up the result, creating a smoother polygon. The task is to find out how this behaves as the parameters to the problem are varied.

Options considered,

Within an hour I had my own test bed, what I know about JavaScript I learned through unwanted osmosis during my professional career, practically speaking, I can't fault the great feeling I got from results in such a short time, and feel embolded I can learn the principles in this book from my GNU/Linux system.

A 2D Graphics Test Bed

Here's the corner-cutting example application I made from the book's explanation,

Click the points of the Polygon to define it


webm: subdivide animation webm: dual animation

This example is extended with the exercise discussions,

  • Added the cutting fraction. For small values, the edge rounding is more pronounced. For large values, it tends towards the Scottish Flag (humour) (I think it might be chaotic, or I have a bug!)
  • The dual operation is interesting. I couldn't find a polygon whose dual was always self-intersecting, it looks to me like the dual operation always finds a way to untangle a self-intersection polygon.

Ray Tracing

The Ray Tracing algorithm is a fundamentally trivial way to paint a scene,

  1. Place the camera and viewport as desired
For each pixel on the screen
  2. Determine which square on the viewport the pixel falls in
  3. Determine what colour should be assigned this square
  4. Paint the pixel with that colour

The tricks in ray tracing focus mostly on Step 3. adding things like textures and lighting. The rest is simple.

Hardware Specifics


OpenGL also exists, but Vulkan is the latest API, it also has advantages thanks to hindsight,

  • OpenGL state is associated to one on-screen context, the makes multithreading more tricky, since the context must be shared and mutual exclusion must be taken into account in an awkward way.
  • OpenGL hides a lot what the GPU is doing. This is a double edged sword. Error checking done by the driver. Shader compilation is usually delayed until an glDraw*, which means we waste CPU time at draw time when we don't really need to use it then.
  • Each OpenGL implementation, due to its scope, provides its own GLSL compiler. This means you get bugs in one driver that don't exist in other drivers, making portability harder to achieve.

Not so say we need to abandon ship, many critical apps still rely on OpenGL, but Vulkan is an interesting technology, and I need to use it for work, so…

Vulkan was based on AMD's Mantle API. This used an API without a global state, using objects instead. MS released equivalent APIs in D3D, and Apple did also in Metal, since all vendors saw that this lower-level interface was going to be useful to developers.

There are some system packages you first require,

$ pacman -Qg vulkan-devel
vulkan-devel spirv-tools
vulkan-devel vulkan-headers
vulkan-devel vulkan-tools
vulkan-devel vulkan-validation-layers

Thanks to the wonders of Arch, clever people have already figured out how to build and install this stuff, so we can get right to using it!

There's a demo repository that uses git submodules to pull in the various bits you need as well,

This seems like a nice starting point for experimentation,

git clone --recurse-submodules
cmake -G "Unix Makefiles" -H. -Bbuild/linux_debug -DCMAKE_BUILD_TYPE=Debug -DVKB_VALIDATION_LAYERS=ON -DVKB_DEBUG=ON
cmake --build build/linux_debug --config Debug --target vulkan_samples -- -j8
./build/linux_debug/app/bin/Debug/x86_64/vulkan_samples hello_triangle

There's a lot of ceremony around getting a Vulkan instance and devices to which rendering / compute jobs can be submitted. It's easy to set this up, just a lot of grunge work. The interesting parts seem the graphics pipeline, the render pass framework, and the explicit synchronization therein.

Created: 2021-11-28 Sun 17:58