CommunityBildgithub.com

TraX22/blender-low-poly

Erstellt stilisierte Low-Poly-Modelle und Szenen in Blender über die offizielle BlenderLab-Verbindung – kantige, facettierte Formen mit wenigen Polygonen, flacher Schattierung, einer kleinen Farbpalette aus einfachen Materialien, übertriebenen Proportionen und der weichen Beleuchtung, die dieser Stil braucht.

Was ist blender-low-poly?

Dieses Skill ermöglicht die Erstellung von Low-Poly-Modellen und -Szenen in Blender, die nicht einfach eine reduzierte Polygonanzahl darstellen, sondern einen bewussten, stilistischen Look mit großen, lesbaren Formen, flachen Facetten und einer begrenzten Farbpalette verfolgen. Es ist ideal für die Entwicklung von Assets für Spiele, Dioramen oder stilisierte Kunstwerke. Das Skill arbeitet über die offizielle BlenderLab-Serververbindung und nutzt Werkzeuge wie `execute_blender_code` und `get_screenshot_of_area_as_image` für die Interaktion. Es definiert klare stilistische Regeln, darunter flache Schattierung, minimale Segmente, keine Texturen und bewusst übertriebene Proportionen. Der Workflow umfasst Blockout, Materialerstellung, Detaillierung und eine abschließende `final_check`-Funktion, die das gerenderte Bild mit einer Referenz vergleicht. Es enthält auch Hilfsfunktionen wie `lp_blocks` für die effiziente Erstellung von Box-Objekten und Budgetrichtlinien für die Polygonanzahl.

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

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

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Low-Poly-Modellierung in Blender

Low Poly ist ein Stil, nicht nur eine niedrige Dreiecksanzahl: große, lesbare Formen, sichtbare flache Facetten, eine Handvoll einfarbiger Farben und Proportionen, die ein wenig über die Realität hinausgehen. Ein realistisches Modell mit weniger Polygonen ist kein Low Poly; es ist ein grobes realistisches Modell.

Der allgemeine Arbeitsablauf (Szene betrachten, in Teilen planen, ein Teil pro Aufruf, Screenshot nach jedem Schritt, niemals löschen, was du nicht erstellt hast) ist im blender-modeling-Skill beschrieben: Folge ihm. Dieses Skill beschreibt, was für Low Poly anders ist.

Deine Blender-Verbindung

Du arbeitest über BlenderLab, den offiziellen Blender-Lab-Server; seine Werkzeuge heißen blenderlab_…:

  • Was in der Szene ist: get_objects_summary; ein Objekt im Detail: get_object_detail_summary (nach name). Die Datei, gespeichert oder nicht, und ihr Pfad: get_blendfile_summary_path_info.
  • Python ausführen: execute_blender_code. Nichts bleibt zwischen Aufrufen erhalten (trage deine Helfer in jedes Skript); was das Skript ausgibt, kommt zurück, und ein Dict, das result zugewiesen wird, kommt als Daten zurück. Seine Schutzmechanismen verweigern einige Operatoren (Blender beenden, Werkseinstellungen).
  • Das 3D-Viewport sehen: get_screenshot_of_area_as_image mit area_ui_type: "VIEW_3D" (das ganze Fenster: get_screenshot_of_window_as_image); auf ein Objekt ausrichten: jump_to_view3d_object_by_name.
  • Die Python-API überprüfen: get_python_api_docs (ein Bezeichner wie bpy.types.BevelModifier), search_api_docs; das Handbuch: search_manual_docs.
  • Schnelles Rendern: render_thumbnail_to_path, render_viewport_to_path; das Bild geht in Blenders temporären Ordner und das Ergebnis gibt den echten Pfad zurück.
  • Exportieren: Code (bpy.ops.export_scene.gltf, bpy.ops.export_scene.fbx).
  • Asset-Bibliotheken und 3D-Generatoren: keine. Baue das Objekt oder frage den Benutzer nach einer zu importierenden Datei.

Falls diese Werkzeuge nicht verfügbar sind, stoppe und sage das: Der Benutzer muss die BlenderLab-Verbindung installieren (Extras → Verbindungen), sie diesem Agenten geben und Blender mit gestartetem Add-On-Server geöffnet haben. Beschreibe keine Arbeit als erledigt, die du nicht ausführen konntest.

