Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

HideElements
cssselector#tocVertical, #tocHorizontal

In this section we give a quick overview of the VFB and the ways we can control it via App SDK.

Responsivegridmacro
VAlignmentstart
Columns2repeat(2, 1fr)
Columns3width1100px
Columns1repeat(3, 1fr)
Columns1width1740px
Columns2width1290px

Div
stylepadding-left: 5px;padding-right: 5px;padding-bottom: 10px;
classdashboard
Textboxcard
PageToIncludeSystem Requirements
CardPageLinkVFB

UI and VFB

The redesigned V-Ray Frame Buffer (VFB) provides a higher level of post processing adjustments and ability to modify your scene.

Textboxcard
PageToIncludeSystem Requirements
CardPageLinkVFB Layers API

VFB Layers API

This page provides information on how to control the V-Ray Frame Buffer Layers via a program API

Introduction

 

The redesigned V-Ray Frame Buffer (VFB) is a second generation V-Ray virtual frame buffer.

VFB is much more than a render image holder window. The new enhanced version provides a higher level of post processing adjustments and ability to modify your scene from inside the VFB. Here is a list of old and new benefits you should know:

  • Image preview:
    Loads render elements channels via a dropdown list;
    Works with display corrections;
    Loads various 8bit and 32bit file formats, including V-Ray resumable files;
    Image comparison between 2 or 4 renders;
  • Image management:
    Keeps the rendered image in full 32-bit floating point format;
    Can store history of rendered images with their post rendering corrections;
    Can save corrected output to various image formats;
  • Image editing and post processing:
    Set Color Corrections to rendered image and its elements;
    Composite mode for Back to Beauty workflow including layers corrections;
    LightMix control on lights contribution in the rendered image;
  • Scene editing:
    Can modify actual lights values by transferring updated intensity and color from LightMix mode (requires implementation);
    IPR camera navigation control from inside VFB;
  • Render management:
    Denoiser control;
    Region rendering control;
    Allows you to choose the order in which the buckets are rendered;

User Interface

Image Removed

VFB Menu

The V-Ray Frame Buffer menu holds the main frame buffer commands. Some of the options are also available in the VFB toolbar for a quick access.

 

...

Menu

...

Menu Options

...

File

...

Save current channel – Saves the currently loaded channel to an image file format.

Save all image channels to separate files – Saves all the render elements to separate files.

Save all image channels to single file – Saves the image to a single multi-channel EXR or .vrimg file.

Load image – Opens an image file to be previewed in the V-Ray Frame Buffer.

Batch image processing – Allows processing of multiple .vrimg files with the same layer tree changes at the same time.

...

Batch Image Processing

Image Removed

Input folder – Specifies a path to start images.

Output folder – Specifies a path for the output images.

Layer preset – Specifies a layer tree corrections preset.

Output filenames suffix – Specifies a suffix added to the output image filenames.

Overwrite existing – Enables overwrite of existing files with the same name in the output folder.

...

Render

...

Start interactive rendering – Calls the VFBRenderInteractive callback. Requires showVfbButtonInteractiveStart to be set to true in RendererOptions.

Abort rendering – Stops the current rendering.

Render – Starts rendering. If the VFBRenderLast callback is set, it will not start rendering, only call the callback.

...

Image

...

Follow mouse – Renders the closest bucket found to the mouse pointer, when using the bucket image sampler. If the progressive sampler is used, V-Ray samples the closest pixels to the mouse pointer.

Follow mouse – Drag the mouse over the VFB while rendering to change what part of the image is sampled first;
Follow mouse (locked) – Locks the bucket (or sampling) starting point.

Copy current channel to clipboard – Copies the current channel to the clipboard.

Clear image – Clears the contents of the frame buffer. This is useful when starting a new render to prevent confusion with the previous image.

...

View

...

Display color space –Specifies the color space, in which the image is displayed.

None – Does not specify a color space;
sRGB – Displays the image in sRGB color space;
OCIO – Displays the image in a color space loaded from an OCIO configuration file;
ICC – Displays the image in a color space loaded from an ICC configuration file;
Gamma 2.2 – Displays the image in Gamma 2.2 color space.

Zoom VFB – Zooms in/out the rendered image in the VFB.

Zoom 50% – Zooms out to 50%;
Zoom 100% – Zooms to 100%. Alternatively, double-click in the VFB with the left mouse button;
Zoom 150% – Zooms in to 150%.
Zoom to fit – Zooms the current image to fit in the VFB. If Render Region is active – zooms to the region.

Channels – Chooses which channels to see.

View red channel – Displays the red channel;
View green channel – Displays the green channel;
View blue channel – Displays the blue channel;
Switch to alpha channel – Displays the alpha channel;
Monochromatic mode –Displays the image in monochromatic mode.

Color clamping – Opens the color clamping submenu options:

Force color clamping – Forces color clamping;
View clamped colors – Displays the clamped colors.

Use pixel aspect – Enables visualization of the pixel aspect ratio.

Panorama View – Shows the image in 360° view.

Show History – Shows the History panel. 

Show Layers – Shows the Layers panel.

...

Options

...

VFB Toolbar

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Specifies RGB values. Click on the arrow to open a context menu with the available option.

None – Does not specify the RGB value.
HSV – Specifies the Hue, Saturation and Value of the pixel under the current mouse position.
Web – Specifies the HEX of the pixel under the current mouse position.
8bit – Specifies the 8bit color palette of the pixel under the current mouse position.

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Save current channel – Saves the current channel to an image file format;
Save all image channels to separate files – Saves all the render elements into separate files;
Save all image channels to single file – Saves the image into a single multi-channel EXR or .vrimg file.

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Render History

The V-Ray VFB keeps a history of previously rendered images, and lists each with a number, thumbnail, and textual details in the Render history panel. Up to four images can be called from the history to be compared in the VFB (as shown below). History files are stored as .vrimg files in a user-specified folder. Render history settings can be configured in the VFB Settings window.

...

Image Removed

...

Enables or disables image A/B vertical comparison. Select images A and B from the render history.

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

 

 

Section
Column
width40%
UI Text Box
typetip

The keyboard keys from 1 to 9 can be used to quickly load the first 9 images from the history to the VFB.

Edit note – Allows you to add a text comment to the image; the comment appears below the image.

