Alexandre Bordereau
Un distributeur automatique japonais rouge généré par l’add-on, mi-rendu Cycles, mi-filaire

Lab · Add-on Blender · En cours

Jihanki Generator

Des distributeurs automatiques japonais générés de toutes pièces, de l’enseigne lumineuse aux étiquettes des canettes. Un seul mesh par machine, et une feuille de route de cinquante étapes vers une image qu’on puisse confondre avec une photo.

Logiciel
Blender 4.2+
Version
0.4.0
Régénération
< 100 ms
Feuille de route
3 / 50
Lecture
11 min

Un jihanki se reconnaît de loin : un caisson peint, une enseigne lumineuse, une vitrine rétroéclairée où les canettes s’alignent au-dessus de leurs prix, bleus pour le froid, rouges pour le chaud, et les boutons qui s’allument 売切 quand c’est épuisé.

Jihanki Generator est une extension Blender qui en fabrique autant qu’on veut, chacun différent. Le but est écrit dans la feuille de route : des machines qu’on puisse confondre avec une photo. Le projet est en cours. Cette page suit le devlog jusqu’à la v0.4.0, et le dernier chapitre dit ce qui vient.

Log 01 / 06

Un seul mesh 自販機 · Jihanki

v0.1 · 29 oct. 2026

Caisson, enseigne, vitrine, canettes, trappe, monnayeur : tout sort du même script, dans le même objet.

Chaque distributeur est un seul mesh construit avec bmesh : des boîtes pour le caisson et les détails, des profils en révolution (lathe) pour les canettes et les bouteilles PET. Il a tout ce qu’on attend d’une machine japonaise : l’enseigne lumineuse, la vitrine rétroéclairée et ses rails, la trappe de sortie, le panneau de paiement avec son écran, les fentes à pièces et à billets et le lecteur de carte IC.

Cinq étapes de construction d’un distributeur, de la caisse vide en argile à la machine éclairée de nuit
Fig. 01Caisson et porte, trappe et paiement, vitrine et rails, produits, puis matériaux et lumière.

Les couleurs ne sont pas dans les matériaux. Chaque face porte la sienne dans un attribut de coin, jhk_color, au-dessus de 1 pour les parties lumineuses. Cinq matériaux partagés le lisent : Paint, Plastic, Metal, Glass et Emit. On peut donc générer autant de machines qu’on veut sans multiplier les matériaux.

FilaireArgilejhk_colorSlotsStudioNuit

La topologie, sans chanfreins ni vitres : un seul mesh.

Fig. 02La même machine et la même caméra, passe après passe.

1
Mesh par machine, enseigne et canettes comprises.
5
Matériaux partagés par toutes les machines de la scène.
< 100 ms
Pour régénérer une machine après un réglage, chanfreins compris.

Les réglages vivent sur l’objet : taille, rangées, colonnes, rangées de bouteilles, couleur du caisson et de l’enseigne, part de boissons chaudes et d’épuisés. Chaque changement régénère la machine. Le seed tire de nouveaux produits, et « Randomize Style » un nouveau style complet. Deux boutons préparent le rendu : Cycles sur le meilleur GPU disponible, et une scène de nuit avec sol mouillé, lune, réverbère et caméra.

Animation : la même machine change de couleur, de largeur et de produits à chaque image
Fig. 03« Randomize Style », image après image : couleurs, largeur, colonnes, rangées de bouteilles et part de boissons chaudes.
Cinq distributeurs aux couleurs et aux marques différentes, alignés de nuit sur un sol mouillé
Fig. 04Cinq machines, cinq styles, dans la scène de nuit de l’add-on. Chacune a sa marque, son enseigne et son affiche.

Log 02 / 06

Cinquante étapes 計画 · Keikaku

v0.1.1 · Feuille de route

Le but : une machine qu’on puisse confondre avec une photo. Le chemin : cinquante étapes, dans l’ordre.

La feuille de route part d’un diagnostic du gros plan sur la vitrine. Quatre choses y trahissent la 3D : les arêtes sont vives, les étiquettes sont des aplats de couleur, la lumière est uniforme, et tout est neuf et identique.