Der Stil, als Regeln

  1. Flache Schattierung überall. Jede Fläche hat eine einzige flache Farbe; keine glatte Schattierung, kein Auto Smooth. Das macht die Facetten sichtbar.
  2. Wenige Segmente, bewusst. Zylinder 6–8 Seiten, Kegel 5–6, Kugeln als Ikosphären mit 1–2 Unterteilungen. Ein 32-seitiger Zylinder ruiniert den Look mehr als alles andere.
  3. Kein Bevel, kein Subdivision Surface. Sie runden die Facetten ab. Für eine weichere Kante höchstens eine einsegmentige Fase.
  4. Einfarbig, keine Texturen. Ein Material pro Farbe, Principled BSDF mit Basis-Farbe, Rauheit 0,8–1,0, Metallisch 0, kein spiegelnder Glanz. Materialien wiederverwenden: Eine ganze Szene braucht normalerweise 6–12.
  5. Eine bewusste Palette. Wähle sie vor dem Modellieren: 1–2 dominante Farben, 2–3 unterstützende, 1 Akzent. Leicht entsättigte Mitteltöne, warm und kühl ausbalanciert, und zwei Töne jeder Hauptfarbe (hell und dunkel) für Abwechslung zwischen benachbarten Teilen.
  6. Klobige, übertriebene Proportionen. Dickere Wände, Balken und Stämme als im echten Leben; übergroße Dächer, Türen und Fenster; sich verjüngende Formen (breiter an der Basis oder oben für ein Cartoon-Gefühl). Dünne Teile verschwinden bei diesem Detailgrad.
  7. Unvollkommenheit von Hand, in kleinen Dosen. Nichts perfekt ausgerichtet: Neige einen Schornstein um 2–4°, variiere Dachziegel um ein paar Prozent ihrer Größe und 2–3° ihrer Neigung, verschiebe Eckpunkte von Felsen und Gelände zufällig. Die Struktur muss noch lesbar sein: Reihen von Ziegeln bleiben Reihen, kein Teil wird seitlich gedreht oder von der Oberfläche gehoben. Mit einem festen Zufallssamen, sodass eine erneute Ausführung das gleiche Ergebnis liefert.
  8. Detail durch separate kleine Teile, nicht durch Unterteilen. Ein Fenster ist ein Rahmen aus vier Quadern plus einer Scheibe; Dachziegel sind Reihen kleiner Platten; Steine sind ein paar unregelmäßige Blöcke, die in die Mauer gesetzt sind. Jedes Teil ist einfach; die Anordnung ergibt den Reichtum.
  9. Teile dürfen sich durchdringen. Low-Poly-Teile werden ineinander geschoben, statt verschweißt: Ein Balken sinkt in eine Wand, ein Fels in den Boden. Gib dich nicht mit Booleschen Operationen oder sauberen Verbindungen ab.

Arbeitsablauf

  1. Lies die Referenz, falls vorhanden: Liste die Teile auf, zähle, was sich wiederholt (Reihen von Ziegeln, Anzahl der Balken, Fenster pro Wand), notiere die Proportionen zwischen Teilen als Verhältnisse (Dachhöhe zu Wandhöhe, Breite zu Höhe) und benenne die Palettenfarben. Baue von dieser Liste aus. Das Bild entscheidet: Verankere eine Größe und leite den Rest aus den Verhältnissen ab, erfinde keine Größen in Metern, die das Bild widerlegt, und füge nichts hinzu, was es nicht zeigt (eine Basis, Requisiten), es sei denn, es wird danach gefragt.
  2. Blockout zuerst die großen Massen mit Boxen und Keilen in den richtigen Proportionen. Mache einen Screenshot und vergleiche die Silhouette: Wenn die Silhouette falsch ist, werden Details sie nicht retten.
  3. Palette: Erstelle die Materialien einmal, benannt nach dem, was sie färben (LP_Wand_Hell, LP_Dach_Rot, LP_Holz_Dunkel).
  4. Struktur, dann sekundäre Teile (Balken, Rahmen, Schornstein, Stufen), dann kleine Details (Ziegel, Steine, Bretter, Risse), dann Umgebung (Bodenplatte, ein paar Felsen, Grasbüschel).
  5. Vergröbern: Die zufälligen Versätze und Neigungen aus Regel 7.
  6. Licht und Rahmen (unten), dann das Viewport auf den Winkel der Referenz ausrichten, erfassen und Teil für Teil vergleichen: Silhouette, Proportionen, wo jedes Teil sitzt, Farben. Korrigieren.
  7. Beende mit final_check, dem letzten Aufruf der Aufgabe: Die Funktion ist unten unter „Der abschließende Check“. Du siehst deine Render nicht; sie misst das Rendering für dich (das Modell getrennt vom Hintergrund, gegen das Referenzbild, wenn du dessen Dateinamen hast) und gibt eine PROBLEM:-Zeile für das aus, was falsch ist. Korrigiere, führe es erneut aus (höchstens zwei Durchläufe) und füge seine Ausgabe in den Bericht ein. Messungen, die du selbst vornimmst, ersetzen es nicht: Eine Aufgabe, die ein Modell erstellt oder ändert, ist erst beendet, wenn diese Funktion gelaufen ist.