Set A – Sets the render as A image for A/B comparison.

Set B –  Sets the render as B image for A/B comparison.

Load to VFB – Loads the selected image in the VFB (same as double-clicking on the image).

Delete – Deletes the selected image from history. The image is moved to the system's Recycle Bin and can be restored from there if needed.

Load layers – Loads the layer tree preset of the selected image.

Reload history – Re-reads the history image list. This may be needed if the history folder is updated outside of Cinema 4D(e.g. from another Cinema 4D session).

UI Text Box
typeinfo

Manually saved .vrimg files can also be added to the History folder, but they need to be saved with all image channels in one .vrimg file to keep the complete image info.

Column
width60%

Image Removed

Layers

The V-Ray Frame Buffer includes a suite of color corrections and tools for adjusting the image. The tools are added as layers and displayed in a layer tree. You can enable or disable a particular tool using the visibility icon (Image Removed) to the left of its name.

For more information on using the Layers, see the Layers page.

...

width50%

...

Image Removed

...

Creates a layer. Multiple layers of the same type can be added.

Folder – Allows grouping multiple layers;
Background – Adds a background color correction layer;
Render Element – Selects a render element from your image that you can use in compositing. This is only available when the Source layer is set to Composite;
Constant – Adds a solid color that can be used to achieve an effect on another layer (for example to multiply by the constant);
Exposure – Adds an Exposure color correction layer;
White Balance – Adds a White Balance color correction layer;
Hue/Saturation – Adds a Hue/Saturation color correction layer;
Color Balance – Adds a Color Balance color correction layer;
Curves – Adds a Curves color correction layer;
Lookup Table – A Lookup Table layer allows loading a LUT file for color transformations;
Filmic Tonemap – Contains different types of mapping curves and gamma corrections. Also allows selection of a color space.

For more information, see the Layers page.

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Image Removed

...

Column
width50%

Image Removed

Each layer has a context menu. Right-click to display it:

...

width50%

...

Column
width50%

Image Removed

Stats

The V-Ray Frame Buffer allows monitoring of different statistics and information about your scene in the Stats panel. The exact contents of the Stats changes depending on the scene,  the rendering mode (interactive vs production, bucket vs progressive) and others.

UI Text Box
typetip

Right-click to display a context menu, allowing you to copy the Stats values.

Section

Image Removed

 

 

Render Region

Region rendering can be used in both IPR and Production modes to isolate only part of the frame for rendering.

Saving a region to an .exr file saves only the render region and the rest of the frame is rendered black. 

 

VFB Shortcuts

These shortcuts navigate through the VFB image. You can also find them in the VFB Settings window. Please note that the VFB window must have the current focus for the shortcuts to have effect:

...

 

Camera control for interactive (RT) rendering

This VFB feature is currently only available in AppSDK-based V-Ray products.

You can modify the camera view while the RT engine is running with the following combinations:

...

Move the camera forward or backward

...

Control from code

If you don't want the VFB window opened besides your app main window, you can hide it using the showFrameBuffer option:

 

Tabs Container
directionhorizontal
Tabs Page
titlePython
Code Block
languagepy
firstline1
with vray.VRayRenderer(showFrameBuffer=False) as renderer:
Tabs Page
titleC++
Code Block
languagecpp
RendererOptions options;
options.showFrameBuffer = false;
VRayRenderer renderer(options);
Tabs Page
titleC#.NET
Code Block
languagec#
RendererOptions options = new RendererOptions();
options.ShowFrameBuffer = false;
 
using (VRayRenderer renderer = new VRayRenderer(options))
{
}
Tabs Page
titleNode.js

 

Code Block
languagejs
var renderer = vray.VRayRenderer({
    showFrameBuffer: false
})

You can also completely disable the window creation using the enableFrameBuffer option (for example to avoid allocating additional resources or for faster startup):

Tabs Container
directionhorizontal
Tabs Page
titlePython
Code Block
languagepy
firstline1
with vray.VRayRenderer(enableFrameBuffer=False) as renderer:
Tabs Page
titleC++
Code Block
languagecpp
RendererOptions options;
options.enableFrameBuffer = false;
VRayRenderer renderer(options);
Tabs Page
titleC#.NET
Code Block
languagec#
RendererOptions options = new RendererOptions();
options.EnableFrameBuffer = false;
 
using (VRayRenderer renderer = new VRayRenderer(options))
{
}
Tabs Page
titleNode.js

 

Code Block
languagejs
var renderer = vray.VRayRenderer({
    enableFrameBuffer: false
})

The VFB class

 

Tabs Container
directionhorizontal
Tabs Page
titlePython
Code Block
languagepy
firstline1
with vray.VRayRenderer() as renderer:
    vfb = renderer.vfb
    vfb.shown = True             # Can be used to hide and show the window
    vfb.interactivity = True     # Whether camera mouse control is enabled
    vfb.position = (0,0)         # Position of the window in screen-space coordinates
    vfb.size = (800, 600)        # Size of the window in pixels
    vfb.alwaysOnTop = True       # Toggles always-on-top window behavior
    stateBuffer = vfb.getState() # Can be used to save serialized window state
    vfb.setState(stateBuffer)    # Can be used to restore serialized window state
Tabs Page
titleC++
Code Block
languagecpp
VRayRenderer renderer;
VRayRenderer::VFB& vfb = renderer.vfb;
vfb.show(true /*show*/, true /*setFocus*/);     // The window is visible and auto focused
vfb.enableInteractivity(true);                  // Whether camera mouse control is enabled
vfb.setPositionAndSize(0, 0, 800, 600);         // Position in screen-space and size in pixels
vfb.setAlwaysOnTop(true);                       // Toggles always-on-top window behavior
size_t numBytes = 0;
VFBState *stateBuffer = vfb.getState(numBytes); // Can be used to save serialized window state
vfb.setState(stateBuffer, numBytes);            // Can be used to restore serialized window state
Tabs Page
titleC#.NET
Code Block
languagec#
using (VRayRenderer renderer = new VRayRenderer())
{
	VFB vfb = renderer.Vfb;
	vfb.Shown = true;                       // Can be used to hide and show the window
	vfb.Interactivity = true;               // Whether camera mouse control is enabled
	vfb.SetPositionAndSize(0, 0, 800, 600); // Position in screen-space and size in pixels
	vfb.AlwaysOnTop = true;                 // Toggles always-on-top window behavior
	byte[] stateBuffer = vfb.GetState();    // Can be used to save serialized window state
	vfb.SetState(stateBuffer);              // Can be used to restore serialized window state
}
Tabs Page
titleNode.js

 

