Issue Programmatically Saving "Raytraced" (Cycles) Renderings

Hello All,

When attempting to render and save in the “Raytraced” (Cycles) mode, the image is written to disk prior to any passes being generated. I’ve researched this for several hours and tried a number of approaches, to no avail.

How does one save the image only after a specified number of passes have completed? (I don’t necessarily have to set the number of passes in the script- using the number of passes specified in Cycles preferences would be acceptable.)

Any help would be greatly appreciated. Thanks.


import Rhino as rc
from   scriptcontext import doc

def SaveRaytracedRender():

  desc = rc.Display.DisplayModeDescription.FindByName("Raytraced")
  desc.DisplayAttributes.RealtimeRenderPasses = 50

  view = doc.Views.ActiveView
  view.ActiveViewport.DisplayMode = desc

  doc.Views.Redraw()

  fullpath = "C:\Users\user\Desktop\raytraced 1.png"
  capture = rc.Display.RhinoView.CaptureToBitmap( view, desc )
  capture.Save( fullpath );

if __name__ == "__main__":
    SaveRaytracedRender()

raytraced_test_file.3dm (1.2 MB)

Hi,
Monday morning- bumping this. Can a dev please reproduce this issue?
Thanks!

Why not just script the _-ViewCaptureToFile command, using Rhino.RhinoApp.RunScript. The command line version allows you to specify the number of passes.

– Dale

Hi Dale,

Thank you very much. Your approach worked. I am new to Rhino (though not to 3d APIs in general) and was not aware of the existence of that command.

Here a script that does a capture using the ViewCapture script. Use this method if you don’t want to use the dashed command version.

# Material switcher
# and Raytraced viewcapturing

import scriptcontext as sc
import Rhino.Render as rr
import Rhino as r
import Rhino.DocObjects as rdob

import System

av = sc.doc.Views.ActiveView

cycles = sc.doc.Views.ActiveView.RealtimeDisplayMode
oldpasses = cycles.MaxPasses
cycles.MaxPasses = 2

def capture_viewport(name):
	cycles.Paused = True
	view_capture = r.Display.ViewCapture()
	view_capture.Width = av.ActiveViewport.Size.Width
	view_capture.Height = av.ActiveViewport.Size.Height
	view_capture.ScaleScreenItems = False
	view_capture.DrawAxes = False
	view_capture.DrawGrid = False
	view_capture.DrawGridAxes = False
	view_capture.TransparentBackground = False
	view_capture.RealtimeRenderPasses = 10
	bitmap = view_capture.CaptureToBitmap(av)
	if bitmap:
		folder = System.Environment.SpecialFolder.Desktop
		path = System.Environment.GetFolderPath(folder)
		filename = System.IO.Path.Combine(path, name + "_raytraced_capture.png")
		print("saving ", filename)
		bitmap.Save(filename, System.Drawing.Imaging.ImageFormat.Png)

selobs = [ob for ob in sc.doc.Objects if ob.IsSelected(False)>0]

if len(selobs) > 0:

	showroom_materials = [rm for rm in sc.doc.RenderMaterials if rm.Tags and rm.Tags.find("ShowRoom")>-1]
	
	for rm in showroom_materials:	
		for ob in selobs:
			ob.RenderMaterial = rm
			ob.CommitChanges()
			sc.doc.Views.Redraw()
		print("capturing with ", rm.Name)
		capture_viewport(rm.Name)
else:
	print("no capturing today")

cycles.MaxPasses = oldpasses
cycles.Paused = False

To see this particular script in action you need a 3dm file with one or more materials that have the tag Showroom. Each material should have a good name. Select an object in your model, then run this script. It will create captures, one for each material on the selected object(s).

Nathan,
I probably won’t have a chance to test this today, but thank you as well. You are correct that I’m trying to stay disciplined and only use dashed commands when there’s no other option.

Would it be possible to add something like

view_capture.EnablePostEffects = True

to have denoising turned on for the capture?

This should work in the latest Service Release Candidate without having to set anything else than what you 've already set for the viewport.

brilliant!