Ernesto Del Valle M.

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.


Project maintained by 3dvm Hosted on GitHub Pages — Theme by mattgraham

Case Study: Art-Driven Render Pipeline (Historias Nativas)

โ† 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.



1. The Problem: Art Direction vs. Farm Downtime

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.

2. The Solution: Autonomous QA & Headless Mutation

To eliminate GUI overhead and human intervention, I engineered a headless rendering framework driven by Bash and executed via Blenderโ€™s Python API (bpy).

  1. Asset Centralization: A headless Python script automatically iterated through bpy.data.libraries to batch-migrate hundreds of shots to a centralized libs/ directory structure without opening the GUI.
  2. Automated Sanity Check (QA): An OS-level script scans the output directories against the original sceneโ€™s length, mathematically detecting missing frames and writing them to a state-tracking manifest (omit.list).
  3. Headless Orchestration: The core Bash script parses the manifest and launches Blender in strict background mode (-b), actively intercepting the initialization sequence to inject custom Python configuration payloads.
flowchart TD %% QA & Sanity Check Phase A[๐Ÿ“ Master Scene .blend] --> Z{๐Ÿ” render_qa_checker.py} Z -->|Scans PNGs vs Scene length| C[(๐Ÿ“„ omit.list log)] %% Orchestration Phase A --> B{โš™๏ธ render_missing_passes.sh} subgraph Orchestration [Bash Render Orchestration] B <-->|Reads Status| C B -->|If Env pass missing| D[Blender + setup_environment_pass.py] B -->|If Char pass missing| E[Blender + setup_character_pass.py] end subgraph Mutation [Python API Mutation - Headless] D -.->|Overrides| F[Anti-Aliasing: ON
Motion Blur: OFF
Z-Mask: OFF] E -.->|Overrides| G[Anti-Aliasing: OFF
Motion Blur: ON
Z-Mask: ON] end F --> H[๐Ÿ–ผ๏ธ Environment Sequence] G --> I[๐Ÿ–ผ๏ธ Character Sequence] H --> J((๐ŸŽฌ Final Compositing)) I --> J %% Styling classDef bash fill:#4EAA25,stroke:#fff,stroke-width:2px,color:#fff; classDef python fill:#3776AB,stroke:#fff,stroke-width:2px,color:#fff; classDef file fill:#E26F25,stroke:#fff,stroke-width:2px,color:#fff; class B bash; class Z,D,E python; class A,C file;

3. Impact & Pipeline Metrics


4. Code Architecture Snapshot

(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


โ† Back to Main Portfolio

Ernesto Del Valle Macuare Pipeline TD & Technical Artist
๐Ÿ”— LinkedIn ๐Ÿ”— GitHub ๐Ÿ“ง edelvallemacuare@gmail.com