Trajectory rendering

Trajectories are rendered as 3-D tubes, with the tube geometry generated on the GPU. This page covers the rendering side; how trajectories are computed and filtered is described in Trajectory Pipeline.

Source code: src/actors/trajectoryactor.cpp, src/glsl/trajectory_tubes.fx.glsl, src/glsl/trajectory_positions.fx.glsl.

Tubes from line segments

Only the trajectory vertices live in GPU memory, in a vertex buffer. A geometry shader turns each line segment into a triangle mesh approximating a tube (trajectory_tubes.fx.glsl): for every vertex a normal is rotated around the segment to produce the ring of tube vertices, and consecutive rings are connected.

At the joint between two segments, the normal must be perpendicular to the tangent at the joint, not to either of the two segments. Otherwise gaps appear at kinks. Consecutive normals must also be consistent with each other; if they are not, the tube twists along its length.

Both conditions require the normals to be computed iteratively along the trajectory. A geometry shader sees at most a few adjacent vertices and cannot do this. This is why normals are not computed in the shader but delivered as a separate data item by MTrajectoryNormalsSource and bound as a vertex attribute.

Selection through the index buffer

Filtering trajectories — by ascent, by region, by any other criterion — does not touch the geometry. The full set of trajectories stays in the vertex buffer, and the selection is expressed as a set of indices in an index buffer. Changing a filter criterion therefore only means uploading a new index buffer, which is why dragging a filter threshold stays interactive even for large trajectory sets.

Particle positions

The position of each air parcel at a given time step is drawn as a sphere. These are not real spheres but billboards: a geometry shader (trajectory_positions.fx.glsl) expands each position into a screen-aligned quad, which the fragment shader shades to look like a sphere. Animating the time step then shows the parcels travelling along their trajectories.

Colouring and shadows

Tubes and particles can be coloured by pressure elevation, by an auxiliary variable carried along the trajectory, or by a constant colour, using a transfer function as a lookup table. Shadows are handled by the scene-wide shadow mapping described in Shadow mapping, rather than by projecting the geometry onto the ground as in the original implementation.