16 Couleurs

16 Couleurs – graphisme & jeu vidéo


5 Commentaires

Making of de Red Eyes sur Sega Mega Drive

Crédit photo : @marexpo

En janvier 2019, Remute, musicien électro basé à Hambourg, annonçait la sortie au mois de mars de Technoptimistic, un album pour la Mega Drive exclusivement disponible en édition physique, une bonne vieille cartouche donc. Outre les pistes de musique elles-mêmes, on y trouverait une interface de type music-disk et un clip vidéo pour le morceau Red Eyes qui tournerait en temps réel sur la console. Pour cela, un an auparavant il avait fait appel à Kabuto (le programmeur derrière la majorité du code de la très impressionnante démo de Titan pour la Mega Drive, Overdrive 2) et à moi-même pour la partie graphique. Difficile de refuser ce genre d’opportunité !

Graphismes 2D

Je commence par la partie la plus classique où il s’est surtout agit de garder en tête les capacités graphiques de la 16 bit de Sega, qui fête ses 30 ans cette année d’ailleurs : une résolution de 320×224 et jusqu’à 64 couleurs par plan (16 couleurs par tile) à choisir parmi une palette de seulement 512 couleurs (8 niveaux par composante RGB, comme ce bon vieil Atari STF). Pour produire les images j’ai utilisé Grafx2 qui est souvent la meilleure solution pour les plateformes old school grâce à ses fonctionnalités spécifiques.

Grafx2

Pour obtenir la trame assez originale du halo derrière le logo et d’autres éléments, j’ai eu recours à mon couteau suisse habituel, Imagemagick, ce dernier permettant en effet de générer des types de tramages sur mesure de bonne facture (voir à la fin du billet pour les instructions détaillées). À l’inverse, les résultats obtenus avec les algorithmes de Photoshop (diffusion, noise…) sont souvent décevants à cause du petit nombre de teintes disponible dans la palette de la Mega Drive.

Graphismes 3D

Le secret de cette partie c’est que la Mega Drive n’affiche pas réellement des scènes 3D comme on pourrait le croire à première vue, mais uniquement des polygones en 2D. Une technique similaire avait été utilisée par Oxygene pour leur démo STNICCC 2000 sur Atari ST. Tous les calculs de perspective, d’occlusion ou autres sont donc effectués auparavant. Pour autant, ça ne permet pas de s’affranchir des contraintes en matière de palette et surtout de complexité des scènes, puisque afficher des centaines de polygones, même 2D, à 25 images par seconde sur une machine qui n’a absolument pas été conçue pour afficher autre chose que des sprites et des tiles nécessite beaucoup de calculs et d’optimisation.

Nous avons discuté la possibilité d’utiliser un éclairage dynamique mais avons préféré y renoncer de peur que le résultat soit décevant au vu de la palette de couleurs limitée. Pour maintenir des performances correctes, je me suis efforcé de me limiter à quelques centaines de polygones généralement, qui est suffisamment léger mais permet néanmoins d’obtenir des scènes intéressantes. Au final le framerate des différentes séquences est bien meilleur qu’espéré initialement grâce aux talents d’optimisation de Kabuto. Pour plus de détails sur le fonctionnement du moteur de rendu des polygones, je ne peux que vous conseiller de vous référer aux explications très détaillés qu’il a écrites.

Blender

L’animation 3D a été entièrement modélisée et animée avec Blender avec l’objectif de générer une séquence d’images directement compatible avec les capacités de la Mega Drive : résolution et palette exactes, pas d’antialiasing, 16 couleurs par image maximum. Les valeurs RGB des matériaux ont été copié de Grafx2 pour s’assurer qu’elles étaient toutes compatibles avec la palette de 512 couleurs. Après avoir validé le workflow grâce à un petit test avec un vaisseau spatial relativement complexe, le temps était venu de se retrousser les manches et de commencer le travail sur les scènes 3D. J’avais une bonne idée du thème général, mais beaucoup d’idées sont apparues après avoir commencé à travailler sur les premières séquences, celles de la poursuite dans le désert. Remute m’a laissé carte blanche, ce qui est toujours un énorme avantage, avec comme seule requête la présence dans l’animation du robot qu’on aperçoit sur un des extraits vidéo au début du clip. Les sources d’inspiration ont été très variées, de WipeOut pour les vaisseaux évidemment, à Blade Runner et Total Recall pour l’ambiance générale, jusqu’au hangar à dirigeables d’Écausseville.

