Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: Color management for Houdini workfiles #5858

Closed
wants to merge 53 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
c2f2fdb
add workfile colorspace to Houdini settings
MustafaJafar Nov 2, 2023
bf32236
add Houdini workfile colorspace to Ayon settings
MustafaJafar Nov 2, 2023
fca6abd
add Houdini SetDefaultDislayView prelaunch hook
MustafaJafar Nov 2, 2023
10cf562
resolve hound
MustafaJafar Nov 2, 2023
537d1ac
BigRoy's comments - Better logging & remove unnecessary logic
MustafaJafar Nov 2, 2023
3ffbf73
resolve hound
MustafaJafar Nov 2, 2023
1a1e48e
BigRoy's comment - update variable name
MustafaJafar Nov 2, 2023
7d80da8
BigRoy's Comment - fix typo
MustafaJafar Nov 2, 2023
cd4d8bd
BigRoy's comment - better doc string
MustafaJafar Nov 3, 2023
b7336e1
Merge branch 'develop' into enhancement/OP-1017_houdini-colorspaces
MustafaJafar Nov 3, 2023
5a269ab
Merge branch 'enhancement/OP-1017_houdini-colorspaces' of https://git…
MustafaJafar Nov 3, 2023
0a8e293
bump patch version
MustafaJafar Nov 3, 2023
a32f0a6
use 'review color space' setting in review creator
MustafaJafar Nov 6, 2023
0eacab2
update houdini workfile color settings
MustafaJafar Nov 6, 2023
c4cd10c
use houdini color settings while review creation and validation
MustafaJafar Nov 6, 2023
1eb82e1
Merge branch 'develop' into enhancement/OP-1017_houdini-colorspaces
MustafaJafar Nov 6, 2023
2caac26
Resolve Hound
MustafaJafar Nov 6, 2023
8de9dcc
update doc string
MustafaJafar Nov 6, 2023
9684978
bump Houdini addon patch version
MustafaJafar Nov 6, 2023
dadddfb
Minkiu comment - remove unnecessary variable
MustafaJafar Nov 7, 2023
a1d1c49
fabia's comment - Better conditional
MustafaJafar Nov 7, 2023
83089da
update set_review_color_space() and get_houdini_color_settings() logic
MustafaJafar Nov 7, 2023
f349df0
undo adding unnecessary setting
MustafaJafar Nov 7, 2023
fd64850
add colorspace data to houdini review extractor
MustafaJafar Nov 8, 2023
205c064
BigRoy's comment - use a conditional
MustafaJafar Nov 8, 2023
7a62d5d
add colorspace data to houdini image sequence extractor
MustafaJafar Nov 9, 2023
251291a
append existent view and display env vars
MustafaJafar Nov 12, 2023
38bf9c1
resolve hound
MustafaJafar Nov 12, 2023
87dc8ca
fix a typo
MustafaJafar Nov 13, 2023
a7e2267
BigRoy's comment - Cleaner env var values
MustafaJafar Nov 13, 2023
a823676
update houdini workfile colorsettings help
MustafaJafar Nov 13, 2023
cb9e22e
resolve hound
MustafaJafar Nov 13, 2023
ebc3d95
BigRoy's suggestion - Better help text
MustafaJafar Nov 13, 2023
1fadecf
Merge branch 'develop' into enhancement/OP-1017_houdini-colorspaces
MustafaJafar Nov 13, 2023
be6d015
BigRoy's suggestion - Better help text, Ayon settings
MustafaJafar Nov 13, 2023
d3362eb
bump houdini addon version
MustafaJafar Nov 13, 2023
cc70c7b
Merge branch 'develop' into enhancement/OP-1017_houdini-colorspaces
MustafaJafar Nov 17, 2023
0c3ff0f
Fabia's Comments
MustafaJafar Nov 17, 2023
b328812
Merge branch 'develop' into enhancement/OP-1017_houdini-colorspaces
MustafaJafar Nov 23, 2023
e45df04
Jeza Comment - Better Labels
MustafaJafar Nov 23, 2023
ab04429
BigRoy's comment - add settings tip
MustafaJafar Nov 24, 2023
ba10409
Merge branch 'develop' into enhancement/OP-1017_houdini-colorspaces
MustafaJafar Dec 11, 2023
1bdbf35
Merge branch 'develop' into enhancement/OP-1017_houdini-colorspaces
MustafaJafar Dec 14, 2023
c40b713
bump houdini addon version
MustafaJafar Dec 14, 2023
fccfb22
Merge branch 'develop' into enhancement/OP-1017_houdini-colorspaces
MustafaJafar Jan 3, 2024
b8f89e1
♻️ Minkiu Comment - refactor repeated code into a method
MustafaJafar Jan 3, 2024
71fe47d
🦴 Resolve Hound
MustafaJafar Jan 3, 2024
ec6a8b2
➖ Remove unnecessary function
MustafaJafar Jan 5, 2024
10cdd11
🐾 Resolve Hound
MustafaJafar Jan 5, 2024
eb123e1
🐾 Resolve Hound
MustafaJafar Jan 5, 2024
05948a9
🐾 Resolve Hound
MustafaJafar Jan 5, 2024
9245fd9
Merge branch 'develop' into enhancement/OP-1017_houdini-colorspaces
MustafaJafar Jan 16, 2024
75b6dfe
bump Houdini addon version
MustafaJafar Jan 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 42 additions & 0 deletions openpype/hosts/houdini/api/lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,48 @@ def get_current_context_template_data_with_asset_data():
return template_data


