Programming
Fundamentals
Setting Up Development Environment
Usage Examples
UnigineScript
C++
C#
UUSL (Unified UNIGINE Shader Language)
File Formats
Rebuilding the Engine and Tools
GUI
Double Precision Coordinates
API
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
CIGI Client Plugin
Rendering-Related Classes

NVIDIA 3D Vision Surround Output with App3DSurround Plugin

An App3DSurround plugin is used to render the application across 3 monitors at the maximum frame rate using NVIDIA 3D Vision technology and multiple GPUs (Multi-GPU or SLI setup). 3D Surround requires to run the application in the fullscreen mode. Windowed mode is rendered in the non-stereoscopic mode.

Notice
The App3DSurround plugin is available only on DirectX 11 graphics API. So it can be used under Windows only.

Launching App3DSurround

To run your application in 3D Vision Surround mode, make sure that it is supported by a graphics card. Stereoscopic 3D should be enabled on the driver lever:

  1. Click on the desktop with the right mouse button.
  2. Open NVIDIA Control panel.
  3. Go to Stereoscopic 3DSet up stereoscopic 3D.
  4. Click Enable stereoscopic 3D settings and follow the setup wizard.

To use the plugin, specify the extern_plugin command line option and STEREO_3D_SURROUND define on the start-up:

Shell commands
main_x86d -extern_plugin "App3DSurround" -extern_define STEREO_3D_SURROUND

Also you can create a new project with NVIDIA 3DSurround support by checking the NVIDIA 3DSurround 3-monitor stereo 3D option in the New Project tab of the Unigine SDK Browser.

Customizing App3DSurround

In the 3D Vision Surround mode, Unigine allows the full control over all cameras that render the application onto three monitors. If necessary, you can create cameras with asymmetric viewing frustums and set any desired field of view for them.

To create custom cameras for 3D Vision Surround stereo mode, you can modify the data/core/scripts/system/stereo.h script. Another possible scenario is to comment stereo.h out from the system script unigine.cpp, wrap your code around with #ifdef HAS_APP_3D_SURROUND ... #endif and implement your own camera configuration in the render() function of the system script.

Source code (UnigineScript)
int render() {
	#ifdef HAS_APP_3D_SURROUND
		// place an implementation of a 
		// custom camera configuration here
		// ...
	#endif
	return 1;
}

There are two possible setups depending on how the primary monitor is rendered. It can be drawn by:

  1. The default engine renderer (the same as when a usual one-window application is rendered).
  2. The 3D Surround renderer itself (which is safer if you are going to use asymmetric frustum for the primary monitor and modify its modelview matrix). This variant gives the full control over all three cameras used for rendering.
Both renderers should not be enabled at the same time.

The following example demonstrates how to set up 3 monitors stereo configuration and choose the renderer for the primary monitor.

1. Using default engine renderer

This variant is used in stereo.h script by default. It is used when you want to control two side monitors without modifying the central camera.

  1. Enable rendering onto two side monitors by the 3D Surround application renderer. The central monitor is rendered by default.
    Source code (UnigineScript)
    // Enable the left monitor
    engine.surround.setEnabled(0,1);
    // Enable the right monitor
    engine.surround.setEnabled(2,1);
  2. Set stereo pair projection matrices for each of two side monitors, i.e. one projection matrix for the left stereo image and one for the right stereo image. For the central monitor the default engine renderer will set matrices automatically.
    Source code (UnigineScript)
    // Set projection matrices (a stereo pair) for the left monitor
    engine.surround.setLeftProjection(0,left_projection_matrices[0]);
    engine.surround.setRightProjection(0,left_projection_matrices[1]);
    
    // Set projection matrices (a stereo pair) for the right monitor
    engine.surround.setLeftProjection(2,right_projection_matrices[0]);
    engine.surround.setRightProjection(2,right_projection_matrices[1]);
  3. In the same way, set stereo pair modelview matrices for the left and right monitors. Again, for the center monitor the default engine renderer will set matrices automatically.
    Source code (UnigineScript)
    // Set modelview matrices (a stereo pair) for the left monitor
    engine.surround.setLeftModelview(0,left_modelview_matrices[0]);
    engine.surround.setRightModelview(0,left_modelview_matrices[1]);
    
    // Set modelview matrices (a stereo pair) for the right monitor
    engine.surround.setLeftModelview(2,right_modelview_matrices[0]);
    engine.surround.setRightModelview(2,right_modelview_matrices[1]);
  4. The stereo pairs for side monitors are ready. But you also need to specify what cameras will render when the application is switched from the stereo mode to the non-stereo one. It is necessary, for example, when 3D Vision Surround application is changed from the full screen mode to the windowed one that does not support stereo rendering.
    For such case, you need to specify separate projection and modelview matrices for rendering cameras in mono mode:
    Source code (UnigineScript)
    // Set projection and modelview matrices for the left monitor in mono mode
    engine.surround.setProjection(0,mono_left_projection_matrix);
    engine.surround.setModelview(0,mono_left_modelview_matrix);
    
    // Set projection and modelview matrices for the right monitor in mono mode
    engine.surround.setProjection(2,mono_right_projection_matrix);
    engine.surround.setModelview(2,mono_right_modelview_matrix);
  5. Set postprocess materials for all three monitors in the update() function of the unigine.cpp system script, including the central monitor, that will allow the corresponding postprocess shader to render viewports in the stereo or mono mode.
    Source code (UnigineScript)
    // Check if the default engine renderer is in mono or stereo mode
    if(engine.render.getStereo()) {
    	// Set postprocess material for stereo rendering for the central monitor
    	engine.render.setPostMaterials("post_stereo_separate");
    } else {
    	// Set postprocess material for mono rendering for the central monitor
    	engine.render.setPostMaterials("post_stereo_replicate");
    }
    
    // Check if 3D Surround renderer is in the mono or stereo mode
    if(engine.stereo.isEnabled()) {
    	// Set postprocess material for stereo rendering for the left and right
    	// monitors
    	engine.surround.setMaterials(0,"post_stereo_separate");
    	engine.surround.setMaterials(2,"post_stereo_separate");	
    } else {
    	// Set postprocess material for mono rendering for the left and right
    	// monitors
    	engine.surround.setMaterials(0,"post_stereo_replicate");
    	engine.surround.setMaterials(2,"post_stereo_replicate");
    }

