Technical Art portfolio bridging code architecture with artist-friendly environments. Includes Python pipeline automation, headless rendering scripts, and procedural Geometry Nodes setups. Built to eliminate bottlenecks and scale 3D workflows in Blender.
| โ Back to Home | ๐ View Full Repository on GitHub |
The "Painting with Polygons" effect: A complex, art-driven result requiring strict Render Layer separation and dynamic scene mutation at render time.
In stylized animation pipelines, splitting scenes into rendering passes (e.g., Backgrounds vs. Characters) requires drastically different DCC settings to achieve specific visual goals. Characters required motion blur to drive vector displacement, while backgrounds required raytracing without blur.
Additionally, the project suffered from asset duplication, where character and prop libraries were copied locally into every episodeโs folder. Relying on artists to manually resolve broken library links, toggle engine settings, and route compositing nodes before submitting to the render farm guaranteed human error, broken dependencies, and massive downtime.
To eliminate GUI overhead and human intervention, I engineered a headless rendering framework driven by Bash and executed via Blenderโs Python API (bpy).
bpy.data.libraries to batch-migrate hundreds of shots to a centralized libs/ directory structure without opening the GUI.omit.list).-b), actively intercepting the initialization sequence to inject custom Python configuration payloads.cut -d" ") surgically injects -s 150 -e 300 into the command line, preventing re-rendering of completed sequences.(A snippet of the Python injection payload used to configure the Character Pass. It utilizes historical API syntax compliant with Blender 2.75 (Python 3.4) to isolate Render Layers with Z-masking and audit the Compositing tree).
import bpy
# 1. Pipeline-Specific Render Settings (Character Pass)
bpy.context.scene.render.use_antialiasing = False
bpy.context.scene.render.use_motion_blur = True
bpy.context.scene.render.use_raytrace = False
# 2. Dynamic Output Path Generation based on File Data
filename = bpy.path.display_name_from_filepath(bpy.data.filepath)
base_path = "//../../render/" + filename[0:2] + "/" + filename[0:5] + "_personaje/"
bpy.context.scene.render.filepath = base_path
# 3. Z-Masking & Render Layer Logic
for layer in bpy.context.scene.render.layers[1:]:
layer.use = True
for m in range(20):
layer.layers_zmask[m] = False # Reset masks
# Activate Z-mask specifically for the background holdout layer
layer.layers_zmask[6] = True
# 4. Compositing Node Tree Audit
if bpy.context.scene.use_nodes:
tree = bpy.context.scene.node_tree
for node in tree.nodes:
if 'File' in node.name:
if 'fondo' in node.base_path:
node.mute = True # Mute background outputs
elif 'personaje' in node.base_path:
node.base_path = base_path
| Ernesto Del Valle Macuare | Pipeline TD & Technical Artist |
| ๐ LinkedIn | ๐ GitHub | ๐ง edelvallemacuare@gmail.com |