Le gros avantage quand on utilise une caméra fixe, à l’opposé d’une caméra repositionnable comme généralement dans les jeux 3D, c’est qu’on peut énormément tricher pour parvenir au résultat souhaité, avec à la clé des grosses économies en matière de polygones ou encore mieux, de temps. L’astuce la plus fréquente est l’utilisation de billboards, des formes 2D qui sont alignées avec la caméra, en lieu et place d’objets modélisés en 3D : la silhouette du personnage dans le hangar, les montagnes à l’extérieur, etc. Autre exemple, lors de la plupart des scènes où les véhicules semblent se déplacer, c’est généralement juste le décor qui défile en dessous, comme un tapis roulant, ce qui simplifie énormément la structure de ces séquences.

Storyboarder

À mesure que l’animation gagnait en complexité, il m’est rapidement apparu que j’allais avoir besoin d’un système pour maintenir une vue d’ensemble de toutes les scènes (21 initialement, chacune un fichier Blender différent – pas forcément l’organisation la plus efficace…) et de la durée totale de l’animation. J’ai pour cela utilisé Storyboarder, un logiciel gratuit de storyboard qui a parfaitement joué son rôle.

L’animation 3D devait durer exactement 85 secondes pour être en phase avec la musique. J’avais à peu près 10 secondes de rab après avoir animé toutes les scènes et il fallait donc en supprimer ou raccourcir certaines. J’ai pu économiser beaucoup de temps pour cette dernière étape en découvrant qu’on pouvait importer et exporter des séquences de PNG dans Adobe Premiere Pro, où réorganiser des séquences se fait de manière très visuelle.

Premiere Pro

Même si la masse de travail a été plus importante que prévue initialement, j’ai beaucoup apprécié travailler sur ce projet et suis fier du résultat obtenu. Nous avons réalisé quelque chose d’inédit sur Mega Drive tout en développant en 1 minute 30 une petite histoire que j’espère divertissante dans un univers cohérent.

La sortie d’une production sur support physique est rare aujourd’hui et le fait de voir la cartouche apparaître aux 4 coins du globe est un motif de satisfaction supplémentaire. Espérons que ces collectionneurs continueront d’apprécier l’album pour de nombreuses années.

crédit image : Remute

D’un point de vue plus personnel j’ai évidemment apprécié cet équilibre presque parfait entre contraintes techniques et liberté artistique. La mise en scène et le cadrage de séquences animées sont des domaines assez nouveaux pour moi et m’y frotter a été très intéressant. Enfin cela m’aura permis d’approfondir mes connaissances de Blender et de travailler dans des conditions inédites, comme pour la dernière scène avec le robot, réalisée sur une petite Surface Go lors d’un vol transcontinental.

Enfin si vous êtes à Londres le 22 juin, je ferai une petite présentation sur mon travail sur Red Eyes au London Blender Day.


Voici la ligne de commande Imagemagick que j’ai utilisé pour le tramage avec colorisation avec la palette Megadrive :

convert input.png -ordered-dither hlines2x2a,6 +remap md_pal.gif output.png

Il faut aussi éditer le fichier thresholds.xml dans le répertoire d’Imagemagick pour y ajouter les nouveaux effets de trame. Plus d’information ici.

<threshold map="hlines2x2a">
<description>Horizontal Lines 2x2 (bounds adjusted)</description>
<levels width="2" height="2" divisor="10">
3 3
9 9
</levels>
</threshold>


5 Commentaires

Low Poly Memories, GIF animé pour la Revision 2017

Ce petit billet est consacré à ma deuxième release lors de la Revision 2017. La party organise traditionnellement une compétition de GIF animés, dont les règles sont les suivantes : résolution imposée de 640×360 et taille maximale de 2 Mo.

M’étant occupé en priorité de mon image en pixel art, j’ai commencé à préparer cette animation un peu à la dernière minute – l’avant veille du début de la Revision pour être exact­­­ ! Heureusement la réalisation a été à peu près aussi rapide qu’espérée puisque les objets 3D sont très basiques et sans textures à proprement parler. C’est d’ailleurs ce style graphique et l’absence d’antialiasing qui a permis de caser le maximum d’étapes d’animation dans la limite des 2 Mo.

