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 for 25

See merge request renderman/projects/RenderManForBlender!16
  • Loading branch information
Ian Hsieh committed Apr 14, 2023
2 parents 9cf2182 + f65d6bf commit 8805939
Show file tree
Hide file tree
Showing 123 changed files with 8,688 additions and 3,840 deletions.
260 changes: 16 additions & 244 deletions __init__.py
Expand Up @@ -22,253 +22,30 @@
#
#
# ##### END MIT LICENSE BLOCK #####
import bpy
import bgl
import blf
import time
import addon_utils

from .rfb_utils.prefs_utils import get_pref
from .rfb_utils import string_utils
from .rfb_utils import register_utils
from .rfb_logger import rfb_log
from .rfb_utils.envconfig_utils import envconfig
from .rman_constants import RFB_FLOAT3

bl_info = {
"name": "RenderMan For Blender",
"author": "Pixar",
"version": (24, 4, 0),
"version": (25, 0, 0),
"blender": (2, 83, 0),
"location": "Info Header, render engine menu",
"description": "RenderMan 24 integration",
"warning": "",
"location": "Render Properties > Render Engine > RenderMan",
"description": "RenderMan 25 integration",
"doc_url": "https://rmanwiki.pixar.com/display/RFB",
"category": "Render"}

__RMAN_ADDON_LOADED__ = False

class PRManRender(bpy.types.RenderEngine):
bl_idname = 'PRMAN_RENDER'
bl_label = "RenderMan"
bl_use_preview = False # Turn off preview renders
bl_use_save_buffers = True
bl_use_shading_nodes = True # We support shading nodes
bl_use_shading_nodes_custom = False
bl_use_eevee_viewport = True # Use Eevee for look dev viewport mode
bl_use_postprocess = True
def load_node_arrange():
'''
Make sure that the node_arrange addon is enabled
'''

def __init__(self):
from . import rman_render
self.rman_render = rman_render.RmanRender.get_rman_render()
self.export_failed = None
if self.is_preview and self.rman_render.rman_swatch_render_running:
# if a preview render is requested and a swatch render is
# already in progress, ignore this render request
return
if self.rman_render.rman_interactive_running:
# If IPR is already running, just return.
# We report an error in render() if this is a render attempt
return

def __del__(self):
try:
from . import rman_render
except ModuleNotFoundError:
return

rr = rman_render.RmanRender.get_rman_render()
try:
if self.is_preview:
# If this was a preview render, return
return
except:
pass

if rr.rman_running:
if rr.rman_interactive_running:
rfb_log().debug("Stop interactive render.")
rr.rman_is_live_rendering = False
elif rr.is_regular_rendering():
rfb_log().debug("Stop render.")
rr.stop_render(stop_draw_thread=False)

def update(self, data, depsgraph):
pass

def view_update(self, context, depsgraph):
'''
For viewport renders. Blender calls view_update when starting viewport renders
and/or something changes in the scene.
'''

# check if we are already doing a regular render
if self.rman_render.is_regular_rendering():
return

if self.export_failed:
return

# if interactive rendering has not started, start it
if not self.rman_render.rman_interactive_running and self.rman_render.sg_scene is None:
self.rman_render.bl_engine = self
if not self.rman_render.start_interactive_render(context, depsgraph):
self.export_failed = True
return
self.export_failed = False

if self.rman_render.rman_interactive_running and not self.rman_render.rman_license_failed:
self.rman_render.update_scene(context, depsgraph)

def view_draw(self, context, depsgraph):
'''
For viewport renders. Blender calls view_draw whenever it redraws the 3D viewport.
This is where we check for camera moves and draw pxiels from our
Blender display driver.
'''
if self.export_failed:
return
if self.rman_render.rman_interactive_running and not self.rman_render.rman_license_failed:
self.rman_render.update_view(context, depsgraph)

self._draw_pixels(context, depsgraph)

def _increment_version_tokens(self, external_render=False):
bl_scene = bpy.context.scene
vi = get_pref('rman_scene_version_increment', default='MANUALLY')
ti = get_pref('rman_scene_take_increment', default='MANUALLY')

if (vi == 'RENDER' and not external_render) or (vi == 'BATCH_RENDER' and external_render):
bl_scene.renderman.version_token += 1
string_utils.set_var('version', bl_scene.renderman.version_token)

if (ti == 'RENDER' and not external_render) or (ti == 'BATCH_RENDER' and external_render):
bl_scene.renderman.take_token += 1
string_utils.set_var('take', bl_scene.renderman.take_token)

def update_render_passes(self, scene=None, renderlayer=None):
# this method allows us to add our AOVs as ports to the RenderLayer node
# in the compositor.

from .rfb_utils import display_utils
if self.is_preview:
return

if self.rman_render.rman_render_into != 'blender':
return

