Nowadays there exist multiple ways of sending geometry to GPUs: displays lists, vertex buffer objects, indexed primitives are some of them. This changes from Direct3D to OpenGL, and new ways of managing geometry appear as APIs evolve. It is difficult to determine which method is the best. This depends on numerous factors (mesh size, number of vertex attributes, and some unknown driver/hardware mechanisms). Moreover some ways of sending the geometry are slow but very convenient (e.g. the OpenGL function calls).
The purpose of GPUmesh is to provide developers with a simple mechanism to send geometry to the GPU. The user chooses which type of mesh storage is desired (display list, vertex buffer, indexed vertex buffer, ...) and GPUmesh automatically performs the required conversions. The chosen mechanism can be changed very easily by changing only one typedef. This makes performance test with various storage solutions very easy. Since the whole library is built upon templates, only the code corresponding to the chosen storage is generated. Their is no runtime overhead.
GPUmesh offers the same mesh specification mechanism under Direct3D and OpenGL, thus simplifying the task of writing mesh loaders. GPUmesh relies on a mechanism similar to the begin/end approach of standard OpenGL. This mechanism has proven to be easy to use and very convenient. Thanks to GPUmesh it now also produces efficient meshes. A complete vertex format specification mechanism is also provided to manage vertex attributes.
Since GPUmesh is only a set of header files, there is nothing to compile. Just include D3DGPUmesh.h or GLGPUmesh.h depending on the graphics API you are using.
By default GPUmesh uses gluX for the extension loading mechanism. gluX can be disabled by defining GPUMESH_NO_GLUX.
GPUmesh is a template library. Unfortunately all compilers do not support all template functionnalities. GPUmesh is compatible with the following compilers:
2.3. Sample programs
The included OpenGL examples use glut, gluX,
and libTexture.
Under Windows, a Visual C++ 7 2002 project is included. The binaries of the libraries are also included (for Visual C++ 7 2002).
Under Linux, please download and install the libraries (glut, gluX, libTexture). The Loki library is already included in the libs/loki directory. Before compiling please edit tutorial/Makefile and update the library path. By default they are set to:
LIBRARY_PATH = $(HOME)/lib.linux GLUX_PATH = $(LIBRARY_PATH)/glux LIBTEXTURE_PATH = $(LIBRARY_PATH)/libtexture LOKI_PATH = $(LIBRARY_PATH)/loki
The first step is to include the appropriate header file. This depends whether your are using OpenGL or Direct3D.
#ifdef OPENGL // include GPUmesh for OpenGL # include "GLGPUmesh.h" #else // include GPUmesh for Direct3D # include "D3DGPUmesh.h" #endif |
Then, a vertex format and a mesh type must be chosen and associated.
// GPUmesh is encapsulated in a namespace using namespace GPUmesh; // define vertex format (2D vertex and RGBA color) typedef GPUMESH_MVF2(mvf_vertex_2f,mvf_color0_rgba) mvf_mesh; // associate mesh and chosen vertex format #ifdef OPENGL typedef GPUmesh_GL_DisplayList<mvf_mesh> SimpleMesh; #else typedef GPUmesh_D3D<mvf_mesh> SimpleMesh; #endif // pointer to mesh object SimpleMesh *g_Object=NULL; |
From now, nothing else depends on the API (OpenGL or Direct3D). The following code creates a simple quad with a color at each vertex:
void initScene() { // ... g_Object = new SimpleMesh(); g_Object->begin(GPUMESH_TRIANGLELIST); g_Object->color0_4(0,0,255,0); g_Object->vertex_2(0.1,0.1); g_Object->color0_4(255,0,0,0); g_Object->vertex_2(0.1,0.9); g_Object->color0_4(0,255,0,0); g_Object->vertex_2(0.9,0.9); g_Object->color0_4(0,0,255,0); g_Object->vertex_2(0.1,0.1); g_Object->color0_4(0,255,0,0); g_Object->vertex_2(0.9,0.9); g_Object->color0_4(64,0,255,0); g_Object->vertex_2(0.9,0.1); g_Object->end(); // ... } |
The code to render an object is simply:
void renderScene() { // ... g_Object->render(); // ... } |
A vertex format describes the attributes of each mesh vertex. A vertex format is a type defined as follows:
typedef GPUMESH_MVF<N>(<First attribute>,...,<Attribute N>) <vertex format name>;For an example,
typedef GPUMESH_MVF2(mvf_vertex_2f,mvf_color0_rgba) mvf_mesh;defines a vertex format called mvf_mesh with two attributes: a 2D vertex position and an RGBA color.
The possible attributes are:
mvf_vertex_2f | mvf_vertex_2d | mvf_vertex_3f | mvf_vertex_3d | ||||
mvf_vertex_4f | mvf_vertex_4d | mvf_normal_3f | mvf_normal_3d | ||||
mvf_color0_3f | mvf_color0_3d | mvf_color0_4f | mvf_color0_4d | ||||
mvf_color0_rgba | mvf_color1_3f | mvf_color1_3d | mvf_color1_4f | ||||
mvf_color1_4d | mvf_color1_rgba | mvf_texcoord0_1f | mvf_texcoord0_1d | ||||
mvf_texcoord0_2f | mvf_texcoord0_2d | mvf_texcoord0_3f | mvf_texcoord0_3d | ||||
mvf_texcoord1_1f | mvf_texcoord1_1d | mvf_texcoord1_2f | mvf_texcoord1_2d | ||||
mvf_texcoord1_3f | mvf_texcoord1_3d | mvf_texcoord2_1f | mvf_texcoord2_1d | ||||
mvf_texcoord2_2f | mvf_texcoord2_2d | mvf_texcoord2_3f | mvf_texcoord2_3d | ||||
mvf_texcoord3_1f | mvf_texcoord3_1d | mvf_texcoord3_2f | mvf_texcoord3_2d | ||||
mvf_texcoord3_3f | mvf_texcoord3_3d | mvf_texcoord4_1f | mvf_texcoord4_1d | ||||
mvf_texcoord4_2f | mvf_texcoord4_2d | mvf_texcoord4_3f | mvf_texcoord4_3d | ||||
mvf_texcoord5_1f | mvf_texcoord5_1d | mvf_texcoord5_2f | mvf_texcoord5_2d | ||||
mvf_texcoord5_3f | mvf_texcoord5_3d | mvf_texcoord6_1f | mvf_texcoord6_1d | ||||
mvf_texcoord6_2f | mvf_texcoord6_2d | mvf_texcoord6_3f | mvf_texcoord6_3d | ||||
mvf_texcoord7_1f | mvf_texcoord7_1d | mvf_texcoord7_2f | mvf_texcoord7_2d | ||||
mvf_texcoord7_3f | mvf_texcoord7_3d |
void begin(int primitive_type) | Begins a mesh definition. primitive_type can be GPUMESH_TRIANGLELIST, GPUMESH_TRIANGLEFAN (OpenGL only), GPUMESH_TRIANGLESTRIP, GPUMESH_QUADS (OpenGL only). Primitive types for lines are not yet implemented. |
void end() | Ends a mesh definition. Data is sent to the GPU at this point. |
void bind() | Binds a mesh for drawing. This must be called before draw(). |
void unbind() | Unbind the mesh. This must be called after draw(). |
void draw() | Draws the mesh. It must be binded. |
void render() | Calls bind(); draw(); unbind();. Use this method if you want to draw the mesh only once. |
int vertex_[2..4]( ... ) | Defines vertex position. The function is available in 3 versions: 2D, 3D and 4D coordinates. Note that similarly to OpenGL, this method save the vertex with all current values of the attributes. In other word, this must be called after having defined all the other vertex attributes. The index of the added vertex is returned. |
void index( ... ) | Defines geometry when using an indexed mesh. If the mesh is not indexed, calling this method has no effect. |
void normal( ... ) | Define vertex normal. If the vertex format does not include a normal, calling this method has no effect. |
void color[0..1]_[3..4]( ... ) | Define vertex color0 or color1. Each function exist in two versions: RGB and RGBA. If the vertex format does not include a color, calling this method has no effect. |
void texcoord[0..7]_[1..4]( ... ) | Define vertex texture coordinates for texture unit 0 to 7. Each function exists in 4 versions: 1D, 2D, 3D and 4D. If the vertex format does not include texture coordinates, calling this method has no effect. |
The mesh declaration should follow some rules that are depicted by some examples of legal / non-legal declarations below.
Given the following vertex format,
typedef GPUMESH_MVF2(mvf_vertex_2f,mvf_color0_rgba,mvf_texcoord0_4) mvf_mesh; |
The following declaration are (legal / illegal):
g_Object->begin(GPUMESH_TRIANGLELIST); g_Object->color0_4(0,0,255,0); g_Object->texcoord0_4(0.0,0.5,0.1,1.0); g_Object->vertex_2(0.1,0.1); g_Object->vertex_2(0.1,0.9); // legal, reuse other attributes value g_Object->vertex_2(0.9,0.9); g_Object->end(); |
g_Object->begin(GPUMESH_TRIANGLELIST); g_Object->vertex_2(0.1,0.1); // legal, missing attributes intialized to 0 g_Object->vertex_2(0.1,0.9); g_Object->vertex_2(0.9,0.9); g_Object->end(); |
g_Object->begin(GPUMESH_TRIANGLELIST); g_Object->vertex_3(0.1,0.1,0.0); // ILLEGAL - do NOT compile g_Object->vertex_3(0.1,0.9,0.0); // (vertex_2 should be used) g_Object->vertex_3(0.9,0.9,0.0); g_Object->end(); |
g_Object->begin(GPUMESH_TRIANGLELIST); g_Object->color0_4(0,0,255,0); g_Object->texcoord0_2(0.0,0.5); // legal, but ignored ! (differs from OpenGL behaviour) g_Object->vertex_2(0.1,0.1); g_Object->vertex_2(0.1,0.9); g_Object->vertex_2(0.9,0.9); g_Object->end(); |
g_Object->begin(GPUMESH_TRIANGLELIST); g_Object->color0_4(0,0,255,0); g_Object->normal(0.0,1.0,0.0); // legal, supplemental attribute is ignored g_Object->vertex_2(0.1,0.1); g_Object->vertex_2(0.1,0.9); g_Object->vertex_2(0.9,0.9); g_Object->end(); |
// define vertex format typedef GPUMESH_MVF2(mvf_vertex_2f,mvf_color0_rgba) mvf_mesh; // associate mesh and choosen vertex format typedef GPUmesh_Indexed_GL_VBO<mvf_mesh,unsigned int> IndexedMesh; void initScene() { // ... g_Object = new IndexedMesh(); g_Object->begin(GPUMESH_TRIANGLELIST); // declare vertices g_Object->color0_4(0,0,255,0); g_Object->vertex_2(0.1,0.1); g_Object->color0_4(255,0,0,0); g_Object->vertex_2(0.1,0.9); g_Object->color0_4(0,255,0,0); g_Object->vertex_2(0.9,0.9); g_Object->color0_4(64,0,255,0); g_Object->vertex_2(0.9,0.1); // build geometry from indices g_Object->index(0); g_Object->index(1); g_Object->index(2); g_Object->index(0); g_Object->index(2); g_Object->index(3); g_Object->end(); // ... } |