def set_review_color_space(opengl_node, review_color_space="", log=None):
"""Set ociocolorspace parameter for the given OpenGL node.

Set `ociocolorspace` parameter of the given OpenGl node
to to the given review_color_space value.
If review_color_space is empty, a default colorspace corresponding to
the display & view of the current Houdini session will be used.

Args:
opengl_node (hou.Node): ROP node to set its ociocolorspace parm.
review_color_space (str): Colorspace value for ociocolorspace parm.
log (logging.Logger): Logger to log to.
"""

if log is None:
log = self.log

# Set Color Correction parameter to OpenColorIO
colorcorrect_parm = opengl_node.parm("colorcorrect")
if colorcorrect_parm.eval() != 2:
colorcorrect_parm.set(2)
log.debug(
"'Color Correction' parm on '{}' has been set to"
" 'OpenColorIO'".format(opengl_node.path())
)

# fall to default review color space if the setting is empty.
if not review_color_space:
from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace # noqa
review_color_space = get_default_display_view_colorspace()

opengl_node.setParms(
{"ociocolorspace": review_color_space}
)

self.log.debug(
"'OCIO Colorspace' parm on '{}' has been set to "
"the view color space '{}'"
.format(opengl_node, review_color_space)
)


def get_context_var_changes():
"""get context var changes."""

Expand Down
58 changes: 58 additions & 0 deletions openpype/hosts/houdini/hooks/set_default_display_and_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from openpype.lib.applications import PreLaunchHook, LaunchTypes


class SetDefaultDisplayView(PreLaunchHook):
"""Set default view and default display for houdini via OpenColorIO.

Houdini's defaultDisplay and defaultView are set by
setting 'OCIO_ACTIVE_DISPLAYS' and 'OCIO_ACTIVE_VIEWS'
environment variables respectively.

More info: https://www.sidefx.com/docs/houdini/io/ocio.html#set-up
"""

app_groups = {"houdini"}
launch_types = {LaunchTypes.local}

def execute(self):

OCIO = self.launch_context.env.get("OCIO")

# This is a cheap way to skip this hook if either global color
# management or houdini color management was disabled because the
# OCIO var would be set by the global OCIOEnvHook
if not OCIO:
return

houdini_color_settings = \
MustafaJafar marked this conversation as resolved.
Show resolved Hide resolved
self.data["project_settings"]["houdini"]["imageio"]["workfile"]

if not houdini_color_settings["enabled"]:
self.log.info(
"Houdini workfile color management is disabled."
)
return

# 'OCIO_ACTIVE_DISPLAYS', 'OCIO_ACTIVE_VIEWS' are checked
# as Admins can add them in Ayon env vars or Ayon tools.

MustafaJafar marked this conversation as resolved.
Show resolved Hide resolved
default_display = houdini_color_settings["default_display"]
if default_display:
# get 'OCIO_ACTIVE_DISPLAYS' value if exists.
self._set_context_env("OCIO_ACTIVE_DISPLAYS", default_display)

