Rendering concepts
Several optimisation were developed in order to keep performance at an acceptable level. The all algorithm is based on octree rendering which goal is to allow the multi resolution to be fast an transparent without conflict.
The full resolution (level 0) are considered the leafs of the octree. The lower resolution build is the root of the octree.
From left to right :
1. you get a leaf of level n.
2. 8 nodes of level n are put together in the ijk domain.
3. the 8 nodes are decimated in 1 node of level N+1.
The building of the octree is made in reverse of the actual use of it which follows common concepts, that from any node you can access it's 8 children.
With fast access to every node data due to gigamodel design, the rendering of each node will be fastest.
The rendering algorithm use multi iteration rendering to smooth the display when view position is unchanged between two frames. It means that when the scene is moved (through mouse for instance) the rendering is done as fast as possible with lower resolution. Then when the view is static, several rendering passes are done to get the best resolution possible at each frame.
Settings
Several rendering parameters are available to tune the display to get the best display quality without sacrificing performance.
All those parameters are accessible through the instanciated grid.
Sample Code
// reservoirgrid is the cgNodifiedGrid instance of the grid
cgGigaJOGLNodifiedGrid gridjoglnode = reservoirgrid.getReservoirGridJOGLNode();
// Get the parameters object
cgRenderParameters renderParameters = gridjoglnode.getRenderParameters();
Rendering Parameters :
- Frame Timelapse (in ms) : This is the goal of rendering time in one frame for the rendering algorithm. The internal mechanics will tune the octree rendering to be as close as possible of this number.
- Extra nodes per iteration : this is the number of nodes the rendering will add to the render scene in each iteration of rendering.
- Multi passes iterations : number of iteration for the rendering. (it is not recommended to set it below 5)
- Cell resolution : optimal celle resolution in pixels. This is the expected celle size on screen. The rendering algorithm will increase or decrease resolution to get the actual cell (not the outline) to be as close as possible of this number (without sacrificing frame timelapse goal).
Rendering Settings :
- Freeze resolution : freeze resolution, to prevent rendering algorithm to change nodes resolution. Useful to watch specific Nodes at full resolution from different angles.
- Force High resolution : enable full resolution when slices I,J,K are enabled.
- Property null value and color : sets the value used to identify null value, and the color it will be rendered. (property filter only)
- Outline Size and color : allow to set size and color of the outline
When you change one or more settings, you need to send an event to the grid.
Sample code
// Set any paramter you want to change
renderparameters.setNbMultiPassesIterations(20);
// Fire grid paramter event
reservoirGrid.fireGridParametersEvent()
Rendering algorithm use internal cache (minimum 1Go) to improve performance. CPU and GPU cache values must be carefully set in accordance to hardware specifications. The rendering algorithm will check if cache values are correct, but if you put too much cache your system might start to swap and slow everything down.
sample code
long valueGPUCache = 700000000L; // 700 Mo
long valueCPUCache = 1000000000; // 1Go
//enable GPU cache
cgParameterSingleton.getInstance().setCacheGPUMemSize(valueGPUCache * _CACHE_GPU_TEXTFIELD_FACTOR);
reservoirGrid.enableCacheGPU(true);
reservoirGrid.fireGridParametersEvent();
// set cpu cache value
reservoirGrid.setCacheCPURatio(valueCPUCache);
Lights
The rendering algortihm offers light handling with two separate rendering.
No light :
sample code
cgGigaJOGLNodifiedGrid grid = ... ; // loaded grid
grid.setLighting(false);
grid.enableDeferred(false);
Classic light
sample code
grid.setLighting(true);
grid.enableDeferred(false);
Ambient occlusion light
sample code
grid.setLighting(true);
grid.enableDeferred(true);
SSAO (ambient occlusion) rendering got some option to tune the rendering.
sample code
cgManageableNodifiedGigaReservoirGrid reservoirNode = ...; // loaded grid
float radius = ...;
reservoirNode.setRadiusVariable(radius);
float stesize = ...;
reservoirNode.setStepsizeVariable(stepsize);
boolean showattributecolor = ...;
reservoirNode.setShowAttributeColor(showattributecolor);
boolean showLambertian = ...;
reservoirNode.setShowLambertianShading(showLambertian);
boolean anticelloverlap = ...;
reservoirNode.setAntiCellOverlapMode(anticelloverlap);
// Update changes
reservoirNode.update();
Filters
The rendering algortihm are supporting several filters. Every filter can be mixed so the user can see exaclty which part of the grid he needs to.
Filters are mixable with AND and OR conditions to create every customisable mix possible.
Basic behavior is a AND root filter. Every filter you add to the grid is mixed in the AND root filter, and so are mixed together. If you need to, you can add a OR filter to the root, then add several filter to this OR filter to create multi slices rendering for instance.
IJK Boundingbox
cgGigaFullBoundingBoxFilter is the base filter. All cells outside the given bounding box are discarded.
First example show how to create a Slice filter :
sample code
// Create slice I in I = 59
// Create Boundingbox
cgGigaIJKBoundingBox iBBox = new cgGigaIJKBoundingBox(
59, reservoirNode.getIJKBoundingBox().getMinJ(), reservoirNode.getIJKBoundingBox().getMinK(),
60, reservoirNode.getIJKBoundingBox().getMaxJ(), reservoirNode.getIJKBoundingBox().getMaxK(),
1, reservoirNode.getIJKBoundingBox().getNbJ(), reservoirNode.getIJKBoundingBox().getNbK());
// create filter from grid and bounding box
iFilterSlicer = new cgGigaFullBoundingBoxFilter((cgGigaJOGLNodifiedGrid)reservoirNode, iBBox);
// add filter to the gid
reservoirNode.addFilter(iFilterSlicer)
Just by changing the bounding box data you can se another filter
sample code
// Create box in I 66 -> 114, J 74 -> 124, K 0 -> 16
// Create Boundingbox
cgGigaIJKBoundingBox iBBox = new cgGigaIJKBoundingBox(
59, 74,124,
114,124,16,
114-59,124-74,16);
// create filter from grid and bounding box
cgGigaFullBoundingBoxFilter filter = new cgGigaFullBoundingBoxFilter((cgGigaJOGLNodifiedGrid)reservoirNode, iBBox);
// add filter to the gid
reservoirNode.addFilter(filter)
Cavity box
cgGigaVoidBoundingBoxFilter is the opposite of the cgGigaFullBoundingBoxFilter. The included bounding box create a cavity in the grid, all cells of the cavity are discarded.
The same principle is used but the class used is different.
sample code
// Create box in I 66 -> 114, J 74 -> 124, K 0 -> 16
// Create Boundingbox
cgGigaIJKBoundingBox iBBox = new cgGigaIJKBoundingBox(
59, 74,124,
114,124,16,
114-59,124-74,16);
// create filter from grid and bounding box
cgGigaVoidBoundingBoxFilter filter = new cgGigaVoidBoundingBoxFilter((cgGigaJOGLNodifiedGrid)reservoirNode, iBBox);
// add filter to the gid
reservoirNode.addFilter(filter)
Property filters
Property filters are depeding directly from built properties in gigamodel. Built propertis must correspond with built geometry.
First you create filter to load some property to the grid.
Sample code
PropertyKey propUid = ...; // Loaded propertyKey or iterate through grid propertyKeys
// Create property instance
cgGigaProperty property = ((cgGigaPropertyManager) reservoirNode).loadProperty(propUid,
propName, PropertyType.CELL);
// create property Filter
cgGigaPropertyFilter propertyFilter = new cgGigaPropertyFilter(property);
// Add it to grid
reservoirNode.addFilter(_propertyFilter);
Then you can set min and max filtered value through property to display filtered cells.
sample code
propertyFilter.setMinFilteredValue(minValue);
propertyFilter.setMaxFilteredValue(maxValue);
In our example, we set it on a slider, and we can filter the grid in real time.
Sometimes some values are not supposed to be there. In order to determine those "null" values we can add some value that will be filtered among all the property values.
Then we chose to discard the rendering of those specified null values, or to display them with a specific color.
The rendering of those null value are decided with
sample code
// Null value render mode possibility
// Nothing done : MODE_PROPERTY_NULL_VALUE.NULL_VALUE_OFF,
// Discard rendering : NULL_VALUE_DISCARDED,
// Use null value color to display them : NULL_VALUE_DISPLAYED;
// this code discard null values
reservoirNode.setPropertyNullValueMode(cgRenderModes.MODE_PROPERTY_NULL_VALUE.NULL_VALUE_DISCARDED,
nullValue, propNullValueColor);
Nothing done :
Discard null value :
White color selected and display nullvalue :