4 Home
dxtr edited this page 2026-10-16 11:07:44 +02:00

cl-slug

cl-slug is the data half of the Slug algorithm for Common Lisp. Slug draws shapes made of quadratic Bézier curves, such as glyphs and vector icons, straight from their curves on the GPU. They stay sharp at any size, scale or turn, even in perspective, without a texture of pixels per size.

cl-slug cuts shapes into bands and packs them into the two textures the Slug shaders read. It knows nothing of GPUs or fonts. Its optional system cl-slug/clsl holds the shaders' pixel half, ported from Eric Lengyel's reference shaders to clsl.

cl-slug is one of the libraries of the Pyssel game engine, whose 2D renderer draws text with it, but it does not depend on the engine and is usable on its own.

A first look

(asdf:load-system :cl-slug)

(defvar *store* (cl-slug:make-store))

;; A triangle in ems, y up: three curves of six numbers, X0 Y0 CX CY X1 Y1.
;; A straight line is a curve whose control point lies on it.
(defvar *triangle*
  (cl-slug:store-add *store* #(0.1 0.1  0.5 0.1  0.9 0.1
                               0.9 0.1  0.7 0.5  0.5 0.9
                               0.5 0.9  0.3 0.5  0.1 0.1)))

;; What a renderer gives the shaders: the bounds to draw a quad over, in
;; ems, and eight numbers for the pixel shader, written into its instance data.
(list (cl-slug:shape-xmin *triangle*) (cl-slug:shape-ymin *triangle*)
      (cl-slug:shape-xmax *triangle*) (cl-slug:shape-ymax *triangle*))
;; => (0.099975586 0.099975586 0.89990234 0.89990234)
(let ((instance (make-array 8 :element-type 'single-float)))
  (cl-slug:write-shape-data *triangle* instance 0)
  instance)
;; => #(1.2501144 1.2501144 -0.12498093 -0.12498093 0.0 0.0 0.0 0.0)

;; Before drawing: upload the rows that changed, into an :RGBA16-FLOAT
;; curve texture and an :RG16-UINT band texture, both 4096 texels wide.
(multiple-value-bind (row count) (cl-slug:take-curve-changes *store*)
  (list row count (length (cl-slug:copy-curve-rows *store* row count))))
;; => (0 1 16384)

The bounds are a little off 0.1 and 0.9 because the curve texture holds 16-bit floats: shapes are rounded to them when they are added.

To draw it, see Drawing on the GPU, which renders a shape with cl-gfx from start to finish.

Pages

Using cl-slug

  • Getting Started: requirements, the systems, installing with stift, running the tests.
  • Concepts: how Slug works, and the model of stores, shapes and textures. Read this first.
  • Shapes and Curves: giving curves, lines, fill rules, glyphs from a font, vector icons.
  • Stores: making stores, adding and caching shapes, threads.
  • Textures and Uploading: the GPU textures, uploading each frame, growing them.
  • Shaders: slug-coverage, write-shape-data, the vertex shader, the reference vertex format.
  • Drawing on the GPU: a complete example with cl-gfx.

Reference

Status

Done: the band builder, stores shared by threads, incremental uploads, the ported pixel shader with both fill rules. Pyssel draws text with it. Not yet: the reference shader's optical weight boost, and a port of its vertex dilation for perspective.

Credit and licence

cl-slug is under the MIT License. cl-slug/clsl is ported from Eric Lengyel's reference shaders, https://github.com/EricLengyel/Slug, Copyright 2017 by Eric Lengyel, under the MIT License. Software that uses them and is distributed must give credit: the text is in NOTICE. The Slug patent was dedicated to the public domain on 2026-03-17.