# # Script by Sean Lewkiw # Help can be found at: # http://www.lewkiw.com # sean@lewkiw.com # ------------------------------------------------ # USUAGE NOTES: # Change the path below to the location of the # accompanying global.cmd file. # In a textport, type: tk path_to_file/global.tk # # NT Users NOTE: If you have an environmental # variable "TEMP" then this utility will put temp # shadow maps there. If you don't, then it will put # them in the directory from which Houdini was launched. # ------------------------------------------------ set PATH /net/homes/slewkiw/global.cmd # Windows, unix or linux? set PLATFORM $tcl_platform(platform) proc platform {} { global PLATFORM PATH tmpPATH tmpdir set tmpdir "" # Where should we put the temp shadow maps? # This variable becomes the prefix for the shadow maps. if {$PLATFORM == "unix" || $PLATFORM == "linux"} { set tmpPATH "/tmp/G_shad" } else { # Must be Windows..... # Does this environment variable exist? catch {set tmpdir $env(TEMP)} # If it's blank, just put temp files in pwd if {$tmpdir == ""} { set tmpPATH "./G_shad" } else { set tmpPATH "${tmpdir}/G_shad" } } } proc check_shader {} { # Are the shaders we need available? # We need v_rayshadow and v_asadlight hscript opcf /shop # This will give us a list of all available operators set temp [hscript opadd] set list "v_rayshadow v_asadlight" foreach i $list { # If the next expression fails, it returns -1, which means the op in question is unavailable. # Sad really. set temp2 [ string first $i $temp ] if { $temp2 == -1 } { puts "The shader ${i} is not available in this Houdini session." puts "Please install it and try again." puts "NOTE: You need both v_rayshadow and v_asadlight in order for this utility to work." tk_messageBox -parent . \ -title {ERROR} \ -icon error \ -message "The shader $i is not available in this Houdini session.\n\nPlease install\ it and try again.\n\nNOTE: You need the shaders: \"v_rayshadow\" and \"v_asadlight\" \ \nin order for this utility to work." exit } } } proc msg { msg } { global debug debugwin # Echo hscript commands to a text widget if requested if {$debug == 1} { # Echo to the shell as well puts $msg if {$debugwin == 0} { # Only create the window if it doesn't exist already. toplevel .warning text .warning.text -width 110 -height 60 pack .warning.text wm title .warning "Debug Log - Close to Clear" set debugwin 1 .warning.text insert end "Copy and paste code below to textport to see if there are errors.\n\n" # If user closes window, reset "debugwin" to zero so that the window # is created again if debug mode is enabled. wm protocol .warning WM_DELETE_WINDOW {set debugwin 0 ; destroy .warning} } .warning.text insert end $msg\n } } proc CHKPTH {} { global PATH # Is the path to global.cmd valid? if { [file exist $PATH ] == 0} { tk_messageBox -parent . \ -title {ERROR} \ -icon error \ -message "The file:\n$PATH\n...does not exist." exit } } proc create_new {} { global PLATFORM PATH tmpPATH PLATFORM res gen debug tmpdir hscript source $PATH init - $tmpPATH $res $gen msg "source $PATH init - $tmpPATH $res $gen" hscript set -g G_inc = 0 msg "set -g G_inc = 0" check if { $tmpdir == ""} { # Change the help button to yellow to alert user # that tmp files will be stored in $HIPDIR .top.help configure -bg yellow } } proc add_light { num } { global PLATFORM PATH tmpPATH PLATFORM res gen tmpdir set pINCR [hscript echo \$G_inc] set INCR [expr $pINCR - 0] set nINCR [incr INCR] if {$INCR != 0 && $num == "one" } { # Add only one light hscript source $PATH add $INCR $tmpPATH $res $gen msg "source $PATH add $INCR $tmpPATH $res $gen" hscript set -g G_inc = $nINCR msg "set -g G_inc = $nINCR" check # If user decides to add lights one at a time, remove # option to populate the entire dome .top.addall configure -state disabled # Enable add key light .top.key configure -state normal } # Populate the whole dome if {$INCR != 0 && $num == "all" } { hscript source $PATH all $INCR $tmpPATH $res $gen msg "hscript source $PATH all $INCR $tmpPATH $res $gen" hscript set -g G_inc = $nINCR msg "set -g G_inc = $nINCR" check # If user decides to populate the entire dome # remove option to add lights one at a time .top.add configure -state disabled .top.addall configure -state disabled # Enable add key light .top.key configure -state normal } # Key light if {$INCR != 0 && $num == "key" } { hscript source $PATH key $INCR $tmpPATH $res $gen msg "source $PATH key $INCR $tmpPATH $res $gen" # Don't allow user to press button again #.top.key configure -state disabled } } proc check {} { global PATH tmpPATH tmpdir platform check_shader set pINCR [hscript echo \$G_inc] if {$pINCR == "" || $pINCR == "{}"} { set pINCR 0 } # Check and see how many points are in the DOME object # commented out as it is slow # exec echo "set -g G_npoints = `npoints(\"/obj/G_dome/OUT\")`" > /tmp/npoints.tmp # hscript source /tmp/npoints.tmp # set nPOINTS [hscript echo \$G_npoints] if {$pINCR > 0} { .top.new configure -state disabled #.top.new configure -text "Create New Global Dome: $nPOINTS" # Enable all the buttons again .top.add configure -state normal .top.addall configure -state normal .top.key configure -state normal .top.add configure -text "Add Light to Dome: [expr $pINCR + 1]" } # Not sure what this was supposed to do, but it breaks the utility in Houdini 8.X # if {$pINCR == 0} { # .top.new configure -state normal # #.top.new configure -text "Create New Global Dome: $nPOINTS" # .top.add configure -text "Add Light to Dome: 0" # .top.add configure -state disabled # .top.addall configure -state disabled # .top.key configure -state disabled # } check_shadow } proc start_over {} { set result [tk_messageBox -parent . \ -type yesno -icon warning \ -title "Are you sure?" \ -message "Okay to delete all objects prepended with: \"G_\"?"] if {$result == "yes"} { hscript opcf /obj hscript oprm G_* hscript opcf /shop hscript oprm G_* hscript opcf /comp hscript oprm G_maps* hscript set -u G_inc hscript opcf /obj msg "opcf /obj ; oprm G_* ; opcf /shop ; oprm G_* ; opcf /comp ; oprm G_maps* ; set -u G_inc ; opcf /obj" check } } proc disable {} { global PATH gen set gSHAD [hscript echo \$G_shad] if {$gSHAD == 1 } { hscript source $PATH shad_on - - - $gen hscript set -g G_shad = 0 msg "source $PATH shad_on - - - $gen" msg "set -g G_shad = 0" } else { hscript source $PATH shad_disable - - - $gen hscript set -g G_shad = 1 msg "source $PATH shad_disable - - - $gen" msg "set -g G_shad = 1" } check_shadow } proc check_shadow {} { set gSHAD [hscript echo \$G_shad] if {$gSHAD == 1 } { .top.disable configure -bg red -text "Enable Shadow Map Generation" } else { .top.disable configure -bg gray80 -text "Disable Shadow Map Generation" } } proc help {} { global title tmpdir .top.help configure -state disabled -text "- Helping -" toplevel .help wm protocol .help WM_DELETE_WINDOW {destroy .help ; .top.help configure -state normal -text "- Help -"} wm title .help "Globaltk Help" if { $tmpdir == ""} { # Change the help button to yellow to alert user # that tmp files will be stored in $HIPDIR message .help.temp -width 7i -bg yellow -text \ "NOTE: Temp shadow maps will be stored in the directory from which\n\ you launched Houdini. If you would like them to be stored elsewhere\n\ be sure to set the environment variable \"TEMP\"." } message .help.m -width 7i -text \ " \n\ Welcome to Global.tk\n\ -----------------------------------\n\ - This GUI will create a lighting rig to mimic global illumination. MORE HELP AT http://www.lewkiw.com/global.html.\n\ - All objects created will be prepended with \"G_\".\n\ - This utility uses point colour information of the \"G_dome\" object to determine each light's colour and position. Colours are \n\ \tscaled, (dimmed), by referencing the \"G_light0\", (the master light's) dimmer.\n\ \n\ Using Global.tk\n\ -----------------------------------\n\ - Set the resolution of the lights. Low resolutions like 64x64 will result in fast rendering, but poor quality. Go to \n\ \tabout 256 to start, and up from there for better quality. To change the resolution of the lights after all the lights have\n\ \tbeen added, change the resolution of \"G_light0\" and the others will update as well.\n\ - Set the \"Depth Map\" paramater. This will require some experimentation to get right. Changing this results in shadow maps\n\ \tbeing calculated with a different algorithm. Experiment if you are getting artifacts.\n\ - Click the \"Create New Global Dome\" button. This will create a new dome to which you lights will be instanced, plus one master\n\ \tlight and shaders.\n\ - Position the dome in the scene so it is centered around the object you wish to render.\n\ - Modify your dome object if you wish. The \"dome\" object can be anything you want, as long as the last SOP is called \"OUT\".\n\ - Click on the \"Add Light to Dome\" button to attach more lights to the dome object, or \"Populate Entire Dome\" to do it all at once.\n\ - View through one of your lights and make sure you can see the objects you are rendering. If you can't, adjust the near and \n\ \tand far clipping planes of the master light. It's probably a good idea to make the region encompassing the geometry as tight \n\ \tas possible by adjusting the near and far paramaters.\n\ - You can add key lights with the \"Add Key Light\" button.\n\ - Change the shadow softness at the SHOP level with the \"Z-depth Softness\" setting in the shadow SHOP.\n\ - Changing the values in either the master light, master shadow SHOP or master light SHOP will cause all other OBJs to update with the \n\ \tsame values. The key light is not linked to any other light. \n\ - Adjust the overall intensity of the lights with the dimmer control in the master light, (G_light0).\n\ - Remove the random light colours by wiring the \"constant_color\" SOP into the \"OUT\" node of the \"G_dome object\".\n\ - Use COPSII if you are using floating point HDR images. Houdini supports floating point images in .pic, .rat, and .tiff formats.\n\ - You can turn on or off contribution to specular or diffuse for all lights at once using the \"Contr to Spec/Diff\" buttons after the \n\ \tlights have been added.\n\ - Clicking the \"Start Over\" button will remove all OBJs, COPs and SHOPs prepended with \"G_\".\n\ - If you have saved out your shadow maps once, you can avoid the overhead of re-creating them each time if you are only adjusting \n\ \texposure, shadow softness etc, AND you are re-rendering the same frame. Just hit the \"Enable/Disable Shadow Map Creation\" \n\ \tbutton to do so.\n\ \n\ Debug Mode\n\ -----------------------------------\n\ - Clicking this on will pop up a window with the hscript commands that are executed by this utility. If you are having problems with this\n\ \tutility, cut and paste these commands into a Houdini textport to help you track down the problem.\n\ \n\ -----------------------------------\n\ Globaltk by Sean Lewkiw. \n\ http://www.lewkiw.com \n\ " button .help.quit -text Exit -command {destroy .help ; .top.help configure -state normal -text "- Help -"} if { $tmpdir == ""} { pack .help.temp -fill x } pack .help.m .help.quit -fill x } proc quit {} { global PATH tmpPATH exit } proc cont { type switch } { # This proc turns on and off contribution to specular or diffuse in every light. global PATH tmpPATH foreach i [ hscript opls -d G_light* ] { update idletasks hscript opparm /obj/${i} $type ( $switch ) msg "opparm /obj/${i} $type ( $switch )" update idletasks } } CHKPTH frame .top pack .top -ipady 4 frame .top.raise -relief raised -borderwidth 3 grid .top.raise -row 0 -column 0 -columnspan 2 label .top.raise.resL -text "Light Resolution:" -bg gray65 tk_optionMenu .top.raise.res res "64" "128" "256" "512" "1024" "2048" "4096" set res 256 label .top.raise.genL -text "Depth Map:" -bg gray65 tk_optionMenu .top.raise.gen gen closest midpoint farthest set gen closest button .top.raise.diff -text "Contr Diff On" -command "cont diffuse on" -bg gray95 button .top.raise.diffo -text "Contr Diff Off" -command "cont diffuse off" button .top.raise.spec -text "Contr Spec On" -command "cont specular on" -bg gray95 button .top.raise.speco -text "Contr Spec Off" -command "cont specular off" button .top.new -text "Create New Global Dome" -command create_new button .top.add -text "Add Light to Dome: 0" -command {add_light one} button .top.addall -text "Populate Entire Dome" -command {add_light all} button .top.key -text "Add Key Light" -command {add_light key} #.top.key configure -state disabled button .top.disable -text "Disable Shadow Map Creation" -command {disable} button .top.help -text "- Help -" -height 1 -command help checkbutton .top.debug -variable debug .top.debug configure -indicatoron 0 -relief solid -text "Debug Mode"\ -selectcolor #668ad0 -borderwidth 2 -height 1 set debug 0 button .top.reset -text "Start Over" -command start_over button .top.quit -text "- Quit -" -command quit -bg gray95 # ---- Pack -------- grid .top.raise.resL -row 0 -column 0 -sticky ew grid .top.raise.res -row 0 -column 1 -sticky ew grid .top.raise.genL -row 1 -column 0 -sticky ew grid .top.raise.gen -row 1 -column 1 -sticky ew grid .top.raise.diff -row 2 -column 0 -sticky ew grid .top.raise.diffo -row 2 -column 1 -sticky ew grid .top.raise.spec -row 3 -column 0 -sticky ew grid .top.raise.speco -row 3 -column 1 -sticky ew grid .top.new -row 4 -column 0 -columnspan 2 -sticky ew grid .top.add -row 5 -column 0 -columnspan 2 -sticky ew grid .top.addall -row 6 -column 0 -columnspan 2 -sticky ew grid .top.key -row 7 -column 0 -columnspan 2 -sticky ew grid .top.disable -row 8 -column 0 -columnspan 2 -sticky ew grid .top.help -row 9 -column 0 -columnspan 1 -sticky ew grid .top.debug -row 9 -column 1 -columnspan 1 -sticky ew grid .top.reset -row 10 -column 0 -columnspan 2 -sticky ew grid .top.quit -row 11 -column 0 -columnspan 2 -sticky ew wm title . "Globaltk 1.5" set debugwin 0 # Make sure this puppy is always on top. # bind . {raise .} check wm protocol . WM_DELETE_WINDOW {quit}