cl-bodge
graphics system
Introduction into This step-by-step guide will introduce you to cl-bodge
graphics API provided by
cl-bodge/graphics
system starting with core concepts first and introducing more complex
notions later.
cl-bodge/graphics
overview
In Common Lisp, function format allows you to print formatted strings into character streams:
it renders template string into an output by filling control placeholders with supplied
arguments. cl-bodge
adapts this concept for graphics with function render
:
(defun render (output pipeline &rest input &key &allow-other-keys)
...)
Signature looks familiar, isn’t it? Indeed, it resembles format
one except input arguments are
keyword pairs. It works quite similar too!
output
argument is often the target framebuffer for the rendering we want to perform into. If
you pass t
as output
rendering will be performed into default framebuffer just like format
would render string into standard output. But you also can provide texture as a target! All the
machinery required to render directly into texture cl-bodge
will handle for you.
pipeline
is an object representing rendering operation and input
is a list of key-value
pairs to control pipeline
behavior.
Now, output
is a framebuffer or a texture, but what is pipeline
then? It can be various
things, but cl-bodge/graphics
system exposes only one: shader pipeline.
Shader pipelines are defined with defpipeline
macro and assembled from shaders using
make-shader-pipeline
function. Unlike various CL graphics libraries (e.g. CEPL) cl-bodge
shaders are written directly in GLSL. But fear not, live reload of GLSL sources is supported (we
will discuss related configuration later), so you can play with shader output in live
session. Shaders are defined with defshader
macro.
Summing up, to display something via cl-bodge\graphics
:
- Define shaders
- Define a pipeline
- Make a pipeline object
- Optionally, make a framebuffer
- Pass a framebuffer, a pipeline and pipeline arguments to
render
function
Guide How-To
This guide is written in literate programming style - documentation is your code. You can
evaluate provided examples block-by-block in your Common Lisp REPL of choice, or use org-mode
to do the same in a more convenient fasion or execute all code blocks in a buffer at once, or,
ultimately, you can just load any system described below in ASDF definitions section and call
appropriate run-example
functions.
Preparations
Just right before digging deeper into cl-bodge
, lets make little preparations by loading
required dependencies and defining a few of helper functions that will help us in our future
adventures.
(ql:quickload '(cl-bodge/graphics cl-bodge/appkit))
(cl:defpackage :hello-bodge-graphics
(:use :cl :cl-bodge.engine :cl-bodge.graphics)
(:export #:*project-path*
#:merge-project-path))
(cl:in-package :hello-bodge-graphics)
(defparameter *project-path* nil)
(defun merge-project-path (relative-path)
"Construct a full path joining *project-path* or a system-relative-pathname if *project-path*
is nil with provided relative path"
(merge-pathnames relative-path (or *project-path*
(asdf:system-relative-pathname :hello-bodge-graphics "./"))))
If you are evaluating from org-mode, this block will setup correct project path
(setf hello-bodge-graphics:*project-path* (uiop:pathname-directory-pathname %buffer-file-name%))
If you are evaluating in REPL, please set *project-path*
manually:
(setf hello-bodge-graphics:*project-path* "/full/path/to/project/")
Now we are ready to explore the examples! Also check out Configure Emacs for cl-bodge
guide to configure live-reloading of shaders directly from glsl-mode
buffer.
Examples
- Minimal Example
- Only absolutely essential code to bring something up onto screen
- Colored Triangle
- Classic example demonstrating rendering of a simple object
ASDF definitions
Lets arrange ASDF definitions for all of our examples we provided above to load them anytime later instead of manually evaluating code blocks one-by-one.
(asdf:defsystem :hello-bodge-graphics
:description "Guide to graphics subsystem of cl-bodge"
:version "1.0.0"
:author "Pavel Korolev"
:license "MIT"
:mailto "dev@borodust.org"
:depends-on (cl-bodge/graphics cl-bodge/appkit)
:pathname "src"
:serial t
:components ((:file "hello-bodge-graphics")))
(asdf:defsystem :hello-bodge-graphics/pass-through
:description "Pass-through pipeline example for cl-bodge/graphics"
:version "1.0.0"
:author "Pavel Korolev"
:license "MIT"
:mailto "dev@borodust.org"
:depends-on (hello-bodge-graphics)
:pathname "src/pass-through/"
:serial t
:components ((:file "app")))
(asdf:defsystem :hello-bodge-graphics/colored-triangle
:description "Classic colored example for cl-bodge/graphics"
:version "1.0.0"
:author "Pavel Korolev"
:license "MIT"
:mailto "dev@borodust.org"
:depends-on (hello-bodge-graphics)
:pathname "src/colored-triangle/"
:serial t
:components ((:file "app")))