self.rman_render.rman_scene.bl_scene = scene
dspy_dict = display_utils.get_dspy_dict(self.rman_render.rman_scene)
self.register_pass(scene, renderlayer, "Combined", 4, "RGBA", 'COLOR')
for i, dspy_nm in enumerate(dspy_dict['displays'].keys()):
if i == 0:
continue
dspy = dspy_dict['displays'][dspy_nm]
dspy_chan = dspy['params']['displayChannels'][0]
chan_info = dspy_dict['channels'][dspy_chan]
chan_type = chan_info['channelType']['value']

if chan_type == 'color':
self.register_pass(scene, renderlayer, dspy_nm, 3, "RGB", 'COLOR')
elif chan_type in ['vector', 'normal', 'point']:
self.register_pass(scene, renderlayer, dspy_nm, 3, "XYZ", 'VECTOR')
else:
self.register_pass(scene, renderlayer, dspy_nm, 1, "Z", 'VALUE')

def render(self, depsgraph):
'''
Main render entry point. Blender calls this when doing final renders or preview renders.
'''

bl_scene = depsgraph.scene_eval
rm = bl_scene.renderman
baking = (rm.hider_type in ['BAKE', 'BAKE_BRICKMAP_SELECTED'])

if self.rman_render.rman_interactive_running:
# report an error if a render is trying to start while IPR is running
if self.is_preview and get_pref('rman_do_preview_renders', False):
#self.report({'ERROR'}, 'Cannot start a preview render when IPR is running')
rfb_log().debug('Cannot start a preview render when IPR is running')
pass
elif not self.is_preview:
self.report({'ERROR'}, 'Cannot start a render when IPR is running')
return
elif self.is_preview:
# double check we're not already viewport rendering
if self.rman_render.rman_interactive_running:
if get_pref('rman_do_preview_renders', False):
rfb_log().error("Cannot preview render while viewport rendering.")
return
if not get_pref('rman_do_preview_renders', False):
# user has turned off preview renders, just load the placeholder image
self.rman_render.bl_scene = depsgraph.scene_eval
#self.rman_render._load_placeholder_image()
return
if self.rman_render.rman_swatch_render_running:
return
self.rman_render.bl_engine = self
self.rman_render.start_swatch_render(depsgraph)
elif baking:
self.rman_render.bl_engine = self
if rm.enable_external_rendering:
self.rman_render.start_external_bake_render(depsgraph)
elif not self.rman_render.start_bake_render(depsgraph, for_background=bpy.app.background):
return
elif rm.enable_external_rendering:
self.rman_render.bl_engine = self
self.rman_render.start_external_render(depsgraph)
self._increment_version_tokens(external_render=True)
else:
for_background = bpy.app.background
self.rman_render.bl_engine = self
if not self.rman_render.start_render(depsgraph, for_background=for_background):
return
if not for_background:
self._increment_version_tokens(external_render=False)

def _draw_pixels(self, context, depsgraph):

scene = depsgraph.scene
w = context.region.width
h = context.region.height

if self.rman_render.rman_license_failed:
pos_x = w / 2 - 100
pos_y = 20
blf.enable(0, blf.SHADOW)
blf.shadow_offset(0, 1, -1)
blf.shadow(0, 5, 0.0, 0.0, 0.0, 0.8)
blf.size(0, 32, 36)
blf.position(0, pos_x, pos_y, 0)
blf.color(0, 1.0, 0.0, 0.0, 1.0)
blf.draw(0, "%s" % (self.rman_render.rman_license_failed_message))
blf.disable(0, blf.SHADOW)
return

# Draw text area that RenderMan is running.
if get_pref('draw_ipr_text', False) and not self.rman_render.rman_is_viewport_rendering:

pos_x = w / 2 - 100
pos_y = 20
blf.enable(0, blf.SHADOW)
blf.shadow_offset(0, 1, -1)
blf.shadow(0, 5, 0.0, 0.0, 0.0, 0.8)
blf.size(0, 32, 36)
blf.position(0, pos_x, pos_y, 0)
blf.color(0, 1.0, 0.0, 0.0, 1.0)
blf.draw(0, "%s" % ('RenderMan Interactive Mode Running'))
blf.disable(0, blf.SHADOW)

if not self.rman_render.rman_is_viewport_rendering:
return

# Bind shader that converts from scene linear to display space,
bgl.glEnable(bgl.GL_BLEND)
bgl.glBlendFunc(bgl.GL_ONE, bgl.GL_ONE_MINUS_SRC_ALPHA)
self.bind_display_space_shader(scene)

self.rman_render.draw_pixels(w, h)

self.unbind_display_space_shader()
bgl.glDisable(bgl.GL_BLEND)
if addon_utils.check('node_arrange')[1] is False:
addon_utils.enable('node_arrange')