Elle liste cinquante features en neuf phases, chacune avec son issue GitHub au même numéro. Les phases suivent les dépendances : les UV débloquent les textures, les textures débloquent les étiquettes et les stickers, et ainsi de suite. Un parcours conseillé traite d’abord les quatre défauts du diagnostic, du meilleur rapport entre gain visuel et effort au moins bon.

  1. 01

    Chanfreins · fait

    Un petit chantier sans dépendance, à l’effet immédiat : chaque arête attrape un liseré de lumière.

  2. 02

    Étiquettes · en cours

    Les produits occupent la moitié de la façade. Il faut les UV, le générateur de textures et la police japonaise : les deux premiers sont faits.

  3. 03

    Lumière · à venir

    De nuit, la vitrine est la source principale. Des points chauds et une décroissance à la place de l’aplat émissif.

  4. 04

    Usure · à venir

    Une machine neuve et propre ne ressemble à aucune machine réelle. Un curseur d’âge, l’usure des arêtes et la crasse qui monte du sol.

PhasePistesPar exempleÉtat
Fondations1–6UV, chanfreins, textures, police japonaise3 sur 6
Caisson7–12porte avec joint et charnières, persiennes, câble—
Façade13–18boutons en relief, afficheurs 7 segments—
Produits19–25canettes détaillées, maquettes 見本—
Matériaux26–31peau d’orange, inox brossé, verre physique—
Usure32–40rouille, crasse, stickers arrachés, tube qui clignote—
Typologies41–43Showa rétro, glaces, marques fictives—
Contexte44–48poubelles de recyclage, météo, caméra « photo »—
Pipeline49–50export temps réel, banc de test face à des photos—
Les neuf phases de la feuille de route, au moment de la v0.4.0.

Avant de toucher au réalisme, j’ai ajouté des images qui montrent comment la machine est construite, avec la méthode de Torii Generator : le même plan rendu deux fois, les vrais matériaux d’un côté, de l’autre l’argile sombre aux arêtes tracées par Freestyle, fondus sur une bande de 30 % de la largeur. Les vitres sont retirées de la passe filaire : Freestyle ignore la transparence et cacherait les produits.

Le distributeur de nuit, mi-rendu Cycles, mi-filaire
Fig. 05

Le breakdown façon VFX aligne six passes en bandes : topologie, argile, normales en espace caméra, attribut jhk_color, matériaux en studio, éclairage de nuit.

Un script rend les passes dans Blender, en headless ; un second les assemble avec le Python du système, et appelle ffmpeg pour les GIF du README. Les images de cette page viennent de ces scripts, ou de rendus faits de la même façon avec l’add-on.

Le distributeur découpé en six bandes obliques : filaire, argile, normales, attribut, matériaux, lumière
Fig. 06Le breakdown en bandes, de gauche à droite : topologie, argile, normales, jhk_color, studio, nuit.

Log 03 / 06

Des arêtes qui se voient 面取り · Mentori

v0.2.0 · Issue #2

Sur le gros plan, aucune arête n’attrapait la lumière : le caisson avait l’air découpé au laser.

Surprise en ouvrant le code : la machine portait déjà un modificateur Bevel de 3 mm, à deux segments. Il fallait comprendre pourquoi il ne se voyait pas.

La mesure tient en deux chiffres. Au coin du toit, le sommet le plus proche du coin théorique est à 0,87 mm avec « Clamp Overlap », et à 2,20 mm sans : le modificateur ne chanfreinait qu’environ 1,2 mm. Ce clamp ne travaille pas pièce par pièce. Blender calcule une seule limite pour tout le mesh, et sur un distributeur ce sont les pièces les plus fines qui décident : 3 mm pour une étiquette de prix, 2 mm pour le rebord sous le bouchon des bouteilles.

3 mm
Le chanfrein demandé au modificateur.
1,2 mm
Le chanfrein obtenu, réduit par la pièce la plus fine.
1
Seule limite pour tout le mesh.