Code Block
languagejs
var renderer = vray.VRayRenderer();
var vfb = renderer.vfb;
vfb.shown = true;                       // Can be used to hide and show the window
vfb.interactivity = true;               // Whether camera mouse control is enabled
vfb.position = { x: 0, y: 0 };          // Position of the window in screen-space coordinates
vfb.size = { width: 800, height: 600 }; // Size of the window in pixels
vfb.alwaysOnTop = true;                 // Toggles always-on-top window behavior
stateBuffer = vfb.getState();           // Can be used to save serialized window state
vfb.setState(stateBuffer);              // Can be used to restore serialized window state

There is also a plugin called SettingsVFB that controls the lens effects of the VFB. The complete list of its parameters can be found in the AppSDK reference guide or inside the installation package in the help/ folder.

 

VFB Progress Bar

You can add text content and a percentage value to the VFB progress bar, e.g. like in the example with the data received from the Progress Event callback.

Image Removed

VFB Viewport Context Menu

You can add also custom context menu items to the VFB viewport.

Image Removed

Tabs Container
directionhorizontal
Tabs Page
titlePython
Code Block
languagepy
firstline1
# VFB Context menu entries
contextMenuItems = [
    {'id': 0, 'type': 'normal',   'text': 'Custom option'},
    {'id': 1, 'type': 'normal',   'text': 'Custom disabled option', 'enabled': False},
    {'id': 2, 'type': 'checkbox', 'text': 'Custom checkbox'},
    {'id': 3, 'type': 'checkbox', 'text': 'Custom checkbox 2', 'defaultValue': 1}
]


# VFB Context menu callback
def onContextMenu(renderer, command, x, y):
    if command == 0:
        print("Custom option clicked")
    elif command == 1:
        print("This is disabled")
    elif command == 2:
        print("Value of Custom checkbox is", renderer.getVFBContextMenuItemValue(command))
        # Note that the value will not change automatically, you must change it yourself
    elif command == 3:
        value = renderer.getVFBContextMenuItemValue(command)
        renderer.setVFBContextMenuItemValue(command, 1 - value)
        print("Value of Custom checkbox 2 changed from", value, "to", 1 - value)
    else:
        print('Command %d not implemented' % command)


renderer.setVFBContextMenuItems(contextMenuItems)
renderer.setOnVFBContextMenuSelected(onContextMenu)
Tabs Page
titleC++
Code Block
languagecpp
// Context menu callback
void onContextMenu(VRayRenderer& renderer, int command, int x, int y, void*) {
	int value = 0;
	switch (command) {
	case 0:
		printf("Custom option clicked\n");
		break;
	case 1:
		printf("This is disabled\n");
		break;
	case 2:
		renderer.getVFBContextMenuItemValue(command, value);
		printf("Value of Custom checkbox is %d\n", value);
		// Note that the value will not change automatically, you must change it yourself
		break;
	case 3:
		renderer.getVFBContextMenuItemValue(command, value);
		renderer.setVFBContextMenuItemValue(command, 1 - value);
		printf("Value of Custom checkbox 2 changed from %d to %d\n", value, 1 - value);
		break;
	default:
		printf("Command %d not implemented\n", command);
	}
}
 
void setupContextMenu(VRayRenderer& renderer) {
	vector<VFBContextMenuItem> contextMenuItems;
 
	// Context menu items
	contextMenuItems.push_back({ 0, VFBMenuItemType::normal,   0, true,  "Custom option" });
	contextMenuItems.push_back({ 1, VFBMenuItemType::normal,   0, false, "Custom disabled option" });
	contextMenuItems.push_back({ 2, VFBMenuItemType::checkbox, 0, true,  "Custom checkbox" });
	contextMenuItems.push_back({ 3, VFBMenuItemType::checkbox, 1, true,  "Custom checkbox 2"});

	renderer.setVFBContextMenuItems(contextMenuItems);
	renderer.setVFBContextMenuSelectedCallback(onContextMenu);
}
Tabs Page
titleC#.NET
Code Block
languagec#
using (VRayRenderer renderer = new VRayRenderer())
{
    // Context menu items
    List<VFBContextMenuItem> contextMenuItems = new List<VFBContextMenuItem>();
    contextMenuItems.Add(new VFBContextMenuItem(0, VFBMenuItemType.normal,  "Custom option"));
    contextMenuItems.Add(new VFBContextMenuItem(1, VFBMenuItemType.normal,  "Custom disabled option", false));
    contextMenuItems.Add(new VFBContextMenuItem(2, VFBMenuItemType.checkbox, "Custom checkbox"));
    contextMenuItems.Add(new VFBContextMenuItem(3, VFBMenuItemType.checkbox, "Custom checkbox 2", true, 1));

    renderer.SetVFBContextMenuItems(contextMenuItems);

    // Context menu callback
    renderer.VFBContextMenuSelected += new EventHandler<VFBContextMenuSelectedEventArgs>((source, e) =>
    {
        int value = 0;
        switch (e.CommandId)
        {
            case 0:
                Console.WriteLine("Custom option clicked");
                break;
            case 1:
                Console.WriteLine("This is disabled");
                break;
            case 2:
                renderer.GetVFBContextMenuItemValue(e.CommandId, out value);
                Console.WriteLine(String.Format("Value of Custom checkbox is {0}", value));
                // Note that the value will not change automatically, you must change it yourself
                break;
            case 3:
                renderer.GetVFBContextMenuItemValue(e.CommandId, out value);
                renderer.SetVFBContextMenuItemValue(e.CommandId, 1 - value);
                Console.WriteLine(String.Format("Value of Custom checkbox 2 changed from {0} to {1}", value, 1 - value));
                break;
            default:
                Console.WriteLine(String.Format("Command {0} note implemented", e.CommandId));
                break;
        }
    });

    renderer.Vfb.Shown = true;
    renderer.WaitForVFBClosed();
}
Tabs Page
titleNode.js

 

