Development log: December 30, 2012

Seamless Forest Rendering for Huge Open-world Scenes, Improved DOF

Seamless Forest Rendering

Forests are now seamlessly rendered even from a bird's eye view for flight simulators, especially together with the increased depth buffer precision.

Trees, vegetation or other objects are scattered via WorldClutter and ObjectMeshClutter, while ObjectGrass is used as a far LOD, with their positions fully matching. This is done via a new Subdivision parameter for ObjectGrass that subdivides big grass cells so that they match smaller clutter ones.

Forest rendering

To create a grass-based LOD, a model is baked into an atlas at different angles using a new Impostor grabber: Tools -> Grabber -> Mode: Impostor. (You can control the aspect ratio of the baked images; alpha noise to smoothly fade between different angles is available as well.) This atlas is used with a new grass_impostor_base material for ObjectGrass. It supports Phong shading with normal maps.

Impostor atlas

Check a new forest system with seamless transitions from a high-detail LOD to distant impostors on new samples/materials/impostor_* samples.


  • Drastic improvement of the Gaussian DOF: higher-quality blurring and smoothly dissolving contours from objects on the foreground. The full control over a blur radius is granted separately for the distance before and after the focal point.
  • Removed a full-screen mode for Glow and DOF effects. Bokeh DOF is also removed as a trade-off for better DOF performance.
  • Added render_use_d32f console command to toggle a depth buffer with 32 bit floating point precision. (For example, for rendering more then 100 km within the visibile range).
  • New Angularity parameter (Render settings -> Scattering tab) allows to compensate for physically-correct light scattering. Set it to 0 for the whole sky to have a uniform Rayleigh scattering independent of the sun position.
  • Added Attenuation parameter for AO and LO that compensates for the falloff of these effects and makes them more prominent in the distance.
  • Improved shader caching algorithm allows shaders to be loaded faster from a cache.
  • In OpenGL ARB_sample_shading extension is now enabled by default to provide a higher-quality alpha test with enabled anti-aliasing.
  • Removed render_use_scattering_falloff console command.
  • Fixed a bug with occasional and random flickering of the rendered scene.
  • New sample samples/shaders/lines_01 draws different kinds of lines using a geometry shader.
  • Particles can now be lit by LightProb light sources.
  • Visualizer can render objects' wireframe while respecting the alpha value.
Here is new DOF in action as the camera focuses:

Object in focus