Le builder écrit maintenant le rayon de chaque arête vive dans son bevel weight, et le modificateur passe en mode poids, avec une largeur de 1 cm : un poids de 0,4 donne 4 mm. Le clamp est coupé, et c’est le builder qui garantit qu’aucun chanfrein ne déborde. Une pièce prend 4 mm, le rayon de la tôle, ou 30 % de sa plus petite dimension si elle est plus fine. La largeur du modificateur devient une échelle globale : la doubler double tous les rayons.

PièceRayon
Caisson, toit, porte, rails4 mm
Serrure3,9 mm
Boutons, plaques du paiement2,7 mm
Étagères1,8 mm
Étiquettes de prix0,9 mm
Bords des canettes et bouteilles0,6 mm × l’échelle
Sur les produits, seules les arêtes de plus de 30° sont chanfreinées : les côtés du cylindre à 16 pans restent lisses.
Le même coin, arêtes chanfreinées qui attrapent la lumièreCoin du toit et enseigne aux arêtes vivesv0.1.1v0.2.0
Fig. 07Le coin du toit et le haut de la porte, même caméra. Le liseré du toit, du montant et du bord des canettes vient des chanfreins.

Un vrai chanfrein crée un nouveau problème. La porte était faite de boîtes côte à côte : deux montants, un linteau, quatre boîtes autour de la trappe. Avec 4 mm de chaque côté, chaque jointure devient une rainure de 8 mm, là où la vraie porte est d’un seul tenant.

Une nouvelle primitive construit une plaque percée comme un seul mesh fermé. Elle découpe la plaque en grille à partir des coordonnées de son contour et de ses trous. Chaque case pleine reçoit une face avant et une face arrière, plus un mur sur chaque côté qui borde un trou ou l’extérieur. Les arêtes de la grille entre deux faces coplanaires ont un angle nul : ni chanfrein, ni ligne d’ombrage. C’est la grille qu’on voit dans la moitié filaire de l’ouverture.

La même porte d’un seul tenant, sans jointuresTrappe et panneau de paiement en argile, jointures visibles autour de la trappev0.1.1v0.2.0
Fig. 08En argile, la trappe et le paiement. Les jointures autour de la trappe disparaissent ; seule reste celle entre la porte et le caisson, qui existe aussi sur une vraie machine.

En vérifiant les poids, le compteur affichait zéro arête chanfreinée. Une face créée par bm.faces.new() a une normale nulle tant qu’on ne la calcule pas, et l’angle des arêtes se lit sur cette normale : tous les angles valaient 0. Le même bug touchait depuis la v0.1 la fonction qui marque les arêtes vives. Les normales durcies du modificateur le masquaient au rendu ; la passe filaire, qui coupe le modificateur, le montrait.

Pythonbuilder.py, v0.2.0
f = self.bm.faces.new(verts)
f.normal_update()  # une face neuve a une normale nulle, et l’angle des arêtes la lit
Passe filaire, montants de la porte ombrés comme des tubesFig. 09 · v0.1.1
La même passe, arêtes nettesFig. 10 · v0.2.0

La passe filaire, dans les mêmes conditions. En v0.1.1, aucune arête n’était marquée vive : les montants de la porte s’ombraient comme des tubes.

Log 04 / 06

Des UV pour les textures 展開 · Tenkai

v0.3.0 · Issue #1

Le mesh n’avait aucune UV. Pas de texture, pas de décal, pas de masque d’usure : presque toute la feuille de route en dépend.

Les UV naissent avec chaque face, comme sa couleur, sur deux couches. La première est métrique : une unité vaut un mètre, sur toutes les pièces. Une texture de rouille ou de crasse aura la même densité sur le caisson et sur un bouton. Les boîtes sont projetées selon leur normale, vues de l’extérieur pour qu’aucune texture ne soit en miroir.

La seconde va de 0 à 1, seulement sur les pièces qui porteront un visuel : l’étiquette des produits, les étiquettes de prix, le panneau publicitaire et l’enseigne. Un attribut de face dit lequel.

