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 Abort rendering – Stops the current rendering. Render – Starts rendering. If the | |
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; 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; Zoom VFB – Zooms in/out the rendered image in the VFB. Zoom 50% – Zooms out to 50%; Channels – Chooses which channels to see. View red channel – Displays the red channel; Color clamping – Opens the color clamping submenu options: Force color clamping – Forces color clamping; 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. | |
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; | ||
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; 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:
Command | Description |
---|---|
Reset | Resets all changes done to the selected layer. |
Save | Saves the layer as a preset. |
Load | Loads a preset for the selected layer. |
Delete | Deletes the selected layer. |
Save all CCs as LUT | Bakes all the color corrections to a LUT file. |
New Layer | Creates a new layer. |
Duplicate | Duplicates the selected layer. |
Blend Modes | Specifies 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:
Mouse | Description |
---|---|
Mouse wheel | Zoom in/Zoom out |
Double-click left button | Zoom to 100% |
Middle button dragging | Pan (hand tool) |
Ctrl+Shift+Left click | Zoom in the rendered image |
Ctrl+Shift+Right click | Zoom out the rendered image |
Keyboard | Description |
Ctrl+Shift+left click, + / = | Zoom in |
Ctrl+Shift+right click, -/_ | Zoom out |
Double click, * | Zoom to 100% |
Arrow keys | Pan left, up, right, down |
F | Fit region or whole image in the VFB |
Esc | Abort render |
Q | Set history A/B vertical compare mode |
W | Set history A/B horizontal compare mode |
E | Enable history A/B/C/D compare mode |
1-9 | Load the respective image from the VFB history |
H | Show/hide history |
Ctrl+L | Show/hide whole right panel |
P | Show/hide only layers tree |
L | Locks 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 scroll | Change camera FoV, effectively zooming in/out |
Shift & drag with left mouse button | Orbit the camera around the scene |
Ctrl & drag with left mouse button | Pan 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 globalenableFrameBuffer
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 windowhideToSceneButton
- (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 logpluginLibraryPath
- 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.