Erwarte zwei oder drei Korrekturrunden gegen die Referenz. Sage, was noch abweicht.

Du hast eine begrenzte Anzahl von Werkzeugrunden pro Aufgabe (siehe „Dein Schrittbudget“ in blender-modeling): Baue zwei oder drei verwandte Teile pro Aufruf, erfasse bei den Meilensteinen (Blockout, Details, Finale) und setze die sichtbarsten Teile zuerst.

Code für jedes Rezept ist in references/low-poly-recipes.md: Palette, flache Schattierung, sich verjüngende Boxen, Satteldächer, Reihen von Ziegeln, Fenster und Türen, Fachwerk, Felsen, Bäume, Gelände, Streuen und die Beleuchtungseinrichtung. Öffne es vor dem ersten Skript.

Viele Blöcke in einem Objekt

Steinreihen, Zinnen, Pflaster, Bretter und Ziegel sind viele kleine Boxen, die in ein Objekt gehören. Baue sie mit lp_blocks: Es beendet jede Box in ihrem eigenen Bmesh und fügt sie erst dann dem Objekt hinzu. Verbinde keine Boxen, indem du Scheitel- und Flächenlisten von Hand anfügst, und verschiebe nicht „die letzten N Scheitelpunkte“ nach einer Operation, die ihre Anzahl ändert (das tut eine Fase): Die Flächen landen auf den falschen Scheitelpunkten und das Modell kommt als gestreckte Spitzen heraus. final_check benennt ein so kaputtes Objekt; baue es neu, melde es nicht.

import bpy, bmesh
from mathutils import Matrix, Vector

def lp_blocks(name, col, mat, blocks, chamfer=0.03):
    """Viele Boxen in EINEM flach schattierten Objekt. blocks ist eine Liste von (Mittelpunkt, Größe) oder
    (Mittelpunkt, Größe, z_Drehung): Mittelpunkt und Größe sind (x, y, z) in Metern, die Drehung in Bogenmaß.
    Jede Box wird in ihrem eigenen Bmesh beendet und erst dann dem Objekt hinzugefügt."""
    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)                                   # fügt die fertige Box dem Objekt-Mesh hinzu
        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