Code Block
languagejs
// VFB Context menu entries
contextMenuItems = [
    {'id': 0, 'type': 'normal',   'text': 'Custom option'},
    {'id': 1, 'type': 'normal',   'text': 'Custom disabled option', 'enabled': false},
    {'id': 2, 'type': 'checkbox', 'text': 'Custom checkbox'},
    {'id': 3, 'type': 'checkbox', 'text': 'Custom checkbox 2', 'defaultValue': 1}
]

renderer.setVFBContextMenuItems(contextMenuItems)
// VFB Context menu callback
renderer.on('vfbContextMenuSelected', function (command, x, y) {
    switch(command){
        case 0:
            console.log("Custom option clicked")
            break
        case 1:
            console.log("This is disabled")
            break
        case 2:
            console.log("Value of Custom checkbox is", renderer.getVFBContextMenuItemValue(command))
            // Note that the value will not change automatically, you must change it yourself
            break
        case 3:
            value = renderer.getVFBContextMenuItemValue(command)
            renderer.setVFBContextMenuItemValue(command, 1 - value)
            console.log("Value of Custom checkbox 2 changed from", value, "to", 1 - value)
            break
        default:
            console.log('Command', command, 'not implemented')
    }
})

Light Mix and Transfer to scene

Here is an example showing how to setup Light Mix, and how to use the transfer to scene callback.

Tabs Container
directionhorizontal
Tabs Page
titlePython
Code Block
languagepy
firstline1
# Compatibility with Python 2.7.
from __future__ import print_function

# The directory containing the vray shared object should be present in the PYTHONPATH environment variable.
# Try to import the vray module from VRAY_SDK/python, if it is not in PYTHONPATH
import sys, os
VRAY_SDK = os.environ.get('VRAY_SDK')
if VRAY_SDK:
    sys.path.append(os.path.join(VRAY_SDK, 'python'))
import vray
import threading

SCENE_PATH = os.path.join(os.environ.get('VRAY_SDK'), 'scenes')
# Change process working directory to SCENE_PATH in order to be able to load relative scene resources.
os.chdir(SCENE_PATH)
# An event used for waiting on the callback
event = threading.Event()

# Create an instance of VRayRenderer.
# The renderer is automatically closed after the `with` block.
with vray.VRayRenderer() as renderer:
    # Usually it's a good idea to have a log callback handler, but we will not add one for this example.
    # Load scene from a file.
    renderer.load(os.path.join(SCENE_PATH, 'cornell_new.vrscene'))
    # Add the LightMix plugin. No need to keep the reference, because you can't do anything with this plugin.
    # It just has to exist in the scene.
    renderer.classes.RenderChannelLightMix()
    # Environment light select
    ls_env = renderer.classes.RenderChannelLightSelect('LSEnvironment')
    ls_env.light_select_mode = 10  # 10 is a special, undocumented value used for environment light
    ls_env.name = 'Environment'
    # Self illumination light select
    ls_self = renderer.classes.RenderChannelLightSelect('LSSelfIllumination')
    ls_self.light_select_mode = 11  # 11 is a special, undocumented value used for self illumination light
    ls_self.name = 'Self Illum.'
    # A full light light select
    ls_light = renderer.classes.RenderChannelLightSelect('LSCeilingLight')
    ls_light.light_select_mode = 4  # full light (direct + indirect)
    ls_light.name = 'Ceiling Light'
    # Adding a light to a light select
    light_rect = renderer.plugins['VRayLightRectShape1']
    light_rect.channels_full = [ ls_light ]
    def lightMixTransfer(r, changes, instant):
        # Each LightMixChange object contains:
        #    - the render element plugin
        #    - isApplied flag (bool) - This must be set by the user and it will reset the change in the VFB
        #    - enabled flag (bool) - Whether the light select is enabled or not in the VFB. This is *not* reset even when isApplied is true.
        #    - intensity multiplier (float)
        #    - color multiplier (VRay::Color)
        for change in changes:
            if change['plugin']:
                print('\t[{}]: mult: {:.2f}, \t{}'.format(change['plugin'].name, change['intensityMult'], change['colorMult']))
                if change['plugin'].getName() == 'LSCeilingLight':
                    # Apply the change to the actual light plugin and mark it as applied, so it will be reset in the VFB.
                    # Note: You will need to keep track of which lights are in which light select render elements.
                    light_rect = r.plugins['VRayLightRectShape1']
                    # Don't forget the changes are multipliers, not overrides.
                    light_rect.color *= change['colorMult']
                    light_rect.intensity *= change['intensityMult']
                    # Mark this change as applied.
                    change['isApplied'] = True
            else:
                # The plugin being empty, means that it's the special "Rest" channel.
                # It contains all the lights that were not added in other light selects.
                print('\t[Rest]: mult: {:.2f}, \t{}'.format(change['intensityMult'], change['colorMult']))
        # Save the image with the corrections applied.
        r.vfb.saveImage('lightmix_vfb.png', {'singleChannel':True, 'applyColorCorrections':True})
        # Notify the main thread that the callback is done.
        event.set()
    # Set the callback
    renderer.setOnLightMixTransferToScene(lightMixTransfer)

    # Avoid getting stuck if VFB is closed
    def vfbClosed(r, _):
        r.stop()
        event.set()
    renderer.setOnVFBClosed(vfbClosed)

    # Start rendering
    renderer.startSync()
    print('Choose Source: LightMix from the layers panel and change the color and intensity of the lights.\n')
    print('Please note, that those are multipliers, not overrides.\n')
    print('When you are done, stop the rendering (if it hasn\'t completed) from the VFB button')
    print('and press the "To Scene" button. This will call the callback function.\n')
    print('Note: The LC pass must end, before the Light Select render elements take effect.\n')
    # Wait for the callback to be executed
    event.wait()
    # Start rendering again, this time with some of the changes applied to the lights in the scene
    renderer.startSync()
    renderer.vfb.shown=1
    print("\nNow, some of the changes are applied to the scene and reset in the LightMix layer.")
    print("The rendered image should look the same.")
    # Wait for rendering to end.
    renderer.waitForRenderEnd()
    # Save the new image.
    renderer.vfb.saveImage('lightmix_scene.png', {'singleChannel':True, 'applyColorCorrections':True})
