Index

Buffers

Trial provides a convenient wrapper around OpenGL's various types of data buffer objects, at the base of which lies the buffer-object resource. Note that despite the naming, this does not include framebuffer objects, as they are their own thing.

A buffer object includes a buffer-type that describes the data being represented, a buffer-data slot for uploading data, a data-usage hint that tells GL how often the data will be written or read, and a size describing the number of octets the buffer currently represents.

You can dynamically change the buffer with resize-buffer and update the data without reallocation with update-buffer-data. to both you may pass either vectors, direct memory pointers, or other kinds of memory-region descriptor objects.

Vertex Buffers

Most of the time you'll need vertex-buffers, which store per-vertex attribute information. By default these buffers only store single-float element data, and as such your buffer-data should be a single-float specialised vector.

Struct Buffers

For buffers that contain more complex, structured, and possibly nested, data, the struct-buffer provides an abstraction. This uses the gl-struct mechanism to represent opaque octet data in memory with a view from Lisp. It also ensures that the data is properly packed in the required layout.

When you want to access a struct buffer's contents, you should use with-buffer-tx. This macro will take care of uploading the changed data on exit, rather than updating the data with every field you change.

Vertex Struct Buffers

A vertex-struct-buffer allows you to specify a gl-struct for the per-vertex data. This in turn allows you to specify more complicated data for each vertex, including non-float fields.

Uniform Buffers

These are stcruct-buffers that represent a Uniform Buffer Block. UBOs allow you to share a block of data with one or more shader programs at once, and allows for more efficient upload of a whole block of uniforms.

Note that Trial generates the GLSL block definition for you. You must include it in the shader source code where you want to access the uniform block. Usually this is as simple as something like this:

(define-class-shader (my-class :fragment-shader)
  (gl-source (// 'pool 'my-ubo)))

You must also include the buffer in the class' buffer list, so that the shader program can ensure to bind the buffer:

(define-shader-entity my-class ()
  ()
  (:buffers (pool my-ubo)))

By default the uniform block will receive a name translated from the gl-struct's class name. If you would like to customise the name, pass the :binding argument. You can also set it to NIL to disable the binding point name, and instead treat each of the uniforms in the block as globals.

To bind the buffer to a program, bind is used, though this is usually automatically called by the shader-program itself.

Note that uniform buffers, while available in GL3.3, have a limited amount of storage. If that storage limit is too low, or the packing overhead too high, you should consider using shader-storage-buffers instead.

Shader Storage Buffers

These are pretty much the same idea as uniform buffers, but using a different mechanism and packing layout. The packing layout should be far more efficient and allow pretty much direct memory access without padding, and the storage limit guaranteed by the standard is way higher. However, SSBOs are only available in GL 4.3 (or with :arb-shader-storage-buffer-object).