Skip to content

Commit 7f37abf

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 7f37abf

50 files changed

Lines changed: 856 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: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
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+
emission: tuple[float, float, float] | None = None,
47+
) -> Any:
48+
material = c4d.BaseMaterial(c4d.Mmaterial)
49+
material.SetName(name)
50+
51+
material[c4d.MATERIAL_USE_COLOR] = emission is None
52+
material[c4d.MATERIAL_USE_LUMINANCE] = emission is not None
53+
material[c4d.MATERIAL_USE_REFLECTION] = False
54+
55+
if emission is not None:
56+
peak = max(emission)
57+
if peak <= 0.0:
58+
raise ValueError("emission must contain at least one positive channel")
59+
material[c4d.MATERIAL_LUMINANCE_COLOR] = c4d.Vector(
60+
*(channel / peak for channel in emission)
61+
)
62+
material[c4d.MATERIAL_LUMINANCE_BRIGHTNESS] = peak
63+
material[c4d.MATERIAL_USE_SPECULAR] = False
64+
else:
65+
material[c4d.MATERIAL_COLOR_COLOR] = c4d.Vector(*color)
66+
material[c4d.MATERIAL_COLOR_BRIGHTNESS] = 1.0
67+
material[c4d.MATERIAL_COLOR_MODEL] = c4d.MATERIAL_COLOR_MODEL_ORENNAYAR
68+
material[c4d.MATERIAL_COLOR_ROUGHNESS] = roughness
69+
material[c4d.MATERIAL_USE_SPECULAR] = True
70+
material[c4d.MATERIAL_SPECULAR_MODE] = c4d.MATERIAL_SPECULAR_MODE_PLASTIC
71+
material[c4d.MATERIAL_SPECULAR_COLOR] = c4d.Vector(1.0)
72+
material[c4d.MATERIAL_SPECULAR_BRIGHTNESS] = 0.25
73+
material[c4d.MATERIAL_SPECULAR_WIDTH] = max(0.05, min(1.0, roughness))
74+
75+
doc.InsertMaterial(material)
76+
return material
77+
78+
79+
def _attach_material(obj: Any, material: Any) -> None:
80+
tag = c4d.TextureTag()
81+
tag.SetMaterial(material)
82+
obj.InsertTag(tag)
83+
84+
85+
def _add_cube(
86+
doc: Any,
87+
name: str,
88+
size: tuple[float, float, float],
89+
position: tuple[float, float, float],
90+
material: Any,
91+
*,
92+
rotation: tuple[float, float, float] = (0.0, 0.0, 0.0),
93+
fillet: float = 0.0,
94+
) -> Any:
95+
cube = c4d.BaseObject(c4d.Ocube)
96+
cube.SetName(name)
97+
cube[c4d.PRIM_CUBE_LEN] = c4d.Vector(*size)
98+
if fillet > 0.0:
99+
cube[c4d.PRIM_CUBE_DOFILLET] = True
100+
cube[c4d.PRIM_CUBE_FRAD] = fillet
101+
cube[c4d.PRIM_CUBE_SUBF] = 4
102+
cube.SetAbsPos(c4d.Vector(*position))
103+
cube.SetAbsRot(c4d.Vector(*(math.radians(value) for value in rotation)))
104+
_attach_material(cube, material)
105+
doc.InsertObject(cube)
106+
return cube
107+
108+
109+
def _point_at(obj: Any, target: tuple[float, float, float]) -> None:
110+
direction = c4d.Vector(*target) - obj.GetAbsPos()
111+
obj.SetAbsRot(c4d.utils.VectorToHPB(direction))
112+
113+
114+
def _add_omni_light(
115+
doc: Any,
116+
name: str,
117+
position: tuple[float, float, float],
118+
color: tuple[float, float, float],
119+
intensity: float,
120+
) -> None:
121+
light = c4d.BaseObject(c4d.Olight)
122+
light.SetName(name)
123+
light[c4d.LIGHT_TYPE] = c4d.LIGHT_TYPE_OMNI
124+
light[c4d.LIGHT_COLOR] = c4d.Vector(*color)
125+
light[c4d.LIGHT_BRIGHTNESS] = intensity
126+
light.SetAbsPos(c4d.Vector(*position))
127+
doc.InsertObject(light)
128+
129+
130+
def _build_geometry(doc: Any) -> None:
131+
backdrop = _physical_material(
132+
doc,
133+
"Light studio backdrop",
134+
(0.24, 0.27, 0.32),
135+
roughness=0.55,
136+
)
137+
floor = _physical_material(
138+
doc,
139+
"Neutral floor",
140+
(0.13, 0.15, 0.18),
141+
roughness=0.4,
142+
)
143+
orange = _physical_material(
144+
doc,
145+
"Orange",
146+
(0.95, 0.12, 0.025),
147+
roughness=0.24,
148+
)
149+
blue = _physical_material(
150+
doc,
151+
"Blue",
152+
(0.025, 0.34, 0.9),
153+
roughness=0.2,
154+
)
155+
green = _physical_material(
156+
doc,
157+
"Green",
158+
(0.035, 0.62, 0.18),
159+
roughness=0.32,
160+
)
161+
hdr_reference = _physical_material(
162+
doc,
163+
"HDR reference",
164+
(0.0, 0.0, 0.0),
165+
emission=(4.0, 3.2, 2.2),
166+
)
167+
168+
_add_cube(
169+
doc,
170+
"Backdrop",
171+
(1100, 620, 30),
172+
(0, 75, 390),
173+
backdrop,
174+
)
175+
_add_cube(
176+
doc,
177+
"Floor",
178+
(1100, 30, 800),
179+
(0, -155, 40),
180+
floor,
181+
fillet=6,
182+
)
183+
_add_cube(
184+
doc,
185+
"HDR reference bar",
186+
(420, 48, 18),
187+
(0, 225, 365),
188+
hdr_reference,
189+
fillet=5,
190+
)
191+
192+
sphere = c4d.BaseObject(c4d.Osphere)
193+
sphere.SetName("Orange sphere")
194+
sphere[c4d.PRIM_SPHERE_RAD] = 120
195+
sphere[c4d.PRIM_SPHERE_SUB] = 36
196+
sphere.SetAbsPos(c4d.Vector(-245, -20, 40))
197+
_attach_material(sphere, orange)
198+
doc.InsertObject(sphere)
199+
200+
_add_cube(
201+
doc,
202+
"Blue beveled cube",
203+
(205, 205, 205),
204+
(0, -35, 45),
205+
blue,
206+
rotation=(8, -20, 6),
207+
fillet=22,
208+
)
209+
210+
torus = c4d.BaseObject(c4d.Otorus)
211+
torus.SetName("Green torus")
212+
torus[c4d.PRIM_TORUS_OUTERRAD] = 125
213+
torus[c4d.PRIM_TORUS_INNERRAD] = 42
214+
torus[c4d.PRIM_TORUS_SEG] = 64
215+
torus[c4d.PRIM_TORUS_CSUB] = 24
216+
torus.SetAbsPos(c4d.Vector(245, -15, 55))
217+
torus.SetAbsRot(c4d.Vector(math.radians(72), math.radians(-8), math.radians(14)))
218+
_attach_material(torus, green)
219+
doc.InsertObject(torus)
220+
221+
_add_omni_light(
222+
doc,
223+
"Warm key light",
224+
(-340, 360, -360),
225+
(1.0, 0.92, 0.82),
226+
1.25,
227+
)
228+
_add_omni_light(
229+
doc,
230+
"Cool fill light",
231+
(380, 130, -220),
232+
(0.62, 0.78, 1.0),
233+
0.7,
234+
)
235+
_add_omni_light(
236+
doc,
237+
"Front fill light",
238+
(0, 25, -520),
239+
(1.0, 1.0, 1.0),
240+
0.3,
241+
)
242+
243+
camera = c4d.BaseObject(c4d.Ocamera)
244+
camera.SetName("OCIO studio camera")
245+
camera.SetAbsPos(c4d.Vector(0, 55, -1080))
246+
_point_at(camera, (0, 5, 70))
247+
camera[c4d.CAMERA_FOCUS] = 50.0
248+
doc.InsertObject(camera)
249+
doc.GetRenderBaseDraw().SetSceneCamera(camera)
250+
251+
252+
def build_ocio_scene(
253+
output_dir: str,
254+
scene_name: str,
255+
view_transform: int,
256+
) -> None:
257+
"""Build and save the shared Physical OCIO scene."""
258+
output_dir = os.path.abspath(output_dir)
259+
os.makedirs(output_dir, exist_ok=True)
260+
261+
doc = c4d.documents.GetActiveDocument()
262+
doc.Flush()
263+
doc[c4d.DOCUMENT_COLOR_MANAGEMENT] = c4d.DOCUMENT_COLOR_MANAGEMENT_OCIO
264+
doc[c4d.DOCUMENT_OCIO_PRESET] = c4d.DOCUMENT_OCIO_PRESET_ACES
265+
doc[c4d.DOCUMENT_OCIO_VIEW_TRANSFORM] = view_transform
266+
267+
_build_geometry(doc)
268+
269+
render_data = doc.GetActiveRenderData()
270+
_configure_physical_renderer(render_data)
271+
render_data[c4d.RDATA_XRES] = WIDTH
272+
render_data[c4d.RDATA_YRES] = HEIGHT
273+
render_data[c4d.RDATA_FRAMEFROM] = c4d.BaseTime(1, doc.GetFps())
274+
render_data[c4d.RDATA_FRAMETO] = c4d.BaseTime(1, doc.GetFps())
275+
render_data[c4d.RDATA_FORMAT] = c4d.FILTER_PNG
276+
render_data[c4d.RDATA_FORMATDEPTH] = c4d.RDATA_FORMATDEPTH_8
277+
render_data[c4d.RDATA_ALPHACHANNEL] = False
278+
render_data[c4d.RDATA_MULTIPASS_SAVEIMAGE] = False
279+
if hasattr(c4d, "RDATA_BAKE_OCIO_VIEW_TRANSFORM_RENDER"):
280+
render_data.GetDataInstance()[c4d.RDATA_BAKE_OCIO_VIEW_TRANSFORM_RENDER] = True
281+
282+
render_data[c4d.RDATA_PATH] = "renders/$prj"
283+
284+
scene_path = os.path.join(output_dir, scene_name)
285+
doc.SetDocumentPath(output_dir)
286+
doc.SetDocumentName(scene_name)
287+
if not c4d.documents.SaveDocument(
288+
doc,
289+
scene_path,
290+
c4d.SAVEDOCUMENTFLAGS_0,
291+
c4d.FORMAT_C4DEXPORT,
292+
):
293+
raise RuntimeError(f"Failed to save integration scene: {scene_path}")
294+
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)