Tabs Page
titleC++
Code Block
languagecpp
#define VRAY_RUNTIME_LOAD_PRIMARY
#include <condition_variable>
#include "vraysdk.hpp"
#include "vrayplugins.hpp"
#include "utils.h"

using namespace VRay;
using namespace VRay::Plugins;
using namespace std;

const char *BASE_PATH = getenv("VRAY_SDK");
string SCENE_PATH = (BASE_PATH ? string(BASE_PATH) : string(".")) + PATH_DELIMITER + "scenes";
mutex m;
condition_variable cv;

// The transfer to scene callback function.
int onTransferToScene(VRayRenderer& r, const vector<LightMixChange>& changes, double instant, void*) {
	// Save the image with the corrections applied.
	ImageWriterOptions iwo;
	iwo.flags.singleChannel = true;
	iwo.flags.applyColorCorrections = true;
	r.vfb.saveImage("lightmix_vfb.png", iwo);
	printf("Transfer to scene callback called:");
	for (auto& change : changes) {
		// The LightMixChange object contains:
		//    - the render element plugin
		//    - isApplied flag (bool) - This must be set by the user and it will reset the change in the VFB
		//    - enabled flag (bool) - Whether the light select is enabled or not in the VFB. This is *not* reset even when isApplied is true.
		//    - intensity multiplier (float)
		//    - color multiplier (VRay::Color)
		if (change.plugin.isNotEmpty()) {
			printf("\t[%s]: mult: %f.2,\t%s\n", change.plugin.getName(), change.intensityMult, change.colorMult.toString().c_str());
			if (!strcmp(change.plugin.getName(), "LSCeilingLight")) {
				// Apply the change to the actual light plugin and mark it as applied, so it will be reset in the VFB.
				// Note: You will need to keep track of which lights are in which light select render elements.
				LightRectangle light_rect = r.getPlugin<LightRectangle>("VRayLightRectShape1");
				// Don't forget the changes are multipliers, not overrides.
				light_rect.set_color(light_rect.get_color() * AColor(change.colorMult));
				light_rect.set_intensity(light_rect.get_intensity() * change.intensityMult);
				// Mark this change as applied.
				change.isApplied = true;
			}
		}
		// The plugin being empty, means that it's the special "Rest" channel.
		// It contains all the lights that were not added in other light selects.
		else
			printf("\t[Rest]\n");
	}
	// Notify the main thread that the callback is complete.
	cv.notify_all();
	return 0;
}

// On VFB closed callback function.
void onVfbClosed(VRayRenderer& r, double instant, void*) {
	r.stop();
	cv.notify_all();
}

int main() {
	// Change process working directory to SCENE_PATH in order to be able to load relative scene resources.
	changeCurrentDir(SCENE_PATH.c_str());
	VRayInit init(NULL, true);
	VRayRenderer renderer;
	// It's recommended to always have a console log, but we will not set it for this example
	// Set the transfer to scene callback. Called when the "To Scene" button is pressed in the VFB
	renderer.setOnLightMixTransferToScene(onTransferToScene);
	// Avoid getting stuck if VFB is closed
	renderer.setOnVFBClosed(onVfbClosed);
	// Load a scene from file.
	renderer.load("cornell_new.vrscene");
	// Add the LightMix plugin. No need to keep the reference, because you can't do anything with this plugin.
	// It just has to exist in the scene.
	renderer.newPlugin<RenderChannelLightMix>();
	// Environment light select
	RenderChannelLightSelect ls_env = renderer.newPlugin<RenderChannelLightSelect>("LSEnvironment");
	ls_env.set_light_select_mode(10); // 10 is a special, undocumented value used for environment light
	ls_env.set_name("Environment");
	// Self illumination light select
	RenderChannelLightSelect ls_self = renderer.newPlugin<RenderChannelLightSelect>("LSSelfIllumination");
	ls_self.set_light_select_mode(11); // 11 is a special, undocumented value used for self illumination light
	ls_self.set_name("Self Illum.");
	// A full light light select
	RenderChannelLightSelect ls_light = renderer.newPlugin<RenderChannelLightSelect>("LSCeilingLight");
	ls_light.set_light_select_mode(4); // full light (direct + indirect)
	ls_light.set_name("Celiling Light");
	// Adding a light to a light select
	LightRectangle light_rect = renderer.getPlugin<LightRectangle>("VRayLightRectShape1");
	light_rect.set_channels_full({ Value(ls_light) });
	// Start rendering
	renderer.startSync();
	printf("Choose Source: LightMix from the layers panel and change the color and intensity of the lights.\n\n");
	printf("Please note, that those are multipliers, not overrides.\n\n");
	printf("When you are done, stop the rendering (if it hasn't completed) from the VFB button\n");
	printf("and press the \"To Scene\" button. This will call the callback function.\n\n");
	printf("Note: The LC pass must end, before the Light Select render elements take effect.\n");
	// Wait for the callback to complete.
	// This can only happen after the rendering is stopped, because the button is disabled while rendering.
	{
		unique_lock<mutex> lk(m);
		cv.wait(lk);
	}
	printf("\nNow, some of the changes are applied to the scene and reset in the LightMix layer.\n");
	printf("The rendered image should look the same.\n");
	// Render again, this time with the lights changed in the scene.
	renderer.startSync();
	renderer.vfb.show(true);
	renderer.waitForRenderEnd();
	// Save the image with the corrections applied.
	ImageWriterOptions iwo;
	iwo.flags.singleChannel = true;
	iwo.flags.applyColorCorrections = true;
	renderer.vfb.saveImage("lightmix_scene.png", iwo);

	return 0;
}
Tabs Page
titleC#.NET
Code Block
languagec#
using System;
using System.IO;
using System.Threading;
using System.Collections.Generic;
using VRay;
using VRay.Plugins;

