CommunityImagegithub.com

TraX22/blender-low-poly

Construit des modèles et scènes stylisés low-poly dans Blender via une connexion Blender (le serveur officiel BlenderLab) – formes facettées et angulaires avec peu de polygones, ombrage plat, une petite palette de couleurs de matériaux unis, des proportions exagérées et l'éclairage doux dont le style a besoin. Utilisez-la lorsque l'utilisateur demande des modèles low-poly, facettés, stylisés, cartoon ou de style jeu (une maison, un arbre, un rocher, un terrain, un véhicule, un accessoire, un diorama) ou souhaite qu'un modèle ressemble à une image de référence low-poly.

Qu'est-ce que blender-low-poly ?

Cette compétence spécialisée pour agents IA (comme Claude Code) permet de créer des modèles 3D low-poly stylisés directement dans Blender, en utilisant le serveur officiel BlenderLab. Elle se distingue par une approche artistique où le faible nombre de polygones n'est pas une limitation technique mais un parti pris esthétique : formes angulaires bombées, ombrage plat, palette de couleurs réduite avec des matériaux unis, proportions exagérées et éclairage doux. L'agent exploite les outils `blenderlab_…` pour inspecter la scène (résumé des objets, capture d'écran 3D), exécuter du code Python arbitraire dans Blender, et exporter les modèles aux formats glTF ou FBX. Le flux de travail est guidé par neuf règles stylistiques strictes (ombrage plat, faible nombre de segments, pas de biseau ni de subdivision, couleurs unies, palette délibérée, proportions exagérées, imperfections aléatoires mais reproductibles, détails par petites pièces séparées, intersections autorisées). L'agent doit suivre un processus itératif : blocage des masses, création de la palette, ajout de la structure puis des détails, rugosification, éclairage, et enfin validation automatique avec la fonction `final_check` qui compare le rendu à l'image de référence. Pour assembler efficacement de nombreux blocs (pierres, tuiles, briques) en un seul objet, la fonction utilitaire `lp_blocks` est fournie. Des budgets de triangles sont donnés pour chaque type d'asset, et un guide d'éclairage spécifique (soleil + monde, transform Standard) assure le rendu final. La compétence s'appuie sur les compétences `blender-modeling`, `blender-materials-render` et `blender-game-export` pour les aspects connexes.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/TraX22/HydraOps-Skills/tree/HEAD/blender-low-poly

Installed? Explore more Image skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Modélisation low-poly dans Blender

Le low poly est un style, pas seulement un faible nombre de triangles : de grandes formes lisibles, des facettes plates visibles, une poignée de couleurs unies, et des proportions un peu poussées au-delà de la réalité. Un modèle réaliste avec moins de polygones n'est pas low-poly ; c'est un modèle réaliste grossier.

La boucle de travail générale (regarder la scène, planifier en parties, une partie par appel, capture d'écran après chaque étape, ne jamais supprimer ce que vous n'avez pas créé) se trouve dans la compétence blender-modeling : suivez-la. Cette compétence indique ce qui est différent pour le low poly.

Votre connexion Blender

Vous travaillez via BlenderLab, le serveur officiel du Blender Lab ; ses outils sont blenderlab_… :

  • Ce qui est dans la scène : get_objects_summary ; un objet en détail : get_object_detail_summary (par name). Le fichier, sauvegardé ou non, et son chemin : get_blendfile_summary_path_info.
  • Exécuter Python : execute_blender_code. Rien ne persiste entre les appels (transportez vos fonctions d'aide dans chaque script) ; ce que le script affiche est renvoyé, et un dictionnaire assigné à result est renvoyé comme données. Son garde-fou refuse quelques opérateurs (quitter Blender, réinitialisations d'usine).
  • Voir la vue 3D : get_screenshot_of_area_as_image avec area_ui_type: "VIEW_3D" (la fenêtre entière : get_screenshot_of_window_as_image) ; la pointer sur un objet : jump_to_view3d_object_by_name.
  • Consulter l'API Python : get_python_api_docs (un identifiant tel que bpy.types.BevelModifier), search_api_docs ; le manuel : search_manual_docs.
  • Rendu rapide : render_thumbnail_to_path, render_viewport_to_path ; l'image va dans le dossier temporaire de Blender et le résultat donne le vrai chemin.
  • Exporter : du code (bpy.ops.export_scene.gltf, bpy.ops.export_scene.fbx).
  • Bibliothèques d'actifs et générateurs 3D : aucun. Construisez l'objet, ou demandez à l'utilisateur un fichier à importer.

Si ces outils ne sont pas disponibles, arrêtez-vous et dites-le : l'utilisateur doit installer la connexion BlenderLab (Outils → Connexions), la donner à cet agent, et avoir Blender ouvert avec le serveur du module complémentaire démarré. Ne décrivez pas le travail comme terminé quand vous n'avez pas pu le faire.

Le style, en règles

  1. Ombrage plat partout. Chaque face est d'une seule couleur plate ; pas d'ombrage lisse, pas d'auto-lissage. C'est ce qui fait apparaître les facettes.
  2. Peu de segments, délibérément. Cylindres à 6-8 côtés, cônes à 5-6, sphères en icosphères avec 1-2 subdivisions. Un cylindre à 32 côtés gâche le look plus que tout autre chose.
  3. Pas de biseau, pas de surface de subdivision. Ils arrondissent les facettes. Pour un bord plus doux utilisez au maximum un chanfrein à un seul segment.
  4. Couleur unie, pas de textures. Un matériau par couleur, Principled BSDF avec Base Color, Rugosité 0.8-1.0, Métallique 0, pas d'éclat spéculaire. Réutilisez les matériaux : une scène entière en nécessite généralement 6 à 12.
  5. Une palette réfléchie. Choisissez-la avant la modélisation : 1-2 couleurs dominantes, 2-3 de soutien, 1 accent. Des demi-teintes légèrement désaturées, des tons chauds et froids équilibrés, et deux nuances de chaque couleur principale (claire et foncée) pour la variété entre les parties voisines.
  6. Proportions massives et exagérées. Murs, poutres et troncs plus épais que dans la réalité ; toits, portes et fenêtres surdimensionnés ; formes fuselées (plus larges à la base, ou au sommet pour un effet cartoon). Les parties fines disparaissent à ce niveau de détail.
  7. Imperfection à la main, en petites doses. Rien de parfaitement aligné : inclinez une cheminée de 2-4°, variez les tuiles de quelques pourcents de leur taille et de 2-3° d'inclinaison, déplacez les sommets des rochers et du terrain aléatoirement. La structure doit rester lisible : les rangées de tuiles restent des rangées, aucune pièce tournée sur le côté ou soulevée de la surface. Avec une graine aléatoire fixe, pour qu'une ré-exécution donne le même résultat.
  8. Détail par petites pièces séparées, pas par subdivision. Une fenêtre est un cadre de quatre boîtes plus un carreau ; les tuiles sont des rangées de petites dalles ; les pierres sont quelques blocs irréguliers encastrés dans le mur. Chaque pièce est simple ; l'agencement donne la richesse.
  9. Les pièces peuvent s'intersecter. Les parties low-poly sont poussées les unes dans les autres au lieu d'être soudées : une poutre s'enfonce dans un mur, un rocher dans le sol. Ne consacrez pas d'efforts aux booléens ou aux jonctions propres.

Flux de travail

  1. Lisez la référence, s'il y en a une : listez les pièces, comptez ce qui se répète (rangées de tuiles, nombre de poutres, fenêtres par mur), notez les proportions entre les pièces sous forme de ratios (hauteur du toit par rapport à la hauteur du mur, largeur par rapport à la hauteur), et nommez les couleurs de la palette. Construisez à partir de cette liste. L'image décide : ancrez une taille et déduisez le reste des ratios, n'inventez pas de tailles en mètres que l'image contredit, et n'ajoutez pas ce qu'elle ne montre pas (un socle, des accessoires) sauf si demandé.
  2. Blocage des grandes masses d'abord avec des boîtes et des coins aux bonnes proportions. Prenez une capture d'écran et comparez la silhouette : si la silhouette est mauvaise, les détails ne la sauveront pas.
  3. Palette : créez les matériaux une fois, nommés par ce qu'ils colorent (LP_Mur_Clair, LP_Toit_Rouge, LP_Bois_Foncé).
  4. Structure, puis pièces secondaires (poutres, cadres, cheminée, marches), puis petits détails (tuiles, pierres, planches, fissures), puis environnement (dalle de sol, quelques rochers, touffes d'herbe).
  5. Rugosification : les décalages et inclinaisons aléatoires de la règle 7.
  6. Éclairage et cadrage (ci-dessous), puis placez la vue à l'angle de la référence, capturez-la et comparez pièce par pièce : silhouette, proportions, emplacement de chaque pièce, couleurs. Corrigez.
  7. Terminez par final_check, le dernier appel de la tâche : la fonction est ci-dessous, dans "La vérification finale". Vous ne voyez pas vos rendus ; elle mesure le rendu pour vous (le modèle séparé du fond, par rapport à l'image de référence lorsque vous avez son nom de fichier) et imprime une ligne PROBLEME: pour ce qui ne va pas. Corrigez, exécutez-la à nouveau (deux tours au maximum) et mettez sa sortie dans le rapport. Les mesures que vous faites vous-même ne la remplacent pas : une tâche qui construit ou modifie un modèle n'est pas terminée tant que cette fonction n'a pas été exécutée.

Attendez-vous à deux ou trois tours de correction par rapport à la référence. Dites ce qui diffère encore.

Vous avez un nombre limité de tours d'outils par tâche (voir "Votre budget d'étapes" dans blender-modeling) : construisez deux ou trois pièces liées par appel, capturez aux jalons (blocage, détails, final) et mettez les pièces les plus visibles en premier.

Le code pour chaque recette se trouve dans references/low-poly-recipes.md : palette, ombrage plat, boîtes fuselées, toits à pignon, rangées de tuiles, fenêtres et portes, structures en bois, rochers, arbres, terrain, dispersion et configuration d'éclairage. Ouvrez-le avant le premier script.

Plusieurs blocs dans un seul objet

Les rangées de pierres, créneaux, pavés, planches et briques sont de nombreuses petites boîtes qui appartiennent à un seul objet. Construisez-les avec lp_blocks : elle termine chaque boîte dans son propre bmesh et seulement ensuite l'ajoute à l'objet. Ne joignez pas les boîtes en ajoutant manuellement des listes de sommets et de faces, et ne déplacez pas "les N derniers sommets" après une opération qui change leur nombre (un chanfrein le fait) : les faces se retrouvent sur les mauvais sommets et le modèle sort sous forme de pointes étirées. final_check nomme un objet cassé de cette façon ; reconstruisez-le, ne le signalez pas.

import bpy, bmesh
from mathutils import Matrix, Vector

def lp_blocks(name, col, mat, blocks, chamfer=0.03):
    """Plusieurs boîtes dans UN objet à ombrage plat. blocks est une liste de (centre, taille) ou
    (centre, taille, rotation_z) : centre et taille sont (x, y, z) en mètres, la rotation en radians.
    Chaque boîte est terminée dans son propre bmesh et seulement ensuite ajoutée à l'objet."""
    whole = bmesh.new()
    for center, size, *rot in blocks:
        bm = bmesh.new()
        bmesh.ops.create_cube(bm, size=1.0)
        bmesh.ops.scale(bm, vec=Vector(size), verts=bm.verts)
        if chamfer > 0:
            bmesh.ops.bevel(bm, geom=bm.edges[:], offset=min(chamfer, min(size) * 0.25), segments=1, affect='EDGES')
        bmesh.ops.transform(bm, matrix=Matrix.Translation(Vector(center)) @ Matrix.Rotation(rot[0] if rot else 0.0, 4, 'Z'), verts=bm.verts)
        piece = bpy.data.meshes.new("_piece")
        bm.to_mesh(piece)
        bm.free()
        whole.from_mesh(piece)                                   # ajoute la boîte terminée au maillage de l'objet
        bpy.data.meshes.remove(piece)
    mesh = bpy.data.meshes.new(name)
    whole.to_mesh(mesh)
    whole.free()
    for poly in mesh.polygons:
        poly.use_smooth = False
    obj = bpy.data.objects.get(name)
    if obj is None:
        obj = bpy.data.objects.new(name, mesh)
        col.objects.link(obj)
    else:
        obj.data = mesh
    obj.data.materials.append(mat)
    return obj

# Une rangée de pierres de mur, alternant deux tailles, dans un seul objet.
col = bpy.data.collections["LP_Model"]
pierre = bpy.data.materials["LP_Pierre_Clair"]
lp_blocks("Rangée_Mur_01", col, pierre,
          [((x * 0.42 - 1.26, -1.0, 0.35), (0.40 if x % 2 else 0.36, 0.20, 0.30)) for x in range(7)])

Formes et comment les obtenir

VoulezConstruisez-le comme
Murs, poutres, planches, marchesBoîtes, mises à l'échelle ; fusselez le haut ou le bas pour le caractère
Pierres, créneaux, pavés, briqueslp_blocks (ci-dessus) : plusieurs boîtes chanfreinées dans un seul objet
Toit à pignonUn prisme (profil triangulaire extrudé), débordant des murs de tous côtés
TuilesRangées de fines dalles sur la pente du toit, chaque rangée chevauchant celle du dessous, avec une petite taille et inclinaison aléatoires
Cheminée, tour, pilierBoîte fuselée ; dalle de capuchon légèrement plus large
ArbreTronc : cylindre fuselé à 5-6 côtés. Feuillage : 2-3 cônes empilés (pin) ou 1-3 icosphères déplacées (feuillu)
RocherIcosphere à 1 subdivision, sommets déplacés aléatoirement, écrasée en Z, enfoncée dans le sol
Terrain, îleUne grille avec peu de coupes, sommets relevés par du bruit, puis ombrage plat ; ou une dalle épaisse irrégulière pour un socle de diorama
EauUn plan plat ou une dalle, d'un bleu, légèrement brillant (Rugosité 0.2)
Herbe, buissonsPetits cônes ou icosphères écrasées en grappes
Objets ronds (tonneau, roue, puits)Cylindres à 6-8 côtés

Budgets

Comptages approximatifs de triangles, pour juger si quelque chose est surconstruit :

ActifTriangles
Petit accessoire (rocher, caisse, buisson)20-150
Arbre60-300
Maison ou bâtiment500-3 000
Personnage300-1 500
Diorama entier3 000-15 000

Imprimez le compte lorsque vous terminez. Bien au-dessus du budget signifie généralement trop de segments ou un modificateur qui subdivise.

Éclairage et présentation

Le style dépend de la lumière : les facettes ne se lisent que lorsque les faces voisines reçoivent une luminosité différente.

  • Un soleil en angle (environ 45° vers le haut, 30-45° sur le côté), intensité 3-4, avec des ombres douces ; plus un monde d'une couleur de ciel claire à une intensité de 0.6-1.0 pour que les ombres ne soient pas noires. Pas de configuration studio à trois points. Ne poussez pas la lumière vers le haut pour obtenir un fond blanc, et ne teintez pas le monde pour le colorer : le matériau de l'arrière-plan donne la couleur.
  • Un soleil légèrement chaud contre un monde légèrement froid donne le look classique.
  • Réglez la transformation de vue sur Standard pour que les couleurs de la palette restent telles que choisies (la transformation par défaut les grisonne).
  • Caméra : vue en trois-quarts depuis le dessus (30-35° vers le bas), objectif long (50-85 mm) ou orthographique pour un diorama.
  • Un fond uni dans une couleur de la palette, ou une dalle de sol qui se termine par un bord net. Un plan d'arrière-plan doit être bien plus grand que le modèle (20 fois ou plus), ou le monde de la même couleur : aucun bord ou horizon ne doit apparaître dans le cadre.
  • EEVEE est suffisant et rapide. Les ombres douces et l'occlusion ambiante aident beaucoup.

Les matériaux, le rendu dans un fichier et le dépannage se trouvent dans blender-materials-render.

Pour un moteur de jeu

Les actifs low-poly vont généralement dans un moteur. Conservez l'ombrage plat lors de l'exportation (les facettes sont stockées sous forme de normales divisées, ce qui augmente le nombre de sommets mais pas le nombre de triangles), regroupez les pièces d'un actif en un seul maillage avec quelques emplacements de matériaux, et placez l'origine au centre inférieur. Suivez blender-game-export pour le reste.

La vérification finale (toujours votre dernier appel)

Les outils de rendu écrivent un fichier et vous donnent son chemin : vous ne voyez jamais l'image. Donc le dernier appel execute_blender_code de la tâche est final_check, copié tel quel, et ce qu'il imprime va dans le rapport tel quel. Il fait un petit rendu depuis la caméra de la scène et nomme ce qui ne va pas : objets sans matériau, géométrie cassée, modèle hors du cadre, rendu brûlé ou sombre, et, avec le nom du fichier de référence, les différences de cadrage, luminosité, couleur et solidité de la silhouette.

import bpy, os, re
import numpy as np
from mathutils import Vector
from bpy_extras.object_utils import world_to_camera_view

MOTS_ARRIERE_PLAN = ("sol", "fond", "plancher", "ciel", "ombre")

def stats_sujet(chemin, taille=128):
    """Une image divisée en arrière-plan (les couleurs de ses quatre coins) et sujet (le reste) :
    combien de l'image le sujet prend, sa boîte, sa luminosité, saturation et couleurs."""
    img = bpy.data.images.load(chemin, check_existing=False)
    w, h = img.size
    sw, sh = (taille, max(8, round(taille * h / w))) if w >= h else (max(8, round(taille * w / h)), taille)
    img.scale(sw, sh)
    px = np.empty(len(img.pixels), dtype=np.float32)
    img.pixels.foreach_get(px)
    bpy.data.images.remove(img)
    rgb = px.reshape(sh, sw, 4)[:, :, :3]                       # la ligne 0 est le bas de l'image
    cy, cx = max(2, sh // 8), max(2, sw // 8)
    coins = np.concatenate([rgb[:cy, :cx].reshape(-1, 3), rgb[:cy, -cx:].reshape(-1, 3),
                            rgb[-cy:, :cx].reshape(-1, 3), rgb[-cy:, -cx:].reshape(-1, 3)])
    # Arrière-plan = proche d'une des couleurs des coins (un dégradé ou une ombre douce compte toujours).
    q = np.unique(np.round(coins * 8).astype(int), axis=0)
    plat = rgb.reshape(-1, 3)
    dist = np.min(np.abs(plat[:, None, :] * 8 - q[None, :, :]).max(axis=2), axis=1)
    sujet = (dist > 1.0).reshape(sh, sw)
    part = float(sujet.mean())
    tout = plat @ np.array([0.2126, 0.7152, 0.0722], dtype=np.float32)
    sortie = {"size": (w, h), "image_brightness": round(float(tout.mean()), 3), "subject_pct": round(100 * part, 1)}
    if part < 0.005:
        return

…

[Version tronquée pour la traduction]

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

Skills associés