In this app, we are given thousands or more data points that we wish to visualize with 3D objects in each frame and we are required to optimize the rendering performance as much as possible. We can achieve this by using GPU supported instanced rendering that improves performance.
In our dataset, each row contains characteristics and a position that represents a tree in a forest. There are just over one thousands of trees in a single time frame, as we go along the axis of time in our dataset, the characteristics of the trees changes. These changes represents the lifetime or trees in a forest. Graphically visualizing this data can help us easily spot abnormalities, any unusual characteristics or just study a group of trees in the forest.
We chose a dataset generated by mathematical model known as FORMIND that simulates forest dynamics. It is an individual based vegetation model that simulates the growth of species-rich forests over a time period on a hectare scale. It includes gap formulations in order to display forest dynamics and forest structure. The individual tree based approach of forest gap models offer a high degree of flexibility to be adapted to different environments like temperate forests or grasslands.
From the output of FORMIND forest model, we have with a dataset with each row representing a tree with following columns:
- Tree_type Nominal column, one of six functional tree types used in the model
- Sphere_diameter Numerical column, Diameter of the tree crown (applies to all three dimensions)
- Cylinder_diameter Numerical column, Diameter of the tree stem (applies to all three dimensions)
- Total_height Numerical column, Total height of the tree (diameter of stem + diameter of crown)
- X Numerical column, X-coordinate of the tree in the plane
- Y Numerical column, Y-coordinate of the tree in the plane
- Frame_number Nominal column, Represents time step of the tree in the model, time step begins from 0 to maximum frame_number
All in all, the dataset contains about 167 frames with each frame containing an average of 4000 trees.
Using GPU instancing becomes very important here because we can represent a tree with a single mesh but there are potentially thousands or millions of trees in a forest and it is not feasible to call the draw function for every individual tree object since it can cause performance bottleneck because of CPU to GPU communication when calling a draw function.
In our program, we procedurally generate 3D models for both cylinder and sphere objects by specifying granularity (number of vertices that represents the precision of object boundary), diameter and height for cylinder and granularity and diameter for sphere. Recall that, we have only one instance of the 3D model of both cylinder and sphere in GPU memory. In our drawing loop, we generate a list of instances for stem and crown for all the trees in the current ‘Frame_number’, each instance in the list corresponds to a tree to rendered in our scene with its own set of parameters as in our dataset. Then we rendered these instances separately for stems (represented by cylinder) and crown (represented by sphere) using instanced rendering.
We use WebGL which is OpenGL API in javascript for rendering graphics on any compatible web browser. Rendered graphics are displayed inside a webpage as an HTML canvas object.