Skip to content

Commit c54880c

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 c54880c

50 files changed

Lines changed: 872 additions & 44 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: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
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 _physical_material(
20+
doc: Any,
21+
name: str,
22+
color: tuple[float, float, float],
23+
*,
24+
roughness: float = 0.35,
25+
metalness: float = 0.0,
26+
emission: tuple[float, float, float] | None = None,
27+
) -> Any:
28+
material = c4d.BaseMaterial(c4d.Mmaterial)
29+
material.SetName(name)
30+
31+
material[c4d.MATERIAL_USE_COLOR] = emission is None
32+
material[c4d.MATERIAL_USE_LUMINANCE] = emission is not None
33+
material[c4d.MATERIAL_USE_REFLECTION] = False
34+
35+
if emission is not None:
36+
peak = max(emission)
37+
if peak <= 0.0:
38+
raise ValueError("emission must contain at least one positive channel")
39+
material[c4d.MATERIAL_LUMINANCE_COLOR] = c4d.Vector(
40+
*(channel / peak for channel in emission)
41+
)
42+
material[c4d.MATERIAL_LUMINANCE_BRIGHTNESS] = peak
43+
material[c4d.MATERIAL_USE_SPECULAR] = False
44+
else:
45+
material[c4d.MATERIAL_COLOR_COLOR] = c4d.Vector(*color)
46+
material[c4d.MATERIAL_COLOR_BRIGHTNESS] = 1.0
47+
material[c4d.MATERIAL_COLOR_MODEL] = c4d.MATERIAL_COLOR_MODEL_ORENNAYAR
48+
material[c4d.MATERIAL_COLOR_ROUGHNESS] = roughness
49+
material[c4d.MATERIAL_USE_SPECULAR] = True
50+
material[c4d.MATERIAL_SPECULAR_MODE] = (
51+
c4d.MATERIAL_SPECULAR_MODE_METAL
52+
if metalness >= 0.5
53+
else c4d.MATERIAL_SPECULAR_MODE_PLASTIC
54+
)
55+
material[c4d.MATERIAL_SPECULAR_COLOR] = (
56+
c4d.Vector(*color) if metalness >= 0.5 else c4d.Vector(1.0)
57+
)
58+
material[c4d.MATERIAL_SPECULAR_BRIGHTNESS] = 0.2 + (0.6 * metalness)
59+
material[c4d.MATERIAL_SPECULAR_WIDTH] = max(0.05, min(1.0, roughness))
60+
61+
doc.InsertMaterial(material)
62+
return material
63+
64+
65+
def _attach_material(obj: Any, material: Any) -> None:
66+
tag = c4d.TextureTag()
67+
tag.SetMaterial(material)
68+
obj.InsertTag(tag)
69+
70+
71+
def _add_cube(
72+
doc: Any,
73+
name: str,
74+
size: tuple[float, float, float],
75+
position: tuple[float, float, float],
76+
material: Any,
77+
*,
78+
rotation: tuple[float, float, float] = (0.0, 0.0, 0.0),
79+
fillet: float = 0.0,
80+
) -> Any:
81+
cube = c4d.BaseObject(c4d.Ocube)
82+
cube.SetName(name)
83+
cube[c4d.PRIM_CUBE_LEN] = c4d.Vector(*size)
84+
if fillet > 0.0:
85+
cube[c4d.PRIM_CUBE_DOFILLET] = True
86+
cube[c4d.PRIM_CUBE_FRAD] = fillet
87+
cube[c4d.PRIM_CUBE_SUBF] = 4
88+
cube.SetAbsPos(c4d.Vector(*position))
89+
cube.SetAbsRot(c4d.Vector(*(math.radians(value) for value in rotation)))
90+
_attach_material(cube, material)
91+
doc.InsertObject(cube)
92+
return cube
93+
94+
95+
def _point_at(obj: Any, target: tuple[float, float, float]) -> None:
96+
direction = c4d.Vector(*target) - obj.GetAbsPos()
97+
obj.SetAbsRot(c4d.utils.VectorToHPB(direction))
98+
99+
100+
def _add_area_light(
101+
doc: Any,
102+
name: str,
103+
position: tuple[float, float, float],
104+
target: tuple[float, float, float],
105+
color: tuple[float, float, float],
106+
intensity: float,
107+
size: tuple[float, float],
108+
) -> None:
109+
light = c4d.BaseObject(c4d.Olight)
110+
light.SetName(name)
111+
light[c4d.LIGHT_TYPE] = c4d.LIGHT_TYPE_AREA
112+
light[c4d.LIGHT_COLOR] = c4d.Vector(*color)
113+
light[c4d.LIGHT_BRIGHTNESS] = intensity
114+
light[c4d.LIGHT_SHADOWTYPE] = c4d.LIGHT_SHADOWTYPE_AREA
115+
light[c4d.LIGHT_AREADETAILS_SHAPE] = c4d.LIGHT_AREADETAILS_SHAPE_RECTANGLE
116+
light[c4d.LIGHT_AREADETAILS_SIZEX] = size[0]
117+
light[c4d.LIGHT_AREADETAILS_SIZEY] = size[1]
118+
light[c4d.LIGHT_AREADETAILS_SHOWINRENDER] = False
119+
light[c4d.LIGHT_AREADETAILS_SHOWINREFLECTION] = False
120+
light.SetAbsPos(c4d.Vector(*position))
121+
_point_at(light, target)
122+
doc.InsertObject(light)
123+
124+
125+
def _build_geometry(doc: Any) -> None:
126+
backdrop = _physical_material(
127+
doc,
128+
"Charcoal backdrop",
129+
(0.028, 0.035, 0.05),
130+
roughness=0.62,
131+
)
132+
floor = _physical_material(
133+
doc,
134+
"Neutral floor",
135+
(0.12, 0.13, 0.15),
136+
roughness=0.28,
137+
metalness=0.15,
138+
)
139+
orange = _physical_material(
140+
doc,
141+
"Burnished orange",
142+
(0.95, 0.09, 0.015),
143+
roughness=0.2,
144+
metalness=0.25,
145+
)
146+
cyan = _physical_material(
147+
doc,
148+
"Glossy cyan",
149+
(0.015, 0.42, 0.72),
150+
roughness=0.14,
151+
metalness=0.05,
152+
)
153+
magenta = _physical_material(
154+
doc,
155+
"Matte magenta",
156+
(0.72, 0.025, 0.2),
157+
roughness=0.48,
158+
)
159+
green = _physical_material(
160+
doc,
161+
"Metallic green",
162+
(0.025, 0.52, 0.13),
163+
roughness=0.24,
164+
metalness=0.7,
165+
)
166+
blue_emission = _physical_material(
167+
doc,
168+
"HDR blue strip",
169+
(0.0, 0.0, 0.0),
170+
emission=(0.02, 0.65, 6.0),
171+
)
172+
173+
_add_cube(
174+
doc,
175+
"Backdrop",
176+
(1300, 760, 30),
177+
(0, 90, 430),
178+
backdrop,
179+
)
180+
_add_cube(
181+
doc,
182+
"Floor",
183+
(1300, 30, 1050),
184+
(0, -210, 50),
185+
floor,
186+
fillet=8,
187+
)
188+
_add_cube(
189+
doc,
190+
"Diagonal HDR strip",
191+
(980, 24, 18),
192+
(0, 115, 395),
193+
blue_emission,
194+
rotation=(0, 0, -8),
195+
fillet=6,
196+
)
197+
198+
sphere = c4d.BaseObject(c4d.Osphere)
199+
sphere.SetName("Orange sphere")
200+
sphere[c4d.PRIM_SPHERE_RAD] = 150
201+
sphere[c4d.PRIM_SPHERE_SUB] = 48
202+
sphere.SetAbsPos(c4d.Vector(-285, -55, 45))
203+
_attach_material(sphere, orange)
204+
doc.InsertObject(sphere)
205+
206+
_add_cube(
207+
doc,
208+
"Cyan beveled cube",
209+
(225, 225, 225),
210+
(-35, -50, 60),
211+
cyan,
212+
rotation=(12, -24, 8),
213+
fillet=24,
214+
)
215+
216+
torus = c4d.BaseObject(c4d.Otorus)
217+
torus.SetName("Green torus")
218+
torus[c4d.PRIM_TORUS_OUTERRAD] = 150
219+
torus[c4d.PRIM_TORUS_INNERRAD] = 48
220+
torus[c4d.PRIM_TORUS_SEG] = 64
221+
torus[c4d.PRIM_TORUS_CSUB] = 24
222+
torus.SetAbsPos(c4d.Vector(285, -45, 75))
223+
torus.SetAbsRot(c4d.Vector(math.radians(78), math.radians(-10), math.radians(16)))
224+
_attach_material(torus, green)
225+
doc.InsertObject(torus)
226+
227+
pyramid = c4d.BaseObject(c4d.Opyramid)
228+
pyramid.SetName("Magenta pyramid")
229+
pyramid[c4d.PRIM_PYRAMID_LEN] = c4d.Vector(230, 285, 230)
230+
pyramid.SetAbsPos(c4d.Vector(115, 85, 205))
231+
pyramid.SetAbsRot(c4d.Vector(0, math.radians(24), math.radians(-5)))
232+
_attach_material(pyramid, magenta)
233+
doc.InsertObject(pyramid)
234+
235+
exposure_values = (0.18, 1.0, 4.0, 16.0)
236+
exposure_positions = (-300, -100, 100, 300)
237+
for value, x_position in zip(exposure_values, exposure_positions):
238+
swatch_material = _physical_material(
239+
doc,
240+
f"Exposure {value:g}",
241+
(0.0, 0.0, 0.0),
242+
emission=(value, value, value),
243+
)
244+
_add_cube(
245+
doc,
246+
f"Exposure swatch {value:g}",
247+
(118, 42, 18),
248+
(x_position, 285, 395),
249+
swatch_material,
250+
fillet=5,
251+
)
252+
253+
target = (0, 10, 80)
254+
_add_area_light(
255+
doc,
256+
"Warm key",
257+
(-430, 430, -360),
258+
target,
259+
(1.0, 0.68, 0.48),
260+
1.35,
261+
(430, 430),
262+
)
263+
_add_area_light(
264+
doc,
265+
"Cool fill",
266+
(470, 160, -220),
267+
target,
268+
(0.3, 0.62, 1.0),
269+
0.8,
270+
(340, 340),
271+
)
272+
_add_area_light(
273+
doc,
274+
"Magenta rim",
275+
(60, 440, 360),
276+
target,
277+
(1.0, 0.18, 0.45),
278+
0.6,
279+
(280, 280),
280+
)
281+
282+
camera = c4d.BaseObject(c4d.Ocamera)
283+
camera.SetName("OCIO studio camera")
284+
camera.SetAbsPos(c4d.Vector(0, 70, -1320))
285+
_point_at(camera, (0, 35, 90))
286+
camera[c4d.CAMERA_FOCUS] = 52.0
287+
doc.InsertObject(camera)
288+
doc.GetRenderBaseDraw().SetSceneCamera(camera)
289+
290+
291+
def build_ocio_scene(
292+
output_dir: str,
293+
scene_name: str,
294+
view_transform: int,
295+
) -> None:
296+
"""Build and save the shared Physical OCIO scene."""
297+
output_dir = os.path.abspath(output_dir)
298+
os.makedirs(output_dir, exist_ok=True)
299+
300+
doc = c4d.documents.GetActiveDocument()
301+
doc.Flush()
302+
doc[c4d.DOCUMENT_COLOR_MANAGEMENT] = c4d.DOCUMENT_COLOR_MANAGEMENT_OCIO
303+
doc[c4d.DOCUMENT_OCIO_PRESET] = c4d.DOCUMENT_OCIO_PRESET_ACES
304+
doc[c4d.DOCUMENT_OCIO_VIEW_TRANSFORM] = view_transform
305+
306+
_build_geometry(doc)
307+
308+
render_data = doc.GetActiveRenderData()
309+
render_data[c4d.RDATA_RENDERENGINE] = PHYSICAL_RENDERER_ID
310+
render_data[c4d.RDATA_XRES] = WIDTH
311+
render_data[c4d.RDATA_YRES] = HEIGHT
312+
render_data[c4d.RDATA_FRAMEFROM] = c4d.BaseTime(1, doc.GetFps())
313+
render_data[c4d.RDATA_FRAMETO] = c4d.BaseTime(1, doc.GetFps())
314+
render_data[c4d.RDATA_FORMAT] = c4d.FILTER_PNG
315+
render_data[c4d.RDATA_FORMATDEPTH] = c4d.RDATA_FORMATDEPTH_8
316+
render_data[c4d.RDATA_ALPHACHANNEL] = False
317+
render_data[c4d.RDATA_MULTIPASS_SAVEIMAGE] = False
318+
if hasattr(c4d, "RDATA_BAKE_OCIO_VIEW_TRANSFORM_RENDER"):
319+
render_data.GetDataInstance()[c4d.RDATA_BAKE_OCIO_VIEW_TRANSFORM_RENDER] = True
320+
321+
render_data[c4d.RDATA_PATH] = "renders/$prj"
322+
323+
scene_path = os.path.join(output_dir, scene_name)
324+
doc.SetDocumentPath(output_dir)
325+
doc.SetDocumentName(scene_name)
326+
if not c4d.documents.SaveDocument(
327+
doc,
328+
scene_path,
329+
c4d.SAVEDOCUMENTFLAGS_0,
330+
c4d.FORMAT_C4DEXPORT,
331+
):
332+
raise RuntimeError(f"Failed to save integration scene: {scene_path}")
333+
c4d.EventAdd()
21.6 KB
Loading
960 Bytes
Loading
3.05 KB
Loading
4.64 KB
Loading
-341 Bytes
Loading
2.4 KB
Loading
3.97 KB
Loading

0 commit comments

Comments
 (0)