default_view = houdini_color_settings["default_view"]
if default_view:
# get 'OCIO_ACTIVE_VIEWS' value if exists.
self._set_context_env("OCIO_ACTIVE_VIEWS", default_view)

def _set_context_env(self, env_var, default_value):
env_value = self.launch_context.env.get(env_var, "")
new_value = ":".join(
key for key in [default_value, env_value] if key
)
self.log.info(
"Setting {} environment to: {}"
.format(env_var, new_value)
)
self.launch_context.env[env_var] = new_value
37 changes: 15 additions & 22 deletions openpype/hosts/houdini/plugins/create/create_review.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""Creator plugin for creating openGL reviews."""
from openpype.hosts.houdini.api import plugin
from openpype.lib import EnumDef, BoolDef, NumberDef

from openpype.hosts.houdini.api.lib import set_review_color_space
import os
import hou

Expand All @@ -14,6 +14,11 @@ class CreateReview(plugin.HoudiniCreator):
label = "Review"
family = "review"
icon = "video-camera"
workfile_color_settings = {}

def apply_settings(self, project_settings):
super(CreateReview, self).apply_settings(project_settings)
self.workfile_color_settings = project_settings["houdini"]["imageio"]["workfile"] # noqa

def create(self, subset_name, instance_data, pre_create_data):

Expand Down Expand Up @@ -87,7 +92,15 @@ def create(self, subset_name, instance_data, pre_create_data):
# Set OCIO Colorspace to the default output colorspace
# if there's OCIO
if os.getenv("OCIO"):
self.set_colorcorrect_to_default_view_space(instance_node)
workfile_color_settings = self.project_settings["houdini"]["imageio"]["workfile"] # noqa
review_color_space = workfile_color_settings["enabled"] and \
workfile_color_settings["review_color_space"]

set_review_color_space(
instance_node,
review_color_space,
log=self.log)


to_lock = ["id", "family"]

Expand Down Expand Up @@ -130,23 +143,3 @@ def get_pre_create_attr_defs(self):
minimum=0.0001,
decimals=3)
]

def set_colorcorrect_to_default_view_space(self,
instance_node):
"""Set ociocolorspace to the default output space."""
from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace # noqa

# set Color Correction parameter to OpenColorIO
instance_node.setParms({"colorcorrect": 2})

# Get default view space for ociocolorspace parm.
default_view_space = get_default_display_view_colorspace()
instance_node.setParms(
{"ociocolorspace": default_view_space}
)

self.log.debug(
"'OCIO Colorspace' parm on '{}' has been set to "
"the default view color space '{}'"
.format(instance_node, default_view_space)
)
15 changes: 11 additions & 4 deletions openpype/hosts/houdini/plugins/publish/extract_composite.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import hou


class ExtractComposite(publish.Extractor):
class ExtractComposite(publish.Extractor,
publish.ColormanagedPyblishPluginMixin):

order = pyblish.api.ExtractorOrder
label = "Extract Composite (Image Sequence)"
Expand Down Expand Up @@ -45,8 +46,14 @@ def process(self, instance):
"frameEnd": instance.data["frameEndHandle"],
}

from pprint import pformat

self.log.info(pformat(representation))
if ext == "exr":
# Inject colorspace with 'scene_linear' as that's the
# default Houdini working colorspace and all extracted
# OpenEXR images should be in that colorspace.
# https://www.sidefx.com/docs/houdini/render/linear.html#image-formats
self.set_representation_colorspace(
representation, instance.context,
colorspace="scene_linear"
)

instance.data["representations"].append(representation)
11 changes: 10 additions & 1 deletion openpype/hosts/houdini/plugins/publish/extract_opengl.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
import hou


class ExtractOpenGL(publish.Extractor):
class ExtractOpenGL(publish.Extractor,
publish.ColormanagedPyblishPluginMixin):

order = pyblish.api.ExtractorOrder - 0.01
label = "Extract OpenGL"
Expand Down Expand Up @@ -46,6 +47,14 @@ def process(self, instance):
"camera_name": instance.data.get("review_camera")
}

if ropnode.evalParm("colorcorrect") == 2: # OpenColorIO enabled
colorspace = ropnode.evalParm("ociocolorspace")
# inject colorspace data
self.set_representation_colorspace(
representation, instance.context,
colorspace=colorspace
)

if "representations" not in instance.data:
instance.data["representations"] = []
instance.data["representations"].append(representation)
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
)
from openpype.pipeline.publish import RepairAction
from openpype.hosts.houdini.api.action import SelectROPAction
from openpype.hosts.houdini.api.lib import set_review_color_space

import os
import hou


class SetDefaultViewSpaceAction(RepairAction):
label = "Set default view colorspace"
class SetReviewColorSpaceAction(RepairAction):
label = "Set Default Review Color Space"
icon = "mdi.monitor"


Expand All @@ -27,7 +28,7 @@ class ValidateReviewColorspace(pyblish.api.InstancePlugin,
families = ["review"]
hosts = ["houdini"]
label = "Validate Review Colorspace"
actions = [SetDefaultViewSpaceAction, SelectROPAction]
actions = [SetReviewColorSpaceAction, SelectROPAction]

optional = True

Expand Down Expand Up @@ -61,30 +62,42 @@ def process(self, instance):
.format(rop_node.path())
)

workfile_color_settings = instance.context.data["project_settings"]["houdini"]["imageio"]["workfile"] # noqa
# skip if houdini workfile color settings are disabled
if workfile_color_settings["enabled"]:
review_color_space = workfile_color_settings["review_color_space"]

# skip if review color space setting is empty.
if review_color_space and \
rop_node.evalParm("ociocolorspace") != review_color_space:

raise PublishValidationError(
"Invalid value: Colorspace name doesn't match studio "
"settings.\nCheck 'OCIO Colorspace' parameter on '{}' ROP"
.format(rop_node.path())
)

@classmethod
def repair(cls, instance):
"""Set Default View Space Action.
"""Set Default Review Space Action.

It is a helper action more than a repair action,
used to set colorspace on opengl node to the default view.
"""
from openpype.hosts.houdini.api.colorspace import get_default_display_view_colorspace # noqa
It sets ociocolorspace parameter.

