Difference between revisions of "Houdini Octane"

From bernie's
Jump to navigation Jump to search
Line 15: Line 15:


import hou
import hou
def chooseRTdialog(buttons):
def chooseRTdialog(buttons):
     buttons.append('Cancel')
     buttons.append('Cancel')
Line 30: Line 29:
     else:
     else:
         menu.set(1)
         menu.set(1)
 
 
   
   
rts = []
rts = []
RT = None
RT = None
Line 38: Line 39:


names = [x.name() for x in rts]         
names = [x.name() for x in rts]         
       
 
if len(rts) == 1:
if len(rts) == 1:
     RT = rts[0]
     RT = rts[0]
Line 45: Line 46:
     chosenRT = chooseRTdialog(names)
     chosenRT = chooseRTdialog(names)
     if chosenRT is not False:
     if chosenRT is not False:
         RT = chosenRT
         RT = rts[chosenRT]


if RT:
if RT:
Line 84: Line 85:
      
      
     hdri.setComment(RT.path()+'\n'+RT.parm('textureEnvironmentFilename').eval().split('/')[-1])
     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)     
     hdri.addEventCallback((hou.nodeEventType.FlagChanged,),linkDispFlag)     
</pre>
</pre>

Revision as of 17:45, 10 October 2025

Octane

Python tools

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/