Le distributeur couvert d’un damier gris, et d’un damier orange sur les étiquettes, l’affiche et l’enseigne
Fig. 11Damier gris de 5 cm sur les UV métriques, damier orange de 8 × 8 sur les UV 0–1 des visuels.

Les produits sont déroulés : u fait le tour, en mètres, v suit le profil plutôt que la hauteur, pour ne pas s’étirer sur l’épaule des bouteilles. La couture passe derrière, face au fond de la vitrine, et l’avant de l’étiquette tombe au milieu.

« Sans étirement » se vérifie arête par arête : la longueur de chaque arête dans les UV, divisée par sa longueur en 3D, doit valoir 1.

SurfacesRapport UV / 3D
Boîtes, plaques, cylindres1,000
Cônes, à moins de 45° de l’avantjusqu’à 1,18
Anneau plat sous le bouchon, vers l’avant1,27
Cônes et anneau, vers la couturejusqu’à 3,3
Mesuré sur trois tailles de machine, de 60 cm à 2 m de large.

Les cônes se cisaillent : les deux anneaux d’une bande n’ont pas le même rayon, donc pas le même u pour un même angle. Le décalage grandit avec l’angle, d’où un u qui part de l’avant, là où l’on regarde les produits. Pour l’éviter tout à fait, il faudrait une couture à chaque anneau ; une buée ou une poussière cachera mieux un léger biais qu’une couture.

FormuleCisaillement d’une bande de cône
rapport = √(1 + (angle × Δr / L)²)
// L : longueur de la bande, Δr : écart entre ses deux rayons
// pire cas : l’anneau plat, Δr = L

Log 05 / 06

Le générateur de textures 印刷 · Insatsu

v0.4.0 · Issue #4

Les étiquettes, les prix, l’affiche et l’enseigne étaient des aplats de couleur. Ils reçoivent des images, dessinées pour chaque seed.

Il fallait d’abord une méthode qui marche en headless, puisque toutes les images de la doc sont rendues ainsi. J’ai testé cinq pistes dans Blender 4.2 et 4.5 ; voici les quatre principales.

Méthode4.2 sans interface4.5 sans interfaceVerdict
blf dans un GPUOffScreennonnonpas de dessin GPU sans interface
blf dans un ImBufn’existe pasouipixels inaccessibles : un fichier par texte
Rendu d’objets texteouiouiun rendu par atlas, trop lent
Contours des glyphes, remplis en numpyouiouiretenue

La méthode retenue confie au moteur de polices de Blender ce qu’il sait faire, lire la police et donner la forme des lettres, et fait le reste en numpy. Un objet texte, qui n’a même pas besoin d’être dans la scène, est converti en courbes, échantillonnées à 8 points par segment. Le remplissage parcourt l’image ligne par ligne : chaque contour croisé ajoute +1 ou −1 selon son sens, et une somme cumulée donne, pour chaque pixel, le nombre de tours des contours autour de lui. 4 × 4 échantillons par pixel lissent les bords. Tout reste en mémoire, sans GPU ni fichier temporaire.

Le texte AOBANE MELON SODA deux fois : en haut les A sans barre, en bas des lettres pleines
Fig. 12

Le premier atlas écrivait « ΛOBΛNE » : des A sans barre, et de petites marques accrochées aux N et aux A. Inter est une police variable, dont les lettres sont faites de traits qui se chevauchent : la barre du A recouvre ses jambes. Remplie avec la règle pair-impair (en haut), chaque zone recouverte deux fois devenait un trou.

La règle non nulle (en bas) règle le problème, à condition de connaître le sens de chaque contour. C’est pour ça que les contours viennent des courbes de Blender, qui le gardent, plutôt que de son maillage.

Un piège attendait la police japonaise. Blender embarque Noto Sans CJK en woff2, 11 Mo compressés, et chaque nouveau caractère y coûte environ 100 ms, comme si toute la police était décompressée à chaque glyphe. Une police non compressée sort une chaîne entière en 2 à 4 ms. Cette étape écrit donc en Inter, la police latine de Blender ; le japonais viendra avec un sous-ensemble non compressé de Noto Sans JP.

