Table of Contents

I’ve been working on a purely functional GUI and I realized that the structures I’ve been using for rendering could be easily abstracted out into a library. The types may seem complex but the ideas are simple enough.

The main idea behind renderable is that all graphics can be broken down into primitives.

Rendering

A rendering is simply an effectful value that draws something on the screen in a specific place. Also needed is an effectful value that releases any resources allocated when creating the rendering. Since both values are created at the same time from here on out a “rendering” will be a tuple of the two. So let’s dive into what we’ll be rendering.

Primitive

First off we have the typeclass Primitive. A primitive is an atomic unit of “graphics”. In my current project I’ve chosen to render boxes, polylines and text. Each of these are a primitive that I’ll use in different combinations to create my interface. Primitive has three associated types - a monad, a transform type and a resource type. The monad represents the context of the primitive rendering calls themselves and in most cases will be the IO monad. If you’re using OpenGL you’ll probably use IO. The transform represents the kind of transformations you will apply to your primitives. I’m using a two dimensional affine transformation but you can use anything. It just represents how a rendering can be changed without having to alter the underlying resources.

Lastly the resource type is whatever datatype holds the resources needed to render primitives. This may be a record that holds shaders or references to windows, fonts, etc. For my current project I’m using a Rez

Primitives must have Hashable instances - this is so they can be cached after being allocated. If you’re using OpenGL like I am then ‘allocation’ means making some IO calls in order to send geometry and other data to the GPU. The compilePrimitive function is where we run the initial IO calls to allocate resources for the datatype’s rendering and then return a tuple of the cleanup function and the draw function. Since all Primitive instances are also instances of Hashable the renderable package will automatically look up any needed renderings in the cache, create new ones and release stale ones without you having to think about it.

Here are some Primitive instances to give you an example - they use another (very) experimental project of mine called gelatin, which at this point is a thin wrapper around gl that provides some very specific things I need for my programs

Composite

The next step up in abstraction applies when you have described some adequate number of primitive types. From here on up you can graphically represent new types as a heterogeneous list of those more primitive types. Element is used to package those primitive types in a list. composite simply takes your type and “decomposes” it into transformed Primitive elements.

This is where making new renderings gets really easy

Rendering a frame

After you have some datatypes to render from primitives it’s dead simple to get them on the screen. All your loop has to keep around is the current data to render and the last rendering cache. Then you can use renderData to render your data to the screen. Here is an example of the function I’m using to render to the screen. There’s only three relevant lines and the rest is GLFW noise

As you can see renderData pulls out the renderings we need from the old cache, creates the new ones, cleans the stale ones, renders your data and returns your new cache that you can use to render the next frame. This way if your interface never changes you don’t have to allocate any new resources - you shouldn’t even have to think about it.

All done

This is all a work in progress but I wanted to get these packages out to hopefully get some feedback before I settle on an API (I’ve already broken it once)! My next article will be about another project called gooey. It’s a monadic layer on top of a previous FRP library I wrote called varying. I just realized how funny the gooey lib looks on hackage

the gooey package

lol