---
name: comfyui_build_parallax_background_workflow
kind: function
lang: py
domain: ml
version: "1.0.0"
purity: pure
signature: "def comfyui_build_parallax_background_workflow(scene: str, *, style: str = \"game background, side-scroller, parallax layers, detailed, no characters\", layers: int = 3, checkpoint: str = \"IMG_dreamshaper_8.safetensors\", negative: str = \"character, person, foreground object, text, watermark, blurry, low quality\", depth_node: str = \"DepthAnythingV2Preprocessor\", depth_model: str = \"depth_anything_v2_vitl.pth\", depth_resolution: int = 512, width: int = 1024, height: int = 512, seed: int = 0, steps: int = 28, cfg: float = 7.0, sampler_name: str = \"dpmpp_2m\", scheduler: str = \"karras\", filename_prefix: str = \"parallax_bg\") -> dict"
description: "Construye el dict (API format) de un workflow ComfyUI para un FONDO DE JUEGO EN CAPAS de parallax 2.5D (side-scroller/plataformas): genera un fondo apaisado con txt2img y estima su MAPA DE PROFUNDIDAD con DepthAnythingV2Preprocessor, guardando ambos PNG (fondo + depth). La separacion en N bandas por rango de profundidad es post-proceso (gap: split_parallax_layers). Compone comfyui_build_txt2img_workflow. Pura, sin red ni I/O. class_types verificados contra /object_info."
tags: [comfyui, ml, gamedev-2d, parallax, background, depth, side-scroller, workflow, stable-diffusion]
uses_functions: [comfyui_build_txt2img_workflow_py_ml]
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
params:
  - name: scene
    desc: "Descripcion de la escena del fondo (ej. 'forest at dusk, fantasy', 'ruined city skyline'). No puede estar vacio."
  - name: style
    desc: "Estilo/encuadre que se concatena a la escena. Por defecto fuerza look de fondo apaisado side-scroller sin personajes. keyword-only."
  - name: layers
    desc: "Numero de capas de profundidad a derivar del depth map en post-proceso (cielo/lejano/medio/frente). Debe ser >= 2. NO genera nodos: se refleja en el filename del depth map para trazabilidad. keyword-only."
  - name: checkpoint
    desc: "Checkpoint base. Default 'IMG_dreamshaper_8.safetensors' (SD1.5 holgado en 8GB). keyword-only."
  - name: negative
    desc: "Prompt negativo. Por defecto evita personajes/props en primer plano que rompen un fondo limpio por capas. keyword-only."
  - name: depth_node
    desc: "class_type del preprocessor de profundidad. Default 'DepthAnythingV2Preprocessor'. Alternativa con misma firma: 'DepthAnythingPreprocessor'. Para MiDaS/Zoe (sin ckpt_name) el builder omite ckpt_name. keyword-only."
  - name: depth_model
    desc: "Peso del depth_node (enum depth_anything_v2_*). Default vitl (buena calidad, cabe en 8GB). Solo aplica a DepthAnything*. keyword-only."
  - name: depth_resolution
    desc: "Resolucion interna del preprocessor de profundidad. keyword-only."
  - name: width
    desc: "Ancho en px (multiplo de 8). Default 1024 (formato apaisado de parallax). keyword-only."
  - name: height
    desc: "Alto en px (multiplo de 8). Default 512. keyword-only."
  - name: seed
    desc: "Semilla del KSampler. keyword-only."
  - name: steps
    desc: "Pasos del KSampler. keyword-only."
  - name: cfg
    desc: "CFG del KSampler. keyword-only."
  - name: sampler_name
    desc: "Sampler del KSampler. keyword-only."
  - name: scheduler
    desc: "Scheduler del KSampler. keyword-only."
  - name: filename_prefix
    desc: "Prefijo del PNG del fondo en output/. El depth map usa '<filename_prefix>_depth_<layers>L'. keyword-only."
output: "dict en API format listo para comfyui_submit_workflow: txt2img base (fondo apaisado) + un SaveImage para el fondo, mas un nodo de profundidad (depth_node) que toma el IMAGE del VAEDecode y un segundo SaveImage para el depth map. Dos imagenes de salida: el fondo y su mapa de profundidad."
example: "wf = comfyui_build_parallax_background_workflow('forest at dusk, fantasy', layers=4, seed=7)"
file_path: python/functions/ml/comfyui_build_parallax_background_workflow.py
tested: true
tests: ["test_golden_background_plus_depth", "test_edge_scene_style_reflected_in_prompt", "test_edge_layers_reflected_in_depth_filename", "test_edge_dims_reflected_in_latent", "test_edge_alt_depth_node_no_ckpt", "test_error_empty_scene", "test_error_layers_below_two", "test_purity_deterministic_and_no_global_state"]
test_file_path: python/functions/ml/comfyui_build_parallax_background_workflow_test.py
---