def load_addon():
global __RMAN_ADDON_LOADED__
Expand All @@ -283,6 +60,7 @@ def load_addon():
from . import rman_handlers
from . import rfb_translations
from . import rman_stats
from . import rman_engine

rman_config.register()
rman_properties.pre_register()
Expand All @@ -294,23 +72,19 @@ def load_addon():
rman_handlers.register()
rfb_translations.register()
rman_stats.register()
rman_engine.register()

__RMAN_ADDON_LOADED__ = True

else:
rfb_log().error(
"Error loading addon. Correct RMANTREE setting in addon preferences.")

classes = [
PRManRender,
]

def register():
register_utils.rman_register_classes(classes)

def register():
from . import preferences
preferences.register()
load_addon()
load_node_arrange()

def unregister():
global __RMAN_ADDON_LOADED__
Expand All @@ -327,6 +101,4 @@ def unregister():
rman_operators.unregister()
rfb_translations.unregister()
rman_stats.unregister()

register_utils.rman_unregister_classes(classes)

rman_engine.unregister()
74 changes: 74 additions & 0 deletions changelog.txt
@@ -1,3 +1,77 @@
v25.0 April 17, 2023

New Features:
* You can now use the Qt version of the preset browser and texture manager, which
matches what is available in the other RenderMan DCC plugins. To use the Qt version,
go to the addon preferences and change UI Framework from Native to Qt
* Blender's "Persistent Data" option is now supported. This is mostly useful in batch rendering
where for subsequent frames only differences in the scene are calculated, rather than
re-generating the whole scene. Note, this option is off by default.
* For external/batch rendering using Blender Batch style, there is a new Frame Chunking option,
which specifies how many frames each blender process will render (previously, each
blender process would only do one frame).
* We now auto load the Blender's builtin Node Arrange addon. This allows for auto
arranging nodes in the shader graph. Two of the operators have been added to the RenderMan
right click context menu.

Changes:
* Scene translation time has been improved. In some cases, as much as 27% speed improvement
has been seen.
* IPR to "it" is no longer a separate setting. To IPR to "it", right click in the Viewport,
and go to RenderMan->Render->IPR to it.
* Support for fluid meshes has been added.
* We now export two new user attributes: "user:blender_is_instance" and "user:blender_instance_uv".
If "user:blender_is_instance" is set to 1, this indicates that the current object is an instance.
* For subdivision meshes, you can now select a face map to act as holes for your mesh (note,
this does not work in XPU).
* Socket names for terminal nodes (ex: RenderMan Material, Bxdf etc) have been renamed. For example,
old name (Bxdf), new name (bxdf_in). This is to match the names used in our other DCC plugins.
* Editing attributes or options during IPR should be faster.
* For meshes, exporting of the tangent and bitangent vectors is now off by default.
* The default Subsurface Model for PxrSurface has changed from "Jensen Dipole" to
"Exponential Path Traced". If you would like to revert the default back to "Jensen Dipole",
you can create an override json file for PxrSurface. The json file would look something like this:

{
"name": "PxrSurface.args",
"params": [
{
"name": "subsurfaceType",
"default": 0,
"always_write": true
}
]
}
See Customizing Blender in the docs on how to install this override file.

* The clapboard icon in the viewport will now first display an option to either render in
the viewport or to "it"
* For float ramps, you can now select the interpolation type to be used
* You can now change the zoom factor for the Enhance operator in the addon preferences
* We now draw the texture map for gobo and cookie light filters, if the draw textured lights option
is turned on
* The External Rendering panel has been renamed to Batch Rendering
* We now use "it" for the preview image task for our batch render jobs, instead of "sho".
* Volumes are now added to the "global volume aggregate" by default. If you want to turn off this
behavior, turn off the "Global Volume Aggregate" checkbox on volume object properties.

Bug Fixes:
* Fixed issues with instancing using geometry nodes.
* Fixed issue where channels in the stylized output were in random order
* Fixed issue where the FOV was not correct when the camera sensor width was not default,
and viewport was in perspective mode
* Fixed issue where using the cookie or gobo light filters was slow in the viewport
* Fixed numerous issues with group nodes in the shader graph.
* Frame step setting should not be respected when batch rendering in RIB mode.
* Fixed issues with light linking when a light or an object are no longer in the scene.
* Fixed issue where normals and vectors were not editable in the shader graph.
* Fixed issue where the viewport render progress bar color was incorrect.
* "it" inspector was displaying the wrong min/max samples for IPR
* Various fixes for the package scene operator
* Fix the viewport drawing of gobo and cookie light filters
* Fixed a bug where UDIM textures from linked collections was not working


v24.4 April 22, 2022

Changes:
Expand Down

0 comments on commit 8805939

Please sign in to comment.