CommunityImagemgithub.com

TraX22/blender-low-poly

Constrói modelos e cenas low-poly estilizados no Blender através de uma conexão BlenderLab — formas facetadas e encorpadas com poucos polígonos, sombreamento plano, uma paleta reduzida de materiais sólidos, proporções exageradas e a iluminação suave que o estilo exige.

O que é blender-low-poly?

Esta skill especializa o agente para criar arte low-poly estilizada no Blender, indo muito além de simplesmente reduzir a contagem de triângulos. Ela impõe regras de estilo fundamentais: sombreamento plano em todas as faces, cilindros com poucos segmentos (6-8 lados), ausência de chanfros e subdivisão, materiais de cor sólida sem texturas, e proporções exageradas com'imperfeições manuais' para dar caráter. A skill utiliza o servidor BlenderLab oficial — as ferramentas `blenderlab_…` — permitindo executar código Python, tirar screenshots da viewport 3D, renderizar, exportar em glTF/FBX e verificar a API. O fluxo de trabalho é altamente estruturado: planejamento com base em uma imagem de referência (se houver), blockout dos volumes principais, criação da paleta de materiais, construção de estrutura, partes secundárias e pequenos detalhes, finalizando com a função `final_check`, que compara automaticamente o modelo renderizado com a referência e aponta problemas de enquadramento, brilho, cor e silhueta. A skill também fornece receitas prontas em um arquivo de referência (`references/low-poly-recipes.md`) para construir de forma eficiente telhados de duas águas, fileiras de telhas, janelas, portas, rochas, árvores, terreno e a configuração de iluminação — essencial para dar vida às facetas.

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

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

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Modelagem low-poly no Blender

Low poly é um estilo, não apenas uma baixa contagem de triângulos: formas grandes e legíveis, facetas planas visíveis, um punhado de cores sólidas e proporções um pouco além da realidade. Um modelo realista com menos polígonos não é low poly; é um modelo realista bruto.

O loop de trabalho geral (olhar a cena, planejar em partes, uma parte por chamada, screenshot após cada etapa, nunca apagar o que você não criou) está na skill blender-modeling: siga-o. Esta skill diz o que é diferente para low poly.

Sua conexão Blender

Você trabalha através do BlenderLab, o servidor oficial do Blender Lab; suas ferramentas são blenderlab_…:

  • O que está na cena: get_objects_summary; um objeto em detalhe: get_object_detail_summary (por name). O arquivo, salvo ou não, e seu caminho: get_blendfile_summary_path_info.
  • Executar Python: execute_blender_code. Nada persiste entre chamadas (carregue seus auxiliares em cada script); o que o script imprime é retornado, e um dicionário atribuído a result retorna como dados. Sua proteção recusa alguns operadores (sair do Blender, reset de fábrica).
  • Ver o viewport 3D: get_screenshot_of_area_as_image com area_ui_type: "VIEW_3D" (a janela inteira: get_screenshot_of_window_as_image); aponte para um objeto: jump_to_view3d_object_by_name.
  • Verificar a API Python: get_python_api_docs (um identificador como bpy.types.BevelModifier), search_api_docs; o manual: search_manual_docs.
  • Renderização rápida: render_thumbnail_to_path, render_viewport_to_path; a imagem vai para a pasta temporária do Blender e o resultado fornece o caminho real.
  • Exportar: código (bpy.ops.export_scene.gltf, bpy.ops.export_scene.fbx).
  • Bibliotecas de assets e geradores 3D: nenhum. Construa o objeto ou peça ao usuário um arquivo para importar.

Se essas ferramentas não estiverem disponíveis, pare e avise: o usuário precisa instalar a conexão BlenderLab (Ferramentas → Conexões), fornecê-la a este agente, e ter o Blender aberto com o servidor do add-on iniciado. Não descreva o trabalho como concluído quando você não pôde realizá-lo.