Object out of focus


  • Added grass_impostor_base material to render impostors.
  • A separate Phong shading option is added for mesh_leaf_base material (for all light sources at once, switch them to Default for leaves to be rendered). Now normals are written into the deferred buffer providing a higher quality for deferred lighting.
  • Fixed incorrect attenuation for non-uniform volumetric objects with volume_cloud_base material assigned.
  • Fixed a bug with incorrect rendering of the volume fog for water_base material.
  • Increased the speed of grass_base and mesh_leaf_base rendering with the Ambient state option checked.
  • New Multisample state for volume_fog_base material for it to work with anti-aliasing (if it's enabled on the hardware level).
  • ObjectMeshCluster and ObjectMeshClutter can now be rendered with mesh_terrain_base material.


  • No more scale floating point precission issues when matrices are composed and decomposed via Node::set/getWorldRotation() and Node::set/getWorldDirection(). It is in effect only for the scale of 1.
  • Added Node::set/isLatest() functions to update a node after all other nodes. For example, this flag is useful to draw nodes strictly in front of the camera (i.e. to make sure that drawn nodes are updated only after the Player was updated to a new position). WorldExpression::set/isPostUpdate() function with the same functionality is removed.
  • Surfaces are correctly enabled and disabled inside NodeReference.
  • Cache of NodeReference can be cleared on demand via function.


  • Added Sync option for ObjectParticles that disables automatic synchronization of a child particle system with a parent one.
  • Added getNormal() function for ObjectWater and ObjectWaterMesh. It returns the normal vector of any point of water waves.
  • Fixed a bug with ObjectMeshDynamic not restoring its bounding box when state_restore console command is called.
  • Improved detection of particles spawning for shift emitters; fixed precision issues for them.
  • Improved intersection speed with ObjectTerrain.

World Nodes

  • New WorldSwitcher node can disable all of its children with the distance. It is used for simultaneous switching off big parts of the world. The point to which a distance from the camera is measured to can either be the bounding sphere or its center point.
  • New WorldSpacer node cuts out parts of ObjectGrass, ObjectWater or ObjectWaterMesh (in a form of a square or ellipse). It allows to dynamically adapt grass or water surface (with Materials -> States -> Spacer Interaction flag) to the added objects. Up to 8 spacers for one grass or water node are supported. Check it on new samples: samples/worlds/spacer_*.
  • Fixed a bug of WorldSector: if it is disabled, its children now become visible.
  • Now logic of environment objects can be scripted via WorldExpression without a single code line added into a world script. WorldExpression automatically receives callbacks from WorldTrigger, PhysicalTrigger and NodeTrigger when these nodes are made its children. Check samples/worlds/expression_04 to see it in action.

WorldSpacer procedurally modifies a water mesh (for example, to render the space inside a ship's hull):

WorldSpacer with water

Grass and Clutters

  • Improved performance of ObjectGrass, ObjectMeshClutter and WorldClutter.
  • Added Min scale and Max scale parameters for WorldClutter and ObjectMeshClutter. They regulate the size of nodes they scatter according to the mask density: for example, to have small objects at the edges (areas with low density), while having full-sized ones in the middle (areas with high density).
  • The Scale and Height parameters of ObjectGrass are gone; instead, the grass height always varies within the specified height range (according to the mask density), no matter what Threshold value is chosen for masking. Please, set up your assets accordingly.
  • Added Subdivision parameter for ObjectGrass to subdivide cells into smaller ones (to match with WorldClutter and ObjectMeshClutter).
  • Added Orientation option for ObjectGrass. It orients the grass along the normal of its parent object, for example, a terrain. By default, the grass is not oriented.
  • New per-column Probability parameter for ObjectGrass. It determines how often one of four grass types (columns) is rendered across the field.

Grass is now even faster and there are new parameters for fine tuning: can be easily fine-tuned with new parameters:



  • Improved search on Materials and Properties panels. On pressing Enter, the next found item is shown.
  • Improved a text search in the text editor. On pressing Enter, the next found item is shown. Text highlighting is also added.
  • On Material and Property panels, base and materials/properties with children are now color coded.
  • Clear option in Nodes -> Surfaces -> Material/Property ('x' icon) has changed its functionality: it removes changes made in the material/property instance rather than removing the material/property itself.
  • Terrain can be safely edited even when double precision builds are used.
  • Fixed memory leaking when ObjectGrass, WorldClutter or ObjectMeshClutter masks are edited.
  • Changes made for a mask of ObjectGrass, WorldClutter or ObjectMeshClutter are not reset if the node is deselected. Instead, a dialog to save changes is shown.
  • Improved brush precision when masks are edited. Crashes on mask editing are fixed as well.
  • NodeReference no longer crashes if a *.node file it refers to cannot be found.
  • Deleting an uncompressed texture (that is checked for modifications in run-time) no longer causes an error message in the console.
  • Added Copy and Paste buttons onto Nodes panel -> Surfaces. They can be used to copy all parameters of all surfaces at once and apply them to an identical mesh (or ObjectMeshClutter/Cluster).
  • Added an impostor grabber (Tools -> Grabber -> Mode: Impostor).
  • Added a button to generate a default LUT texture (Render settings -> Color -> LUT texture -> '+' icon).
  • Added Tools -> Plugins -> Core button to easily access plugins stored inside a core.ung archive.
  • File dialogs now have Open system file browser button (with a folder icon).
  • Added support of the undo operation on removal and renaming of materials and properties.

New color highlighting in the editor:

Material editor


  • Added console variables to change appearance of GUI: gui_path (specifies a path to a new GUI skin), console_font (console's font to be used), console_size (console's font size), profiler_font (profiler's font to be used) and profiler_size (profiler's font size). For changes to take effect, restart the application (gui_path can be passed as a start-up option).
  • WidgetListBox and WidgetTreeBox can render their items in custom colors via setItemColor() function.
  • When widgets are rendered as disabled, custom colors set via Widget::setFontColor() or WidgetListBox/WidgetTreeBox::setItemColor() are not greyed out as in case with default ones.
  • Added access to all WidgetTreeBox items via getItems() function.
  • Complex GUI widgets (for example, with thousands of items in the tree) work correctly and do not cause a vertex buffer overflow.
  • TTF font textures are cached before rendering.
  • Fixed a minor bug with incorrect layout inside WidgetV/HBox in some cases.
  • Images are now correctly flipped in DirectX APIs for WidgetSprite/Material/Node/Viewport widgets via renderImage() function.
  • New Gui::isFocused() function checks if the current GUI instance contains a focused widget.
  • No more shaking artifact when manipulators are used in double-precision builds.
  • All editor dialogs are refactored to have only Yes/No or Ok options.


  • Files can now be buffered in the memory via engine.filesystem.addBufferFile(). If they need to be frequently modified in run-time (for example, images), they can be loaded from a disk and kept in the memory for faster access. For examples, see samples/systems/socket_01 sample that saves a screen image into a buffered file and sends it to a web browser. (Do not forget to check Tools -> Always update option).
  • Added preprocessor() function that allows to preproceces source files, such as unigine scripts or shaders.
  • Added crc32() system function that returns a control sum for a given string.
  • Improved greyscale alpha support in Image::extrude() function.
  • Function bezier() can receive vec4 and dvec4 for float and double precision coordinates.
  • Function system() (from Core library -> OS functions) that executes shell commands is now available on Mac OS X.

High-Level Scripts

  • Tracker perfectly works on very far distances with double-precision builds.
  • In Tracker, getParameterNext/PrevTime() functions are renamed into getNext/PrevParameterTime().
  • If NodeReference contains a node with an identical name inside, such node cannot be handled by the Tracker.
  • Fixed a bug in Skinner's block skinned.difference.
  • When Syncker is used, multiple slaves can safely connect to a master (server) running on a Windows PC due to increased connection timeouts.

Mobile Platforms

  • Added a number of samples into the Android platform SDK (such as app initilaization, running callbacks between Java code and the script, simple joystick handling). They can be found under source/samples/Android directory.
  • Menu bar is not shown in Android samples any more. For it to disapper in your Android project, change the target device to target-14 in the manifest.
  • Materials -> Common -> Offset for polygons is not availble on feature levels 9_1, 9_2 and 9_3 of DirectX 11.
  • Function UnigineActivity::runFunction() that executes functions from a system script is renamed to UnigineActivity::runSystemFunction() and made public.
  • On Android, up to 2 argument now can be passed from a system script to Java code, and vice versa (both arguments should be of the same type). Integer, float and string arguments are supported.
  • Fixed a bug when callbacks from world and physical triggers were not handled on iOS.


  • User classes can be inherited from a base MovieClip due to the added support of instanceOf operator.
  • Added support of addProperty() method of Object to create custom properties for objects. User classes can now contain set and get keywords.
  • Added support of getInstanceAtDepth() method of MovieClip.
  • Added support of set/clearTimeout() and set/clearInterval() functions.
  • Fixed a bug with WidgetFlash performing an incorrect stencil test for its elemets under DirectX 11.


  • Added extern_package console command to be passed on the start-up. It loads UNG archive from the specified location.
  • Added editor_plugin console command to load any editor plugin (comma-separated, if there are several of them) via start-up options.
  • Improved detection of the available CPU cores number for Windows (hyper-threading is ignored).
  • OpenAL Sound system support is automatically disabled for WindowsRT builds.
  • No more file queueing stalls. Queued requests on loading are automatically cleared if files are no longer required.
  • Fixed a bug with random crashes on calling state_save console command.
  • Added nocompiler build option for SCons. It disables compilation of shaders in run-time for WindowsRT and PlayStation3, to conform with these platforms' requirements. Instead, shaders need to be precompiled offline; the resulting cache is placed into the data root directory.
  • Added an additional system button App::KEY_CMD (for a command key on Mac OS X). Some keyboard codes (including a Scroll Lock, Caps, Num Lock and F1-F12 keys) must be reset because of that.


  • AppStereo, AppSurround and AppWall plugins are now available on Linux. They can also be run in the OpenGL API on Windows.
  • AppSoft is renamed into AppLevel. Now it is possible to select different rendering devices on its start-up via -type CLI option: hw (for the hardware GPU), ref (a reference rasterizer), null (no renderer), soft (a software rasterizer), warp (a WARP device) and feature levels of DirectX (91, 92, 93, 10, 101, 11).

Stand-alone Tools

  • New Terrain console tool creates a Unigine-native terrain and a normal map for it from a hight map, and vice versa. It can be used to automate terrain creation, if necessary.
  • Added an shader compiler for Direct3D11 and PlayStation3 (it is found under source/tools/Interpreter/scripts/render folder). For offline compilation of shaders into a cache, the effect-compiler tool (fxc.exe) is required.

P.S.: Happy New Year to everyone! We have a full pack of new amazing developments in progress, soon to be released in further updates of Ungine SDK.