Development log: March 26, 2013
Multi-projector Output, Edge Blending, Non-linear Image Mapping
AppProjection is used to create multi-projector setups, that are commonly-used for virtual training and simulation systems. Due to edge blending and non-linear image mapping support, it is possible to create large curved displays covering 360 degrees, if required.
Settings for each projection (via Main menu -> Wall -> Projection) include:
- Geometry distortion correction
- Soft-edge blending
- Color correction
Adjustable field of view and bezel compensation are also available.
The number of displays in a row is controlled via -width CLI option. Set up configuration can be saved into a preset file (*.projection) to be loaded at any time.
Here is a three-projector setup in our studio. The size of this screen is 6x2 meters (suddenly there's not so much space left in the conference room).
Huge spaces of Valley benchmark (64 000 000 square meters) projected onto a screen:
Panoramic Rendering and Fisheye
With a new AppPanorama plugin, it is possible to render impressive 180 degree panoramas in case extra-wide field of view is required. Unlike AppProjection, it is used across one screen only. It has three modes available via -mode CLI option passed on the start-up:
- panorama - panoramic projection with curved edges (by default)
- linear - linear panorama without distortion at the edges
- fisheye - spherical panorama (requires a square aspect ratio)
Curved panoramas of Valley and Heaven (be informed, can cause dizziness):
AppPanorama stitches four viewports into one (due to a very high degree of curvature for edges). The overlapping area between viewports is controlled via -border CLI option. It takes arguments from 0 (no overlapping, visible seams) to 1 (half-screen overlapping area). Here are these four viewports:
- Improved the quality of HDR shaft flares. They are now rendered into a half-screen buffer (rather than quarter of the screen size). Additional blurring and noise eliminate any banding artifacts.
- Added additional Attenuation parameter for HDR shaft flares (Render -> HDR -> Shaft -> Attenuation) to control fading of flares along their length.
- Added similar Attenuation parameter for Volumetric shadows (Render -> Postprocess -> Shaft -> Volumetric attenuation).
- Now it is possible to have up to 4 types of impostors rendered fast and efficiently (in one DIP) via a single ObjectGrass with grass_impostor_base assigned. For that, bake impostors into a diffuse texture row by row. Height, probability of spreading and other parameters of such impostors are set up per type (row). Check a new sample samples/materials/impostor_03.
- New sample to stress-test hardware occlusion query functionality: samples/stress/query_00.
- Small performance optimization for Tracker: it checks if render textures (for example, LUT texture, Environment cube map or any other set via engine.render.set*TextureName()) are already used before updating them each frame.
- Correct detection of the video memory size on Windows in case it is higher then 4GB.
- AMD GPUs under Linux are now correctly detected.
- Windows 8 OS name is now correctly logged into the console and a log file.
- FPS counter filtration can be set up via engine.app.setFilter() (for example, disable it completely and always show the current value by setting it to 0).
- Added getter functions to return modelview and projection matrices for all multi-viewport plugins: AppWall, AppSurround, App3DSurround or AppProjection.
- In utils.h, Unigine::getPlayerMouseDirection() function works for all viewports when multi-viewport plugins are loaded (AppWall, AppSurround, App3DSurround or AppProjection). This allows for testing mouse intersection across all screens.
- For Windows XP, the application will be rendered black when the window is out of focus. It is also valid if any multi-viewport plugin is loaded.
- When AppWall plugin is used, monitor bezel compensation sliders (Main menu -> Wall -> Bezel X and Bezel Y) are disabled if they are not available for the current configuration of a monitor wall.
- All C++ engine App* plugins (such as AppWall, AppSurround, etc.) use core profile if run in OpenGL API.
- For all App* engine plugins, device remove event under DirectX 11 is now correctly handled.
- In case of a multi-monitor configuration, full-windowed applications without decorations (with video_fullscreen set to 2) automatically choose the best display from available ones based on the resolution on Windows and Linux. If a resolution is set to cover all available displays, the application is automatically spanned across them. It works both for horizontal and vertical setups.
ZLIB Image Compression
Now image resources can have smaller memory footprint due to ZLIB image compression. It is useful for images that cannot be compressed using quality-loss algorithms (DXT, JPG, etc.): e.g. GUI textures with thin lines that need to be rendered with pixel precision.
Two new compressed image formats are available:
- ZLC1 for faster compression (for example, in run-time)
- ZLC2 for compression that enables a smaller file size
Both formats are supported in the ImageDDS tool.
- Now it is possible to create mesh-based particle systems. If ObjectMeshCluster is added as a child node of ObjectParticles, meshes are automatically spawned (due to new getParticleTransforms() and getParticleVelocity() functions). Check a new sample samples/objects/cluster_01.
- A mesh-based mask can be set for ObjectGrass, ObjectMeshClutter or WorldClutter (Nodes -> Mesh -> Mask mesh). For example, this option can be used to create roads, rivers and in other cases when vector mask precision is required. A mesh for masking should be a simple planar mesh. Inverse option toggles if objects are placed inside or outside the mesh contour. Check new samples samples/objects/clutter_01, grass_01 and grass_03.
- Volumetric clouds of ObjectSky can be simulated in the background - when a volume surface is disabled or no material is assigned to it - via the Simulation option (Nodes -> Parameters -> Simulation). When weather is controlled by Tracker, clouds are enabled and rendered much faster, since all required calculations are already done.
- Added setDensityOffset() and getDensityOffset() functions for volumetric clouds of ObjectSky. They allow to set/get the current offset of a 3D mask and reposition the clouds, if necessary.
- WorldClutter, ObjectMeshClutter and ObjectGrass check for intersections with ObjectTerrain, ObjectMesh and ObjectMeshDynamic even if they are much higher up in the hierarchy and there are some other nodes between them.
- Now more issues when ObjectVolumeSphere scaled uniformly is rendered with volume_light_base material.
An example of mesh-based particles:
Mesh-based vector masking for grass with high precision:
- Antialiasing works correctly on Mac OS X systems running on AMD graphics cards.
- Fixed issues on disabling light scattering.
- Fixed a bug with shadows not rendered in reflections (when Materials -> States -> Shadow option is enabled).
- Flipped buffers for the interlaced stereo mode; now a left buffer goes to the left eye and the right buffer to the right one.
- Multi-channel rendering system (Syncker) now runs on Windows nodes smooth and fast. The size of UDP packets sent over the network has been reduced, while socket buffers were increased in size for better performance.
- New send() and recv() functions in Socket class give control over the internal socket buffer size.
- Added Reflection class for the user/extern class and namespace reflection. It allows to get names and custom attribute string for all variables, arrays, user classes and namespaces within it. Such attributes can be used for smart, automatic code generation for GUI or game logic. For example, it is possible to get attributes, parse them in the required way, and feed them to Expression which will compile the resulting code.
- Script performance is increased due to a heap of new mnemonics.
- Added two-element swizzles for vectors (in addition to already implemented one-, three- and four-element ones): vec3.xz.
- Added engine.world.callv(), engine.system.callv() and enigne.editor.callv() functions that execute any world, system or editor script function and receive an array of arguments (up to 8 arguments in the array are supported).
- Fixed incorrect scoping of private class functions.
- New allocate() method for vectors that pre-allocates memory for a given number of elements.
- Added + and - operators to add or subtract a scalar value from a vector (a vector should go first, before a scalar).
- Added support for scatter/gather operations for four-component vectors. Only ivec4 type is supported for array indexing. After an array is created (for example, float array), the accessor function (array[ivec4(0,1,2,3)]) returns four values as ivec4 (if the array type is int or long), vec4 (if float) or dvec4 (if double).
- Now Unigine engine comes with a new GUI skin.
- All imaged-based GUI resources are compressed into the ZLC1 format for smaller memory footprint.
- Performance gain by 10-15 per cent for all GUI fonts and WidgetFlash due to fixed-function pipeline (FFP) optimizations. Check new samples samples/widgets/font_07 (with a texture-based font) and flash_07.
- Added convenient snap-to-grid options (Tools -> Common) to position and rotate nodes. The grid can be rendered with depth testing; per-axis alignment or a grid mode are also available.
- Console and the profiler are now always rendered on top (first, the console and then the profiler).
- Messages rendered via engine.visualizer.renderMessage2D() and engine.visualizer.renderMessage3D() can be aligned by passing a second element of the vector as an align argument (see more details in the function library).
- Added fixed width and hight attributes for tables in all widgets with rich-text formatting support. The syntax is as follows: <tr height="x"> and <td width="x">.
- Added setFontPermanent() function into Widget class. It prevents the text color from being changed when an option is not available, the widget loses focus and so on.
- Added new modes for hiding scrollbox sliders via setHScrollHidden() and setVScrollHidden() (see more details in the function library).
- Fixed a bug when after a click on the disabled field, the window lost focus.
- Fixed an issue with WidgetIcon translation.
- Tracker window is automatically closed when no world is loaded.
- New Widgets::Deform high-level widget allows for projection distortion correction in AppProjection plugin. (It can be found in data/core/systems/widgets/widget_deform.h.) Check it on a new sample samples/interface/deform_00.
- Each viewport of AppWall, AppSurround or App3DSurround plugins now has a dedicated GUI instance for interface rendering. It is accessed via engine.wall.getGui() and engine.surround.getGui() functions. Check samples samples/plugins/app_wall_00 and app_surround_00.
New minimalistic look of the engine interface:
Snap to grid option for positioning (Tools -> Common in UnigineEditor):
- Decreased WidgetFlash memory footprint due to an optimized texture atlas handling. Now it is regenerated when required (for example, on video_restart) rather than stored in the system memory.
- Flash bitmap images are now compressed into ZLC1 format by default for smaller memory footprint.
- Fixed a bug with non-freed memory. Now when a movie clip loads a movie and is deleted afterwards, the memory is properly deallocated.
C++ API is extended to allow low-level, graphics API independent access to textures, shaders and states. Any post-process effect can now be implemented purely on C++ side.
- Added Unigine::Texture class to create texture resources on any API and handle them on the low level.
- Added Unigine::Shader class with support for parameter setting, which allows for low-level shader implementation access.
- Added Unigine::State class for handling render states for all APIs.
- Added Unigine::TextureRender class to create and manage a render target/framebuffer. If allows for access to render textures of different types (depth, screen color, cube textures, etc.), as well as render texture layers.
Other C++ API changes are:
- Added Unigine::Player class for managing base parameters of cameras. The current in-game or editor player can be get via Unigine::Game::getPlayer() or Unigine::Editor::getPlayer() functions.
- Added a bunch of useful functions to work with triangles (including calculation of barycentric coordinates, normal vectors and triangle planes), lines, points, as well as handle orthographic transformations. Check UngineGeometry.h file.
- Added a number of functions into Unigine::Node class to check if a node is an object, light source, decal, sound source, and so on (isObject(), etc. functions).
- Added methods for fast binary searching into Unigine::Vector class: left() (finds a previous value in the vector) and right() (finds the next value). Similar functions as available in UnigineScript.
- Added new functions for fast rendering of primitives into Unigine::Ffp class: addVertex() that accepts a vertex array, and addIndices() that accepts two, three arguments or an array of indices.
- Double-click event is now available on all tablet devices via APP_BUTTON_DCLICK. This event is correctly handled even by low FPS.
- For iOS platform, _PAD, _IPHONE and _IPOD defines with versions are now available. For example, you can use the following syntax: #if defined(_IPAD) && (_IPAD >= 3) ... #endif. (Please note that iPod devices are detected by the system with _IPOD and _IPHONE defines at the same time, hence iPod-specific code should always go before iPhone-specific one.)
- Added support for mouse wheel scroll events for Windows RT via APP_BUTTON_UP and APP_BUTTON_DOWN.
- Android applications running on the foreground are now correctly restored after the shutdown event.
- Samples in the Unigine SDK for Android now set the targetSdkVersion to 14.
- Fixed an issue with non-compiling shaders on PowerVR GPUs for Android.
- Updated OpenAL sound library version on Android now goes with OpenSL ES support.
- Fixed OpenAL errors on iOS.
- Added a new APP_IDENTIFIER environment variable into the iospack script. Now developers have full control over a name of the signed application.
- Added detection of Qualcomm Adreno 205 and 305 graphics chips.
- In *.ulink files absolute path names can be used on all supported platforms. It is possible to access resources from another disk on Windows (for example, E:\resources\) or use paths from root level on Linux or Mac OS X (for example, /username/resources/).
- Console command memory_info now prints information on heap memory as well.
Added set/isFixed() flag to synchronize rendering FPS to the physics' one. Such FPS limitation allows to calculate physics each rendered frame (rather than interpolate it when this flag is set to 0). In this mode, there is no twitching of physical objects if they have non-linear velocities. (If the rendering FPS is lower than the physics one, this flag has no effect.)
- Improved XML file compression; now compressed files are around two times smaller than before.
- Added show and hide console commands to open and close the console. For example, on mobile devices they allow for checking console messages via Telnet connection.
- date() function can receive a second integer argument with Unix timestamp to be converted into a readable format.
- Fixed a bug with slowing down of sound when video and sound were played from separate files.
- During compilation, plugins check if all required dependencies are found. If libraries are not found, the current plugin is skipped and all other modules are still built.
- Fixed issues with Visual Studio 2008 projects.
- GPUMonitor plugin now correctly detects chip frequencies for NVIDIA GPUs due to the extended NVApi library.
- Now it is easier to create custom App* engine plugins based on the existing ones (such as AppWall, AppSurround, etc.), since they are initialized in the base virtual classes.
New Project Generator
From an SDK browser, it is now possible to conveniently create a new project. To start developing your Unigine-based application, choose a path to store files, project settings and hit Create new project button.
PS: The Android version of Oil Rush is finally available on Google Play! (For now, exclusively for Qualcomm chips: Adreno 225 or 320 GPU is required.)
PPS: Oculus Rift support is on the way, it is already implemented and will be available for customers in the next SDK update in April.