Texturas con Stable Diffusion para juegos indie
Generar tileables, normal maps y atlases con SDXL + ControlNet. Workflow indie sin contratar artista para placeholders y prototipos. Y dónde NO usarlo.
Publicado: · Por Juanjo "Banyo" López
0. Introducción
Eres un dev indie. Tienes un prototipo de dungeon crawler que necesita 80 texturas distintas: paredes, suelos, puertas, cofres, telas, metales. Contratar a un artista cuesta lo que no tienes; los packs de stock decentes pasan los 200 USD y los gratuitos repiten los mismos 10 stones que se ven en cien juegos de itch.io. Stable Diffusion abre una tercera puerta: generas las texturas tú, con prompts, en tu propia máquina.
No es una bala de plata. Es una herramienta con zona gris legal en algunos mercados (Steam exige disclosure de contenido generado por IA desde 2023, App Store tiene reglas más estrictas, ciertas plataformas directamente lo prohíben). Y la calidad va de “perfecto para un placeholder” a “necesita media hora en Photoshop para que se vea bien”. Conviene saber dónde aplica antes de meterte.
En este tutorial vas a ver:
- Qué workflow se usa hoy para generar texturas con SDXL + ControlNet.
- Cómo conseguir tileables reales (SD no los hace solo).
- Cómo pasar de un albedo plano a un material PBR completo en Unity.
1. Demo
2. Concepto y workflow
Stable Diffusion es un modelo open source de generación de imágenes texto→imagen. Con prompts cuidados, modelos finetuneados y ControlNet, puedes generar texturas usables para juego indie. Calidad: variable; control: alto con la herramienta correcta.
El pipeline completo va de un prompt a un material PBR importado en Unity. Mira el flujo de alto nivel antes de entrar en cada pieza:
Prompt → SDXL+ControlNet → albedo crudo → tileable post-process → maps PBR → Unity. Cada caja produce el input de la siguiente.
2.1 ¿Cuándo SÍ y cuándo NO usar SD para texturas de juego?
Honestidad antes que entusiasmo. Hay casos en los que esto te salva un mes; hay otros en los que te mete en un lío.
SÍ tiene sentido cuando:
- Estás en prototipo o vertical slice. Necesitas algo decente en pantalla rápido.
- Eres solo-indie sin presupuesto para artista, publicas en plataformas que lo permiten y estás dispuesto a declararlo.
- Generas mood boards o referencias para pasárselas después a un artista humano.
- Necesitas variaciones masivas (50 piedras distintas para un sembrado de detalles).
NO lo uses cuando:
- Apuntas a App Store / Apple Arcade, o a plataformas con políticas estrictas sobre IA generativa.
- Tu juego tiene presupuesto para arte y tu marca depende de un estilo único y reconocible.
- El asset es hero (la espada legendaria, la cara del protagonista). Eso lo hace una persona.
- Trabajas con clientes/publishers que exigen contrato limpio de derechos de cada asset.
2.2 SD 1.5 vs SDXL vs Flux: ¿cuál uso?
No hay “el mejor modelo”. Hay el modelo que cabe en tu VRAM y se ajusta a lo que necesitas.
| Modelo | VRAM mínima | Calidad | Velocidad | Licencia |
|---|---|---|---|---|
| SD 1.5 | 4 GB | Aceptable, viejo | Rápida | RAIL (uso comercial permitido) |
| SDXL | 12 GB | Buena | Media | OpenRAIL |
| Flux Dev | 24 GB | Excelente | Lenta | Non-commercial sin licencia |
Recomendación práctica para textura indie: SDXL en una RTX 3060 12GB o superior. Flux Dev se ve mejor, pero su licencia base no autoriza uso comercial; tendrías que pasar a Flux Schnell (Apache 2.0) o pagar licencia. SD 1.5 sigue siendo válido si tu hardware es modesto y aceptas perder algo de detalle.
2.3 ¿Cómo conseguir texturas tileables?
Stable Diffusion no genera tileables por defecto. Si pegas la imagen cruda en un plano y la repites, vas a ver costuras donde se encuentran los bordes. Tres caminos:
- Extensión “Tileable” en Automatic1111 / Forge: modifica las convoluciones del modelo durante la generación para que los bordes “cierren”. Resultado: 70% de éxito; a veces salen tileables limpios, a veces siguen mostrando costura.
- Post-process manual con offset: generas la textura normal, la desplazas 50% horizontal y 50% vertical (la costura ahora queda en el centro), y la curas con clone stamp en Photoshop / GIMP / Krita. Funciona casi siempre. Toma 5-10 minutos por textura.
- Modelos finetuneados específicos (búscalos en Civitai con tag “tileable”): entrenados sobre texturas tileables. Mejor calidad de base, menos limpieza posterior.
Diagrama del problema del tile:
Imagen cruda con costura escondida en los bordes → offset 50% trae la costura al centro → clone stamp la elimina y la textura ya tilea.
2.4 ControlNet para consistencia entre tiles
Si tienes un tileset (paredes que conectan con suelos, baldosas con bordes específicos), necesitas que las texturas mantengan composición y dirección de iluminación. Generar 12 piedras sueltas te da 12 estilos distintos. ControlNet te deja forzar la estructura.
Modos útiles para texturas:
- Canny / Lineart: pasas un sketch de bordes; SD respeta la silueta.
- Depth: das un mapa de profundidad burdo; SD respeta el relieve.
- Tile: variante específica que mantiene coherencia al regenerar regiones de una textura grande.
Esto es lo que separa “8 texturas que parecen del mismo juego” de “8 texturas que parecen de 8 juegos distintos”.
2.5 De color map a PBR completo
SD genera un albedo (color base). Para un material PBR en Unity necesitas además normal, roughness y, opcionalmente, AO y height. Opciones:
- Estimadores desde albedo: herramientas como Materialize (gratuito), Substance Sampler, o nodos en Blender que infieren normal y roughness a partir del color. Calidad: aceptable, no perfecta. Para placeholder sobra.
- Modelos especializados: Marigold estima depth desde una imagen RGB con resultados muy decentes; ese depth lo conviertes en normal con un bake.
- Manual en Substance Designer / Photoshop: máxima calidad. Más tiempo.
Para indie en prototipo, el flujo Materialize (albedo → normal + roughness + AO + height) en dos minutos por textura suele ser suficiente.
2.6 ¿Cómo se escribe un prompt para textura de juego?
El prompt para textura no es el prompt para arte conceptual. Las diferencias:
- Vista cenital o frontal plana:
top-down viewofront view, flat. No quieres perspectiva. - Sin iluminación:
no shadows, no lighting, flat lighting, evenly lit. El shader pondrá luz; si la textura ya trae sombras, se ven dobles. - Material y resolución:
4k texture, PBR albedo, seamless, tileable. - Negativos:
--no people, characters, watermark, signature, vignette, depth of field.
Ejemplo completo para una textura de muro de musgo y piedra:
seamless tileable texture of moss covering ancient stone wall,
top-down orthographic view, evenly lit, no shadows, no lighting,
PBR albedo base color map, 4k, high detail, photorealistic
--no people, watermark, signature, vignette, frame
2.7 Upscaling y limpieza final
SDXL genera nativo a 1024×1024. Si necesitas 2K o 4K (para macro shots, terreno grande), usa un upscaler:
- ESRGAN / Real-ESRGAN: clásico, rápido, gratis. Bueno para texturas.
- SUPIR: más nuevo, calidad superior, lento y caro en VRAM.
- Latent upscale en SDXL: combina upscaling con re-difusión; preserva detalle.
Después del upscale, siempre una pasada de Photoshop / Krita para eliminar artefactos (líneas, manchas, repeticiones), ajustar contraste y, si toca, desaturar levemente (los outputs de SD tienden a saturar de más).
2.8 ¿Qué documentar para no tener problemas legales o de marca?
Esto importa más de lo que parece. Mantén un registro por textura:
- Modelo y versión usado (SDXL base 1.0, LoRA Tile-Pack v3, etc.).
- Prompt completo y prompt negativo.
- Seed (si quieres reproducibilidad) y parámetros (steps, CFG, sampler).
- Post-procesos aplicados (offset, healing, upscale, Photoshop manual).
- Decisión final: ¿se usa en el juego? ¿En qué nivel/material?
Esto te sirve para disclosure en Steam, para responder si alguien pregunta, y para regenerar variaciones consistentes. Si planeas un estilo propio, entrena un LoRA sobre tus propias referencias o sketches: el modelo aprende tu paleta y tus formas, y deja de salirte “el look genérico de SDXL”.
3. Pseudocódigo
El flujo no es un programa: es una secuencia de comandos CLI más un par de pasos manuales. Esto es lo que harías por textura, asumiendo Automatic1111 / ComfyUI / cli wrapper equivalente:
# 1. Generar 8 candidatas con la misma seed base
sdxl-cli "seamless tileable stone wall texture, top-down, evenly lit, \
no shadows, PBR albedo, 4k, photorealistic" \
--negative "people, watermark, signature, vignette, frame" \
--width 1024 --height 1024 \
--steps 30 --cfg 7 --sampler dpmpp_2m \
--seed 42 --count 8 \
--out generated/stone_wall/
# 2. Filtrar visualmente. Elegir 1-2 candidatas. Borrar el resto.
# 3. Post-process tileable: offset 50% y heal seams
imagemagick convert stone_wall_03.png -roll +512+512 stone_wall_03_offset.png
# Abrir en Photoshop/GIMP. Clone stamp sobre la costura visible. Exportar.
# 4. Generar maps PBR desde el albedo
materialize-cli --input stone_wall_03_final.png \
--output stone_wall_03 \
--normal-strength 8 \
--roughness-mode invert-luminance \
--ao yes --height yes
# 5. Upscale opcional a 2K
realesrgan -i stone_wall_03_final.png -o stone_wall_03_2k.png -s 2
# 6. Copiar a Assets/Generated/stone_wall/ en el proyecto Unity.
# El importer del editor (sección 4) toma desde ahí.
Opcionalmente, un script Python orquesta todo el pipeline desde el prompt hasta los maps PBR. Esa orquestación es lo que vende el asset; el flujo manual te da el control fino que necesitas en producción.
4. Implementación en Unity / C#
El cuello de botella en Unity no es generar la textura: es importarla bien. Si dejas los settings por defecto, tus normales se ven mal (Unity las trata como sRGB por error), tus tileables no repiten (wrap mode equivocado) y tus mipmaps se ven borrosas. Un editor script automatiza todo.
using System.IO;
using UnityEditor;
using UnityEngine;
public static class AITextureImporter {
const string SourceFolder = "Assets/Generated/";
[MenuItem("Tools/AI Textures/Import from Generated Folder")]
public static void ImportAll() {
var paths = Directory.GetFiles(SourceFolder, "*.png", SearchOption.AllDirectories);
foreach (var path in paths) {
var importer = AssetImporter.GetAtPath(path) as TextureImporter;
if (importer == null) continue;
var name = Path.GetFileNameWithoutExtension(path).ToLowerInvariant();
ConfigureImporter(importer, name);
importer.SaveAndReimport();
}
// Tras reimportar, agrupar por prefijo y construir materiales PBR
BuildMaterials(paths);
AssetDatabase.Refresh();
}
static void ConfigureImporter(TextureImporter importer, string name) {
importer.wrapMode = TextureWrapMode.Repeat; // tileables, siempre
importer.mipmapEnabled = true;
importer.filterMode = FilterMode.Trilinear;
importer.anisoLevel = 4;
if (name.EndsWith("_normal")) {
importer.textureType = TextureImporterType.NormalMap;
importer.sRGBTexture = false;
} else if (name.EndsWith("_roughness") || name.EndsWith("_ao") || name.EndsWith("_height")) {
importer.textureType = TextureImporterType.Default;
importer.sRGBTexture = false; // datos lineales, no color
} else {
importer.textureType = TextureImporterType.Default;
importer.sRGBTexture = true; // albedo va en sRGB
}
}
static void BuildMaterials(string[] paths) {
// Agrupa por prefijo (ej: "stone_wall_03") y crea un Material URP/Lit
// asignando _BaseMap, _BumpMap, _MetallicGlossMap, _OcclusionMap.
// Implementación omitida por brevedad — el asset la trae completa.
}
}
5. En otros engines
- Godot: editor plugin con
@toolscript. Leesres://generated/, aplicasimport_optionspor sufijo (normal map →compress/normal_map = ENABLED), generas unStandardMaterial3Dprogramáticamente. Misma idea, otra API. - Unreal: Python scripting en el Editor (
unreal.AssetTools,unreal.TextureFactory). Importas, marcasCompressionSettings = TC_Normalmappara las normales, construyes elMaterialInstance. Más verboso pero las decisiones son idénticas. - JS / web (Three.js, Babylon): no hay “import pipeline”; cargas las texturas con
TextureLoader, asignastexture.wrapS = wrapT = RepeatWrappingy montas elMeshStandardMaterial. Lo que cambia es solo el destino: el workflow de generación es agnóstico al engine.
La parte que cambia entre engines son los flags de import y la API del material. El workflow (generar → tileable → maps PBR → import) no cambia.
6. Quiz
Pon a prueba lo que entendiste
Responde una por una. La explicación aparece al elegir, correcta o no.
Tu textura se ve perfecta como imagen suelta pero al aplicarla en un plano repetido en Unity se ve una costura clarísima. ¿Qué te falta?
Tu juego apunta a App Store / Apple Arcade. ¿Es viable montar el arte con Stable Diffusion?
Generaste el albedo con SDXL. ¿Qué te falta para tener un material PBR usable en Unity?
¿Por qué conviene fijar la seed cuando generas texturas con Stable Diffusion?