Un des éléments pour lequel j’ai tâtonné fut en fait la génération de l’animation du tunnel qui devait durer exactement 30 frames pour qu’elle boucle de manière synchronisée avec le reste. Vu mes maigres connaissances en programmation, j’ai dû me résoudre à simuler cet effet 2D avec de la 3D, en déplaçant une texture sur un cylindre aplati.

Puis survint une mauvaise surprise dans la dernière ligne droite : la réalisation à minuit passé que Blender ne supporte pas les textures animés quand on utilise OpenGL Render Animation (qui capture juste les frames rendues en OpenGL, donc très rapide). La mort dans l’âme, j’ai été contraint de faire manuellement un rendu OpenGL pour chacune des 120 images, opération qui s’est terminée dans la douleur vers 2h du matin le jour où commençait la Revision. Tout ça n’aura pas été en vain puisque l’animation a terminé 3e dans la catégorie 🙂

Exocet - Low Poly Memories (Revision 2017 Animated GIF competition)

Low Poly Memories sur Demozoo


1 commentaire

Des exemples d’automatisation de traitement d’images avec ImageMagick

J’avais l’an dernier évoqué ImageMagick, un logiciel de traitement d’images en ligne de commande aussi puissant que parfois difficile d’approche. Dans ce nouveau billet je présente quelques exemples d’utilisation du programme qui m’ont permis d’économiser pas mal de temps ces derniers mois.

À la base le logiciel se contrôle comme suit, après avoir ouvert une fenêtre de ligne de commande dans Windows (ou Mac ou Linux) :

convert image1.jpg actions image2.jpg

On ouvre l’image image1.jpg, effectue une ou plusieurs manipulations dessus puis la sauvegarde sous le nom d’image2.jpg.

Créer un GIF animé

Créer un GIF animé avec ImageMagickUn cas de figure assez fréquent : une animation est exportée d’un logiciel quelconque (Animate, After Effects…) sous la forme d’une suite d’images et on souhaite la convertir en GIF animé. Une opération somme toute très basique, mais étonnamment pas si simple en pratique : l’exportation native de GIF animé dans Animate n’est souvent pas exploitable (une couleur sombre est systématiquement choisie comme transparente même si on ne veut pas de transparence), Adobe Media Encoder pas vraiment idéal en pratique (aucune optimisation du GIF donc un résultat au poids rapidement énorme) et Photoshop trop lent si on veut pouvoir enchaîner les conversions. Avec ImageMagick il suffit de taper la commande suivante dans le répertoire où se situe les images :

convert *.png -dither None -loop 0 -layers optimize -set delay 3 anim.gif
  • -dither None (optionnel) remplace le dithering par des aplats de couleurs, pour dans certains cas un meilleur rendu et un GIF plus léger.
  • -loop 0 permet à l’image de boucler de manière perpétuelle.
  • -layers optimize indique l’animation sera optimisée en actualisant seulement les pixels qui changent d’une frame à l’autre.
  • -set delay 3 indique la durée de chaque frame en centièmes de seconde. Ici 0.03 seconde, donc un framerate d’environ 33 images par seconde.

En laissant la fenêtre Command Prompt ouverte, on peut obtenir un nouveau GIF animé à chaque fois qu’on réexporte les images en appuyant juste sur la flèche du haut puis Entrée.

Recolorer en blanc une série d’image avec une couche alpha

Recolorer en blanc une série d'image avec une couche alphaUne requête un peu plus spécifique mais qui s’est manifestée lors du développement d’un jeu pour Peak : une centaine de sprites en 32 bit devaient être recolorés en blanc tout en conservant la transparence. Facilement réalisable avec Photoshop, mais pas beaucoup plus compliqué avec ImageMagick avec l’avantage de la flexibilité et de la rapidité. Attention, cette commande remplace tous les PNG dans le répertoire.

FOR %a in (*.png) DO convert %a -brightness-contrast "100 0" %a
  • FOR %a in (*.png) DO crée une boucle qui traitera tous les PNG du répertoire (%a est la variable pour les noms de fichiers, répétée telle quelle à la fin de la commande, d’où l’écrasement des fichiers d’origine).
  • -brightness-contrast « 100 0 » augmente la luminosité au maximum et réduit le contraste au minimum, donc toutes les valeurs deviennent blanches.

Redimensionner une série d’images et les recolorer avec une palette prédéfinie

Redimensionner une série d’images et les recolorer avec une palette prédéfinie avec ImageMagick

