©Anton Podvalny

Table of Contents

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


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

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 settings – Opens the VFB Settings window where you can adjusts settings for Render View, Render Region, History and Layers.

VFB Toolbar



This dropdown gives access to render elements rendered for the scene. The selected render element is displayed in the VFB. By default, the RGB color and Alpha render elements are available. Any additional render elements that have been added to the scene also appear in the drop-down.

Displays the coordinates of the mouse pointer.

Specifies the sampled area size. Click on the arrow to open a context menu with the available sampled area sizes: 1x1, 3x3, 5x5, and 7x7.

Specifies whether color and display corrections are applied (RGB) or not (Raw) when showing the sampled pixel values at the current mouse pointer position.

Displays the RGB pixel values at the current mouse pointer position before applying any color corrections.

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.

Displays the Hue, Saturation and Value of the pixel under the current mouse position when HSV is selected.

Displays the HEX of the pixel under the current mouse position when Web is selected.

Displays the 8bit color palette of the pixel under the current mouse position when 8bit is selected.

Locks the mouse pointer coordinates and displays information for the selected pixel.

Shows corrected colors.

Shows the V-Ray log.

Displays the Alpha channel.

Displays the red channel.

Displays the green channel.

Displays the blue channel.

Saves the image to disk. Press and hold the icon to bring up the submenu:

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.

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

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. With this option enabled, you can right-click on the image and select Lock bucket starting point to lock the bucket (or sampling) starting point.

Allows you to render regions in the VFB. See the Render Region section for more information.

Starts IPR.

Stops the current rendering.

Starts rendering.



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.

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

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

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

Saves the current image from the VFB to the render history. The image is placed at the top of the render history list.

Loads the selected image from the render history to the VFB.

Removes the selected image from the render history.

A search field where you can filter the images based on the scene paths and notes.



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).

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.

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 () to the left of its name.

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


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.

Deletes the selected layer(s).

Saves a layer tree preset.

Loads a layer tree preset.

Quick access to custom layer presets. You must set the path to it in the VFB Settings.

Undo create layer.

Redo create layer.


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

CommandDescription
ResetResets all changes done to the selected layer.
SaveSaves the layer as a preset.
LoadLoads a preset for the selected layer.
DeleteDeletes the selected layer.
Save all CCs as LUTBakes all the color corrections to a LUT file.
New LayerCreates a new layer.
DuplicateDuplicates the selected layer.
Blend ModesSpecifies how the selected layer blends with the result from all layers below it.



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.

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



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:

MouseDescription
Mouse wheelZoom in/Zoom out
Double-click left buttonZoom to 100%
Middle button draggingPan (hand tool)
Ctrl+Shift+Left clickZoom in the rendered image
Ctrl+Shift+Right clickZoom out the rendered image


KeyboardDescription
Ctrl+Shift+left click, + / =Zoom in
Ctrl+Shift+right click, -/_Zoom out
Double click, *Zoom to 100%
Arrow keysPan left, up, right, down
FFit region or whole image in the VFB
EscAbort render
QSet history A/B vertical compare mode
WSet history A/B horizontal compare mode
EEnable history A/B/C/D compare mode
1-9Load the respective image from the VFB history
HShow/hide history
Ctrl+LShow/hide whole right panel
PShow/hide only layers tree
LLocks the mouse pointer coordinates and displays information for the selected pixel, i.e. activates the Lock pixel info coordinates button.


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:

Shift & mouse wheel scroll

Move the camera forward or backward

Ctrl & mouse wheel scrollChange camera FoV, effectively zooming in/out
Shift & drag with left mouse buttonOrbit the camera around the scene
Ctrl & drag with left mouse buttonPan the camera

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:


with vray.VRayRenderer(showFrameBuffer=False) as renderer:
RendererOptions options;
options.showFrameBuffer = false;
VRayRenderer renderer(options);
RendererOptions options = new RendererOptions();
options.ShowFrameBuffer = false;
 
using (VRayRenderer renderer = new VRayRenderer(options))
{
}



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):


with vray.VRayRenderer(enableFrameBuffer=False) as renderer:
RendererOptions options;
options.enableFrameBuffer = false;
VRayRenderer renderer(options);
RendererOptions options = new RendererOptions();
options.EnableFrameBuffer = false;
 
using (VRayRenderer renderer = new VRayRenderer(options))
{
}



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

The VFB class


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
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
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
}



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.

VFB Viewport Context Menu

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

# 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)
// 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);
}
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();
}



// 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.

# 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})
#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;
}
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);
			}
		}
	}
}
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:

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)
#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;
}
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();
			}
		}
	}
}
 // 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:

  • 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.
  • No labels
Was this helpful?