Zebra Codes

How to Draw Concentric Triangles in a Shader

25th September, 2025

A simple way to draw a triangle, or concentric triangles, in a shader.

Read more: How to Draw Concentric Triangles in a Shader

Given any point (u, v) in space, we wish to find the size of the triangle upon which that point lies. We can then use that size to draw the triangle.

We will define the size of the triangle as the distance between centre and the midpoint of each edge. The triangle is symmetrical about the y axis, with the horizontal edge on the bottom. The centre is at the origin, (0, 0).

  1. Calculate a as
    a = -v.
  2. Calculate b by rotating the edge to be vertical, then taking the horizontal part of the coordinate:
    b = rotate2d((abs(u), v), 90 - α).x
    where α is the angle between the base of the triangle and one side of the triangle.
  3. The size of the triangle is then the greater of a and b:
    size = max(a, b)

The size can then be used to daw the triangle:

  • To draw a filled triangle, colour any points where the size is less than a threshold.
  • To draw a triangular cutout, colour any points where the size is greater than a threshold.
  • To draw concentric triangles, colour any points where sin(size * frequency) > 0.

To make a non-symmetrical triangle perform step 2 twice, once with the angle of the left side and once with the angle of the right side.

To rotate, scale or translate the triangle: rotate, scale or translate (u, v) by the inverse of the effect required before performing this procedure.

Writing Generator Functions in C++

19th November, 2023
C++

Many languages have the ability to let you create generators: a function that can be called multiple times, picking up where it left off and returning a different value each time. Unfortunately C++ does not give you this functionality, however that doesn’t mean that we can’t implement it ourselves.

Read More >

How to Perform an Unbuffered Query in Laravel

26th September, 2023

If you wish to process a very large number of rows from a database then it may be prohibitively expensive to load them all into memory first. Laravel’s chunk() function may look like the solution however this performs a query for each chunk and is therefore extremely slow.

The ideal solution is to disable query buffering and thereby only ever have a single row in memory at once. Note that this option is specific to the MySQL PDO driver.

Read More >

How to Mock a Library with NodeJS, TypeScript, and Jest

18th September, 2023

The ability to provide a mock implementation of functionality is essential to unit testing, however the method for doing so with Jest and TypeScript is not well documented. This tutorial aims to elucidate the method for mocking a JavaScript library that is loaded into your TypeScript project. This is demonstrated with the ws WebSocket library but applies equally to any library, including built-in NodeJS modules.

Read More >

OpenTelemetry Null Span Exporter

24th August, 2023

The OpenTelemetry C++ implementation ships with several exporters for outputting your recorded traces: ostream, HTTP, gRPC, and more. It does not, however, provide a null implementation.

A null exporter is useful in test environments, where you just want to discard instrumentation data. The simple class below provides an implementation of a null span exporter.

Read More >

Impersonation in Laravel 10 with Sanctum

16th August, 2023

Impersonation is a useful tool: it allows an administrator to view the website as if they were logged in as another user, but without having to know their password. The Laravel documentation implies that you can do this using Auth::loginUsingId(), but you will find that this doesn’t work.

Read More >

Building Redis++ with CMake

14th June, 2023

Redis++ is the recommended C++ binding for connecting to a Redis server from a C++ application, however its build script is not entirely friendly towards CMake. It relies upon hiredis, but the make script expects it to already be compiled on the system.

Read More >