Skip to content

Commit

Permalink
Merge branch 'dev' into 'main'
Browse files Browse the repository at this point in the history
Merge dev to main

See merge request renderman/projects/RenderManForBlender!27
  • Loading branch information
Ian Hsieh committed Dec 12, 2024
2 parents 56f26d0 + a60bf9f commit 7e17452
Show file tree
Hide file tree
Showing 47 changed files with 619 additions and 191 deletions.
12 changes: 10 additions & 2 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
bl_info = {
"name": "RenderMan For Blender",
"author": "Pixar",
"version": (26, 2, 0),
"version": (26, 3, 0),
"blender": (2, 93, 0),
"location": "Render Properties > Render Engine > RenderMan",
"description": "RenderMan 26 integration",
Expand All @@ -46,7 +46,15 @@ def load_node_arrange():
'''

if addon_utils.check('node_arrange')[1] is False:
addon_utils.enable('node_arrange')
available = False
for m in addon_utils.modules():
# check if node_arrange is available
# it's been removed as of blender 4.0
if m.__name__ == 'node_arrange':
available = True
break
if available:
addon_utils.enable('node_arrange')

def load_addon():
global __RMAN_ADDON_LOADED__
Expand Down
2 changes: 1 addition & 1 deletion preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ def draw(self, context):
col.prop(self, 'rman_render_nurbs_as_mesh')
col.prop(self, 'rman_show_cycles_convert')
col.prop(self, 'rman_emit_default_params')
col.prop(self, 'rman_invert_light_linking')
# col.prop(self, 'rman_invert_light_linking')
col.prop(self, 'rman_solo_collapse_nodes')
col.prop(self, 'rman_use_blend_dir_token')
col.prop(self, 'rman_parent_lightfilter')
Expand Down
2 changes: 1 addition & 1 deletion rfb_unittests/test_shader_nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def test_value_conversion(self):

self.assertAlmostEqual(unitLength, string_utils.convert_val(n1.unitLength, type_hint='float'))
self.assertEqual(diffuseDoubleSided, string_utils.convert_val(n1.diffuseDoubleSided, type_hint='int'))
self.assertEqual(var_type, string_utils.convert_val(n2.type, type_hint='string'))
self.assertEqual(var_type, string_utils.convert_val(n2.rman_type, type_hint='string'))

bpy.data.materials.remove(mat)

Expand Down
9 changes: 2 additions & 7 deletions rfb_utils/display_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,14 @@ def __init__(self, channelType, channelName, channelSource="", channelStatistics
OutputChannel("color", "Ci"),
OutputChannel("float", "a"),
DENOISER_ALBEDO,
OutputChannel("color", "albedo_var", "color lpe:nothruput;noinfinitecheck;noclamp;unoccluded;overwrite;C<.S'passthru'>*((U2L)|O)", "variance"),
OutputChannel("color", "albedo_mse", "color lpe:nothruput;noinfinitecheck;noclamp;unoccluded;overwrite;C<.S'passthru'>*((U2L)|O)", "mse"),
OutputChannel("vector", "backward", "vector motionBack"),
OutputChannel("color", "diffuse", "color lpe:C(D[DS]*[LO])|O"),
OutputChannel("color", "diffuse_mse", "color lpe:C(D[DS]*[LO])|O", "mse"),
OutputChannel("vector", "forward", "vector motionFore"),
OutputChannel("color", "mse", "color Ci", "mse"),
DENOISER_NORMAL,
OutputChannel("normal", "normal_var", "normal Nn", "variance"),
OutputChannel("color", "normal_mse", "normal Nn", "mse"),
OutputChannel("color", "specular", "color lpe:CS[DS]*[LO]"),
OutputChannel("color", "specular_mse", "color lpe:CS[DS]*[LO]", "mse"),
OutputChannel("float", "zfiltered", "float zfiltered"),
OutputChannel("float", "zfiltered_var", "float zfiltered", "variance"),
OutputChannel("float", "sampleCount", "sampleCount")
]

Expand Down Expand Up @@ -247,8 +241,9 @@ def _add_interactive_denoiser_channels(dspys_dict, dspy_params, rman_scene):
dspys_dict['displays']['beauty']['params']['displayChannels'].append(output_chan.name)

dspys_dict['displays']['beauty']['is_variance'] = True
dspy_driver = dspys_dict['displays']['beauty']['driverNode']

if rman_scene.is_viewport_render:
if dspy_driver == 'quicklyNoiseless':
param_list = rman_scene.rman.Types.ParamList()
rm = rman_scene.bl_scene.renderman
if rman_scene.ipr_render_into == "blender":
Expand Down
3 changes: 2 additions & 1 deletion rfb_utils/filepath_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from ..rfb_logger import rfb_log
from .prefs_utils import get_pref
from . import string_utils
from .. import rman_constants

def view_file(file_path):

Expand Down Expand Up @@ -54,7 +55,7 @@ def get_cycles_shader_path():
path = ''
version = '%d.%d' % (bpy.app.version[0], bpy.app.version[1])
binary_path = os.path.dirname(bpy.app.binary_path)
rel_config_path = os.path.join(version, 'scripts', 'addons', 'cycles', 'shader')
rel_config_path = os.path.join(version, rman_constants.CYCLES_SHADERS_PATH)
if sys.platform == ("win32"):
path = os.path.join(binary_path, rel_config_path)
elif sys.platform == ("darwin"):
Expand Down
7 changes: 1 addition & 6 deletions rfb_utils/generate_property_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,7 @@ def update_colorspace_name(self, context, param_name):
if txfile:
params = txfile.params.as_dict()
if params['ocioconvert'] != ociconvert:
params['ocioconvert'] = ociconvert
txfile.params.from_dict(params)
txfile.delete_texture_files()
txfile.build_texture_dict()
texture_utils.get_txmanager().txmake_all(blocking=False)

texture_utils.update_txfile_colorspace(txfile, ociconvert)
bpy.ops.rman_txmgr_list.refresh('EXEC_DEFAULT')

def colorspace_names_list():
Expand Down
11 changes: 10 additions & 1 deletion rfb_utils/osl_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,16 @@ def readOSO(filePath):
prop_meta['renderman_type'] = type

# default
if not pdict['isstruct']:
if pdict['default'] is None:
if prop_meta['type'] == 'float':
prop_meta['default'] = 0.0
elif prop_meta['type'] == 'int':
prop_meta['default'] = 0
elif prop_meta['type'] in ['color', 'point', 'normal', 'vector']:
prop_meta['default'] = (0.0, 0.0, 0.0)
else:
prop_meta['default'] = ""
elif not pdict['isstruct']:
prop_meta['default'] = pdict['default']
if prop_meta['type'] == 'float':
prop_meta['default'] = float('%g' % prop_meta['default'])
Expand Down
4 changes: 2 additions & 2 deletions rfb_utils/property_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1061,8 +1061,8 @@ def portal_inherit_dome_params(portal_node, dome, dome_node, rixparams):
rixparams.SetFloat('temperature', string_utils.convert_val(prop, type_hint='float'))

# inherit lightColorMap directly from the dome
tx_node_id = texture_utils.generate_node_id(dome_node, 'lightColorMap', ob=dome)
tx_val = texture_utils.get_txmanager().get_output_tex_from_id(tx_node_id)
prop = getattr(dome_node, 'lightColorMap')
tx_val = texture_utils.get_txmanager().get_output_tex_from_path(dome_node, 'lightColorMap', prop, ob=dome)
rixparams.SetString('domeColorMap', tx_val)

# inherit exposure directly from dome
Expand Down
2 changes: 1 addition & 1 deletion rfb_utils/rfb_node_desc_utils/rfb_node_desc_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
'set_function_name', 'set_function',
'get_function_name', 'get_function',
'readOnly', 'always_write', 'ipr_editable', 'hideInput',
'uiStruct', 'bl_prop_options']
'uiStruct', 'bl_prop_options', 'arraySize']

def blender_finalize(obj):
"""Post-process some parameters for Blender.
Expand Down
49 changes: 48 additions & 1 deletion rfb_utils/scene_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,52 @@ def set_lightlinking_properties(ob, light_ob, illuminate, update_light=True):

return changed

def reset_workspace(scene):
from .. import rman_config

# Set all output paths to default.
# There doesn't seem to be a way to set properties back to default, so do it manually
rmcfg = rman_config.__RMAN_CONFIG__.get('rman_properties_scene', None)
for param_name, ndp in rmcfg.params.items():
if ndp.panel != 'RENDER_PT_renderman_workspace':
continue
setattr(scene.renderman, param_name, ndp.default)

def use_renderman_textures(context, force_colorspace=True, blocking=True):
'''
Change all textures on texture nodes to use the RenderMan .tex file
Arguments:
context (bpy.context) - the current Blender context
force_colorspace (bool) - if on, force the use of the node's selection
of colorspace, if the node and the texture manager disagree on what colorpsace
the texture should be using
blocking (bool) - updating the colorspace will trigger a txmake event. Set this to False
if you don't want to block while txmake is running
'''
from . import texture_utils

for node in shadergraph_utils.get_all_shading_nodes():
for prop_name, meta in node.prop_meta.items():
param_type = meta['renderman_type']
if param_type != 'string':
continue
if shadergraph_utils.is_texture_property(prop_name, meta):
prop = getattr(node, prop_name)
if prop != '':
ob = find_node_owner(node, context)
txfile = texture_utils.get_txmanager().get_txfile(node, prop_name, ob=ob)
if txfile and not txfile.source_is_tex():
colorspace_nm = '%s_colorspace' % prop_name
colorspace = getattr(node, colorspace_nm, None)
if colorspace:
# check the colorspace
params = txfile.params.as_dict()
if params['ocioconvert'] != colorspace and force_colorspace:
texture_utils.update_txfile_colorspace(txfile, colorspace, blocking=blocking)
setattr(node, prop_name, txfile.get_output_texture())
continue

def is_renderable(scene, ob):
return (is_visible_layer(scene, ob) and not ob.hide_render) or \
(ob.type in ['ARMATURE', 'LATTICE', 'EMPTY'] and ob.instance_type not in SUPPORTED_DUPLI_TYPES)
Expand Down Expand Up @@ -689,4 +735,5 @@ def _get_subframes_(segs, scene):
elif rm.shutter_timing == 'FRAME_OPEN':
min = 0

return [min + i * shutter_interval / (segs - 1) for i in range(segs)]
return [min + i * shutter_interval / (segs - 1) for i in range(segs)]

5 changes: 5 additions & 0 deletions rfb_utils/scenegraph_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ def update_sg_displays(context):
rr = rman_render.RmanRender.get_rman_render()
rr.rman_scene_sync.update_displays(context)

def update_root_lightlinks(context):
from .. import rman_render
rr = rman_render.RmanRender.get_rman_render()
rr.rman_scene_sync.update_displays(context)

def export_vol_aggregate(bl_scene, primvar, ob):
vol_aggregate_group = []
for i,v in enumerate(bl_scene.renderman.vol_aggregates):
Expand Down
29 changes: 15 additions & 14 deletions rfb_utils/shadergraph_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,24 +188,25 @@ def get_socket_name(node, socket):
if node_desc:
idx = -1
is_output = socket.is_output
if is_output:
for i, output in enumerate(node.outputs):
if socket.name == output.name:
idx = i
break
else:
for i, input in enumerate(node.inputs):
if socket.name == input.name:
idx = i
break
node_desc_params = node_desc.outputs if is_output else node_desc.params
sockets = node.outputs if is_output else node.inputs

# Let's look if there's one with a similar
# name already
for p in node_desc_params:
if socket.name in p.name:
return p.name

# try based on index
for i, input in enumerate(sockets):
if socket.name == input.name:
idx = i
break

if idx == -1:
return socket.identifier.replace(' ', '')

if is_output:
node_desc_param = node_desc.outputs[idx]
else:
node_desc_param = node_desc.params[idx]
node_desc_param = node_desc_params[idx]

return node_desc_param.name

Expand Down
6 changes: 5 additions & 1 deletion rfb_utils/string_expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ def update_out_token(self):
self.tokens['OUT'] = root_path

unsaved = True if not bpy.data.filepath else False
if unsaved:
scene = self.bl_scene
rm = scene.renderman
if rm.blenddir_token != "":
self.tokens['blend_dir'] = rm.blenddir_token
elif unsaved:
self.tokens['blend_dir'] = self.tokens['OUT']
else:
self.tokens['blend_dir'] = os.path.split(bpy.data.filepath)[0]
Expand Down
3 changes: 2 additions & 1 deletion rfb_utils/string_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
'ies': 'ies', 'ptex': 'ptex'
}

__NODE_NAME_REGEXP__ = r'\s+|\.+|:'
# regex to capture whitespace, '.', ':', '[', ']'
__NODE_NAME_REGEXP__ = r'\s+|\.+|:|\[|\]'

class SceneStringConverter(object):
"""Class maintaining an up-to-date StringExpression object.
Expand Down
31 changes: 28 additions & 3 deletions rfb_utils/texture_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from .color_manager_blender import color_manager

from bpy.app.handlers import persistent
from copy import deepcopy

import os
import bpy
Expand Down Expand Up @@ -194,7 +195,12 @@ def add_texture(self, node, ob, param_name, file_path, node_type='PxrTexture', c
txfile = self.txmanager.get_txfile_from_id(plug_uuid)
txmake_all(blocking=False)
if txfile:
self.done_callback(plug_uuid, txfile)
self.done_callback(plug_uuid, txfile)
if not txfile.source_is_tex():
param_colorspace = '%s_colorspace' % param_name
ociconvert = getattr(node, param_colorspace, None)
if ociconvert:
update_txfile_colorspace(txfile, ociconvert)

def is_file_src_tex(self, node, prop_name):
id = scene_utils.find_node_owner(node)
Expand Down Expand Up @@ -285,6 +291,19 @@ def update_texture(node, ob=None, check_exists=False, is_library=False):
category = getattr(node, 'renderman_node_type', 'pattern')
get_txmanager().add_texture(node, ob, prop_name, fpath, node_type=node_type, category=category)

def update_txfile_colorspace(txfile, ociconvert, blocking=False):
if ociconvert == '0':
return
params = txfile.params.as_dict()
if params['ocioconvert'] != ociconvert:
params['ocioconvert'] = ociconvert
txfile.params.from_dict(params)
txfile.set_params(txfile.params)
txfile.build_texture_dict()
if txfile.check_dirty(force_check=True):
txfile.delete_texture_files()
get_txmanager().txmake_all(blocking=blocking)

def generate_node_name(node, prop_name, ob=None, nm=None):
node_name = ''
if not nm:
Expand Down Expand Up @@ -416,8 +435,14 @@ def txmanager_load_cb(bl_scene):
return
get_txmanager().txmanager.reset()
get_txmanager().txmanager.load_state()
bpy.ops.rman_txmgr_list.parse_scene('EXEC_DEFAULT')
bpy.ops.rman_txmgr_list.clear_unused('EXEC_DEFAULT')
scene = bpy.context.scene
rm = getattr(scene, 'renderman', None)
state = None
if rm:
state = getattr(rm, 'txmanagerData', state)
if state is None:
bpy.ops.rman_txmgr_list.parse_scene('EXEC_DEFAULT')
bpy.ops.rman_txmgr_list.clear_unused('EXEC_DEFAULT')

@persistent
def txmanager_pre_save_cb(bl_scene):
Expand Down
14 changes: 14 additions & 0 deletions rfb_utils/upgrade_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .. import rman_constants
from ..rfb_utils import shadergraph_utils, object_utils
from ..rfb_logger import rfb_log
from ..rfb_utils.prefs_utils import get_pref
from collections import OrderedDict
import bpy

Expand Down Expand Up @@ -267,6 +268,18 @@ def upgrade_261_0(scene):
if len(rm.prim_vars) > 0:
rm.output_all_primvars = False

def upgrade_262_1(scene):
'''
In 26.2 and below, the invert light linking attribute was a user preference.
Unfortunately, this doesn't help when rendering in the cloud as the cloud provider
won't know what the user had selected.
So we add the invert_light_linking as a scene property.
For older scenes, if the user pref had invert light linking set to on, we also
set the scene property as well
'''
if get_pref('rman_invert_light_linking'):
scene.renderman.invert_light_linking = 1

__RMAN_SCENE_UPGRADE_FUNCTIONS__ = OrderedDict()

Expand All @@ -276,6 +289,7 @@ def upgrade_261_0(scene):
__RMAN_SCENE_UPGRADE_FUNCTIONS__['25.0.1'] = upgrade_250_1
__RMAN_SCENE_UPGRADE_FUNCTIONS__['26.0.0'] = upgrade_260_0
__RMAN_SCENE_UPGRADE_FUNCTIONS__['26.1.0'] = upgrade_261_0
__RMAN_SCENE_UPGRADE_FUNCTIONS__['26.2.1'] = upgrade_262_1

def upgrade_scene(bl_scene):
global __RMAN_SCENE_UPGRADE_FUNCTIONS__
Expand Down
4 changes: 0 additions & 4 deletions rman_bl_nodes/rman_bl_nodes_menus.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
from ..rfb_logger import rfb_log
from ..rfb_utils.osl_utils import readOSO
from ..rfb_utils import shadergraph_utils
from ..rfb_utils import rman_socket_utils
from ..rman_constants import RFB_FLOAT3
from .. import rman_render
from .. import rman_bl_nodes
from .. import rfb_icons
from bpy.types import Menu
from bpy.props import EnumProperty, StringProperty, CollectionProperty
import _cycles
import bpy

class NODE_MT_renderman_param_presets_menu(Menu):
bl_label = "Parameter Presets"
Expand Down
Loading

0 comments on commit 7e17452

Please sign in to comment.