100 ms
Par nouveau caractère japonais, dans la police woff2 de Blender.
5 ms
Par nouveau caractère latin, en Inter, puis en cache.
2–4 ms
Pour une chaîne entière, dans une police non compressée.

Les matériaux sont partagés par toutes les machines : un atlas par machine les aurait obligées à avoir chacune les leurs. Le seed du catalogue, une propriété de la scène, décide donc d’un catalogue commun : 48 produits tirés de 12 boissons, avec leur marque, leur motif, leur contenance et leur prix. Les marques sont huit noms inventés. Chaque machine pioche dans ce catalogue avec son propre seed.

AtlasCasesCaseContenu
Étiquettes48512 × 256centre face à la vitrine, motifs raccordés à la couture
Prix22256 × 64de ¥100 à ¥200, en bleu (froid) et en rouge (chaud)
Affiches8512 × 512une par marque
Enseignes81024 × 128une par marque
Les quatre atlas d’un catalogue, dessinés en 1,4 s.
Quarante-huit étiquettes de boissons inventées, en six rangées, aux motifs de bandes, rayures, pois et vagues
Fig. 13L’atlas des étiquettes du catalogue 0 : canettes en bas, bouteilles en haut. Une marque dans un badge, un nom, une contenance, et cinq motifs.

Chaque face qui porte un visuel enregistre sa case. Dans les matériaux, un groupe de nœuds partagé en tire la colonne et la rangée, place les UV 0–1 dans la case avec un pixel et demi de marge, lit le bon atlas et multiplie la couleur de la face. Les étiquettes reçoivent un blanc pur, qui laisse passer l’image telle quelle ; les affiches et les enseignes sont dessinées en gris, et la couleur d’accent de la machine les teinte.

Le même gros plan, étiquettes de marques, prix en yensGros plan sur la vitrine, produits en aplats de couleurv0.3.0v0.4.0
Fig. 14Le gros plan du diagnostic, même caméra. Les prix sont lisibles, en bleu pour le froid et en rouge pour le chaud ; le bouchon et le liquide des bouteilles gardent les couleurs de leur étiquette.
2 Mo
Le .blend avec ses quatre atlas packés.
0
Pixel d’écart, rouvert dans un Blender sans l’add-on.
2 s
Pour changer de catalogue sur toute la scène.

Log 06 / 06

La suite 続き · Tsuzuki

En cours

Trois pistes sur cinquante. Les étiquettes sont à mi-chemin.

La prochaine étape est la police japonaise et le générateur de textes : des noms en katakana, des prix, les mentions qu’on lit sur toutes les canettes (500ml, 無糖, 新発売). Viendront ensuite les étiquettes elles-mêmes, avec marque, nom, illustration, code-barres et contenance. Après elles, la lumière, puis l’âge.

  1. 01

    #5 Police japonaise

    Noto Sans JP en sous-ensemble non compressé, et des textes tirés par seed.

  2. 02

    #22 Étiquettes

    Marque, nom, illustration (thé, grain de café, fruit), code-barres, contenance.

  3. 03

    #30 Lumière

    Diffuseur avec points chauds, LED visibles en gros plan, température de couleur, unités physiques.

  4. 04

    #32 Âge

    Un curseur, du neuf au Showa abandonné, qui pilotera l’usure des arêtes, la crasse et la rouille.

Au-delà, la suite dépend de l’usage : la façade pour les gros plans (boutons en relief, afficheurs 7 segments, trappe à volet), le contexte pour les plans larges (poubelles de recyclage, rangées de machines sous un auvent, pluie sur la vitrine), et un export temps réel pour Unity ou Unreal. La dernière piste est un banc de test : une scène de lookdev à côté de vraies photos, pour mesurer le réalisme au lieu de le deviner.

Projet
Personnel, en cours
Compatibilité
Blender 4.2+ · Cycles · EEVEE
Version
0.4.0, 30 octobre 2026
Licence
Propriétaire : revente et modification interdites
  • Python
  • bmesh
  • numpy
  • Nœuds de shader
  • Freestyle
  • Rendu headless