Construye el dict (API format) de un workflow ComfyUI para un **fondo de juego en
capas** orientado a parallax 2.5D (side-scroller / plataformas). En lugar de
intentar separar las capas dentro del grafo (caro y fragil), produce las dos
piezas que el motor necesita para el parallax:

1. **El fondo apaisado** (txt2img) — la escena completa, formato ancho típico de un
   nivel de plataformas.
2. **Su mapa de profundidad** (`DepthAnythingV2Preprocessor` sobre el IMAGE del
   `VAEDecode`) — escala de grises donde el brillo codifica la distancia.

Con el fondo + el depth map, derivar N capas por rango de profundidad
(cielo / fondo lejano / plano medio / frente) es un post-proceso de numpy: umbralar
el depth en `layers` bandas y recortar el fondo con cada máscara a un PNG RGBA. Ese
split es un **gap documentado** (`split_parallax_layers`, aún no creada), no este
builder.

Cableado (verificado contra `/object_info` de ComfyUI 0.26.0):

```
CheckpointLoaderSimple -> ... -> KSampler -> VAEDecode --IMAGE--+-> SaveImage (fondo)
                                                                 `-> DepthAnythingV2Preprocessor -> SaveImage (depth)
```

## Ejemplo

```python
import sys, os
sys.path.insert(0, os.path.join("python", "functions"))
from ml.comfyui_build_parallax_background_workflow import comfyui_build_parallax_background_workflow

# Fondo apaisado + su mapa de profundidad, 4 bandas de parallax (función pura, sin red).
wf = comfyui_build_parallax_background_workflow("forest at dusk, fantasy", layers=4, seed=7)

# El dict API format trae DOS SaveImage: el fondo y el depth map. Encólalo con submit_workflow.
saves = [n for n in wf.values() if n.get("class_type") == "SaveImage"]
print(len(saves), "SaveImage (fondo + depth)")   # 2
```

## Cuando usarla

Cuando necesites el fondo de un nivel 2D con scroll parallax y quieras las capas
por profundidad. Genera el fondo + el depth en una sola pasada, y deja que el
post-proceso corte las bandas. Sube `layers` para más planos de profundidad
(3-5 es lo habitual). Para texturas tileables del propio fondo (suelos, muros que
se repiten) usa `comfyui_build_seamless_tile_workflow`; para props/edificios iso,
`comfyui_build_isometric_workflow`.

## Gotchas

- **Función pura: no valida contra el server.** Si `depth_node` o su peso no están
  instalados, ComfyUI devuelve HTTP 400 al enviar. Verifica con
  `comfyui_object_info` (o `curl /object_info`) que `DepthAnythingV2Preprocessor`
  existe (lo está). Alternativa con misma firma: `DepthAnythingPreprocessor`. Para
  `MiDaS-DepthMapPreprocessor` / `Zoe-DepthMapPreprocessor` (sin `ckpt_name`) pásalo
  como `depth_node` y el builder omite `ckpt_name` automáticamente.
- **El peso de DepthAnything se descarga on-demand** al primer uso (controlnet_aux
  baja `depth_anything_v2_vitl.pth` ~335 MB desde HF). Requiere red la primera vez;
  luego queda cacheado. Para arranque más ligero usa `depth_model="depth_anything_v2_vits.pth"`.
- **`layers` NO genera nodos.** Solo se refleja en el filename del depth map
  (`<prefix>_depth_<N>L`). El número real de capas se materializa en el post-proceso
  del split, no en este grafo.
- **SD1.5 a 1024x512** (apaisado) puede repetir elementos; si aparecen, baja a
  768x384 o usa un checkpoint SDXL. Para 8GB lowvram, 1024x512 SD1.5 + DepthAnything
  vitl caben sin OOM (se ejecutan secuencialmente, no a la vez).
- **GAP: `split_parallax_layers`** (numpy) aún no existe — segmentaría el depth en
  `layers` bandas y recortaría el fondo a N PNG RGBA. Hasta entonces el split es
  manual o se hace en el motor.

## Capability growth log

(sin cambios — v1.0.0)
