How to snapshot a Clone's output?

   678   6   2
User Avatar
Member
253 posts
Joined: 7月 2013
Offline
Currently I'm using a single cloned Houdini session, using clone panel, to render into the render gallery. Lets say I want to iterate some samples/denoise/filter options and want to do an A/B comparison.. how do I stash/duplicate the current clone output? (so I can compare to future output from the same clone)

I can fire up a new clone and stop the other one but that's a bit over the top.

And I'm probably missing some knowledge here, but is using a clone the only way to render into the gallery so it's not a nondeterministic snapshot of the viewport? (As in, be exactly as what would be written to disk on a render-to-disk run)

And I'm Still missing the 'render' button here.. I can lock/unlock a clone to sort of get the same effect. But just doing some updates and then pressing a render button to see the results in the gallery is still a bit of an enigma.

I'm paying my own energy bill here so, and for environmental reasons as well, I don't want my GPU flat out rendering every change I make for no good reason.
More code, less clicks.
User Avatar
Member
273 posts
Joined: 11月 2013
Offline
Jonathan de Blok
And I'm Still missing the 'render' button here
Is the 'Background' button (next to 'Snap') what you're looking for?
Edited by antc - 2024年1月30日 13:42:32
User Avatar
Member
12 posts
Joined: 6月 2018
Offline
antc
Jonathan de Blok
And I'm Still missing the 'render' button here
Is the 'Background' button (next to 'Snap') what you're looking for?

I really wish the label could be changed on that one. Perhaps simply "Render" would do. For a long time I figured it was for loading an image background or something..
User Avatar
スタッフ
451 posts
Joined: 6月 2020
Offline
We don't currently have a way to take a snapshot of a running clone (short of disconnecting the clone), but it's a request we've heard loud and clear
User Avatar
Member
253 posts
Joined: 7月 2013
Offline
Good to know clone snapshot is on the radar!

About the 'background' button. I too thought it was about backgrounds, pressing it and setting it to 'live render' shows this popup:


When increasing the limit to 2 it still pops up (do the clones count for this as well?). Increasing it higher leads to a 'Unable to find a Scene View pane to launch a render from' so I guess even when this works it's still linked to a viewport which is not really what I want, I want it locked to a camera.

I think the general issue is that everything is designed for a workflow where rendering and a viewport are tightly connected. Which can be nice but also really frustrating if you just want to tweak some things after which you want to update the render, doing it though a fixed camera with no relation what so ever to a viewport. Using a clone for this will at least disconnect it from any viewport and locks it to a camera, all that is missing a 'render' button to trigger manual updates.