rop_node = hou.node(instance.data["instance_node"])
If workfile settings are enabled, it will use the value
exposed in the settings.

if rop_node.evalParm("colorcorrect") != 2:
rop_node.setParms({"colorcorrect": 2})
cls.log.debug(
"'Color Correction' parm on '{}' has been set to"
" 'OpenColorIO'".format(rop_node.path())
)
If the value exposed in the settings is empty,
it will use the default colorspace corresponding to
the display & view of the current Houdini session.
"""

opengl_node = hou.node(instance.data["instance_node"])

# Get default view colorspace name
default_view_space = get_default_display_view_colorspace()
workfile_color_settings = instance.context.data["project_settings"]["houdini"]["imageio"]["workfile"] # noqa
review_color_space = workfile_color_settings["enabled"] and \
workfile_color_settings["review_color_space"]

rop_node.setParms({"ociocolorspace": default_view_space})
cls.log.info(
"'OCIO Colorspace' parm on '{}' has been set to "
"the default view color space '{}'"
.format(rop_node, default_view_space)
)
set_review_color_space(
opengl_node,
review_color_space,
log=cls.log)
6 changes: 6 additions & 0 deletions openpype/settings/defaults/project_settings/houdini.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
"file_rules": {
"activate_host_rules": false,
"rules": {}
},
"workfile":{
"enabled": false,
"default_display": "ACES",
"default_view": "sRGB",
"review_color_space": ""
MustafaJafar marked this conversation as resolved.
Show resolved Hide resolved
}
},
"shelves": [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,39 @@
{
"type": "template",
"name": "template_host_color_management_ocio"
},
{
"key": "workfile",
"type": "dict",
"label": "Workfile",
"collapsible": true,
"checkbox_key": "enabled",
"children": [
{
"type": "boolean",
"key": "enabled",
"label": "Enabled"
},
{
"type": "label",
"label": "Empty values will be skipped, allowing any existing env vars to pass through as defined.\nNote: The render space in Houdini is always set to the 'scene_linear' role."
},
{
"type": "text",
"key": "default_display",
"label": "Default active displays"
},
{
"type": "text",
"key": "default_view",
"label": "Default active views"
},
{
"type": "text",
"key": "review_color_space",
"label": "Review colorspace"
}
]
}
]
},
Expand Down