Ici j’exporte une animation sous forme d’une série d’images que je souhaite ensuite convertir vers une résolution et une palette spécifiques à un ordinateur 8 bit. La commande mogrify utilisée est d’un usage similaire à convert, à la différence que les images d’origine sont systématiquement écrasées.

mogrify -filter "Box" -resize "160x200!" -dither None -remap c:\tmp\nouvelle_palette.png *.png
  • -filter « Box » choisit le filtre « Box » pour la commande resize qui suit. Ce filtre donne les meilleurs résultats dans ce cas de figure (réduction de pixel art sans bavure). Voir la documentation très détaillée sur ce sujet.
  • -resize « 160×200! » indique la résolution souhaitée. Le point d’exclamation signifie que le ratio d’origine sera ignoré.
  • -dither None pour éviter de dithering (dégradés) lors de la conversion.
  • -remap c:\tmp\nouvelle_palette.png : les images sont recolorées avec la palette issue de cette image.

Tripler la résolution d’une série d’images

Tripler la résolution d'une série d'images avec ImageMagick

Drag & drop avec ImageMagickImageMagick permet ici de redimensionner et renommer les images avec un simple drag and drop des fichiers sur une icône du bureau Windows, ce qui est extrêmement pratique. Je me sers de ce script pour modifier pour Twitter des captures d’écran en 320×200 (généralement réalisées pour Demozoo ou Mobygames) qui font un peu timbre-poste sur nos écrans modernes. Il suffit de créer un fichier .BAT avec le contenu suivant :

if [%1]==[] goto :eof
:loop
convert %1 -scale 300%% "%~dpn1_x3%~x1"
shift
if not [%1]==[] goto loop

Le format est un peu différent puisqu’il s’agit de supporter le drag and drop de plusieurs fichiers sur l’icône du fichier .bat.

  • if [%1]==[] goto :eof vérifie si la liste des fichiers transférée n’est pas vide et termine le script si c’est le cas.
  • :loop : label de la boucle
  • convert %1 -scale 300%% triple la résolution
  • « %~dpn1_x3%~x1 » ajoute « _x3 » à la fin du nom de fichier pour éviter d’écraser l’image d’origine. La syntaxe un peu cryptique permet juste de manipuler les différents éléments du nom de fichier (voir ici pour plus de détails).
  • shift : on itère dans la boucle
  • if not [%1]==[] goto loop : on continue tant qu’on n’a pas traité tous les fichiers

Pour changer l’icône du fichier batch, le plus simple est de placer sur le bureau non pas directement le fichier batch, mais plutôt un raccourci vers celui-ci. Il suffit ensuite de faire un clic droit sur l’icone et de cliquer sur « changer l’icône » dans l’onglet « raccourci ».

Il est possible d’effectuer des opérations beaucoup plus complexes avec ImageMagick mais j’espère que ces quelques exemples simples auront aidé à vous convaincre de l’utilité du programme. La prise en main est ardue mais heureusement il existe une documentation en ligne très complète qui permet de ne pas avoir à trop tâtonner.

La documentation officielle pour aller plus loin (en anglais) :


3 Commentaires

Automatiser la création d’images avec ImageMagick et Python

Certains projets peuvent nécessiter la création d’un grand nombre d’images qui ne se différencient que par le texte ou symbole qui y est surimposé. L’exemple typique est une série d’images représentant des « achievements » ou destinées à être partagées sur les réseaux sociaux, telle que celle que j’ai réalisées récemment pour notre projet « Test your memory » chez Peak :

Images générées avec ImageMagick et Python

ImageMagick-wizardImageMagick est une sorte de couteau suisse du traitement d’image gratuit et open-source. Outre les fonctions de conversion (plus de 200 formats supportés), la modification d’images (redimensionnement, rotation, ajouts de texte ou d’éléments graphiques, modification des couleurs…) ou même leur génération complète sont les principaux usages de l’outil. On peut par exemple facilement écrire un script qui redimensionnera une image à 50%, y ajoutera un logo et sauvera le tout en JPEG de qualité 60%. Pratique pour préparer des photos pour un blog, par exemple.

Généralement contrôlé en ligne de commande, ImageMagick est ardu à l’utilisation et nécessite souvent de nombreux essais/erreurs mais la documentation très détaillée et les exemples fournis aident beaucoup. Je m’en suis ici servi pour ajouter deux lignes de texte sur une image existante.