O estilo, como regras

  1. Sombreamento plano em toda parte. Cada face é uma cor plana; sem sombreamento suave, sem suavização automática. Isto é o que faz as facetas aparecerem.
  2. Poucos segmentos, de propósito. Cilindros com 6-8 lados, cones com 5-6, esferas como icospheras com 1-2 subdivisões. Um cilindro de 32 lados estraga o visual mais do que qualquer outra coisa.
  3. Sem Chanfro, sem Superfície de Subdivisão. Eles arredondam as facetas. Para uma borda mais suave, use no máximo um chanfro de um segmento.
  4. Cor sólida, sem texturas. Um material por cor, Principled BSDF com Cor Base, Rugosidade 0.8-1.0, Metálico 0, sem brilho especular. Reutilize materiais: uma cena inteira geralmente precisa de 6-12.
  5. Uma paleta deliberada. Escolha antes de modelar: 1-2 cores dominantes, 2-3 de suporte, 1 de destaque. Meio-tons ligeiramente dessaturados, equilíbrio entre quentes e frios, e dois tons de cada cor principal (claro e escuro) para variedade entre partes vizinhas.
  6. Proporções encorpadas e exageradas. Paredes, vigas e troncos mais grossos que na vida real; telhados, portas e janelas superdimensionados; formas cônicas (mais largas na base, ou no topo para um visual cartoon). Partes finas desaparecem neste nível de detalhe.
  7. Imperfeição manual, em pequenas doses. Nada perfeitamente alinhado: incline uma chaminé 2-4°, varie telhas em alguns por cento de seu tamanho e 2-3° de inclinação, mova vértices de rochas e terreno aleatoriamente. A estrutura ainda deve ser legível: fileiras de telhas permanecem fileiras, nenhuma peça virada de lado ou levantada da superfície. Com uma semente aleatória fixa, para que uma reexecução dê o mesmo resultado.
  8. Detalhe através de pequenas peças separadas, não subdividindo. Uma janela é um quadro de quatro caixas mais uma vidraça; telhas são fileiras de pequenas lajes; pedras são alguns blocos irregulares embutidos na parede. Cada peça é simples; a disposição dá a riqueza.
  9. Peças podem se intersectar. Partes low-poly são empurradas umas nas outras em vez de serem soldadas: uma viga afunda em uma parede, uma rocha no chão. Não gaste esforço com booleanos ou junções limpas.

Fluxo de trabalho

  1. Leia a referência, se houver uma: liste as partes, conte o que se repete (fileiras de telhas, número de vigas, janelas por parede), anote as proporções entre partes como razões (altura do telhado contra altura da parede, largura contra altura), e nomeie as cores da paleta. Construa a partir dessa lista. A imagem decide: ancore um tamanho e derive o resto das razões, não invente tamanhos em metros que a imagem contradiz, e não adicione o que ela não mostra (uma base, adereços) a menos que seja solicitado.
  2. Blockout primeiro as grandes massas com caixas e cunhas nas proporções corretas. Tire um screenshot e compare a silhueta: se a silhueta estiver errada, os detalhes não a salvarão.
  3. Paleta: crie os materiais uma vez, nomeados pelo que colorem (LP_Parede_Claro, LP_Telhado_Vermelho, LP_Madeira_Escuro).
  4. Estrutura, depois partes secundárias (vigas, quadros, chaminé, degraus), depois pequenos detalhes (telhas, pedras, tábuas, rachaduras), depois arredores (laje de chão, algumas rochas, tufos de grama).
  5. Enrugar: os deslocamentos e inclinações aleatórios da regra 7.
  6. Iluminação e enquadramento (abaixo), depois coloque a vista no ângulo da referência, capture-a e compare parte por parte: silhueta, proporções, onde cada parte se senta, cores. Corrija.
  7. Finalize com final_check, a última chamada da tarefa: a função está abaixo, em "A verificação final". Você não vê seus renders; ela mede o render para você (o modelo separado do fundo, contra a imagem de referência quando você tem seu nome de arquivo) e imprime uma linha PROBLEM: para o que está errado. Corrija, execute novamente (no máximo duas rodadas) e coloque sua saída no relatório. Medidas que você mesmo faz não a substituem: uma tarefa que constrói ou altera um modelo não está concluída até que essa função tenha sido executada.

Espere duas ou três rodadas de correção contra a referência. Diga o que ainda difere.

Você tem um número limitado de rodadas de ferramenta por tarefa (veja "Seu orçamento de etapas" em blender-modeling): construa duas ou três partes relacionadas por chamada, capture nos marcos (blockout, detalhes, final) e coloque as partes mais visíveis primeiro.

Código para cada receita está em references/low-poly-recipes.md: paleta, sombreamento plano, caixas cônicas, telhados de duas águas, fileiras de telhas, janelas e portas, esquadrias de madeira, rochas, árvores, terreno, dispersão e a configuração de iluminação. Abra-o antes do primeiro script.

Muitos blocos em um objeto

Fiadas de pedras, ameias, pavimentos, tábuas e tijolos são muitas caixas pequenas que pertencem a um objeto. Construa-os com lp_blocks: ela finaliza cada caixa em seu próprio bmesh e só então a adiciona ao objeto. Não junte caixas anexando listas de vértices e faces manualmente, e não mova "os últimos N vértices" após uma operação que muda seu número (um chanfro faz isso): as faces acabam nos vértices errados e o modelo sai como picos esticados. final_check nomeia um objeto quebrado assim; reconstrua-o, não o reporte.

import bpy, bmesh
from mathutils import Matrix, Vector

def lp_blocks(name, col, mat, blocks, chamfer=0.03):
    """Muitas caixas em UM objeto com sombreamento plano. blocks é uma lista de (centro, tamanho) ou
    (centro, tamanho, rotação_z): centro e tamanho são (x, y, z) em metros, a rotação em radianos.
    Cada caixa é finalizada em seu próprio bmesh e só então adicionada ao objeto."""
    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)                                   # adiciona a caixa finalizada à malha do objeto
        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

