Houdini Octane

From bernie's
Jump to navigation Jump to search

Octane

Python tools

IPR Launch

Bound it to F9 -- for the 3ds crowd ;)

import hou

def chooseIPRdialog(buttons):
    try:
        c = hou.session.choice
    except:
        hou.session.choice = 0

    buttons.append('Cancel')
    dialog = hou.ui.displayMessage('IPR choice', buttons=buttons,default_choice=hou.session.choice)
    hou.session.choice = dialog
    if dialog == len(buttons)-1:
        dialog = False
    return dialog
    
#grab all iprs
iprs = []
for node in hou.node('/').allSubChildren():
    if node.type().name() == 'Octane_ROP':
        iprs.append(node)

#simple names
names = [x.name() for x in iprs]

#if we have duplicate names, give a more detailed path
if len(names) != len(set(names)):
    names = [x.path() for x in iprs]

#if only one IPR found, launch it otherwise launch dialog, return ipr, launch ipr if not cancelled    
if len(names) == 1:
    iprs[0].parm('HO_IPR').pressButton()
else:
    chosenIPR = chooseIPRdialog(names)
    if chosenIPR is not False:
        iprs[chosenIPR].parm('HO_IPR').pressButton()

HDRI in the viewport control

It's a pain in the ass to go to the rendertarget each time, this acts like a normal environment preview. Barebones but works.

WD2MCEI.gif

'''
links a null with some parameters to a chosen Rendertarget texture. 
Display flag sets texture on/off just like for lights.
No error checking.
'''

import hou
def chooseRTdialog(buttons):
    buttons.append('Cancel')
    dialog = hou.ui.displayMessage('Choose which RTarget HDRi to link to', buttons=buttons)
    if dialog == len(buttons)-1:
        dialog = False
    return dialog

def linkDispFlag(node,event_type):
    RT = hou.node(node.parm('RT').eval())
    menu = RT.parm('environmentMenu')
    if node.isDisplayFlagSet() == 1:
        menu.set(6)
    else:
        menu.set(1)

    
    
rts = []
RT = None
for node in hou.node('/').allSubChildren():
    if 'octane_mat_renderTarget' in node.type().name():
        rts.append(node)

names = [x.name() for x in rts]        

if len(rts) == 1:
    RT = rts[0]

else:
    chosenRT = chooseRTdialog(names)
    if chosenRT is not False:
        RT = rts[chosenRT]

if RT:
    hdri = hou.node("/obj").createNode("null", "hdri")
    hdri.setSelectableInViewport(True)
    hdri.useXray(True)
    hdri.setDisplayFlag(True)
    hdri.hide(False)
    hdri.setSelected(True)
    hdri.parm('geoscale').set(10)
    hdri.parm('controltype').set(1)
    hdri.setUserData("nodeshape", "circle")
    hdri.setColor(hou.Color([0.976, 0.78, 0.263]))
    
    hdri.setGenericFlag(hou.nodeFlag.DisplayComment,True)

    ptg = hdri.parmTemplateGroup()

    slider = hou.FloatParmTemplate("hdripower", "Hdri Power", 1, default_value=(0.0,))
    exr = hou.StringParmTemplate("exr", "HDRI", 1, string_type=hou.stringParmType.FileReference, file_type=hou.fileType.Image)
    path = hou.StringParmTemplate("RT", "RTarget", 1, string_type=hou.stringParmType.NodeReference,default_value=(RT.path(),)) 

    ptg.insertBefore((0,0),path)
    ptg.insertBefore((0,0),exr)
    ptg.insertBefore((0,0),slider)

    hdri.setParmTemplateGroup(ptg)
        
    parmsFrom = 'tx ty tz rx ry rz sx sy sz exr hdripower'
    parmsTo = 'translation121 translation122 translation123 textureEnvTilt textureEnvLeftRight textureEnvRoll textureEnvScale1 textureEnvScale2 textureEnvScale3 textureEnvironmentFilename textureEnvPower'

    parmsFrom = parmsFrom.split(' ')
    parmsTo = parmsTo.split(' ')

    for i in range(len(parmsFrom)):
        hdri.parm(parmsFrom[i]).set(RT.parm(parmsTo[i]).eval())     
        RT.parm(parmsTo[i]).set(hdri.parm(parmsFrom[i]))
    
    hdri.setComment(RT.path()+'\n'+RT.parm('textureEnvironmentFilename').eval().split('/')[-1])
    #hou.nodeEventType.FlagChanged
    #hdri.addEventCallback(hou.nodeEventType.FlagChanged,print("hi"))
    #RT.parm('environmentMenu').eval()
    hdri.addEventCallback((hou.nodeEventType.FlagChanged,),linkDispFlag)    

Shading Guide

For C4D, still good: https://www.behance.net/gallery/102948251/Octane-Universal-Material-Guide-Starter-File

Shading instances with custom colors

Is a little more hands on than getting custom attributes

If you have a single object that you want to instance but have it have a random shader (in my example, using color), you can use a trick/weird workaround.

To make it work:

  • in your scattered points (the ones that hold @instance, @orient, @pscale, @Cd) /obj/ level geo, make sure you choose 'Packed RGBA Values from 'Cd' Point Attribute'.
  • in your instance shader, you need to grab 'Texture Instance Color' and go pick a .ppm texture that sits in the install directory of octane under the /tex folder called rgb4k_map.ppm
  • plug it in directly your diffuse or use it to drive other textures like a ramp in my example

GZIUm2z.png

Shadow catcher with diffuse bounce

I think default shadow catching doesn't get the bounce so you can whip it up with a rayswitch. I sort of plugged stuff into stuff for it to work (topright pigheads -- bottom left is normal shadowcatcher,plane grid is a green material):

(also i cropped the rayswitch like an idiot but camera ray is at 0 the rest at 1

8yxOMxr.png

KsjjsQK.png

Double sided material in Octane

You can use tool_polygon_side to drive a material mixer:

e1aOVPh.png


Arnold

Weird render procedural stuff: https://arnoldsupport.com/2018/11/21/backdoor-setting-visibility/