namespace _09_lightmix
{
	class Program
	{
		static void Main(string[] args)
		{
			AutoResetEvent autoResetEvent = new AutoResetEvent(false);
			string SCENE_PATH = Path.Combine(Environment.GetEnvironmentVariable("VRAY_SDK"), "scenes");
			// Change process working directory to SCENE_PATH in order to be able to load relative scene resources.
			Directory.SetCurrentDirectory(SCENE_PATH);
			// Create an instance of VRayRenderer with default options. The renderer is automatically closed after the `using` block.
			using (VRayRenderer renderer = new VRayRenderer())
			{
				// It's usually a good idea to have a listener for any type of log message, but we will not add one for this example.
				ImageWriterOptions iwo = new ImageWriterOptions();
				iwo.SingleChannel = true;
				iwo.ApplyColorCorrections = true;
				// Avoid getting stuck if VFB is closed
				renderer.VFBClosed += new EventHandler<VRayEventArgs>((source, e) =>
				{
					renderer.Stop();
					autoResetEvent.Set();
				});
				renderer.LightMixTransferToScene += new EventHandler<LightMixTransferToSceneEventArgs>((source, e) =>
				{
					// Save the image with the corrections applied.
					renderer.Vfb.SaveImage("lightmix_vfb.png", iwo);
					Console.WriteLine("Transfer to scene callback called:");
					foreach (var change in e.Changes)
					{
						// The LightMixChange object contains:
						//    - The render element plugin
						//    - IsApplied flag (bool) - This must be set by the user and it will reset the change in the VFB
						//    - Enabled flag (bool) - Whether the light select is enabled or not in the VFB. This is *not* reset even when isApplied is true.
						//    - Intensity multiplier (float)
						//    - Color multiplier (VRay::Color)
						if (change.Plugin != null)
						{
							Console.WriteLine(String.Format("\t[{0}]: mult: {1:F2},\t{2}", change.Plugin.GetName(), change.IntensityMult, change.ColorMult.ToString()));
							if (change.Plugin.GetName() == "LSCeilingLight")
							{
								// Apply the change to the actual light plugin and mark it as applied, so it will be reset in the VFB.
								// Note: You will need to keep track of which lights are in which light select render elements.
								LightRectangle lightRect = renderer.GetPlugin<LightRectangle>("VRayLightRectShape1");
								// Don't forget the changes are multipliers, not overrides.
								lightRect.Color = lightRect.Color * new AColor(change.ColorMult, 1);
								lightRect.Intensity = lightRect.Intensity * change.IntensityMult;
								// Mark this change as applied.
								change.IsApplied = true;
							}
						}
						// The plugin being empty, means that it's the special "Rest" channel.
						// It contains all the lights that were not added in other light selects.
						else
							Console.WriteLine("\t[Rest]\n");
					}
					// Notify the main thread that the callback is complete.
					autoResetEvent.Set();
				});
				// Load scene from a file.
				renderer.Load("cornell_new.vrscene");
				// Add the LightMix plugin. No need to keep the reference, because you can't do anything with this plugin.
				// It just has to exist in the scene.
				renderer.NewPlugin<RenderChannelLightMix>();
				// Environment light select
				RenderChannelLightSelect ls_env = renderer.NewPlugin<RenderChannelLightSelect>("LSEnvironment");
				ls_env.LightSelectMode = 10; // 10 is a special, undocumented value used for environment light
				ls_env.SetName("Environment");
				// Self illumination light select
				RenderChannelLightSelect ls_self = renderer.NewPlugin<RenderChannelLightSelect>("LSSelfIllumination");
				ls_self.LightSelectMode = 11; // 11 is a special, undocumented value used for self illumination light
				ls_self.SetName("Self Illum.");
				// A full light light select
				RenderChannelLightSelect ls_light = renderer.NewPlugin<RenderChannelLightSelect>("LSCeilingLight");
				ls_light.LightSelectMode = 4; // full light (direct + indirect)
				ls_light.SetName("Celiling Light");
				// Adding a light to a light select
				LightRectangle light_rect = renderer.GetPlugin<LightRectangle>("VRayLightRectShape1");
				light_rect.ChannelsFull = new List<object>() { ls_light };
				// Start rendering.
				renderer.StartSync();
				Console.WriteLine("Choose Source: LightMix from the layers panel and change the color and intensity of the lights.\n");
				Console.WriteLine("Please note, that those are multipliers, not overrides.\n");
				Console.WriteLine("When you are done, stop the rendering (if it hasn't completed) from the VFB button");
				Console.WriteLine("and press the \"To Scene\" button. This will call the callback function.\n");
				Console.WriteLine("Note: The LC pass must end, before the Light Select render elements take effect.\n");
				// Wait for the callback to complete.
				// This can only happen after the rendering is stopped, because the button is disabled while rendering.
				autoResetEvent.WaitOne();
				Console.WriteLine("\nNow, some of the changes are applied to the scene and reset in the LightMix layer.");
				Console.WriteLine("The rendered image should look the same.");
				// Render again, this time with the lights changed in the scene.
				renderer.StartSync();
				renderer.Vfb.Shown = true;
				renderer.WaitForRenderEnd();
				renderer.Vfb.SaveImage("lightmix_scene.png", iwo);
			}
		}
	}
}
Tabs Page
titleNode.js
Code Block
languagejs
var path = require('path');
var vray = require(path.join(process.env.VRAY_SDK, 'node', 'vray'));

var SCENE_PATH = path.join(process.env.VRAY_SDK, 'scenes');
// Change process working directory to SCENE_PATH in order to be able to load relative scene resources.
process.chdir(SCENE_PATH);

// Create an instance of VRayRenderer.
var renderer = vray.VRayRenderer();
// It's recommended to always have a console log callback but we will not add one for this example.

// Close the renderer when VFB is closed.
renderer.on("vfbClosed", function(instant) {
	// This call is mandatory in order to free up the event loop.
	// The renderer object is unusable after closing since its resources
	// are freed. It should be released for garbage collection.
	renderer.close();
});

