-
Notifications
You must be signed in to change notification settings - Fork 64
Primitive Rendering
Im3d supports rendering the following primitive types:
- points
- lines
- line strips
- line loops
- triangles
- triangle strips
Rendering generally follows the pattern of OpenGL immediate mode. Vertices are added to a primitive between calls to Begin*()
and End()
functions, as follows:
BeginPoints(); // start primitive
Vertex(x, y, z); // declare vertices
End(); // end current primitive
The application must make a valid number of calls to Vertex()
between Begin*()
and End()
for the specified primitive type. For example, lines require at least 2 vertices, and the total number of vertices must be a multiple of 2. Triangles require at least 3 vertices, and the total number must be a multiple of 3.
Note that there are several convenient overloads of Vertex()
, see im3d.h for details.
As with OpenGL immediate mode, Im3d supports a matrix stack. All incoming vertices are multiplied by the top of the matrix stack:
PushMatrix(worldMatrix);
BeginPoints();
Vertex(x, y, z);
End();
PopMatrix();
Note that there is no concept of a view/projection matrix. In fact, because of the requirement for VR support, it is expected that applications will only specify vertices in world space and perform the view-projection transform at draw time (usually in the shader).
Draw state controls most aspects of primitive rendering. Each draw state has its own stack:
PushColor(Color(1.0f, 0.0f, 0.0f, 1.0f)); // RGBA
PushSize(4.0f); // radius/thickness for points/lines (pixels)
BeginPoints();
Vertex(x, y, z);
End();
PopSize();
PopColor();
Because vertex color/size may vary frequently, overloads of the Vertex()
function allow setting the draw state directly:
BeginPoints();
Vertex(
x, y, z, // position
4.0f // size
Color_Red // color
);
EndPoints();
In this case the size and color are written directly to the vertex data and the state stacks are unaffected.
The alpha draw state multiplies color draw state's alpha.
BeginPoints();
SetColor(Color_Red);
Vertex(x, y, z); // draw a red point
SetAlpha(0.1f); // modify alpha draw state
Vertex(x, y, z); // draw a red point with alpha = 0.1
EndPoints();
When sorting is enabled, primitives are sorted back-to-front before being sent to the application for rendering. Sorting is performed relative to AppData::m_viewOrigin
(specified by the application).
When sorting is disabled, triangles are drawn first followed by lines and then points. Within each primitive type the order is determined by the order in which the application called the associated Begin*()
function.
Sorting is a per-primitive draw state (it cannot be changed between calls to Begin*()
/End()
).
Note that per-primitive sorting is potentially a performance bottleneck.
Layers permit the application to group primitives. See Layers.
Im3d provides a number of helpers for drawing high order shapes - quads, circles, boxes, spheres, etc. These have the form Draw*()
for wireframe shapes, and Draw*Filled()
for solid shapes.
Of particular interest are DrawPoint()
and DrawLine()
. These are shortcuts for the common case of drawing a single point or line, avoiding the need to call Begin*()
and End()
.
Some shape functions have a _detail
argument which controls the level of detail, e.g. the subdivision of circles/spheres. If this argument is set to -1 Im3d will select a level of detail based on the distance to AppData::m_viewOrigin
(for perspective projections).