(Btw, the clones only pickup the cameras that are in USD stage, not the ones floating in /obj level. I understand why and it makes sense from a technical point of view, but when using the Karma ROP the only cam that's available to the clones is the cam that is assigned to the ROP. Maybe just gathering all cameras in the stage might be an option for the Karma ROP?)

Anyways, I've made it myself. When running the code below in the python source editor (or put it in a shelf tool) it will add a 'Render' button to ll of the currently opened Clone Control Panels. Ctrl-Clicking will create a new set of snapshots in the gallery so you can compare it to previous renders. Normal clicking overwrites the clone's active snapshot. The older snaps are prefixed with the creation date in the label.

In the screenshot below you can see the added button at the top of the 'Clone Control Panel' and some older and current snapshots from the two clones. It's a bit hacky but all I could do with the currently exposed python bits.




import hou
from time import sleep, time
from datetime import datetime
from hutil.Qt import QtWidgets, QtCore


def render():
    new_snap= QtWidgets.QApplication.keyboardModifiers() == QtCore.Qt.ControlModifier
      
    for clone in hou.clone.clones():
        snapshots=clone.renderGalleryDataSource()
        if snapshots:
            if len([x for x in snapshots.itemIds() if snapshots.label(x) == clone.name()])==0: #check if there are active snapshots for the clone(s)
                new_snap=True
        
        #rename previous snapshot if new snapshot is requested
        if new_snap:
            if snapshots:
                for snap in snapshots.itemIds():
                
                    if snapshots.label(snap) == clone.name():
                        snap_date=datetime.fromtimestamp(snapshots.modificationDate(snap)).strftime("%m/%d/%Y, %H:%M:%S")
                        snapshots.setLabel(snap,f"{clone.name()} {snap_date}")
                        
                        #write membuf to disk and set as source for old thumbs
                        tmpfile=snapshots.generateItemFilePath( snap, "exr" )
                        f=hou.node("/img/comp1").createNode("file")
                        f.parm("filename1").set( snapshots.filePath(snap) )
                        f.saveImage(tmpfile)
                        f.destroy()
                        snapshots.setFilePath(snap,tmpfile)
      
        
        clone.setProcessUpdates(False)
        
        #touching a clone's LopNode will generate a new set of snapshots, touching camera path will only trigger an update
        if new_snap:
            tmp=clone.lopNode()
            clone.setLopNode(None)
        else:        
            tmp=clone.cameraPath()
            clone.setCameraPath(None)
        
        clone.setProcessUpdates(True)
        
        if new_snap:
            clone.setLopNode(tmp)
        else:
            clone.setCameraPath(tmp)
    
        #small delay required so clones can start rendering.        
        sleep(0.1)
        
        clone.setProcessUpdates(False)


#find open clone control tabs        
cc_tabs=[item  for item in hou.ui.paneTabs() if getattr(item, "activeInterface", False) and item.activeInterface().name()=="clone_control"]
uiscale = hou.ui.globalScaleFactor()

#shift table down and inset pushbutton
for cc in cc_tabs:

    root=cc.activeInterfaceRootWidget()
    root.layout().setContentsMargins(0, 35* uiscale, 0, 0);

    if not getattr(root, "but_render", False):
        root.but_render = QtWidgets.QPushButton(root)
        root.but_render.clicked.connect(render)
        root.but_render.setText('Render')
        root.but_render.setGeometry(5*uiscale, 5*uiscale, 100*uiscale, 24*uiscale) 
        root.but_render.show()
Edited by Jonathan de Blok - 2024年1月31日 13:10:48

Attachments:
houdini_BsTTZrsFb8.png (73.6 KB)
Screenshot 2024-01-31 145138.jpg (203.3 KB)

More code, less clicks.
User Avatar
スタッフ
451 posts
Joined: 6月 2020
Offline
Jonathan de Blok
When increasing the limit to 2 it still pops up (do the clones count for this as well?).

Yes, at present there is some shared identification mechanism between the clones and the background renders. This is what drives them both having the little film icon overlay in the top-left corner, and also what leads to them summing together when considering a maximum-active count. It's on our list to tease them apart a bit more.

Increasing it higher leads to a 'Unable to find a Scene View pane to launch a render from' so I guess even when this works it's still linked to a viewport which is not really what I want, I want it locked to a camera.

The background renders are linked to a viewport to the degree that the viewport is the mechanism by which they access the USD stage and information about the current camera (which may be an actual USD camera, or an arbitrary view).
User Avatar
Member
253 posts
Joined: 7月 2013
Offline
robp_sidefx
The background renders are linked to a viewport to the degree that the viewport is the mechanism by which they access the USD stage and information about the current camera (which may be an actual USD camera, or an arbitrary view).

Ahh that's why it works that way, that make a bit of sense. And with the clones you explicitly point them a lop node to tell it where to fetch the a USD stage and which cam to use etc for rendering. I guess technically the background-render and clones are the same thing in a different wrapper?

And I must say I've been using my shiny new 'render' button all day and it actually did instantly improve my workflow quite a lot, I can manually trigger a single render when I want or unlock the clones for live updates when required. Ideally for more control each clone could have it's own 'render' button in a table-column as well, then you can render a specific shot from one of the clones. I hope something like this, or something better, will eventually be there right out of the box!
Edited by Jonathan de Blok - 2024年2月1日 06:42:37
More code, less clicks.
  • Quick Links