renderer.on("lightMixTransferToScene", function(changes, count) {
	// Each LightMixChange object contains:
	//    - the render element plugin
	//    - isApplied flag (bool) - This must be set by the user and it will reset the change in the VFB
	//    - enabled flag (bool) - Whether the light select is enabled or not in the VFB. This is *not* reset even when isApplied is true.
	//    - intensity multiplier (float)
	//    - color multiplier (VRay::Color)
	changes.forEach(change => {
		if (change.plugin != null) {
			console.log(`\t[${change.plugin.name}]: mult: ${change.intensityMult.toFixed(2)}, \t${change.colorMult}`);
			if (change.plugin.getName() == "LSCeilingLight") {
				// Apply the change to the actual light plugin and mark it as applied, so it will be reset in the VFB.
				// Note: You will need to keep track of which lights are in which light select render elements.
				light_rect = renderer.plugins["VRayLightRectShape1"];
				// Don't forget the changes are multipliers, not overrides.
				light_rect.color = light_rect.color.mul(vray.AColor(change.colorMult));
				light_rect.intensity *= change.intensityMult;
				// Mark this change as applied.
				change.isApplied = true;
			}
		}
		else {
			// The plugin being empty, means that it's the special "Rest" channel.
			// It contains all the lights that were not added in other light selects.
			console.log(`\t[Rest]: mult: ${change.intensityMult.toFixed(2)}, \t${change.colorMult}`);
		}
	});
	// Save the image with the corrections applied.
	renderer.vfb.saveImageSync("lightmix_vfb.png", {singleChannel: true, applyColorCorrections: true});
	// Render again, this time with the lights changed in the scene.
	setTimeout(afterCallback, 0);
});

// Load scene from a file asynchronously.
renderer.load("cornell_new.vrscene", function(err) {
	if (err) { throw err; } // Scene was not loaded.
	// Add the LightMix plugin. No need to keep the reference, because you can't do anything with this plugin.
	// It just has to exist in the scene.
	renderer.classes.RenderChannelLightMix();
	// Environment light select
	ls_env = renderer.classes.RenderChannelLightSelect("LSEnvironment");
	ls_env.light_select_mode = 10; // 10 is a special, undocumented value used for environment light
	ls_env.name = "Environment";
	// Self illumination light select
	ls_self = renderer.classes.RenderChannelLightSelect("LSSelfIllumination");
	ls_self.light_select_mode = 11; // 11 is a special, undocumented value used for self illumination light
	ls_self.name = "Self Illum.";
	// A full light light select
	ls_light = renderer.classes.RenderChannelLightSelect("LSCeilingLight");
	ls_light.light_select_mode = 4; // full light (direct + indirect)
	ls_light.name = "Ceiling Light";
	// Adding a light to a light select
	light_rect = renderer.plugins["VRayLightRectShape1"]
	light_rect.channels_full = [ ls_light ];
	// Start rendering.
	renderer.start(function(err) {
		if (err) { throw err; } // Couldn't start rendering.
		console.log("Choose Source: LightMix from the layers panel and change the color and intensity of the lights.\n");
		console.log("Please note, that those are multipliers, not overrides.\n");
		console.log("When you are done, stop the rendering (if it hasn't completed) from the VFB button");
		console.log("and press the \"To Scene\" button. This will call the callback function.\n");
		console.log("Note: The LC pass must end, before the Light Select render elements take effect.\n");
	});
});

function afterCallback() {
	renderer.start(function(err) {
		if (err) { throw err; } // Couldn't start rendering.
		console.log("\nNow, some of the changes are applied to the scene and reset in the LightMix layer.");
		console.log("The rendered image should look the same.");
		renderer.waitForRenderEnd(function() {
			// Save the new image.
			renderer.vfb.saveImageSync("lightmix_scene.png", {singleChannel: true, applyColorCorrections: true});
			// Close the renderer.
			renderer.close();
		});
	});
}

Other callbacks

Here are example usages of the other VFB related callbacks that the VRayRenderer offers:

Tabs Container
directionhorizontal
Tabs Page
titlePython
Code Block
languagepy
firstline1
def onRenderLast(renderer, isRendering, instant):
    print('Starting rendering at:', instant)
    renderer.startSync()

def onRenderInteractive(renderer, isRendering, instant):
    print('Starting Interactive rendering at:', instant)
    oldRenderMode = renderer.renderMode
    renderer.renderMode = 'interactive'
    renderer.startSync()
    renderer.renderMode = oldRenderMode # resetting the renderMode after the rendering has started will not affect the current rendering process

def onShowVFBLog(renderer, instant):
    renderer.vfb.logMessage(vray.LOGLEVEL_INFO, 'VFB Log opened')

def onVFBClosed(renderer, instant):
    renderer.stop()

# called when the Render button or menu action is pressed. If not set, pressing Render will start rendering (like calling renderer.start())
renderer.setOnVFBRenderLast(onRenderLast) 
# called when the Start Interactive Render button or menu action is pressed. Requires showVfbButtonInteractiveStart to be True
renderer.setOnVFBRenderInteractive(onRenderInteractive) 
# called when the VFB Log tab is opened
renderer.setOnVFBShowMessagesWindow(onShowVFBLog)
# called when the VFB window is closed
renderer.setOnVFBClosed(onVFBClosed)
Tabs Page
titleC++
Code Block
languagecpp
#define VRAY_RUNTIME_LOAD_PRIMARY
#include "vraysdk.hpp"
#include "utils.h"
using namespace VRay;
using namespace std;

const char *BASE_PATH = getenv("VRAY_SDK");
string SCENE_PATH = (BASE_PATH ? string(BASE_PATH) : string(".")) + PATH_DELIMITER + "scenes";

void onRenderLast(VRayRenderer& renderer, bool isRendering, double instant, void* userData) {
	printf("Starting rendering at: %f\n", instant);
	renderer.startSync();
}
void onRenderInteractive(VRayRenderer& renderer, bool isRendering, double instant, void* userData) {
	printf("Starting Interactive rendering at: %f\n", instant);
	VRayRenderer::RenderMode oldRenderMode = renderer.getRenderMode();
	renderer.setRenderMode(VRayRenderer::RENDER_MODE_INTERACTIVE);
	renderer.startSync();
	renderer.setRenderMode(oldRenderMode); // resetting the renderMode after the rendering has started will not affect the current rendering process
}
void onShowVFBLog(VRayRenderer& renderer, double instant, void* userData) {
	renderer.vfb.logMessage(MessageInfo, "VFB Log opened");
}
void onVFBClosed(VRayRenderer& renderer, double instant, void* userData) {
	renderer.stop();
}