# Eine Reihe von Wandsteinen, abwechselnd zwei Größen, in einem einzigen Objekt.
col = bpy.data.collections["LP_Model"]
stone = bpy.data.materials["LP_Stone_Light"]
lp_blocks("Wall_Course_01", col, stone,
          [((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)])

Formen und wie man sie bekommt

GewünschtBaue es als
Wände, Balken, Bretter, StufenBoxen, skaliert; oben oder unten verjüngt für Charakter
Steinblöcke, Zinnen, Pflaster, Ziegellp_blocks (oben): viele gefaste Boxen in einem Objekt
SatteldachEin Prisma (Dreiecksprofil extrudiert), das auf allen Seiten über die Wände überhängt
DachziegelReihen dünner Platten auf der Dachschräge, jede Reihe überlappt die darunter, mit kleinen zufälligen Größen und Neigungen
Schornstein, Turm, PfeilerVerjüngte Box; Abschlussplatte etwas breiter
BaumStamm: 5–6-seitiger verjüngter Zylinder. Laub: 2–3 gestapelte Kegel (Kiefer) oder 1–3 verschobene Ikosphären (Laubbaum)
FelsIkosphäre mit 1 Unterteilung, Scheitelpunkte zufällig verschoben, in Z gestaucht, in den Boden versenkt
Gelände, InselEin Gitter mit wenigen Schnitten, Scheitelpunkte durch Rauschen angehoben, dann flach schattiert; oder eine dicke unregelmäßige Platte als Dioramenbasis
WasserEine flache Ebene oder Platte, einfarbig blau, leicht glänzend (Rauheit 0,2)
Gras, BüscheKleine Kegel oder gestauchte Ikosphären in Gruppen
Runde Dinge (Fass, Rad, Brunnen)6–8-seitige Zylinder

Budgets

Ungefähre Dreiecksanzahlen, um zu beurteilen, ob etwas überbaut ist:

AssetDreiecke
Kleine Requisite (Fels, Kiste, Busch)20–150
Baum60–300
Haus oder Gebäude500–3,000
Figur300–1,500
Ganzes Diorama3,000–15,000

Gib die Anzahl aus, wenn du fertig bist. Weit über dem Budget bedeutet normalerweise zu viele Segmente oder einen Modifikator, der unterteilt.

Licht und Präsentation

Der Stil hängt vom Licht ab: Facetten werden nur sichtbar, wenn benachbarte Flächen unterschiedliche Helligkeit erhalten.

  • Eine Sonne in einem Winkel (etwa 45° nach oben, 30–45° zur Seite), Stärke 3–4, mit weichen Schatten; plus eine Welt in einer hellen Himmelsfarbe bei Stärke 0,6–1,0, damit Schatten nicht schwarz sind. Kein Drei-Punkt-Studio-Setup. Schiebe das Licht nicht nach oben, um einen weißen Hintergrund zu bekommen, und töne die Welt nicht farbig: Das eigene Material des Hintergrunds gibt die Farbe.
  • Eine leicht warme Sonne gegen eine leicht kühle Welt ergibt den klassischen Look.
  • Setze die Ansichtstransformation auf Standard, damit die Palettenfarben so bleiben, wie gewählt (die Standardtransformation macht sie grau).
  • Kamera: Dreiviertelansicht von oben (30–35° nach unten), langes Objektiv (50–85 mm) oder orthografisch für ein Diorama.
  • Ein einfarbiger Hintergrund in einer Palettenfarbe oder eine Bodenplatte, die in einer sauberen Kante endet. Eine Hintergrundebene muss viel größer sein als das Modell (20-mal oder mehr), oder die Welt dieselbe Farbe haben: Es darf keine Kante oder Horizont im Bild sichtbar sein.
  • EEVEE ist ausreichend und schnell. Weiche Schatten und Umgebungsverdeckung helfen sehr.

Materialien, Rendern in eine Datei und Fehlerbehebung sind in blender-materials-render.

Für eine Game-Engine

Low-Poly-Assets gehen normalerweise in eine Engine. Behalte die flache Schattierung beim Exportieren bei (die Facetten werden als Split-Normals gespeichert, was die Scheitelpunktanzahl erhöht, aber nicht die Dreiecksanzahl), führe die Teile eines Assets in einem Mesh mit wenigen Material-Slots zusammen und setze den Ursprung auf die untere Mitte. Folge für den Rest blender-game-export.

Der abschließende Check (immer dein letzter Aufruf)

Die Render-Werkzeuge schreiben eine Datei und geben dir ihren Pfad: Du siehst das Bild nie. Daher ist der letzte execute_blender_code-Aufruf der Aufgabe final_check, genau so kopiert, und was er ausgibt, kommt so in den Bericht. Es erstellt ein kleines Rendering aus der Kamera der Szene und benennt, was falsch ist: Objekte ohne Material, kaputte Geometrie, ein Modell außerhalb des Rahmens, ein verbranntes oder dunkles Rendering, und, mit dem Dateinamen der Referenz, die Unterschiede in Bildausschnitt, Helligkeit, Farbe und wie solide die Silhouette ist.

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

BACKDROP_WORDS = ("ground", "backdrop", "floor", "sky", "shadow")

def subject_stats(path, size=128):
    """Ein Bild aufgeteilt in Hintergrund (die Farben seiner vier Ecken) und Motiv (der Rest):
    Wie viel des Bildes das Motiv einnimmt, seine Box, seine Helligkeit, Sättigung und Farben."""
    img = bpy.data.images.load(path, check_existing=False)
    w, h = img.size
    sw, sh = (size, max(8, round(size * h / w))) if w >= h else (max(8, round(size * w / h)), size)
    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]                       # Zeile 0 ist der untere Bildrand
    cy, cx = max(2, sh // 8), max(2, sw // 8)
    corners = 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)])
    # Hintergrund = nahe einer der Eckfarben (ein Farbverlauf oder ein weicher Schatten zählt noch).
    q = np.unique(np.round(corners * 8).astype(int), axis=0)
    flat = rgb.reshape(-1, 3)
    dist = np.min(np.abs(flat[:, None, :] * 8 - q[None, :, :]).max(axis=2), axis=1)
    subject = (dist > 1.0).reshape(sh, sw)
    share = float(subject.mean())
    whole = flat @ np.array([0.2126, 0.7152, 0.0722], dtype=np.float32)
    out = {"size": (w, h), "image_brightness": round(float(whole.mean()), 3), "subject_pct": round(100 * share, 1)}
    if share < 0.005:
        return 

…

Individual skills in this repo

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

Verwandte Skills