Skip to content

Primitive Rendering

John Chapman edited this page Jan 14, 2018 · 10 revisions

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.

Matrix Stack

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

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.

Alpha

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();

Sorting

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

Layers permit the application to group primitives. See Layers.

High Order Shapes

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).

Clone this wiki locally