int main() {
	// Change process working directory to SCENE_PATH in order to be able to load relative scene resources.
	changeCurrentDir(SCENE_PATH.c_str());
	// Load V-Ray SDK library.
	VRayInit init(NULL, true);
	// The renderer is automatically closed at the end of the current scope.
	VRayRenderer renderer;
	// called when the Render button or menu action is pressed. If not set, pressing Render will start rendering (like calling renderer.start())
	renderer.setOnVFBRenderLast(onRenderLast);
	// called when the Start Interactive Render button or menu action is pressed. Requires showVfbButtonInteractiveStart to be true
	renderer.setOnVFBInteractiveStart(onRenderInteractive);
	// called when the VFB Log tab is opened
	renderer.setOnVFBShowMessagesWindow(onShowVFBLog);
	// called when the VFB window is closed
	renderer.setOnVFBClosed(onVFBClosed);
	// Load scene from a file.
	renderer.load("cornell_new.vrscene");
	// Start rendering.
	renderer.startSync();
	// Wait until rendering has finished.
	renderer.waitForRenderEnd();
	return 0;
}
Tabs Page
titleC#.NET
Code Block
languagec#
using System;
using System.IO;
using VRay;

namespace _other_vfb_callbacks
{
	class Program
	{
		static void Main(string[] args)
		{
			string SCENE_PATH = Path.Combine(Environment.GetEnvironmentVariable("VRAY_SDK"), "scenes");
			// Change process working directory to SCENE_PATH in order to be able to load relative scene resources.
			Directory.SetCurrentDirectory(SCENE_PATH);
			// Create an instance of VRayRenderer with default options. The renderer is automatically closed after the `using` block.
			using (VRayRenderer renderer = new VRayRenderer())
			{
				// called when the Render button or menu action is pressed. If not set, pressing Render will start rendering (like calling renderer.Start())
				renderer.VFBRenderLast += new EventHandler<RenderLastEventArgs>((source, e) =>
				{
					Console.WriteLine("Starting rendering at: {0}", e.Instant);
					renderer.StartSync();
				});
				// called when the Start Interactive Render button or menu action is pressed. Requires ShowVfbButtonInteractiveStart to be true
				renderer.VFBRenderInteractive += new EventHandler<RenderInteractiveEventArgs>((source, e) =>
				{
					Console.WriteLine("Starting Interactive rendering at: {0}", e.Instant);
					RenderMode oldRenderMode = renderer.RenderMode;
					renderer.RenderMode = RenderMode.INTERACTIVE;
					renderer.StartSync();
					renderer.RenderMode = oldRenderMode; // resetting the RenderMode after the rendering has started will not affect the current rendering process
				});
				// called when the VFB Log tab is opened
				renderer.VFBShowMessagesWindow += new EventHandler<VRayEventArgs>((source, e) =>
				{
					renderer.Vfb.LogMessage(LogLevelType.Info, "VFB Log opened");
				});
				// called when the VFB window is closed
				renderer.VFBClosed += new EventHandler<VRayEventArgs>((source, e) =>
				{
					renderer.Stop();
				});
				// Load scene from a file.
				renderer.Load("cornell_new.vrscene");
				// Start rendering.
				renderer.StartSync();
				// Wait until rendering has finished.
				renderer.WaitForRenderEnd();
			}
		}
	}
}
Tabs Page
titleNode.js
Code Block
languagejs
 // called when the Render button or menu action is pressed. If not set, pressing Render will start rendering (like calling renderer.start())
renderer.on("vfbRenderLast", function(isRendering, instant) {
	console.log("Starting rendering at: ", instant);
	renderer.startSync();
});
// called when the Start Interactive Render button or menu action is pressed. Requires showVfbButtonInteractiveStart to be true
renderer.on("vfbRenderInteractive", function(isRendering, instant) {
	console.log("Starting Interactive rendering at:", instant);
	var oldRenderMode = renderer.renderMode;
	renderer.renderMode = "interactive";
	renderer.startSync();
	renderer.renderMode = oldRenderMode; // resetting the renderMode after the rendering has started will not affect the current rendering process
});
// called when the VFB Log tab is opened
renderer.on("vfbShowMessagesWindow", function(instant) {
	renderer.vfb.logMessage(vray.LOGLEVEL_INFO, "VFB Log opened");
});
// called when the VFB window is closed
renderer.on("vfbClosed", function(instant) {
	renderer.stop();
	// Closes the renderer. This call is mandatory in order to free up the event loop.
	// The renderer object is unusable after closing since its resources are freed. 
	// It should be released for garbage collection.
	renderer.close();
});

RendererOptions

The VRayRenderer class has an options member which can be passed to its constructor. It's a struct in C++ and .Net and in Python and Node.js it is a dictionary. These options are immutable and can't be changed after the renderer is constructed. They are mostly related to the VFB so they are listed here:

Fancy Bullets
  • enableFrameBuffer - (default: true) Controls whether the VFB will be used by this renderer. Notice that this is different from the global enableFrameBuffer function that disables the V-Ray GUI for the whole life of the process.

  • showFrameBuffer - (default: true) Controls whether the VFB is shown when rendering starts. It can still be shown later through the VFB API.

  • noRenderLicensePreCheck - (default: false) - By default creating a V-Ray renderer engages an AppSDK license and also very briefly engages a render license and releases it in order to be able to return a license error early. You can disable this pre-check with this flag for example to reduce network communication.

  • useDefaultVfbTheme - (default: true) If set to false the VFB theme is ignored and the parent application theme is inherited.

  • showVfbButtonInteractiveStart -(default: false) - Show an additional Start Interactive Rendering button and menu action. When pressed, calls a user callback (does not start rendering by default).
  • previewRenderer - (default: false) Optimize the renderer for small preview purposes. Should not be used for production.
  • allowInvalidCharactersInPluginNames - (default: false) - Allow the use of invalid characters in plugin names.

  • dockFrameBuffer- (default: false) - Dock the VFB window
  • hideToSceneButton - (default: false) - Hide the Light Mix transfer <To Scene> button in VFB. If you don't plan on implementing that functionality, it's a good idea to hide the button (otherwise it will always be disabled).
  • useVfbLog - (default: true) - Use the built-in VFB log
  • pluginLibraryPath - This can be used optionally to define a non-default path for loading V-Ray plugins. Most users won't need to set this. It allows multiple files to be specified.

  • vfbDrawStyle - This enum controls the style and colors of the VFB GUI. The available styles are those of the V-Ray Standalone product as well as V-Ray for 3dsMax and V-Ray for Maya

    .