2. Using 3D Surround renderer

This variant allows you to configure all three monitors, including the primary (central) one. This method serves to set custom cameras with asymmetric frustums for all three monitors, including the primary one.

  1. Disable the default engine renderer (the same renderer as in case of a usual one-window application) via engine.render.setEnabled(). This is a necessary step if you are going to set asymmetric viewing frustum for the central camera (because modifying a modelview matrix of the default renderer directly can be unsafe).
    Source code (UnigineScript)
    engine.render.setEnabled(0);
  2. Enable rendering onto all three monitors by the 3D Surround application renderer:
    Source code (UnigineScript)
    // Enable the left monitor
    engine.surround.setEnabled(0,1);
    // Enable the center monitor
    engine.surround.setEnabled(1,1);
    // Enable the right monitor
    engine.surround.setEnabled(2,1);
  3. Set stereo pair projection matrices for each monitor, i.e. one projection matrix for the left stereo image and one for the right stereo image:
    Source code (UnigineScript)
    // Set projection matrices (a stereo pair) for each of three monitors
    engine.surround.setLeftProjection(monitor_number, projection_matrices[0]);
    engine.surround.setRightProjection(monitor_number, projection_matrices[1]);
  4. Set stereo pair modelview matrices for each of three monitors:
    Source code (UnigineScript)
    // Set modelview matrices (a stereo pair) for each of three monitors
    engine.surround.setLeftModelview(monitor_number, modelview_matrices[0]);
    engine.surround.setRightModelview(monitor_number, modelview_matrices[1]);
  5. The stereo pairs for all monitors are ready. But you also need to specify what cameras will render when the application is switched from the stereo mode to the non-stereo one. It is necessary, for example, when 3D Vision Surround application is changed from the full screen mode to the windowed one that does not support stereo rendering.
    For such case, you need to specify separate projection and modelview matrices for rendering cameras in mono mode:
    Source code (UnigineScript)
    // Set projection and modelview matrices for each of three monitors in mono mode
    engine.surround.setProjection(monitor_number, mono_projection_matrices);
    engine.surround.setModelview(monitor_number, mono_modelview_matrices);
  6. Set postprocess materials for all three monitors that will allow the corresponding postprocess shader to render viewports in the stereo or mono mode.
    Source code (UnigineScript)
    if(engine.stereo.isEnabled()) {
    	// Set postprocess material for stereo rendering for each monitor
    	engine.surround.setMaterials(monitor_number,"post_stereo_separate");
    } else {
    	// Set postprocess material for mono rendering for each monitor
    	engine.surround.setMaterials(monitor_number,"post_stereo_replicate");
    }

After setting 18 matrices for rendering cameras in stereo and mono modes and assigning corresponding postprocess materials, your application is ready for 3D Vision Surround.
In addition, you can also control what nodes and what reflections are rendered into each of three viewports by using engine.surround.setViewportMask() and engine.surround.setReflectionMask(), respectively.

Last update: 2017-12-21