# Uma fiada de pedras de parede, alternando dois tamanhos, em um único objeto.
col = bpy.data.collections["LP_Model"]
stone = bpy.data.materials["LP_Pedra_Claro"]
lp_blocks("Parede_Fiada_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)])

Formas e como obtê-las

DesejoConstrua como
Paredes, vigas, tábuas, degrausCaixas, escaladas; afile o topo ou a base para dar caráter
Blocos de pedra, ameias, pavimento, tijoloslp_blocks (acima): muitas caixas chanfradas em um objeto
Telhado de duas águasUm prisma (perfil de triângulo extrusado), com beiral em todos os lados
TelhasFileiras de lajes finas na inclinação do telhado, cada fileira sobrepondo a de baixo, com pequeno tamanho e inclinação aleatórios
Chaminé, torre, pilarCaixa cônica; laje de topo ligeiramente mais larga
ÁrvoreTronco: cilindro cônico de 5-6 lados. Folhagem: 2-3 cones empilhados (pinheiro) ou 1-3 icospheras deslocadas (frondosa)
RochaIcosphere com 1 subdivisão, vértices movidos aleatoriamente, achatada em Z, afundada no chão
Terreno, ilhaUma grade com poucos cortes, vértices elevados por ruído, depois sombreamento plano; ou uma laje irregular grossa para base de diorama
ÁguaUm plano ou laje plana, azul, ligeiramente brilhante (Rugosidade 0.2)
Grama, arbustosPequenos cones ou icospheras achatadas em aglomerados
Coisas redondas (barril, roda, poço)Cilindros de 6-8 lados

Orçamentos

Contagens aproximadas de triângulos, para julgar se algo está superconstruído:

AssetTriângulos
Pequeno adereço (rocha, caixote, arbusto)20-150
Árvore60-300
Casa ou edifício500-3,000
Personagem300-1,500
Diorama inteiro3,000-15,000

Imprima a contagem ao finalizar. Muito acima do orçamento geralmente significa muitos segmentos ou um modificador que subdivide.

Iluminação e apresentação

O estilo depende da luz: as facetas só são lidas quando faces vizinhas recebem brilhos diferentes.

  • Um sol em ângulo (cerca de 45° para cima, 30-45° para o lado), força 3-4, com sombras suaves; mais um mundo de uma cor de céu clara com força 0.6-1.0 para que as sombras não sejam pretas. Nenhuma configuração de estúdio de três pontos. Não aumente a luz para obter um fundo branco, e não tinge o mundo para colori-lo: o material do próprio fundo dá a cor.
  • Um sol ligeiramente quente contra um mundo ligeiramente frio dá o visual clássico.
  • Defina a transformação de visualização para Standard para que as cores da paleta permaneçam como escolhidas (a transformação padrão as acinzenta).
  • Câmera: vista de três quartos de cima (30-35° para baixo), lente longa (50-85 mm) ou ortográfica para um diorama.
  • Um fundo simples em uma cor da paleta, ou uma laje de chão que termina em uma borda limpa. Um plano de fundo tem que ser muito maior que o modelo (20 vezes ou mais), ou o mundo da mesma cor: nenhuma borda ou horizonte pode aparecer no quadro.
  • EEVEE é suficiente e rápido. Sombras suaves e oclusão ambiente ajudam muito.

Materiais, renderização para arquivo e solução de problemas estão em blender-materials-render.

Para um motor de jogo

Assets low-poly geralmente vão para um motor. Mantenha o sombreamento plano ao exportar (as facetas são armazenadas como normais divididas, o que aumenta a contagem de vértices, mas não a de triângulos), mescle as peças de um asset em uma única malha com alguns slots de material, e coloque a origem no centro inferior. Siga blender-game-export para o resto.

A verificação final (sempre sua última chamada)

As ferramentas de render escrevem um arquivo e fornecem seu caminho: você nunca vê a imagem. Então, a última chamada execute_blender_code da tarefa é final_check, copiada como está, e o que ela imprime vai para o relatório como está. Ela faz um pequeno render da câmera da cena e nomeia o que está errado: objetos sem material, geometria quebrada, um modelo fora do quadro, um render queimado ou escuro, e, com o nome do arquivo da referência, as diferenças em enquadramento, brilho, cor e quão sólida é a silhueta.

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

BACKDROP_WORDS = ("chão", "fundo", "piso", "céu", "sombra")

def subject_stats(path, size=128):
    """Uma imagem dividida em fundo (as cores de seus quatro cantos) e assunto (o resto):
    quanto da imagem o assunto ocupa, sua caixa, seu brilho, saturação e cores."""
    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]                       # linha 0 é a parte inferior da imagem
    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)])
    # Fundo = próximo a uma das cores do canto (um gradiente ou uma sombra suave ainda conta).
    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 

…

[truncado para tradução]

Individual skills in this repo

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

Habilidades Relacionadas