go-gl/glh — pull request #21 by jteeuwen (2012-10-29 13:29:18+00:00)
Title: glh.MeshBuffer: Major overhaul number 2

glh.MeshBuffer: Major overhaul number 2:
* Adds 2 more render modes
* Adds user-configurable attributes.

This patch performs a second overhaul of the `MeshBuffer` type.
Previously we were stuck to using a fixed set of attributes, along
with one render mode using VBO's. This has been fixed.

We now define 3 render modes, which can be selected with a constant
value in the `NewMeshBuffer` call. These render modes are:

// Classic mode uses manual glBegin/glEnd calls to construct the
// mesh. This is extremely slow, and mostly only useful for debugging
// purposes. This implies OpenGL version 'Ye Olde'+.
RenderClassic

// Arrays mode uses vertex arrays which involves gl*Pointer calls and
// directly passing in the vertex data. This is slower than using VBO's,
// because the data has to be uploaded to the GPU on every render pass.
// It is useful for older systems where glBufferData is not available.
// This implies OpenGL version 1.5+.
RenderArrays

// Buffered mode uses VBO's. This is the preferred mode for systems
// where shader support is not present or deemed necessary. This implies
// OpenGL version 2.1+.
RenderBuffered

@pwaller: The `RenderArrays` mode should be what we referred to previously
as `immediate mode` in issues #15 and #16. Please give this a try and see
of this meets with your expectations.

A possible fourth render mode is still missing. This would use VBO's as well,
but uses Vertex Attributes instead of the current `gl*Pointer` calls, so
vertex components can directly be addressed in shader programs. This is why
the `Attr` type currently has a `name` field. I added this in anticipation
of the shader support and will be necessary to provide a complete implementation
of my `freetype-gl` port. This has not been added yet, because I am not familiar
enough with shaders to implement this in a reliable and clean manner.

Creating a new MeshBuffer can now take attributes in any order, and no longer
requires us to explicitly pass `nil` for those components we do not need.
We simply only supply attributes for components we do need. Components being
indices, vertex positions, texture coordinates, normals and colors.

mb := NewMeshBuffer(
// Render our data using VBO's.
glh.RenderBuffered,

// Indices: 1 unsigned short per index; static data.
NewIndexAttr(1, gl.USIGNED_SHORT, gl.STATIC_DRAW),

// Positions: 3 floats; static data.
NewPositionAttr(3, gl.FLOAT, gl.STATIC_DRAW),

// Colors: 4 floats; changing regularly.
NewColorAttr(4, gl.FLOAT, gl.DYNAMIC_DRAW),

// A custom attribute.
NewAttr("customComponent", 3, gl.FLOAT, gl.DYNAMIC_DRAW),
)

The MeshBuffer requires at least one attribute for vertex positions. The rest
is all optional. In the example above, we use the helper functions to create
the index-, position- and color-attributes. These are just wrappers for the
following:

NewAttr("index", 1, gl.USIGNED_SHORT, gl.STATIC_DRAW)
NewAttr("position", 3, gl.FLOAT, gl.STATIC_DRAW)
NewAttr("color", 4, gl.FLOAT, gl.DYNAMIC_DRAW)

They are provided to make it easier to deal with the current render modes.
The `NewAttr` function will become useful when Vertex Attributes and shader
support are added in the fourth render mode.

Adding mesh data to the buffer has remained relatively unchanged. Where we
would previously call:

mb.Add(indices, positions, colors, nil, nil)

We can now omit the `nil` values. All that is required here, is that one
supplies data for every attribute we defined in `NewMeshBuffer`. The data
must also be pushed in the same order.

mb.Add(indices, positions, colors)

The example programs will be updated to reflect these changes if/when this
patch is accepted.