Skip to content

Commit 76c05cd

Browse files
committed
fix: Fix the color tone for tile rendering.
Signed-off-by: Karthik Bekal Pattathana <133984042+karthikbekalp@users.noreply.github.com>
1 parent 0364064 commit 76c05cd

50 files changed

Lines changed: 835 additions & 62 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/deadline/cinema4d_adaptor/Cinema4DClient/tile_rendering.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -228,13 +228,16 @@ def finalize_tile_render(
228228
render_data: The render data object (to restore output paths).
229229
frame: The current frame number.
230230
"""
231-
# Restore the OCIO bake flag to its original value
232-
if ctx.orig_bake_flag is not None:
233-
rd[c4d.RDATA_BAKE_OCIO_VIEW_TRANSFORM_RENDER] = ctx.orig_bake_flag
234-
235-
if ctx.requires_baking:
236-
baked = c4d.documents.BakeOcioViewToBitmap(bm, rd, c4d.SAVEBIT_NONE)
237-
bm = baked or bm
231+
try:
232+
if ctx.requires_baking:
233+
# setup_tile_render disabled the render-time bake. It must remain
234+
# disabled here or BakeOcioViewToBitmap assumes the bitmap was
235+
# already baked and returns None.
236+
baked = c4d.documents.BakeOcioViewToBitmap(bm, rd, c4d.SAVEBIT_NONE)
237+
bm = baked or bm
238+
finally:
239+
if ctx.orig_bake_flag is not None:
240+
rd[c4d.RDATA_BAKE_OCIO_VIEW_TRANSFORM_RENDER] = ctx.orig_bake_flag
238241

239242
if c4d.GetC4DVersion() >= C4D_VERSION_2025_2:
240243
bm.SetColorProfile(c4d.bitmaps.ColorProfile(), c4d.COLORPROFILE_INDEX_DISPLAYSPACE)

test/integ/fixtures/auto_open_submitter/AutoOpenSubmitter.pyp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Where the submitter's AWS calls go depends on the test mode:
3232
3333
The test then drives the resulting Qt dialog with xa11y.
3434
"""
35+
3536
import os
3637
import traceback
3738

@@ -201,6 +202,11 @@ def _load_active_scene(scene_path):
201202
c4d.documents.InsertBaseDocument(doc)
202203
c4d.documents.SetActiveDocument(doc)
203204
c4d.EventAdd()
205+
if doc.GetChanged():
206+
# The fixture was just generated and saved. Older C4D versions
207+
# can mark Redshift node materials changed while loading them.
208+
doc[c4d.DOCUMENT_USERCHANGE] = False
209+
_diag("cleared generated scene changed state after load")
204210
_diag("scene loaded and set as active")
205211
else:
206212
_diag(f"LoadDocument returned None for {scene_path}")

test/integ/ocio_scene.py

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
"""Shared Physical OCIO studio scene for Cinema 4D integration tests."""
3+
4+
from __future__ import annotations
5+
6+
import math
7+
import os
8+
from typing import Any
9+
10+
import c4d
11+
12+
WIDTH = 384
13+
HEIGHT = 216
14+
ACES_DEFAULT_VIEW_TRANSFORM = 0
15+
ACES_UNTONE_MAPPED_VIEW_TRANSFORM = 3
16+
PHYSICAL_RENDERER_ID = 1023342
17+
18+
19+
def _configure_physical_renderer(render_data: Any) -> None:
20+
"""Use fixed sampling so repeated renders produce stable image baselines."""
21+
render_data[c4d.RDATA_RENDERENGINE] = PHYSICAL_RENDERER_ID
22+
23+
physical_settings = render_data.GetFirstVideoPost()
24+
while physical_settings is not None:
25+
if physical_settings.GetType() == PHYSICAL_RENDERER_ID:
26+
break
27+
physical_settings = physical_settings.GetNext()
28+
29+
if physical_settings is None:
30+
physical_settings = c4d.documents.BaseVideoPost(PHYSICAL_RENDERER_ID)
31+
if physical_settings is None:
32+
raise RuntimeError("Failed to create Physical renderer settings")
33+
render_data.InsertVideoPostLast(physical_settings)
34+
35+
physical_settings[c4d.VP_XMB_RAYTRACING_SAMPLER] = c4d.VP_XMB_RAYTRACING_SAMPLER_FIXED
36+
physical_settings[c4d.VP_XMB_RAYTRACING_QUALITY] = c4d.VP_XMB_RAYTRACING_QUALITY_CUSTOM
37+
physical_settings[c4d.VP_XMB_RAYTRACING_SAMPLES] = 4.0
38+
39+
40+
def _physical_material(
41+
doc: Any,
42+
name: str,
43+
color: tuple[float, float, float],
44+
*,
45+
roughness: float = 0.35,
46+
specular_brightness: float = 0.0,
47+
emission: tuple[float, float, float] | None = None,
48+
) -> Any:
49+
material = c4d.BaseMaterial(c4d.Mmaterial)
50+
material.SetName(name)
51+
52+
material[c4d.MATERIAL_USE_COLOR] = emission is None
53+
material[c4d.MATERIAL_USE_LUMINANCE] = emission is not None
54+
material[c4d.MATERIAL_USE_REFLECTION] = False
55+
56+
if emission is not None:
57+
peak = max(emission)
58+
if peak <= 0.0:
59+
raise ValueError("emission must contain at least one positive channel")
60+
material[c4d.MATERIAL_LUMINANCE_COLOR] = c4d.Vector(
61+
*(channel / peak for channel in emission)
62+
)
63+
material[c4d.MATERIAL_LUMINANCE_BRIGHTNESS] = peak
64+
material[c4d.MATERIAL_USE_SPECULAR] = False
65+
else:
66+
material[c4d.MATERIAL_COLOR_COLOR] = c4d.Vector(*color)
67+
material[c4d.MATERIAL_COLOR_BRIGHTNESS] = 1.0
68+
material[c4d.MATERIAL_COLOR_MODEL] = c4d.MATERIAL_COLOR_MODEL_ORENNAYAR
69+
material[c4d.MATERIAL_COLOR_ROUGHNESS] = roughness
70+
material[c4d.MATERIAL_USE_SPECULAR] = specular_brightness > 0.0
71+
if specular_brightness > 0.0:
72+
material[c4d.MATERIAL_SPECULAR_MODE] = c4d.MATERIAL_SPECULAR_MODE_PLASTIC
73+
material[c4d.MATERIAL_SPECULAR_COLOR] = c4d.Vector(1.0)
74+
material[c4d.MATERIAL_SPECULAR_BRIGHTNESS] = specular_brightness
75+
material[c4d.MATERIAL_SPECULAR_WIDTH] = max(0.05, min(1.0, roughness))
76+
77+
doc.InsertMaterial(material)
78+
return material
79+
80+
81+
def _attach_material(obj: Any, material: Any) -> None:
82+
tag = c4d.TextureTag()
83+
tag.SetMaterial(material)
84+
obj.InsertTag(tag)
85+
86+
87+
def _add_cube(
88+
doc: Any,
89+
name: str,
90+
size: tuple[float, float, float],
91+
position: tuple[float, float, float],
92+
material: Any,
93+
*,
94+
rotation: tuple[float, float, float] = (0.0, 0.0, 0.0),
95+
fillet: float = 0.0,
96+
) -> Any:
97+
cube = c4d.BaseObject(c4d.Ocube)
98+
cube.SetName(name)
99+
cube[c4d.PRIM_CUBE_LEN] = c4d.Vector(*size)
100+
if fillet > 0.0:
101+
cube[c4d.PRIM_CUBE_DOFILLET] = True
102+
cube[c4d.PRIM_CUBE_FRAD] = fillet
103+
cube[c4d.PRIM_CUBE_SUBF] = 2
104+
cube.SetAbsPos(c4d.Vector(*position))
105+
cube.SetAbsRot(c4d.Vector(*(math.radians(value) for value in rotation)))
106+
_attach_material(cube, material)
107+
doc.InsertObject(cube)
108+
return cube
109+
110+
111+
def _point_at(obj: Any, target: tuple[float, float, float]) -> None:
112+
direction = c4d.Vector(*target) - obj.GetAbsPos()
113+
obj.SetAbsRot(c4d.utils.VectorToHPB(direction))
114+
115+
116+
def _add_omni_light(
117+
doc: Any,
118+
name: str,
119+
position: tuple[float, float, float],
120+
color: tuple[float, float, float],
121+
intensity: float,
122+
) -> None:
123+
light = c4d.BaseObject(c4d.Olight)
124+
light.SetName(name)
125+
light[c4d.LIGHT_TYPE] = c4d.LIGHT_TYPE_OMNI
126+
light[c4d.LIGHT_COLOR] = c4d.Vector(*color)
127+
light[c4d.LIGHT_BRIGHTNESS] = intensity
128+
light.SetAbsPos(c4d.Vector(*position))
129+
doc.InsertObject(light)
130+
131+
132+
def _build_geometry(doc: Any) -> None:
133+
backdrop = _physical_material(
134+
doc,
135+
"Neutral backdrop",
136+
(0.28, 0.32, 0.36),
137+
roughness=0.6,
138+
)
139+
floor = _physical_material(
140+
doc,
141+
"Neutral floor",
142+
(0.12, 0.14, 0.16),
143+
roughness=0.55,
144+
)
145+
orange = _physical_material(
146+
doc,
147+
"Saturated orange",
148+
(1.0, 0.08, 0.015),
149+
roughness=0.32,
150+
specular_brightness=0.15,
151+
)
152+
blue = _physical_material(
153+
doc,
154+
"Saturated blue",
155+
(0.015, 0.34, 1.0),
156+
roughness=0.28,
157+
specular_brightness=0.12,
158+
)
159+
hdr_reference = _physical_material(
160+
doc,
161+
"HDR reference",
162+
(0.0, 0.0, 0.0),
163+
emission=(4.0, 2.8, 1.6),
164+
)
165+
166+
_add_cube(
167+
doc,
168+
"Backdrop",
169+
(1100, 620, 30),
170+
(0, 75, 390),
171+
backdrop,
172+
)
173+
_add_cube(
174+
doc,
175+
"Floor",
176+
(1100, 30, 800),
177+
(0, -155, 40),
178+
floor,
179+
)
180+
_add_cube(
181+
doc,
182+
"HDR reference bar",
183+
(420, 48, 18),
184+
(0, 225, 365),
185+
hdr_reference,
186+
fillet=5,
187+
)
188+
189+
sphere = c4d.BaseObject(c4d.Osphere)
190+
sphere.SetName("Orange sphere")
191+
sphere[c4d.PRIM_SPHERE_RAD] = 132
192+
sphere[c4d.PRIM_SPHERE_SUB] = 32
193+
sphere.SetAbsPos(c4d.Vector(-165, -15, 35))
194+
_attach_material(sphere, orange)
195+
doc.InsertObject(sphere)
196+
197+
_add_cube(
198+
doc,
199+
"Blue beveled cube",
200+
(235, 235, 235),
201+
(145, -25, 45),
202+
blue,
203+
rotation=(5, -18, 4),
204+
fillet=14,
205+
)
206+
207+
_add_omni_light(
208+
doc,
209+
"Warm key light",
210+
(-320, 340, -360),
211+
(1.0, 0.9, 0.78),
212+
1.15,
213+
)
214+
_add_omni_light(
215+
doc,
216+
"Cool fill light",
217+
(360, 160, -260),
218+
(0.58, 0.76, 1.0),
219+
0.55,
220+
)
221+
222+
camera = c4d.BaseObject(c4d.Ocamera)
223+
camera.SetName("OCIO studio camera")
224+
camera.SetAbsPos(c4d.Vector(0, 55, -1080))
225+
_point_at(camera, (0, 0, 65))
226+
camera[c4d.CAMERA_FOCUS] = 50.0
227+
doc.InsertObject(camera)
228+
doc.GetRenderBaseDraw().SetSceneCamera(camera)
229+
230+
231+
def build_ocio_scene(
232+
output_dir: str,
233+
scene_name: str,
234+
view_transform: int,
235+
) -> None:
236+
"""Build and save the shared Physical OCIO scene."""
237+
output_dir = os.path.abspath(output_dir)
238+
os.makedirs(output_dir, exist_ok=True)
239+
240+
doc = c4d.documents.GetActiveDocument()
241+
doc.Flush()
242+
doc[c4d.DOCUMENT_COLOR_MANAGEMENT] = c4d.DOCUMENT_COLOR_MANAGEMENT_OCIO
243+
doc[c4d.DOCUMENT_OCIO_PRESET] = c4d.DOCUMENT_OCIO_PRESET_ACES
244+
doc[c4d.DOCUMENT_OCIO_VIEW_TRANSFORM] = view_transform
245+
246+
_build_geometry(doc)
247+
248+
render_data = doc.GetActiveRenderData()
249+
_configure_physical_renderer(render_data)
250+
render_data[c4d.RDATA_XRES] = WIDTH
251+
render_data[c4d.RDATA_YRES] = HEIGHT
252+
render_data[c4d.RDATA_FRAMEFROM] = c4d.BaseTime(1, doc.GetFps())
253+
render_data[c4d.RDATA_FRAMETO] = c4d.BaseTime(1, doc.GetFps())
254+
render_data[c4d.RDATA_FORMAT] = c4d.FILTER_PNG
255+
render_data[c4d.RDATA_FORMATDEPTH] = c4d.RDATA_FORMATDEPTH_8
256+
render_data[c4d.RDATA_ALPHACHANNEL] = False
257+
render_data[c4d.RDATA_MULTIPASS_SAVEIMAGE] = False
258+
if hasattr(c4d, "RDATA_BAKE_OCIO_VIEW_TRANSFORM_RENDER"):
259+
render_data.GetDataInstance()[c4d.RDATA_BAKE_OCIO_VIEW_TRANSFORM_RENDER] = True
260+
261+
render_data[c4d.RDATA_PATH] = "renders/$prj"
262+
263+
scene_path = os.path.join(output_dir, scene_name)
264+
doc.SetDocumentPath(output_dir)
265+
doc.SetDocumentName(scene_name)
266+
if not c4d.documents.SaveDocument(
267+
doc,
268+
scene_path,
269+
c4d.SAVEDOCUMENTFLAGS_0,
270+
c4d.FORMAT_C4DEXPORT,
271+
):
272+
raise RuntimeError(f"Failed to save integration scene: {scene_path}")
273+
c4d.EventAdd()
17.1 KB
Loading
1.79 KB
Loading
5.24 KB
Loading
2.97 KB
Loading
-777 Bytes
Loading
498 Bytes
Loading
3.13 KB
Loading

0 commit comments

Comments
 (0)