S’il ne semble pas possible d’itérer sur du texte directement, il est par contre possible de contrôler ImageMagick directement dans Python avec une librairie dédiée (PythonMagick) mais l’installation de celle-ci semble trop complexe pour le commun des mortels. La solution que j’ai retenue a été d’utiliser Python uniquement pour générer un fichier .BAT qui permet à ImageMagick de créer les images. Quelques lignes suffisent :

# Generates a batch file for ImageMagick to create 93 FB share pictures
f = open("FBShare.bat","w")
for number in range (1,16):
   f.write('convert c:\Utils\ImageMagick\images\FBShareBG.png -font c:\Windows\Fonts\GothamSSm-Bold.otf '
   '-fill white -pointsize 168 -gravity center -annotate +0-60 "TOP ' + str(number) + '%%" '
   '-font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 120 -gravity center '
   '-annotate +0+70 "MEMORY" c:\Utils\ImageMagick\images\FBShare' + str(number) + '.png' + '\n')
for number in range (18,94):
   f.write('convert c:\Utils\ImageMagick\images\FBShareBG.png -font c:\Windows\Fonts\GothamSSm-Bold.otf '
   '-fill white -pointsize 110 -gravity center -annotate +0-72 "MY BRAIN AGE:" '
   '-font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 140 -gravity center '
   '-annotate +0+60 ' + '"' + str(number) + ' YEARS OLD" '
   'c:\Utils\ImageMagick\images\FBShare' + str(number) + '.png' + '\n')
f.write('PAUSE')

On obtient alors un fichier batch avec les instructions nécessaires à la création des 91 images :

convert c:\Utils\ImageMagick\images\FBShareBG.png -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 168 -gravity center -annotate +0-60 "TOP 1%%" -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 120 -gravity center -annotate +0+70 "MEMORY" c:\Utils\ImageMagick\images\FBShare1.png
convert c:\Utils\ImageMagick\images\FBShareBG.png -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 168 -gravity center -annotate +0-60 "TOP 2%%" -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 120 -gravity center -annotate +0+70 "MEMORY" c:\Utils\ImageMagick\images\FBShare2.png
convert c:\Utils\ImageMagick\images\FBShareBG.png -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 168 -gravity center -annotate +0-60 "TOP 3%%" -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 120 -gravity center -annotate +0+70 "MEMORY" c:\Utils\ImageMagick\images\FBShare3.png
[...]
convert c:\Utils\ImageMagick\images\FBShareBG.png -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 168 -gravity center -annotate +0-60 "TOP 15%%" -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 120 -gravity center -annotate +0+70 "MEMORY" c:\Utils\ImageMagick\images\FBShare15.png
convert c:\Utils\ImageMagick\images\FBShareBG.png -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 110 -gravity center -annotate +0-72 "MY BRAIN AGE:" -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 140 -gravity center -annotate +0+60 "18 YEARS OLD" c:\Utils\ImageMagick\images\FBShare18.png
convert c:\Utils\ImageMagick\images\FBShareBG.png -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 110 -gravity center -annotate +0-72 "MY BRAIN AGE:" -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 140 -gravity center -annotate +0+60 "19 YEARS OLD" c:\Utils\ImageMagick\images\FBShare19.png
convert c:\Utils\ImageMagick\images\FBShareBG.png -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 110 -gravity center -annotate +0-72 "MY BRAIN AGE:" -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 140 -gravity center -annotate +0+60 "20 YEARS OLD" c:\Utils\ImageMagick\images\FBShare20.png
[...]
convert c:\Utils\ImageMagick\images\FBShareBG.png -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 110 -gravity center -annotate +0-72 "MY BRAIN AGE:" -font c:\Windows\Fonts\GothamSSm-Bold.otf -fill white -pointsize 140 -gravity center -annotate +0+60 "93 YEARS OLD" c:\Utils\ImageMagick\images\FBShare93.png
PAUSE

Le gros avantage de cette méthode est la flexibilité qu’elle apporte. Jean-Christian Ranu préfère le fond en rose ? Berthier de la compta veut une version avec le texte en breton ? Inutile de commencer à transpirer à gros bouillons, en deux minutes c’est réglé.

Combiné à Python ou tout autre langage de programmation, les possibilités offertes par ImageMagick sont très vastes. On peut par exemple introduire un facteur aléatoire qui permettra par exemple d’alterner entre différentes images de fond, introduire des règles plus complexes, comme une taille de fonte différente tous les n images ou même générer des frames pour une animation.