Les connaissances ne devraient pas être brevetées, elles sont faites pour être partagées

Karim Aktouf

Dernière mise à jour: 2025-09-17

Banque de cours - Intro à Blender (matière commune)

# Intro à Blender (matière commune)

📌

N’installez pas Blender à travers Steam ou via le Microsoft Store siouplaît, ça crée un tas de problèmes, surtout avec les simulations

Tony de Peltrie de Softimage

# Intro, Blender: Historique, installation, configuration, interface, plugins

Intro

  • Introduction, plan de cours

  • Présentation du professeur

  • Présentation du système d’évaluation/notation du cours

  • Sensibilisation des étudiants au plagiat et l’utilisation de l’IA dans ce cours

  • Rappel sur la notion de droit d’auteur à Rubika Montréal et lien vers le règlement intérieur (Réglement Intérieur - Rubika MT.docx)

Ce gars est tellement inspirant!

Une brève histoire de Blender

https://images.app.goo.gl/ns8cCjE77PQpSrpU8

Histoire de Blender

Blender a été créé par Ton Roosendaal, un directeur artistique néerlandais et développeur de logiciels autodidacte. Attiré par tout ce qui est technique et créatif, Roosendaal a commencé des études en design industriel, mais a abandonné pour créer son propre studio d’animation 3D, NeoGeo, en 1989 (la console de jeux vidéo du même nom est apparue un an plus tard). Initialement basé dans le grenier de Roosendaal, NeoGeo a rapidement grandi, remportant des prix et devenant la plus grande entreprise de son genre aux Pays-Bas.

Roosendaal a écrit les premiers fichiers source intitulés “Blender” le 2 janvier 1994, encore considéré comme l’anniversaire officiel de Blender. À l’origine, Blender était prévu comme une application interne pour NeoGeo ; il a grandi à partir d’une série d’outils préexistants, dont un traceur de rayons construit pour l’Amiga. Cette première version de Blender visait à répondre à une frustration perpétuelle parmi les créatifs : comment mettre en œuvre sans douleur les multiples changements qu’un client difficile demande à un projet ? Grâce à son approche hautement configurable, Blender visait à apporter une réponse. (En passant : le nom fait référence à une chanson d’un groupe électronique suisse, Yello).

Roosendaal a investi ses économies dans une station de travail Silicon Graphics. Coûtant l’équivalent de trente mille dollars américains, cet ordinateur a conduit à Blender 1.0. Lancée en janvier 1995, cette première itération de Blender proprement dite incorporait des idées alors innovantes, notamment une seule fenêtre qui pouvait être subdivisée à la convenance de l’utilisateur.

Pour la petite histoire, les machines Silicon Graphics étaient commercialisés par Pixar, fondé par Ed Catmull de chez Industrial Light & Magic. C’est Steve Jobs qui a convaincu Ed de se concentrer sur la production de films animés plutôt que sur du Hardware. L’algorithme Z-Buffer, inventé par Ed Catmull dans les années 70 roulent sur tous les ordis aujourd’hui.

À l’époque, la 3D était jugée commercialement sans intérêt. Cependant, Roosendaal était tombé amoureux de ce qu’il décrit comme sa “capacité magique à créer tout un monde dans un ordinateur”. Lorsque NeoGeo a fermé, lui et son partenaire Frank van Beek ont fondé une nouvelle entreprise axée sur le développement et la commercialisation de Blender. Not a Number (NaN) a ouvert ses portes en juin 1998, distribuant Blender sous une stratégie de tarification freemium : le logiciel était gratuit à télécharger, avec NaN vendant des clés pour débloquer des fonctionnalités plus avancées.

Blender devient Open Source

Grâce à ce modèle d’affaires, NaN a pu financer un stand à une conférence de renom sur l’infographie à Los Angeles, SIGGRAPH (Special Interest Group on Computer Graphics and Interactive Techniques). En conséquence, Blender a attiré deux tours de financement totalisant environ cinq millions et demi de dollars américains. Malgré cet investissement, un climat économique difficile, des dépenses excessives et des relations tendues entre NaN et ses investisseurs ont conduit à la fermeture de l’entreprise en 2002.

Avec la disparition de NaN, le développement de Blender a cessé. Incapable d’acheter les droits auprès des bailleurs de fonds de NaN, Roosendaal a opté pour un plan novateur. En mai 2002, il a créé une organisation à but non lucratif, la Blender Foundation, dans le but de rendre Blender open-source. Il espérait créer un monument public à Blender, et donner à tous ceux qui avaient travaillé sur le projet Blender la possibilité de l’utiliser pour leur portefeuille. En juillet de la même année, il a lancé la première campagne de financement participatif : Free Blender. Grâce à la communauté de 250 000 utilisateurs de Blender, la Blender Foundation a pu recueillir **cent dix mille euros en seulement sept semaines **- suffisamment pour récupérer Blender de ses investisseurs.

Le dimanche 13 octobre 2002, Blender a été publié sous les termes de la GNU General Public Licence, le contrat open-source le plus strict possible. Non seulement Blender serait gratuit, mais son code source resterait gratuit, à jamais, pour être utilisé à n’importe quelle fin.

Le succès de Free Blender a ouvert la voie à un style de développement qui est devenu la force déterminante de Blender. Si l’évolution de Blender est en partie impulsée par des développeurs financés par des subventions et guidée par une équipe centrale à la Blender Foundation, Amsterdam, son plus grand avantage est une communauté mondiale de bénévoles dévoués. Grâce à leurs efforts, Blender est capable d’itérer rapidement et de répondre aux besoins des artistes et des créateurs. Une telle agilité et créativité seraient beaucoup plus difficiles à réaliser dans le cadre d’un modèle d’affaires traditionnel.

Blender crée des films ouverts

Comme moyen de tester les capacités croissantes de Blender, la Blender Foundation a mis au défi les artistes les plus talentueux de sa communauté de réaliser un court métrage d’animation 3D. Le seul critère était qu’ils devaient utiliser des outils open source, avec Blender en tête de liste.

Sous le nom de code “Project Orange”, ce projet a commencé en 2005, aboutissant à Elephants Dream, une aventure surréaliste à travers une machine gigantesque. Le film et tous ses actifs ont été rendus librement disponibles sous une licence Creative Commons.

Après le succès d’Elephants Dream, le Blender Institute a été créé à l’été 2007. En plus d’aider à définir les objectifs de la Blender Foundation, le Blender Institute comprend un bureau et un studio permanents, avec l’intention expresse de générer des projets ouverts liés aux films 3D, aux jeux ou aux effets visuels. Dans le cadre de sa production, le Blender Institute a créé une série de films ouverts en collaboration avec des artistes de premier plan. Ils comprennent la comédie Big Buck Bunny (2008), le thriller de science-fiction Tears of Steel (2012), une fantaisie poétique Spring (2019) et l’horreur-comédie Sprite Fright (2021).

https://vagon.io/blog/movies-made-with-blender/

Le dernier en lice: Flow!

Flow, the award winning animation was entirely made in Blender:

Jalons de Blender

Chaque projet ouvert impose de nouvelles exigences à Blender en tant qu’ensemble de création 3D, ce qui entraîne à son tour des mises à niveau supplémentaires. Bien qu’une liste complète des mises à jour dépasse le cadre de cet article, certains jalons méritent d’être mentionnés.

Début 2008 a vu le début du projet Blender 2.5. Il a combiné une refonte majeure de l’interface utilisateur, avec de nouvelles définitions d’outils, un système d’accès aux données, une gestion des événements et un nouveau système d’animation. Pour 2.5, l’objectif principal était de mettre à jour les normes de l’interface et les méthodes d’entrée.

Cycles est le moteur de ray-tracing de production de Blender, incorporé pour la première fois dans la version 2.61, en 2011. Au fil des ans, Cycles a introduit le support pour une large gamme de possibilités de rendu, y compris AMD et NVIDIA. De même, il a évolué pour inclure le support de nombreuses fonctionnalités, y compris les cheveux, le flou de mouvement, la fumée et le feu, les principaux shaders et matériaux, les subdivisions adaptatives, les caustiques, et bien plus encore.

Avec sa version 2.8 révolutionnaire en juillet 2019, Blender a fait irruption dans le monde des grands de la 3D. Avec une interface utilisateur radicalement revue, la série 2.8 comprenait une multitude d’innovations, de EEVEE (un moteur de rendu en temps réel), à de nouvelles options de remaillage pour les sculpteurs, à l’intégration de Mantaflow, à un espace de travail d’animation 2D entièrement fonctionnel qui offrait également la possibilité d’un flux de travail hybride 2D/3D.

Bien que la reconnaissance de l’industrie pour Blender ait augmenté au fil des décennies, 2.8 a marqué le moment où il a été largement accepté comme une alternative légitime aux concurrents payants. En plus d’utiliser Blender dans leurs propres projets, certaines des plus grandes et des plus reconnues entreprises du monde sont devenues des contributeurs réguliers au Fonds de développement de Blender, assurant que Blender peut continuer à innover. La chose a forcé Maya à introduire une version plus abordable (Maya Indie), disponible sous certaines conditions.

En plus de Blender et des projets ouverts réalisés avec Blender, il y a le Blender Cloud. Cette plateforme de production ouverte basée sur l’abonnement fournit des mises à jour régulières sur les projets de films ouverts actuels, ainsi qu’une archive d’actifs de films sous forme de fichiers .blend, des décompositions d’animations et de plans, des shaders et des textures, et des vidéos de formation complètes d’artistes professionnels et de développeurs, souvent ceux employés au siège de Blender à Amsterdam.

Blender : Présent et Futur

Au total, l’organisation Blender compte une vingtaine d’employés, travaillant à Amsterdam, à distance, et sur la base de subventions. Pour Blender, cette équipe ne représente qu’une petite partie d’une communauté beaucoup plus large, qu’elle définit comme tous ceux qui contribuent au développement de Blender, gagnent leur vie avec Blender, ou le téléchargent simplement.

La mission de Blender peut se résumer par “mettre la meilleure technologie 3D au monde entre les mains des artistes en tant qu’open-source, et faire des choses incroyables avec elle”.

À l’avenir, Blender espère devenir une organisation durable et à l’épreuve du temps, dédiée à la promotion de sa philosophie de l’open-source, de ses valeurs de curiosité et d’innovation, à un engagement envers l’excellence technique, et à des objectifs créatifs de plus en plus ambitieux.

Blender roule sur un budget annuel de seulement 5 millions de $! On espère qu’au moins 2% de la communauté Blender, depuis Blender Conf 2024, contribue à aider Blender de manière à augmenter le budget à 15 millions.

https://docs.blender.org/manual/en/latest/blender_manual_html.zip

https://docs.blender.org/manual/en/latest/blender_manual_epub.zip

  1. The Complete Guide to Blender Graphics: Computer Modeling and Animation: Volume 1, Sept. 19 2023 by John M. Blain
  2. The Complete Guide to Blender Graphics: Computer Modeling and Animation: Volume 2, Sept. 19 2023 by John M. Blain
  3. Learn Blender Simulations the Right Way: Create attractive and realistic animations with Mantaflow, rigid and soft bodies, and Dynamic Paint Paperback – Nov. 18 2022

Si vous voulez aller plus loin:

Unreal Engine:

Unity:

La doc importante pour nous Simulation: https://docs.blender.org/manual/en/4.0/physics/index.html

Shortcuts et cheat sheets

Les drivers Nvidia

  • Télécharger et installer l’app NVidia

  • Démarrer l’app NVidia et choisir les drivers “Studio”

Configuration de Nvidia pour Blender

💡

Note: Le NVIDIA Control Panel se trouve dans “Settings” dans l’app nVidia, tout à fait en bas : “NVIDIA Control Panel”

En gros:

  • Démarrer l’app NVIDIA et télécharger les derniers pilotes Studio

  • Cliquer sur Settings et, tout à fait en bas, choisir Open à droite de “NVIDIA Control Panel”

  • Dans “Adjust Image Settings with Preview”, s’assurer de sélectionner “Use the advanced 3D image settings”:

  • Dans “Configure Surround, PhysX”, s’assurer que Processor est bien votre carte graphique:

  • Finalement dans Manage 3D settings, d’abord faire “Add” pour rajouter l’executable Blender (s’assurer de rajouter la bonne version):

  • Enfin s’assurer que les paramètres en gras sont configurés comme suit:


Configuration de Blender

  • Edit → Preferences

  • Interface

  • Système

  • Keymaps

  • Navigation

  • Save & Load et Autosave de la configuration

  • Addons pré-installés à activer

  • Sauvegarde du fichier de démarage, après avoir retiré le cube par défaut, sa caméra et la source de lumière

Plugins essentiels

BlenderKit

  1. Créer un compte sur https://blenderkit.com
  2. Télécharger le plugin BlenderKit (la version gratuite)

PowerSave

  1. Créer un compte sur https://blendermarket.com
  2. Chercher le plugin PowerSave (c’est gratuit!) et téléchargez-le (https://blendermarket.com/products/powersave)
  3. Configurer autosave pour qu’il créé des fichiers de backup toutes les deux minutes en rajoutant un suffixe.

Realtime materials (Demo)

  1. Cherchez le plugin Realtime Materials for Blender (la version démo est gratuite) (https://blendermarket.com/products/realtime-materials-for-blender)

Introduction à l’interface

  • 3D Viewport (fenêtre) au centre
  • Outliner (plan et table de contenu) en haut à droite
  • Properties (propriétés) en bas à droite
  • Timeline (Éditeur de chronologie) en bas au centre

Un pléthore de workspaces supplémentaires Modélisation : Pour la modification de la géométrie par les outils de modélisation. Sculpture : Pour la modification des maillages par les outils de sculpture.

Édition UV : Pour le mappage des coordonnées de texture d’image sur des surfaces 3D.
Peinture de texture : Pour colorer les textures d’image dans la vue 3D.

Ombrage : Pour spécifier les propriétés des matériaux pour le rendu.

Animation : Pour rendre les propriétés des objets dépendantes du temps.

Rendu : Pour visualiser et analyser les résultats de rendu.

Composition : Pour la combinaison et le post-traitement des images et des informations de rendu.

Nœuds de géométrie : Pour la modélisation procédurale en utilisant les Nœuds de géométrie.

Scripting : Pour interagir avec l’API Python de Blender et écrire des scripts.

Animation 2D : Espace de travail général pour travailler avec le Crayon à Graisse.
Toile 2D complète : Similaire à “Animation 2D” mais contient une toile plus grande.

Masquage VFX : Pour créer des masques 2D pour la composition ou le montage vidéo.
Suivi de mouvement : Pour calculer le mouvement de la caméra et stabiliser les séquences vidéo.

Première modélisation, un ballon

  • File → New → General

  • ⇧A → Mesh - → UV Sphere

  • Dans l’espace de travail “Shading”, sélectionner la sphère, s’assurer d’être en mode “Object” et non pas “World” et cliquer sur “New”

  • ⇧A → Texture → Checker Texture

  • Connecter Color de noeud texture à “Base Color” du “Principled BSDF”

  • Changer la couleur 2 pour une couleur de votre choix plus intéressante

  • Avec le Checker Texture sélectionné, appuyer sur ⌃T (Node Wrangler doit être activé dans les préférences). Cela va rajouter un contrôle des coordonnées de la texture.

  • Connecter la sortie UV de Texture Coordinate à l’entrée Vector du noeud Mapping.

  • Changer le scale à 2.

  • Cliquer droit sur le ballon → Shade Smooth by Angle

  • Baisser la rugausité “Roughness” du Principled BSDF à 0.2

  • Revenir à l’espace de travail “Layout”, appuyer sur Z et choisir Rendered

  • Ajouter une caméra: ⇧ A → Camera → Camera

  • Ajouter une source de lumière: ⇧A → Light → Point Light

  • G et bouger la souris pour sortir la source de lumière de la sphère (les objets sont crées là où se trouve le curseur 3D)

  • Changer l’intensité de la lumière à 1000 W

  • Appuyer sur ⌃ + ⌥ + 0 du pad numérique pour positionner la caméra exactement au point de vue de l’espace de travail “Viewport”. La caméra va se déplacer et se positionner de manière à partager ce même point de vue.

  • Render → Render Image! Dans Cycles et dans EEVEE

From Maya to Blender

Devoirs

  • Passer au travers de ces trois tutoriels

# Éclairage, caméra, rendering, compositing, render farm

Configuration de EEVEE EEVEE est le moteur de rendu temps réel de Blender. Très efficace mais beaucoup moins réaliste, il n’utilise pas de ray tracing. EEVEE peut tout de même produire des rendus de très haute qualité.

Sampling: Le nombre d’échantillons par pixel

Ambient Occlusion: Occlusion ambiante, le noir causé par l’absence de lumière dans les endroits où la lumière ne peut pas pénétrer. Coût cher à calculer mais augmente le réalisme et le contraste.

Bloom: effet de post-traitement qui diffuse les pixels très lumineux. Ceci imite les artefacts de lentilles des vraies caméras (e.g. effet de halo (glare)).

Screen Space Reflections: Comportement des rayons de lumière plus réaliste (réflexions, réfractions, etc.)

Motion Blur: Flou occasionné par le mouvement d’un frame à l’autre.

Volumetrics: Interaction des rayons lumineux avec les volumes tels que le brouillard par exemple.

High Quality Normals: Meilleur rendu grâce à un calcul plus précis des normales à la surface

Shadows: Ombres portées de meilleure qualité

Film: On ne veut pas voir le HDRI, mais on garde son effet d’éclairage ambiant

Simplify: Simplification intelligente de la scène pour des rendus plus rapides

Look: Augmenter le contraste des rendus

Configuration de Cycles Cycles est le moteur de rendu réaliste de Blender. Il utilise la technique de raytracing et est basé sur le tracé de chemin physique de Blender pour la production. Il est conçu pour fournir des résultats basés sur la physique dès le départ tout en fournissant une pléthore de contrôles artistiques et autres nœuds de shading flexibles pour les besoins de production.

Device: Évidemment, si l’on a une carte graphique, autant l’utiliser: Device = GPU Compute

Viewport: Dans le viewport (temps réel):

Noise Threshold: Seuil de bruit en deça duquel on arrête de générer de nouveaux échantillons pour un pixel.

Max Samples: Nombre d’échantillons par pixel dans le viewport de travail.

La réduction du bruit dans le viewport ralentit l’interaction

Render: Rendu final:

Noise Threshold: Seuil de bruit en deça duquel on arrête de générer de nouveaux échantillons pour un pixel.

Max Samples: Nombre d’échantillons par pixel

Denoise: On activera la réduction du bruit dans le compositor. Ce dernier utilise OpenImageDenoiser plutôt qu’OptiX. OpenImageDenoiser est plus précis et plus cohérent (ce qui génère moins d’artéfacts dans les animations et rends le rendus moins dépendants du type de carte graphique) et la réduction du bruit dans le compositor plutôt qu’au moment du rendu diminue le temps du rendu de chaque frame.

Max Bounces: Le nombre de rebonds d’un rayon de lumière en fonction de son type. Par exemple, s’il n’y aucun objet transparent dans notre scène, on peut réduire le nombre de rebonds des rayons transmis à travers une surface (“Tramsmission”) à 1.

Caustics: Veut-on des réflexions caustiques dans notre scène? Elles peuvent êtres causées par la réflexion (lumière qui rebondit sur une surface réfléchissante) our par la réfraction (lumière qui passe à travers un médium différent ayant un certain niveau de transparence). Cela peut coûter très cher en termes de rendus, mais rends très réaliste les scènes impliquant de l’eau par exemple. On l’activera quand on fera de la simulation de fluides.

Simplify: Simplification intelligente de la scène pour des rendus plus rapides

Motion Blur: Flou occasionné par le mouvement.

Film Transparency: On ne veut pas voir le HDRI, mais on garde son effet d’éclairage ambiant

Look: Augmenter le contraste des rendus

Configuration de l’output Output en mode frame par frame. On favorise pour l’instant PNG à EXR car SheepIt Render Farm mets beaucoup de limitations pour les fichiers EXR.

Le mode output vers des fichiers (1 fichier par frame) permet de pouvoir continuer là où on était rendu en cas de crash.

Resolution: Mode Full HD portrait

Frame Rate: Entre 24 et 30 FPS typiquement.

Frame Range: Dépend des paramètres du timeline

Output: Les images seront générées dans un répertoire nommé “export” relatif au dossier dans lequel se trouve votre fichier Blender (car le nom du dossier commencer par //). Ne pas oublier non plus le suffixe “/”, sinon les images seront générées dans le même dossier que le fichier .blend et ils commenceront aver le préfixe “export_”.

Color et Color Depth: Privilégier RGBA si vous avez de la transparence dans vos frames. 16 bits pour les couleurs donnent un rendu de meilleure qualité, mais en général pas nécessaire pour des vidéos de plus faible qualité.

Post Processing Pipeline Compositing: on veut que les paramètres qu’on a configuré dans le Compositor soient utilisés et appliqués sur chaque frame.

Post Processing Pipeline Sequencer: Si on a déjà une séquence d’images dans le Video Sequencer, c’est le rendu de l’édition vidéo qui se fera à la place.

On utilise le mode génération de vidéo soit parce que l’on a déjà notre séquence d’images, soit parce qu’on ne veut pas faire d’édition vidéo et prend le risque de perdre notre rendu en case de crash si l’on génère directement une vidéo. L’autre option, que je préfère, c’est d’importer la séquence d’images dans votre logiciel d’édition vidéo (Da Vinci Resolve, Adobe Premiere, Final Cut Pro, …)

File Format: On privilégie le format FF MPEG pour plus de compatibilité.

Container: Le container le plus versatile pour le moment est MPEG-4

Video Codec: H.264 et l’un des codecs (enCOder - DECoder) les plus répandus (H.265 commence à l’être aussi).

Audio Codec: On peut mettre du son dans le séquenceur (édition vidéo) de Blender, si si!

Post Processing: Ici Blender saura, par la présence des séquences d’images dans le séquenceur, qu’il faut générer la vidéo à partir du séquenceur et non pas le rendu+compositing de chaque frame.

Configuration du HDRI et du Compositing

HDRI

  • Télécharger le HDRI suivant: https://drive.google.com/file/d/1F-WJRFaQ32RiQfKDZFNuoKtt7h5P_dTT/view?usp=sharing

  • Ce HDRI créé une lumière diffuse d’un plafond nuageux propice à la majorité des scènes, c’est-à-dire qu’il ne cause pas de coloration dû à une lumière du soleil trop intense par exemple. En ce sens, ce HDRI illumine sans créer d’effets involontaires.

  • Dans votre dossier Blender, créer un dossier “HDRI” et y copier le fichier HDRI

  • Dans l’espace de travail “Shading”, activer “Use Nodes”, choisir “World” et créer les noeuds suivants.

  • On commence par créer le noeud “Environment Texture”: ⇧ A → Add → Texture → Environment Texture

  • Cliquer sur le dossier pour choisir votre HDRI (abandoned_slipway_4k.exr)

  • Ajoutons le background Shader: ⇧ A → Shader → Background. Connecter la sortie “Color” du Environment Texture à l’entrée Color du Shader Background.

  • Ajouter le noeud World Output sinon on ne verra rien: ⇧ A et taper “World Output” (search automatiquement), ou alors ⇧ A → Output → World Output.

  • Connecter la sortie “Background” du Background Shader à l’entrée “Surface” du World Output.

  • Sélectionner l’Environment Texture et appuyer sur ^ T (une fonction de l’addon Node Wrangler).

  • Pourquoi ajouter un noeud “Mapping”? Changer la rotation Z par exemple et vous verrez l’effet de rotation de l’environnement HDRI dans votre scène.

  • Retourner à l’espace de travail “Layout” et enlever le mode “Transparent” de la section “Film” de vos paramètres de rendu Cycles ou EEVEE. Avec le bouton du centre de la souris, tourner le point de vue du Viewport pour voir le HDRI dans toute sa splendeur.

  • Ne pas oublier d’activer “Transparent” à nouveau à moins que vous vouliez que le HDRI soit apparent dans vos rendus.

  • Changeons l’intensité du HDRI à 0.3 au lieu de 1, de manière à ce que la lumière ambiante ne soit trop intense. Choisir “World” dans l’espace de travail des propriétés et réduire Strength à 0.3

Compositing

  • On se rappelle qu’on veut activer la réduction du bruit dans le compositeur plutôt que dans le moteur de rendu. Choisir Cycles comme moteur de rendu (car il n’y a pas de réduction de bruit en EEVEE et si c’est ce dernier qui est le moteur activé, les paramètres de réduction du bruit ne seront pas disponibles).

  • Dans les propriétés Layers, s’assurer que dans “Data”, “Denoising Data” est activé.

  • Maintenant choisir l’espace de travail “Compositing” et activer “Use nodes”.

  • On va d’abord créer un noeud “Render layers” pour pouvoir récupérer les données de réduction de bruit.

  • Créer un noeud Color Balance et un noeud “Denoise”.

  • Connecter la sortie “Image” du noeud Render Layer à l’entrée Image du noeud “Color Balance” puis connecter la sortie “Image” de ce dernier à l’entrée “Image” du noeud Denoise.

  • En même temps, connecter les sorties “Denoising Normal” et “Denoising Albedo” du noeud Render Layer aux entrés, respectivement, “Normal” et “Albedo” du noeud Denoise.


- [ ] tout dépendant du type de colorisation que l’on recherche, on peut travailler la balance des couleurs dans le compositor et cela affectera chaque rendu.
- [ ] Maintenant créer un noeud Glare puis un noeud Lense distortion et les connecter en série à la suite du Denoise par les entrées et sorties Image appropriées. Configurer ces deux nouveaux noeuds comme suit:


- [ ] On peut jouer avec les paramètres des noeuds Glare et Lens Distortion pour exagérer les effets de halo et de distortion. Ici, les noeuds sont configurés de manière à créer un effet subtil.

- [ ] Ajouter un noeud RGB Curves qui nous donnera plus de contrôle sur la colorisation ainsi que les ombres et lumières si nécessaire. s’assurer que l’option “Filmlike” est choisie.
- [ ] Ajoutons maintenant un noeud “Brightness/Contrast” puis un noeud “Gamma” que l’on connectera en série à RGB Curves via les entrées/sorties Images. 
- [ ] Enfin, la sortie Image du noeud Gamma sera connectée deux fois. Une fois à un nouveau Noeud “Composite” (sinon le compositing ne se fera pas) et une seconde fois à un noeud “Viewer” qui nous permettra de voir l’effet du compositing directement dans l’espace de travail.
- [ ] S’assurer que “Use Alpha” (transparence) est cochée dans les deux cas.


- [ ] Cela nous permet maintenant, en fonction de nos besoin, d’avoir plus de contrôle sur la luminosité et le contraste de nos rendus ainsi que sur la correction Gamma.

- [ ] On devrait se retrouver avec le graphe de noeuds suivants dans l’espace de travail de compositing à la fin:


- [ ] Si vous voulez un channel Alpha (transparence dans Blender), il faut non seulement activer “Transparent” dans la section Film des paramètres Render de Cycles, mais également, dans les paramètres Output choisir PNG RGBA et, enfin, dans le Compositor, connecter la sortie Alpha du noeud Render Layers à l’entrée Alpha du noeud Composite. Viewer aussi si vous voulez voir le résultat dans le Compositor.

Configuration du timeline

  • Avec la souris sur l’espace de travail Timeline, cliquer droit et choisir “Interpolation Mode → Bézier” puis refaire la même chose pour choisir “Easing Mode → Automatic Easing”
  • Ainsi, l’interpolation entre deux keyframes se fera selon une spline de type Bézier (courbe douce) et l’accélération/amorce du début ou de la fin seront déterminés en fonction, justement, du type d’interpolation.

Configuration de l’espace de travail d’édition vidéo

  • Ajoutons un nouvel espace de travail: édition vidéo.
  • Sur la barre du haut, à droite de Scripting, cliquer sur le bouton + et choisir Video Editing → Video Editing
  • L’espace ressemble maintenant à ceci:
  • Le séquenceur vidéo montre un horodateur plutôt que les numéros de frames. Rajoutons le timeline car ce dernier montre les numéros de frame. Amener la souris entre le Video Sequencer et la fenêtre de “Preview” et cliquer droit puis choisir “horizontal split”.
  • Déplacer la souris un peu vers le haut (pas trop) et cliquer gauche. Dans le sélecteur de workspace, choisir Timeline.
  • Ça y est, nous avons un environnement d’édition vidéo adéquat:

Configuration du fichier .blend (inclure tous les fichiers externes)

  • File → External Data : s’assurer que “Automatically Pack Resources” est activé. Les fichiers .blend seront plus gros mais contiendrons toutes les ressources utilisées (sauf la cache de la cuisson des simulations (baked data cache)).

Sauvegarde du fichier par défaut

  • Choisir l’espace de travail “Layout”.
  • On passe au niveau Pro: on efface le cube, la caméra et la lumière qui se trouvent dans notre scène; soyons fous.
  • On sauvegarde le Startup File: File → Defaults → Save Startup File

Installation et configuration de Sheep-it Renderfarm


  • Dans la section Get Started, télécharger le client
  • Le client est le fichier téléchargé lui-même, même si le nom porte à confusion; il n’y a donc rien à installer. Copier le client dans un dossier à part (un dossier SheepIt dans votre dossier qui contient le dossier des HDRI par exemple).
  • Exécuter le client et aller dans “Settings”, entrer votre nom d’usager et votre mot de passe. Cocher uniquement NVDIA (pas CPU), maximiser CPU cores et Memory mais réduire la priorité à “Low”. “Block EEVEE” projects devrait être activé sinon le CPU de votre ordi va beaucoup souffrir.
  • S’assurer que “Auto sign in” est coché.
  • Cliquer sur “Save & go back”.

  • Le client devrait déjà recevoir des tâches (frames à générer) à exécuter. Évidemment, vous ne voulez pas que cela interfère avec votre travail. Configurons le client pour qu’il démarre à une certaine heure le soir pour ne rouler que la nuit.

Dans la barre de recherche de Windows, chercher pour “Task Scheduler” et démarrer cette app.

  • Cliquer-droit sur “Task Scheduler Library” et choisir “New Folder…” que l’on nommera “SheepIt”.

  • Cliquer sur le dossier “SheepIt” pour le sélectionner puis, dans l’onglet “Actions”, choisir “Create Task…” et nommez-là “Start SheepIt Client”

  • Choisir l’exécutable du client SheepIt dans “Program/script” et cliquer sur OK.

  • Vous devriez avoir l’action suivante maintenant dans l’onglet “Action”

  • Dans l’onglet “General” de cette nouvelle action, vérifier le nom ou l’y inscrire (”Run SheepIt Client”).

  • S’Assurer que “Run only when user is logged on” est activé.

  • Dans l’onglet “Triggers” (déclencheurs), créer un nouveau trigger, le configurer comme suit (par exemple démarrer le client à 20h le soir)

  • Malheureusement le “Stop task” ne semble pas fonctionner; quand vous arrivez le matin à votre poste de travail, ne pas oublier d’arrêter le client SheepIt.

  • Cliquer sur OK et vous devriez voir ce nouveau trigger:

  • Configurations dans l’onglet “Conditions”:

  • Configurations dans l’onglet “Settings”:

  • Si vous voulez que le client SheepIt roule pendant la nuit, rester logged-in sur votre station de travail, donc pas de logout (ou signout ?), juste lock screen.

M’en fous, pas l’temps, rien à cirer, donne-moi le fichier défaut grave direct pliiize

Now, here’s a real Blender for beginners course!

Lien vers l'original

Banque de cours - Anim Shading, contour, techniques de modé rapides

# Anim : Shading, contour, techniques de modé rapides

Toon shader Cycles

  • Cycles a maintenant un shader intitulé Toon BSDF. Mais il ne donne pas le même résultat qu’en EEVEE et le noeud “Shader to RGB” n’est pas disponible.

📌

L’effet visuel est un peu meilleur si on passe de Filmic à Standard pourle View Transform dans la section Color Management des paramètres de Cycles. Look à medium Contrast peut aider également.

Toon Shader EEVEE

  • Télécharger ce fichier Blender de départ:
  • En mode EEVEE, si on transforme la sortie d’un shader (Diffuse, Glass, Principled, etc.) en couleurs RGB et qu’on passe ses couleurs dans un color ramp en mode “constant”, on obtient un toon shader de type “cell shading”!
  • On a justement modifié le Color Management des paramètres EEVEE, pour Standard au lieu de Filmic pour View Transform et Medium Contrast pour le Look.
  • Sélectionnez le empty qui contrôle tout l’objet
  • Avec le N menu, sous Item, keyframons par un driver la rotation de l’axe des Z en inscrivant: “#frame / (pi / 180)”.
  • L’objet tourne alors de 1 degré par frame sur 360 frames. On a rapidement un turnaround complet.
  • Faites “Play” et expérimentez avec d’autres couleurs dans le color ramp, ajoutez des color stops, modifiez la distance entre elles, etc.
  • Dans un toon shader traditionnel, il y a trois tons:
    • La couleur locale (midtones) : choisissez une couleur de votre choix et placer le stop au centre à peu près.
    • La couleur de l’ombre: Copiez la couleur locale, paste dans un stop à gauche, réduire la valeur (Value), ça va rendre la couleur plus sombre tout en conservant la même teinte. Augmenter un peu la saturation (au choix).
    • La couleur des rehauts de lumière: encore une fois, même teinte (Hue) que la couleur locale, mais Valeur plus élevée (plus de lumière) et une bien moins grande saturation en pigments, ce qui donnera de la lumière.

📌

Si vous amenez la souris au-dessus d’une couleur, vous pouvez faire copier/coller!

  • On peut aussi utiliser un color ramp au lieu du Mix Node, c’est plus intuitif et inverser

Toon shader sensible aux couleurs de l’environnement en EEVEE

Dessin à l’encre (ma technique préférée en dessin!)

Noir et blanc

  • Changer le color ramp pour deux couleurs, pur noir et pur blanc.
  • Changez Constant pour d’autres valeurs pour voir l’effet. Par exemple, en B-Spline (n’oubliez pas de le faire pour les yeux également), voici ce qu’on obtientÈ

Halftone

  • Ajoutons un Voronoi Texture à la patente.
  • changer Scale à 20 et Random à 0.
  • ⌃ ⇧ - left click sur le noeud Voronoi pour un preview
  • Remplacer le color ramp par un Math node de type “Greater than”
  • Comparer Shader to RGB à Voronoi via le noeud Greater Than:
  • Il faut inverser les ronds blancs et les rond noirs. Ajoutons un Mix node. La distance du Voronoi est connectée à Factor du Mix Node, avec une valeur de 1 pour A.
  • Ça va inverser le toutim.
  • Premièrement, halftone est une technique 2D utilisé dans les bandes-dessinées des années 50. Donc changeons la dimension de la texture Voronoi de 3D à 2D.
  • Mais les coordonnées sont tout décâlissées.
  • Quelles coordonnées utiliser pour que qu’on ait une impression de halftone? Par défaut c’est Generated du noeud Texture Coordinate squi est branché, même si le noeud n’est pas présent et, manifestement, ça ne marche pas:
  • Drag l’input Vector du Voronoi vers la droite et choisir “Texture Coordinates - Camera”.
  • Changer le scale de Voronoi à 60 et faites play ou déplacez-vous dans le viewport.
  • Chouette chouette!

Hatching (gravure)

  • Changer Voronoi pour Wave Texture. Scale à 30.
  • Ajouter un Vector Rotate Node entre Texture Coordinates et Wave Texture.
  • Changer le type de Vector Rotate à Euler et changer la rotation Z à “45d”
  • jouez avec la rotation en Z et avec la valeur A du Mix Shader.
  • Ah oui mais je ne veux pas que mon objet soit blanc, et si je change la couleur du Diffuse BSDF, ça ne fait rien. On peut utiliser un Mix Color mode en mode “Multiply” (comme le mixing de layers dans Procreate, Affinity Photo, PixelMateor, Krita, Gimp, etc.)
  • Maintenant la couleur du shader va se “multiplier” à celle de la texture Wave.
  • En mode “Color Burn”, les hachures seront plus foncées. On peut aussi Amener le Factor de ce shader à 1 pour “favoriser” l’input B. (0 favorisera l’input A).
  • Pour aller plus loin dans les hachures, ce tuto est sumpa, mais il faut l’adapter à Blender 4.3 (il a été fait avec Blender 2.9). Cela étant dit, le jeu des textures Noise, Voronoi, Wave, etc., n’a pas beaucoup changé:

Outline (ligne de contour)

  • Revenir au premier Toon Shader:

Layer Weight

  • Ajouter un Layer Weight node, un Math Node et un Mix Color node. Connecter Facing à Value de Math Node que vous changez à Greater Than.
  • Mettre le Threshold à 0.7. En gros, si la normale (Facing) dans le layer Weight est plus grande que 0.7, mettre le Factor du Mix Color Node à 1, ce qui favorisera l’entrée B (la sortie du Color Ramp), sinon, ça va prendre la valeur de A, i.e. la couleur noire.
  • Contrairement à Fresnel (effet de la couleur sur les bords d’une surface), Facing, qui indique combien la surface fait face à la caméra, ne tient pas compte de l’indice de réfraction.
  • Connectez l’output de Less Than à Factor du Mix Color node.
  • Connecter le Color Ramp à l’input B du Mix color. L’input A du Mix color devrait être la couleur que vous voulez du contour (j’ai choisi noir).

Freestyle

  • Revenir au Toon Shader de base.

  • Activer “Freestyle en mode Relative” dans les paramètres de EEVEE.

  • Faite Render Image.

📌

On ne voit pas l’effet dans le viewport car Freestyle est un effet post-process et EEVEE ne peut le montrer dans le viewport.

  • Chouette non!
  • Voici l’animation turnaround 360 en freestyle:

Grease Pencil Line Art

  • Revenir au toon shader de base encore une fois.

  • désactiver Freestyle dans les paramètres d’EEVEE.

  • Ajouter un Grease Pencil Stroke à la scène. Le déplacer hors caméra:

  • Avec le Grease Pencil stroke sélectionné, ajouter un modifier de type Lineart:

  • Pour la collection qui sera affectée par le grease pencil, choisir “Cute cat in the red hoody”

  • Layer: Color (i.e. dans quel Layer on veut assigner les “strokes” générés)

  • Material: essentiellement la couleur à donner aux strokes. Choisir le material “Black”.

  • Line thickness à 10.

  • Dans les paramètres Layers, activer, dans la section “Data”, “Combined” et “Z”, pour bien rendre des scènes qui utilisent Grease Pencil, c’est nécessaire.

  • And wala!

  • Il faut être en vue caméra pour que ça fonctionne.

  • Jouer avec les paramètres du lineart modifier.

📌

  • Ah oui, sélectionnez le Grease Pencil Stroke. Passez en Edit mode. C’est comme un vector, on peutle modifier, faire Extrude, déplacer les Vertex, etc.!

Painterly textures

  • Revenons au fichier Toon Shader startup file
  • https://drive.google.com/file/d/1czeHQn3n-3ke0F_d22QUk9QkYkwywXdq/view?usp=drive_link
  • Cliquer sur l’empty du chat, et faire un scale 20 (S 20), l’objet est trop petit pour ce qu’ont veut faire sinon.
  • Sélectionner le corps et ajouter un Principled BSDF qu’on connecte au noeud Material Output.
  • Ajouter un Voronoi Texture. Connecter Position au Base Color du shader
  • ⌃ ⇧ - left-click sur ce dernier pour avoir un preview.
  • Ok, drag Vector du Voronoi vers la gauche et choisir Texture Coordinate - Normal.
  • Reconnecter le Shader au Material Output
  • Connecter Position du Voronoi non pas au Base Color du shader mais bien au socket Normal.
  • Maintenant on va adoucir les bords.
  • Ajouter un Noise Texture ainsi qu’un Mix Color Node.
  • Socket Normal de Texture Coordinates dans A de Mix Color.
  • Socket Object de Texture Coordinates dans Vector de Noise, socket Fac de TExture dans B de Mix Color.
  • ⌃ ⇧ - left-click sur le Voronoi pour l’effet de l’ajustement de Factor de Mix Color pour favoriser l’input de la normale ou celui du noise. Observez l’effet. 0.4 c’est chouette.

📌

Si c’est distance de Voronoi qui est connecté à Material Output, connecter plutôt Color ou Position, c’est plus facile à voir ainsi l’effet.

  • Ajuster également les paramètres du Noise pour obtenir l’effet désiré.

  • Moi j’ai gardé les paramètres du Noise à leurs valeurs par défaut, et le FActor du Mix Color à 0.15.

  • Ajustons par contre les paramètres du Voronoi:

    • Scale = 4
    • Detail = 1
  • Reconnecter l’output du shader à Surface du Material Output

  • On va utiliser une Brush d’un asset pack nommé Crafty Asset Pack (la version gratuite) disponible sur BlenderMarket (https://blendermarket.com/products/crafty-asset-pack)

  • Téléchargez le asset file ici: https://drive.google.com/file/d/1x6vBpFAMwNHQI6OpMIpmpmH8rhCE43-H/view?usp=sharing

  • Dans Edit → Preferences → File Paths, trouver le chemin vers “User Library”, copier le fichier à cet endroit sur votre ordi. (Dans mon cas, c’est /Users/bahanzai/Documents/Blender/Assets)

  • Créer un nouveau workspace à gauche du Shader Editor et aller vers l’Asset Library, choisir User Library.

📌

  • Si vous ne voyez rien, sauvegardez votre fichier blender, et redémarrer Blender.
  • On va aller chercher le normal map de l’asset 4k-Paint-Brush.

  • Créer un UV Sphere dans le viewport. Le déplacer un peu.

  • Drag and drop le 4K-Paint—Brush de l’Asset Browser sur la UV Sphere.

  • Vous devriez voir apparaître le shader du UV-Sphere, avec un Node group nommé Paint-Brush.

  • Cliquez sur ce node Group et faire “Tab” aller dedans.

  • Sélectionnez le noeud “Paint-Brush_normal.png node et faire Copier.

  • Sélectionner le corps du chat.

  • Faire Paste. Le noeud normal map devrait apparaître.

  • Connecter le socket Object de Texture Coordinates à Vector du nouveau noeud Normal Map.

  • Insérer un Mapping Node entre les deux. Cela va permettre de contrôler la taille de cette normal map.

  • Drag le socket Scale du Mapping vers la gauche et ajouter un Value Node. Ça va nous permettre de contrôler uniformément le scale.

  • On va utiliser le Normal Map pour contrôler le Voronoi Texture ainsi que la normale du Shader.

  • Sélectionner le Mix Node, faire ⇧ D pour le copier immédiatement à sa droite.

  • Changer le blend mode à Linear Light pour les deux.

  • Connecter le socket Color du normal map à l’entrée B du 2ème Linear Light Node.

  • Essentiellement, on vient de mélanger l’info des normales de l’objet, avec celle du Noise Texture et celle du Paint-Brush normal map.

📌

P.S., j’ai retiré le workspace Asset Browser.

  • Connecter la sortie Color du normal map au socket Color d’un Normal Map node qu’on connecte au socket Normal du Shader.
  • Changer la couleur du Shader à une couleur de votre choix. Je vais rester dans le rose bombom.
  • Changer la projection du noeud Paint-Brush_normal à Box pour avoir une meilleure project UV.
  • Vous devriez voir l’effet du brush stroke.
  • Si vous trouvez que les brush strokes sont trop intenses, augmenter le Blend à 1 dans le Paint-Brush_normal.png node.
  • Augmenter également le Strength du Normal Map à 5.
  • Maintenant, on doit mélanger l’effet du Voronoi Texture à celui du Normal Map texture.
  • Ajoutons Un Mix Color et le laisser purement à Mix et combiner Position du Voronoi (dans A) et la Normal du normal map (dans B).
  • Moi j’aimerai voir plus du Voronoi et moins les brush strokes. Ajustons le Factor de ce Mix Shader pour favoriser son input A.
  • Ajustons Factor à 0.3 environ.
  • Ok, on va aller chercher maintenant la composante Paint-Brush_diffuse du paint brush.
  • Sélectionner la sphère, on devrait se retrouver dans les shader nodes de la sphère.
  • Encore une fois, sélectionner le Node Group et rentrer à l’intérieur avec Tab.
  • Sélectionner le noeud Paint-Brush-diffuse.png, le copier.
  • Sélectionner le corps du chat.
  • Faire Paste
  • Vous devriez voir maintenant la texture Paint-Brush_normal.png apparaître.
  • Connecter la sortie Vector du noeud Mapping à Vector du Paint-Brush_diffuse.
  • Changer la project à Box au lieu de Flat et monter le Blend à 1.
  • On va mélanger la couleur du Paint-Brush_diffuse et la couleur du Voronoi, en mode Multiply. Créer un Mix Color, en mode Multiply. Connecter Color de Paint-Brush_diffuser au Socket B, et Color du Voronoi au socket A. Factor à 0.7, donc 30 % diffuse, 70 % Voronoi.
  • ⌃ ⇧ - Left-click sur le Mix Multiply pour voir l’impact visuellement
  • Pour le Voronoi, on ne veut pas de la couleur, mais un greyscale. Un color ramp par défaut fera l’affaire:
  • Dupliquer le Color Mix Multiply le plus à droite. Connecter Result du premier à Factor cette fois du 2e.
  • Connecter le Result du 2e à Base Color du Principled BSDF Shader
  • Ce que ça va faire, c’est
  • Ajustons maintenant les couleurs A et B. Choisir une couleur chaude pour A et une froide pour B.
  • En gros le Voronoi, à 70 %, et le diffuse Map du paint brush, à raison de 30 %, vont contrôler le mélanger entre la couleur froide et chaude.
  • Vous pouvez paramétrer les couleurs A et B en y connectant des couleurs aux inputs, des textures, des maps, you name it!
  • Ajustons le roughness de notre shader en utilisant le résultat du mix shader entre Paint-Brush_Diffuse et Voronoi
  • Prendre l’output de l’avant-dernier Mix, qu’on passe dans un color ramp standard qui alimentera le roughness du Principled BSDF.
    • Ajuster la caméra (on avait fait scale vous vous souvenez?
    • Déplacer la sphère en dehors du frame.
    • Comme on utilise pas de Shader to RGB ici, l’effet est mieux rendu en Cycles. Passer donc à Cycles et faite play. Vous aurez peut-être à reconfigurer le driver de l’empty (rotation Z = “#frame * (pi/180)”
    • Play the animation!

Glass toon shader en EEVEE

  • File → New → General

  • Passer en mode EEVEE

  • Créer un Circle

  • Passer en Edit mode, Vertex.

  • Select All vertices.

📌

Noubliez pas d’être en mode transparent pour s’assurer de sélectionner les vertices cachées!

  • Extrude vers le haut avec la contrainte Z activé ( E Z et drag vers le haut).
  • Sélectionner les vertices du haut et faire S pour agrandir un peu le haut du verre.
  • Tout sélectionner, faire E puis S et scale-extrude vers l’intérieur. Cela va donner de l’épaisseur à notre objet.
  • Sélectionner les deux loops du haut et fire S Z 0 pour les aligner selon l’axe des Z
  • Faire la même chose avec les deux loops du bas.
  • sélectionner la loop intérieure du bas (⌥ left-click sur l’un des edges de cette loop
  • Faire F pour crèer une face.
  • Faire I pour créer un Inseted loop cut.
  • Élargissons le dessus un peu plus. Sélectionner tous les vertices du haut, faire S pour scale avec Shift-Z pour ne pas créer de déformation en X ou Y.
  • Dans les modifiers, ajouter un Smooth by Angle, avec Ignore Sharpness activé
  • Passer au shader editor, en mode Render
  • En mode Object, faire New pour créer un nouveau Material.
  • Remplacer le Principled BSDF par un Glossy Shader couplé à un Shader to RGB. lui même couplé à un Color Ramp

📌

  • Assurez-vous d’être en mode EEVEE, le noeud Shader to RGB n’existe pas en Cycles
  • Roughness à 0.7, et la position du stop blanc du color ramp à 0.2 environ.
  • Ajoutons un Mix Shader pour pouvoir mélanger le Glossy Shader à un Transparent Shader
  • Ajuster le Factor à 0.2, ainsi il y’aura plus Transparent et moins de Glossy
  • Ajoutons un noeud Fresnel couplé à un color ramp en mode constant. Déplacer le stop blanc à 0.1
  • Ajouter un autre Mix Shader et connecter l’output Color du color ramp du Fresnel au Factor du nouveau Mix Shader; le shader du Mix Shader précédent connecté au premier socket Shader du 2 Mix Shader.
  • Ainsi, Fresnel, qui dépend du point de vue de la caméra, va affecter le mélange des deux autres shaders (Glossy et Transparent).
  • Changer l’IOR du noeud Fresnel pour 1, pour un effet de transparence plus cartoon.
  • Ajoutons un Emission Shader connecter au 2e socket Shader du 2e Mix Shader
  • Aussi, dans les propriétés Material, dans Settings, changer Render Method à Blended au lieu de Dithered. Ça fera un mélange (Blend) plus smooth.
  • Modifier la couleur de l’Emission Shader pour un bleu gris lumineux.
  • Modifier la couleur du premier stop du color ramp du Glossy shader à un gris plus foncé.
  • Pour une réflection moins parfaite, ajoutons un Noise qui alimente le roughness du Glossy Shader.
  • Ajustez les valeurs to your liking (Scale à 3, Roughness à 0.14, Distortion à 0.1 par exemple)
  • Avec deux objets ajouté, voici un exemple de rendu:
  • Pour un effet encore plus cartoon, rajoutons un cartoon avec un Grease Pencil Stroke.
  • N’oubliez pas qu’il faut activer Z Pass dans les propriétés Layers dans la section Data pour que Grease Pencil fonctionne correctement.

  • Wala!
  • Allez, on l’améliore! Ajoutons un teapot avec Toon shading. Aussi, remplaçons l’Emission Shader pour un Transmission Shader. Rajoutons également un sussucre. C’est important les sussucres.

Textured lights - Light Gobos and God Rays

  • Ouvrez le fichier suivant: https://drive.google.com/file/d/1eHs25i6jgItdj7TCt8i87avagug4tAIg/view?usp=sharing

  • On ne voit rien, c’est normal, le HDRI est à 0.

  • Ajoutons un area light, au-dessus de la chambre

  • Placer l’area light à angle, comme si elle provenait du trou à gauche de la chambre. Plus facile si vous êtes en vue orthogonale frontale (Numpad 1).

  • Aussi, changer la puissance de la lampe à 100W.

  • Ajoutons un cube qui va couvrir toute la scène, mais pas la caméra.

  • Avec le cube sélectionné, passer en mode Shader Editor.

  • Faire New, retirer le Principled BSDF et le remplacer par un Principled Volume.

📌

  • Il faut, évidemment, brancher le socket Voilume du shader à Volume et non pas Surface dans le Material Output.
  • Changer la densité à 0.08
  • Sélectionner la area Lamp.
  • Changer le Shape à Disk, et la puissance à 50 W (100 W c’est trop puissant).
  • Orienteer la lampe de manière à ce qu’elle pointe vers le divan simple.
  • Avec la lampe sélectionnée, changer le Spread dans Beam Shape pour la lampe à 1.
  • Modifier Size à 2.36 m environ et ajuster la rotation de manière à bien éclairer le divan.
  • Avec la lampe toujours sélectionnée, activer Use Nodes dans le Shader Editor. On va texturer la lampe!
  • Un Emission Shader va apparaître.
  • Connecter un Wave Texture au socket Color du Shader.
  • ^ T pour ajouter un texture coordinates avec un mapping node. Jouer avec les paramètres pour obtenir un résultat satisfaisant:
    • Mapping Node:
      • Z = 45
    • Voronoi node:
      • Scale = 2
      • Distortion = 5
    • Light Properties:
      • Size 2.2
      • Spread 3 degrés pour un peu plus de blur dans les rayures
    • Résultat:
    • On peut également changer la couleur de la lampe et/ou la couleur du Shader du volume.
    • Devinez quoi, à la place du Voronoi, on peut mettre une image, par exemple le dessin
    • Par exemple, allez chercher cette image: https://drive.google.com/file/d/1eR979Vrh-dvkbB8woLIC1PMBxXB3qvJO/view?usp=sharing
    • Dans le shader editor, retirewr Voronoi et ajouter un Image Texture et ouvrir l’image
    • Jouer avec le mapping pour orienter l’ombre de la feuille.

Devoir

  1. Glass toon shader pour les cylindres afin de voir au travers
  2. Toon shader pour les autres composantes (y compris le plancher!)
  • Ajouter des petites simulations de fluides pour
    1. Intake (entrée des gaz, essence et air)
    2. Compression (compression des gaz, changement de la couleur vers l’orange)
    3. Kaboom (explosion, feu)
    4. Exhaust (sortie fumée noir)
    5. Exemple:
  • Comme d’hab, plus vous êtes créatifs, plus vos points augmentent! Par exemple, vous pourriez ajouter les valves!
  • N’oubliez pas montage vidéo et sonore
  • P.S.: Si vous détestez les moteurs, proposez-moi quelque chose d’équivalent en termes de niveau de difficulté!

Escalier en colimaçon avec Geo Nodes

Charpentes métalliques avec modifiers

Escalier rapide avec Bevel Profile

  • Créer un cube. Faites un Bevel d’une des arrêtes en Edit Mode - mode Edges.

  • Choisir la taille du Bevel et le nombre de segments (déplacement souris et roulette souris puis click-gauche)

  • Choisir Custom Profile Type et choisir Steps dans Presets.

  • En Edit mode toujours, mais en mode Face Select, effacez les faces dont on n’a pas besoin (Select Face → Delete → Delete Faces), pour ne garder que les marches et contre-marches.
  • Ajoutez un Solidify modifier, avec “Even thickness” activé.

Lien vers l'original

# Blender Geo nodes, Dataviz, Simulations et Python

Geo Nodes

Cours 1 - Geo Nodes I

Banque de cours - Un super vidéo for geo nodes by geo nodes

Un super vidéo for geo nodes by geo nodes

Lien vers l'original

Banque de cours - Le tout début avec les geo nodes

Le tout début avec les geo nodes

  • Geo nodes est un modifier
  • Geo nodes à partir d’un Plane (les puristes vont faire un merge at center)
  • Les Mesh primitives sont de dimension 2 en traditionnel, de dimension 1 en Geo Nodes
  • Group Input.
  • Mode Edit du geo nodes revient au plane de base!
  • On drag and drop Suzanne
  • Grid puis Cube → Points → Instance on points avec Suzanne comme instance qui passe par un Transform Geometry node
  • Et si on branchait le grid de base, voire le Group Input au socket “Instance” de Instance on points?

Lien vers l'original

Banque de cours - Les geo nodes, data, sockets, fields

Les geo nodes, data, sockets, fields

Banque de cours - La couleur des noeuds et le data type associé

La couleur des noeuds et le data type associé:

La forme des noeuds:

# Data et sockets (connecteurs)

Tous les nœuds dans Blender sont basés sur une construction similaire. Cela s’applique à n’importe quel type de nœud. Ces parties comprennent le titre, les connecteurs, les propriétés et plus encore.

Titre

Le titre montre le nom/type du nœud ; il peut être remplacé en modifiant le Label du nœud. Sur le côté gauche du titre se trouve le bouton réduire qui peut être utilisé pour replier le nœud. Cela peut également être fait avec H.

Comment un nœud apparaît quand il est replié.

Aperçu

Les aperçus sont une superposition qui montre une petite image au-dessus du nœud affichant le résultat du nœud. Tous les nœuds ne prennent pas en charge les aperçus, mais ceux qui le font peuvent être basculés en utilisant les icônes / dans le coin supérieur droit du nœud à côté du titre.

Les aperçus peuvent être désactivés pour tout l’arbre de nœuds en utilisant le bouton Aperçus.

Connecteurs

Les connecteurs sont des valeurs d’entrée et de sortie pour le nœud. Ils apparaissent comme de petits cercles colorés de part et d’autre du nœud. Les connecteurs inutilisés peuvent être masqués avec Ctrl-H.

Chaque connecteur est codé par couleur selon le type de données qu’il gère.

Intégrés

**Shader (vert vif)**Utilisé pour les shaders dans Cycles et EEVEE.**Géométrie (turquoise)**Utilisé dans les Geometry Nodes.**Menu (gris foncé)**Utilisé pour les entrées de type énumération qui affichent un menu déroulant ou un bouton radio dans l’interface utilisateur.

Données

**Booléen (rose clair)**Utilisé pour transmettre une valeur vrai ou faux.**Couleur (jaune)**Indique que le connecteur accepte/produit des informations de couleur. Les couleurs peuvent avoir ou non une composante alpha selon le type d’arbre de nœuds.**Nombre à virgule flottante (gris clair)**Indique que le connecteur accepte/produit des nombres à virgule flottante.**Entier (vert lime)**Utilisé pour transmettre une valeur entière (un nombre sans composante fractionnelle).**Chaîne de caractères (bleu clair)**Utilisé pour transmettre une valeur textuelle.**Vecteur (bleu foncé)**Représente des données vectorielles comme des coordonnées et des normales. Les vecteurs peuvent avoir 2, 3 ou 4 composantes :
2D : Affiche et utilise uniquement les composantes X et Y.
3D : Comprend les composantes X, Y et Z.
4D : Comprend les composantes X, Y, Z et W.**Rotation (rose)**Indique une rotation/quaternion.**Matrice (rose foncé)**Indique une matrice 4×4 de valeurs flottantes, elle est souvent utilisée pour représenter une Matrice de transformation.

  • 2D : Affiche et utilise uniquement les composantes X et Y.
  • 3D : Comprend les composantes X, Y et Z.
  • 4D : Comprend les composantes X, Y, Z et W.

Blocs de données

**Collection (blanc)**Utilisé pour transmettre un bloc de données de collection.**Objet (orange)**Utilisé pour transmettre un bloc de données d’objet.**Matériau (saumon)**Utilisé pour transmettre un bloc de données de matériau.**Texture (rose)**Utilisé pour transmettre un bloc de données de texture.**Image (abricot)**Utilisé pour transmettre un bloc de données d’image.

Structure des connecteurs

Les connecteurs de données peuvent avoir différents types de structure, indiquant comment les valeurs sont transmises et interprétées. Des structures plus complexes permettent de transmettre plusieurs valeurs à travers une seule connexion.

**Simple (Cercle)**Ces connecteurs attendent une seule valeur, ils sont représentés par une forme de connecteur circulaire.**Champs (Losange)**Représente une valeur qui peut varier par élément (par ex. par point, arête ou face). Vous pouvez considérer un champ comme une “carte de valeurs”, similaire à la façon dont la luminosité des pixels dans une image en niveaux de gris représente des valeurs variables à travers l’espace.
Si une valeur unique est connectée à un connecteur de champ, elle est implicitement diffusée à tous les éléments qui reçoivent la même valeur.
Les champs peuvent avoir l’apparence suivante :
Losange : Le connecteur peut accepter une entrée de champ, ou il produit un champ. Une valeur constante unique peut être connectée à ces connecteurs, mais la sortie ne variera souvent pas par élément.
Losange avec point : Le connecteur peut être un champ, mais il s’agit actuellement d’une valeur unique. Cela est utile car il permet de suivre où les valeurs uniques sont calculées, au lieu d’un champ avec de nombreux résultats différents. Cela signifie également que l’Inspection des connecteurs affichera la valeur au lieu des noms d’entrée du champ.
Voir aussi
Documentation sur les champs des Geometry Nodes

  • Losange : Le connecteur peut accepter une entrée de champ, ou il produit un champ. Une valeur constante unique peut être connectée à ces connecteurs, mais la sortie ne variera souvent pas par élément.
  • Losange avec point : Le connecteur peut être un champ, mais il s’agit actuellement d’une valeur unique. Cela est utile car il permet de suivre où les valeurs uniques sont calculées, au lieu d’un champ avec de nombreux résultats différents. Cela signifie également que l’Inspection des connecteurs affichera la valeur au lieu des noms d’entrée du champ.

Entrées

Les entrées sont situées sur le côté inférieur gauche du nœud et fournissent les données dont le nœud a besoin pour exécuter sa fonction. Chaque connecteur d’entrée, à l’exception de l’entrée de shader verte, lorsqu’il est déconnecté, a une valeur par défaut qui peut être modifiée via une interface de couleur, numérique ou vectorielle. Dans la capture d’écran du nœud ci-dessus, la deuxième option de couleur est définie par une interface d’entrée de couleur.

Certains nœuds ont des connecteurs spéciaux qui peuvent accepter plusieurs entrées. Ces connecteurs auront une forme d’ellipse plutôt qu’un cercle pour indiquer leur comportement spécial.

Sorties

Les sorties sont situées sur le côté supérieur droit du nœud et peuvent être connectées à l’entrée des nœuds plus en aval dans l’arbre de nœuds.

Conversion

Certains types de connecteurs peuvent être convertis en d’autres, soit implicitement, soit explicitement. La conversion implicite se produit automatiquement sans avoir besoin d’un nœud de conversion. Par exemple, les connecteurs Float et Color peuvent être liés les uns aux autres.

Une fois qu’une conversion de connecteur est effectuée, des données peuvent être perdues et ne peuvent pas être récupérées plus loin dans l’arbre de nœuds. La conversion implicite de connecteur peut parfois changer les unités de données également. Lorsque vous branchez un nœud d’entrée Value dans un connecteur d’angle, il utilisera par défaut les radians indépendamment des Unités de la scène. Cela se produit parce que le nœud Value n’a pas d’unité alors que l’entrée d’angle en a une.

Conversions valides :

  • Entre couleur et vecteur – correspondance entre les canaux de couleur et les composantes de vecteur.
  • Entre couleur et float – les données de couleur sont converties en leur équivalent en niveaux de gris.
  • Couleur/float/vecteur vers Shader – convertit implicitement en couleur et donne le résultat de l’utilisation d’un nœud Emission.
  • Entre float et entier – les entiers deviennent simplement des floats, les floats sont tronqués.
  • Entre float et vecteur – quand un float devient un vecteur, la valeur est utilisée pour chaque composante. Quand un vecteur devient un float, la moyenne des composantes est prise.
  • Entre float et booléen – les valeurs supérieures à 0 sont vraies, vrai correspond à 1, et faux à 0.
  • Entre rotations et matrices.

La conversion explicite nécessite l’utilisation d’un nœud de conversion tel que le nœud Shader To RGB ou le nœud RGB to BW. Le nœud Math contient également certaines fonctions pour convertir entre degrés et radians.

Propriétés

De nombreux nœuds ont des paramètres qui peuvent affecter la façon dont ils interagissent avec les entrées et les sorties. Les paramètres des nœuds sont situés sous les sorties et au-dessus des entrées.

Un exemple des contrôles sur le nœud Chroma Key.

# Fields (Champs)

Fondamentalement, un field (champ) est une fonction : un ensemble d’instructions qui peut transformer un nombre arbitraire d’entrées en une seule sortie. Le résultat d’un champ peut ensuite être calculé plusieurs fois avec différentes données d’entrée. Ils sont utilisés dans tous les geometry nodes pour permettre des calculs qui produisent des résultats différents pour chaque élément (sommets de maillage, faces, etc.).

Un champ en entrée d’un nœud.

Par exemple, dans la figure ci-dessus, le champ connecté au nœud “Set Position” dépend de deux entrées, Position et Index, et les transforme en un vecteur en utilisant une seule instruction.

Visualisation des champs

Les formes des connecteurs (sockets) sont utilisées pour indiquer quels connecteurs sont des champs et lesquels sont des données régulières. Il existe trois formes possibles de connecteurs, chacune visualisant son “statut de champ” :

**Cercle :**Le connecteur nécessite une seule valeur réelle, il ne peut pas accepter un champ en entrée. Pour les connecteurs de sortie, cela signifie que le nœud produit toujours une seule valeur.**Losange :**Le connecteur peut accepter un champ en entrée, ou il produit un champ. Une valeur constante unique peut être connectée à ces connecteurs, mais la sortie ne variera souvent pas par élément.**Losange avec point :**Le connecteur peut être un champ, mais il s’agit actuellement d’une valeur unique. Cela est utile car il permet de suivre où les valeurs uniques sont calculées, au lieu d’un champ avec plusieurs résultats différents. Cela signifie également que l’Inspection des connecteurs affichera la valeur au lieu des noms d’entrée du champ.

La forme du connecteur est un losange avec un point, ce qui signifie que le champ a la même valeur pour chaque élément. Chaque point sera déplacé vers le haut de 5 m.

La forme du connecteur est un losange et l’entrée du champ a maintenant une entrée variable. En d’autres termes, la valeur peut être différente pour chaque élément. Dans ce cas, la position sera doublée, puisque le décalage pour chaque point est la position du point.

Astuce

Souvent, on souhaite extraire une seule valeur d’un champ. Bien qu’il ne soit pas logique conceptuellement de simplement transformer un champ en une seule valeur, le Nœud Sample Index ou le Nœud Attribute Statistic peuvent être utilisés pour récupérer une seule valeur d’un champ évalué sur une géométrie.

Lorsqu’une connexion est établie entre deux connecteurs de nœuds qui prennent en charge les champs, la connexion du nœud sera dessinée sous forme de ligne pointillée. Si vous faites l’erreur de connecter un connecteur non-champ à un connecteur de champ, la connexion sera dessinée sous forme de ligne rouge continue indiquant qu’il y a une erreur.

Types de nœuds

Les nœuds peuvent être séparés en deux catégories : les nœuds de flux de données qui transmettent généralement la géométrie, et les nœuds de champ qui opèrent sur les données par élément. Les nœuds de champ peuvent être des nœuds d’entrée qui apportent des données de géométrie dans l’arbre de nœuds, ou des nœuds de fonction qui opèrent sur ces données.

Nœuds de flux de données

Les nœuds avec une entrée de géométrie et une sortie de géométrie seront presque toujours des nœuds de flux de données. Cela signifie qu’ils modifient effectivement les données de géométrie qui seront produites par le modificateur Geometry Nodes.

Nœuds de fonction

Les nœuds avec des entrées et sorties de connecteurs en losange sont des nœuds de champ, et ressemblent aux instructions qui seront évaluées par les nœuds de flux de données. Des exemples de nœuds de fonction sont les nœuds mathématiques et aussi des nœuds plus complexes comme le Nœud Geometry Proximity.

Nœuds d’entrée

Les nœuds d’entrée fournissent des données au processus d’évaluation du champ. Par eux-mêmes, ils ne signifient rien ; ils doivent être évalués dans le contexte d’un nœud de flux de données (géométrie) pour réellement produire une valeur. Des exemples de nœuds d’entrée sont les nœuds d’entrée d’attributs intégrés comme Position et ID, mais aussi des nœuds de sélection comme Endpoint Selection.

Les entrées de champ peuvent également provenir d’autres nœuds qui traitent la géométrie comme le Distribute Points on Faces, sous la forme d’Attributs Anonymes.

Contexte de champ

Tous les nœuds de champ fonctionnent dans le contexte du nœud de flux de données auquel ils sont connectés. Le contexte consiste généralement en un type de composant de géométrie et un domaine d’attribut, donc il détermine quelles données sont récupérées à partir des nœuds d’entrée.

Un malentendu courant est que le même arbre de nœuds de champ utilisé à plusieurs endroits produira les mêmes données. Ce n’est pas nécessairement vrai, car l’arbre de nœuds de champ sera évalué pour chaque nœud de flux de données, récupérant potentiellement des données d’une géométrie différente ou modifiée.

Ici, le champ d’entrée du nœud Set Position est évalué une fois. Pour évaluer le champ, le nœud remonte en arrière pour récupérer les entrées des nœuds d’entrée de champ.

Lorsqu’un deuxième nœud Set Position est ajouté, le même arbre de nœuds de champ est évalué deux fois, une fois pour chaque nœud de flux de données. Au deuxième nœud Set Position, les résultats seront différents puisque son entrée de géométrie aura déjà la position modifiée du premier nœud.

Cependant, il est souvent nécessaire d’utiliser les mêmes valeurs de champ même après avoir modifié la géométrie. Le Nœud Capture Attribute évalue un champ, en copiant le résultat dans un attribut anonyme sur la géométrie.

Ici, un nœud Capture Attribute stocke une copie de la position initiale. Notez que l’évaluation du champ d’entrée du nœud Capture Attribute est une étape entièrement différente. Par la suite, les champs d’entrée des nœuds Set Position n’utilisent pas la position réelle, mais la copie d’attribut anonyme de celle-ci.

Nouvelles formes de sockets dans Blender

Traduction de l’article de Jacques Lucke publié le 8 août 2025 sur code.blender.org


Solution

Le principe directeur de cette refonte est le suivant : les formes de sockets communiquent le type de données qu’un nœud attend ou génère, indépendamment de la façon dont il est utilisé.

Signification des nouvelles formes

  • Barre verticale — Entrée/sortie de valeur unique
  • Losange (diamant) — Entrée/sortie de type champ (field)
  • Cercle — Types de données dynamiques (entrées/sorties flexibles)
  • Formes grille/liste — Fonctionnalités en cours de développement, sémantique similaire aux losanges

La forme losange-avec-point a été abandonnée.

Anciennes formes de sockets sur le nœud Set Position

Exemples

Quatre nœuds clés illustrent cette refonte :

  1. Nœud Math — Les sockets circulaires indiquent une compatibilité dynamique avec les valeurs uniques, les champs, les listes, etc.
  2. Nœud Triangulate — Entrées à valeur unique avec une sélection évaluée en tant que champ
  3. Nœud Set Position — Une entrée géométrie unique plus plusieurs entrées de type champ (toutes de forme identique)
  4. Nœud Cube — Entrées à valeur unique générant une sortie de type champ

Exemples d’utilisation des nouvelles formes de sockets

Point essentiel : les formes de sockets restent statiques, quelle que soit la connexion établie (à l’exception des nœuds de groupe).

Groupes de nœuds

Les nœuds d’entrée/sortie de groupe peuvent ajuster automatiquement leurs formes en fonction des connexions. Les auteurs peuvent remplacer la détection automatique lorsque la forme inférée ne correspond pas à la fonctionnalité souhaitée.

Comment remplacer la forme d’une entrée de groupe

Liens

Les connexions en pointillés indiquent toujours un passage potentiel de champ nécessitant un contexte d’évaluation. Elles complètent désormais l’information des formes de sockets au lieu de la dupliquer.

Liens de nœuds en pointillés

Nouvelles formes expérimentales

Les nœuds Sample Grid et Get List Item utilisent de nouvelles formes de sockets encore en développement, conçues pour les structures de données de type grille et liste.

Formes de sockets expérimentales pour les grilles et les listes

Informations perdues

Trois catégories d’informations précédemment communiquées ne sont plus visibles dans les formes de sockets :

  • Propagation de droite à gauche des exigences de valeur unique — toujours active en interne ; les avertissements sur les liens sont conservés
  • Propagation de gauche à droite de l’information de contenu de champ — préservée via les liens en pointillés
  • Distinction visuelle des valeurs de champ par défaut — accessible via les infobulles (tooltips)

Nœud Set Position avec une infobulle


Au-delà des Geometry Nodes

Ces nouvelles formes s’étendent aux nœuds du Compositeur, marquant les entrées acceptant uniquement des valeurs uniques et permettant potentiellement de distinguer les sockets d’image des sockets dynamiques. Le support futur des champs dans le compositing est en discussion.

Le nœud Glare utilise les nouvelles formes de sockets

Les nœuds de shaders ne sont pas concernés pour l’instant.

Débloquer de nouvelles fonctionnalités

Cette refonte élimine les barrières architecturales qui freinaient le développement des grilles volumétriques et des listes, accélérant ainsi la réalisation de fonctionnalités auparavant retardées par les contraintes liées aux formes de sockets.

Conclusion

Les auteurs reconnaissent que modifier la signification des formes de sockets affecte tous les utilisateurs des Geometry Nodes. Malgré la perte de certaines informations visuelles, les capacités acquises pour les nouvelles structures de données justifient ce compromis et évitent la stagnation du développement.


Source : code.blender.org/2025/08/new-socket-shapes — Jacques Lucke, 8 août 2025

Lien vers l'original

Lien vers l'original

Cours 2 - Geo Nodes II

Banque de cours - Légos

# Légos

🔥

Merci à CBaileyFilm pour l’inspiration et l’aimable permission!

Grid, points, instance on points

Primitive Légo

  • Créer un nouveau fichier .blend.

  • Passer au Workspace Geometry Nodes

  • Créer un Plane dans le Viewport (⇧A → “Plane”)

  • Cliquer “New” dans l’espace de travail Geo Nodes.

  • Ce qu’on vient de faire, c’est de rajouter un Geometry Node Modifier à notre objet. Pour l’instant, l’input c’est la géométrie de l’objet, et l’output c’est ce qu’on voit dans le 3D viewport.

  • Renommons notre geometry nodes “Légos” au lieu de “Geometry Nodes”.

  • Déconnecter l’input de l’output (⌃ ou ⌘ - clique droit et couper le lien vert). Le plan va disparaître.

  • Créons une primitive Cube dans le geometry nodes (⇧A → “Cube”, s’assurer de choisir “Mesh → Primitives → Cube”).

  • Un cube de 1 a été créé dans le 3D Viewport.

  • Créer maintenant un cylindre (⇧A → “Cylinder”). Il n’apparaîtra que si on le branche au noeud Group Output.

  • Mais on veut joindre les deux objets entre eux.

  • Ajoutons donc un noeud Join Geometry (⇧A → “Join”) et connecter les deux primitives à ce nouveau noeud. Connecter Join au Group Output.

  • Pour l’instant on ne voit que le cylindre car il est plus grand que le cube et cache ce dernier.

  • On veut créer une primitive de type Légo.

  • Commençons par changer la taille en Z du cube à 0.5 et le “depth” du cylindre à 1 et son rayon (”radius”) à 0.3.

  • Mais, comme vous le savez, les transformations se font par rapport à l’origine des objets, c’est pour ça que le cylindre dépasse en bas et en haut. Comment régler ça?

  • Allons chercher un “Transform Geometry” node et y brancher le cylindre.

📌

Au moment de créer le noeud, si vous le déplacez au-dessus d’un lien de manière à ce que le lien devienne blanc, le nouveau noeud s’insèrera de manière intelligente entre le noeud à gauche dudit lien et celui à droite.

On appelle cela “Inserting a node”. Dans ce cas-ci, le Transform Node s’insèrera entre le Cylinder et le Join, en connectante la sortie Mesh du Cylinder à son entrée Geometry, et on connectant sa sortie Geometry à l’entrée Geometry du Join.

  • On va ajouter un 2e Transform geometry. Il est important de comprendre qu’une transform se sert, comme base, des transforms précédents s’il y en a. C’est un peu comme changer l’origine locale de l’objet avec le premier transform pour appliquer des transforms plus intuitifs après.
  • Ajoutons donc un 2e transform branché au premier. Vous pouvez faire ⇧D après avoir sélectionner le premier transform pour le dupliquer.
  • Jouez avec les valeurs des deux transforms pour comprendre ce que ça mange en hiver cette bibitte-là.
  • Modifier les valeurs des primitives et des transforms de manière à obtenir une primitive qui ressemble à un morceau de Légo de base.

Shade smooth

  • On aimerait maintenant faire un shade smooth mais pas partout, seulement le contour du cylindre. Il doit y avoir moyen de faire ça.
  • Ajouter un node “Set Shade Smooth”. Si on le branche à la fin du pipeline de noeuds, tout va être lissé, ce n’est pas ce qu’on veut:
  • Mais remarquez, oh c’est puissant les geo nodes, que la primitive Cylinder at des sélections créées automagiquement: Top, Side, Bottom et UV Map! Ça tombe bien vu qu’on veut un shade smooth du tour du cylindre, on va donc choisir la composante Side du noeud!
  • Il n’y a pas de noeuds Bevel. Cela dit, Geometry node un est “Modifier” et on peut ajouter un autre Modidifier au stack, en l’occurence un Bevel Modifier!
  • Alors allons-y, un Bevel Modifier après le GeometryNodes Modifier, avec une ampleur (Amount) de 0.008 m et 4 segments.
  • Ooooh ça recommence à ressembler à une pièce de Légo ça! Mais, où sont passés nos Noeuds, l’espace de travail Geometry Nodes est vide!
  • Faut juste sélectionner le Modifier GeometryNodes pour retrouver notre travail.
  • Ah, tant que vous y êtes, un Save peut-être?

Des morceaux de Légo de manière procédurale

  • Ce qu’on veut faire maintenant, c’est créer des morceaux de Légo un peu partout de manière procédurale.

  • Le noeud Points créé des points dans la scène, mais ces points ne font pas partie du rendu, ce sont juste des marqueurs de position si l’on veut.

  • Let’s go, ajoutons un Points Node, et ne connections que celui-ci à l’output pour l’instant.

  • Attends attends, j’en ai demandé 20 (”Counts”) mais je n’en vois qu’un seul? Pourquoi? C’est parce qu’ils sont tous au même endroit pour l’instant.

  • Je prends le temps de vous expliquer le noeud Grid, mais ce n’est pas celui qu’on va utiliser. Chaque sommet (Vertex) d’un grid peut-être utilisé comme un point.

  • Un grid est un plan tout simplement et on peut le Subdiviser en augmentant le nombre de Vertices en X et Y, par exemple, 10 x 10.

  • Pour mettre des instances d’objet sur les points de la grille, le noeud vedette, c’est Instance on Points.

  • Ici, ce que je viens de faire, c’est dire à Blender : je veux que tu utilises la géométrie d’un Grid comme référence de points et sur chacun des points (les Vertices), mets une instance de ma primitive Légo.

  • Chouette non? Jouez avec le scale et le nombre de Vertices de la grille.

  • Je prends le temps également de vous expliquer qu’on peut distribuer les points sur un objet. Et on peux drag and drop un objet dans le géo node!

📌

Si on laisse Original plutôt que Relative, les points seront distribués sur l’objet avant les transformations (e.g. Scale). On peut faire, bien sûr, “Apply Scale” pour régler la chose; auquel cas, il n’y aura pas de différence entre Original et Relative.

  • Jouez avec la densité et le Seed.

  • Mais bon, y’a un meilleur moyen, c’est ce que je vous montre maintenant.

  • Vous avez remarqué le section “spreadsheet” en haut à gauche? Chaque objet, chaque Vertex, chaque Edge, chaque Face se voit attribué un “ID” par Blender. Maintenant, dans le noeud “Point” vous avez remarquer que l’entrée “Position” a la forme d’un losange plutôt qu’une cercle? Dans les Geo Nodes, un noeud de type losange veut dire “s’applique aux ID de l’objet”. Ooooh c’est puissant ça.

📌

Avec l’arrivée prochaine de Blender 4.3, nous aurons officiellement le noeud “For loop”, une must pour tout.e programmeur.e qui se respecte!

  • Par exemple, sélectionnez le noeud Points et dans le spreadsheet, choisir “Instances”. Augmentez le nombre de points (Count). Vous voyez les IDs apparaître dans le spreadsheet?
  • La manière dont ça fonctionne c’est que, ici, chacun des 9 points créé une instance grâce au noeud Instance on Points et comme ce dernier est connecté à l’output du système de Geo Nodes, le spreadsheet nous montre les 9 instances avec un ID respectif de 0 à 8. Pour chaque instance, vous avez un tas d’information comme la position, la rotation, le scale, etc.
  • Vous commencez à voir où on veux aller? On va prendre chaque ID de chaque point et changer sa position relative.
  • Je veux que le Légo qui a l’ID 0 ait la position 0 en X par exemple. Celui avec l’ID 1, je veux qu’il soit 1m plus loin. Oh ça tombe bien, nos primitives Légo font 1m x 1m (c’est la taille du cube de départ).
  • Essentiellement donc, j’aimerai que la position en X soit fonction de l’ID du point!
  • J’en profite pour vous montrer une autre manière d’ajouter un noeud: Cliquez sur Position du Noeud Point, drag vers la gauche et laissez aller. C’est l’équivalent de faire ⇧A tout en connectant en même temps.
  • On va faire on drag vers la gauche à partir de l’input “Position” du noeud Points, et on va chercher pour le Noeud Combine XYZ. Cela nous permet de pouvoir contrôler chaque élément du vecteur (X, Y ou Z) de manière séparée.
  • Ensuite, le X de Combine XYZ, on lui connecte un noeud de type ID.
  • Z’avez vu ce que ça donne avec un Count de 4?
  • Vous avez remarqué aussi que le lien et comme hachuré entre ID et Combine XYZ? Même chose entre Combine XYZ et Points? Même chose entre Cylinder → Side et Set Shade Smooth → Selection. C’est un indicateur visuel qu’on parle ici d’une boucle, qu’on traverse une série d’éléments de la spreadsheet du noeud en question (toutes les Edges du côté du cylindre, tous les IDs des points, etc.
  • Analysez le spreadsheet et voyez comme la position en X est en fait la valeur de l’ID de chaque point.
  • Tiens, si on mettait un Map node, ou un Multiply node entre ID et Combine XYZ?
  • Comment faire maintenant pour contrôler la valeur Y?
  • On va ajouter un second Instance on points, connecter les instances du premier au deuxième, et, au deuxième, ajouter un système ID → Combine XYZ → Points mais où ID contrôle la valeur Y:
  • Maintenant, si je fais varier le count du premier noeud Points, j’augmente le nombre de primitives Légo selon l’axe des X, donc, si on veut, la longueur du morceau de Légo, et le count du 2e noeud Points contrôle la largeur du morceau de Légo!

Contrôle des paramètres avec Group Input

  • Un peu comme dans le shader unreal où l’on convertit une constante en Param, on va créer des paramètres contrôlables grâce au noeud Group Input qu’on n’a jamais connecté encore!

  • Vous voyez qu’il y a une sortie ronde sans couleur dans Group Input? Amenez Group Input près des deux noeuds Points et connecter l’output vide sans couleur de Group Input à Count du premier noeud Points. Une nouvelle sortie sans couleur se rajoutera au noeud Group Input. Connectez-là à l’entrée Count du 2e noeud Points.

  • Et wala (comme écrivait mon ami anglophone de Dallas), dans les Modifiers, vous avez maintenant deux paramètres que vous pouvez contrôler directement dans le Modifier GeomtryNodes!

  • Maintenant, sélectionnez l’objet dans le Outliner et faites dupliquez (Shift-D) avec la souris dans le viewport ! Vous pouvez maintenant modifier le Geo Node pour les deux en même temps, mais les paramètres du Group Input sont uniques à chaque instance!

  • Ouais mais bon, je veux pas que ça s’appelle Count. J’aimerai que le contrôle en X soit nommé L (pour Length) et celui en Y W pour Width. Je fais ça comment?

📌

Hint : sélectionnez le Group Input Node et aller dans le “N” menu à l’aide la touche N ou de l’indicateur open-left (<) à droite de l’espace Geo Nodes.

Légos de différentes hauteurs

  • Les Légos, ça n’a pas toujours la même hauteur. Ajoutons un Combine XYZ au paramètre Size du noeud Cube. Il est important de laisser donner la valeur 1 à X et Y dans le Combine XYZ (car c’était leurs valeurs directement dans le cube, on ne veut changer que Z).
  • Aussi, connecter l’output vide de Group Input au Z du Combine XYZ du cube. Renommez le paramètre à H (pour Height).
  • Maintenant, si vous changez la valeur H, vous verrez que le cube “scale” autant vers le haut que vers le bas, car, comme on ne lui a pas fait subir Transform comme au cylindre, son origine est au milieu du cube. Ajoutons donc un transform.
  • La position de ce dernier, on va l’alimenter d’un Combine XYZ. La valeur Z de ce dernier recevra le paramètre H du Group Input divisé par 2.
  • Ainsi, à chaque fois qu’on change la valeur H, la position Z du cube montera (ou descendra si H est négatif) de la moitié de H
  • vérifiez, jouez avec la valeur H.
  • Ah oui mais je veux que le cylindre se déplace aussi en fonction de la hauteur du cube.
  • D’abord on va remettre les valeurs Z du Scale des deux transforms du cylindre à 1. On va donner une profondeur de 0.15 au cylindre (Depth).
  • Maintenant, on veut que le cylindre soit déplacé de Depth/2 vers le haut. On prend alors la valeur Z de Translation du premier Transform, et on peut carrément écrire la formule “0.15/2” dans le champ Z. Blender va le calculer pour nous.
  • Finalement, on veut que le Z du 2e transform se déplace de la valeur H du Group Input:
  • Woot woot, maintenant on peut avoir des pièces de Légo de l’épaisseur qu’on veut! Jouez avec le paramètre H.
  • Le système de Geo nodes au complet ressemble maintenant à ceci:
  • Tout ce que vous voyez là, on peut également le programmer en Python :)

Oh non, le Bevel ne fonctionne plus!

  • Notre Bevel Modifier ne fonctionne plus. En effet, il ne fonctionne pas sur des “Instances” (ici, ce qu’on affiche, c’est le résultat après le dernier Instance on Points, i.e. ce qui est connecté à Group Output).
  • Des instances ne sont pas de “vrais” objets, mais des instances d’un objet. Avec le noeud Realize Instances, on va corriger ça.
  • Par contre, vous voyez que le bevel se fait sur chaque Instance on Points? Ça apparaît de manière évidente si on augment le Bevel (Amount dans le Bevel Modifier):
  • Ce n’est pas ce qu’on veut, on veut que ça Bevel le morceau de Légo en le traitant comme étant un seul morceau.
  • On va utiliser le noeud “Merge by Distance” pour ce faire. Merge by Distance va fusionner tous les Vertex qui sont à moins de “Distance” les uns des autres.
  • Finalement, un peu d’ajustements. On remarque que le cylindre est juste un peu trop haut sur le cube.
  • Changeons le Depth du cylindre à 0.2 m et le Z du premier Transform à 0.03 m

Material

  • On va d’abord créer un Material dans les propriétés Material, mais vous verrez que ça n’affecte rien pour l’instante.
  • Assurez-vous d’être en Render View (Z → Render) dans le 3D Viewport.
  • Créer un Principled BSDF Material avec une couleur orangée.
  • Dans le système Geo Nodes, ajouter un “Set Material” entre Merge by Distance et Group output; choisir notre Material (qui devrait se nommer “Material” si on ne l’a pas renommé)
  • Vous avez deviné, on va également paramétrer le Material. Donc on prend la sortie vide de Group Input et on la connecte à l’entrée Material du noeud Set Material.
  • Vous pouvez maintenant créer des Materials et les assigner via le Geo Nodes Modifier.

Mieux organiser notre système de Geo Nodes

  • On va maintenant utiliser des Frames et des Reroutes pour mieux organiser notre système de Geo Nodes.

  • ⇧ et clique droit à travers des connecteurs va faire en sorte des le regrouper via un point commun nommé reroute dans Blender.

  • On peut ensuite déplace le reroute en le sélectionnant puis en utilisant la touche G (pour Grab), si si, comme pour bouger n’importe quoi d’autre dans Blender.

  • On peut aussi faire ⇧A → “Reroute”, c’est dans Layout.

  • (Alt - clique gauche sur le reroute et drag pour enlever un reroute). Attention, pas X sur le reroute, ça va effacer toutes les connexions.

  • On peut aussi regrouper des noeuds dans des Frames.

  • Sélectionnez les noeuds que vous voulez regrouper, ensuite faire ⌃J. Dans le N Menu, sous l’onglet Node, vous pouvez changer la couleur du Frame et son Label, etc.

  • Et voilà le travail. Cliquer sur un noeud puis sur un Frame puis ⌃P va créer un lien de parenté (comme avec les objets) et donc insérer le noeud dans le frame. ⌥P avec un noeud sélectionné pour retirer ce dernier d’un frame. Drag and drop d’un noeud dans un Frame va la rajouter au frame. Notez que puisque “Shrink est sélectionné), si vous déplacez un noeud à l’intérieur d’un frame, la taille du frame s’ajustera en conséquence.

Valeurs discrètes en Z (les Légos n’ont pas de hauteurs arbitraires)

  • Todo : comment utiliser un Map Range ou un Color Ramp pour ne permettre que quelques valeurs discrètes pour H?

📌

  • Maintenant amusez-vous à construite un monde en Légo!
Lien vers l'original

Banque de cours - Quelques défis

Quelques défis

Changements au Geo Workspace

  • Ajoutons le timeline et le shader editor dans l’espace de travail Geometry Nodes puis sauvegardons le nouveau fichier défaut

Défi 1 - Cube Rubik

Créer ceci à l’aide de geometry node:

Solution

Lien vers l'original

Cours 3 - Geo Nodes III

Banque de cours - Escalier en colimaçon en geo nodes

Escalier en colimaçon en geo nodes

Lien vers l'original

Banque de cours - Suzanne qui se dissout

Suzanne qui se dissout

Et si on animait Suzanne ?

Lien vers l'original

Banque de cours - Floaty flottants

Floaty flottants

  • Ajouter un Plane avec un “Ocean” modifier, avec, pour les Waves, un Scale à 2.5 et Choppiness à 0.3

  • Pour le time, ajoutez comme driver l’équation “#frame/20” puis appuyer sur ↩, ça va animer l’océan.

  • S’assurer que l’interpolation est linéaire

  • Faites “Play” (spacebar) pour voir 🙂

  • Créer un cube, aller dans le workspace Geometry Nodes et faire New.

  • Assurez-vous d’épingler le workspace geo nodes pour ne pas qu’il disparaisse dès lors qu’on sélectionne un autre objet ou un autre modifier du cube.

  • Ajouter un noeud raycast, ne pas le connecter pour l’isntant.

  • La cible, c’est l’océan, Donc Drag and drop l’ocean de l’Outliner vers le workspace des geo nodes et connecter le socket geometry de cew dernier à socket du Raycast.

  • Aussi, assurez-vous que Object Info est à Relative afin que les matrice de transformations “World” soient appliqués, sinon la référence locale de l’objet sera prise en considération.

👌🏼

Vous avez renommé le Plane à “Ocean” et le Geo Nodes à, genre, “Flotty flottant”, right?

  • BTW, si vous voulez ce bel effet de transparence en mode Solid View, on l’active dans les paramètres du Shading. X-Ray (et Cavity pour les occlusions ambiantes).

  • Ajoutez les noeuds suivants puis faire Play. Vous voyez l’emprunte du cube flotter sur la surface de l’océan. C’est un bon départ.

  • Donc le cube et l’objet qui “cast” des rayons sur l’océan dans la direction des Z négatifs. On prend la valeur Z de la distance du rayon entre le cube et l’océan, on le multiplie par -1 pour le rendre négatif et on se sert de cette valeur pour calculer l’offset de Set Position dudit cube. Set Position va “transformer” la position du cube à l’endroit ou les rayons de ce dernier frappent la surface de l’océan.

  • Oui on a perdu le cube et c’est parce que Set Position va modifier la position de tous les vertices du cube en fonction du calcul et du ray cast qu’on vient de faire, l’écrapoutissant ce faisant (en d’autres termes, chaque paire de vertices du cube alignés en Z auront la même valeur Z à la sortie du Group Output).

  • Si on ajoute un join geometry pour voir le cube, déplacez-le et tournez-le pour voir l’effet sur l’océan.

  • Ain’t it chouette?

  • Une manière de retrouver l’objet, c’est de modifier “Source Position” du Raycast, pour lui dire que l’on veut conserver les positions relatives des vertices du cube.

  • P.S., j’ai retiré le join geometry node.

  • On veut aussi influencer la rotation, donc Set Position n’est pas le bon noeud. On va utiliser un noeud plus générique, le Transform geometry Node peut modifier non seulement la position (comme Set Position), mais également la rotation et le scale.

  • Pour la rotation, celle-ci est forcément fonction de la normale à la surface de l’océan.

  • Incidemment, le socket “Hit normal” du Raycast donne la direction du vecteur normal à la surface à l’endroit de la collision du casted ray. C’est exactement ce que l’on veut utiliser, avec un “Align Rotation to Vector”

  • Ça marche, mais vous notez le “jitter” (sautillement)? Si on réduisait le “choppiness” des vagues à zéro, se serait mieux, plus smooth, mais le saccadé vient du fait qu’une seule normal pour tout le cube est calculée, celle à l’endroit où le rayon touche à la surface de l’océan.

  • En d’autres termes, la variation de l’angle de la surface de l’océan, d’un frame à l’autre, varie trop à cause du “choppinness” des vagues.

  • Pour ça, il y a plusieurs manières. On va utiliser un noeud “Attributes Statistic” qui va nous calculer des valeurs comme la moyenne, etc., de notre cube.

  • On va remplacer le Location info du cube qui aliment Source Position du RayCast par la valeur “Mean” (moyenne) du Attribute Statics. Bien sûr, il faut dire à ce dernier que les stats, sur sur la position qu’on veut la calculer.

  • C’est encore trop “choppy”. On peut soit réduire le “choppiness” des vagues, soit calculer la. valeur de la normale autour de celle du rayon, sur le plan XY et en faire une moyenne.

  • On va donc copier Le Raycast 4 fois supplémentaires. On va connecter à chaque fois la géometrie de l’Object Info du cube au socket Target Geometry du Raycast.

  • Mais l’output Mean du Attribute Statistic, on va d’abord le faire passer par un Vector Math node de type Add.

  • La première fois, on laisse ça à zéro (donc la valeur moyenne au centre de l’objet).

  • La fois 2 et 3, on ajoute 1 en X puis on retire 1 en X (pas Z et pas Y).

  • Les 2 dernières fois, on ajoute 1 en Y, puis on retire 1 en Y (pas Z et pas X).

  • On a donc maintenant 5 rayons, un au centre, et 4 autres autour de ce dernier. Il suffit maintenant de calculer la valeur moyenne de la normale.

  • Un Vector Math à chaque fois, qui additionne tous les 5 vecteurs puis on divise par 5. Et c’est cette nouvelle normale, qui est la moyenne des 5 mesurées, qui sera utilisée pour aligner la rotation du cube.

  • Tada!

  • Remplacez le cube par une sphère par exemple.
Lien vers l'original

Cours 4 -Geo Nodes IV - on va au gym !

Banque de cours - F16 qui pointe

F16 qui pointe

Lien vers l'original

Banque de cours - Le très puissant noeud Raycast

Le très puissant noeud Raycast

👌🏼

Merci à Erin, Xan3D, Khamurai, Robbie Tilton, Kaizen pour leurs super tutos!

  • Un peu de doc sur le Raycast node:

https://docs.blender.org/manual/en/latest/modeling/geometry_nodes/geometry/sample/raycast.html

  • On va créer un empty pour contrôler la direction des rayons, un object Curve pour montrer la direction desdits rayons.
  • On va également modifier l’impact du raycast: delete mesh au lieu de Set Position.
  • Pour finir, on veut contrôler la longueur des rayons pour que ceux du raycast soit le même que ceux des curves.
  • Vous pouvez télécharger le fichier .blend ci-haut ici:
    https://drive.google.com/file/d/12FNVDy85chgSD-cXbnmFEgbMDRARk5T6/view?usp=sharing
  • Déplacez l’empty pour voir l’effet du raycast. Modifiez la longueur des rayons. Déplacez Suzanne.
Lien vers l'original

Banque de cours - Quelques défis 2

Quelques défis

Défi 1 - Spirale

Créer cette animation à l’aide de geometry nodes

Solution Ici, on a keyframé le 2e valeur du Math node Add (juste après l’index).

Une solution plus élégante, serait d’utiliser le noeud “Scene time”:

Défi 2 - Pastilles

Créer cette animation à l’aide des geometry nodes

Solution

Défi 3 - Ronde dansante

Et maintenant cette animation, encore une fois à l’aide de geo nodes

Solution

Lien vers l'original

Banque de cours - Xam Geo Nodes

Xam Geo Nodes

Bulles volcaniques : 25 %

Évaluation et pondération

Pondération25 %
Critères d’évaluationDéplacement des sphères progressif en fonction de la proximité à un empty
Scale (mise à l’échelle) des bulles progressif en fonction de la proximité à l’empty
Couleurs procédurales en fonction de la proximité à un empty
Animation/déplacement des bulles progressive en fonction de la proximité à un empty que l’on déplace dans le viewport selon le plan XY (ne perdez pas de temps à faire le rendu de l’animation).

Quelques indices Noeuds utiles :

  • Proximity Geometry à un empty dont la position devient un Mesh Line avec un seul point:
  • Grid
  • Instance on points
  • Map Range
  • Stored Name Attributed (pour la couleur à transmettre au Shader)
  • Scale Instances et Translate Instances
  • Set Material

À remettre

  • Dans le drive (là où vous remettez vos devoirs)
  • Créez un dossier à votre nom (utilisez le même pour les 3 défis)
  • Dans ce dossier, ajouter Votre fichier “Nom - Bulles volcaniques.blend” (Assurez-vous d’activer le checkbox “File → External Data → Automatically Pack Resources” avant de sauvegarder)

Texte en geo wire frames : 30 % Créez ceci (pas besoin d’animation), mais, bien sûr, changez Karim pour votre prénom

Évaluation et pondération

Pondération30 %
Critères d’évaluationUn mesh en forme de cylindre pour les arrêtes (edges)
Une sphère pour les sommets (vertices)
Une face réfléchissante pour les plans
Une couleur différente pour les sommets, arrêtes et faces
Ne perdez pas de temps à faire un rendu d’une image ou d’une animation. Un mode “Rendered” dans le viewport suffira

Quelques indices Quelques noeuds utiles

  • String to Curve
  • Fill Curve

  • Extrude Mesh
  • Pour les Vertex : Instance on points
  • Pour les Edges : Mesh to Curve + Curve to Mesh avec un “Curve Circle” comme profil
  • Join Geometry

À remettre

  • Dans le drive (là où vous remettez vos devoirs)
  • Créez un dossier à votre nom (utilisez le même pour les 3 défis)
  • Dans ce dossier, ajouter Votre fichier “Nom - Texte.blend” (Assurez-vous d’activer le checkbox “File → External Data → Automatically Pack Resources” avant de sauvegarder)

Random City : 35 %

  1. Commencez par télécharger ce fichier Blender localement sur votre disque dur :
    https://drive.google.com/file/d/1C36Immf3IwxGeqRXn4hOFc5KX_8BmQNk/view?usp=sharing

  2. Renommez-le “Nom - City.blend”

  3. Ce fichier contient une collection d’assets représentant des buildings

  4. Ajoutez des geo nodes afin d’obtenir une distribution de building random selon une distribution de Poisson:

Évaluation et pondération

Pondération35 %
Critères d’évaluationDistribution random à partir d’une série d’objets
Présence de sources de lumières colorées également distribuées de manière random
Des objets ajoutés à la liste d’objets à distribuer sont pris en compte automatiquement
Rotation random des buildings, mais selon des multiples de 90 degrés
Scale random des buildings, mais clamped (map range !)
Pas besoin de textures ou Materials

Quelques indices Quelques noeud utiles

  • Distribute Points on Faces
  • Map Range
  • Random Value

À remettre

  • Dans le drive (là où vous remettez vos devoirs)
  • Créez un dossier à votre nom (utilisez le même pour les 3 défis)
  • Dans ce dossier, ajouter Votre fichier “Nom - City.blend” (Assurez-vous d’activer le checkbox “File → External Data → Automatically Pack Resources” avant de sauvegarder)
Lien vers l'original

Cours 5 - Geo Nodes V

Banque de cours - Geo nodes et Cloth simulations - Partie 1 - Coussin

Geo nodes et Cloth simulations - Partie 1 - Coussin

🔥

Un grand merci à Syn_cub pour son aimable permission de m’inspirer de ses tutos!

☝🏼

Ici, on explorera une utilisation avancée du système de geometry nodes, comment en utiliser plusieurs et les combiner avec une simulation phlysique.

Le coussin gonflable pas encore gonflé

  • Pour que la simulation fonctionne, il faut que l’objet soit un objet créé dans le Viewport, pas par le système de geo nodes.

  • Commençons donc par un cube dans le Viewport et faire ^3 pour le subdiviser 3 fois

☝🏼

Ça va ajouter un Subdivision surface modifier. Ajuster le render à 3 également.

  • Ajouter un “Cast” modifier de type sphérique avec un facteur de 1 pour que l’objet ressemble vraiment à une sphère, pas à un vieux ballon de volleyball en cuir 🙂


Le Cast Modifier dans Blender déforme un objet en transformant sa forme vers une forme géométrique prédéfinie — généralement une sphère, un cylindre, ou un parallélépipède (boîte). Il est souvent utilisé pour des effets stylisés ou pour corriger subtilement une forme.

### **📦 Comment ça fonctionne :**
Le modificateur Cast “attire” les sommets d’un maillage vers une forme cible, donnant l’impression que l’objet est en train d’être « reconfiguré » selon cette forme.

### **🛠️ Principaux paramètres :**
- **Type de déformation (Cast Type)** :
    - Sphère : attire les sommets vers une forme sphérique.
    - Cylindre : les attire vers une forme cylindrique (axe défini).
    - Boîte : transforme l’objet en une structure de type boîte.
- **Facteur (Factor)** :
    - Contrôle la **force** de l’effet.
    - 1.0 = transformation complète vers la forme cible.
    - 0.0 = aucun changement.
    - On peut même utiliser des **valeurs négatives** pour inverser ou “gonfler” la forme.
- **Rayon (Radius)** :
    - Limite l’effet aux sommets situés dans une certaine distance du centre.
- **Taille (Size)** :
    - Définit la taille de la forme cible vers laquelle les sommets sont attirés.
- **Utiliser X/Y/Z** :
    - Active la déformation seulement sur certains axes.
- **Utiliser la transformation (Use Transform)** :
    - Permet d’utiliser la transformation (position, rotation, échelle) d’un objet cible comme origine de la déformation.

  • Faire un “Apply” des deux modifiers pour avoir une réelle géométrie avant d’aller dans les geo nodes.

  • Pourquoi on a fait ça au lieu d’utiliser un UV Sphere par exemple? Bonne question, c’est qu’un UV Sphere a des triangles comme polygones aux pôles, et ça, les simulations n’aime pas, on veut des Quads.

  • Ici, avec bien sûr l’objet sélectionné, vous pouvez soit faire un “New” dans le workspace Geo Nodes, ou ajouter un Geo Node Modifier; rappelons-nous qu’un système de geo nodes est un modifier. Ici d’un objet réelle qui ressemble à une sphère.

  • Écrabouillons la sphère selon l’axe Z à l’aide d’un Transform Geometry Node où la valeur Z du Scale est à 0.33

  • On va maintenant distordre la galette en changeant le scale des normales via un Texture Noise dont le scale sera ajusté à environ 1.7 et le niveau de détail à 0.1

  • Ce qu’on a fait effectivement ici, c’est changer la taille (scale) des normales à la surface de notre objet en fonction d’une texture Noise et on a utilisé cette valeur pour déplacer les faces le long de chaque normale à la surface de la valeur du scale.

  • Pour l’instant le Map Range ne fait rien, mais ça nous permet de mieux ajuster la portée du noise plus tard.

  • Ajoutons un Set Shade Smooth (il peut être avant, i.e. tout de suite après le transform ou le group Input, comme il peut être à la fin, après le Set Position).

  • Ajouter un Subdivision Surface avec une résolution du subdivision à 2.

⚠️

J’ai activé le “Show timing”, c’est dans les overlays (voir la flèche), pour voir si ça changeait la performance de mettre le Set Shade Smooth à différents endroits, mais cela ne semble pas être le cas, la durée totale (au niveau du Group Output) variant entre 7 et 12 ms.

  • J’ai donc décidé de mettre le Set Shade Smooth après le Set Position, ça me semble plus logique.

  • On va réduire la puissance du noise à l’aide du Map Range et en jouant encore avec les valeurs du Noise Texture. Scale à 1.2 au lieu de 1.72 et Le To Max du Map Range à 0.7. Ainsi, le scale des normales va varier entre 0 et 0.7.

  • Groupons tout ce beau monde (Sélectionnez tous les noeuds sauf Group Output, faire F - pour Frame -, ce qui, ici, va créer un Frame - et appelons-le coussin gonflable.

☝🏼

J’ai également activé le mode wireframe même en mode solide (c’est dans les Overlays, là vous voyez la flèche).

Voro qui?

  • Maintenant, on aimerait que notre coussin se gonfle via un Cloth Simulation, sauf là où on aura épinglé des Vertex (Pin Group). Et on aimerait utiliser un Pin Group qui change avec le temps, en fonction de, par exemple, une texture Voronoi.

  • En d’autres mots, on veut qu’à l’endroit des Pin Groups, le coussin ne gonfle pas, mais on veut que les Vertex du pin group changent dynamiquement au fur et à mesure de l’animation de manière visuellement cool.

  • On va créer, dans les paramètres ‘Data’ de l’objet, un Vertex group vide qu’on va nommer “PinGroup”.

☝🏼

Notez que j’ai épinglé le système de Geo Nodes, c’est pour cela que les noeuds n’ont pas disparus même si je ne suis plus dans la paramètres “modifiers” de l’objet.

  • Créons une texture Voronoi et et brancher sa sortie Color à l’entrée Value d’un noeud “Viewer”.

☝🏼

  • Pour voir l’effet du Voronoi en couleur, il faut faire ^ ⇧ left-mouse sur le noeud Voronoi deux fois (la première fois, il va montrer la sortie du socket “Distance”, qui est en noir et blanc, et la 2e fois, ce sera le socket Color et Blender va automatiquement savoir qu’on s’attends à des valeurs RGB.
  • Brancher le socket de sortie Geometry du dernier noeud du groupe “Coussin gonflable”, au socket Geometry du Viewer.

  • Ctrl-Shift et cliquer sur le noeud voronoi. Une première fois, ça va montrer la distance.

  • Ctrl-Shift et cliquer une 2 fois sur le même noeud, va montrer la couleur.

☝🏼

Si vous branchez le noeud couleur à la main, le résultat sera en noir et blanc, aucune idée pourquoi.

  • Cela permet de voir l’effet du Voronoi sur l’objet:

  • Jouez avec les paramètres du Voronoi pour voir l’effet!

  • Changer le Scale du Voronoi à 1.5

  • Maintenant un truc super cool pour mettre un peu de symétrie dans cette texture le long de l’axe des X

  • Pour ce faire, il suffit de ne considérer que la valeur absolue de la composante X de la position des vertex dans la géométrie pour contrôler le vecteur de la texture Voronoi.

  • Chouette non? En gros, par rapport à l’axe des X, partout où les coordonnées de la texture avaient une valeur négative de X, celle-ci est transformée en la même valeur mais positive cette fois-ci, et donc la même texture se trouve de chaque côté, en ayant l’axe des Y comme miroir.

  • On veut maintenant tourner la texture en fonction du temps.

  • On va prendre un noeud Vector Rotate auquel on ajoute un driver à Angle à l’aide de la formule “#frame/80”. Donc les vecteurs vont tourner du numéro de frame divisé par 60 à chaque frame.

☝🏼

Avec l’introduction du Noeud Scene Time, on peut également éviter d’utiliser un driver et plutôt brancher le socket Frame du noeud Scene time à un Math Divide et c’est ce qu’on branche au socket Angle du Vector Rotate:

  • Faites “Play”.

  • Bon, c’est bien que le Voronoi tourne et tout, mais on va ajouter un peu de dynamisme.

  • Pour ce faire, ajoutez la 4e dimension à la texture Voronoi (4D), c’est la dimension W, qu’on peut voir comme la dimension temps. Changer la valeur de W équivaut à changer le visuel Voronoi.

  • On va donc ajouter un Driver à la valeur W: “#frame/30” par exemple.

  • Faites “Play”. Le mouvement est plus intéressant maintenant.

  • Bon, je dis ça, je dis rien hein, c’est à vous de jouer avec ces paramètres. Vous pouvez par exemple aussi ajouter un noeud Vector Math après Vector Rotate. Les possibilités sont assez infinies.

☝🏼

Là aussi, vous pouvez alimenter le paramètre W avec le socket Frame du noeud Scene Time divisé par une constante qui vous convient.

  • Mais bon, dans mon cas, ce que j’aime moins des drivers, c’est qu’il faut cliquer sur le champs pour voir l’équation utilisée.

  • Je vais donc plutôt le faire de manière plus explicite, avec le noeud Scene Time qui lui va alimenter autant Vector Rotante que W de Voronoi:

  • Ainsi, on peut ajuster la valeur du Divide plus facilement et plus “visuellement”. Bien sûr, si vous ne voulez pas la même valeur pour Angle et pour W, vous n’avez qu’à avoir deux noeuds Divide par exemple.
  • Encore une fois, les possibilités sont infinies, ça dépend du VFX que vous cherchez à obtenir.
  • Perso, je trouve que Frame/80 donne de bons résultats.

Archipel en pin group

  • On va utiliser un super noeud intitulé “Face Group Boundaries”.

  • Et ça tombe bien, chaque couleur du Voronoi possède un face group ID (vous avais-je dit que tout dans Blender possède un ID, un identificateur unique?).

  • Donc le face group Boundaries va identifier les bords de chaque face group ID, i.e. de chaque île de couleur que crée la texture Voronoi.

  • Et, je vous le donne en mille, les îles vont changer de forme à chaque frame puisqu’on alimenter la rotation du vecteur et du W de la texture Voronoi.

  • Faire ^ ⇧ et clic gauche sur le noeud Face Group Boundaries.

  • On ne voit rien pour l’instant parce que la sortie de la valeur Color est trop faible.

  • On va la multiplier par 100.

  • Ah ha! Comme vous pouvez le constater, ça créé un “Mask” où les valeurs blanches sont les frontières des îles de couleur.

  • Ça me fait penser au problème des 4 couleurs en théorie des graphes.

  • Et si l’on fait “Play”, on verra les frontières des îles changer puisque les îles de couleur changent de forme.

  • Vous l’avez deviné? On va utiliser les “Boundaries”, i.e. les valeurs blanches, comme étant les pin groups de la simulation Cloth qu’on va bientôt entreprendre.

  • Tout ce qui va être noir dans le mesh va gonfler, et tout ce qui est blanc ne bougera pas et toutes les zones grises joueront le rôle de facteur d’influence entre 0 et 1 (0 = full gonflé ↔ 1 = pas gonflé du tout).

  • Pour ce faire, on va tirer partie du fait que les noms de variables sont globales dans Blender.

  • Vous vous souvenez qu’on avait nommé “PinGroup” le Vertex Group dans les propriétés Data du Mesh?

  • Eh bien on peut ajouter des Vertex au Vertex Group PinGroup via le noeud Store Named Attributes. Si vous cliquez dans l’input “Name”, le nom “PinGroup” va apparaître (mais seulement si la géométrie Coussin gonflable est connectée au socket Geometry du Store Named Attribute). En fait le nom de toutes les variables globales que Blender a trouvé vont apparaître.

  • On peut rafraîchir, à chaque frame, le contenu du Vertex Group “PinGroup” en fonction des edges trouvés par le noeud Face Group Boundaries.
  • Si vous passez au mode “Weight Paint” (C’est en haut à gauche, là où c’est marqué e ce moment “Object Mode”) et que vous faites play, vous allez voir le contenu du Vertex Group “PinGroup” évoluer à chaque frame.
Lien vers l'original

Banque de cours - Geo nodes et Cloth simulations - Partie 2 - Trippy

Geo nodes et Cloth simulations - Partie 2 - Trippy

La wireframe collision (ou comment créer un objet vachement trippy)

  • Je trouve la résolution trop faible, augmentons la valeur Level du noeud Subdivision Surface à 3.Pour voir les wireframes même en mode solide, c’est dans les Overlays.

☝🏼

Pour voir le wireframe même en mode solide ou weight paint, c’est dans les Overlays

  • Finalement, on va stocker (donc noeud Store Named Attribute) la position (donc noeud Position) avant simulation de tous les Vertex du mesh dans une nouvelle variable qu’ont va appeler “Repos”.

☝🏼

J’aime bien nommer mes variables en français pour être certain de ne pas entrer en conflit avec des noms de variables déjà existants dans Blender, puisque les variables on une porté globale.

  • La position “Repos” du mesh va nous aider à calculer la collision avec le Wireframe qu’on va créer à la prochaine étape. Z’allez voir.

  • Renommer notre Geo Node “Avant Simulation”.

☝🏼

Si votre Geo Node est épinglé, vous ne pourrez pas changer son nom dans le workspace Geo nodes, mais vous pouvez le faire dans le Geo Nodes Modifier.

  • Voici le système de Geo Nodes jusqu’à maintenant, où j’ai corrigé le Store Named Attribute nommé repos, la valeur stockée est un vecteur et non pas un float puisqu’on stocke la position de chaque vertex du PinGroup:

☝🏼

Notez qu’on voit la valeur maintenant des store Named Attributes dans le Spreadsheet, ça ça aide beaucoup!

  • Le but ici, c’est de créer un mesh à partir des vertex du pin group. Ça tombe bien, c’est ce que Face Group Boundaries nous donne!

  • Avec l’objet sélectionnée (Il s’appelle Cube, vous vous rappelez?), dans le viewport, faites Shift-D pour le dupliquer.

  • Faites enter pour ne pas déplacer le nouvel objet (qui se nomme Cube.001). C’est ce dernier qui est maintenant sélectionné.

  • Cliquer sur le chiffre 2 à côté du nom du geo node (”Avant Simulation”) pour que ce ne soit pas un seul système utilisé deux fois (par les deux objets) mais pour que notre nouvel objet utilise son propre système de Geo Nodes basé sur le premier.

☝🏼

Dans l’image, c’est Vector et non pas Float qu’on devrait lire sur le noeud Store Named Attribute nommé “Repos”.
Donc mettez ce noeud à Vector au lieu de Float!

  • Renommer le nouveau système de Geo Nodes à “Wireframe”.

  • Dans ce nouveau système de geo nodes sur le nouvel objet (Cube.001), on va effacer les deux Store Named Attributes, on n’en a pas besoin ici.

  • L’idée maintenant, c’est de créer un mesh à partir du Face Group Boundaries, qui sont, rappelons-le, les Vertex du Pin Group.

  • Ajouter un Mesh to Curve juste avant le group output; ça va convertir le maillage (mesh) du deuxième cube en courbe. Pour la sélection, on ne va choisir que les bords des îlots, i.e. la sortie de Face Group Boundaries.

  • Si on “Hide” le premier objet (Cube), on va voir le résultat. On a maintenant des Curves qui correspondent aux bords des îlots.

  • On va maintenant convertir les courbes en Mesh (Noeud Curve to Mesh) sur lequel on va appliquer un Subdivision Surface de niveau 2.

  • Ensuite, un truc pour adoucir la forme, c’est de contrôler la position des vecteurs de ce mesh avec la fonction Blur Attribute avec une itération assez élevées (genre 150).

☝🏼

Je vous avais dit que c’était puissant les geo nodes.
P.S.: si vous cliquez droit sur un noeud, un menu “Online Manual” va apparaître. Allez voir le noeud Blur Attribute, qui “smooths attribute values between neighbouring gemetry elements; the goal of each step being the mixing of the values of each element with its neighbours.”.

P.P.S.: Ce n’est pas important que les mesh ne se touchent pas. Ce wireframe ne sert pas de Vertex Pin Group (ça c’est le rôle justement de la variable PinGroup qu’on alimente dans le premier système de geo nodes).

  • Après moultes essais et erreurs, on a réalisé qu’on avait besoin de faire un “remesh topology”.

  • Une manière de le faire, c’est de convertir le mesh en points, les points en volume et le volume en mesh avec les bons paramètres pour la partie cruciale qui est le Points to Volume (ici Voxel amount à 256 et radius à 0.05.)

  • On va finalement et derechef adoucir la géométrie avec le noeud Blur Attribute, mais avec moins d’itérations cette fois-ci (e.g. 75).

☝🏼

Notez au passage cette manière de créer une structure complexe qu’il serait assez difficile à modéliser de manière traditionnelle.

  • Allez, faites “Play”. C’est beau, avouez!

  • Unhide du Cube.

  • Renommer “Cube.001” à “Collision” et “Cube” à “Coussin”. On va se servir du mesh Collision, plus tard, pour corriger la collision du Coussin.

La gonflette - ”Vous gonfliez ? J’en suis fort aise : eh bien ! Dansez maintenant.”

  • Passer au Workspace Layout.

  • Assurez-vous d’être au Frame 1 dans la Timeline.

  • Avec l’objet Coussin sélectionné, aller dans les propriétés Physics et choisir Cloth.

  • Choisir le Preset “Silk”.

  • Réduire les valeurs de “Damping” à 0 et ajuster toutes les valeurs de Stiffness à 1, mais laisser Bending à 0.5.

  • Cela va donner un feel très “léger” au tissu, comme s’il était fait de papier.

☝🏼

Right-click sur un input et choisir Online Manual 🙂 ou refaire les cours sur la simulation de tissu dans la section Techart 2 😇

  • Désactiver la gravité également (valeur 0 à Gravity dans Fields Weights). Sinon, notre coussin va se mettre à tomber tant qu’il n’a pas de pin groups.

  • Maintenant, tout le but en était un de gonflette, alors activons la pression, avec une “Pressure” de 10 atmosphères.

  • Dans Shape, choisir le Pin Group “PinGroup”.

  • Ajuster le Shrinking Factor à -0.25, ça donne un coussin mieux froissé.

  • Cachez l’objet “Collision” et faire “Play” rien qu’un peu 🙂

☝🏼

Notez que “Play” tente de calculer la simulation en temps réel. Les résultats peuvent être très bizarres tout dépendant de votre RAM et puissance CPU.

  • Activons le Self-Collision avec une bonne précision (Distance à sa valeur minimale, i.e. 0.001) pour améliorer la simulation et empêche l’objet d’entrer en collision avec lui-même.

  • Revenir au Frame 1, aller dans la section Cache et faire Bake (des 250 frames si votre CPU est assez puissant, sinon baissez à 100 frames et ajuster aussi le End frame dans le Timeline à 100).

☝🏼

Pour le rendu final, dans les Simulation Nodes de l’objet Coussin, vous pouvez augmenter le niveau de Subdivision Surface à 4 au lieu de 3 et refaire Bake à partir du Frame 1.
Ça dépend de votre CPU. Si votre Frame Rate baisse trop lors du Play, ajuster le niveau de Subdivisions. L’idée, c’est que seulement à a la toute fin, quand on est prêt à faire un rendu final, on augmente les valeurs pour un résultat plus précis.

Lien vers l'original

Cours 6 - Geo Nodes VI

Banque de cours - Geo nodes et Cloth Simulations - Partie 3 - Dansez

Geo nodes et Cloth Simulations - Partie 3 - Dansez

Dansez, certes ! Mais avec retenue je vous prie

  • On va enfin se servir de la variable “Repos” qui a gardé en mémoire la position au repos des Vertex du coussin, et du mesh Wireframe qu’on a créé pour mieux calculer la position au repos des Vertex du Pin groups.

☝🏼

Cette étape n’est pas nécessaire mais donne un meilleur rendu.

  • Passer dans le workspace Geo Nodes.

  • Si un Geo Nodes est épinglé, désactiver la chose.

  • Avec l’objet Coussin sélectionné, dans les propriétés Modifiers, ajouter un Geo Node Modifier après le Cloth Modifier, qu’on va appeler “Après Simulation” et faire “New” pour créer le nouveau système de Geo Node.

  • On va aller cherche le Collider Object, c’est l’objet nommé Collision.
  • Vous pouvez soit faire un drag and drop de l’Outliner vers le workspace Geo node, ou créer un noeud Object Info et utiliser la pipette pour cherche l’objet “Collision”.
  • On va calculer la distance entre les points de l’objet collision et ceux du coussin. Là ou la distance est 0, on va faire un set position de ces Vertex à la position “Repos” qu’on avait gardé en mémoire.
  • Cela aura pour effet de réduire les chevauchements de géométrie entre le coussin au repos et le filet qui l’empêche, en ces endroits, de gonfler.
  • Voyez plutôt, sans le noeud Set Position:

  • Et avec le noeud Set Position:

  • Ajoutons un noeud Sample Nearest Surface (de type Vector) pour échantillonner la position du coussin.
  • On va changer la position des échantillons du collision en fonction de la géométrie du Collision object (ici, comme on na pas déplacé l’objet par rapport à l’originie, ça ne change rien de choisir Original ou Relative).
  • Pour ce faire, on va déplacer les Vertex après le Sample Nearest Surface en fonction de la position de l’objet Collision.

  • Comme on le constate, le mesh du collision object s’est aplati, il est exactement tangente à la surface du coussin au repos.
  • Bon, je monte Object Info plus haut, pour pas que les noodles se croisent

  • Tiens, branchez le socket Value de Sample Nearest Surface à Offset également, avec un Vector Scale. C’est chouette non?

Lien vers l'original

Banque de cours - Geo nodes et cloth Simulations - Partie 4 - Masking

Geo nodes et cloth Simulations - Partie 4 - Masking

  • Bon, mais c’est pas ça qu’on veut. Revenons à nos coussins.
  • Maintenant que le mesh du Collision est exactement sur la surface du coussin au repos, on va sen servir pour mieux calculer les collisions.
  • Reprenons le Named Attribute Repos. On va créer un mask en retirant tous les vertex du coussin qui sont à proximité du collision.
  • On soustrait donc de la valeur Repos la position de Geometry Proximity, on calcule la longueur résultante.
  • Si la distance est exactement 0, ce sera totalement noir puis ça ira en tons de gris de plus en plus vers le blanc.
  • Pour voir l’effet, Ctrl-Shift left click sur le noeud Vector Length, puis la même chose sur le premier Set Position.
  • On voit alors l’effet du vecteur résultant Length sur la géométrie du coussin au repos. Un mask quoi!

  • Mais il y a trop de gris. On va réduire la portée du mask (Map Range!) où on arrête de considérer les longueurs plus élevées que 0.04 par exemple:

  • On peut ensuite ajuster le falloff de noir vers blanc pour qu’il ne commence pas trop tôt (i.e. avoir plus de noir) avec une fonction Power. Ça donne essentiellement une courbe exponentielle, donc au début c’est lent, mais plus on avance, plus ça tombe (falloff) vite.

  • Et pour terminer le mask, un petit blur pour adoucir les bords:

  • Ok, maintenant, il est temps de combiner les deux, le coussin et la collision à l’aide du mask.
  • Alors, là où c’est noir, on veut que le coussin soit à sa position au repos, et plus il s’éloigne de ces endroits, plus il gonfle.
  • Pour ce faire, on Vector Mix la position des Vertex du coussin au repos avec la position du coussin gonflé. Le Factor mélangera de manière uniforme les deux.

  • Alors devinez qui va alimenter Factor? Si si, le Mask!

  • Maintenant, là où se trouve l’objet Collision, la forme du coussin est à sa position au repos. Voyez avec ce Geo nodes et sans.
  • Avant:

  • Après:

  • Vu qu’on a l’objet Collision dans nos Geo nodes, autant continuer comme ça, pas besoin de rendre visible l’objet Collision dans l’outliner. Même qu’on va retirer du render aussi.
  • On va donc joindre la géométrie du Collision avec le coussin et ajouter un set shade smooth.

Lien vers l'original

Banque de cours - Geo nodes et Cloth Simulations - Partie 5 - Material, Lighting et Shad

Geo nodes et Cloth Simulations - Partie 5 - Material, Lighting et Shading

Material, Lighting et Shading

  • Ajoutons un Set Material avant le dernier Join Geometry pour les deux géométries, celle du coussin et celle de l’objet collision:

  • À vous de jouer, créez de beaux materials, un bel éclairage, du beau compositing. Augmentez le subdivision surface du coussin (premier Geo node) à 4. Augmentez les valeurs du cloth simulation si nécessaire (Quality steps, Collision Quality) et refaites un bake puis un render de l’animation.

Lighting (tri-light, backdrop, contrast back light, compositing)

  • On le fait ensemble en classe

Un frame

L’animation

Lien vers l'original

DataViz

Cours 7 - Un peu de DataViz et de maths

Banque de cours - Historique 2

Historique

La visualisation de données est née avec les cartes préhistoriques et les marques de comptage, évoluant à travers les premiers graphiques statistiques créés par des personnalités comme William Playfair au 18e siècle, et les visualisations cruciales de données médicales par John Snow au 19e siècle. Les développements clés incluent les diagrammes en rose de Florence Nightingale pendant la guerre de Crimée, les travaux fondamentaux de statisticiens comme John Tukey et Jacques Bertin dans les années 1960-70, et la révolution numérique qui a rendu le traitement rapide des données et les visualisations interactives largement accessibles.

Origines préhistoriques et antiques

Premiers outils :

Les premières formes de visualisation de données étaient des outils primitifs pour compter et naviguer, comme les marques de comptage sur des os (par exemple, l’os d’Ishango il y a 20 000 ans) et les premières cartes.

Le 17e siècle a vu l’émergence de la visualisation statistique, avec des personnalités comme Michael Florent van Langren produisant les premières représentations de données statistiques.

Au 18e siècle, des figures comme William Playfair ont introduit des graphiques et diagrammes révolutionnaires pour visualiser les données économiques.

Le 19e siècle : Percées médicales et perspectives sociologiques

Épidémie de choléra :

En 1854, le Dr John Snow a créé une carte d’une épidémie de choléra à Londres, un moment crucial dans l’utilisation de la visualisation de données pour résoudre des problèmes concrets et influencer la santé publique.

Florence Nightingale :

Pendant la guerre de Crimée, Nightingale a utilisé des “diagrammes en rose” pour illustrer que davantage de soldats mouraient de maladies dans les hôpitaux que sur le champ de bataille, influençant la réforme hospitalière.

W.E.B. Du Bois :

Le début du 20e siècle a vu le travail pionnier de Du Bois, qui a utilisé des visualisations complexes dans son travail sociologique pour mettre en évidence les disparités raciales en Amérique.

Le 20e siècle : L’essor de la théorie scientifique et de l’informatique

Des chercheurs comme John Tukey et Jacques Bertin ont développé les bases scientifiques de la visualisation de données dans les années 1960 et 1970, faisant progresser les graphiques statistiques et la cartographie.
Edward Tufte :

Le livre influent de Tufte, “The Visual Display of Quantitative Information”, publié en 1983, a contribué à établir la visualisation de données comme domaine d’étude.

La fin du 20e siècle et le début du 21e siècle ont vu l’émergence d’outils et de plateformes logiciels sophistiqués, conduisant à des visualisations interactives et des tableaux de bord de données utilisés dans le journalisme, les entreprises et les gouvernements.

Le génial Nael Shiab (Radio-Canada et CBC)

https://ici.radio-canada.ca/info/2022/03/etalement-urbain-densite-population-villes-transport-commun-changements-climatiques/en

https://ici.radio-canada.ca/info/2022/07/ilots-chaleur-villes-inegalites-injustice-changements-climatiques/en

https://manpopex.us/

Lien vers l'original

Banque de cours - Quelques banques de données publiques

Quelques banques de données publiques

🌍 Mondial

OrganizationDomainLink
UN Data / UNStatsDemographics, health, economydata.un.org
World Bank Open DataEconomy, poverty, trade, developmentdata.worldbank.org
OECD DataSocial, labor, innovation, economydata.oecd.org
IMF DataFinance, debt, tradeimf.org/en/Data
FAO (Food & Agriculture)Agriculture, food securityfao.org/statistics
WHO (World Health Organization)Health, disease, life expectancywho.int/data
IPCC Climate DataClimate projectionsipcc-data.org
International Energy Agency (IEA)Energy, renewables, emissionsiea.org/data-and-statistics
ITU (Telecommunications)Internet, ICT adoptionitu.int/en/ITU-D/Statistics

🇫🇷 France

OrganizationDomainLink
INSEEEconomy, population, housinginsee.fr/en/statistiques
Data.gouv.frNational open data portaldata.gouv.fr
Ministère de la Transition ÉcologiqueClimate, energy, transportstatistiques.developpement-durable.gouv.fr
Météo-FranceWeather, climatedonneespubliques.meteofrance.fr
Banque de FranceEconomy, financebanque-france.fr/statistiques

🇨🇦 Canada

OrganizationDomainLink
Statistics CanadaDemographics, economy, societystatcan.gc.ca/data
Government of Canada Open DataFederal datasetsopen.canada.ca
Bank of CanadaFinance, monetary policybankofcanada.ca/rates/indicators
Environment and Climate Change CanadaClimate, environmentclimate.weather.gc.ca
Canadian Institute for Health Information (CIHI)Health systemcihi.ca/en

⚜️ Québec

OrganizationDomainLink
Institut de la statistique du Québec (ISQ)Demographics, economy, laborstat.gouv.qc.ca
Données Québec (open data)Provincial & municipal datasetsdonneesquebec.ca
Hydro-QuébecEnergy production/consumptionhydroquebec.com/data
Ministère de la Santé et des Services sociaux (MSSS)Health, public servicesmsss.gouv.qc.ca
Ministère de l’Environnement et Lutte contre les changements climatiquesEnvironment, climateenvironnement.gouv.qc.ca

🏙️ Montréal

Organization / PortalDomainLink
Ville de Montréal – Données ouvertesOfficial open data portal: urban planning, culture, infrastructure, transport, financesdonnees.montreal.ca
STM (Société de transport de Montréal)Public transport schedules, bus/metro networks, ridershipstm.info/en/about/developers
ExoSuburban trains and buses around Greater Montréalexo.quebec/en/about/open-data
Bixi MontréalBike-sharing data: stations, usage, historical trip datasetsbixi.com/en/open-data
SPVM (Service de police de la Ville de Montréal)Crime, safety, incident statistics (partly via Données Montréal)donnees.montreal.ca/organization/spvm
Santé Montréal (CIUSSS, Santé publique)Public health, environment, population indicatorssantemontreal.qc.ca
Montréal Open Environmental DataAir quality, water quality, green spaces, waste managementdonnees.montreal.ca/en/group/environnement
Port of MontréalTrade, shipping, logistics statisticsport-montreal.com/en/statistics.html
Lien vers l'original

Banque de cours - Quelques magnifiques Dataviz

# Quelques magnifiques Dataviz

Lien vers l'original

Banque de cours - Quelques autres magnifiques Dataviz

# Quelques autres magnifiques Dataviz

Lien vers l'original

Banque de cours - Quelques autres magnifiques Dataviz

# Quelques autres magnifiques Dataviz

Lien vers l'original

Banque de cours - Major cities population mapped onto Earth - Partie 1

Major cities population mapped onto Earth - Partie 1

☝🏼

Un énorme merci à Thijs Manders et ses tutos sur sa chaîne MTR Animation, avec son aimable permission!

  • Démarrer Blender, la version la plus récente
  • Créer les geo nodes suivants. Pour le noeud Import CSV, faites-le pointer vers le fichier CSV que vous venez de télécharger.

  • On va. faire un peu de math. On veut les points distribués sur une sphère.

  • Pour se faire, voici les formules mathématiques de projection sphérique:


  • Alors donc allons-y!

  • On va faire la première formule. Donc deux maths nodes de type cosine.

☝🏼

Essayez ensuite ctrl-shift-rmb et drag entre les deux noeuds Cosine. Blender va ajouter un math node qui combine les deux, on doit juste changer add pour multiply.
Note: Il faut activer l’addon “Node Wrangler”.

  • On doit également multiplier le résultat par une constante (c). Décidons pour l’instant d’une valeur de c = 4. On changera ça plus tard si nécessaire.
  • Ça c’est pour l’axe des X, donc on connecte le dernier multiply au socket X du Combine XYZ.

  • On doit faire la même chose pour y et z, sauf que y c’est sin * cos et z juste sin. Changeons également Value pour 50.

  • Bon, on voit un globe, mais y’a pas de continents. La raison en est que Longitude et Latitude sont données en degrés dans le CSV alors que Blender s’attend à des valeurs en radian.

  • On va créer un reroute au niveau des deux sorties de Longitude et des 3 sorties de Latitude.

☝🏼

Un truc pour ça: Shift-rmb et drag à travers les noodles!

  • Woah, c’est-y pas beau tout ça!

  • Maintenant, on va montrer la population par ville, on a cette donnée!

  • Commençons simplement, avec le set point radius. Mais faut remapper (map range!).

  • Mais on ne sait pas à l’avance le min et le max de la colonne Population. Comment faire?

  • Le noeud Attribute Statistics is the key!

  • Donc le map range va distribuer les valeurs qui sont, à l’origine entre Min et Max de la valeur Population, à un intervalle de [0.02, 0.7] par exemple.

  • Zoomez et allez voir vos villes préférées! Voyez par exemple la région montagneuses (Les rocheuses, les Alpes, l’Himalaya, y’a moins de points ou de très petits points!
  • Remarquez que ça coûte très peu cher car ce n’est pas de la géométrie encore!
Lien vers l'original

Cours 8 - La terre en DataViz - suite

Banque de cours - Major cities population mapped onto Earth - Partie 2

Major cities population mapped onto Earth - Partie 2

  • On va créer la Terre maintenant.
  • Ajouter une UV Sphere (une vraie), scale de manière à ce qu’elle soit juste un peu plus petite que les points en terme de diamètre.
  • Ajouter un subdivision surface modifier (2 pour le viewport, 3 pour le render).

  • Cachons les points (sélectionnez l’objet dont vous vous êtes servi pour créer le geo nodes et appuyer sur H.
  • Avec la sphère sélectionnée, allons dans le Shader Editor, Object Shader, et faire New Material que vous nommerez Earth.
  • Créez un Image Texture Node, allez chercher l’image “8k_earth_specular_map.tif” et connectez-la au socket Base Color du Principled BSDF.

  • On va créer un outline en se basant sur le fait qu’il y a gradiant entre le blanc (l’eau) et le noir (les continents).
  • Avec un Math node, on va aller chercher les valeurs entre 0.1 et 0.3 (donc le gris à la frontière), on les multiplie ensemble, ça va donner la valeur 0.03 et c’est cette valeur qu’on va utiliser de la texture.
  • Ça fait un super contour:

  • On va ajuster la puissance des lignes de contour:

  • Vous avez deviner, c’est en contrôlant la “Strength” de l’Emission Color qu’on peut arriver à le faire.

  • Je vais choisir un ton bleuté

  • Aussi, right-click sur la sphère et faire “Shade Smooth”

  • Aussi, je vais rendre notre sphère métalique et augmenter la roughness

  • Qu’est-ce qu’elle a la Terre de particulier que la Lune n’a pas? Une atmosphère bien sûr. On va en ajouter une.
  • Pour ce faire, un Layer Weight, qui offre un type de lentille fresnel va nous aider.

☝🏼

Les noeuds Fresnel et Layer Weight:
Le Fresnel Node et le Layer Weight Node sont essentiels pour créer des matériaux réalistes dans Blender, surtout lorsqu’on veut simuler les reflets, la translucidité ou le comportement optique des surfaces selon l’angle de vue.


1. Principe général : l’effet Fresnel

Le Fresnel (d’après Augustin Fresnel) décrit le phénomène selon lequel une surface réfléchit plus fortement à ras du regard (grazing angle) qu’en face directe.

➡️ En d’autres termes :

  • Quand tu regardes une surface de face, elle réfléchit peu.
  • Quand tu la regardes de biais, elle réfléchit davantage.

Ce principe est crucial pour tous les matériaux physiques (verre, eau, métal, plastique, etc.).


2. Le Fresnel Node

🔹 Localisation :

Shader Editor → Add → Input → Fresnel

🔹 Fonction :

Ce nœud calcule le facteur Fresnel pur à partir de l’indice de réfraction (IOR) du matériau.

La sortie du nœud donne une valeur entre 0 et 1 représentant la proportion de lumière réfléchie selon l’angle de vue.

🔹 Entrée principale :

  • IOR (Index of Refraction) : contrôle la courbe du dégradé.
    • Verre ≈ 1.45
    • Eau ≈ 1.33
    • Plastique ≈ 1.45
    • Métal (non applicable directement, car les métaux ont une réflexion complexe)

🔹 Sortie :

  • Fac (Factor) : intensité du Fresnel à chaque pixel.
    → 0 = vue de face, 1 = vue de biais.

🔹 Utilisation typique :

Mélanger deux shaders :

  • Un Diffuse BSDF (vue de face)
  • Un Glossy BSDF (vue de biais)

Exemple :

Fresnel (IOR=1.45)

└──> Mix Shader (Fac=Fresnel)
     ├── Diffuse BSDF
     └── Glossy BSDF

→ Résultat : un matériau réaliste dont les reflets augmentent selon l’angle de vue.


Le Layer Weight Node

🔹 Localisation :

Shader Editor → Add → Input → Layer Weight

🔹 Fonction :

Ce nœud est plus artistique et flexible.

Il ne se limite pas à la physique optique (comme Fresnel) mais te donne deux types de courbes liées à l’angle de vue :

  • Fresnel
  • Facing

🌀 Sortie :

Fresnel

Similaire au Fresnel Node, mais moins physiquement exact — c’est une approximation pratique.

  • Blend (entrée) : contrôle la douceur de la transition.
    • 0 → transition brutale
    • 1 → transition très douce
  • Fresnel (sortie) : valeur entre 0 et 1, plus élevée sur les bords (angles rasants).

déal pour créer des effets stylisés ou ajuster le contraste visuel sans se soucier des valeurs physiques exactes d’IOR.


Sortie :

Facing

C’est le complément du Fresnel :

  • 1 quand la surface fait face à la caméra.
  • 0 quand elle est vue de biais.

En gros :

“Facing” =
vue de face

“Fresnel” =
vue de biais


Utilisation typique :

  • Mélanger des shaders selon l’angle :
    → “Facing” pour un matériau mat au centre, brillant sur les bords.
  • Contrôler un dégradé sur la surface.
  • Animer des effets comme des lueurs sur les bords (rim light).

Exemple :

Layer Weight (Blend=0.3)

├── Fresnel → Mix Shader (brillance sur les bords)
└── Facing  → Factor pour un ramp color (effet halo)

4. Différences résumées

CaractéristiqueFresnel NodeLayer Weight Node
But principalPhysiquement exact (IOR)Contrôle artistique flexible
Entrée principaleIORBlend
Sortie principaleFresnel (angle de réflexion)Fresnel et Facing
Valeur de sortie0–1 selon l’angle0–1 selon angle ou face
Idéal pourRéalisme (verre, eau, plastique)Stylisation (halo, rim light, toon shading)

5. Exemples d’usage

Matériau réaliste

Fresnel (IOR=1.45)
 → Mix Shader
    ├── Diffuse BSDF
    └── Glossy BSDF

→ Reflète plus sur les bords, parfait pour plastique ou verre.


Effet artistique type “rim light”

Layer Weight (Blend=0.3)
 → Facing → ColorRamp → Emission Strength

→ Bord du modèle illuminé, centre plus sombre : effet de halo stylisé (très utilisé pour les effets toon ou outlines).


Astuce bonus :

Tu peux inverser la sortie “Facing” avec un ColorRamp inversé pour avoir le comportement opposé (par ex. éclairer le centre au lieu des bords).


  • Ce serait chouette de voir les longitudes et les latitudes. Il y a un moyen simple avec les geo nodes.
  • Ajouter un petit workspace et choisir Geometry nodes.
  • Avec la sphère sélectionné, faites New Geo Nodes.
  • Ajoutez un noeud de type Mesh to Curve et choisir Edges plutôt que Faces.

  • Mais on ne voit plus la terre. On va faire un join geometry. Rappelez-vous pouvez faire ctrl-shift et right-lmb et drag Le Group Input et le Mesh to Curve ça va les “additionner” de manière intelligente (ici, c’est bien sûr un join geometry).
  • Aussi, je trouve qu’il y’en a trop, je vais modifier le subdivision surface à 1 pour Viewport et Render:

  • Ceci dit, je ne veux pas si la grille sur les continents, seulement les océans.
  • Comment faire?
  • On peut utiliser la même texture de la map terrestre et s’en servir comme masque de sélection sur un noeud Delete Geometry!

  • Pas tout à fait ça encore, et c’est parce que la texture n’est pas mappé selon les UV. Pour ça, on va aller chercher les UV et utiliser un Maprange pour inverser le masque afin que la grille soit sur l’océan seulement:

☝🏼

On aurait pu uitiliser un Mathy Boolean de type “Not” plutôt qu’un Map Range, c’est même plus logique

  • Maintenant faut travailler les frontières. Vous remarquez, en mode Render, les edges sont effacés au complet ou rien. On veut donc plus de points par edge. Un resample curve va aider.

  • Bon, maintenant, ça traverse un peu sur les continents, y’a beaucoup de lignes semi effacées, et ça c’est dû au fait que Blender a de la difficulté à calculer sur des curves. Delete geometry, ça marche bien sur de la geometry, par sur des curves. On va convertir en mesh et ça va marcher.

  • Aaaah, beaucoup plus mieux!

☝🏼

Attention, dans Blender 5.x, l’ordre du join geometry est important ! Si vous ne voyez plus les continents, assurez-vous que l’entrée socket Geometry du Group Input est avant (plus haut) celle du Delete Geometry.

  • Ajustez la valeur de count dans Resample Curve pour améliorer encore plus la précision.

  • Un peu d’épaisseur pour longitudes et latitudes? Très facile vu que Curve to Mesh a un socket Profile Curve!

  • Un cercle comme profile curve, ça vous dit?

  • Un material sur les lignes serait sympa.
  • Dans la partie Shader (à gauche), cliquez sur la flèche de Slot et cliquer sur + pour créer un nouveau slot.
  • Ensuite cliquer sur New Material et nommez-le “Grid”.

  • Effacer le Principled BSDF et créer un noeud Emission.
    • Couleur dun ton bleuté
    • Strength = 6.
  • Du côté du geo nodes, insérer un Set Material entre Delete Geometry et Join Geometry (On veut cette texture seulement sur les lignes qui surplomblent les océeans).
  • Choisir Grid comme Material du noeud Set Material.

  • Dans le World Properties, mettre le strength de l’environment map à 0.

☝🏼

Si votre ordi en arrache avec le “Updating lights”, allez dans Render properties, sous Light et désactivez Light Tree.

Lien vers l'original

Banque de cours - Major cities population mapped onto Earth - Partie 3

Major cities population mapped onto Earth - Partie 3

  • Maintenant, ramenons les points (L’oeil à droite de l’objet Plane dans l’Outliner).
  • On aimerait les rendre plus visibles.

  • Avec les points sélectionnés, faites “New” do côté du Shader Editor.
  • Appelez ce Material “Cities”.
  • Remplacer Principled BSDF par un Emission Shader.
  • Ajoutez un Set Material dans la section Geo nodes.

  • Du côté de Emission, mettez la valeur de Strength à 20.
  • On veut maintenant que la couleur des points dépendent de la population à cet endroit.
  • On veut utiliser le même principe dans le Shader Editor que dans le Geo nodes: la population passant à travers un Map Range pour réduire l’échelle sans changer le rapport de proportions.
  • Cela étant dit, il n’y a pas de noeuds Map Range dans le Shader Editor (pas encore). On va donc créer des variables (Store Named Attributes) dans les Geometry Nodes qu’on va ensuite utiliser (Named Attribute) dans le Shader Editor.
  • On va donc utiliser le map range, mais un nouveau parce qu’on veut une valeur variant entre 0 (aucune couleur) et 1 (pleine saturation).

  • Un color ramp va rendre ça plus beau. Il faut par contre amener la couleur du côté très grandes populations vers la gauche pour qu’en en voit plus.
  • Il faut également réduire le diamètre des points, ça, c’est la valeur “To Min” du premier Map Range, on va le diviser par 10: de 0.02, on va passer à 0.002.

  • Maintenant qu’on connaît bien les lentilles Fresnel, ajoutons un petit glow autour des points.
  • À l’aide d’un noeud Layer Weight pour contrôler le Strength de l’Emission Shader.

  • Les points sont trop distancés par rapport à la sphère, corrigeons le tir.
  • Pour ce faire, on va positionner chaque point (Set position) sur la surface la plus proche (Geometry Proximity) de la sphère.
  • On va faire un drag and drop de la sphère dans le geo node pour obtenir son Object Info et on va s’en servir pour alimenter un noeud Set Position.

  • Vous remarquez que les points sont décalés un petit peu par rapport aux frontières. On peut ajuster en simplement faisant une rotation de la sphère selon son axe local (R R).

☝🏼

Attention, c’est lourd, allez-y doucement avec la touche Shift pour des micro-rotations.

  • Après ajustement:

  • Ça ne sera pas parfait, mais l’Univers s’en fout.

  • Vous pouvez aussi jouer avec la constante C (50) et l’échelle de la sphère (50,50,50), mais, normalement, ils devraient avoir la même valeur.

Le volume ambiant

  • Créer un cube beaucoup plus grand que la sphère (scale de 100 par exemple).
  • Dans data, Viewport Display, choisissez Wireframe.
  • Aussi, allez en mode Material Preview. Comme le lighting n’est pas encore fait, la sphère va apparaître noire en Render Mode.

  • Avec le cube sélectionné, allez dans le Shader Editor.
  • Vous pouvez phagociter le Geo Nodes workspace
  • On va créer un nouveau Shader (New), et on le nomme “Space Volume”.
  • Effacer le Principled BSDF et le remplacer par un Principled Volume.
  • Attention, il doit être connecté à Volume et non pas Surface du Material Output.

  • On va contrôler la couleur et la densité avec des noise textures disposées en fonction des texture coordinates de l’objet.

  • Pour la couleur, on va rendre la distribution des points entre 0 et 1 plus “smooth” (Map Range avec Smoother Step) avec un Map Range où on ne change pas les from et To min max.
  • Il faut aussi faire passer ce noise par un noeud Hue/Saturation/Value, on veut contrôler juste le Hue (la teinte) et avoir une valeur très faible (0.1).
  • La couleur, on va la choisir un peut bleutée.

  • Pour la densité, un Map Range qui est très petit à la sortie (entre 0 et 0.01). Voici des valeurs qui fonctionnent bien:

  • Oupsie, vous voyez l’erreur? J’ai branché le socket Density Attribute. C’est densité que je dois brancher.
  • J’ai aussi utiliser le socket Color (3 valeurs) des Noise Texture alors que Map Range s’attend à une seule valeur. Il faut utiliser le socket “Fac” à la place:

  • Revenir en mode Layout et en mode Rendered.
  • Ajouter une Light de type Sun et ajuster sa puissance à 10.

Les étoiles

  • Ça se fait très bien avec une IcoSphere.
  • Ajoutons donc une Ico Sphere avec un scale de 130 environ.

  • Right-Click et faire Shade Smooth.
  • Dans Viewport Display de la section Data Properties, Display as Wire comme le cube.

  • Ceci dit, on ne veut pas que le soleil affecte l’icosphere (c’est pour ça qu’elle apparaît blanche en haut).
  • Sélectionner le cube, faire “M” pour New Collection et nommer la collection “Fog”.

  • Ensuite, sélectionner l’objet Sun et dans les propriétés Data:
    • Aller dans la section Shading et choisir Light Linking.
    • Choisir la collection “Fog”.
  • Maintenant, le soleil n’éclaire que le volume du cube:

  • Pour les étoiles, sélectionnez l’Icosphere et aller dans le Shader Editor.
  • On va utiliser un Voronoi pour ça.
  • Faire New et nommer le Material Stars.
  • On va contrôler les étoiles et leur intensité avec l’alpha du Principled BSDF (on garde une couleur blanche) et le strength de l’Emission de ce dernier:

  • En zoomant un peu, je trouve que les grosses étoiles (threshold de 0.1) sont trop grosses. Je vais baisser le seuil (Threshold) à 0.05:

  • La beauté des cellules Voronoi, qu’on retrouve partout dans la nature
  • Un diagramme de Voronoï (ou polygones de Thiessen) est une partition d’un espace en régions adjacentes (appelées cellules) à partir d’un ensemble de points appelés “germes”
    • Chaque cellule contient un seul germe, et tous les points de cette cellule sont plus proches du germe qui s’y trouve que de tout autre germe.
    • La frontière entre une cellule et une autre est un segment de droite qui se trouve à égale distance entre le germe de la première cellule et celui de la deuxième.
    • Pavage de l’espace : Il divise l’espace (un plan, par exemple) en un ensemble de polygones.
    • Cellules d’influence : Chaque cellule délimite la zone la plus proche d’un point spécifique par rapport à tous les autres points de l’ensemble.
    • Applications : Ils sont utilisés dans de nombreux domaines, comme l’analyse spatiale (délimitation de zones d’influence) ou la géométrie.

  • Tout compte fait, un scale de 200 au lieu de 500 pour le Voronoi donne un meilleur résultat:

Compositing

  • Ajoutez une caméra
  • Passez en mode Caméra (cliquez sur l’icône caméra près du N menu dans le viewport ou faites 0 sur le numpad).
  • Cliquez sur le cadenas près du N Menu dans le viewport (juste en dessous de la caméra).
    • Ça va activer le “View navigation within the Camera View”
  • Maintenant faire Ctrl-B et créez une rectangle qui définira le frame de la caméra.

  • Cette technique permet de cacher ce qui sort du frame de la caméra.
  • Vu qu’on est en mode View Lock, utilisez la souris pour zoomer in/out, panner et tourner pour choisir le bon point de vue.

  • Pour mieux voir les étoiles, dans les propriétés de la caméra, changez le clip End à 1000 m par exemple.
  • Dans les Render Properties, choisir Cycles et changer le Max Samples à 128
  • Allez dans Render et faire Render Image pour avoir au moins un Frame et ainsi pouvoir voir l’effet du compositing.
  • Aller en Mode Compositing.
  • Pour ajuster le zoom de l’image, choisir View du côté du N Menu et ajuster le paramètre Zoom.
  • Commençons avec les noeuds de base suivants (vous vous souvenez? Celui du fichier Default.blend):

☝🏼

Dans Options du N Menu du Compositor, choisissez GPU pour accélérer le processus de compositing

- [ ] La couleur du Lift du Color Balance, un peu bleutée
- [ ] Un Glare de type Fog Glow pas trop fort
- [ ] Une légère distortion de la lentille
- [ ] Un peu plus de contraste et de brightness
- [ ] Un gamma légèrement augmenté

  • Ajoutez un effet de vignette:
    • Pour ce faire, on ajoute un masque de type Ellipse.
    • La taille est fonction de la taille de l’image (ici 40% de l’image)
    • On fait passer tout ça dans un Gaussian Blur.

  • Que l’on combine avec l’image elle-même à l’aide du mode Overlay. Aussi, j’ai désactivé (M pour Mute), le noeud Lens Distortion, il enlève trop des étoiles.

  • Il est important ici de désactiver le denoise, car ce dernier va retirer la majorité des étoiles, qu’il interprètera comme du bruit!
  • Conséquemment, faut augmenter le nombre d’échantillons et réduire le noise threshold.

  • J’ai ajusté le Voronoi des étoiles, je trouvais qu’il y’avait trop de gros points blancs:

  • Voici donc le résultat:

  • Je vous avoue que moi, je préfère sans compositing du tout. À vous de jouer!

Lien vers l'original

Banque de cours - Xam Geo Nodes

Xam Geo Nodes

Bulles volcaniques : 25 %

Évaluation et pondération

Pondération25 %
Critères d’évaluationDéplacement des sphères progressif en fonction de la proximité à un empty
Scale (mise à l’échelle) des bulles progressif en fonction de la proximité à l’empty
Couleurs procédurales en fonction de la proximité à un empty
Animation/déplacement des bulles progressive en fonction de la proximité à un empty que l’on déplace dans le viewport selon le plan XY (ne perdez pas de temps à faire le rendu de l’animation).

Quelques indices Noeuds utiles :

  • Proximity Geometry à un empty dont la position devient un Mesh Line avec un seul point:
  • Grid
  • Instance on points
  • Map Range
  • Stored Name Attributed (pour la couleur à transmettre au Shader)
  • Scale Instances et Translate Instances
  • Set Material

À remettre

  • Dans le drive (là où vous remettez vos devoirs)
  • Créez un dossier à votre nom (utilisez le même pour les 3 défis)
  • Dans ce dossier, ajouter Votre fichier “Nom - Bulles volcaniques.blend” (Assurez-vous d’activer le checkbox “File → External Data → Automatically Pack Resources” avant de sauvegarder)

Texte en geo wire frames : 30 % Créez ceci (pas besoin d’animation), mais, bien sûr, changez Karim pour votre prénom

Évaluation et pondération

Pondération30 %
Critères d’évaluationUn mesh en forme de cylindre pour les arrêtes (edges)
Une sphère pour les sommets (vertices)
Une face réfléchissante pour les plans
Une couleur différente pour les sommets, arrêtes et faces
Ne perdez pas de temps à faire un rendu d’une image ou d’une animation. Un mode “Rendered” dans le viewport suffira

Quelques indices Quelques noeuds utiles

  • String to Curve
  • Fill Curve

  • Extrude Mesh
  • Pour les Vertex : Instance on points
  • Pour les Edges : Mesh to Curve + Curve to Mesh avec un “Curve Circle” comme profil
  • Join Geometry

À remettre

  • Dans le drive (là où vous remettez vos devoirs)
  • Créez un dossier à votre nom (utilisez le même pour les 3 défis)
  • Dans ce dossier, ajouter Votre fichier “Nom - Texte.blend” (Assurez-vous d’activer le checkbox “File → External Data → Automatically Pack Resources” avant de sauvegarder)

Random City : 35 %

  1. Commencez par télécharger ce fichier Blender localement sur votre disque dur :
    https://drive.google.com/file/d/1C36Immf3IwxGeqRXn4hOFc5KX_8BmQNk/view?usp=sharing

  2. Renommez-le “Nom - City.blend”

  3. Ce fichier contient une collection d’assets représentant des buildings

  4. Ajoutez des geo nodes afin d’obtenir une distribution de building random selon une distribution de Poisson:

Évaluation et pondération

Pondération35 %
Critères d’évaluationDistribution random à partir d’une série d’objets
Présence de sources de lumières colorées également distribuées de manière random
Des objets ajoutés à la liste d’objets à distribuer sont pris en compte automatiquement
Rotation random des buildings, mais selon des multiples de 90 degrés
Scale random des buildings, mais clamped (map range !)
Pas besoin de textures ou Materials

Quelques indices Quelques noeud utiles

  • Distribute Points on Faces
  • Map Range
  • Random Value

À remettre

  • Dans le drive (là où vous remettez vos devoirs)
  • Créez un dossier à votre nom (utilisez le même pour les 3 défis)
  • Dans ce dossier, ajouter Votre fichier “Nom - City.blend” (Assurez-vous d’activer le checkbox “File → External Data → Automatically Pack Resources” avant de sauvegarder)
Lien vers l'original

Simulations

Cours 10 - Simulation nodes I

Banque de cours - Avant de commencer

Avant de commencer

Solution - Bulles volcaniques

Solution - Texte en geo wire frames

Solution - Random City

Lien vers l'original

Petite intro aux sim nodes

  • Créer cube
  • Dans le layout Geometry Nodes, ajouter un Simulation Node
  • Créer un Transform Geometry à l’intérieur
  • → geo nodes - Sim nodes
  • Ajouter un transform dans la sim et mettre Z à -0.1
  • On peut contrôler Skip pour arrêter la simulation
  • Delta time = 1 / FPS. On peut s’en servir pour s’assurer que, peu importe le FPS, la durée de la simulation reste la même
  • Ajouter le timeline sur une petite fenêtre en base de la zone Geo Nodes
  • Faire Play
  • Tout ce qui se trouve dans la zone Sim est répété pour chaque frame
  • Changeons le seed de la distribution à chaque frame de manière à vraiment avoir une distribution aléatoire.
  • Ajoutons un Grid et un Join Geometry avec un Distributed points on faces
  • Il faut revenir au début du timeline (Frame 1) pour recalculer la simulation
  • Avec un Set Position où Z = -0.1, on vient de créer une pluie de points de la dimension du Grid
  • Maintenant, on va enregistrer un attribut sous le nom “Vélocité”. C’est comme une variable en programmation.
  • Avec le noeud Store Named Attribute, une valeur sera enregistrée à chaque itération dans une variable que l’on nommera “Vélocité”
  • Avec un noeud Attribute, on peut récupérer cette valeur (i.e. celle du frame précédent) et l’appliquer au frame courant
  • Ici, on prend donc l’information du noeud Set Position, c’est un vecteur (une position [X,Y,Z]). On l’enregistre en mémoire sous le nom “Vélocité”. Le Store Named Attributed doit donc être de type “Vector” et le doamin est “Point” puisque Set Position détermine la position de la sortie de “Distribute Points on Faces”.
  • On prends cette valeur pour la prochaine itération via un noeud Attribute, on lui soustrait 0.01 selon l’axe des Z, et on utilise cette valeur pour la position du nouveau point. Vous m’suivez?
  • Revenir au Frame 1 et faire Play. Vous remarquez l’accélération?
  • Maintenant on veut un peu plus de random, c’est trop aligné notre pluie.
  • Pour ce faire, on peu créer une position initiale des points plus random. Et pour vraiment une distribution aléatoire, varier le seed du noeud Random à l’aide du No de frame:
  • En veut faire varier la position initiale d’un point entre -0.2 et 0.2 selon l’axe des Z

Banque de cours - Shadow tracing on an animated robot

Shadow tracing on an animated robot

Préparation

  • Aller chercher le fichier startup ici (une immense merci à Antoine Deslandes - Discord Delta Uniqx pour le modèle et l’animation):
    https://drive.google.com/file/d/1ctWQxCBzj_rKohLYOKKyazLhL1xrnJ2i/view?usp=sharing

  • Dans ce fichier, un robot a été modélisé et animé. Les morceaux de robots (les Québécois de ma génération verront la référence :D) se trouvent dans une collection nommée “Robot parts”

  • On voudrait expérimenter avec de la simulation de particules (la première simulation intégrée au Geo Nodes) à partir de la géométrie du robot.

  • Comme le robot est composé de plusieurs objets distincts, les amener à la main en tant que “Object Info” dans un système de geo nodes serait fastidieux (il y a une centaine objets!).

  • Commençons par le créer un objet pour avoir un système de geo nodes. Un Plane suffit.

⚠️

Assurez-vous de ne pas être dans la collection “Robot parts”!

  • Aller dans le système de Geo Nodes et faire New en s’assurant que le Plane est sélectionné. Nommer le geo nodes “Particle Sim” et l’épingler.

  • Maintenant on va écrire un script Python qui va aller chercher tous les objets de la collection “Robot parts”, les ajouter de manière ordonnée avec full cable management en tant que noeuds Object Info et les connecter à un Join Geometry.
  • Aller dans l’espace de travail “Scripting”.
  • Faites “Text → New”
  • Copier le code suivant:
import bpy
 
def add_object_info_nodes_from_collection(collection_name):
    # Get the active object and its Geo Node tree
    obj = bpy.context.active_object
    if not obj or not obj.modifiers or obj.modifiers[-1].type != 'NODES':
        print("No active object with a Geometry Nodes modifier selected!")
        return
    
    geo_nodes = obj.modifiers[-1].node_group
    nodes = geo_nodes.nodes
    links = geo_nodes.links
 
    # Find or create a Join Geometry node
    join_node = None
    for node in nodes:
        if node.type == 'JOIN_GEOMETRY':
            join_node = node
            break
    if not join_node:
        join_node = nodes.new(type='GeometryNodeJoinGeometry')
 
    # Load the collection
    collection = bpy.data.collections.get(collection_name)
    if not collection:
        print(f"Collection '{collection_name}' not found!")
        return
 
    # Create a Frame node to hold all Object Info nodes
    frame = nodes.new(type='NodeFrame')
    frame.label = f"{collection_name} Objects"
    frame.name = f"{collection_name}_Frame"
    frame.width = 400
 
    # Grid layout settings
    spacing_x = 200  # Horizontal spacing between columns
    spacing_y = -200 # Vertical spacing between rows
    nodes_per_column = 10
 
    created_nodes = []
 
    max_col = 0
    max_row = 0
 
    for index, obj_in_collection in enumerate(collection.objects):
        # Calculate grid position
        col = index // nodes_per_column
        row = index % nodes_per_column
 
        max_col = max(max_col, col)
        max_row = max(max_row, row)
 
        x = -600 + (col * spacing_x)
        y = row * spacing_y
 
        # Create Object Info node
        obj_info = nodes.new(type='GeometryNodeObjectInfo')
        obj_info.parent = frame
        obj_info.location = (x, y)
        obj_info.inputs['As Instance'].default_value = False
        obj_info.inputs['Object'].default_value = obj_in_collection
 
        if hasattr(obj_info, 'transform_space'):
            obj_info.transform_space = 'RELATIVE'
 
        # Create a Reroute node
        reroute = nodes.new(type='NodeReroute')
        reroute.location = (x + 150, y)
 
        # Connect Object Info to Reroute
        links.new(obj_info.outputs['Geometry'], reroute.inputs[0])
 
        # Connect Reroute to Join Geometry
        links.new(reroute.outputs[0], join_node.inputs['Geometry'])
 
        created_nodes.append(obj_info)
 
    # Calculate Frame Size (optional: Blender does it automatically if you move nodes manually)
    frame.location = (-650, 150)
    frame_width = (max_col + 1) * spacing_x
    frame_height = (max_row + 1) * abs(spacing_y)
 
    # Move Join Geometry node to right of Frame
    join_node.location = (-600 + frame_width + 300, 0)
 
    print(f"Added {len(created_nodes)} Object Info nodes from collection '{collection_name}', framed, with reroutes, 10x10 grid, Join Geometry neatly positioned.")
 
# Direct call (no popup)
add_object_info_nodes_from_collection("Robot parts")
  • En gros, le script crée des Object Info pour chaque objet trouvé dans la collection “Robot parts”, les configure en mode “relative”, les grouper dans un Frame nommé “Robot Parts Objects” et les connecte à un noeud “Join Geometry”.

  • Déplacer le noeud Group Output assez loin à droite

  • Cliquer sur le bouton “Run script” (le bouton “Play” du Script Editor.

⚠️

J’ai configuré mon Scripting workspace pour qu’on voit à droite le 3D Viewport ainsi que le Geo Node.
Aussi, il se peut que le système de nodes crée cache les noeuds Group Input et Group Output. Comme les Object Info et le Join Geo sont sélectionnés, vous pouvez les déplacer (G then move with the mouse).

  • On a terminé avec le script. Revenir au workspace Geometry Nodes.

  • Connecter la sortie de Join Geometry à l’entrée Group Output. Déconnecter Group Input (on ne veut pas voir le Plane).

  • Cacher les objects Robot Parts dans l’Outliner, on veut voir le résultat du système de geo nodes seulement.

  • Faites Play dans le timeline!

  • Comme les objects sont la géométrie du robot tel qu’animé, l’animation est conservée dans la version geo nodes. Chouette non?
  • On est prêt pour de la simulation de particules!

Simulation 1 - Onion Skin shadow trail

  • Ajouter une Simulation Zone et connecter la sortie du Join Geomtery à l’entrée d’un 2e Join geometry qui, lui, se trouve dans la simulation Zone.

  • Faites Play.

  • Que constatez-vous?

  • That’s right! Les geo nodes, sans Simulation zone, sont “stateless”, c’est-à dire que tout est calculé à chaque frame.

  • Mais avec un simulation Zone, tout d’un coup, les frames précédents sont accumulés! On vient de créer un “Stateful” machine!

  • Ok, et si on voulait retenir seulement, disons, les 5 frames précédents seulement?

  • On veut effacer tout ce qui est plus ancien que “n” frames. Comment faire?

  • On va commencer par garder en mémoire la géométrie courante:

  • Maintenant, il nous suffit de retirer du Join Geometry de la Simulation Zone, les géométries des frames plus petits qu’une certaine distance du Frame courant.

  • Ici, on “Delete Geometry” tout ce qui fait partie de “Selection”.

  • Ce qui aliment le socket Selection du noeud Delete Geometry, c’est le noeud Compare → Less than, qui évalue la valeur de “Frame_courant” (dans le noeud Named Attributed) par rapport au No de frame de l’animation (Scene Time) moins une certaine valeur, ici 4.

  • Ce que ça fait effectivement, c’est effacer toutes les géométries dont le No de frame est plus petit que le frame courant moins 4.

  • L’effet est un trail Onion Skin.

  • Je réalise que je devrais nommer “Frame_courant” à “stored_frame” plutôt, car il n’est plus courant dès qu’il ne l’est plus :) Je le fais de suite:

⚠️

Ah oui, si vous changez quelque chose dans la simulation zone, faut revenir au frame 1 pour recalculer la cache et voir l’effet du chngement.

Lien vers l'original

Banque de cours - Il pleut sur mon parapluie

Il pleut sur mon parapluie

Parapluie

  • Allez chercher le fichier ici: https://drive.google.com/file/d/1egIiBe2CITLGio_DKGRpxmP6gYiuU9RN/view?usp=sharing
  • Ok, il y a un parapluie et on aimerait que la pluie de points entre en collision avec le parapluie.
  • Remarquez que le parapluie est dans une collection nommée “Low poly umbrella”
  • Ajouter un noeud “Collection info” dans la section Geo nodes.
  • Choisir la collection du parapluie et choisir Relative au lieu d’Original (on veut la position relative au monde, pas la position locale).
  • Ajouter un noeud Realize Instance. C’est la géométrie du parapluie qu’on va pouvoir alors utiliser comme collision.
  • On a besoin de calculer la normale à la surface sur le parapluie au point d’impact des particules.
  • Alors ce que fait cette séquence:
    • Prends la collection Low Poly Umbrella
    • Crée une géométrie réalisée (un vrai mesh)
    • De cette géométrie, trouve d’abord l’index de la face la plus proche
    • À partir de cet index, trouve la normale (Vecteur) de cette face.
    • Capish?
    • On va utiliser maintenant un Vector Math avec l’opération “Reflect”, qui va calculer la réflexion d’une particule qui frappe une surface en fonction de la normale à cette dernière.
    • Ça tombe bien, on a gardé l’info de la position de chaque particule dans l’attribut “Vélocité, vous vous souvenez?
    • On veut calculer la réflection d’une particule, basé sur sa vélocité lorsqu’elle frappe l’une des faces du parapluie.
    • Avec ce calcul, la sortie du socket Reflect est un vecteur dans la direction réfléchie de la direction initiale de la particule.
    • Maintenant, on doit calculer “quand”, i.e. combien proche de la surface du parapluie doit-on être pour modifier la particule et ne plus utiliser sa vélocité, mais plutôt sa valeur “Reflected”.
    • Le noeud Geometry Proximity va bien nous aider pour ça!
    • On veut que la proximité soit plus petite qu’une certaine valeur. Cette valeur, on va la calculer.
    • On prend la position d’une particule, i.e. son vecteur, on la normalise (Noeud Named Attributed dans Normalize).
    • On fait la même chose avec le vecteur à la sortie de Sample Index, qui est l’index d’une la face la plus proche d’une particule. On la normalise également.
    • On utilise ensuite l’opération vectorielle Dot Product (produit scalaire), qui permet de déterminer l’angle entre deux vecteurs.
    • Le produit scalaire, ça vous rappelle des mauvais souvenirs? Moi oui, quand j’étais ingénieur, quoique j’aimais les maths reliés à tout ce qui est visuel (splines, Béziers, mesh, quadriques, etc.).

Produit Scalaire, définition et exemples Le produit scalaire (également appelé produit intérieur ou dot product en anglais) de deux vecteurs est une opération mathématique qui prend deux séquences de nombres de même longueur (représentant généralement des vecteurs dans un espace euclidien) et renvoie un nombre unique (scalaire).

Définition

Pour deux vecteurs A et B dans un espace de dimension :

Le produit scalaire est défini par :

Interprétation géométrique

Le produit scalaire peut également s’exprimer en fonction des normes (magnitude) des vecteurs et du cosinus de l’angle  entre eux :

Exemple de calcul:

Si

Alors

Le produit scalaire est largement utilisé en physique, en ingénierie et en informatique, notamment pour déterminer les angles entre les vecteurs, les projections et les calculs de travail en physique.

- [ ] En gros, le Dot product est utilisé pour déterminer l’orientation entre 2 vecteurs.
    **Interprétation d’un produit scalaire négatif **$(\mathbf{A} \cdot \mathbf{B} < 0)$** :**
        Comme la fonction cosinus détermine le signe du produit scalaire, un produit scalaire négatif se produit lorsque $\cos\theta < 0$
        Cela arrive lorsque l’angle entre les deux vecteurs est **supérieur à 90° et inférieur à 180°** $( 90^\circ < \theta < 180^\circ )$
        Cela implique que les 2 vecteurs pointent principalement dans des directions opposées.
        Si le produit scalaire est exactement 0, cela signifie que les vecteurs sont perpendiculaires ($\theta = 90^\circ$).
- [ ] En d’autres termes: Si un vecteur est projeté sur un autre et que le produit scalaire est négatif, la projection pointe dans la **direction opposée** au vecteur de référence.
- [ ] Bon ben c’est ce qu’on veut!
- [ ] Donc on veut faire quelque chose si le produit scalaire est plus petit que 0.
- [ ] Voici la séquence pour déterminer la direction des particules de pluie:


- [ ] En gros:
1. On va chercher la collection “Parapluie”. On “réalise les instances”, i.e. la géométrie sera un vrai mesh. Sinon, pas de collisions possibles.
2. Normal et Sample Nearest et Sample Index permettent d’aller chercher l’index de la face la plus proche d’une particule.
3. Geometry proximity va chercher la distance entre une particule de pluie et une face de la géométrie du parapluie.
4. Si la distance est “les than” un certain seuil (ici on a mis 0.2, mais on va le paramétrer avec un group input), alors le résultat est “True”, sinon le résultat est False.
5. Alimentons ce résultat dans le noeud Multiply à droite.
6. En parallèle si on veut, comparons la valeur normalisée du vecteur de la normale à la surface d’une surface donnée du parapluie (Normal + Sample Nearest + Sample Index + Normalise), et la valeur normalisée de la vélocité d’une particule de pluie (Named Attribute + Normalise).
7. Calculons le produit scalaire des deux vecteurs, donc de la vélocité de la particule et de la normale à la surface.
8. S’ils sont opposés (Less Than à droite), retourne Vrai et alimente le Multiply.
9. Si les deux valeurs à l’entrée de Multiply sont vraies, alors la sortie sera True (1), sinon la sortie sera False (0). Cette sortie alimente le Factor du Noeud Mix Vector.
10. Le Mix Vector, via son Factor qui est alimenté par le noeud Multiply, va essentiellement favoriser soit le vecteur A si Factor = False (0), ou le vecteur B si Factor = True (1).
11. L’entrée A du Mix Vector c’est la vélocité de la particule de pluie.
12. L’entrée B du Mix Vector, c’est la valeur “Reflect” par rapport à la normale à la surface du parapluie avec un Vector Math de type Scale pour contrôler le rebondissement des particules sur le parapluie.
- [ ] Puissant non?
- [ ] Maintenant, tout ça, i.e. la boîte “Direction de la pluie” va alimenter le substract avec Z = 0.01 du début.
- [ ] Si les particules de pluie ne sont pas assez proches du parapluie, c’est la vélocité dont la valeur Z est déduite de 0.01 à chaque fois.
- [ ] Si les particules sont très proches du parapluie, les particules vont aller dans la direction opposée à la normale à la surface à laquelle elles touchent, à raison de la même vélocité Z = Z = 0.01) mais cette fois-ci dans la direction de cette normale.
- [ ] Ouf, si vous êtes perdus, voici le fichier avec les noeuds à date: https://drive.google.com/file/d/1eoQBUndh8QdeNlYH0m0-lIj71TOo10Bw/view?usp=sharing
- [ ] Ok, on va brancher maintenant des noeuds du Group Input à:
- [ ] Threshold du premier Less Than (Celui après “Geometry Proximity)
- [ ] Scale du Vector Math de type Scale (après Reflect)

- [ ] Avec le noeud Group Input sélectionné, activez le N Menu (N).
- [ ] Renommez Value pour “Proximité” et Scale pour “Rebond”.
- [ ] On peut maintenant contrôler la taille de la pluie (Size X et Size Y, ainsi que la distance en deçà de laquelle les particules de pluie se mettent à rebondir ainsi que le taux de rebondissement!

- [ ] Jouez avec tout ça!
- [ ] Vous pouvez également paramétrer la valeur de l’incrément en Z (0.01) du noeud Substract, i.e. la vélocité de la pluie. Comment faire? (Hint: Combine XYZ).
- [ ] Renommez Z à Vélocité

- [ ] Et tant qu’à y être, on va paramétrer aussi la densité (noeud distribute points on faces). Il se nomme déjà Density, pas besoin de le renommer.

- [ ] Be careful with density, Size X Size Y, trop grandes valeurs = komputer kaput 🙂
- [ ] Le fichier final: https://drive.google.com/file/d/1esuuOK05OhBPpHvGxRIF3lHcEQrdvYla/view?usp=sharing
- [ ] Avec Play en action, déplacez le parapluie.
- [ ] À vous de jouer.

Lien vers l'original

Banque de cours - Particle Sim with aging and Lifetime

Particle Sim with aging and Lifetime

Lien vers l'original

Cours 11 - Simulation nodes II

Banque de cours - Mantaflow, Domaines, Flow, Effectors, ma première simulation feu

# Mantaflow, Domaines, Flow, Effectors, ma première simulation: feu

Mantaflow Mantaflow est le simulateur de dynamique des fluides (liquides ou gazeux) adopté par Blender à partir de la version 2.82. Mantaflow a d’abord été développé en 2009 par le Computer Graphics Laboratory de l’Institut fédéral des technologies de Zurich. Il est dorénavant maintenu et développé par l’Université Technique de Munich.

📌

“Replay” ne fonctionne que lorsque le mode de synchronisation de lecture est réglé sur “Play Every Frame”. Si vous avez besoin d’utiliser “Frame Dropping” ou “Sync to Audio”, envisagez d’utiliser les options “Modular” ou “All” ci-dessous.

Ma première simulation

Le domaine

  • Créer un cube (⇧ A → Mesh → Cube)

  • Avec le cube sélectionné, mise à l’échelle selon l’axe des Z multiplié par 2 (s → z → 2 → ↩)

  • Avec le cube sélectionné, appliquer la mise à l’échelle (Apply Scale) : ⌃ A → Scale

  • Créer une sphere (⇧ A → Mesh → UV Sphere)

  • Avec la sphère sélectionnée, scale 0.5 (s → 0.5 → ↩)

  • Avec la sphère sélectionnée, appliquer la mise à l’échelle (Apply Scale) : ⌃ A → Scale

  • Passer à la vue de face (Numpad 1)

  • Avec la sphère sélectionnée, déplacer à la base du cube (g → z → -1.4 → ↩)

  • Sauvegardez votre scène dans un dossier nommé “Ma première simulation”, intitulez le ficher .blend “Ma première simulation.blend”. Il est important de sauvegarder le fichier dans son propre répertoire dédié avant de créer la simulation car sinon les données de la cache seront générées au mauvais endroit.

  • Avec le cube sélectionné, activer la simulation “Fluid” dans les propriétés physiques

  • Choisir le type “Domain”. Les frontières du cube constituent maintenant la limite du domaine à l’intérieur duquel sera calculée la simulation.

  • Vous remarquerez qu’un petit cube apparaît maintenant à la base du cube, indiquant qu’il s’agit d’un domaine de simulation. Ce cube est en fait un Voxel et sa taille détermine la “résolution” de la simulation

  • Avec le cube sélectionné, assurez-vous que le checkbox “Adaptive Domain” est activé

  • Sous “Cache”, choisissez 150 comme nombre de frames (Frame Start = 1, End = 150). Assurez-vous que le type de cache est “Modular” au lieu de “Replay”

  • Avec le cube sélectionné, Aller dans Material et cliquer sur “New”.

  • Nous ne voulons pas un “Principled BSDF” mais bien un “Principled Volume”.

  • Choisir la couleur de la fumée, régler la densité à 8 et le “blackbody Intensity” à 7

  • Avec le cube sélectionné, passer à l’espace de travail “Shading”

  • Choisir “Object” et s’assurer que la sortie du Principled Volume Shared soit connecté à l’entrée “Volume” et non pas “Surface” du noeud “Material Output”

  • Sélectionner la sphère, aller dans les propriétés Material, choisir New Material (“Principled BSDF” sera sélectionné par défaut) et choisir une couleur orangée comme couleur de base

Le fluide (feu + fumée)

  • Maintenant passons au feu. Sélectionner la sphère, et choisir “Fluid” dans les propriétés physiques. Choisir comme type “Flow”

  • Changer le “Flow Type” pour “Fire + Smoke”. “Flow Behavior” devrait être “Inflow”. Fixer “Fuel” à 1.3 et dans la section “Flow Source”, “Surface Emission” devrait être à 0.5

  • Dans le timeline, s’assurer que le dernier Frame de l’animation est bien 150.

  • Sélectionner le Cube. Nous somme prêt à bake la simulation! Appuyer sur le gros bouton “Bake Data” dans les prorpiétés physiques, sous la section “Settings”.

  • Cliquer sur “Play” dans la barre d’animation pour voir le résultat!

La caméra

  • En vue de face (Front View: Numpad 1), ajouter une caméra (⇧ A → Camera → Camera).

  • Passer à la vue de côté (Numpad 3) et déplacer la caméra vers la gauche de 10 mètres (g → y → -10)

  • Passer à la vue Caméra, vous devriez voir ceci

  • Nous n’avons pas besoin d’éclairage car nous avons mis en place un environnement HDRI. Mais réduisons l’intensité de cet environnement un peu.

  • Dans la propriété “World”, réduisez la force (Strength) à 0.2.

Amélioration de la qualité

  • Taille des voxels. Si l’on augmente la “Resolution Division”, le voxel rapetissera, indiquant un plus grand nombre de voxels dans le domaine et conséquemment une plus grande résolution de la simulation.

  • Cela dit, plus la division de résolution est grande (i.e. plus la taille des voxels est petite), plus la cache occupera de l’espace disque et plus la simulation prendra du temps à cuire.

📌

La simulation est composée de voxels, une grille de cubes qui compose le domaine, et la résolution de cette grille est le paramètre principal pour une meilleure qualité. Veuillez noter que si vous doublez la résolution, vous obtenez en réalité 8x les cellules (et le temps de cuisson) car elle double dans 3 directions.

  • Avec le cube sélectionné, dans les propriétés physiques, cliquer sur le bouton “Free Data” pour effacer la cache de la simulation.
  • Augmenter la division de résolution (Resolution Division) à 64.
  • Déselectionner “Adaptive Domain”.
  • sous la section “Fire”, Réduire le “Reaction Speed” à 0.5. Ce paramètre contrôle la hauteur des flammes. Plus la valeur est faible, plus les flammes seront hautes.
  • Sous cette même section, augmenter la “Vorticity” à 0.7.
  • Cliquer sur “Bake Data”. Cela devrait prendre plus de temps et la cache sera plus grande. Mais le résultat plus beau également!

Le rendu d’une image

  • Choisissez un frame sur le timeline où la simulation est visuellement intéressante (e.g. Frame 60)
  • Dans le menu “Render”, choisir “Render Image”
  • Une fois le rendu terminé, choisir le menu “Image → Save” et sauvegarder l’image sous le nom “Frame 60.png” dans le même dossier que celui de votre animation.

Le rendu de l’animation sur notre machine

  • Dans la propriété “Output”, section “Output”, choisir “//” pour le dossier (cela veut dire le même endroit que là où se trouve le fichier .blend). Pour File Format, choisir “FFmpeg Video”. Choisir “MPEG-4” comme “Container” dans la section “Encoding”. Enfin dans la section “Video”, choisir le codec “H.264”.
  • Choisir le menu “Render → Render Animation”.
  • “Patience et longueur de temps valent mieux que force ni que rage”…

Devoirs

  • Installer Sheep-It Render Farm
  • Suivre les 3 tutos suivants si vous n’avez jamais touché à Blender:


Lien vers l'original

Banque de cours - Simulation de tissu et objets gonflables

# Simulation de tissu et objets gonflables

Bon, d’accord…

  • Si vous voulez absolument les Gizmos, c’est par ici:
  • Et pour le curseur à l’origine du monde (le fameux ⇧ - clique droit de la souris que vous avez en mémoire musculaire Maya et qui vous fait déplacer le curseur), c’est par ici (ou alors ⇧ S → Cursor to World Origin):

Un peu de théorie La simulation de tissu est l'un des aspects les plus difficiles de la 3D; il s’agit en effet d’un élément du monde réel simple en apparence que l'on tient pour acquis, mais qui a en réalité le résultat d’interactions internes et environnementales très complexes (à ce sujet, si vous voulez apprendre à dessiner de manière réaliste, dessinez des drapés!). Le tissu est généralement modélisé comme un maillage 2D pour simuler des objets du monde réel tels que les tissus, les drapeaux, les bannières. Et pourtant, le tissu peut aussi être utilisé pour modéliser des objets 3D tels que les ours en peluche, les oreillers, les ballons, ou les balles. Le tissu interagit avec et est affecté par d'autres objets en mouvement, le vent et d'autres forces, les points de tension, la texture dudit tissue, la gravité, ainsi qu'un modèle aérodynamique général. Not an easy thang to simulate.

La physique du tissu est simulée avec des ressorts virtuels qui relient les sommets (vertices) d’un maillage (mesh). Il existe quatre types de ressorts qui contrôlent la manière dont le tissu se plie:

Ressorts de tension (bleu), ressorts de compression (rouge), ressorts de cisaillement (shear) (cyan), et ressorts de flexion angulaire (bending) (vert).

Ressorts de tensionContrôle la rigidité du tissu.
Ressorts de CompressionContrôle la force requise pour compresser, plier ou froisser le tissu.
Ressorts de cisaillement (Shear)Contrôle la déformation angulaire du tissu.
Ressorts de flexion angulaire (Bending)Contrôle la résistance du tissu au pliage ou au froissement.

Un drapeau qui flotte au vent

Modélisation et simulation

  • Ouvrir nouveau projet Blender (File → New → General) dans un dossier intitulé “Drapeau”
  • Copiez une image dans votre dossier “Drapeau” (par exemple celle-ci: https://drive.google.com/file/d/1H51xBe3DCgpHPHMArblzj9WcycXGrR70/view?usp=sharing)
  • Créer un plan, le tourner de 90 degrés par rapport à l’axe des X
  • Il est très important de subdiviser le plan d’abord avant de lui donner une forme plus rectangulaire d’un drapeau, sinon les subdivisions ne seront pas carrées et cela créera de drôles de comportements lors de la simulation.
  • Avec l’objet toujours sélectionné, passer en mode “Edit” (Tab → Edges)
  • Ajoutons de la géométrie à l’objet. Cliquer droit sur l’object en mode Edit et choisir subdivide.
  • Ouvrir le menu des paramètres de la subdivision (en bas à gauche du viewport)
  • Choisir 40 pour la valeur de “Number of Cuts” puis faire ↩ et revenir en mode objet (Tab → Object)
  • Maintenant on peut rendre le carré rectangulaire et les subdivisions seront correctes. Revenir en mode Object, S X 2 ↩ puis Apply Scale (⌃ A → Scale).

  • Remarquez que “Number of Cuts” = 40 donne une subdivision de 41 x 41 n-gons et non pas 40 x 40 n-gons car un Cut de 1 = 2 x 2 n-gons.

  • Avec l’objet sélectionné choisir les paramètres physiques et choisir “Cloth”

📌

Note, on peut choisir des tissus prédéfinis dans le petit menu hamburger à droite de l’intitulé “Cloth”, comme Cotton, Soie, etc. Mais nous allons régler nos paramètres manuellement.

  • Donc ne pas choisir de tissu prédéfini, choisir Cloth et nous allons régler les paramètres manuellement.

  • Si on fait “Play” de l’animation, on constatera que “tissu” tombe raide comme un bloc à cause de la gravité. Bon, c’est déjà ça.

  • Nous allons maintenant fixer un groupe de sommets (Vertices) de manière à ce que le tissu soit comme accroché (on l’accrochera à un poteau tout à l’heure)

  • Passer en mode Objet, édition des sommets (Tab → Edit Vertex). Dans les propriétés “Object Data”, ajouter un Vertex group et nommez-le “Accroche”.

  • Sélectionner les deux premiers sommets (Vertices) en haut à gauche et les deux derniers en bas à droite du mesh, puis cliquer sur le bouton “assign” dans le “Data property”, en s’assurant que le Vertex Group “Accroche” soit sélectionné. Cela va assigner les 4 sommets au groupe Accroche avec un poids de 1.

  • Pour vérifier que la chose a fonctionner, Sortir du mode Object et passer au mode Weight Paint:

  • Maintenant, revenons aux propriétés physiques et dans la section “Shape”, choisir le “Pin Group” “Accroche”.

  • Passer en mode Object et faire Play. Vous devriez constater que la gravité a toujours un effet sur le tissu, mais les points d’accroche ne bougent pas. Mais on remarque que le drapeau se traverse lui-même, normalement ce n’est pas normal. Il faut activer le “Self collision” afin que l’objet entre en collision avec lui-même.

  • Vous devriez maintenant constater que, si vous faites Play, l’animation est plus lente car Blender doit calculer les collisions de l’objet avec lui même.

  • Ajoutons un peu de vent. ⇧ A → Force Field → Wind.

  • On veux que le vent parte de la gauche vers la droite dans la direction de l’axe des X, derrière le drapeau. R Y 90 ↩ puis G X -5 ↩

  • Sélectionner le drapeau, passer à l’espace de travail Shader, choisir Object au lieu de World puis choisir New. Un Principled BSDF va apparaître. Ajouter une Image texture (⇧ A → Texture → Image Texture). Faire Open et choisir l’image Akira.jpg. Connecter la sortie Color de noeud Image Texture à l’entrée Base Color du Principled BSDF.

  • Passer en vue orthogonale frontale (Numpad 1), changer en mode “Material Preview” (Z → Material Preview) et changer la force du vent (entre 15 000 et 30 000 environ). Faire Play. Vous devriez voir l’effet du vent sur le drapeau.

  • Changer également la durée de l’animation à 500 frames. N’oubliez pas de mettre 500 pour le End Frame également dans la propriétés physiques, sous “Cache”.

  • Dans les Modifiers du drapeau, ajouter un Subdivision Surface (3 pour le viewport, 4 pour le render) et un “Smooth by angle”. S’assurer que le Smooth by angle soit le dernier en bas dans la pile (stack). Donc dans l’ordre, les modifiers devraient être : Cloth, Subdivision puis Smooth by Angle.

  • Il est temps de régler les paramètres de simulation du tissu. Dans les propriétés Physiques:

PropriétéValeurDescription
Quality Steps7Un peu plus élevée mais pas trop pour ne pas ralentir la simulation pendant qu’on travaille dessus. Au moment du rendu, on augmentera le steps à une bien plus grande valeur (e.g. 256).
Speed Multiplier1Le facteur influençant la durée du temps écoulé. 1 = “temps réel”.
Stiffness → Tension15Contrôle la rigidité du tissu.
Stiffness → Compression15Contrôle la force requise pour compresser, plier ou froisser le tissu.
Stiffness → Shear5Contrôle la déformation angulaire du tissu.
Stiffness → Bending2Contrôle la résistance du tissu au pliage ou au froissement.
Damping → Tension5Même chose que pour Stiffness, mais comme une suspension de voiture, ici Damping indique l’intensité avec laquelle les effets de stiffness s’estomperont. Par analogie, s’il n’y avait que le ressort dans une suspension de voiture (comme au début), la voiture oscillera beaucoup; l’amortisseur amorti les oscillations du ressort.
Damping → Compression5
Damping → Shear5
Damping → Bending2
Caching → Simulation Start1début de la simulation
Caching → Simulation End500Fin de la simulation.
Collision → Quality6Contrôle la qualité du calcul des collisions, autant avec l’objet lui-même qu’avec les autres objets. Évidemment, plus le chiffre est élevé, plus ça va coûter cher en calculs.
Object CollisionActivéOn veut que l’objet entre en collision avec les autres objets de manière réaliste.
Distance0.01
Self CollisionActivéOn ne veut pas que l’objet passe à travers lui-même.
Distance0.01
  • Le champ de force Vent donne une force constante dans une seule direction, le long de l’axe Z local de l’objet de force. La puissance de cette force est visualisée par l’espacement des cercles affichés et la taille de la flèche.
  • Pour le vent, les paramètres sont comme suit:
PropriétéValeurDescription
ShapePlaneLa forme selon laquelle le vent sera calculée
Strength30 000La puissance du vent
Flow1La facteur “vitesse” du fluide “air”. 1 = réaliste.
Affect → LocationOui
Affect → RotationOui
Noise Amount0.5Histoire de ne pas avoir un vent qui ne varie jamais.
Seed21Changer le seed changera la génération des nombres aléatoires
AbsorbtionOuiUne partie de l’énergie du vent est absorbée par les objets ayant la propriété Collision
Wind Factor1Le degré avec lequel l’énergie du vent est absorbée par des tissus
FalloffPas utiliséParamètres contrôlant le degré avec lequel la force du vent diminue avec la distance. Dans notre cas, ne pas le spécifier signifie que la force du vent ne diminuera pas, ce qui fera en sorte que la distance du Force Field par rapport au drapeau n’importera pas.
  • Dans les propriétés Render, choisir Cycles, retirer la transparence dans la section “Film”. En mode Render (Z → Rendered) vous devriez voir le HDRI.
  • Passer en mode Shading, choisir World au lieu de Object, diminuezl’intensité du HDRI à 0.7. Dans le preview, passer en mode Rendered, puis changer les valeurs de rotation Z et X de la texture Environment HDRI jusqu’à que vous ayez un point de vue satisfaisant:
  • Dans l’espace de travail “Layout”, ajuster un peu plus le point de vue, puis ajouter une caméra et faire ⌃ ⌥ Numpad 0 pour fixer la position de la caméra. S’assurer que le drapeau soit un peu vers le premier tiers à gauche du cadre de la caméra.
  • Passons maintenant à la texture du drapeau. Sélectionner le drapeau et passer en mode Shading. S’Assurer de sélection Object et non pas World. Vous devriez voir la texture Akira (ou l’image que vous aviez choisie au début).
  • Allons d’abord chercher des textures de tissu, une pour le maillage lui-même, l’autre pour des défauts de tissu, pour un peu plus de réalisme. Poliigon.com est super chouette, mais il y’en a des tonnes. Je vous en ai préparé deux, télécharger ces deux fichiers .zip dans un dossier que vous nommez “Textures” dans votre dossier Drapeau et y décompresser les fichiers .zip:
  • Nous avons déjà la couleur pour notre drapeau (l’image Akira), ce dont nous avons besoin, c’est de la texture de tissu, pas sa couleur. Dans Le shading Editor, ajouter une “Image Texture” et ouvrir le “Displacement” map 2K de la texture FabricCanvas001, en l’occurence le fichier FabricCanvas001_DISP_2K.jpg
  • Maintenant, on veut connecter cette texture à l’entrée “Normal” du Principled BSDF, mais pour ce faire, il faut passer à travers un Noeud Bump pour convertir l’entrée “Color” du Displacement Map en information de variation de la normale. Enfin, il faut connecter Color du displacement map à l’entrée “Height” du Bump, pas “Normal”. La couleur des connecteurs vous indiquent dans Blender si la connexion est compatible ou pas.
  • Par exemple, avec la connexion suivante, on constate que le bump map ne fonctionne pas, que le connecteur passe du jaune au violet et qu’on ne voit pas l’effet de la texture dans le rendu:
  • La texture est trop grande. Cliquer sur le noeud Displacement, faire ⌃ T pour, via le Node Wrangler, ajouter les coordonnées de la texture, et augmenter l’échelle (scale) à 5 sur les trois axes. On va également réduire l’intensité du bump node à 0.4 et mettre la distance a 0.5
  • Ajoutons maintenant des plis et défauts, en utilisant la texture “FabricCreasesWrinkles001”.
  • D’abord sélectionner dans le node editor la texture Displacement et faire ⇧ D pour le dupliquer.
  • Dans la nouvelle instance de l’image texture node, faire X pour retirer l’image actuelle et faire Open ou ouvrir le fichier normal map intitulé “FabricCreasesWrinkles001_NRM_VAR1_2K.jpg”.
  • Connecter ce nouveau noeud à un noeud “Normal Map” dont vous changez l’intensité (Strength) à 0.4. La sortie Normal de ce noeud Normal Map devrait être connecté à l’entrée “Normal” du Bump Node.
  • Maintenant, notre drapeau est trop mince, ajoutons un “Solidify Modifier”, mais s’assurer qu’il se trouve avant le dernier modifier intitulé “Smooth by Angle”.
  • Il est temps de créer le poteau. Revenir dans l’espace de travail “Layout”, en mode Solid, en vue orthogonale frontale (Numpad 1) et créer un cylinder (⇧ A → Mesh → Cylinder)
  • Dans les paramètres de création, changer le diamètre (Radius) à 0.03, la hauteur (Depth) à 4. Cliquer dans un endroit vide fera disparaître le menu des propriétés de création.

  • Sélectionner le cylindre derechef, et déplacer le à la gauche du drapeau et bien évidement le haut du cylindre doit être aligné à peu près avec le haut du drapeau.
  • Comme nous n’avons pas déplacé le drapeau suite à sa création, le cylindre devrait être aligné quand on regarde le tout en vue orthogonale d’élévation (Numpad 7). Vérifier que c’est bien le cas et corriger si nécessaire.
  • Ajoutons une sphère au bout d’une petite extrusion au sommet du poteau.
  • D’abord sélectionner le poteau, passer en mode édition “Face”, sélectionner la face du haut.
  • Faire “Inset” (I), déplacer la souris de manière à créer un cercle concentrique au diamètre extérieur du cylindre, puis faire Extrude dans l’axe des Z (E Z) et déplacer encore une fois la souris pour obtenir cette petite extrusion.
  • Ajoutons une petite boule au sommet du poteau et ce sera assez. ⌃ A → Mesh → UV Sphere. Donnez-lui un diamètre de 0.05 et déplacez-la au sommet du poteau.
  • Une petite texture métallique maintenant pour le poteau et la sphère. Sélectionner le poteau, et dans les paramètres “Material”, faire New pour un créer un Princpled BSDF. Nommer ce Material “Poteau”. Choisir une couleur gris-bleu, Mettalic à 1. C’est assez.
  • Maintenant sélectionner la sphère, est dans les paramètres Material, ne pas faire New mais choisir “Poteau” comme material. Les deux vont partager la même texture maintenant.
  • Cliquer droit sur le poteau et faire “Shade Smooth”. Même chose pour la sphère.
  • Le drapeau doit entrer en collision avec le poteau, il faut donc s’assurer que ce dernier ait la propriété physique “Collision”. Sélectionner le poteau, et choisir “Collision” dans les propriétés physiques:
  • Nous sommes prêts à faire un “Bake” de la simulation. Sélectionner le drapeau, aller dans les propriété “Physics” et augmenter la qualité (Quality Steps) à 128. Pour un rendu de production, augmenter la qualité à 256, 512, voire plus.
  • Augmenter également la qualité des collisions, dans la section “Collisions”, choisir 10 par exemple.
  • Dans la section “Cache”, mettre le End Frame à 120, le changer également dans l’animation, sinon à 500 frames, le calcul de la simulation va prendre trop de temps.
  • Cliquer sur Bake. C’est le temps d’une pause.
  • Faites Play en mode Render. Faites un rendu d’un des frames. C’est zoli quand même non?

Animation

  • On va quand même rendre ça cool, avec de la brume et la caméra qui tremble à cause du vent.

  • Commencer par créer un cube qui couvre toute la scène qui apparaît devant la caméra:

  • Ce cube servira de volume qui contiendra l’effet volumétrique de brume.

  • Dans le shading Editor, avec le cube sélectionné, s’assurer d’être en mode Object et faire New pour créer un nouveau Material.

  • Effacer le Principled BSDF et créer plutôt un noeud “Principled Volume”. Connecter la sortie Volume de ce dernier à l’entrée Volume du Material Output. Tout va devenir noir car le volume est très dense. Baisser la densité à environ 0.1.

  • Créer un noeud Noise Texture et un noeud Color Ramp; connecter la sortie Factor du Noise Texture à l’entrée Factor du Color Ramp puis connecter la sortie Color du Color Ramp à l’entrée Density du Principled Volume.

  • Faire ⌃ T en ayant le Noise Texture sélectionné pour rajouter des Mapping Coordinates. On veut les coordonnées du cube, donc connecter la sortie “Object” du noeud Texture Coordinates à l’entrée Vector du noeud Mapping.

  • Changer l’échelle du Noise Texture à 15 et déplacer la couleur noire du color ramp vers le milieu. Ici le Color Ramp agit comme un pinceau : la couleur noire complètement à gauche apparaîtra quand la valeur du facteur est 0, puis graduellement vers le blanc quand cette valeur se rapproche de 1.

  • Maintenant, on veut animer le mouvement de la brume. Pour ce faire, on va passer de 3D à 4D pour le Noise Texture, ce qui va rajouter la dimension temporelle “W”.

  • Augmenter le niveau de détail à 16 pour le Noise Texture.

  • Ce qu’on veut animer c’est la position X (déplacement vers la droite dans le sens du vent) et le paramètre W.

  • S’assurer, dans le layout Editor, d’être au Frame 1. Dans le Shading Editor, cliquer droit sur la coordonnée X du noeud Mapping et faire “Insert Keyframes”. Si vous avez déjà un keyframe à cet endroit, le sous-menu contextuel sera “Replace Keyframes” au lieu de “Insert Keyframes”.

  • Aller au frame 120, changer la valeur X à, disons 5, 10 ou 30, et faire “Insert Keyframes” derechef. Il faut jouer avec cette valeur jusqu’à ce que vous obteniez un effet satisfaisant (et c’est là qu’une carte graphique performante aide grandement!).

📌

Vous pouvez temporairement ajouter une section montrant le timeline dans le shading editor pour ne pas avoir à changer de layout à chaque fois que vous voulez déplacer la tête de lecture dans le timeline.

  • À bien y penser, je vais baisser l’intensité du HDRI à 0.4 au lieu de 0.7 (World dans le shading Editor, ou alors la propriété World dans la section des propriétés à droite). Vous savez comment faire.

  • Revenir au frame 1. Cliquer droit sur la coordonnée W et faire Insert Keyframes.

  • Aller au frame 120, changer la valeur de W pour, disons, 10, et faire encore une fois Insert Keyframes.

  • Woot woot! Maintenant, on va faire trembler la caméra.

  • En vue Layout, ajouter un workspace pour voir le Graph Editor. Sélectionner la caméra.

  • Au frame 1, faire I pendant que la caméra est sélectionnée et que la souris est dans le 3D viewport.

  • Sélectionner l’Axe des X du keyframe de la caméra dans “Object Transform” du Graph Editor. On peut ajouter des modifiers aux courbes!

  • Faire “N” dans le graph editor pour faire apparaître le “N” menu s’il n’est pas visible. Dans la section Modifiers, faire Add Modifier et choisir Noise.

  • Du bruit a été ajouté au mouvement selon l’axe des X de la caméra!

  • Changer l’échelle à 6-10 (Scale) du modifier pour un mouvement saccadé certes, mais pas débile mental.

  • Changer le depth à environ 5, cela donnera un aspect moins robotique au noise.

  • Vous pouvez jouer avec les paramètres, comme le strength si le noise est trop fort (je l’ai baissé à 0.7).

  • Vous pouvez ajouter des noise modifiers aux autres axes (Y et Z) si vous voulez, pour plus de réalisme.

  • Vous pouvez également animer un mouvement à la caméra si l’idée vous en dit.

  • Et voilà, on a terminé. Ce qui est cool, c’est qu’un effet Parallax nous donne l’impression que le poteau bouge également (ce que l’on pourrait faire!).

  • Maintenant le rendu! Utilisez SheepIt Render Farm si vous pouvez, sinon votre carte graphique locale. Générez des PNGs puis faites un montage vidéo avec son et tout le toutim et générer la vidéo!

  • Voici ce que ça donne de mon côté (P.S., je suis allé chercher un poteau dans BlenderKit et j’ai modélisé des oeillets au niveau des accroches; j’ai également joué avec les paramètres du Noise Texture, ceux de la valeur des Keyframes X du mapping et W du Noise Texture jusqu’à satisfaction). Le bruitage, j’ai tout trouvé ça sur artlist.io. Si vous les voulez, c’est par ici:

    https://drive.google.com/drive/folders/1KMvh9JOHhtWA1y4HkoR-OaF2d0sfCKc5?usp=sharing

  • À votre tour, soyez créatifs, changez le HDRI, ajouter un soleil comme source de lumière tiens, changer la texture du drapeau, ajouter des lampadaires avec émission de lumière, have fun, soyez fous!

Devoirs

  • Un coussin gonflable à votre effigie, similaire à ceci:

  • Critères

    • Changer la texture pour quelque chose qui vous représente
    • Vous pouvez modifier le End Frame pour une rotation plus lente: 360 au lieu de 80. Moi, pour la démo, j’ai tout simplement doublé la séquence, en inversant l’ordre de la deuxième série d’images.
    • Ajouter des effets sonores
    • Laisser aller votre imagination, surprenez-moi
  • Walkthrough

Lien vers l'original

Python

Banque de cours - Blender et Python 1

Blender et Python 1

Blender et Python, Intro

Installation de Python - Ça vient avec Blender

  • Installer Blender 5.1.1 (blender.org)
  • Démarrer un PowerShell (Win-R ou taper “PowerShell” dans le search bar) et tapez la commande suivante pour vérifier la présence de Python:
C:\'Program Files\Blender Foundation\Blender 5.1'\5.1\python\bin\python --version

Activer Developper Extras et Python Tooltips dans Blender

  • Dans Blender, choisir Edit→Preferences et dans interface, activer “Developper Extras” et “Python Tooltips”

Blender Workspace pour Python

  • Créer un nouveau fichier .blend

  • Ajouter un espace de travail horizontal en haut de type “Scripting → Info”

  • Ajouter un espace de travail vertical à droite de type “Scripting → Text Editor”

  • Changer le timeline pour l’espace de travail “Scripting → Python Console”

  • Pour le reste du cours on va jouer à créer des primitives

  • Dans le viewport, faites ⇧ A et créez par exemple un cube

  • Qule code Python apparaît dans l’espace “Info”?

  • Effacer le cube, copiez et coller le code de création dans la console Python, changez un peu les paramètres de Localtion et Scale et faites ↩

  • Essayez d’autres actions et jouer avec la console

  • Dans l’espace text Editor, assurez-vous d’activer Line numbers, Word Wrap et Syntax Highlighting. Cliquez également sur New et tapez le nom du fichier python “AddObject.py”

  • Choisir le menu Text, puis Save-As et sauvegarder le code dans le dossier cours1

  • Sauvegarder également le fichier Blender sous le nom AddObject.blend dans le même dossier cours1

💡

Note: le code dans le script editor est sauvegardé avec le fichier .blend, mais il est bon d’en avoir une copie externe dans un fichier .py, donc faire régulièrement, dans l’espace de travail Text Editor: Text → Save

  • Tapez les instructions suivantes dans le text editor:
import bpy
 
for i in range (1,10):
    bpy.ops.mesh.primitive_cube_add(size=2, enter_editmode=False, align='WORLD', location=(i, i/2, i), scale=(0.2, i/5, 1))
  • Amusez-vous à essayer toute sortes de trucs et machins
  • À la fin du cours, n’oubliez pas de faire Text → Save du fichier .py dans l’espace de travail Text Editor et File → Save du fichier .blend

https://karimaktouf.ca/graphs/bpy-module-map/

Essayez ces exemples de code

import bpy
 
# Select all objects in the scene
bpy.ops.object.select_all(action='SELECT')
 
# Delete all selected objects
bpy.ops.object.delete()
 
#
# Create Cubes
#
 
for i in range (1,10):
    bpy.ops.mesh.primitive_cube_add(size=2, enter_editmode=False, align='WORLD', location=(i, i/2, i), scale=(0.2, i/5, 1))
#
# Random Objects
#
 
import bpy
import random
 
# Clear the current scene by selecting and deleting all objects
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
 
# Define the number of primitives to create along X and Y axes
grid_size_x = 5
grid_size_y = 5
spacing = 3
 
# Create primitives in a grid
for i in range(grid_size_x):
    for j in range(grid_size_y):
        # Randomly select a primitive type to add
        primitive_type = random.choice(['CUBE', 'SPHERE', 'CONE', 'TORUS'])
        
        # Calculate the position for the primitive
        x = i * spacing
        y = j * spacing
        z = random.uniform(0, 5)  # Random height
        
        # Add the chosen primitive type
        if primitive_type == 'CUBE':
            bpy.ops.mesh.primitive_cube_add(size=1, location=(x, y, z))
        elif primitive_type == 'SPHERE':
            bpy.ops.mesh.primitive_uv_sphere_add(radius=1, location=(x, y, z))
        elif primitive_type == 'CONE':
            bpy.ops.mesh.primitive_cone_add(radius1=1, depth=2, location=(x, y, z))
        elif primitive_type == 'TORUS':
            bpy.ops.mesh.primitive_torus_add(location=(x, y, z))
        
        # Randomize the rotation of the object
        obj = bpy.context.object
        obj.rotation_euler = (random.uniform(0, 3.14), random.uniform(0, 3.14), random.uniform(0, 3.14))
        
        # Add a random scale factor to make each object unique
        scale_factor = random.uniform(0.5, 2)
        obj.scale = (scale_factor, scale_factor, scale_factor)
 
# Adjust camera
bpy.ops.object.camera_add(location=(10, -15, 10))
camera = bpy.context.object
camera.rotation_euler = (1.1, 0, 0.8)
 
# Adjust lighting
bpy.ops.object.light_add(type='POINT', radius=1, location=(10, 10, 10))
light = bpy.context.object
light.data.energy = 1000
#
# Sinusoïdale
#
 
import bpy
import math
 
# Clear the current scene by selecting and deleting all objects
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
 
# Animation settings
frame_start = 1
frame_end = 250
bpy.context.scene.frame_start = frame_start
bpy.context.scene.frame_end = frame_end
 
# Define the grid size and spacing
grid_size_x = 10
grid_size_y = 10
spacing = 2
 
# Create a list to store the spheres
spheres = []
 
# Create spheres in a grid pattern
for i in range(grid_size_x):
    for j in range(grid_size_y):
        # Add a UV sphere
        bpy.ops.mesh.primitive_uv_sphere_add(radius=0.5, location=(i * spacing, j * spacing, 0))
        sphere = bpy.context.object
        spheres.append(sphere)
 
# Animate the spheres with a wave effect
for frame in range(frame_start, frame_end + 1):
    bpy.context.scene.frame_set(frame)
    
    # Loop through each sphere and set its location based on a sine wave
    for index, sphere in enumerate(spheres):
        i = index // grid_size_x
        j = index % grid_size_x
        
        # Calculate the wave height based on sine function (wave-like motion)
        wave_height = math.sin((frame / 10) + (i + j) / 2)
        new_location = (i * spacing, j * spacing, wave_height * 2)
        
        # Update sphere location
        sphere.location = new_location
        
        # Insert a keyframe for the location
        sphere.keyframe_insert(data_path="location", index=-1)
 
# Adjust camera to have a good view of the animation
bpy.ops.object.camera_add(location=(12, -20, 15))
camera = bpy.context.object
camera.rotation_euler = (1.1, 0, 0.8)
 
# Set active camera
bpy.context.scene.camera = camera
 
# Add lighting to the scene
bpy.ops.object.light_add(type='SUN', location=(15, -10, 20))
light = bpy.context.object
light.data.energy = 5
#
# Petit robot avec Material
#
 
import bpy
 
# Clear the current scene by selecting and deleting all objects
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
 
# Function to create a material with a given color
def create_material(name, color):
    mat = bpy.data.materials.new(name=name)
    mat.diffuse_color = color  # RGBA values
    return mat
 
# Create materials for different parts of the robot
body_material = create_material("BodyMaterial", (0.1, 0.5, 0.8, 1))  # Blueish
head_material = create_material("HeadMaterial", (0.8, 0.8, 0.8, 1))  # Light Grey
eye_material = create_material("EyeMaterial", (0, 0, 0, 1))  # Black
arm_leg_material = create_material("ArmLegMaterial", (0.3, 0.3, 0.3, 1))  # Dark Grey
antenna_material = create_material("AntennaMaterial", (1, 0, 0, 1))  # Red
 
# Create the robot body
bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 1))
body = bpy.context.object
body.scale = (1, 0.6, 1.5)  # Reshape the cube to form the body
body.data.materials.append(body_material)  # Apply material
 
# Create the robot head
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.75, location=(0, 0, 3.25))
head = bpy.context.object
head.data.materials.append(head_material)  # Apply material
 
# Create the robot eyes
for eye_location in [(-0.3, 0.4, 3.5), (0.3, 0.4, 3.5)]:
    bpy.ops.mesh.primitive_uv_sphere_add(radius=0.1, location=eye_location)
    eye = bpy.context.object
    eye.data.materials.append(eye_material)  # Apply material
 
# Create the robot arms
for arm_location in [(-1.5, 0, 1.5), (1.5, 0, 1.5)]:
    bpy.ops.mesh.primitive_cylinder_add(radius=0.2, depth=2, location=arm_location)
    arm = bpy.context.object
    arm.rotation_euler = (0, 1.57, 0)  # Rotate to align properly
    arm.data.materials.append(arm_leg_material)  # Apply material
 
# Create the robot legs
for leg_location in [(-0.5, 0, 0), (0.5, 0, 0)]:
    bpy.ops.mesh.primitive_cube_add(size=0.5, location=leg_location)
    leg = bpy.context.object
    leg.scale = (0.3, 0.3, 1)  # Reshape to form legs
    leg.data.materials.append(arm_leg_material)  # Apply material
 
# Create the robot antenna
bpy.ops.mesh.primitive_cylinder_add(radius=0.05, depth=1.5, location=(0, 0, 4.5))
antenna = bpy.context.object
antenna.data.materials.append(antenna_material)  # Apply material
 
# Create the antenna top sphere
bpy.ops.mesh.primitive_uv_sphere_add(radius=0.1, location=(0, 0, 5.25))
antenna_top = bpy.context.object
antenna_top.data.materials.append(antenna_material)  # Apply material
 
# Set up lighting
bpy.ops.object.light_add(type='AREA', radius=5, location=(5, -5, 6))
light = bpy.context.object
light.data.energy = 1000  # Increase light intensity
 
# Set up camera
bpy.ops.object.camera_add(location=(7, -7, 5))
camera = bpy.context.object
camera.rotation_euler = (1.1, 0, 0.8)
 
# Set the camera as the active camera
bpy.context.scene.camera = camera
#
# Fibonnaci
#
import bpy
import math
 
# Clear the current scene by selecting and deleting all objects
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
 
spheres = []
 
def generateSunflowerSpiral(numPoints=1000, spacing=0.4, zHeight=0):
    points = []
    goldenAngle = 137.5 * (math.pi / 180.0);
 
    for i in range(numPoints):
        angle = i * goldenAngle;
        radius = spacing * math.sqrt(i);
 
        x = radius * math.cos(angle);
        y = radius * math.sin(angle);
 
        points.append((x, y, zHeight));
 
    return points;
 
 
points = generateSunflowerSpiral()
 
for x,y,z in points:
    # Add a UV sphere
    bpy.ops.mesh.primitive_uv_sphere_add(radius=0.2, location=(x,y,z))
    sphere = bpy.context.object
    spheres.append(sphere)
Lien vers l'original

Banque de cours - AMazeIng

AMazeIng

Que fait ce bout de code selon vous? Et en quel langage est-il écrit?

char*M,A,Z,E=40,J[40],T[40];main(C){for(*J=A=scanf(M="%d",&C);
--            E;             J[              E]             =T
[E   ]=  E)   printf("._");  for(;(A-=Z=!Z)  ||  (printf("\n|"
)    ,   A    =              39              ,C             --
)    ;   Z    ||    printf   (M   ))M[Z]=Z[A-(E   =A[J-Z])&&!C
&    A   ==             T[                                  A]
|6<<27<rand()||!C&!Z?J[T[E]=T[A]]=E,J[T[A]=A-Z]=A,"_.":" |"];}

On a Maze program - The art of obfuscation par John Tromp

Mon tout premier projet professionnel 3D - Parcours 3D dans un labyrinthe, commande par la voix

/*========================================================================*\
||                                                                        ||
|| MODULE     : MAZE.C                                                    ||
||                                                                        ||
||                                                                        ||
|| DESCRIPTION: Programme qui genere un labyrinthe 2-D a l'aide de        ||
||              l'algorithme du "spanning tree" (arbre de recouvrement).  ||
||                                                                        ||
|| REMARQUES  : L'impression est en mode texte.                           ||
||                                                                        ||
||                                                                        ||
|| AUTEUR     : Karim Aktouf                                              ||
||                                                                        ||
|| CREATION   : le 10 aout 1993 <-- VOUS N'ÉTIEZ PAS NÉS!                 ||
||                                                                        ||
|| REVISION   : le 13 aout 1993                                           ||
||              le 03 juin 1996 - Les parametres ont maintenant une       ||
||                                valeur par defaut, et ajout de deux     ||
||                                autres parametres pour specifier le     ||
||                                charactere pour les lignes horizontales ||
||                                et celui des lignes verticales.         ||
||                                                                        ||
\*========================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
 
typedef enum _bool {FALSE, TRUE} BOOL;
 
typedef unsigned TypedeCell;
#define AUCUN     0
#define SPAN      1
#define FRONTIERE 2
 
typedef unsigned TypedeCase;
#define FERMEE  0
#define OUVERTE 1
 
 
/* La norme ANSI veut pas de enum dans des bit fields !!!
 * Dommage, c'est elegant...
 *
 * typedef enum _TypedeCell {AUCUN, SPAN, FRONTIERE} TypedeCell;
 * typedef enum _TypedeCase {FERMEE, OUVERTE}        TypedeCase;
 */
 
typedef struct _Cell  Cell;
typedef struct _FCell FCell;
 
 
struct _Cell
{
  TypedeCell Type:2;
  TypedeCase Bas:1,
             Droite:1;
};
 
 
struct _FCell                 /* Element de la liste circulaire de cellules */
{                             /* frontiere                                  */
  int L;
  int C;
  FCell *Next;
  FCell *Prev;
};
 
 
 
/*========================================================================*\
||                                                                        ||
||  Prototypes des fonctions utilisees                                    ||
||                                                                        ||
\*========================================================================*/
 
Cell  **InitMaze      (void);
void  GenerateMaze    (int L, int C);
void  PrintMaze       (char H, char V);
void  AddToFList      (FCell *FPtr);
void  RemoveFromFList (FCell *FPtr);
void  MarkAdj         (int L, int C, TypedeCell T);
FCell *ChooseRandomF  (void);
void  ConnectToSPAN   (int L, int C);
 
 
/*========================================================================*\
||                                                                        ||
||  Variables globables                                                   ||
||                                                                        ||
\*========================================================================*/
 
Cell  **MazePtr     = NULL;
FCell *FList        = NULL;
 
int  NbL=10,                    /* Nombre de lignes              */
     NbC=10,                    /* Nombre de colonnes            */
     NbF=0;                     /* Nombre d'elements dans FList  */
 
char H='|',                     /* Char. des lignes horizontales */
     V='|';                     /* Char. des lignes verticales   */
 
 
int main(int argc, char **argv)
{
  time_t t;
  int i=0;
 
  if (argc >= 2)
    if ((NbL = atoi(argv[1])) < 2)
    {
      printf("\nNombre de lignes invalide (%d) doit etre au moins 2.\n", NbL);
      return -1;
    }
 
  if (argc >= 3)
    if ((NbC = atoi(argv[2])) < 2)
    {
      printf("\nNombre de colonnes (%d) doit etre au moins 2.\n", NbC);
      return -1;
    }
 
  if (argc >= 4)
    H=*argv[3];
 
  if (argc >= 5)
    V=*argv[4];
 
  if (!(MazePtr = InitMaze()))
    return -1;
 
  /* On choisit une cellule au hasard entre i=1..NbL-1 et j=1..NbC-1 */
 
  srand((unsigned) time(&t));
  GenerateMaze((rand() % (NbL-1)) + 1, (rand() % (NbC-1)) + 1);
 
  PrintMaze(H, V);
 
  return 0;
}
 
 
/*========================================================================*\
||                                                                        ||
||   Fonction   : InitMaze                                                ||
||                                                                        ||
||   Description: Alloue l'espace memoire necessaire et initialise aux    ||
||                valeurs par defaut chaque cellule du labyrinthe.        ||
||                                                                        ||
||   Parametres : nil                                                     ||
||                                                                        ||
||   Retour     : Pointeur a l'espace memoire occupe par le labyrinthe    ||
||                                                                        ||
||   Remarques  : Le labyrinthe est organise en matrice 2-D dynamique,    ||
||                c'est-a-dire que le pointeur pointe a une COLONNE de    ||
||                pointeurs contenant NbL pointeurs, chacuns pointant sur ||
||                une LIGNE de NbC elements. l'acces a la cellule de la   ||
||                LIGNE i, COLONNE J se fait alors par [i][j] tout        ||
||                simplement, comme s'il s'agissait d'un tableau 2-D      ||
||                statique.                                               ||
||                                                                        ||
||   Auteur     : Karim Aktouf                                            ||
||                                                                        ||
||   Creation   : le 10 aout 1993                                         ||
||                                                                        ||
||   Revision   : le 13 aout 1993                                         ||
||                                                                        ||
\*========================================================================*/
Cell **InitMaze(void)
{
  Cell **Maze;
  int i, j;
 
  if (!(Maze = (Cell **) malloc(sizeof(Cell *) * NbL)))
    return NULL;
 
  for (i=0; i < NbL; i++)
  {
    if (!(Maze[i] = (Cell *) malloc(sizeof(Cell) * NbC)))
      return NULL;
 
    for (j=0; j < NbC; j++)
    {
      Maze[i][j].Type   = AUCUN;
      Maze[i][j].Bas    = FERMEE;
      Maze[i][j].Droite = FERMEE;
    }
  }
 
  /* Le mur du haut est un peu special */
  for (j=0; j < NbC; j++)
    Maze[0][j].Droite = OUVERTE;
 
  /* Meme chose pour le mur de droite  */
  for (i=0; i < NbL; i++)
    Maze[i][0].Bas    = OUVERTE;
 
  return Maze;
 
} /* InitMaze */
 
 
 
/*========================================================================*\
||                                                                        ||
||   Fonction   : GenerateMaze                                            ||
||                                                                        ||
||   Description: Genere le labyrinthe, en partant de la cellule L,C      ||
||                choisie prealablement au hasard.                        ||
||                                                                        ||
||   Parametres : L : Ligne de la cellule choisie au hasard               ||
||                C : Colonne de la cellule choisie au hasard.            ||
||                                                                        ||
||   Retour     : nil                                                     ||
||                                                                        ||
||   Remarques  : Pour ne pas generer a chaque fois le meme labyrinthe    ||
||                avec les meme parametres, il faut s'assurer             ||
||                d'initialiser le generateur de nombre aleatoires a une  ||
||                valeur differente a chaque fois.  Pour ce faire, il faut||
||                se baser sur la valeur de l'horloge de l'ordinateur, qui||
||                varie tout le temps:                                    ||
||                                                                        ||
||                                                                        ||
||                #include <time.h>                                       ||
||                #include <stdio.h>                                      ||
||                                                                        ||
||                void main(void)                                         ||
||                {                                                       ||
||                  time_t t; int i;                                      ||
||                                                                        ||
||                  srand ((unsigned) time(&t));                          ||
||                                                                        ||
||                  for (i=0; i < 100; i++)                               ||
||                    printf("%d ",rand() % 100);                         ||
||                }                                                       ||
||                                                                        ||
||                                                                        ||
||                Ce bout de code generera 100 nombres aleatoires         ||
||                differents a chaque appel du programme. Si on omet le   ||
||                srand(nombre associe a l'horloge), la meme serie de     ||
||                nombres pseudo-aleatoires sera generee a chaque fois.   ||
||                                                                        ||
||   Auteur     : Karim Aktouf                                            ||
||                                                                        ||
||   Creation   : le 10 aout 1993                                         ||
||                                                                        ||
||   Revision   : le 13 aout 1993                                         ||
||                                                                        ||
\*========================================================================*/
void GenerateMaze(int L, int C)
{
  FCell *FPtr;
  int LL, CC;
 
 /* On marque la cellule choisie au hasard comme etant SPAN        */
 MazePtr[L][C].Type = SPAN;
 
 /* On marque toutes les cellules adjacentes comme etant FRONTIERE */
 MarkAdj(L, C, FRONTIERE);
 
 while (FList)    /* Tant que la liste des cellules frontieres n'est pas vide */
 {
   /* On choisit une cellule frontiere au hasard */
   FPtr = ChooseRandomF();
 
   /* On la marque comme etant SPAN */
   LL = FPtr->L;
   CC = FPtr->C;
   RemoveFromFList(FPtr);
   MazePtr[LL][CC].Type = SPAN;
 
   /* On la connecte a une cellule SPAN adjacente prise au hasard */
   ConnectToSPAN(LL, CC);
 
   /* On marque les cellules adjacentes de type AUCUN a FRONTIERE */
   MarkAdj(LL, CC, FRONTIERE);
 }
 /* On choisit l'entree... */
 MazePtr[1][0].Droite     = OUVERTE;
 
 /* et la sortie.          */
 MazePtr[NbL-1][NbC-1].Droite = OUVERTE;
 
} /* GenerateMaze */
 
 
/*========================================================================*\
||                                                                        ||
||   Fonction   : ChooseRandomF                                           ||
||                                                                        ||
||   Description: Choisit au hasard une cellule frontiere parmis la liste ||
||                de cellules frontieres.                                 ||
||                                                                        ||
||   Parametres : nil                                                     ||
||                                                                        ||
||   Retour     : Pointeur a la cellule choisie.                          ||
||                                                                        ||
||   Remarques  : nil                                                     ||
||                                                                        ||
||   Auteur     : Karim Aktouf                                            ||
||                                                                        ||
||   Creation   : le 10 aout 1993                                         ||
||                                                                        ||
||   Revision   : le 11 aout 1993                                         ||
||                                                                        ||
\*========================================================================*/
 
FCell *ChooseRandomF(void)
{
  int tmp = (rand() % NbF) + 1;
  int i=1;
  FCell *FPtr = FList;
 
  while (i++ != tmp)
    FPtr = FPtr->Next;
 
  return FPtr;
 
} /* ChooseRandomF */
 
 
 
/*========================================================================*\
||                                                                        ||
||   Fonction   : ConnectToSPAN                                           ||
||                                                                        ||
||                                                                        ||
||   Description: Connecte la cellule L,C a une cellule SPAN adjacente,   ||
||                prise au hasard.                                        ||
||                                                                        ||
||   Parametres : L : Ligne de la cellule a connecter                     ||
||                C : Colonne de la cellule a connecter                   ||
||                                                                        ||
||   Retour     : nil                                                     ||
||                                                                        ||
||   Remarques  : nil                                                     ||
||                                                                        ||
||   Auteur     : Karim Aktouf                                            ||
||                                                                        ||
||   Creation   : le 12 aout 1993                                         ||
||                                                                        ||
||   Revision   : le 13 aout 1993                                         ||
||                                                                        ||
\*========================================================================*/
void ConnectToSPAN(int L, int C)
{
  BOOL Span_Adj[4] = {FALSE};
  int NbSpanAdj = 0;
  int tmp, i, j, SpanToConnect;
 
  /* cellule adjacente du haut   */
  if ((L-1 > 0) && (MazePtr[L-1][C].Type == SPAN))
  {
    Span_Adj[0] = TRUE;
    NbSpanAdj++;
  }
 
  /* cellule adjacente de droite */
  if ((C+1 < NbC) && (MazePtr[L][C+1].Type == SPAN))
  {
    Span_Adj[1] = TRUE;
    NbSpanAdj++;
  }
 
  /* cellule adjacente du bas    */
  if ((L+1 < NbL) && (MazePtr[L+1][C].Type == SPAN))
  {
    Span_Adj[2] = TRUE;
    NbSpanAdj++;
  }
 
  /* cellule adjacente de gauche */
  if ((C-1 > 0) && (MazePtr[L][C-1].Type == SPAN))
  {
    Span_Adj[3] = TRUE;
    NbSpanAdj++;
  }
 
  if (NbSpanAdj < 1)     /* Ne devrais jamais arriver!!! */
  {
     printf("\nWow!!!  Pas de cellule SPAN adjacente a Cell(%d, %d)!!!!\n", L, C);
     exit(-1);
  }
 
  if (NbSpanAdj == 1)
  {
    tmp=-1;
    while(Span_Adj[++tmp] == FALSE)
      ;
 
    SpanToConnect = tmp;
  }
  else
  {
    tmp = (rand() % NbSpanAdj) + 1;
 
    i=0;
    for (j=0; j < 4; j++)
    {
      if (Span_Adj[j] == TRUE)
      {
        if (++i == tmp)
        {
          SpanToConnect = j;
          break;
        }
      }
    }
  }
 
  /* Ok, La cellule adjacente numero SpanToConnect est la SPAN a connecter */
  switch(SpanToConnect)
  {
    case 0: MazePtr[L-1][C].Bas    = OUVERTE;
            break;
 
    case 1: MazePtr[L][C].Droite   = OUVERTE;
            break;
 
    case 2: MazePtr[L][C].Bas      = OUVERTE;
            break;
 
    case 3: MazePtr[L][C-1].Droite = OUVERTE;
            break;
  }
 
} /* ConnectToSPAN */
 
 
 
/*========================================================================*\
||                                                                        ||
||   Fonction   : MarkAdj                                                 ||
||                                                                        ||
||   Description: Marque comme etant de type FRONTIERE toutes les cellules||
||                de type AUCUN voisines de la cellule L,C                ||
||                                                                        ||
||   Parametres : L : Ligne de la cellule dont on doit marquer les        ||
||                    cellules adjacentes.                                ||
||                C : Colonne de la cellule dont on doit marquer les      ||
||                    cellules adjacentes.                                ||
||                                                                        ||
||   Retour     : nil                                                     ||
||                                                                        ||
||   Remarques  : nil                                                     ||
||                                                                        ||
||   Auteur     : Karim Aktouf                                            ||
||                                                                        ||
||   Creation   : le 11 aout 1993                                         ||
||                                                                        ||
||   Revision   : le 11 aout 1993                                         ||
||                                                                        ||
\*========================================================================*/
void MarkAdj(int L, int C, TypedeCell T)
{
  FCell *FPtr;
 
  /* Cellule adjacente du haut   */
  if (L-1 > 0)
  {
    if (MazePtr[L-1][C].Type == AUCUN)
    {
      MazePtr[L-1][C].Type = T;
 
      if (!(FPtr = (FCell *) malloc(sizeof(FCell))))
      {
        printf("\nPas assez de memoire pour FPtr\n");
        exit(-1);
      }
      FPtr->L = L-1;
      FPtr->C = C;
      AddToFList(FPtr);
    }
  }
 
  /* Cellule adjacente du bas   */
  if (L+1 < NbL)
  {
    if (MazePtr[L+1][C].Type == AUCUN)
    {
      MazePtr[L+1][C].Type = T;
 
      if (!(FPtr = (FCell *) malloc(sizeof(FCell))))
      {
        printf("\nPas assez de memoire pour FPtr\n");
        exit(-1);
      }
      FPtr->L = L+1;
      FPtr->C = C;
      AddToFList(FPtr);
    }
  }
 
  /* Cellule adjacente de gauche */
  if (C-1 > 0)
  {
    if (MazePtr[L][C-1].Type == AUCUN)
    {
      MazePtr[L][C-1].Type = T;
 
      if (!(FPtr = (FCell *) malloc(sizeof(FCell))))
      {
        printf("\nPas assez de memoire pour FPtr\n");
        exit(-1);
      }
      FPtr->L = L;
      FPtr->C = C-1;
      AddToFList(FPtr);
    }
  }
 
  /* Cellule adjacente de droite */
  if (C+1 < NbC)
  {
    if (MazePtr[L][C+1].Type == AUCUN)
    {
      MazePtr[L][C+1].Type = T;
 
      if (!(FPtr = (FCell *) malloc(sizeof(FCell))))
      {
        printf("\nPas assez de memoire pour FPtr\n");
        exit(-1);
      }
      FPtr->L = L;
      FPtr->C = C+1;
      AddToFList(FPtr);
    }
  }
} /* MarkAdj */
 
 
 
/*========================================================================*\
||                                                                        ||
||   Fonction   : AddToFList                                              ||
||                                                                        ||
||   Description: Ajoute l'element pointe par FPtr dans la liste          ||
||                circulaire a double liens des cellules de type FRONTIERE||
||                                                                        ||
||   Parametres : FPtr : Pointeur a l'element a ajouter.                  ||
||                                                                        ||
||   Retour     : nil                                                     ||
||                                                                        ||
||   Remarques  : nil                                                     ||
||                                                                        ||
||   Auteur     : Karim Aktouf                                            ||
||                                                                        ||
||   Creation   : le 10 aout 1993                                         ||
||                                                                        ||
||   Revision   : le 10 aout 1993                                         ||
||                                                                        ||
\*========================================================================*/
void AddToFList(FCell *FPtr)
{
  if (!FList)
  {
    FList       = FPtr;
    FList->Next = FList;
    FList->Prev = FList;
  }
  else
  {
    FList->Prev->Next = FPtr;
    FPtr->Next        = FList;
    FPtr->Prev        = FList->Prev;
    FList->Prev       = FPtr;
  }
 
  NbF++;
 
} /* AddToFList */
 
 
 
/*========================================================================*\
||                                                                        ||
||   Fonction   : RemoveFromFList                                         ||
||                                                                        ||
||   Description: retire de la liste circulaire l'element pointe par FPtr.||
||                                                                        ||
||   Parametres : FPtr : Pointeur a l'element a retirer.                  ||
||                                                                        ||
||   Retour     : nil                                                     ||
||                                                                        ||
||   Remarques  : nil                                                     ||
||                                                                        ||
||   Auteur     : Karim Aktouf                                            ||
||                                                                        ||
||   Creation   : le 10 aout 1993                                         ||
||                                                                        ||
||   Revision   : le 10 aout 1993                                         ||
||                                                                        ||
\*========================================================================*/
void RemoveFromFList(FCell *FPtr)
{
  if (FList->Next == FList)
  {
    free(FList);
    FList = NULL;
  }
  else
  {
    if (FList == FPtr)
       FList = FPtr->Next;
 
    FPtr->Prev->Next = FPtr->Next;
    FPtr->Next->Prev = FPtr->Prev;
 
    free(FPtr);
  }
 
  NbF--;
 
} /* RemoveFromFList */
 
 
 
/*========================================================================*\
||                                                                        ||
||   Fonction   : PrintMaze                                               ||
||                                                                        ||
||   Description: Imprime le labyrinthe en mode texte. Chaque cellule     ||
||                est representee par:                                    ||
||                                                                        ||
||       Case toujours ouverte->    HV <- Case droite, OUVERTE, FERMEE    ||
||                                                                        ||
||       Case Bas, OUVERTE,   -> VH HV <- Case toujours fermee            ||
||                 FERMEE                                                 ||
||                                                                        ||
||   Parametres : nil                                                     ||
||                                                                        ||
||   Retour     : nil                                                     ||
||                                                                        ||
||   Remarques  : nil                                                     ||
||                                                                        ||
||   Auteur     : Karim Aktouf                                            ||
||                                                                        ||
||   Creation   : le 12 aout 1993                                         ||
||                                                                        ||
||   Revision   : le 12 aout 1993                                         ||
||                                                                        ||
\*========================================================================*/
void PrintMaze(char H, char V)
{
  int i, j;
 
  printf("\n\nMaze %dx%d:", NbL, NbC);
  for (i=0; i < NbL; i++)
  {
    printf("\n");
    for (j=0; j < NbC; j++)
      if (MazePtr[i][j].Droite == OUVERTE)
        printf("    ");
      else
	printf("  %c%c", H, V);
 
    printf("\n");
    for (j=0; j < NbC; j++)
      if (MazePtr[i][j].Bas == OUVERTE)
        printf("  %c%c", H, V);
      else
	printf("%c%c%c%c", V, H, H, V);
  }
  printf("\n");
 
 
} /* PrintMaze */
 

Générateur de Labyrinthes

Un peu de théorie Here's some info I wrote up once for a C class assignment. I can send you C code if you want, but your request asked for the algorithm...

…Rickperry@vill.edu == r.perry@ieee.org

Dr. Rick Perry, ECE Department, Villanova University, Villanova, PA 19085

215-645-4969, fax: 215-645-4436, hm: 215-259-8734

Creating a maze

Here is an example of a maze of size 5 by 8:

	        0   1   2   3   4   5   6   7
	     XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
     0 XX  XX              XX          XX
	     XX  XX  XXXXXX  XXXXXX  XXXXXX  XX
     1 XX  XX  XX                  XX
	     XX  XXXXXXXXXXXXXX  XXXXXXXXXX  XX
     2 XX  XX              XX  XX
	     XX  XXXXXX  XXXXXX  XX  XX  XX  XX
     3 XX                  XX  XX  XX  XX
	     XX  XX  XXXXXX  XXXXXX  XX  XXXXXX
     4 XX  XX  XX          XX  XX      XX
       XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 

Highlight of the cells:

           0    1    2    3    4    5    6    7
       XX|XXXX|XXXX|XXXX|XXXX|XXXX|XXXX|XXXX|XXXX|
       --|----|----|----|----|----|----|----|----|
     0 XX|  XX|    |    |    |  XX|    |    |  XX|
       XX|  XX|  XX|XXXX|  XX|XXXX|  XX|XXXX|  XX|
       --|----|----|----|----|----|----|----|----|
     1 XX|  XX|  XX|    |    |    |    |  XX|    |
       XX|  XX|XXXX|XXXX|XXXX|  XX|XXXX|XXXX|  XX|
       --|----|----|----|----|----|----|----|----|
     2   |    |  XX|  XX|    |    |    |  XX|  XX|
       XX|  XX|XXXX|  XX|XXXX|  XX|  XX|  XX|  XX|
       --|----|----|----|----|----|----|----|----|
     3 XX|    |    |    |    |  XX|  XX|  XX|  XX|
       XX|  XX|  XX|XXXX|  XX|XXXX|  XX|  XX|XXXX|
       --|----|----|----|----|----|----|----|----|
     4 XX|  XX|  XX|    |    |  XX|  XX|    |  XX|
       XX|XXXX|XXXX|XXXX|XXXX|XXXX|XXXX|XXXX|XXXX|
       --|----|----|----|----|----|----|----|----|
 

The maze is a two-dimensional array of cells. In this display, each cell
is two-characters high and 4 characters wide. There are two blanks in
the top left corner of each cell, and two X’s in the bottom right corner
of each cell. Each cell has a right wall and a bottom wall which may or
may not be open. For example, cell (0,0) has its right wall closed and
its bottom wall open, cell (0,1) has both walls open, cell (1,1) has both
walls closed.

In addition to the cells of the maze, a top wall of X’s and a left wall of XX’s
(with one opening for the maze entrance) comprise the display of the maze.
The bottom wall of the maze is formed by the last row of cells, none of which
have their bottom wall open. The right wall of the maze is formed by the last
column of cells, one of which has its right wall open for the maze exit.

Note that there is only one path between any two cells of the maze. Any cell
can be reached from another cell by a unique path. Such a set of paths between
cells is called a spanning tree. The creation of a maze starts with the all
the cell walls closed and systematically opens cell walls until the complete
spanning tree is formed. The maze entrance and exit are then chosen at
random or fixed locations on opposite sides of the maze.

During the formation of the maze, there will be three types of cells in the
array:

-  those that are already in the spanning tree.
 
-  those that are not in the spanning tree but are immediately
   adjacent to some cell in the spanning tree.  These cells are
   called Frontier Cells.
 
-  all the other cells, which are neither in the spanning tree
   nor the frontier.
 

A bit-field structure, together with some symbolic constants for the
allowed values of the fields, is appropriate to represent a maze cell,
for example:

#define NEITHER  0	/* kinds of cells */
#define SPANTREE 1
#define FRONTIER 2
 
#define CLOSED 0	/* walls */
#define OPEN   1
 
typedef struct {
	unsigned int kind : 2;	/* NEITHER, SPANTREE, or FRONTIER */
	unsigned int down : 1;	/* CLOSED or OPEN */
	unsigned int right: 1;	/* CLOSED or OPEN */
} Cell;
 

If cell is a two-dimensional array of these Cell’s, then typical statements
using cell would be:

cell[i][j].kind = FRONTIER;
 
cell[i][j].down = OPEN;
 
if( cell[i][j].kind == NEITHER) ...
 

The algorithm to create a maze is:

1.  Randomly choose any cell of the array and mark it as a spanning
    tree cell.  The four cells immediately adjacent to it (fewer if
    it is on an edge or in a corner) are then marked as frontier cells.
 
Repeat Steps 2 and 3 until there are no frontier cells left:
 
2.  Randomly choose a frontier cell and connect it to one cell of the
    current spanning tree by opening one wall.  If it is adjacent to
    more than one cell of the spanning tree (it could be adjacent to
    as many as four), randomly choose one of them to connect it to
    and mark the appropriate wall as open.  Note: to connect cell[i][j]
    to the cell above it means  cell[i-1][j].down = OPEN;
 
3.  Check the cells adjacent to the cell just added to the spanning
    tree.  Any such cells that are neither part of the spanning tree
    nor the frontier must now be marked as frontier cells.
 

To be able to easily and efficiently choose a random frontier cell in Step 2,
the row and column indices of the frontier cells must be kept in a circularly
linked list. Such a data structure would be declared like:

typedef struct element {
	int row, col;
	struct element *next;
} Node;
 

Example illustrating maze creation

In this example, ++ is used instead of XX for the walls so that the F and S
characters, indicating Frontier and Spanning tree cells, stand out clearly.

     0   1   2   3
   ++++++++++++++++++
 0 ++  ++  ++F ++  ++	Cell (1,2) chosen as the initial spanning tree.
   ++++++++++++++++++
 1 ++  ++F ++S ++F ++	Adjacent cells (0,2), (1,1), (1,3), and (2,2)
   ++++++++++++++++++
 2 ++  ++  ++F ++  ++	added to frontier list.
   ++++++++++++++++++
 3 ++  ++  ++  ++  ++
   ++++++++++++++++++
 4 ++  ++  ++  ++  ++
   ++++++++++++++++++
 
     0   1   2   3
   ++++++++++++++++++
 0 ++  ++  ++F ++  ++
   ++++++++++++++++++
 1 ++  ++F ++S ++F ++
   ++++++++++  ++++++
 2 ++  ++F ++S ++F ++	Frontier cell (2,2) added to the spanning tree.
   ++++++++++++++++++
 3 ++  ++  ++F ++  ++	Adjacent cells (2,1), (2,3) and (3,2)
   ++++++++++++++++++
 4 ++  ++  ++  ++  ++	added to the frontier list.
   ++++++++++++++++++
 
     0   1   2   3
   ++++++++++++++++++
 0 ++  ++  ++F ++  ++
   ++++++++++++++++++
 1 ++  ++F ++S ++F ++
   ++++++++++  ++++++
 2 ++F ++S   S ++F ++	Frontier cell (1,2) added to the spanning tree.
   ++++++++++++++++++
 3 ++  ++F ++F ++  ++	Adjacent cells (0,2) and (1,3) added to the
   ++++++++++++++++++
 4 ++  ++  ++  ++  ++	frontier list.
   ++++++++++++++++++
 

L'Algorithme de Backtracking Récursif

Principe Fondamental L'algorithme de backtracking récursif est une méthode de génération de labyrinthes basée sur la recherche en profondeur (Depth-First Search - DFS). Il crée un labyrinthe en "creusant" des passages à travers une grille initialement remplie de murs.

Fonctionnement Étape par Étape

  1. Initialisation
    • On commence avec une grille où toutes les cellules ont leurs quatre murs (Nord, Sud, Est, Ouest)
    • Toutes les cellules sont marquées comme “non visitées”
    • On choisit une cellule de départ (généralement (0,0))
  2. Exploration
    • Marquer la cellule courante comme “visitée”
    • Obtenir la liste des cellules voisines non visitées
  3. Décision
    • Si des voisins non visités existent:
      • Choisir un voisin aléatoire
      • Empiler la cellule courante (pour pouvoir y revenir)
      • Supprimer le mur entre la cellule courante et le voisin choisi
      • Faire du voisin la nouvelle cellule courante
      • Répéter depuis l’étape 2
    • Si aucun voisin non visité n’existe:
      • Dépiler une cellule (backtracking/retour en arrière)
      • Faire de cette cellule la cellule courante
      • Répéter depuis l’étape 2
  4. Terminaison
    • L’algorithme se termine quand la pile est vide et qu’il n’y a plus de cellule à explorer

Visualisation de l’Algorithme

Étape 1: Départ en (0,0)
┌─┬─┬─┐
│S│ │ │    S = Start (cellule de départ)
├─┼─┼─┤
│ │ │ │
├─┼─┼─┤
│ │ │ │
└─┴─┴─┘
 
Étape 2: Exploration vers l'Est
┌─┬─┬─┐
│S X│ │    X = cellule visitée
├─┼─┼─┤
│ │ │ │
├─┼─┼─┤
│ │ │ │
└─┴─┴─┘
 
Étape 3: Backtracking quand bloqué
┌─┬─┬─┐
│S X X│    On revient en arrière
├─┼ ┼─┤    puis on explore Sud
│ │X│ │
├─┼─┼─┤
│ │ │ │
└─┴─┴─┘
 
... et ainsi de suite jusqu'à ce que
toutes les cellules soient visitées.
 

Propriétés Mathématiques

  • Complexité temporelle: O(n) où n est le nombre de cellules
  • Complexité spatiale: O(n) pour la pile de backtracking
  • Garanties:
    • Chaque cellule est visitée exactement une fois
    • Le labyrinthe est connexe (tous les points sont accessibles)
    • Le labyrinthe est “parfait” (sans boucles, un seul chemin entre deux points)
    • La génération est uniforme (tous les labyrinthes possibles ont la même probabilité)

Avantages et Inconvénients

Avantages:

  • Simple à mettre en oeuvre
  • Génère des labyrinthes avec de longs couloirs sinueux
  • Utilisation efficace de la mémoire
  • Visuellement intéressant (structure organique)

Inconvénients:

  • Peut créer des labyrinthes avec un biais directionnel
  • Les chemins ont tendance à être longs et tortueux
  • Moins de contrôle sur la difficulté du labyrinthe

Histoire de l'Algorithme

Origines et Développement

L’algorithme de backtracking pour la génération de labyrinthes trouve ses racines dans les années 1960-1970, période dorée de l’exploration des algorithmes de graphes.

Contexte Historique

Années 1960 - Les Prémices

  • L’algorithme de recherche en profondeur (DFS), base du backtracking, est formalisé par les pionniers de l’informatique
  • Les premiers ordinateurs permettent d’explorer des algorithmes de génération procédurale
  • Les labyrinthes deviennent un terrain de jeu pour tester les algorithmes de graphes

Années 1970 - Popularisation

  • Les ordinateurs personnels émergent, rendant la programmation accessible
  • Les magazines d’informatique publient des algorithmes de génération de labyrinthes
  • Les jeux vidéo utilisent des labyrinthes procéduraux (début des roguelikes)

Années 1980-1990 - Raffinement

  • Étude systématique des différentes méthodes de génération
  • Comparaison des propriétés visuelles et mathématiques
  • Le recursive backtracking devient l’algorithme de référence pour les labyrinthes “parfaits”

Pourquoi le Backtracking Récursif?

L’algorithme s’est imposé pour plusieurs raisons:

  1. Élégance conceptuelle - L’idée de “creuser” des tunnels en explorant puis en revenant en arrière est intuitive
  2. Simplicité d’implémentation - Quelques dizaines de lignes suffisent
  3. Qualité esthétique - Produit des labyrinthes avec de longs passages sinueux, visuellement satisfaisants
  4. Performance - Complexité linéaire, très rapide même sur de grandes grilles

Variantes et Évolution

Au fil du temps, d’autres algorithmes ont été développés:

  • Algorithme de Prim - Croissance aléatoire
  • Algorithme de Kruskal - Union-find sur les arêtes
  • Division récursive - Diviser et conquérir
  • Algorithme d’Eller - Génération ligne par ligne

Mais le backtracking récursif reste le plus populaire pour sa simplicité et ses résultats esthétiques.

Architecture du Code

Structure Globale

MazeGenerator (Classe principale)

├── __init__()              # Initialisation de la grille
├── generate_maze()         # Algorithme de backtracking
├── create_entrance_exit()  # Création des accès
└── create_maze_geometry()  # Génération 3D dans Blender

    ├── _create_wall()      # Création d'un mur individuel
    ├── _create_floor()     # Création du sol
    ├── _create_markers()   # Marqueurs entrée/sortie
    └── _get_marker_position() # Calcul de position
 

Diagramme de Flux

┌─────────────────────────┐
│  Initialisation         │
│  - Créer grille         │
│  - Tous murs présents   │
└───────────┬─────────────┘


┌─────────────────────────┐
│  Génération Labyrinthe  │
│  - Backtracking DFS     │
│  - Suppression de murs  │
└───────────┬─────────────┘


┌─────────────────────────┐
│  Création Entrée/Sortie │
│  - Sélection aléatoire  │
│  - Sur périmètre        │
└───────────┬─────────────┘


┌─────────────────────────┐
│  Génération Géométrie   │
│  - Création murs 3D     │
│  - Sol et marqueurs     │
└─────────────────────────┘
 

Explication Détaillée du Code

1. Initialisation (__init__)

def __init__(self, width=10, height=10, wall_thickness=0.1,
             wall_height=2.0, cell_size=2.0):
    self.width = width
    self.height = height
    self.wall_thickness = wall_thickness
    self.wall_height = wall_height
    self.cell_size = cell_size
 
    # Grille: chaque cellule a 4 murs possibles
    self.grid = [[{'N': True, 'S': True, 'E': True, 'W': True,
                   'visited': False}
                 for _ in range(width)] for _ in range(height)]
 
    self.entrance = None
    self.exit = None
 

Explication:
- La grille est une matrice 2D de dictionnaires
- Chaque cellule stocke l’état de ses 4 murs (True = présent)
- ‘N’, ‘S’, ‘E’, ‘W’ correspondent aux directions cardinales
- visited permet de suivre la progression de l’algorithme

Structure de données:

grid[y][x] = {
    'N': True,      # Mur Nord
    'S': True,      # Mur Sud
    'E': True,      # Mur Est
    'W': True,      # Mur Ouest
    'visited': False # État de visite
}
 

2. Génération du Labyrinthe (generate_maze)

def generate_maze(self):
    stack = []
    current = (0, 0)
    self.grid[current[1]][current[0]]['visited'] = True
 
    while True:
        neighbors = self._get_unvisited_neighbors(current)
 
        if neighbors:
            # Avancer: choisir un voisin
            next_cell = random.choice(neighbors)
            stack.append(current)
            self._remove_wall(current, next_cell)
            self.grid[next_cell[1]][next_cell[0]]['visited'] = True
            current = next_cell
        elif stack:
            # Reculer: backtracking
            current = stack.pop()
        else:
            # Terminé: tous les chemins explorés
            break
 

Analyse détaillée:

  1. Pile (Stack):
    • Stocke le chemin parcouru
    • Permet de revenir en arrière (backtracking)
    • Structure LIFO (Last In, First Out)
  2. Boucle principale:
    • Continue tant qu’il reste des cellules dans la pile
    • Gère deux cas: exploration et backtracking
  3. Choix aléatoire:
    • random.choice(neighbors) assure l’uniformité
    • Chaque labyrinthe généré est unique

Invariants:

  • Une cellule visitée l’est définitivement
  • La pile contient toujours un chemin valide vers l’origine
  • À la fin, toutes les cellules sont visitées

3. Recherche de Voisins (_get_unvisited_neighbors)

def _get_unvisited_neighbors(self, cell):
    x, y = cell
    neighbors = []
 
    # Nord (y-1)
    if y > 0 and not self.grid[y-1][x]['visited']:
        neighbors.append((x, y-1))
 
    # Sud (y+1)
    if y < self.height - 1 and not self.grid[y+1][x]['visited']:
        neighbors.append((x, y+1))
 
    # Est (x+1)
    if x < self.width - 1 and not self.grid[y][x+1]['visited']:
        neighbors.append((x+1, y))
 
    # Ouest (x-1)
    if x > 0 and not self.grid[y][x-1]['visited']:
        neighbors.append((x-1, y))
 
    return neighbors
 

Points importants:

  • Vérification des limites de la grille (0 ≤ x < width, 0 ≤ y < height)
  • Seules les cellules non visitées sont retournées
  • L’ordre de vérification n’affecte pas l’uniformité (choix aléatoire après)

Système de coordonnées:

     x →
y  ┌─────┬─────┬─────┐
↓  │(0,0)│(1,0)│(2,0)│
   ├─────┼─────┼─────┤
   │(0,1)│(1,1)│(2,1)│
   ├─────┼─────┼─────┤
   │(0,2)│(1,2)│(2,2)│
   └─────┴─────┴─────┘
 

4. Suppression de Murs (_remove_wall)

def _remove_wall(self, current, next_cell):
    x1, y1 = current
    x2, y2 = next_cell
 
    if x2 == x1 + 1:  # Mouvement Est
        self.grid[y1][x1]['E'] = False
        self.grid[y2][x2]['W'] = False
    elif x2 == x1 - 1:  # Mouvement Ouest
        self.grid[y1][x1]['W'] = False
        self.grid[y2][x2]['E'] = False
    elif y2 == y1 + 1:  # Mouvement Sud
        self.grid[y1][x1]['S'] = False
        self.grid[y2][x2]['N'] = False
    elif y2 == y1 - 1:  # Mouvement Nord
        self.grid[y1][x1]['N'] = False
        self.grid[y2][x2]['S'] = False
 

Principe de symétrie:

  • Supprimer un mur affecte deux cellules
  • Le mur Est de A est le mur Ouest de B
  • Maintient la cohérence de la structure

Visualisation:

Avant:                Après:
┌───┬───┐            ┌───┬───┐
│ A │ B │    →       │ A   B │
└───┴───┘            └───┴───┘
     ↑                    ↑
  Mur entre A et B    Mur supprimé
 

5. Création Entrée/Sortie (create_entrance_exit)

def create_entrance_exit(self):
    perimeter_walls = []
 
    # Mur Nord (haut)
    for x in range(self.width):
        perimeter_walls.append((x, 0, 'N'))
 
    # Mur Sud (bas)
    for x in range(self.width):
        perimeter_walls.append((x, self.height - 1, 'S'))
 
    # Mur Ouest (gauche)
    for y in range(self.height):
        perimeter_walls.append((0, y, 'W'))
 
    # Mur Est (droite)
    for y in range(self.height):
        perimeter_walls.append((self.width - 1, y, 'E'))
 
    # Sélection aléatoire
    random.shuffle(perimeter_walls)
    entrance_wall = perimeter_walls[0]
    exit_wall = perimeter_walls[1]
 
    # Suppression des murs
    x, y, direction = entrance_wall
    self.grid[y][x][direction] = False
    self.entrance = entrance_wall
 
    x, y, direction = exit_wall
    self.grid[y][x][direction] = False
    self.exit = exit_wall
 

Stratégie:

  1. Collecter tous les murs du périmètre
  2. Mélanger aléatoirement la liste
  3. Prendre les deux premiers (garantit qu’ils sont différents)

Nombre de positions possibles:

  • Mur Nord: width positions
  • Mur Sud: width positions
  • Mur Est: height positions
  • Mur Ouest: height positions
  • Total: 2 × (width + height) positions

6. Génération de la Géométrie 3D

a) Création des Murs (create_maze_geometry)

for y in range(self.height):
    for x in range(self.width):
        cell = self.grid[y][x]
        pos_x = x * self.cell_size
        pos_y = y * self.cell_size
 
        # Mur Nord
        if cell['N']:
            self._create_wall(pos_x, pos_y,
                            self.cell_size, self.wall_thickness,
                            maze_collection, mat)
 
        # Mur Ouest
        if cell['W']:
            self._create_wall(pos_x, pos_y,
                            self.wall_thickness, self.cell_size,
                            maze_collection, mat)
 

Optimisation:

  • Seuls les murs intérieurs sont créés lors du parcours
  • Les murs Sud et Est sont créés uniquement pour la dernière ligne/colonne
  • Évite la duplication de géométrie

Calcul de position:

Cellule (x, y) → Position 3D (pos_x, pos_y)
pos_x = x × cell_size
pos_y = y × cell_size
 
Exemple: cellule (2, 1) avec cell_size=2.0
→ Position (4.0, 2.0) dans l'espace Blender
 

b) Création d’un Mur (_create_wall)

def _create_wall(self, x, y, size_x, size_y, collection, material):
    # Créer un cube unitaire
    bpy.ops.mesh.primitive_cube_add(
        size=1,
        location=(x + size_x/2, y + size_y/2, self.wall_height/2)
    )
    wall = bpy.context.active_object
 
    # Mise à l'échelle pour la taille désirée
    wall.scale = (size_x, size_y, self.wall_height)
 
    # Application du matériau
    wall.data.materials.append(material)
 
    # Déplacement vers la collection du labyrinthe
    for coll in wall.users_collection:
        coll.objects.unlink(wall)
    collection.objects.link(wall)
 

Processus Blender:

  1. Création d’un cube avec primitive_cube_add
  2. Positionnement au centre du mur
  3. Mise à l’échelle pour obtenir les bonnes dimensions
  4. Application du matériau bleu
  5. Organisation dans la collection “Maze”

Position du centre:

  • Pour un mur horizontal: (x + size_x/2, y + wall_thickness/2, height/2)
  • Pour un mur vertical: (x + wall_thickness/2, y + size_y/2, height/2)

c) Création des Marqueurs (_create_markers)

def _create_markers(self, collection):
    # Marqueur d'entrée (vert)
    entrance_pos = self._get_marker_position(self.entrance)
    bpy.ops.mesh.primitive_cylinder_add(
        radius=0.5,
        depth=0.3,
        location=(entrance_pos[0], entrance_pos[1], 0.15)
    )
    entrance_marker = bpy.context.active_object
    entrance_marker.name = "Entrance_Marker"
 
    # Matériau vert avec émission
    mat_entrance = bpy.data.materials.new(name="EntranceMaterial")
    mat_entrance.use_nodes = True
    bsdf = mat_entrance.node_tree.nodes["Principled BSDF"]
    bsdf.inputs["Base Color"].default_value = (0.0, 1.0, 0.0, 1.0)
    bsdf.inputs["Emission Color"].default_value = (0.0, 1.0, 0.0, 1.0)
    bsdf.inputs["Emission Strength"].default_value = 2.0
 

Matériaux avec émission:

  • Base Color: Couleur de base de l’objet
  • Emission Color: Couleur de la lumière émise
  • Emission Strength: Intensité lumineuse (0 = pas d’émission)

Effet visuel:

  • Les marqueurs brillent légèrement dans le rendu
  • Facilement repérables même dans des labyrinthes complexes
  • Vert = début (go!), Rouge = fin (stop!)

d) Calcul de Position des Marqueurs

def _get_marker_position(self, wall_info):
    x, y, direction = wall_info
    pos_x = x * self.cell_size + self.cell_size / 2
    pos_y = y * self.cell_size + self.cell_size / 2
 
    # Ajustement selon la direction
    if direction == 'N':
        pos_y = y * self.cell_size
    elif direction == 'S':
        pos_y = (y + 1) * self.cell_size
    elif direction == 'W':
        pos_x = x * self.cell_size
    elif direction == 'E':
        pos_x = (x + 1) * self.cell_size
 
    return (pos_x, pos_y)
 

Logique de positionnement:

  • Par défaut: centre de la cellule
  • Ajustement: déplacer vers le mur concerné
  • Résultat: marqueur exactement sur l’ouverture

Exemple:

Cellule (2, 1), direction 'E', cell_size = 2.0
→ Centre: (5.0, 3.0)
→ Ajustement Est: pos_x = 3 × 2.0 = 6.0
→ Position finale: (6.0, 3.0)
 

Utilisation et Personnalisation

Paramètres de Base

maze = MazeGenerator(
    width=15,           # Largeur (nombre de cellules en X)
    height=15,          # Hauteur (nombre de cellules en Y)
    wall_thickness=0.2, # Épaisseur des murs (en unités Blender)
    wall_height=3.0,    # Hauteur des murs
    cell_size=2.0       # Taille d'une cellule
)
 

Exemples de Configuration

Labyrinthe Compact

# Petit labyrinthe, murs fins, basse hauteur
maze = MazeGenerator(width=8, height=8, wall_thickness=0.1,
                     wall_height=2.0, cell_size=1.5)
 
  • Idéal pour: tests rapides, visualisation simple
  • Temps de génération: < 1 seconde
  • Dimensions finales: 12 × 12 unités Blender

Labyrinthe Épique

# Grand labyrinthe, murs épais, haute hauteur
maze = MazeGenerator(width=50, height=50, wall_thickness=0.3,
                     wall_height=5.0, cell_size=3.0)
 
  • Idéal pour: jeux vidéo, explorations complexes
  • Temps de génération: quelques secondes
  • Dimensions finales: 150 × 150 unités Blender

Labyrinthe Artistique

# Proportions asymétriques
maze = MazeGenerator(width=30, height=15, wall_thickness=0.15,
                     wall_height=4.0, cell_size=2.5)
 
  • Idéal pour: designs uniques, compositions visuelles
  • Forme rectangulaire plutôt que carrée

Modifications Avancées

1. Changer les Couleurs

Murs:

# Dans create_maze_geometry(), ligne créant le matériau
mat.node_tree.nodes["Principled BSDF"].inputs[0].default_value = (R, G, B, 1.0)
 
# Exemples:
# Murs rouges: (1.0, 0.0, 0.0, 1.0)
# Murs dorés: (1.0, 0.84, 0.0, 1.0)
# Murs noirs: (0.0, 0.0, 0.0, 1.0)
 

Marqueurs:

# Entrée en bleu au lieu de vert
bsdf.inputs["Base Color"].default_value = (0.0, 0.0, 1.0, 1.0)
bsdf.inputs["Emission Color"].default_value = (0.0, 0.0, 1.0, 1.0)
 

2. Ajouter un Plafond

def _create_ceiling(self, collection):
    """Créer un plafond pour le labyrinthe."""
    floor_size_x = self.width * self.cell_size
    floor_size_y = self.height * self.cell_size
 
    bpy.ops.mesh.primitive_plane_add(
        size=1,
        location=(floor_size_x/2, floor_size_y/2, self.wall_height)
    )
    ceiling = bpy.context.active_object
    ceiling.scale = (floor_size_x, floor_size_y, 1)
    ceiling.name = "MazeCeiling"
    # ... (appliquer matériau et lier à la collection)
 

Puis dans create_maze_geometry():

self._create_floor(maze_collection)
self._create_ceiling(maze_collection)  # Ajouter cette ligne
 

3. Formes de Marqueurs Différentes

Remplacer les cylindres par d’autres formes:

# Sphère pour l'entrée
bpy.ops.mesh.primitive_uv_sphere_add(
    radius=0.5,
    location=(entrance_pos[0], entrance_pos[1], 0.5)
)
 
# Cône pour la sortie
bpy.ops.mesh.primitive_cone_add(
    radius1=0.5,
    depth=1.0,
    location=(exit_pos[0], exit_pos[1], 0.5)
)
 

4. Ajouter de l’Éclairage

def _create_lighting(self):
    """Ajouter une lumière au-dessus du labyrinthe."""
    bpy.ops.object.light_add(
        type='SUN',
        location=(self.width * self.cell_size / 2,
                 self.height * self.cell_size / 2,
                 self.wall_height + 10)
    )
    light = bpy.context.active_object
    light.data.energy = 5.0
 

Extensions Possibles

Algorithmes Alternatifs

  1. Algorithme de Prim (Croissance)
def generate_maze_prim(self):
    # Commencer avec une cellule
    # Ajouter ses murs à une liste
    # Répéter:
    #   - Choisir un mur aléatoire
    #   - Si il connecte visité/non-visité: le supprimer
 
  1. Division Récursive
def generate_maze_recursive_division(self):
    # Diviser l'espace avec un mur
    # Créer une ouverture dans le mur
    # Répéter récursivement sur les deux sous-espaces
 

Fonctionnalités Additionnelles

  1. Génération de Solution
def find_solution(self):
    """Trouver le chemin de l'entrée à la sortie (BFS)."""
    # Implémentation du breadth-first search
    # Retourne une liste de cellules formant le chemin
 
  1. Niveaux de Difficulté
def set_difficulty(self, level):
    """Modifier la difficulté en ajoutant/supprimant des murs."""
    if level == "easy":
        # Supprimer 10% des murs restants
    elif level == "hard":
        # Garder tous les murs (labyrinthe parfait)
 
  1. Export vers d’Autres Formats
def export_to_json(self):
    """Exporter le labyrinthe en JSON."""
    return json.dumps({
        'width': self.width,
        'height': self.height,
        'grid': self.grid,
        'entrance': self.entrance,
        'exit': self.exit
    })
 

Conseils d’Optimisation

Performance pour Grands Labyrinthes

Pour des labyrinthes > 100×100 cellules:

  1. Utiliser des instances pour les murs:
# Créer un mur "template"
template_wall = bpy.data.objects["WallTemplate"]
 
# Créer des instances au lieu de nouveaux objets
instance = template_wall.copy()
instance.data = template_wall.data  # Partage la géométrie
instance.location = (x, y, z)
 
  1. Fusion des murs adjacents:
# Au lieu de créer un mur par segment,
# fusionner les murs alignés en un seul mesh
 
  1. LOD (Level of Detail):
# Pour la visualisation à distance,
# utiliser des murs low-poly
 

Intégration dans un Projet

Utilisation comme Module

# maze_generator.py (votre fichier)
from maze_generator import MazeGenerator
 
# Dans votre script principal
maze = MazeGenerator(20, 20)
maze.generate_maze()
maze.create_entrance_exit()
maze.create_maze_geometry("MyMaze")
 
# Accéder aux données
entrance_cell = maze.entrance
print(f"Entrée en position: {entrance_cell}")
 

Génération Procédurale dans un Jeu

# Générer un nouveau niveau à chaque partie
import time
 
seed = int(time.time())
random.seed(seed)
 
maze = MazeGenerator(25, 25)
maze.generate_maze()
# ... utiliser le labyrinthe dans votre jeu
 

Ressources Supplémentaires

Lectures Recommandées

  1. Algorithmes de Labyrinthes:
    • “Mazes for Programmers” par Jamis Buck
    • “Think Labyrinth!” par Walter D. Pullen
  2. Backtracking et Graphes:
    • “Introduction to Algorithms” par Cormen et al. (CLRS)
    • “The Algorithm Design Manual” par Steven Skiena
  3. Code Golf et Optimisation:
    • Les travaux de John Tromp sur la complexité de Kolmogorov
    • Code Golf Stack Exchange (communauté)

Communautés

  • r/proceduralgeneration - Reddit sur la génération procédurale
  • Blender Artists Forum - Discussion sur Python et Blender
  • Stack Overflow - Questions techniques

Outils Connexes

  • MazeSolver - Visualiseur d’algorithmes de recherche de chemins
  • Procedural Toolkit for Unity - Générateurs de labyrinthes pour Unity
  • Processing - Framework pour art génératif

Le code pour Blender Copiez/coller et exécutez dans un script Blender:

"""
Blender Maze Generator
A Python script to generate 3D mazes in Blender using recursive backtracking algorithm.
"""
 
import bpy
import random
 
 
class MazeGenerator:
    def __init__(self, width=10, height=10, wall_thickness=0.1, wall_height=2.0, cell_size=2.0):
        """
        Initialize the maze generator.
        
        Args:
            width: Number of cells in X direction
            height: Number of cells in Y direction
            wall_thickness: Thickness of walls
            wall_height: Height of walls
            cell_size: Size of each cell
        """
        self.width = width
        self.height = height
        self.wall_thickness = wall_thickness
        self.wall_height = wall_height
        self.cell_size = cell_size
        
        # Initialize maze grid (True = wall, False = path)
        self.grid = [[{'N': True, 'S': True, 'E': True, 'W': True, 'visited': False} 
                     for _ in range(width)] for _ in range(height)]
        
        # Store entrance and exit positions
        self.entrance = None
        self.exit = None
    
    def generate_maze(self):
        """Generate maze using recursive backtracking algorithm."""
        stack = []
        current = (0, 0)
        self.grid[current[1]][current[0]]['visited'] = True
        
        while True:
            neighbors = self._get_unvisited_neighbors(current)
            
            if neighbors:
                # Choose random neighbor
                next_cell = random.choice(neighbors)
                stack.append(current)
                
                # Remove wall between current and next cell
                self._remove_wall(current, next_cell)
                
                # Mark next cell as visited and move to it
                self.grid[next_cell[1]][next_cell[0]]['visited'] = True
                current = next_cell
            elif stack:
                # Backtrack
                current = stack.pop()
            else:
                # Maze complete
                break
    
    def _get_unvisited_neighbors(self, cell):
        """Get list of unvisited neighboring cells."""
        x, y = cell
        neighbors = []
        
        # Check North
        if y > 0 and not self.grid[y-1][x]['visited']:
            neighbors.append((x, y-1))
        # Check South
        if y < self.height - 1 and not self.grid[y+1][x]['visited']:
            neighbors.append((x, y+1))
        # Check East
        if x < self.width - 1 and not self.grid[y][x+1]['visited']:
            neighbors.append((x+1, y))
        # Check West
        if x > 0 and not self.grid[y][x-1]['visited']:
            neighbors.append((x-1, y))
        
        return neighbors
    
    def _remove_wall(self, current, next_cell):
        """Remove wall between two cells."""
        x1, y1 = current
        x2, y2 = next_cell
        
        if x2 == x1 + 1:  # Moving East
            self.grid[y1][x1]['E'] = False
            self.grid[y2][x2]['W'] = False
        elif x2 == x1 - 1:  # Moving West
            self.grid[y1][x1]['W'] = False
            self.grid[y2][x2]['E'] = False
        elif y2 == y1 + 1:  # Moving South
            self.grid[y1][x1]['S'] = False
            self.grid[y2][x2]['N'] = False
        elif y2 == y1 - 1:  # Moving North
            self.grid[y1][x1]['N'] = False
            self.grid[y2][x2]['S'] = False
    
    def create_entrance_exit(self):
        """Create random entrance and exit on perimeter walls."""
        perimeter_walls = []
        
        # Top wall (North side)
        for x in range(self.width):
            perimeter_walls.append((x, 0, 'N'))
        
        # Bottom wall (South side)
        for x in range(self.width):
            perimeter_walls.append((x, self.height - 1, 'S'))
        
        # Left wall (West side)
        for y in range(self.height):
            perimeter_walls.append((0, y, 'W'))
        
        # Right wall (East side)
        for y in range(self.height):
            perimeter_walls.append((self.width - 1, y, 'E'))
        
        # Randomly select entrance and exit
        random.shuffle(perimeter_walls)
        entrance_wall = perimeter_walls[0]
        exit_wall = perimeter_walls[1]
        
        # Remove walls for entrance and exit
        x, y, direction = entrance_wall
        self.grid[y][x][direction] = False
        self.entrance = entrance_wall
        
        x, y, direction = exit_wall
        self.grid[y][x][direction] = False
        self.exit = exit_wall
        
        print(f"Entrance: Cell ({self.entrance[0]}, {self.entrance[1]}) - {self.entrance[2]} wall")
        print(f"Exit: Cell ({self.exit[0]}, {self.exit[1]}) - {self.exit[2]} wall")
    
    def create_maze_geometry(self, collection_name="Maze"):
        """Create 3D geometry for the maze in Blender."""
        # Create new collection for maze
        if collection_name in bpy.data.collections:
            maze_collection = bpy.data.collections[collection_name]
        else:
            maze_collection = bpy.data.collections.new(collection_name)
            bpy.context.scene.collection.children.link(maze_collection)
        
        # Create material for walls
        mat = bpy.data.materials.new(name="MazeMaterial")
        mat.use_nodes = True
        mat.node_tree.nodes["Principled BSDF"].inputs[0].default_value = (0.2, 0.3, 0.5, 1.0)
        
        # Create walls
        for y in range(self.height):
            for x in range(self.width):
                cell = self.grid[y][x]
                pos_x = x * self.cell_size
                pos_y = y * self.cell_size
                
                # North wall
                if cell['N']:
                    self._create_wall(
                        pos_x, pos_y, 
                        self.cell_size, self.wall_thickness,
                        maze_collection, mat
                    )
                
                # West wall
                if cell['W']:
                    self._create_wall(
                        pos_x, pos_y,
                        self.wall_thickness, self.cell_size,
                        maze_collection, mat
                    )
                
                # South wall (only for last row)
                if y == self.height - 1 and cell['S']:
                    self._create_wall(
                        pos_x, pos_y + self.cell_size,
                        self.cell_size, self.wall_thickness,
                        maze_collection, mat
                    )
                
                # East wall (only for last column)
                if x == self.width - 1 and cell['E']:
                    self._create_wall(
                        pos_x + self.cell_size, pos_y,
                        self.wall_thickness, self.cell_size,
                        maze_collection, mat
                    )
        
        # Create floor
        self._create_floor(maze_collection)
        
        # Add entrance and exit markers
        self._create_markers(maze_collection)
        
        print(f"Maze generated: {self.width}x{self.height} cells")
    
    def _create_wall(self, x, y, size_x, size_y, collection, material):
        """Create a single wall segment."""
        bpy.ops.mesh.primitive_cube_add(
            size=1,
            location=(x + size_x/2, y + size_y/2, self.wall_height/2)
        )
        wall = bpy.context.active_object
        wall.scale = (size_x, size_y, self.wall_height)
        
        # Apply material
        if wall.data.materials:
            wall.data.materials[0] = material
        else:
            wall.data.materials.append(material)
        
        # Link to collection
        for coll in wall.users_collection:
            coll.objects.unlink(wall)
        collection.objects.link(wall)
    
    def _create_floor(self, collection):
        """Create floor for the maze."""
        floor_size_x = self.width * self.cell_size
        floor_size_y = self.height * self.cell_size
        
        bpy.ops.mesh.primitive_plane_add(
            size=1,
            location=(floor_size_x/2, floor_size_y/2, 0)
        )
        floor = bpy.context.active_object
        floor.scale = (floor_size_x, floor_size_y, 1)
        floor.name = "MazeFloor"
        
        # Create floor material
        mat = bpy.data.materials.new(name="FloorMaterial")
        mat.use_nodes = True
        mat.node_tree.nodes["Principled BSDF"].inputs[0].default_value = (0.8, 0.8, 0.8, 1.0)
        
        if floor.data.materials:
            floor.data.materials[0] = mat
        else:
            floor.data.materials.append(mat)
        
        # Link to collection
        for coll in floor.users_collection:
            coll.objects.unlink(floor)
        collection.objects.link(floor)
    
    def _create_markers(self, collection):
        """Create visual markers for entrance and exit."""
        if not self.entrance or not self.exit:
            print("Warning: Entrance or exit not set!")
            return
        
        print(f"Creating entrance marker at {self.entrance}")
        print(f"Creating exit marker at {self.exit}")
        
        # Create entrance marker (green)
        entrance_pos = self._get_marker_position(self.entrance)
        bpy.ops.mesh.primitive_cylinder_add(
            radius=0.5,
            depth=0.3,
            location=(entrance_pos[0], entrance_pos[1], 0.15)
        )
        entrance_marker = bpy.context.active_object
        entrance_marker.name = "Entrance_Marker"
        
        # Green material for entrance
        mat_entrance = bpy.data.materials.new(name="EntranceMaterial")
        mat_entrance.use_nodes = True
        bsdf = mat_entrance.node_tree.nodes["Principled BSDF"]
        bsdf.inputs["Base Color"].default_value = (0.0, 1.0, 0.0, 1.0)
        bsdf.inputs["Emission Color"].default_value = (0.0, 1.0, 0.0, 1.0)
        bsdf.inputs["Emission Strength"].default_value = 2.0
        
        entrance_marker.data.materials.append(mat_entrance)
        
        # Move to collection
        for coll in entrance_marker.users_collection:
            coll.objects.unlink(entrance_marker)
        collection.objects.link(entrance_marker)
        
        # Create exit marker (red)
        exit_pos = self._get_marker_position(self.exit)
        bpy.ops.mesh.primitive_cylinder_add(
            radius=0.5,
            depth=0.3,
            location=(exit_pos[0], exit_pos[1], 0.15)
        )
        exit_marker = bpy.context.active_object
        exit_marker.name = "Exit_Marker"
        
        # Red material for exit
        mat_exit = bpy.data.materials.new(name="ExitMaterial")
        mat_exit.use_nodes = True
        bsdf = mat_exit.node_tree.nodes["Principled BSDF"]
        bsdf.inputs["Base Color"].default_value = (1.0, 0.0, 0.0, 1.0)
        bsdf.inputs["Emission Color"].default_value = (1.0, 0.0, 0.0, 1.0)
        bsdf.inputs["Emission Strength"].default_value = 2.0
        
        exit_marker.data.materials.append(mat_exit)
        
        # Move to collection
        for coll in exit_marker.users_collection:
            coll.objects.unlink(exit_marker)
        collection.objects.link(exit_marker)
        
        print("Entrance and exit markers created successfully!")
    
    def _get_marker_position(self, wall_info):
        """Calculate position for entrance/exit marker."""
        x, y, direction = wall_info
        pos_x = x * self.cell_size + self.cell_size / 2
        pos_y = y * self.cell_size + self.cell_size / 2
        
        # Adjust position based on wall direction
        if direction == 'N':
            pos_y = y * self.cell_size
        elif direction == 'S':
            pos_y = (y + 1) * self.cell_size
        elif direction == 'W':
            pos_x = x * self.cell_size
        elif direction == 'E':
            pos_x = (x + 1) * self.cell_size
        
        return (pos_x, pos_y)
 
 
def clear_maze_collection(collection_name="Maze"):
    """Clear existing maze collection."""
    if collection_name in bpy.data.collections:
        collection = bpy.data.collections[collection_name]
        for obj in collection.objects:
            bpy.data.objects.remove(obj, do_unlink=True)
        bpy.data.collections.remove(collection)
 
 
# Main execution
if __name__ == "__main__":
    # Clear any existing maze
    clear_maze_collection("Maze")
    
    # Create and generate maze
    # Adjust parameters here:
    maze = MazeGenerator(
        width=15,           # Number of cells in X
        height=15,          # Number of cells in Y
        wall_thickness=0.2, # Wall thickness
        wall_height=3.0,    # Wall height
        cell_size=2.0       # Size of each cell
    )
    
    maze.generate_maze()
    maze.create_entrance_exit()
    maze.create_maze_geometry("Maze")
    
    print("Maze generation complete!")

Code python pour Unreal Engine Créez un fichier intitulé unreal_maze_generator.py

"""
Unreal Engine Maze Generator
A Python script to generate 3D mazes in Unreal Engine using recursive backtracking algorithm.
Requires: Unreal Engine with Python Editor Script Plugin enabled
"""
 
import unreal
import random
 
 
class UnrealMazeGenerator:
    def __init__(self, width=10, height=10, wall_thickness=20.0, wall_height=300.0, cell_size=200.0):
        """
        Initialize the maze generator for Unreal Engine.
        
        Args:
            width: Number of cells in X direction
            height: Number of cells in Y direction
            wall_thickness: Thickness of walls in cm (Unreal units)
            wall_height: Height of walls in cm
            cell_size: Size of each cell in cm
        """
        self.width = width
        self.height = height
        self.wall_thickness = wall_thickness
        self.wall_height = wall_height
        self.cell_size = cell_size
        
        # Initialize maze grid
        self.grid = [[{'N': True, 'S': True, 'E': True, 'W': True, 'visited': False} 
                     for _ in range(width)] for _ in range(height)]
        
        # Store entrance and exit positions
        self.entrance = None
        self.exit = None
        
        # Unreal Editor utilities
        self.editor_level_lib = unreal.EditorLevelLibrary()
        self.editor_actor_subsystem = unreal.get_editor_subsystem(unreal.EditorActorSubsystem)
        
        # Store spawned actors for organization
        self.maze_actors = []
    
    def generate_maze(self):
        """Generate maze using recursive backtracking algorithm."""
        stack = []
        current = (0, 0)
        self.grid[current[1]][current[0]]['visited'] = True
        
        while True:
            neighbors = self._get_unvisited_neighbors(current)
            
            if neighbors:
                # Choose random neighbor
                next_cell = random.choice(neighbors)
                stack.append(current)
                
                # Remove wall between current and next cell
                self._remove_wall(current, next_cell)
                
                # Mark next cell as visited and move to it
                self.grid[next_cell[1]][next_cell[0]]['visited'] = True
                current = next_cell
            elif stack:
                # Backtrack
                current = stack.pop()
            else:
                # Maze complete
                break
    
    def _get_unvisited_neighbors(self, cell):
        """Get list of unvisited neighboring cells."""
        x, y = cell
        neighbors = []
        
        # Check North
        if y > 0 and not self.grid[y-1][x]['visited']:
            neighbors.append((x, y-1))
        # Check South
        if y < self.height - 1 and not self.grid[y+1][x]['visited']:
            neighbors.append((x, y+1))
        # Check East
        if x < self.width - 1 and not self.grid[y][x+1]['visited']:
            neighbors.append((x+1, y))
        # Check West
        if x > 0 and not self.grid[y][x-1]['visited']:
            neighbors.append((x-1, y))
        
        return neighbors
    
    def _remove_wall(self, current, next_cell):
        """Remove wall between two cells."""
        x1, y1 = current
        x2, y2 = next_cell
        
        if x2 == x1 + 1:  # Moving East
            self.grid[y1][x1]['E'] = False
            self.grid[y2][x2]['W'] = False
        elif x2 == x1 - 1:  # Moving West
            self.grid[y1][x1]['W'] = False
            self.grid[y2][x2]['E'] = False
        elif y2 == y1 + 1:  # Moving South
            self.grid[y1][x1]['S'] = False
            self.grid[y2][x2]['N'] = False
        elif y2 == y1 - 1:  # Moving North
            self.grid[y1][x1]['N'] = False
            self.grid[y2][x2]['S'] = False
    
    def create_entrance_exit(self):
        """Create random entrance and exit on perimeter walls."""
        perimeter_walls = []
        
        # Top wall (North side)
        for x in range(self.width):
            perimeter_walls.append((x, 0, 'N'))
        
        # Bottom wall (South side)
        for x in range(self.width):
            perimeter_walls.append((x, self.height - 1, 'S'))
        
        # Left wall (West side)
        for y in range(self.height):
            perimeter_walls.append((0, y, 'W'))
        
        # Right wall (East side)
        for y in range(self.height):
            perimeter_walls.append((self.width - 1, y, 'E'))
        
        # Randomly select entrance and exit
        random.shuffle(perimeter_walls)
        entrance_wall = perimeter_walls[0]
        exit_wall = perimeter_walls[1]
        
        # Remove walls for entrance and exit
        x, y, direction = entrance_wall
        self.grid[y][x][direction] = False
        self.entrance = entrance_wall
        
        x, y, direction = exit_wall
        self.grid[y][x][direction] = False
        self.exit = exit_wall
        
        unreal.log(f"Entrance: Cell ({self.entrance[0]}, {self.entrance[1]}) - {self.entrance[2]} wall")
        unreal.log(f"Exit: Cell ({self.exit[0]}, {self.exit[1]}) - {self.exit[2]} wall")
    
    def create_maze_in_level(self, folder_name="/Game/Maze"):
        """Create the maze geometry in the Unreal level."""
        unreal.log("Creating maze geometry in Unreal Engine...")
        
        # Create materials
        wall_material = self._create_wall_material()
        floor_material = self._create_floor_material()
        
        # Create walls
        wall_count = 0
        for y in range(self.height):
            for x in range(self.width):
                cell = self.grid[y][x]
                pos_x = x * self.cell_size
                pos_y = y * self.cell_size
                
                # North wall
                if cell['N']:
                    self._create_wall(
                        pos_x, pos_y, 
                        self.cell_size, self.wall_thickness,
                        wall_material, f"Wall_N_{x}_{y}"
                    )
                    wall_count += 1
                
                # West wall
                if cell['W']:
                    self._create_wall(
                        pos_x, pos_y,
                        self.wall_thickness, self.cell_size,
                        wall_material, f"Wall_W_{x}_{y}"
                    )
                    wall_count += 1
                
                # South wall (only for last row)
                if y == self.height - 1 and cell['S']:
                    self._create_wall(
                        pos_x, pos_y + self.cell_size,
                        self.cell_size, self.wall_thickness,
                        wall_material, f"Wall_S_{x}_{y}"
                    )
                    wall_count += 1
                
                # East wall (only for last column)
                if x == self.width - 1 and cell['E']:
                    self._create_wall(
                        pos_x + self.cell_size, pos_y,
                        self.wall_thickness, self.cell_size,
                        wall_material, f"Wall_E_{x}_{y}"
                    )
                    wall_count += 1
        
        # Create floor
        self._create_floor(floor_material)
        
        # Create entrance and exit markers
        self._create_markers()
        
        unreal.log(f"Maze generation complete! Created {wall_count} walls")
        unreal.log(f"Maze dimensions: {self.width}x{self.height} cells")
        unreal.log(f"Total actors spawned: {len(self.maze_actors)}")
    
    def _create_wall_material(self):
        """Create a blue material for walls."""
        # In a real scenario, you would load or create a material asset
        # For simplicity, we'll return None and set color via actor properties
        return None
    
    def _create_floor_material(self):
        """Create a gray material for floor."""
        return None
    
    def _create_wall(self, x, y, size_x, size_y, material, name):
        """
        Create a single wall segment using a Cube static mesh.
        
        Note: In Unreal, coordinates are X=forward, Y=right, Z=up
        We're treating our maze as X-Y plane (top-down view)
        """
        # Calculate center position
        center_x = x + size_x / 2
        center_y = y + size_y / 2
        center_z = self.wall_height / 2
        
        # Create location (Unreal uses cm by default)
        location = unreal.Vector(center_x, center_y, center_z)
        rotation = unreal.Rotator(0, 0, 0)
        scale = unreal.Vector(size_x / 100.0, size_y / 100.0, self.wall_height / 100.0)
        
        # Spawn a cube actor
        actor_class = unreal.EditorAssetLibrary.load_blueprint_class('/Engine/BasicShapes/Cube.Cube')
        
        if actor_class:
            spawned_actor = self.editor_level_lib.spawn_actor_from_class(
                actor_class,
                location,
                rotation
            )
            
            if spawned_actor:
                # Set scale
                spawned_actor.set_actor_scale3d(scale)
                
                # Set name
                spawned_actor.set_actor_label(name)
                
                # Add to our list
                self.maze_actors.append(spawned_actor)
                
                # Set color (blue-ish)
                # This would require setting up material instances in practice
        else:
            # Fallback: create a static mesh actor with cube
            spawned_actor = self.editor_level_lib.spawn_actor_from_object(
                unreal.load_object(None, '/Engine/BasicShapes/Cube.Cube'),
                location,
                rotation
            )
            
            if spawned_actor:
                spawned_actor.set_actor_scale3d(scale)
                spawned_actor.set_actor_label(name)
                self.maze_actors.append(spawned_actor)
    
    def _create_floor(self, material):
        """Create floor for the maze."""
        floor_size_x = self.width * self.cell_size
        floor_size_y = self.height * self.cell_size
        
        # Center position
        center_x = floor_size_x / 2
        center_y = floor_size_y / 2
        center_z = -10.0  # Slightly below ground
        
        location = unreal.Vector(center_x, center_y, center_z)
        rotation = unreal.Rotator(0, 0, 0)
        scale = unreal.Vector(floor_size_x / 100.0, floor_size_y / 100.0, 0.2)
        
        # Spawn floor cube
        actor_class = unreal.EditorAssetLibrary.load_blueprint_class('/Engine/BasicShapes/Cube.Cube')
        
        if actor_class:
            floor_actor = self.editor_level_lib.spawn_actor_from_class(
                actor_class,
                location,
                rotation
            )
            
            if floor_actor:
                floor_actor.set_actor_scale3d(scale)
                floor_actor.set_actor_label("MazeFloor")
                self.maze_actors.append(floor_actor)
    
    def _create_markers(self):
        """Create visual markers for entrance and exit."""
        if not self.entrance or not self.exit:
            unreal.log_warning("Entrance or exit not set!")
            return
        
        unreal.log(f"Creating entrance marker at {self.entrance}")
        unreal.log(f"Creating exit marker at {self.exit}")
        
        # Create entrance marker (green cylinder)
        entrance_pos = self._get_marker_position(self.entrance)
        self._create_marker(entrance_pos[0], entrance_pos[1], "Entrance_Marker", is_entrance=True)
        
        # Create exit marker (red cylinder)
        exit_pos = self._get_marker_position(self.exit)
        self._create_marker(exit_pos[0], exit_pos[1], "Exit_Marker", is_entrance=False)
        
        unreal.log("Entrance and exit markers created successfully!")
    
    def _create_marker(self, x, y, name, is_entrance=True):
        """Create a cylinder marker at the specified position."""
        location = unreal.Vector(x, y, 15.0)  # 15cm above floor
        rotation = unreal.Rotator(0, 0, 0)
        scale = unreal.Vector(0.5, 0.5, 0.3)  # Radius 50cm, height 30cm
        
        # Load cylinder mesh
        actor_class = unreal.EditorAssetLibrary.load_blueprint_class('/Engine/BasicShapes/Cylinder.Cylinder')
        
        if actor_class:
            marker = self.editor_level_lib.spawn_actor_from_class(
                actor_class,
                location,
                rotation
            )
            
            if marker:
                marker.set_actor_scale3d(scale)
                marker.set_actor_label(name)
                self.maze_actors.append(marker)
                
                # In practice, you would apply a green/red emissive material here
    
    def _get_marker_position(self, wall_info):
        """Calculate position for entrance/exit marker."""
        x, y, direction = wall_info
        pos_x = x * self.cell_size + self.cell_size / 2
        pos_y = y * self.cell_size + self.cell_size / 2
        
        # Adjust position based on wall direction
        if direction == 'N':
            pos_y = y * self.cell_size
        elif direction == 'S':
            pos_y = (y + 1) * self.cell_size
        elif direction == 'W':
            pos_x = x * self.cell_size
        elif direction == 'E':
            pos_x = (x + 1) * self.cell_size
        
        return (pos_x, pos_y)
    
    def clear_maze(self):
        """Clear all spawned maze actors from the level."""
        unreal.log("Clearing previous maze actors...")
        
        for actor in self.maze_actors:
            if actor:
                self.editor_level_lib.destroy_actor(actor)
        
        self.maze_actors.clear()
        unreal.log("Maze cleared!")
    
    def select_all_maze_actors(self):
        """Select all maze actors for easy manipulation."""
        self.editor_level_lib.set_selected_level_actors(self.maze_actors)
        unreal.log(f"Selected {len(self.maze_actors)} maze actors")
 
 
def clear_existing_maze():
    """Helper function to clear any existing maze actors."""
    # Find all actors with "Wall_", "MazeFloor", or markers in their name
    all_actors = unreal.EditorLevelLibrary.get_all_level_actors()
    maze_actors = [actor for actor in all_actors 
                   if actor and (actor.get_actor_label().startswith("Wall_") or 
                                actor.get_actor_label().startswith("Maze") or
                                actor.get_actor_label().endswith("_Marker"))]
    
    for actor in maze_actors:
        unreal.EditorLevelLibrary.destroy_actor(actor)
    
    unreal.log(f"Cleared {len(maze_actors)} existing maze actors")
 
 
# Main execution
if __name__ == "__main__":
    unreal.log("=" * 60)
    unreal.log("UNREAL ENGINE MAZE GENERATOR")
    unreal.log("=" * 60)
    
    # Clear any existing maze
    clear_existing_maze()
    
    # Create and generate maze
    # Adjust parameters here:
    maze = UnrealMazeGenerator(
        width=15,              # Number of cells in X
        height=15,             # Number of cells in Y
        wall_thickness=20.0,   # Wall thickness in cm
        wall_height=300.0,     # Wall height in cm (3 meters)
        cell_size=200.0        # Size of each cell in cm (2 meters)
    )
    
    unreal.log("Generating maze structure...")
    maze.generate_maze()
    
    unreal.log("Creating entrance and exit...")
    maze.create_entrance_exit()
    
    unreal.log("Building maze geometry in level...")
    maze.create_maze_in_level()
    
    unreal.log("=" * 60)
    unreal.log("MAZE GENERATION COMPLETE!")
    unreal.log("=" * 60)
    unreal.log("TIP: Select all maze actors by uncommenting the line below:")
    unreal.log("# maze.select_all_maze_actors()")

Dans UE:

  • Activer Python dans Unreal: Edit → Plugins → “Python Editor Script Plugin”
  • Exécuter via: Tools → Execute Python Script
  • Personnaliser les paramètres (width, height, wall_height, etc.)

À vous de jouer, ajoutez le pack First Person et trouvez la sortie du labyrinthe!

Lien vers l'original

# Blender TA3

# Techart 3 - Modélisation d’objets 3D V - Blender II

# Cours 1 - Geometry nodes

# Cours 2 - Geometry Nodes

Banque de cours - Les geo nodes, data, sockets, fields

Les geo nodes, data, sockets, fields

Banque de cours - La couleur des noeuds et le data type associé

La couleur des noeuds et le data type associé:

La forme des noeuds:

# Data et sockets (connecteurs)

Tous les nœuds dans Blender sont basés sur une construction similaire. Cela s’applique à n’importe quel type de nœud. Ces parties comprennent le titre, les connecteurs, les propriétés et plus encore.

Titre

Le titre montre le nom/type du nœud ; il peut être remplacé en modifiant le Label du nœud. Sur le côté gauche du titre se trouve le bouton réduire qui peut être utilisé pour replier le nœud. Cela peut également être fait avec H.

Comment un nœud apparaît quand il est replié.

Aperçu

Les aperçus sont une superposition qui montre une petite image au-dessus du nœud affichant le résultat du nœud. Tous les nœuds ne prennent pas en charge les aperçus, mais ceux qui le font peuvent être basculés en utilisant les icônes / dans le coin supérieur droit du nœud à côté du titre.

Les aperçus peuvent être désactivés pour tout l’arbre de nœuds en utilisant le bouton Aperçus.

Connecteurs

Les connecteurs sont des valeurs d’entrée et de sortie pour le nœud. Ils apparaissent comme de petits cercles colorés de part et d’autre du nœud. Les connecteurs inutilisés peuvent être masqués avec Ctrl-H.

Chaque connecteur est codé par couleur selon le type de données qu’il gère.

Intégrés

**Shader (vert vif)**Utilisé pour les shaders dans Cycles et EEVEE.**Géométrie (turquoise)**Utilisé dans les Geometry Nodes.**Menu (gris foncé)**Utilisé pour les entrées de type énumération qui affichent un menu déroulant ou un bouton radio dans l’interface utilisateur.

Données

**Booléen (rose clair)**Utilisé pour transmettre une valeur vrai ou faux.**Couleur (jaune)**Indique que le connecteur accepte/produit des informations de couleur. Les couleurs peuvent avoir ou non une composante alpha selon le type d’arbre de nœuds.**Nombre à virgule flottante (gris clair)**Indique que le connecteur accepte/produit des nombres à virgule flottante.**Entier (vert lime)**Utilisé pour transmettre une valeur entière (un nombre sans composante fractionnelle).**Chaîne de caractères (bleu clair)**Utilisé pour transmettre une valeur textuelle.**Vecteur (bleu foncé)**Représente des données vectorielles comme des coordonnées et des normales. Les vecteurs peuvent avoir 2, 3 ou 4 composantes :
2D : Affiche et utilise uniquement les composantes X et Y.
3D : Comprend les composantes X, Y et Z.
4D : Comprend les composantes X, Y, Z et W.**Rotation (rose)**Indique une rotation/quaternion.**Matrice (rose foncé)**Indique une matrice 4×4 de valeurs flottantes, elle est souvent utilisée pour représenter une Matrice de transformation.

  • 2D : Affiche et utilise uniquement les composantes X et Y.
  • 3D : Comprend les composantes X, Y et Z.
  • 4D : Comprend les composantes X, Y, Z et W.

Blocs de données

**Collection (blanc)**Utilisé pour transmettre un bloc de données de collection.**Objet (orange)**Utilisé pour transmettre un bloc de données d’objet.**Matériau (saumon)**Utilisé pour transmettre un bloc de données de matériau.**Texture (rose)**Utilisé pour transmettre un bloc de données de texture.**Image (abricot)**Utilisé pour transmettre un bloc de données d’image.

Structure des connecteurs

Les connecteurs de données peuvent avoir différents types de structure, indiquant comment les valeurs sont transmises et interprétées. Des structures plus complexes permettent de transmettre plusieurs valeurs à travers une seule connexion.

**Simple (Cercle)**Ces connecteurs attendent une seule valeur, ils sont représentés par une forme de connecteur circulaire.**Champs (Losange)**Représente une valeur qui peut varier par élément (par ex. par point, arête ou face). Vous pouvez considérer un champ comme une “carte de valeurs”, similaire à la façon dont la luminosité des pixels dans une image en niveaux de gris représente des valeurs variables à travers l’espace.
Si une valeur unique est connectée à un connecteur de champ, elle est implicitement diffusée à tous les éléments qui reçoivent la même valeur.
Les champs peuvent avoir l’apparence suivante :
Losange : Le connecteur peut accepter une entrée de champ, ou il produit un champ. Une valeur constante unique peut être connectée à ces connecteurs, mais la sortie ne variera souvent pas par élément.
Losange avec point : Le connecteur peut être un champ, mais il s’agit actuellement d’une valeur unique. Cela est utile car il permet de suivre où les valeurs uniques sont calculées, au lieu d’un champ avec de nombreux résultats différents. Cela signifie également que l’Inspection des connecteurs affichera la valeur au lieu des noms d’entrée du champ.
Voir aussi
Documentation sur les champs des Geometry Nodes

  • Losange : Le connecteur peut accepter une entrée de champ, ou il produit un champ. Une valeur constante unique peut être connectée à ces connecteurs, mais la sortie ne variera souvent pas par élément.
  • Losange avec point : Le connecteur peut être un champ, mais il s’agit actuellement d’une valeur unique. Cela est utile car il permet de suivre où les valeurs uniques sont calculées, au lieu d’un champ avec de nombreux résultats différents. Cela signifie également que l’Inspection des connecteurs affichera la valeur au lieu des noms d’entrée du champ.

Entrées

Les entrées sont situées sur le côté inférieur gauche du nœud et fournissent les données dont le nœud a besoin pour exécuter sa fonction. Chaque connecteur d’entrée, à l’exception de l’entrée de shader verte, lorsqu’il est déconnecté, a une valeur par défaut qui peut être modifiée via une interface de couleur, numérique ou vectorielle. Dans la capture d’écran du nœud ci-dessus, la deuxième option de couleur est définie par une interface d’entrée de couleur.

Certains nœuds ont des connecteurs spéciaux qui peuvent accepter plusieurs entrées. Ces connecteurs auront une forme d’ellipse plutôt qu’un cercle pour indiquer leur comportement spécial.

Sorties

Les sorties sont situées sur le côté supérieur droit du nœud et peuvent être connectées à l’entrée des nœuds plus en aval dans l’arbre de nœuds.

Conversion

Certains types de connecteurs peuvent être convertis en d’autres, soit implicitement, soit explicitement. La conversion implicite se produit automatiquement sans avoir besoin d’un nœud de conversion. Par exemple, les connecteurs Float et Color peuvent être liés les uns aux autres.

Une fois qu’une conversion de connecteur est effectuée, des données peuvent être perdues et ne peuvent pas être récupérées plus loin dans l’arbre de nœuds. La conversion implicite de connecteur peut parfois changer les unités de données également. Lorsque vous branchez un nœud d’entrée Value dans un connecteur d’angle, il utilisera par défaut les radians indépendamment des Unités de la scène. Cela se produit parce que le nœud Value n’a pas d’unité alors que l’entrée d’angle en a une.

Conversions valides :

  • Entre couleur et vecteur – correspondance entre les canaux de couleur et les composantes de vecteur.
  • Entre couleur et float – les données de couleur sont converties en leur équivalent en niveaux de gris.
  • Couleur/float/vecteur vers Shader – convertit implicitement en couleur et donne le résultat de l’utilisation d’un nœud Emission.
  • Entre float et entier – les entiers deviennent simplement des floats, les floats sont tronqués.
  • Entre float et vecteur – quand un float devient un vecteur, la valeur est utilisée pour chaque composante. Quand un vecteur devient un float, la moyenne des composantes est prise.
  • Entre float et booléen – les valeurs supérieures à 0 sont vraies, vrai correspond à 1, et faux à 0.
  • Entre rotations et matrices.

La conversion explicite nécessite l’utilisation d’un nœud de conversion tel que le nœud Shader To RGB ou le nœud RGB to BW. Le nœud Math contient également certaines fonctions pour convertir entre degrés et radians.

Propriétés

De nombreux nœuds ont des paramètres qui peuvent affecter la façon dont ils interagissent avec les entrées et les sorties. Les paramètres des nœuds sont situés sous les sorties et au-dessus des entrées.

Un exemple des contrôles sur le nœud Chroma Key.

# Fields (Champs)

Fondamentalement, un field (champ) est une fonction : un ensemble d’instructions qui peut transformer un nombre arbitraire d’entrées en une seule sortie. Le résultat d’un champ peut ensuite être calculé plusieurs fois avec différentes données d’entrée. Ils sont utilisés dans tous les geometry nodes pour permettre des calculs qui produisent des résultats différents pour chaque élément (sommets de maillage, faces, etc.).

Un champ en entrée d’un nœud.

Par exemple, dans la figure ci-dessus, le champ connecté au nœud “Set Position” dépend de deux entrées, Position et Index, et les transforme en un vecteur en utilisant une seule instruction.

Visualisation des champs

Les formes des connecteurs (sockets) sont utilisées pour indiquer quels connecteurs sont des champs et lesquels sont des données régulières. Il existe trois formes possibles de connecteurs, chacune visualisant son “statut de champ” :

**Cercle :**Le connecteur nécessite une seule valeur réelle, il ne peut pas accepter un champ en entrée. Pour les connecteurs de sortie, cela signifie que le nœud produit toujours une seule valeur.**Losange :**Le connecteur peut accepter un champ en entrée, ou il produit un champ. Une valeur constante unique peut être connectée à ces connecteurs, mais la sortie ne variera souvent pas par élément.**Losange avec point :**Le connecteur peut être un champ, mais il s’agit actuellement d’une valeur unique. Cela est utile car il permet de suivre où les valeurs uniques sont calculées, au lieu d’un champ avec plusieurs résultats différents. Cela signifie également que l’Inspection des connecteurs affichera la valeur au lieu des noms d’entrée du champ.

La forme du connecteur est un losange avec un point, ce qui signifie que le champ a la même valeur pour chaque élément. Chaque point sera déplacé vers le haut de 5 m.

La forme du connecteur est un losange et l’entrée du champ a maintenant une entrée variable. En d’autres termes, la valeur peut être différente pour chaque élément. Dans ce cas, la position sera doublée, puisque le décalage pour chaque point est la position du point.

Astuce

Souvent, on souhaite extraire une seule valeur d’un champ. Bien qu’il ne soit pas logique conceptuellement de simplement transformer un champ en une seule valeur, le Nœud Sample Index ou le Nœud Attribute Statistic peuvent être utilisés pour récupérer une seule valeur d’un champ évalué sur une géométrie.

Lorsqu’une connexion est établie entre deux connecteurs de nœuds qui prennent en charge les champs, la connexion du nœud sera dessinée sous forme de ligne pointillée. Si vous faites l’erreur de connecter un connecteur non-champ à un connecteur de champ, la connexion sera dessinée sous forme de ligne rouge continue indiquant qu’il y a une erreur.

Types de nœuds

Les nœuds peuvent être séparés en deux catégories : les nœuds de flux de données qui transmettent généralement la géométrie, et les nœuds de champ qui opèrent sur les données par élément. Les nœuds de champ peuvent être des nœuds d’entrée qui apportent des données de géométrie dans l’arbre de nœuds, ou des nœuds de fonction qui opèrent sur ces données.

Nœuds de flux de données

Les nœuds avec une entrée de géométrie et une sortie de géométrie seront presque toujours des nœuds de flux de données. Cela signifie qu’ils modifient effectivement les données de géométrie qui seront produites par le modificateur Geometry Nodes.

Nœuds de fonction

Les nœuds avec des entrées et sorties de connecteurs en losange sont des nœuds de champ, et ressemblent aux instructions qui seront évaluées par les nœuds de flux de données. Des exemples de nœuds de fonction sont les nœuds mathématiques et aussi des nœuds plus complexes comme le Nœud Geometry Proximity.

Nœuds d’entrée

Les nœuds d’entrée fournissent des données au processus d’évaluation du champ. Par eux-mêmes, ils ne signifient rien ; ils doivent être évalués dans le contexte d’un nœud de flux de données (géométrie) pour réellement produire une valeur. Des exemples de nœuds d’entrée sont les nœuds d’entrée d’attributs intégrés comme Position et ID, mais aussi des nœuds de sélection comme Endpoint Selection.

Les entrées de champ peuvent également provenir d’autres nœuds qui traitent la géométrie comme le Distribute Points on Faces, sous la forme d’Attributs Anonymes.

Contexte de champ

Tous les nœuds de champ fonctionnent dans le contexte du nœud de flux de données auquel ils sont connectés. Le contexte consiste généralement en un type de composant de géométrie et un domaine d’attribut, donc il détermine quelles données sont récupérées à partir des nœuds d’entrée.

Un malentendu courant est que le même arbre de nœuds de champ utilisé à plusieurs endroits produira les mêmes données. Ce n’est pas nécessairement vrai, car l’arbre de nœuds de champ sera évalué pour chaque nœud de flux de données, récupérant potentiellement des données d’une géométrie différente ou modifiée.

Ici, le champ d’entrée du nœud Set Position est évalué une fois. Pour évaluer le champ, le nœud remonte en arrière pour récupérer les entrées des nœuds d’entrée de champ.

Lorsqu’un deuxième nœud Set Position est ajouté, le même arbre de nœuds de champ est évalué deux fois, une fois pour chaque nœud de flux de données. Au deuxième nœud Set Position, les résultats seront différents puisque son entrée de géométrie aura déjà la position modifiée du premier nœud.

Cependant, il est souvent nécessaire d’utiliser les mêmes valeurs de champ même après avoir modifié la géométrie. Le Nœud Capture Attribute évalue un champ, en copiant le résultat dans un attribut anonyme sur la géométrie.

Ici, un nœud Capture Attribute stocke une copie de la position initiale. Notez que l’évaluation du champ d’entrée du nœud Capture Attribute est une étape entièrement différente. Par la suite, les champs d’entrée des nœuds Set Position n’utilisent pas la position réelle, mais la copie d’attribut anonyme de celle-ci.

Nouvelles formes de sockets dans Blender

Traduction de l’article de Jacques Lucke publié le 8 août 2025 sur code.blender.org


Solution

Le principe directeur de cette refonte est le suivant : les formes de sockets communiquent le type de données qu’un nœud attend ou génère, indépendamment de la façon dont il est utilisé.

Signification des nouvelles formes

  • Barre verticale — Entrée/sortie de valeur unique
  • Losange (diamant) — Entrée/sortie de type champ (field)
  • Cercle — Types de données dynamiques (entrées/sorties flexibles)
  • Formes grille/liste — Fonctionnalités en cours de développement, sémantique similaire aux losanges

La forme losange-avec-point a été abandonnée.

Anciennes formes de sockets sur le nœud Set Position

Exemples

Quatre nœuds clés illustrent cette refonte :

  1. Nœud Math — Les sockets circulaires indiquent une compatibilité dynamique avec les valeurs uniques, les champs, les listes, etc.
  2. Nœud Triangulate — Entrées à valeur unique avec une sélection évaluée en tant que champ
  3. Nœud Set Position — Une entrée géométrie unique plus plusieurs entrées de type champ (toutes de forme identique)
  4. Nœud Cube — Entrées à valeur unique générant une sortie de type champ

Exemples d’utilisation des nouvelles formes de sockets

Point essentiel : les formes de sockets restent statiques, quelle que soit la connexion établie (à l’exception des nœuds de groupe).

Groupes de nœuds

Les nœuds d’entrée/sortie de groupe peuvent ajuster automatiquement leurs formes en fonction des connexions. Les auteurs peuvent remplacer la détection automatique lorsque la forme inférée ne correspond pas à la fonctionnalité souhaitée.

Comment remplacer la forme d’une entrée de groupe

Liens

Les connexions en pointillés indiquent toujours un passage potentiel de champ nécessitant un contexte d’évaluation. Elles complètent désormais l’information des formes de sockets au lieu de la dupliquer.

Liens de nœuds en pointillés

Nouvelles formes expérimentales

Les nœuds Sample Grid et Get List Item utilisent de nouvelles formes de sockets encore en développement, conçues pour les structures de données de type grille et liste.

Formes de sockets expérimentales pour les grilles et les listes

Informations perdues

Trois catégories d’informations précédemment communiquées ne sont plus visibles dans les formes de sockets :

  • Propagation de droite à gauche des exigences de valeur unique — toujours active en interne ; les avertissements sur les liens sont conservés
  • Propagation de gauche à droite de l’information de contenu de champ — préservée via les liens en pointillés
  • Distinction visuelle des valeurs de champ par défaut — accessible via les infobulles (tooltips)

Nœud Set Position avec une infobulle


Au-delà des Geometry Nodes

Ces nouvelles formes s’étendent aux nœuds du Compositeur, marquant les entrées acceptant uniquement des valeurs uniques et permettant potentiellement de distinguer les sockets d’image des sockets dynamiques. Le support futur des champs dans le compositing est en discussion.

Le nœud Glare utilise les nouvelles formes de sockets

Les nœuds de shaders ne sont pas concernés pour l’instant.

Débloquer de nouvelles fonctionnalités

Cette refonte élimine les barrières architecturales qui freinaient le développement des grilles volumétriques et des listes, accélérant ainsi la réalisation de fonctionnalités auparavant retardées par les contraintes liées aux formes de sockets.

Conclusion

Les auteurs reconnaissent que modifier la signification des formes de sockets affecte tous les utilisateurs des Geometry Nodes. Malgré la perte de certaines informations visuelles, les capacités acquises pour les nouvelles structures de données justifient ce compromis et évitent la stagnation du développement.


Source : code.blender.org/2025/08/new-socket-shapes — Jacques Lucke, 8 août 2025

Lien vers l'original

Lien vers l'original

Banque de cours - Suzanne qui se dissout

Suzanne qui se dissout

Et si on animait Suzanne ?

Lien vers l'original

# Cours 3

Banque de cours - F16 qui pointe

F16 qui pointe

Lien vers l'original

Banque de cours - Quelques défis

Quelques défis

Changements au Geo Workspace

  • Ajoutons le timeline et le shader editor dans l’espace de travail Geometry Nodes puis sauvegardons le nouveau fichier défaut

Défi 1 - Cube Rubik

Créer ceci à l’aide de geometry node:

Solution

Lien vers l'original

# Cours 4

Banque de cours - Kanban

Kanban

  • 看板 (Kanban) : Enseigne, signe visuel

  • Dans les années 1940, l’ingénieur industriel de Toyota Taiichi Ohno, remarque que l’inventaire dans les supermarchés américains suit une approche intéressante : Just In Time. Au lieu de tenir l’inventaire complet en tout temps et en permanence, le supermarché réapprovisionnait uniquement un rayon lorsqu’il était presque vide et ce, avec juste assez de marchandise pour satisfaire la demande prévue et confirmée.

    • En approvisionnement “Just In Time” (JIT en anglais, ou JAT en français), l’approvisionnement ne se fait qu’au moment où la demande est confirmée.

    • Toyota, cartes Kanban à l’usine Motomachi, circa 1965

    • Un exemple de carte Kanban

graph LR
  A((Les valeurs de la méthode Kanban)) --> B(Respect)
  A --> C(Amélioration continue)
  A --> D(Transparence)

graph LR
	A((Éléments du Kanban)) --> B(Cartes)
	A --> C(Colonnes)
	A --> D(Limites de travail -WIP)
	A --> E(Point engagement) --> F(Le backlog -ou à faire-)
	F --> G(Où on propose des tâches et idées)
	F --> H(Moment où une idée est reprise ou pgiée)
	A --> I(Point de livraison) --> J(La fin du workflow)
	I --> K(Correspond au moment de la livraison)
	A --> L(Système -Pull-) --> M(Les tâches ne sont pas déléguées. Chaque membre pige)
	L --> N(En fonction de ses capacités cette journée-là)
	L --> O(La direction: assigne les priorités et importances, mais ne délègue pas de tâches)
graph TD
	A((Meilleures pratiques Kanban)) --> B((Limite du travail en cours))
	A --> C((Gestion du flux de travail))
	A --> D((Critères, règles et politiques explicites et transparentes))
	A --> E((Boucles de rétroaction))
	A --> F((Amélioration continue et collaboration))
	A --> G((Viosualisation en temps réel et en tou temps du flux de travail))
		
		
- [ ] Un exemple de carte Kanban réelle, avec attributs


- [ ] Un tableau Kanban dans sa plus simple expression

Quelques logiciels Kanban:
    - [Atlassian Trello](https://trello.com/)
    - [Atlassian Jira](https://www.atlassian.com/software/jira)
    - [Clickup](https://clickup.com/)
    - [Monday.com](https://monday.com/)
    - [Asana](https://asana.com/fr)
    - [Notion](http://notion.com/)
    - Et un [tas](https://www.ntaskmanager.com/blog/best-kanban-tools/) d'autres...

- [ ] La machine à états qu’est le flux Kanban:

- [ ] Le Trello de mon comité géothermie

☝🏼

DEMO avec mon KANBAN sur Notion

graph LR
	A((Objectifs et avantages de la méthode Kanban)) --> B(Transparence) --> C(Temps réel)
	B --> D(En un coup d'oeil)
	B --> F(Ce qui reste à faire)
	B --> G(Ce qui traîne)
	B --> H(Qui fait quoi)
	B --> I(Responbilisation, redevabilité, imputabilité)
	A --> J(Efficacité) --> K(Fluide)
	J --> L(Mise en évidence des goulots d'étranglement)
	J --> M(Attentes claires et cohérentes)
	J --> N(Détection des inefficacités)
	A --> O(Just in Time) --> P(Réduction ou élmimination de l'inventaire inutilisé)
	O --> Q(Évite l'accumulation de stock)
	A --> R(Limite de travail en cours -WIP-)
	A --> S(Ludique)
	A --> T(Encoureage la collaboration et l'entraide)
- [ ] Dans l’industrie et avec un outil approprié (e.g. Jira), Les données de Kanban permettent de puissantes analyses

- [ ] Le temps de cycle est une représentation du temps qu'il faut pour terminer des éléments de travail individuels sur votre tableau Kanban. L'objectif du Cycle Time Scatterplot est de visualiser les temps d'achèvement de vos missions dans un laps de temps prédéfini.
- [ ] En attribuant différentes couleurs, le diagramme de dispersion est utilisé pour comparer les performances de différents types d'éléments de travail. Il fournit également une méthode simple pour prévoir la durée du cycle des futures affectations.

- [ ] L'histogramme du temps de cycle montre la distribution globale des temps de cycle de vos tâches terminées. Si la diffusion de vos données est trop large, cela signifie que votre processus est instable et qu'il y a trop de variabilité.
- [ ] L'histogramme du temps de cycle montre les délais de livraison moyens, médians et moyens et comment les tendances se développent au fil du temps. La mesure de votre temps de cycle moyen vous permet d'évaluer les performances de votre équipe. Idéalement, les lignes devraient rester régulières ou descendre. Plus votre temps de cycle est rapide, meilleures sont vos performances.

- [ ] L'histogramme de débit vous permet de visualiser la régularité avec laquelle votre équipe fournit des résultats.
- [ ] Il calcule vos moyennes de débit en utilisant les valeurs moyennes, médianes et de mode de votre distribution de fréquence de débit. Et votre débit moyen au cours du mois est la mesure la plus importante que vous souhaitez découvrir à partir de ce graphique. C'est une représentation de votre capacité à livrer.
- [ ] Au fil du temps, vous pouvez identifier les tendances de vos taux de livraison. Idéalement, votre débit moyen devrait augmenter progressivement ou rester à des niveaux similaires.

- [ ] Le suivi du débit à l'aide du graphique d'exécution du débit aide les équipes à maintenir de manière proactive un flux de travail stable en évaluant leur débit sur une base quotidienne, hebdomadaire ou mensuelle et en comparant ses valeurs au fil du temps. Plus les valeurs sont proches, plus votre processus est prévisible.

- [ ] L'Aging Chart vous permet de suivre vos tâches en cours. Il utilise le même format visuel que votre tableau Kanban, chaque colonne représentant un état de votre processus.
- [ ] Le graphique de vieillissement extrait les données de votre tableau Kanban et fournit un résumé visuel concis de votre flux. Le graphique vous donne une indication des performances de votre équipe dans des contextes similaires dans le passé. Plus le temps de cycle est élevé, plus le risque de retard est grand.

- [ ]
Lien vers l'original

Banque de cours - Quelques défis 2

Quelques défis

Défi 1 - Spirale

Créer cette animation à l’aide de geometry nodes

Solution Ici, on a keyframé le 2e valeur du Math node Add (juste après l’index).

Une solution plus élégante, serait d’utiliser le noeud “Scene time”:

Défi 2 - Pastilles

Créer cette animation à l’aide des geometry nodes

Solution

Défi 3 - Ronde dansante

Et maintenant cette animation, encore une fois à l’aide de geo nodes

Solution

Lien vers l'original

# Cours 5

Banque de cours - Xam Geo Nodes

Xam Geo Nodes

Bulles volcaniques : 25 %

Évaluation et pondération

Pondération25 %
Critères d’évaluationDéplacement des sphères progressif en fonction de la proximité à un empty
Scale (mise à l’échelle) des bulles progressif en fonction de la proximité à l’empty
Couleurs procédurales en fonction de la proximité à un empty
Animation/déplacement des bulles progressive en fonction de la proximité à un empty que l’on déplace dans le viewport selon le plan XY (ne perdez pas de temps à faire le rendu de l’animation).

Quelques indices Noeuds utiles :

  • Proximity Geometry à un empty dont la position devient un Mesh Line avec un seul point:
  • Grid
  • Instance on points
  • Map Range
  • Stored Name Attributed (pour la couleur à transmettre au Shader)
  • Scale Instances et Translate Instances
  • Set Material

À remettre

  • Dans le drive (là où vous remettez vos devoirs)
  • Créez un dossier à votre nom (utilisez le même pour les 3 défis)
  • Dans ce dossier, ajouter Votre fichier “Nom - Bulles volcaniques.blend” (Assurez-vous d’activer le checkbox “File → External Data → Automatically Pack Resources” avant de sauvegarder)

Texte en geo wire frames : 30 % Créez ceci (pas besoin d’animation), mais, bien sûr, changez Karim pour votre prénom

Évaluation et pondération

Pondération30 %
Critères d’évaluationUn mesh en forme de cylindre pour les arrêtes (edges)
Une sphère pour les sommets (vertices)
Une face réfléchissante pour les plans
Une couleur différente pour les sommets, arrêtes et faces
Ne perdez pas de temps à faire un rendu d’une image ou d’une animation. Un mode “Rendered” dans le viewport suffira

Quelques indices Quelques noeuds utiles

  • String to Curve
  • Fill Curve

  • Extrude Mesh
  • Pour les Vertex : Instance on points
  • Pour les Edges : Mesh to Curve + Curve to Mesh avec un “Curve Circle” comme profil
  • Join Geometry

À remettre

  • Dans le drive (là où vous remettez vos devoirs)
  • Créez un dossier à votre nom (utilisez le même pour les 3 défis)
  • Dans ce dossier, ajouter Votre fichier “Nom - Texte.blend” (Assurez-vous d’activer le checkbox “File → External Data → Automatically Pack Resources” avant de sauvegarder)

Random City : 35 %

  1. Commencez par télécharger ce fichier Blender localement sur votre disque dur :
    https://drive.google.com/file/d/1C36Immf3IwxGeqRXn4hOFc5KX_8BmQNk/view?usp=sharing

  2. Renommez-le “Nom - City.blend”

  3. Ce fichier contient une collection d’assets représentant des buildings

  4. Ajoutez des geo nodes afin d’obtenir une distribution de building random selon une distribution de Poisson:

Évaluation et pondération

Pondération35 %
Critères d’évaluationDistribution random à partir d’une série d’objets
Présence de sources de lumières colorées également distribuées de manière random
Des objets ajoutés à la liste d’objets à distribuer sont pris en compte automatiquement
Rotation random des buildings, mais selon des multiples de 90 degrés
Scale random des buildings, mais clamped (map range !)
Pas besoin de textures ou Materials

Quelques indices Quelques noeud utiles

  • Distribute Points on Faces
  • Map Range
  • Random Value

À remettre

  • Dans le drive (là où vous remettez vos devoirs)
  • Créez un dossier à votre nom (utilisez le même pour les 3 défis)
  • Dans ce dossier, ajouter Votre fichier “Nom - City.blend” (Assurez-vous d’activer le checkbox “File → External Data → Automatically Pack Resources” avant de sauvegarder)
Lien vers l'original

# Cours 6

Banque de cours - Floaty flottants

Floaty flottants

  • Ajouter un Plane avec un “Ocean” modifier, avec, pour les Waves, un Scale à 2.5 et Choppiness à 0.3

  • Pour le time, ajoutez comme driver l’équation “#frame/20” puis appuyer sur ↩, ça va animer l’océan.

  • S’assurer que l’interpolation est linéaire

  • Faites “Play” (spacebar) pour voir 🙂

  • Créer un cube, aller dans le workspace Geometry Nodes et faire New.

  • Assurez-vous d’épingler le workspace geo nodes pour ne pas qu’il disparaisse dès lors qu’on sélectionne un autre objet ou un autre modifier du cube.

  • Ajouter un noeud raycast, ne pas le connecter pour l’isntant.

  • La cible, c’est l’océan, Donc Drag and drop l’ocean de l’Outliner vers le workspace des geo nodes et connecter le socket geometry de cew dernier à socket du Raycast.

  • Aussi, assurez-vous que Object Info est à Relative afin que les matrice de transformations “World” soient appliqués, sinon la référence locale de l’objet sera prise en considération.

👌🏼

Vous avez renommé le Plane à “Ocean” et le Geo Nodes à, genre, “Flotty flottant”, right?

  • BTW, si vous voulez ce bel effet de transparence en mode Solid View, on l’active dans les paramètres du Shading. X-Ray (et Cavity pour les occlusions ambiantes).

  • Ajoutez les noeuds suivants puis faire Play. Vous voyez l’emprunte du cube flotter sur la surface de l’océan. C’est un bon départ.

  • Donc le cube et l’objet qui “cast” des rayons sur l’océan dans la direction des Z négatifs. On prend la valeur Z de la distance du rayon entre le cube et l’océan, on le multiplie par -1 pour le rendre négatif et on se sert de cette valeur pour calculer l’offset de Set Position dudit cube. Set Position va “transformer” la position du cube à l’endroit ou les rayons de ce dernier frappent la surface de l’océan.

  • Oui on a perdu le cube et c’est parce que Set Position va modifier la position de tous les vertices du cube en fonction du calcul et du ray cast qu’on vient de faire, l’écrapoutissant ce faisant (en d’autres termes, chaque paire de vertices du cube alignés en Z auront la même valeur Z à la sortie du Group Output).

  • Si on ajoute un join geometry pour voir le cube, déplacez-le et tournez-le pour voir l’effet sur l’océan.

  • Ain’t it chouette?

  • Une manière de retrouver l’objet, c’est de modifier “Source Position” du Raycast, pour lui dire que l’on veut conserver les positions relatives des vertices du cube.

  • P.S., j’ai retiré le join geometry node.

  • On veut aussi influencer la rotation, donc Set Position n’est pas le bon noeud. On va utiliser un noeud plus générique, le Transform geometry Node peut modifier non seulement la position (comme Set Position), mais également la rotation et le scale.

  • Pour la rotation, celle-ci est forcément fonction de la normale à la surface de l’océan.

  • Incidemment, le socket “Hit normal” du Raycast donne la direction du vecteur normal à la surface à l’endroit de la collision du casted ray. C’est exactement ce que l’on veut utiliser, avec un “Align Rotation to Vector”

  • Ça marche, mais vous notez le “jitter” (sautillement)? Si on réduisait le “choppiness” des vagues à zéro, se serait mieux, plus smooth, mais le saccadé vient du fait qu’une seule normal pour tout le cube est calculée, celle à l’endroit où le rayon touche à la surface de l’océan.

  • En d’autres termes, la variation de l’angle de la surface de l’océan, d’un frame à l’autre, varie trop à cause du “choppinness” des vagues.

  • Pour ça, il y a plusieurs manières. On va utiliser un noeud “Attributes Statistic” qui va nous calculer des valeurs comme la moyenne, etc., de notre cube.

  • On va remplacer le Location info du cube qui aliment Source Position du RayCast par la valeur “Mean” (moyenne) du Attribute Statics. Bien sûr, il faut dire à ce dernier que les stats, sur sur la position qu’on veut la calculer.

  • C’est encore trop “choppy”. On peut soit réduire le “choppiness” des vagues, soit calculer la. valeur de la normale autour de celle du rayon, sur le plan XY et en faire une moyenne.

  • On va donc copier Le Raycast 4 fois supplémentaires. On va connecter à chaque fois la géometrie de l’Object Info du cube au socket Target Geometry du Raycast.

  • Mais l’output Mean du Attribute Statistic, on va d’abord le faire passer par un Vector Math node de type Add.

  • La première fois, on laisse ça à zéro (donc la valeur moyenne au centre de l’objet).

  • La fois 2 et 3, on ajoute 1 en X puis on retire 1 en X (pas Z et pas Y).

  • Les 2 dernières fois, on ajoute 1 en Y, puis on retire 1 en Y (pas Z et pas X).

  • On a donc maintenant 5 rayons, un au centre, et 4 autres autour de ce dernier. Il suffit maintenant de calculer la valeur moyenne de la normale.

  • Un Vector Math à chaque fois, qui additionne tous les 5 vecteurs puis on divise par 5. Et c’est cette nouvelle normale, qui est la moyenne des 5 mesurées, qui sera utilisée pour aligner la rotation du cube.

  • Tada!

  • Remplacez le cube par une sphère par exemple.
Lien vers l'original

# Cours 7

Banque de cours - Geo nodes et Cloth simulations - Partie 1 - Coussin

Geo nodes et Cloth simulations - Partie 1 - Coussin

🔥

Un grand merci à Syn_cub pour son aimable permission de m’inspirer de ses tutos!

☝🏼

Ici, on explorera une utilisation avancée du système de geometry nodes, comment en utiliser plusieurs et les combiner avec une simulation phlysique.

Le coussin gonflable pas encore gonflé

  • Pour que la simulation fonctionne, il faut que l’objet soit un objet créé dans le Viewport, pas par le système de geo nodes.

  • Commençons donc par un cube dans le Viewport et faire ^3 pour le subdiviser 3 fois

☝🏼

Ça va ajouter un Subdivision surface modifier. Ajuster le render à 3 également.

  • Ajouter un “Cast” modifier de type sphérique avec un facteur de 1 pour que l’objet ressemble vraiment à une sphère, pas à un vieux ballon de volleyball en cuir 🙂


Le Cast Modifier dans Blender déforme un objet en transformant sa forme vers une forme géométrique prédéfinie — généralement une sphère, un cylindre, ou un parallélépipède (boîte). Il est souvent utilisé pour des effets stylisés ou pour corriger subtilement une forme.

### **📦 Comment ça fonctionne :**
Le modificateur Cast “attire” les sommets d’un maillage vers une forme cible, donnant l’impression que l’objet est en train d’être « reconfiguré » selon cette forme.

### **🛠️ Principaux paramètres :**
- **Type de déformation (Cast Type)** :
    - Sphère : attire les sommets vers une forme sphérique.
    - Cylindre : les attire vers une forme cylindrique (axe défini).
    - Boîte : transforme l’objet en une structure de type boîte.
- **Facteur (Factor)** :
    - Contrôle la **force** de l’effet.
    - 1.0 = transformation complète vers la forme cible.
    - 0.0 = aucun changement.
    - On peut même utiliser des **valeurs négatives** pour inverser ou “gonfler” la forme.
- **Rayon (Radius)** :
    - Limite l’effet aux sommets situés dans une certaine distance du centre.
- **Taille (Size)** :
    - Définit la taille de la forme cible vers laquelle les sommets sont attirés.
- **Utiliser X/Y/Z** :
    - Active la déformation seulement sur certains axes.
- **Utiliser la transformation (Use Transform)** :
    - Permet d’utiliser la transformation (position, rotation, échelle) d’un objet cible comme origine de la déformation.

  • Faire un “Apply” des deux modifiers pour avoir une réelle géométrie avant d’aller dans les geo nodes.

  • Pourquoi on a fait ça au lieu d’utiliser un UV Sphere par exemple? Bonne question, c’est qu’un UV Sphere a des triangles comme polygones aux pôles, et ça, les simulations n’aime pas, on veut des Quads.

  • Ici, avec bien sûr l’objet sélectionné, vous pouvez soit faire un “New” dans le workspace Geo Nodes, ou ajouter un Geo Node Modifier; rappelons-nous qu’un système de geo nodes est un modifier. Ici d’un objet réelle qui ressemble à une sphère.

  • Écrabouillons la sphère selon l’axe Z à l’aide d’un Transform Geometry Node où la valeur Z du Scale est à 0.33

  • On va maintenant distordre la galette en changeant le scale des normales via un Texture Noise dont le scale sera ajusté à environ 1.7 et le niveau de détail à 0.1

  • Ce qu’on a fait effectivement ici, c’est changer la taille (scale) des normales à la surface de notre objet en fonction d’une texture Noise et on a utilisé cette valeur pour déplacer les faces le long de chaque normale à la surface de la valeur du scale.

  • Pour l’instant le Map Range ne fait rien, mais ça nous permet de mieux ajuster la portée du noise plus tard.

  • Ajoutons un Set Shade Smooth (il peut être avant, i.e. tout de suite après le transform ou le group Input, comme il peut être à la fin, après le Set Position).

  • Ajouter un Subdivision Surface avec une résolution du subdivision à 2.

⚠️

J’ai activé le “Show timing”, c’est dans les overlays (voir la flèche), pour voir si ça changeait la performance de mettre le Set Shade Smooth à différents endroits, mais cela ne semble pas être le cas, la durée totale (au niveau du Group Output) variant entre 7 et 12 ms.

  • J’ai donc décidé de mettre le Set Shade Smooth après le Set Position, ça me semble plus logique.

  • On va réduire la puissance du noise à l’aide du Map Range et en jouant encore avec les valeurs du Noise Texture. Scale à 1.2 au lieu de 1.72 et Le To Max du Map Range à 0.7. Ainsi, le scale des normales va varier entre 0 et 0.7.

  • Groupons tout ce beau monde (Sélectionnez tous les noeuds sauf Group Output, faire F - pour Frame -, ce qui, ici, va créer un Frame - et appelons-le coussin gonflable.

☝🏼

J’ai également activé le mode wireframe même en mode solide (c’est dans les Overlays, là vous voyez la flèche).

Voro qui?

  • Maintenant, on aimerait que notre coussin se gonfle via un Cloth Simulation, sauf là où on aura épinglé des Vertex (Pin Group). Et on aimerait utiliser un Pin Group qui change avec le temps, en fonction de, par exemple, une texture Voronoi.

  • En d’autres mots, on veut qu’à l’endroit des Pin Groups, le coussin ne gonfle pas, mais on veut que les Vertex du pin group changent dynamiquement au fur et à mesure de l’animation de manière visuellement cool.

  • On va créer, dans les paramètres ‘Data’ de l’objet, un Vertex group vide qu’on va nommer “PinGroup”.

☝🏼

Notez que j’ai épinglé le système de Geo Nodes, c’est pour cela que les noeuds n’ont pas disparus même si je ne suis plus dans la paramètres “modifiers” de l’objet.

  • Créons une texture Voronoi et et brancher sa sortie Color à l’entrée Value d’un noeud “Viewer”.

☝🏼

  • Pour voir l’effet du Voronoi en couleur, il faut faire ^ ⇧ left-mouse sur le noeud Voronoi deux fois (la première fois, il va montrer la sortie du socket “Distance”, qui est en noir et blanc, et la 2e fois, ce sera le socket Color et Blender va automatiquement savoir qu’on s’attends à des valeurs RGB.
  • Brancher le socket de sortie Geometry du dernier noeud du groupe “Coussin gonflable”, au socket Geometry du Viewer.

  • Ctrl-Shift et cliquer sur le noeud voronoi. Une première fois, ça va montrer la distance.

  • Ctrl-Shift et cliquer une 2 fois sur le même noeud, va montrer la couleur.

☝🏼

Si vous branchez le noeud couleur à la main, le résultat sera en noir et blanc, aucune idée pourquoi.

  • Cela permet de voir l’effet du Voronoi sur l’objet:

  • Jouez avec les paramètres du Voronoi pour voir l’effet!

  • Changer le Scale du Voronoi à 1.5

  • Maintenant un truc super cool pour mettre un peu de symétrie dans cette texture le long de l’axe des X

  • Pour ce faire, il suffit de ne considérer que la valeur absolue de la composante X de la position des vertex dans la géométrie pour contrôler le vecteur de la texture Voronoi.

  • Chouette non? En gros, par rapport à l’axe des X, partout où les coordonnées de la texture avaient une valeur négative de X, celle-ci est transformée en la même valeur mais positive cette fois-ci, et donc la même texture se trouve de chaque côté, en ayant l’axe des Y comme miroir.

  • On veut maintenant tourner la texture en fonction du temps.

  • On va prendre un noeud Vector Rotate auquel on ajoute un driver à Angle à l’aide de la formule “#frame/80”. Donc les vecteurs vont tourner du numéro de frame divisé par 60 à chaque frame.

☝🏼

Avec l’introduction du Noeud Scene Time, on peut également éviter d’utiliser un driver et plutôt brancher le socket Frame du noeud Scene time à un Math Divide et c’est ce qu’on branche au socket Angle du Vector Rotate:

  • Faites “Play”.

  • Bon, c’est bien que le Voronoi tourne et tout, mais on va ajouter un peu de dynamisme.

  • Pour ce faire, ajoutez la 4e dimension à la texture Voronoi (4D), c’est la dimension W, qu’on peut voir comme la dimension temps. Changer la valeur de W équivaut à changer le visuel Voronoi.

  • On va donc ajouter un Driver à la valeur W: “#frame/30” par exemple.

  • Faites “Play”. Le mouvement est plus intéressant maintenant.

  • Bon, je dis ça, je dis rien hein, c’est à vous de jouer avec ces paramètres. Vous pouvez par exemple aussi ajouter un noeud Vector Math après Vector Rotate. Les possibilités sont assez infinies.

☝🏼

Là aussi, vous pouvez alimenter le paramètre W avec le socket Frame du noeud Scene Time divisé par une constante qui vous convient.

  • Mais bon, dans mon cas, ce que j’aime moins des drivers, c’est qu’il faut cliquer sur le champs pour voir l’équation utilisée.

  • Je vais donc plutôt le faire de manière plus explicite, avec le noeud Scene Time qui lui va alimenter autant Vector Rotante que W de Voronoi:

  • Ainsi, on peut ajuster la valeur du Divide plus facilement et plus “visuellement”. Bien sûr, si vous ne voulez pas la même valeur pour Angle et pour W, vous n’avez qu’à avoir deux noeuds Divide par exemple.
  • Encore une fois, les possibilités sont infinies, ça dépend du VFX que vous cherchez à obtenir.
  • Perso, je trouve que Frame/80 donne de bons résultats.

Archipel en pin group

  • On va utiliser un super noeud intitulé “Face Group Boundaries”.

  • Et ça tombe bien, chaque couleur du Voronoi possède un face group ID (vous avais-je dit que tout dans Blender possède un ID, un identificateur unique?).

  • Donc le face group Boundaries va identifier les bords de chaque face group ID, i.e. de chaque île de couleur que crée la texture Voronoi.

  • Et, je vous le donne en mille, les îles vont changer de forme à chaque frame puisqu’on alimenter la rotation du vecteur et du W de la texture Voronoi.

  • Faire ^ ⇧ et clic gauche sur le noeud Face Group Boundaries.

  • On ne voit rien pour l’instant parce que la sortie de la valeur Color est trop faible.

  • On va la multiplier par 100.

  • Ah ha! Comme vous pouvez le constater, ça créé un “Mask” où les valeurs blanches sont les frontières des îles de couleur.

  • Ça me fait penser au problème des 4 couleurs en théorie des graphes.

  • Et si l’on fait “Play”, on verra les frontières des îles changer puisque les îles de couleur changent de forme.

  • Vous l’avez deviné? On va utiliser les “Boundaries”, i.e. les valeurs blanches, comme étant les pin groups de la simulation Cloth qu’on va bientôt entreprendre.

  • Tout ce qui va être noir dans le mesh va gonfler, et tout ce qui est blanc ne bougera pas et toutes les zones grises joueront le rôle de facteur d’influence entre 0 et 1 (0 = full gonflé ↔ 1 = pas gonflé du tout).

  • Pour ce faire, on va tirer partie du fait que les noms de variables sont globales dans Blender.

  • Vous vous souvenez qu’on avait nommé “PinGroup” le Vertex Group dans les propriétés Data du Mesh?

  • Eh bien on peut ajouter des Vertex au Vertex Group PinGroup via le noeud Store Named Attributes. Si vous cliquez dans l’input “Name”, le nom “PinGroup” va apparaître (mais seulement si la géométrie Coussin gonflable est connectée au socket Geometry du Store Named Attribute). En fait le nom de toutes les variables globales que Blender a trouvé vont apparaître.

  • On peut rafraîchir, à chaque frame, le contenu du Vertex Group “PinGroup” en fonction des edges trouvés par le noeud Face Group Boundaries.
  • Si vous passez au mode “Weight Paint” (C’est en haut à gauche, là où c’est marqué e ce moment “Object Mode”) et que vous faites play, vous allez voir le contenu du Vertex Group “PinGroup” évoluer à chaque frame.
Lien vers l'original

Projet intégrateur

# Cours 8

Banque de cours - Geo nodes et Cloth simulations - Partie 2 - Trippy

Geo nodes et Cloth simulations - Partie 2 - Trippy

La wireframe collision (ou comment créer un objet vachement trippy)

  • Je trouve la résolution trop faible, augmentons la valeur Level du noeud Subdivision Surface à 3.Pour voir les wireframes même en mode solide, c’est dans les Overlays.

☝🏼

Pour voir le wireframe même en mode solide ou weight paint, c’est dans les Overlays

  • Finalement, on va stocker (donc noeud Store Named Attribute) la position (donc noeud Position) avant simulation de tous les Vertex du mesh dans une nouvelle variable qu’ont va appeler “Repos”.

☝🏼

J’aime bien nommer mes variables en français pour être certain de ne pas entrer en conflit avec des noms de variables déjà existants dans Blender, puisque les variables on une porté globale.

  • La position “Repos” du mesh va nous aider à calculer la collision avec le Wireframe qu’on va créer à la prochaine étape. Z’allez voir.

  • Renommer notre Geo Node “Avant Simulation”.

☝🏼

Si votre Geo Node est épinglé, vous ne pourrez pas changer son nom dans le workspace Geo nodes, mais vous pouvez le faire dans le Geo Nodes Modifier.

  • Voici le système de Geo Nodes jusqu’à maintenant, où j’ai corrigé le Store Named Attribute nommé repos, la valeur stockée est un vecteur et non pas un float puisqu’on stocke la position de chaque vertex du PinGroup:

☝🏼

Notez qu’on voit la valeur maintenant des store Named Attributes dans le Spreadsheet, ça ça aide beaucoup!

  • Le but ici, c’est de créer un mesh à partir des vertex du pin group. Ça tombe bien, c’est ce que Face Group Boundaries nous donne!

  • Avec l’objet sélectionnée (Il s’appelle Cube, vous vous rappelez?), dans le viewport, faites Shift-D pour le dupliquer.

  • Faites enter pour ne pas déplacer le nouvel objet (qui se nomme Cube.001). C’est ce dernier qui est maintenant sélectionné.

  • Cliquer sur le chiffre 2 à côté du nom du geo node (”Avant Simulation”) pour que ce ne soit pas un seul système utilisé deux fois (par les deux objets) mais pour que notre nouvel objet utilise son propre système de Geo Nodes basé sur le premier.

☝🏼

Dans l’image, c’est Vector et non pas Float qu’on devrait lire sur le noeud Store Named Attribute nommé “Repos”.
Donc mettez ce noeud à Vector au lieu de Float!

  • Renommer le nouveau système de Geo Nodes à “Wireframe”.

  • Dans ce nouveau système de geo nodes sur le nouvel objet (Cube.001), on va effacer les deux Store Named Attributes, on n’en a pas besoin ici.

  • L’idée maintenant, c’est de créer un mesh à partir du Face Group Boundaries, qui sont, rappelons-le, les Vertex du Pin Group.

  • Ajouter un Mesh to Curve juste avant le group output; ça va convertir le maillage (mesh) du deuxième cube en courbe. Pour la sélection, on ne va choisir que les bords des îlots, i.e. la sortie de Face Group Boundaries.

  • Si on “Hide” le premier objet (Cube), on va voir le résultat. On a maintenant des Curves qui correspondent aux bords des îlots.

  • On va maintenant convertir les courbes en Mesh (Noeud Curve to Mesh) sur lequel on va appliquer un Subdivision Surface de niveau 2.

  • Ensuite, un truc pour adoucir la forme, c’est de contrôler la position des vecteurs de ce mesh avec la fonction Blur Attribute avec une itération assez élevées (genre 150).

☝🏼

Je vous avais dit que c’était puissant les geo nodes.
P.S.: si vous cliquez droit sur un noeud, un menu “Online Manual” va apparaître. Allez voir le noeud Blur Attribute, qui “smooths attribute values between neighbouring gemetry elements; the goal of each step being the mixing of the values of each element with its neighbours.”.

P.P.S.: Ce n’est pas important que les mesh ne se touchent pas. Ce wireframe ne sert pas de Vertex Pin Group (ça c’est le rôle justement de la variable PinGroup qu’on alimente dans le premier système de geo nodes).

  • Après moultes essais et erreurs, on a réalisé qu’on avait besoin de faire un “remesh topology”.

  • Une manière de le faire, c’est de convertir le mesh en points, les points en volume et le volume en mesh avec les bons paramètres pour la partie cruciale qui est le Points to Volume (ici Voxel amount à 256 et radius à 0.05.)

  • On va finalement et derechef adoucir la géométrie avec le noeud Blur Attribute, mais avec moins d’itérations cette fois-ci (e.g. 75).

☝🏼

Notez au passage cette manière de créer une structure complexe qu’il serait assez difficile à modéliser de manière traditionnelle.

  • Allez, faites “Play”. C’est beau, avouez!

  • Unhide du Cube.

  • Renommer “Cube.001” à “Collision” et “Cube” à “Coussin”. On va se servir du mesh Collision, plus tard, pour corriger la collision du Coussin.

La gonflette - ”Vous gonfliez ? J’en suis fort aise : eh bien ! Dansez maintenant.”

  • Passer au Workspace Layout.

  • Assurez-vous d’être au Frame 1 dans la Timeline.

  • Avec l’objet Coussin sélectionné, aller dans les propriétés Physics et choisir Cloth.

  • Choisir le Preset “Silk”.

  • Réduire les valeurs de “Damping” à 0 et ajuster toutes les valeurs de Stiffness à 1, mais laisser Bending à 0.5.

  • Cela va donner un feel très “léger” au tissu, comme s’il était fait de papier.

☝🏼

Right-click sur un input et choisir Online Manual 🙂 ou refaire les cours sur la simulation de tissu dans la section Techart 2 😇

  • Désactiver la gravité également (valeur 0 à Gravity dans Fields Weights). Sinon, notre coussin va se mettre à tomber tant qu’il n’a pas de pin groups.

  • Maintenant, tout le but en était un de gonflette, alors activons la pression, avec une “Pressure” de 10 atmosphères.

  • Dans Shape, choisir le Pin Group “PinGroup”.

  • Ajuster le Shrinking Factor à -0.25, ça donne un coussin mieux froissé.

  • Cachez l’objet “Collision” et faire “Play” rien qu’un peu 🙂

☝🏼

Notez que “Play” tente de calculer la simulation en temps réel. Les résultats peuvent être très bizarres tout dépendant de votre RAM et puissance CPU.

  • Activons le Self-Collision avec une bonne précision (Distance à sa valeur minimale, i.e. 0.001) pour améliorer la simulation et empêche l’objet d’entrer en collision avec lui-même.

  • Revenir au Frame 1, aller dans la section Cache et faire Bake (des 250 frames si votre CPU est assez puissant, sinon baissez à 100 frames et ajuster aussi le End frame dans le Timeline à 100).

☝🏼

Pour le rendu final, dans les Simulation Nodes de l’objet Coussin, vous pouvez augmenter le niveau de Subdivision Surface à 4 au lieu de 3 et refaire Bake à partir du Frame 1.
Ça dépend de votre CPU. Si votre Frame Rate baisse trop lors du Play, ajuster le niveau de Subdivisions. L’idée, c’est que seulement à a la toute fin, quand on est prêt à faire un rendu final, on augmente les valeurs pour un résultat plus précis.

Lien vers l'original

# Cours 9

Banque de cours - Geo nodes et Cloth Simulations - Partie 3 - Dansez

Geo nodes et Cloth Simulations - Partie 3 - Dansez

Dansez, certes ! Mais avec retenue je vous prie

  • On va enfin se servir de la variable “Repos” qui a gardé en mémoire la position au repos des Vertex du coussin, et du mesh Wireframe qu’on a créé pour mieux calculer la position au repos des Vertex du Pin groups.

☝🏼

Cette étape n’est pas nécessaire mais donne un meilleur rendu.

  • Passer dans le workspace Geo Nodes.

  • Si un Geo Nodes est épinglé, désactiver la chose.

  • Avec l’objet Coussin sélectionné, dans les propriétés Modifiers, ajouter un Geo Node Modifier après le Cloth Modifier, qu’on va appeler “Après Simulation” et faire “New” pour créer le nouveau système de Geo Node.

  • On va aller cherche le Collider Object, c’est l’objet nommé Collision.
  • Vous pouvez soit faire un drag and drop de l’Outliner vers le workspace Geo node, ou créer un noeud Object Info et utiliser la pipette pour cherche l’objet “Collision”.
  • On va calculer la distance entre les points de l’objet collision et ceux du coussin. Là ou la distance est 0, on va faire un set position de ces Vertex à la position “Repos” qu’on avait gardé en mémoire.
  • Cela aura pour effet de réduire les chevauchements de géométrie entre le coussin au repos et le filet qui l’empêche, en ces endroits, de gonfler.
  • Voyez plutôt, sans le noeud Set Position:

  • Et avec le noeud Set Position:

  • Ajoutons un noeud Sample Nearest Surface (de type Vector) pour échantillonner la position du coussin.
  • On va changer la position des échantillons du collision en fonction de la géométrie du Collision object (ici, comme on na pas déplacé l’objet par rapport à l’originie, ça ne change rien de choisir Original ou Relative).
  • Pour ce faire, on va déplacer les Vertex après le Sample Nearest Surface en fonction de la position de l’objet Collision.

  • Comme on le constate, le mesh du collision object s’est aplati, il est exactement tangente à la surface du coussin au repos.
  • Bon, je monte Object Info plus haut, pour pas que les noodles se croisent

  • Tiens, branchez le socket Value de Sample Nearest Surface à Offset également, avec un Vector Scale. C’est chouette non?

Lien vers l'original

Projet intégrateur - Moodboard

  • Pop quiz! - Maze avec murs modulaires
  • L’arc narratif
  • Votre début d’histoire - on complète les 6 phrases narratives

# Cours 10

Banque de cours - Geo nodes et cloth Simulations - Partie 4 - Masking

Geo nodes et cloth Simulations - Partie 4 - Masking

  • Bon, mais c’est pas ça qu’on veut. Revenons à nos coussins.
  • Maintenant que le mesh du Collision est exactement sur la surface du coussin au repos, on va sen servir pour mieux calculer les collisions.
  • Reprenons le Named Attribute Repos. On va créer un mask en retirant tous les vertex du coussin qui sont à proximité du collision.
  • On soustrait donc de la valeur Repos la position de Geometry Proximity, on calcule la longueur résultante.
  • Si la distance est exactement 0, ce sera totalement noir puis ça ira en tons de gris de plus en plus vers le blanc.
  • Pour voir l’effet, Ctrl-Shift left click sur le noeud Vector Length, puis la même chose sur le premier Set Position.
  • On voit alors l’effet du vecteur résultant Length sur la géométrie du coussin au repos. Un mask quoi!

  • Mais il y a trop de gris. On va réduire la portée du mask (Map Range!) où on arrête de considérer les longueurs plus élevées que 0.04 par exemple:

  • On peut ensuite ajuster le falloff de noir vers blanc pour qu’il ne commence pas trop tôt (i.e. avoir plus de noir) avec une fonction Power. Ça donne essentiellement une courbe exponentielle, donc au début c’est lent, mais plus on avance, plus ça tombe (falloff) vite.

  • Et pour terminer le mask, un petit blur pour adoucir les bords:

  • Ok, maintenant, il est temps de combiner les deux, le coussin et la collision à l’aide du mask.
  • Alors, là où c’est noir, on veut que le coussin soit à sa position au repos, et plus il s’éloigne de ces endroits, plus il gonfle.
  • Pour ce faire, on Vector Mix la position des Vertex du coussin au repos avec la position du coussin gonflé. Le Factor mélangera de manière uniforme les deux.

  • Alors devinez qui va alimenter Factor? Si si, le Mask!

  • Maintenant, là où se trouve l’objet Collision, la forme du coussin est à sa position au repos. Voyez avec ce Geo nodes et sans.
  • Avant:

  • Après:

  • Vu qu’on a l’objet Collision dans nos Geo nodes, autant continuer comme ça, pas besoin de rendre visible l’objet Collision dans l’outliner. Même qu’on va retirer du render aussi.
  • On va donc joindre la géométrie du Collision avec le coussin et ajouter un set shade smooth.

Lien vers l'original

# Cours 11

Banque de cours - Geo nodes et Cloth Simulations - Partie 5 - Material, Lighting et Shad

Geo nodes et Cloth Simulations - Partie 5 - Material, Lighting et Shading

Material, Lighting et Shading

  • Ajoutons un Set Material avant le dernier Join Geometry pour les deux géométries, celle du coussin et celle de l’objet collision:

  • À vous de jouer, créez de beaux materials, un bel éclairage, du beau compositing. Augmentez le subdivision surface du coussin (premier Geo node) à 4. Augmentez les valeurs du cloth simulation si nécessaire (Quality steps, Collision Quality) et refaites un bake puis un render de l’animation.

Lighting (tri-light, backdrop, contrast back light, compositing)

  • On le fait ensemble en classe

Un frame

L’animation

Lien vers l'original

  • Projet intégrateur - Storyboard II

# Cours 12

Banque de cours - La lumière - Éclairage 1

La lumière - Éclairage 1

Un peu de théorie

Éclairage extérieur

  • Créez un nouveau Niveau, complètement vide

  • Ajoutez un grand plancher (un cube au scale (10,10,0.2) et un autre cube unitaire déposé dessus (shortcut numpad “end”).

  • Sauvegardez le niveau sous le nom “LV_Lighting”
  • Dans le menu Window, choisir “Env. light Mixer”

  • Cliquez sur les 5 boutons un après l’autre pour les ajouter à notre scène

  • On a maintenant un soleil (Directional Light), une perspective atmosphérique (ExponentialHeightFog), une atmosphère (SkyAtmosphère), un éclairage ambiant venant du ciel (SkyLight) et des nuages (VolumetricCloud).
  • Dans l’Outliner, cachez-les ou montrez-les un par un ou par groupes pour voir l’effet

DirectionalLight (soleil)

  • Sélectionnez DirectionalLight (le soleil) et tournez-le

  • Vous pouvez aussi utiliser Ctrl-L et maintenir cette combinaison appuyée pour bouger la souris de gauche à droite (direction) et d’avant à arrière (élévation) pour régler la position du soleil dans le ciel.

  • [ ]

ExponentialHeightFog (effet de smog ou léger brouillard ou perspective atmosphérique)

  • Jouez avec la densité, le falloff
  • Je vous recommande d’activer Volumetric Fog, c’est plus réaliste

SkyAtmosphere (atmosphère du ciel)

  • Vous pouvez changer la couleur du ciel (Rayleigh Scattering))
  • Vous pouvez créer un effet de lumière diffuse (overcast) on modifiant le paramètre Mie Scattering Scale

  • Revenir aux valeurs défaut (le bouton Undo à droite de chaque paramètre que vous avez changé) et augmentez seulement le Mie Scattering Scale pour voir l’effet d’une lumière diffuse sur les objets et leur ombre portée.

SkyLight (lumière ambiante provenant du ciel)

  • Il s’agit de la lumière indirecte et réfractée du soleil sur l’atmosphère.
  • Par exemple, voyez l’effet de l’échelle d’intensité et de la couleur de cette lumière sur le monde

  • Si vous désactivez l’effet de skylight, l’ombre sera affreusement noire:

VolumetricCloud (nuages)

  • Il s’agit des nuages, de leur forme et de leur distribution
  • Jouez avec certains paramètres (layer Height, Bottom Altitude, etc.)

  • Vous pouvez également changer le Cloud material pour plus d’effet sur la couleur et la forme.
  • Constatez qu’il est un peu compliqué 😄

Post Process Volume

  • Pour contrôler l’exposition et l’adaptation de l’oeil aux différentes conditions d’éclairage, ajoutez un PostProcessVolume

  • Vous vous souvenez que par défaut, l’effet n’a lieu qu’à l’intérieur du PostProcessVolume, mais on peut le configurer comme étant “unbound”
  • Alors, typiquement, on le cache sous le plancher et on s’assure d’activer “Infinite Extent (Unbound)

  • Les paramètres utilisées typiquement, par exemple pour une exposition constante non adaptive:
    • Exposure Metering Mode : Manual
    • Exposure Compensation: autour de 10
  • Bloom:
    • Preferred Method : Convolution pour plus de réalisme
    • Intensity : à vous de choisir
    • Convolution donne des effets plus réalistes, voyez l’effet de bloom “convoluted” sur le soleil
  • Et pour la fameuse aberration chromatique typique des lentilles physiques, c’est-à-dire une décomposition de la lumière blanche en plusieurs bandes de couleurs:
  • Lens flare
  • Color grading
    • Vous pouvez jouer ici avec la température et la tinte de celle-ci
    • Dans Global, vous pouvez contrôler la saturation, le contraste, le gamma, le gain

HDRIs

  • Drag and drop ton HDRI
  • Dans les plugins, activer HDRI Backdrop
  • Redémarrer Unreal
  • Vous avez maintenant HDRIBackdrop

☝🏼

Pour activer le panneau de gauche, c’est Window → Place Actor 😄

God Rays

Beam Skeletal Mesh

  • Show Engine Content
  • Cherchez pour Beam
  • Drag and drop de S_EV_SimpleLightBeam_03 dans votre Content à vous
  • Copiez le Material de cet objet et faites-en une instance ou une copie dans votre Content
  • Modifiez à votre guise
  • Drag and drop de cet Actor dans votre scène
  • Jouez avec les paramètres (surtout la taille et direction) et ceux de son Material

Light behaviour in Volumetric Fog

  • Le Volumetric Fog de votre Scène (Exponential HeightFog)
  • Le secret ici est de jouer avec les paramètres de chaque Light Source
    • Intensity
    • Volumetric Scattering Intensity
    • Vous aurez sans doute à ajuster r.VolumetricFog.GridPixelSize et la réduire à 2 (par défaut elle est à 8).

Directional Light Shafts

  • Dans les propriétés de votre DirectonalLight, dans la section Light Shaft
    • Activez Light Shaft Occlusion
    • Activez Light Shaft Bloom
    • Jouez avec les paramètres et la direction de la lumière (Ctrl-L)

Éclairage d’intérieur

  • Allez chercher Cigar Room dans Fab

  • Ouvrez la Map Cigar Room
  • On va s’amuser à l’éclairer correctement en fonction de l’ambiance qu’on veut créer

Lien vers l'original

# Cours 13

Banque de cours - La lumière - Éclairage 2

La lumière - Éclairage 2

Éclairage de produits

  • Dans le logiciel de votre choix, désignez un backdrop gris-blanc de votre choix ayant la forme suivante:
    • Shade smooth
    • Material: un gris-blanc diffus, roughness à 1.

☝🏼

Les unités dans Blender sont typiquement des m, dans Unreal, des cm. Donc pas besoin de le faire trop gros, 10x10 m c’est amplement suffisant.

  • Exportez-le en FBX, nommez-le Backdrop et importez-le dans Unreal Engine.
  • Allez chercher Shoe Hiking 01 dans Fab

  • Ou n’importe quel autre soulier ou produit qui vous plaît :)

  • On va éclairer la scène avec

    • Split viewport and bookmarking one of them
    • Seamless Backdrop
    • using multiple viewports
    • Tri-light
    • using rectangular lights with Barn Door Angles and Length control
    • Background popping out
    • Channels to control cast shadow
    • Attenuation radius
    • Piloting a CineActor
    • Focus method = tracking on the shoe

Éclairage de personnages

  • Allez chercher Paragon: Countess dans Fab

  • On va éclairer le personnage
    • The Rembrandt triangle
    • Tri-light
    • Couleurs des lumières
    • Props
    • Backdrop light
    • Seamless Backdrop
    • Depth of Field
    • Fog

Material de type Light Function

  1. Using Source texture with a Rect Light

  2. Create a material, domain should be light function

  • Connecte Time to multiply to sine to another multiply to the emissive color to create a flicker effect:

Éclairage sous l’eau (à venir)

  • TBD

Exercices Reproduire l’éclairage d’une scène de film !

Lien vers l'original

# Cours 14

Projet intégrateur

# Cours 15

Projet intégrateur

# ≤ 2024

Blender - Blender I - Intro à Blender

# Blender I - Intro à Blender

Cours 01 (3h) - Installation et configuration de Blender, Intro à Blender (voir matière commune)

  • Voir matière commune
    • Historique

    • Installation

    • Explication Compositor, hdri, cycles, eevee

    • Activer Cuda et la carte graphique dans Preferences

Intro aux G, R, S, aux vues orthogonales; un peu de toon shading Télécharger le fichier blender suivant:

Devoir

  • Suivre les 3 tutos suivants si vous n’avez jamais touché à Blender:


Cours 02 (3h) - Modélisation et Toon shading

  • Les bases de la modélisation
    • Les viewports
    • Les trois transformations, ou les 3 mondes (local, global, caméra)
    • Le 3D cursor
    • Les loop cuts
    • Quelques Modifiers importants
    • Bevel
      • Edges
      • Vertex
    • Normales à la surface
    • Drivers (e.g. rotate)
    • Alt-Ctrl-0 to setup Camera View
      • Graph Editor for 360 rotation → Noise Modifierg

Devoir 1

  • Suivre le tuto suivant. Le fichier startup se trouve ici: https://drive.google.com/file/d/1fPsQBTs8mHAq2VaOV34EwG_FDwxwVlQp/view?usp=sharing
  • Notes importantes:
    • Pour les vues orthogonales (Front, Side, Top), je préfère les touches 1, 3 et 7 du pavé numérique à la touche tilde “~”
    • 10:42
      • Double-clic sur un Edge ne sélectionne pas la boucle (loop), c’est sans doute un shortcut qu’a configuré Christopher 3D sans s’en rappeler.
      • Pour sélection une loop, Alt-Left click.
    • 10:46
      • Si le menu Dissolve Edges n’apparaît pas sous le menu Edges, c’est parce qu’on activé les Pie Menus.
      • Avec la loop sélectionnée, faites plutôt X puis choisir Dissolve Edges.
    • 29:11
      • Le Knife tool (k), dans mon cas, n’a pas fait de loop cut faisant tout le tour de l’objet. Aucune idée pourquoi. Alors j’ai sélectionné le Vertex du début et celui de la fin et j’ai fait “J” (Connect Vertex Path).
    • 31:50
      • Pour Merge Vertices, dans notre cas, il faut faire M et le Pie Menu va apparaître.
      • Tant que vous avez des quad-gons plus ou moins équilibrés, pas obligé de faire exactement comme lui.
    • 49:18
      • Zarbi, il a le Base Gold Rim de sélectionné, mais le mirror modifier s’applique au base. Mais bon, au Base, il faut un Mirror Axis le long de X et Y avec Bisect X et Y et Flip Y, pour le base Gold Rim, juste Mirror Axis X et Y.
    • 01:03:20
      • C’est slash (/) pas backslash () pour isoler un objet
    • 01:14:40
    • 01:21:35
      • Ne pas oublier, pour sélectionner un loop au complet, c’est Alt-clic. Pour en sélectionner un 2e, Shift-Alt-clic.
    • 01:28:30
      • Ah oui, j’ai désactivé “Align to View” (Edit → Preferences → Align to) et remis à Align to “World”, ça me rendait dingue :)
      • Je préfère savoir que l’objet sera crée et aligné selon les axes du World et aligner moi-même l’objet ensuite à ce que je veux.
    • 01:29:39
      • La touche “.” (pas celle du pavé numérique, l’autre) est super pratique en mode Edit. Par exemple pour faire un Scale par rapport à un pivot qui n’est pas le curseur 3D
      • On aurait pu faire aussi S puis Z pour contraindre la mise à l’échelle à l’axe des Z seulement
    • 01:31:33
      • Arêtes Manifold vs. Non-Manifold dans Blender
        • Arêtes manifold :
          • Ce sont des arêtes appartenant à un maillage bien défini et fermé, où chaque arête est connectée exactement à deux faces.
          • Cela signifie que la géométrie est solide et peut être utilisée pour des opérations comme l’impression 3D ou les simulations physiques.
        • Arêtes non-manifold :
          • Ce sont des arêtes problématiques qui indiquent la présence de trous, de faces internes ou de géométrie détachée. Elles peuvent apparaître dans les cas suivants :
          • Arêtes ouvertes (qui ne sont attachées qu’à une seule face ou à aucune).
          • Faces internes (faces cachées à l’intérieur du modèle).
          • Arêtes connectées à plus de deux faces (comme dans une géométrie qui s’intersecte).
        • Sélectionner les arêtes Manifold dans Blender
          • Pour sélectionner les arêtes non-manifold, vous pouvez utiliser :
            • Mode Édition → Menu Sélection (Sélection > Sélectionner tout par attribut > Non-manifold).
            • Raccourci : Shift + Ctrl + Alt + M.
    • 01:40:53
      • Quand vous ajoutez le Mirror Modifier, assurez-vous qu’il soit, dans le stack, avant le Smooth by Angle. En d’autres termes, on Bevel, on Mirror et seulement ensuite on Smooth by angle.
    • 01:46:22
    • Vous avez remarqué qu’il a oublié de modéliser la plaque dans son tuto. À vous de jouer :)

  • Instructions (pour les Game Arts seulement):
    • Sur la plaque dorée, inscrivez votre nom. Trouvez comment 🙂
    • Surprenez-moi, soyez créatives et créatifs
    • Difficultés en anglais? Qui pourrait vous aider? Et si vous le faisiez en groupe?
    • Sur le drive, remettre l’image rendered en Cycles.
  • critères d’évaluation:
    • Créativité
    • Capacité à l’entraide
  • À remettre:

Résultat minimal attendu

⚠️

P.S.: vous n’aurez pas tout les points si vous ne faites que le minimum.
Ici, j’ai ajouté un peu de Bloom ainsi qu’une distortion de la lentille (vous avez ça dans le compositor d’un fichier défaut). J’ai également transféré le denoise au Compositor.

Cours 03 (3h) - Logo reveal et un peu de nodes

Banque de cours - Logo reveal

Logo reveal

  • Modélisation d’après image de référence
    • Utilisation de courbes, ou primitives
    • Extrusion
  • Physics sim
    • Force Field négatif
    • Particules Eco Spheres
Lien vers l'original

Node stuff

  • UV mapping
  • Quelques éléments de shading
    • Image texture
    • Node Wrangler
    • Texture coordinates (Ctrl-T)
    • Color Ramp
    • Gestion des spaghetti
      • Grouping
      • Ajout de reroute
      • Retrait d’un spaghetti
      • Click socket then drag

Banque de cours - Devoir

Devoir

  • Aucun
Lien vers l'original

Cours 05 (3h) - Animations vers Unity TBD

Devoir 1 (GA seulement) TBD

Cours 06 (3h) - Raycasting et autres trucs intéressants TBD

Cours 07 (3h) - Intro aux Sim Nodes

Devoir

  • TBD

Cours 08 (3h) - Animations et Game Engines

Banque de cours - Transfert de shape keys de Vertex vers Shape Blends (format mdd)

Transfert de shape keys de Vertex vers Shape Blends (format mdd)

  • Une technique pour exporter une animation geo nodes ou par modifiers (e.g. Ocean ou Wave Modifier) de Blender vers Unity,

  • Cette technique fonctionne bien lorsqu’il s’agit, un peu comme les VAT (Vertex Animation Texture), de modifier les vecteurs des vertices sans en ajouter ou en retirer.

⚠️

Il est important de choisir un frame rate adéquat. On va choisir, ici, 60 fps (dans les paramètres Output).

  • Créer un Plane et ajoutez un Ocean Modifier.

  • Dans les paramètres Waves, mettre l’échelle à 2.5 et le “Choppiness” à 2 pour avoir des vagues plus hautes et plus cassées.
  • Pour que que le Blend Shape fonctionne dans Unity, il faut une animation avec des keyframes.
  • Keyframer le time à 0 au Frame 1, puis à 10 par exemple, au frame 250.
  • Assurez-vous que l’interpolation est linéaire et qu’il n’y a pas de Ease-In ou Ease-Out (Sélectionner tous les keyframes, ou tout les points dans le graph editor, cliquer-droit et choisir Interpolation Mode → Linear et Easing Type → Automatic Easing).

  • Installer et activer l’add-on “NewTek MDD format” et l’activer.

  • Le format NewTek MDD (Motion Designer Data) est un format de fichier d’animation basé sur l’utilisation de shape keys utilisé qui permet de stocker les données de déplacement de vertex dans une animation 3D. Il a été développé à l’origine pour LightWave 3D, un logiciel de modélisation et d’animation de NewTek, mais il est aussi utilisé dans d’autres logiciels 3D comme Blender, Maya (via des plugins), Houdini, etc.

  • Le fichier .mdd contient les positions de tous les sommets d’un objet 3D à chaque frame de l’animation. (Ça ressemble au textures VAT hein!). Cela permet de :

    • Transférer des animations précises (notamment des simulations complexes comme des cloths, fluides ou destructions) entre différents logiciels.
    • Jouer une animation en “bake”, c’est-à-dire sans avoir besoin des armatures, simulations ou contraintes d’origine.
    • Faciliter le rendu dans des moteurs externes ou pipelines complexes.
  • Structure typique d’un fichier .mdd :

    • Nombre de points (sommets)
    • Nombre de frames
    • Pour chaque frame : une liste de positions (x, y, z) pour chaque sommet
  • Sélectionner le Plane et faire File → Export → “Lightwave Point Cache (.mdd)”. Ce sous-menu a été ajouté par l’add-on qu’on vient d’activer.

  • Appliquer le modifier. L’animation va disparaître, mais elle est, maintenant, frame par frame et vertex par vertex, dans le fichier .mdd.

  • Sélectionner encore une fois l’objet inanimé et sans modifiers et faire “File → Import → “Lightwave Point Cache (.mdd)” et choisir le fichier qu’on a exporté durant l’opération d’export.

  • Faites Play, l’objet est à nouveau animé, mais cette fois-ci avec des keyframes pour chaque frame et pour chaque Vertex!

  • Maintenant, il vous suffit d’exporter l’objet en format FBX. Ne pas oublier d’activer “Limnit to: Selected Objects” et d’activer le checkbox “Animation”.

  • Ok, on passe à Unity.

  • Unity est capable de comprendre les shape keys (qu’il appelle Blend Shapes) mais il faut écrire un script pour looper à travers tous les blend shapes. Le script est inspiré de ceci, qu’on peut trouver dans la doc de Unity 6:

https://docs.unity3d.com/Manual/BlendShapes.html

  • Dans Unity, drag and drop le FBX dans les assets puis dans la scène.
  • Créer un nouveau script (+ en dessous de Project, “Monobehaviour script”) et le nommer ShapeBend.cs
  • Drag and drop le FBX dans la scène (sous Hierarchy)
  • Associer à cet objet le script suivant (appelez-le “ShapeBend.cs” par exemple) que vous aurez écrit. La bonne nouvelle, c’est que c’est le même script pour n’importe quel animation généré par cette méthode.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class NewMonoBehaviourScript : MonoBehaviour
{
 
    SkinnedMeshRenderer skinnedMeshRenderer;
    Mesh skinnedMesh;
    int blendShapeCount;
 
    int playIndex = 0;
 
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        skinnedMeshRenderer = GetComponent<SkinnedMeshRenderer>();
        skinnedMesh = GetComponent<SkinnedMeshRenderer>().sharedMesh;
        blendShapeCount = skinnedMesh.blendShapeCount;
    }
 
    // Update is called once per frame
    void Update()
    {
        if (playIndex > 0) skinnedMeshRenderer.SetBlendShapeWeight(playIndex - 1, 0f);
        if (playIndex == 0) skinnedMeshRenderer.SetBlendShapeWeight(blendShapeCount - 1, 0f);
 
        skinnedMeshRenderer.SetBlendShapeWeight(playIndex, 100f);
        playIndex++;
 
        if (playIndex > blendShapeCount - 1) playIndex = 0;
    }
}
 
  • Ajouter un Empty à la scène et lui associer le code suivant (Appelez-le ”FpsLock.cs” par exemple). Ce code impose le même frame rate que celui utilisé dans Blender (donc modifier la valeur en fonction de votre animation Blender).

  • Si vous ne le faites pas, l’animation va tourner trop vite.

🔥

Ceci est un quickfix. Idéalement, on impose pas de frame rate, mais on contrôle la durée de l’animation.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class FpsLock : MonoBehaviour
{
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        Application.targetFrameRate = 30;
    }
 
    // Update is called once per frame
    void Update()
    {
        
    }
}

  • Jouez la scène. Badabeen, badaboon! (Ajouter un component “Free Camera” à l’objet “Main Camera” si vous voulez vous promener dedans en mode “Play”).

  • Key stuff:

    • Limitation: la géométrie doit être la même en termes de nombre de vertex. Si l’animation dans Blender on ajoute ou en enlève, cette méthode ne fonctionnera pas.
      • Ça fonctionne donc avec, par exemple, Wave Modifier, Lattice Modifier, cloth simulation, etc.
      • Pour le geo nodes, ça ne fonctionne pas si les geo nodes ajoutent de la géométrie par rapport à l’objet de base. Et pourtant…
    • FpsLock C# file associated with an empty in the scene, frame rate should be the same as the one set in Blender
    • Enable mdd add-on in Blender
  • Une manière brillante de rendre votre loop “seamless”:

Lien vers l'original

Simulation Nodes - Particle Sim

Préparation

  • Aller chercher le fichier startup ici (une immense merci à Antoine Deslandes - Discord Delta Uniqx pour le modèle et l’animation):
    https://drive.google.com/file/d/1ctWQxCBzj_rKohLYOKKyazLhL1xrnJ2i/view?usp=sharing

  • Dans ce fichier, un robot a été modélisé et animé. Les morceaux de robots (les Québécois de ma génération verront la référence :D) se trouvent dans une collection nommée “Robot parts”

  • On voudrait expérimenter avec de la simulation de particules (la première simulation intégrée au Geo Nodes) à partir de la géométrie du robot.

  • Comme le robot est composé de plusieurs objets distincts, les amener à la main en tant que “Object Info” dans un système de geo nodes serait fastidieux (il y a une centaine objets!).

  • Commençons par le créer un objet pour avoir un système de geo nodes. Un Plane suffit.

⚠️

Assurez-vous de ne pas être dans la collection “Robot parts”!

  • Aller dans le système de Geo Nodes et faire New en s’assurant que le Plane est sélectionné. Nommer le geo nodes “Particle Sim” et l’épingler.

  • Maintenant on va écrire un script Python qui va aller chercher tous les objets de la collection “Robot parts”, les ajouter de manière ordonnée avec full cable management en tant que noeuds Object Info et les connecter à un Join Geometry.
  • Aller dans l’espace de travail “Scripting”.
  • Faites “Text → New”
  • Copier coller le code suivant:
import bpy
 
def add_object_info_nodes_from_collection(collection_name):
    # Get the active object and its Geo Node tree
    obj = bpy.context.active_object
    if not obj or not obj.modifiers or obj.modifiers[-1].type != 'NODES':
        print("No active object with a Geometry Nodes modifier selected!")
        return
    
    geo_nodes = obj.modifiers[-1].node_group
    nodes = geo_nodes.nodes
    links = geo_nodes.links
 
    # Find or create a Join Geometry node
    join_node = None
    for node in nodes:
        if node.type == 'JOIN_GEOMETRY':
            join_node = node
            break
    if not join_node:
        join_node = nodes.new(type='GeometryNodeJoinGeometry')
 
    # Load the collection
    collection = bpy.data.collections.get(collection_name)
    if not collection:
        print(f"Collection '{collection_name}' not found!")
        return
 
    # Create a Frame node to hold all Object Info nodes
    frame = nodes.new(type='NodeFrame')
    frame.label = f"{collection_name} Objects"
    frame.name = f"{collection_name}_Frame"
    frame.width = 400
 
    # Grid layout settings
    spacing_x = 200  # Horizontal spacing between columns
    spacing_y = -200 # Vertical spacing between rows
    nodes_per_column = 10
 
    created_nodes = []
 
    max_col = 0
    max_row = 0
 
    for index, obj_in_collection in enumerate(collection.objects):
        # Calculate grid position
        col = index // nodes_per_column
        row = index % nodes_per_column
 
        max_col = max(max_col, col)
        max_row = max(max_row, row)
 
        x = -600 + (col * spacing_x)
        y = row * spacing_y
 
        # Create Object Info node
        obj_info = nodes.new(type='GeometryNodeObjectInfo')
        obj_info.parent = frame
        obj_info.location = (x, y)
        obj_info.inputs['As Instance'].default_value = False
        obj_info.inputs['Object'].default_value = obj_in_collection
 
        if hasattr(obj_info, 'transform_space'):
            obj_info.transform_space = 'RELATIVE'
 
        # Create a Reroute node
        reroute = nodes.new(type='NodeReroute')
        reroute.location = (x + 150, y)
 
        # Connect Object Info to Reroute
        links.new(obj_info.outputs['Geometry'], reroute.inputs[0])
 
        # Connect Reroute to Join Geometry
        links.new(reroute.outputs[0], join_node.inputs['Geometry'])
 
        created_nodes.append(obj_info)
 
    # Calculate Frame Size (optional: Blender does it automatically if you move nodes manually)
    frame.location = (-650, 150)
    frame_width = (max_col + 1) * spacing_x
    frame_height = (max_row + 1) * abs(spacing_y)
 
    # Move Join Geometry node to right of Frame
    join_node.location = (-600 + frame_width + 300, 0)
 
    print(f"Added {len(created_nodes)} Object Info nodes from collection '{collection_name}', framed, with reroutes, 10x10 grid, Join Geometry neatly positioned.")
 
# Direct call (no popup)
add_object_info_nodes_from_collection("Robot parts")
  • En gros, le script crée des Object Info pour chaque objet trouvé dans la collection “Robot parts”, les configure en mode “relative”, les grouper dans un Frame nommé “Robot Parts Objects” et les connecte à un noeud “Join Geometry”.

  • Déplacer le noeud Group Output assez loin à droite

  • Cliquer sur le bouton “Run script” (le bouton “Play” du Script Editor.

⚠️

J’ai configuré mon Scripting workspace pour qu’on voit à droite le 3D Viewport ainsi que le Geo Node.
Aussi, il se peut que le système de nodes crée cache les noeuds Group Input et Group Output. Comme les Object Info et le Join Geo sont sélectionnés, vous pouvez les déplacer (G then move with the mouse).

  • On a terminé avec le script. Revenir au workspace Geometry Nodes.

  • Connecter la sortie de Join Geometry à l’entrée Group Output. Déconnecter Group Input (on ne veut pas voir le Plane).

  • Cacher les objects Robot Parts dans l’Outliner, on veut voir le résultat du système de geo nodes seulement.

  • Faites Play dans le timeline!

  • Comme les objects sont la géométrie du robot tel qu’animé, l’animation est conservée dans la version geo nodes. Chouette non?
  • On est prêt pour de la simulation de particules!

Simulation 1 - Onion Skin shadow trail

  • Ajouter une Simulation Zone et connecter la sortie du Join Geomtery à l’entrée d’un 2e Join geometry qui, lui, se trouve dans la simulation Zone.

  • Faites Play.

  • Que constatez-vous?

  • That’s right! Les geo nodes, sans Simulation zone, sone “stateless”, c’est-à dire que tout est calculé à chaque frame.

  • Mais avec un simulation Zone, tout d’un coup, les frames précédents sont accumulés! On vient de créer un “Stateful” machine!

  • Ok, et si on voulait retenir seulement, disons, les 5 frames précédents seulement?

  • On veut effacer tout ce qui est plus ancien que “n” frames. Comment faire?

  • On va commencer par garder en mémoire la géométrie courante:

  • Maintenant, il nous suffit de retirer du Join Geometry de la Simulation Zone, les géométries des frames plus petits qu’une certaine distance du Frame courant.

  • Ici, on “Delete Geometry” tout ce qui fait partie de “Selection”.

  • Ce qui aliment le socket Selection du noeud Delete Geometry, c’est le noeud Compare → Less than, qui évalue la valeur de “Frame_courant” (dans le noeud Named Attributed) par rapport au No de frame de l’animation (Scene Time) moins une certaine valeur, ici 4.

  • Ce que ça fait effectivement, c’est effacer toutes les géométries dont le No de frame est plus petit que le frame courant moins 4.

  • L’effet est un trail Onion Skin.

  • Je réalise que je devrais nommer “Frame_courant” à “stored_frame” plutôt, car il n’est plus courant dès qu’il ne l’est plus :) Je le fais de suite:

⚠️

Ah oui, si vous changez quelque chose dans la simulation zone, faut revenir au frame 1 pour recalculer la cache et voir l’effet du chngement.

Lien vers l'original

Blender - Blender II - Tooling Blender I

# Blender II - Tooling Blender I

🙏🏼

Plusieurs des simulations présentées dans ce cours sont basées sur l’immense travail de Stephen Pearson et son livre “Learn Blender Simulations the Right Way”, avec son aimable permission.

Sa chaîne youtube: https://www.youtube.com/@BlenderMadeEasy

Son livre: https://www.packtpub.com/product/learn-blender-simulations-the-right-way/9781803234151

Son livre en format PDF: https://drive.google.com/file/d/131CZ3yBDeeVickdW57V3m_6Fu2f206Wx/view?usp=sharing

Un immense merci à toi Stephen Pearson pour ton aimable permission d’utiliser ton livre, with gratitude and admiration!

Banque de cours - Mantaflow, Domaines, Flow, Effectors, ma première simulation feu

# Mantaflow, Domaines, Flow, Effectors, ma première simulation: feu

Mantaflow Mantaflow est le simulateur de dynamique des fluides (liquides ou gazeux) adopté par Blender à partir de la version 2.82. Mantaflow a d’abord été développé en 2009 par le Computer Graphics Laboratory de l’Institut fédéral des technologies de Zurich. Il est dorénavant maintenu et développé par l’Université Technique de Munich.

📌

“Replay” ne fonctionne que lorsque le mode de synchronisation de lecture est réglé sur “Play Every Frame”. Si vous avez besoin d’utiliser “Frame Dropping” ou “Sync to Audio”, envisagez d’utiliser les options “Modular” ou “All” ci-dessous.

Ma première simulation

Le domaine

  • Créer un cube (⇧ A → Mesh → Cube)

  • Avec le cube sélectionné, mise à l’échelle selon l’axe des Z multiplié par 2 (s → z → 2 → ↩)

  • Avec le cube sélectionné, appliquer la mise à l’échelle (Apply Scale) : ⌃ A → Scale

  • Créer une sphere (⇧ A → Mesh → UV Sphere)

  • Avec la sphère sélectionnée, scale 0.5 (s → 0.5 → ↩)

  • Avec la sphère sélectionnée, appliquer la mise à l’échelle (Apply Scale) : ⌃ A → Scale

  • Passer à la vue de face (Numpad 1)

  • Avec la sphère sélectionnée, déplacer à la base du cube (g → z → -1.4 → ↩)

  • Sauvegardez votre scène dans un dossier nommé “Ma première simulation”, intitulez le ficher .blend “Ma première simulation.blend”. Il est important de sauvegarder le fichier dans son propre répertoire dédié avant de créer la simulation car sinon les données de la cache seront générées au mauvais endroit.

  • Avec le cube sélectionné, activer la simulation “Fluid” dans les propriétés physiques

  • Choisir le type “Domain”. Les frontières du cube constituent maintenant la limite du domaine à l’intérieur duquel sera calculée la simulation.

  • Vous remarquerez qu’un petit cube apparaît maintenant à la base du cube, indiquant qu’il s’agit d’un domaine de simulation. Ce cube est en fait un Voxel et sa taille détermine la “résolution” de la simulation

  • Avec le cube sélectionné, assurez-vous que le checkbox “Adaptive Domain” est activé

  • Sous “Cache”, choisissez 150 comme nombre de frames (Frame Start = 1, End = 150). Assurez-vous que le type de cache est “Modular” au lieu de “Replay”

  • Avec le cube sélectionné, Aller dans Material et cliquer sur “New”.

  • Nous ne voulons pas un “Principled BSDF” mais bien un “Principled Volume”.

  • Choisir la couleur de la fumée, régler la densité à 8 et le “blackbody Intensity” à 7

  • Avec le cube sélectionné, passer à l’espace de travail “Shading”

  • Choisir “Object” et s’assurer que la sortie du Principled Volume Shared soit connecté à l’entrée “Volume” et non pas “Surface” du noeud “Material Output”

  • Sélectionner la sphère, aller dans les propriétés Material, choisir New Material (“Principled BSDF” sera sélectionné par défaut) et choisir une couleur orangée comme couleur de base

Le fluide (feu + fumée)

  • Maintenant passons au feu. Sélectionner la sphère, et choisir “Fluid” dans les propriétés physiques. Choisir comme type “Flow”

  • Changer le “Flow Type” pour “Fire + Smoke”. “Flow Behavior” devrait être “Inflow”. Fixer “Fuel” à 1.3 et dans la section “Flow Source”, “Surface Emission” devrait être à 0.5

  • Dans le timeline, s’assurer que le dernier Frame de l’animation est bien 150.

  • Sélectionner le Cube. Nous somme prêt à bake la simulation! Appuyer sur le gros bouton “Bake Data” dans les prorpiétés physiques, sous la section “Settings”.

  • Cliquer sur “Play” dans la barre d’animation pour voir le résultat!

La caméra

  • En vue de face (Front View: Numpad 1), ajouter une caméra (⇧ A → Camera → Camera).

  • Passer à la vue de côté (Numpad 3) et déplacer la caméra vers la gauche de 10 mètres (g → y → -10)

  • Passer à la vue Caméra, vous devriez voir ceci

  • Nous n’avons pas besoin d’éclairage car nous avons mis en place un environnement HDRI. Mais réduisons l’intensité de cet environnement un peu.

  • Dans la propriété “World”, réduisez la force (Strength) à 0.2.

Amélioration de la qualité

  • Taille des voxels. Si l’on augmente la “Resolution Division”, le voxel rapetissera, indiquant un plus grand nombre de voxels dans le domaine et conséquemment une plus grande résolution de la simulation.

  • Cela dit, plus la division de résolution est grande (i.e. plus la taille des voxels est petite), plus la cache occupera de l’espace disque et plus la simulation prendra du temps à cuire.

📌

La simulation est composée de voxels, une grille de cubes qui compose le domaine, et la résolution de cette grille est le paramètre principal pour une meilleure qualité. Veuillez noter que si vous doublez la résolution, vous obtenez en réalité 8x les cellules (et le temps de cuisson) car elle double dans 3 directions.

  • Avec le cube sélectionné, dans les propriétés physiques, cliquer sur le bouton “Free Data” pour effacer la cache de la simulation.
  • Augmenter la division de résolution (Resolution Division) à 64.
  • Déselectionner “Adaptive Domain”.
  • sous la section “Fire”, Réduire le “Reaction Speed” à 0.5. Ce paramètre contrôle la hauteur des flammes. Plus la valeur est faible, plus les flammes seront hautes.
  • Sous cette même section, augmenter la “Vorticity” à 0.7.
  • Cliquer sur “Bake Data”. Cela devrait prendre plus de temps et la cache sera plus grande. Mais le résultat plus beau également!

Le rendu d’une image

  • Choisissez un frame sur le timeline où la simulation est visuellement intéressante (e.g. Frame 60)
  • Dans le menu “Render”, choisir “Render Image”
  • Une fois le rendu terminé, choisir le menu “Image → Save” et sauvegarder l’image sous le nom “Frame 60.png” dans le même dossier que celui de votre animation.

Le rendu de l’animation sur notre machine

  • Dans la propriété “Output”, section “Output”, choisir “//” pour le dossier (cela veut dire le même endroit que là où se trouve le fichier .blend). Pour File Format, choisir “FFmpeg Video”. Choisir “MPEG-4” comme “Container” dans la section “Encoding”. Enfin dans la section “Video”, choisir le codec “H.264”.
  • Choisir le menu “Render → Render Animation”.
  • “Patience et longueur de temps valent mieux que force ni que rage”…

Devoirs

  • Installer Sheep-It Render Farm
  • Suivre les 3 tutos suivants si vous n’avez jamais touché à Blender:


Lien vers l'original

Banque de cours - Simulation de tissu et objets gonflables

# Simulation de tissu et objets gonflables

Bon, d’accord…

  • Si vous voulez absolument les Gizmos, c’est par ici:
  • Et pour le curseur à l’origine du monde (le fameux ⇧ - clique droit de la souris que vous avez en mémoire musculaire Maya et qui vous fait déplacer le curseur), c’est par ici (ou alors ⇧ S → Cursor to World Origin):

Un peu de théorie La simulation de tissu est l'un des aspects les plus difficiles de la 3D; il s’agit en effet d’un élément du monde réel simple en apparence que l'on tient pour acquis, mais qui a en réalité le résultat d’interactions internes et environnementales très complexes (à ce sujet, si vous voulez apprendre à dessiner de manière réaliste, dessinez des drapés!). Le tissu est généralement modélisé comme un maillage 2D pour simuler des objets du monde réel tels que les tissus, les drapeaux, les bannières. Et pourtant, le tissu peut aussi être utilisé pour modéliser des objets 3D tels que les ours en peluche, les oreillers, les ballons, ou les balles. Le tissu interagit avec et est affecté par d'autres objets en mouvement, le vent et d'autres forces, les points de tension, la texture dudit tissue, la gravité, ainsi qu'un modèle aérodynamique général. Not an easy thang to simulate.

La physique du tissu est simulée avec des ressorts virtuels qui relient les sommets (vertices) d’un maillage (mesh). Il existe quatre types de ressorts qui contrôlent la manière dont le tissu se plie:

Ressorts de tension (bleu), ressorts de compression (rouge), ressorts de cisaillement (shear) (cyan), et ressorts de flexion angulaire (bending) (vert).

Ressorts de tensionContrôle la rigidité du tissu.
Ressorts de CompressionContrôle la force requise pour compresser, plier ou froisser le tissu.
Ressorts de cisaillement (Shear)Contrôle la déformation angulaire du tissu.
Ressorts de flexion angulaire (Bending)Contrôle la résistance du tissu au pliage ou au froissement.

Un drapeau qui flotte au vent

Modélisation et simulation

  • Ouvrir nouveau projet Blender (File → New → General) dans un dossier intitulé “Drapeau”
  • Copiez une image dans votre dossier “Drapeau” (par exemple celle-ci: https://drive.google.com/file/d/1H51xBe3DCgpHPHMArblzj9WcycXGrR70/view?usp=sharing)
  • Créer un plan, le tourner de 90 degrés par rapport à l’axe des X
  • Il est très important de subdiviser le plan d’abord avant de lui donner une forme plus rectangulaire d’un drapeau, sinon les subdivisions ne seront pas carrées et cela créera de drôles de comportements lors de la simulation.
  • Avec l’objet toujours sélectionné, passer en mode “Edit” (Tab → Edges)
  • Ajoutons de la géométrie à l’objet. Cliquer droit sur l’object en mode Edit et choisir subdivide.
  • Ouvrir le menu des paramètres de la subdivision (en bas à gauche du viewport)
  • Choisir 40 pour la valeur de “Number of Cuts” puis faire ↩ et revenir en mode objet (Tab → Object)
  • Maintenant on peut rendre le carré rectangulaire et les subdivisions seront correctes. Revenir en mode Object, S X 2 ↩ puis Apply Scale (⌃ A → Scale).

  • Remarquez que “Number of Cuts” = 40 donne une subdivision de 41 x 41 n-gons et non pas 40 x 40 n-gons car un Cut de 1 = 2 x 2 n-gons.

  • Avec l’objet sélectionné choisir les paramètres physiques et choisir “Cloth”

📌

Note, on peut choisir des tissus prédéfinis dans le petit menu hamburger à droite de l’intitulé “Cloth”, comme Cotton, Soie, etc. Mais nous allons régler nos paramètres manuellement.

  • Donc ne pas choisir de tissu prédéfini, choisir Cloth et nous allons régler les paramètres manuellement.

  • Si on fait “Play” de l’animation, on constatera que “tissu” tombe raide comme un bloc à cause de la gravité. Bon, c’est déjà ça.

  • Nous allons maintenant fixer un groupe de sommets (Vertices) de manière à ce que le tissu soit comme accroché (on l’accrochera à un poteau tout à l’heure)

  • Passer en mode Objet, édition des sommets (Tab → Edit Vertex). Dans les propriétés “Object Data”, ajouter un Vertex group et nommez-le “Accroche”.

  • Sélectionner les deux premiers sommets (Vertices) en haut à gauche et les deux derniers en bas à droite du mesh, puis cliquer sur le bouton “assign” dans le “Data property”, en s’assurant que le Vertex Group “Accroche” soit sélectionné. Cela va assigner les 4 sommets au groupe Accroche avec un poids de 1.

  • Pour vérifier que la chose a fonctionner, Sortir du mode Object et passer au mode Weight Paint:

  • Maintenant, revenons aux propriétés physiques et dans la section “Shape”, choisir le “Pin Group” “Accroche”.

  • Passer en mode Object et faire Play. Vous devriez constater que la gravité a toujours un effet sur le tissu, mais les points d’accroche ne bougent pas. Mais on remarque que le drapeau se traverse lui-même, normalement ce n’est pas normal. Il faut activer le “Self collision” afin que l’objet entre en collision avec lui-même.

  • Vous devriez maintenant constater que, si vous faites Play, l’animation est plus lente car Blender doit calculer les collisions de l’objet avec lui même.

  • Ajoutons un peu de vent. ⇧ A → Force Field → Wind.

  • On veux que le vent parte de la gauche vers la droite dans la direction de l’axe des X, derrière le drapeau. R Y 90 ↩ puis G X -5 ↩

  • Sélectionner le drapeau, passer à l’espace de travail Shader, choisir Object au lieu de World puis choisir New. Un Principled BSDF va apparaître. Ajouter une Image texture (⇧ A → Texture → Image Texture). Faire Open et choisir l’image Akira.jpg. Connecter la sortie Color de noeud Image Texture à l’entrée Base Color du Principled BSDF.

  • Passer en vue orthogonale frontale (Numpad 1), changer en mode “Material Preview” (Z → Material Preview) et changer la force du vent (entre 15 000 et 30 000 environ). Faire Play. Vous devriez voir l’effet du vent sur le drapeau.

  • Changer également la durée de l’animation à 500 frames. N’oubliez pas de mettre 500 pour le End Frame également dans la propriétés physiques, sous “Cache”.

  • Dans les Modifiers du drapeau, ajouter un Subdivision Surface (3 pour le viewport, 4 pour le render) et un “Smooth by angle”. S’assurer que le Smooth by angle soit le dernier en bas dans la pile (stack). Donc dans l’ordre, les modifiers devraient être : Cloth, Subdivision puis Smooth by Angle.

  • Il est temps de régler les paramètres de simulation du tissu. Dans les propriétés Physiques:

PropriétéValeurDescription
Quality Steps7Un peu plus élevée mais pas trop pour ne pas ralentir la simulation pendant qu’on travaille dessus. Au moment du rendu, on augmentera le steps à une bien plus grande valeur (e.g. 256).
Speed Multiplier1Le facteur influençant la durée du temps écoulé. 1 = “temps réel”.
Stiffness → Tension15Contrôle la rigidité du tissu.
Stiffness → Compression15Contrôle la force requise pour compresser, plier ou froisser le tissu.
Stiffness → Shear5Contrôle la déformation angulaire du tissu.
Stiffness → Bending2Contrôle la résistance du tissu au pliage ou au froissement.
Damping → Tension5Même chose que pour Stiffness, mais comme une suspension de voiture, ici Damping indique l’intensité avec laquelle les effets de stiffness s’estomperont. Par analogie, s’il n’y avait que le ressort dans une suspension de voiture (comme au début), la voiture oscillera beaucoup; l’amortisseur amorti les oscillations du ressort.
Damping → Compression5
Damping → Shear5
Damping → Bending2
Caching → Simulation Start1début de la simulation
Caching → Simulation End500Fin de la simulation.
Collision → Quality6Contrôle la qualité du calcul des collisions, autant avec l’objet lui-même qu’avec les autres objets. Évidemment, plus le chiffre est élevé, plus ça va coûter cher en calculs.
Object CollisionActivéOn veut que l’objet entre en collision avec les autres objets de manière réaliste.
Distance0.01
Self CollisionActivéOn ne veut pas que l’objet passe à travers lui-même.
Distance0.01
  • Le champ de force Vent donne une force constante dans une seule direction, le long de l’axe Z local de l’objet de force. La puissance de cette force est visualisée par l’espacement des cercles affichés et la taille de la flèche.
  • Pour le vent, les paramètres sont comme suit:
PropriétéValeurDescription
ShapePlaneLa forme selon laquelle le vent sera calculée
Strength30 000La puissance du vent
Flow1La facteur “vitesse” du fluide “air”. 1 = réaliste.
Affect → LocationOui
Affect → RotationOui
Noise Amount0.5Histoire de ne pas avoir un vent qui ne varie jamais.
Seed21Changer le seed changera la génération des nombres aléatoires
AbsorbtionOuiUne partie de l’énergie du vent est absorbée par les objets ayant la propriété Collision
Wind Factor1Le degré avec lequel l’énergie du vent est absorbée par des tissus
FalloffPas utiliséParamètres contrôlant le degré avec lequel la force du vent diminue avec la distance. Dans notre cas, ne pas le spécifier signifie que la force du vent ne diminuera pas, ce qui fera en sorte que la distance du Force Field par rapport au drapeau n’importera pas.
  • Dans les propriétés Render, choisir Cycles, retirer la transparence dans la section “Film”. En mode Render (Z → Rendered) vous devriez voir le HDRI.
  • Passer en mode Shading, choisir World au lieu de Object, diminuezl’intensité du HDRI à 0.7. Dans le preview, passer en mode Rendered, puis changer les valeurs de rotation Z et X de la texture Environment HDRI jusqu’à que vous ayez un point de vue satisfaisant:
  • Dans l’espace de travail “Layout”, ajuster un peu plus le point de vue, puis ajouter une caméra et faire ⌃ ⌥ Numpad 0 pour fixer la position de la caméra. S’assurer que le drapeau soit un peu vers le premier tiers à gauche du cadre de la caméra.
  • Passons maintenant à la texture du drapeau. Sélectionner le drapeau et passer en mode Shading. S’Assurer de sélection Object et non pas World. Vous devriez voir la texture Akira (ou l’image que vous aviez choisie au début).
  • Allons d’abord chercher des textures de tissu, une pour le maillage lui-même, l’autre pour des défauts de tissu, pour un peu plus de réalisme. Poliigon.com est super chouette, mais il y’en a des tonnes. Je vous en ai préparé deux, télécharger ces deux fichiers .zip dans un dossier que vous nommez “Textures” dans votre dossier Drapeau et y décompresser les fichiers .zip:
  • Nous avons déjà la couleur pour notre drapeau (l’image Akira), ce dont nous avons besoin, c’est de la texture de tissu, pas sa couleur. Dans Le shading Editor, ajouter une “Image Texture” et ouvrir le “Displacement” map 2K de la texture FabricCanvas001, en l’occurence le fichier FabricCanvas001_DISP_2K.jpg
  • Maintenant, on veut connecter cette texture à l’entrée “Normal” du Principled BSDF, mais pour ce faire, il faut passer à travers un Noeud Bump pour convertir l’entrée “Color” du Displacement Map en information de variation de la normale. Enfin, il faut connecter Color du displacement map à l’entrée “Height” du Bump, pas “Normal”. La couleur des connecteurs vous indiquent dans Blender si la connexion est compatible ou pas.
  • Par exemple, avec la connexion suivante, on constate que le bump map ne fonctionne pas, que le connecteur passe du jaune au violet et qu’on ne voit pas l’effet de la texture dans le rendu:
  • La texture est trop grande. Cliquer sur le noeud Displacement, faire ⌃ T pour, via le Node Wrangler, ajouter les coordonnées de la texture, et augmenter l’échelle (scale) à 5 sur les trois axes. On va également réduire l’intensité du bump node à 0.4 et mettre la distance a 0.5
  • Ajoutons maintenant des plis et défauts, en utilisant la texture “FabricCreasesWrinkles001”.
  • D’abord sélectionner dans le node editor la texture Displacement et faire ⇧ D pour le dupliquer.
  • Dans la nouvelle instance de l’image texture node, faire X pour retirer l’image actuelle et faire Open ou ouvrir le fichier normal map intitulé “FabricCreasesWrinkles001_NRM_VAR1_2K.jpg”.
  • Connecter ce nouveau noeud à un noeud “Normal Map” dont vous changez l’intensité (Strength) à 0.4. La sortie Normal de ce noeud Normal Map devrait être connecté à l’entrée “Normal” du Bump Node.
  • Maintenant, notre drapeau est trop mince, ajoutons un “Solidify Modifier”, mais s’assurer qu’il se trouve avant le dernier modifier intitulé “Smooth by Angle”.
  • Il est temps de créer le poteau. Revenir dans l’espace de travail “Layout”, en mode Solid, en vue orthogonale frontale (Numpad 1) et créer un cylinder (⇧ A → Mesh → Cylinder)
  • Dans les paramètres de création, changer le diamètre (Radius) à 0.03, la hauteur (Depth) à 4. Cliquer dans un endroit vide fera disparaître le menu des propriétés de création.

  • Sélectionner le cylindre derechef, et déplacer le à la gauche du drapeau et bien évidement le haut du cylindre doit être aligné à peu près avec le haut du drapeau.
  • Comme nous n’avons pas déplacé le drapeau suite à sa création, le cylindre devrait être aligné quand on regarde le tout en vue orthogonale d’élévation (Numpad 7). Vérifier que c’est bien le cas et corriger si nécessaire.
  • Ajoutons une sphère au bout d’une petite extrusion au sommet du poteau.
  • D’abord sélectionner le poteau, passer en mode édition “Face”, sélectionner la face du haut.
  • Faire “Inset” (I), déplacer la souris de manière à créer un cercle concentrique au diamètre extérieur du cylindre, puis faire Extrude dans l’axe des Z (E Z) et déplacer encore une fois la souris pour obtenir cette petite extrusion.
  • Ajoutons une petite boule au sommet du poteau et ce sera assez. ⌃ A → Mesh → UV Sphere. Donnez-lui un diamètre de 0.05 et déplacez-la au sommet du poteau.
  • Une petite texture métallique maintenant pour le poteau et la sphère. Sélectionner le poteau, et dans les paramètres “Material”, faire New pour un créer un Princpled BSDF. Nommer ce Material “Poteau”. Choisir une couleur gris-bleu, Mettalic à 1. C’est assez.
  • Maintenant sélectionner la sphère, est dans les paramètres Material, ne pas faire New mais choisir “Poteau” comme material. Les deux vont partager la même texture maintenant.
  • Cliquer droit sur le poteau et faire “Shade Smooth”. Même chose pour la sphère.
  • Le drapeau doit entrer en collision avec le poteau, il faut donc s’assurer que ce dernier ait la propriété physique “Collision”. Sélectionner le poteau, et choisir “Collision” dans les propriétés physiques:
  • Nous sommes prêts à faire un “Bake” de la simulation. Sélectionner le drapeau, aller dans les propriété “Physics” et augmenter la qualité (Quality Steps) à 128. Pour un rendu de production, augmenter la qualité à 256, 512, voire plus.
  • Augmenter également la qualité des collisions, dans la section “Collisions”, choisir 10 par exemple.
  • Dans la section “Cache”, mettre le End Frame à 120, le changer également dans l’animation, sinon à 500 frames, le calcul de la simulation va prendre trop de temps.
  • Cliquer sur Bake. C’est le temps d’une pause.
  • Faites Play en mode Render. Faites un rendu d’un des frames. C’est zoli quand même non?

Animation

  • On va quand même rendre ça cool, avec de la brume et la caméra qui tremble à cause du vent.

  • Commencer par créer un cube qui couvre toute la scène qui apparaît devant la caméra:

  • Ce cube servira de volume qui contiendra l’effet volumétrique de brume.

  • Dans le shading Editor, avec le cube sélectionné, s’assurer d’être en mode Object et faire New pour créer un nouveau Material.

  • Effacer le Principled BSDF et créer plutôt un noeud “Principled Volume”. Connecter la sortie Volume de ce dernier à l’entrée Volume du Material Output. Tout va devenir noir car le volume est très dense. Baisser la densité à environ 0.1.

  • Créer un noeud Noise Texture et un noeud Color Ramp; connecter la sortie Factor du Noise Texture à l’entrée Factor du Color Ramp puis connecter la sortie Color du Color Ramp à l’entrée Density du Principled Volume.

  • Faire ⌃ T en ayant le Noise Texture sélectionné pour rajouter des Mapping Coordinates. On veut les coordonnées du cube, donc connecter la sortie “Object” du noeud Texture Coordinates à l’entrée Vector du noeud Mapping.

  • Changer l’échelle du Noise Texture à 15 et déplacer la couleur noire du color ramp vers le milieu. Ici le Color Ramp agit comme un pinceau : la couleur noire complètement à gauche apparaîtra quand la valeur du facteur est 0, puis graduellement vers le blanc quand cette valeur se rapproche de 1.

  • Maintenant, on veut animer le mouvement de la brume. Pour ce faire, on va passer de 3D à 4D pour le Noise Texture, ce qui va rajouter la dimension temporelle “W”.

  • Augmenter le niveau de détail à 16 pour le Noise Texture.

  • Ce qu’on veut animer c’est la position X (déplacement vers la droite dans le sens du vent) et le paramètre W.

  • S’assurer, dans le layout Editor, d’être au Frame 1. Dans le Shading Editor, cliquer droit sur la coordonnée X du noeud Mapping et faire “Insert Keyframes”. Si vous avez déjà un keyframe à cet endroit, le sous-menu contextuel sera “Replace Keyframes” au lieu de “Insert Keyframes”.

  • Aller au frame 120, changer la valeur X à, disons 5, 10 ou 30, et faire “Insert Keyframes” derechef. Il faut jouer avec cette valeur jusqu’à ce que vous obteniez un effet satisfaisant (et c’est là qu’une carte graphique performante aide grandement!).

📌

Vous pouvez temporairement ajouter une section montrant le timeline dans le shading editor pour ne pas avoir à changer de layout à chaque fois que vous voulez déplacer la tête de lecture dans le timeline.

  • À bien y penser, je vais baisser l’intensité du HDRI à 0.4 au lieu de 0.7 (World dans le shading Editor, ou alors la propriété World dans la section des propriétés à droite). Vous savez comment faire.

  • Revenir au frame 1. Cliquer droit sur la coordonnée W et faire Insert Keyframes.

  • Aller au frame 120, changer la valeur de W pour, disons, 10, et faire encore une fois Insert Keyframes.

  • Woot woot! Maintenant, on va faire trembler la caméra.

  • En vue Layout, ajouter un workspace pour voir le Graph Editor. Sélectionner la caméra.

  • Au frame 1, faire I pendant que la caméra est sélectionnée et que la souris est dans le 3D viewport.

  • Sélectionner l’Axe des X du keyframe de la caméra dans “Object Transform” du Graph Editor. On peut ajouter des modifiers aux courbes!

  • Faire “N” dans le graph editor pour faire apparaître le “N” menu s’il n’est pas visible. Dans la section Modifiers, faire Add Modifier et choisir Noise.

  • Du bruit a été ajouté au mouvement selon l’axe des X de la caméra!

  • Changer l’échelle à 6-10 (Scale) du modifier pour un mouvement saccadé certes, mais pas débile mental.

  • Changer le depth à environ 5, cela donnera un aspect moins robotique au noise.

  • Vous pouvez jouer avec les paramètres, comme le strength si le noise est trop fort (je l’ai baissé à 0.7).

  • Vous pouvez ajouter des noise modifiers aux autres axes (Y et Z) si vous voulez, pour plus de réalisme.

  • Vous pouvez également animer un mouvement à la caméra si l’idée vous en dit.

  • Et voilà, on a terminé. Ce qui est cool, c’est qu’un effet Parallax nous donne l’impression que le poteau bouge également (ce que l’on pourrait faire!).

  • Maintenant le rendu! Utilisez SheepIt Render Farm si vous pouvez, sinon votre carte graphique locale. Générez des PNGs puis faites un montage vidéo avec son et tout le toutim et générer la vidéo!

  • Voici ce que ça donne de mon côté (P.S., je suis allé chercher un poteau dans BlenderKit et j’ai modélisé des oeillets au niveau des accroches; j’ai également joué avec les paramètres du Noise Texture, ceux de la valeur des Keyframes X du mapping et W du Noise Texture jusqu’à satisfaction). Le bruitage, j’ai tout trouvé ça sur artlist.io. Si vous les voulez, c’est par ici:

    https://drive.google.com/drive/folders/1KMvh9JOHhtWA1y4HkoR-OaF2d0sfCKc5?usp=sharing

  • À votre tour, soyez créatifs, changez le HDRI, ajouter un soleil comme source de lumière tiens, changer la texture du drapeau, ajouter des lampadaires avec émission de lumière, have fun, soyez fous!

Devoirs

  • Un coussin gonflable à votre effigie, similaire à ceci:

  • Critères

    • Changer la texture pour quelque chose qui vous représente
    • Vous pouvez modifier le End Frame pour une rotation plus lente: 360 au lieu de 80. Moi, pour la démo, j’ai tout simplement doublé la séquence, en inversant l’ordre de la deuxième série d’images.
    • Ajouter des effets sonores
    • Laisser aller votre imagination, surprenez-moi
  • Walkthrough

Lien vers l'original

Banque de cours - Eau et dynamic paint

# Eau et dynamic paint

Une chute d’eau

Modélisation

  • Créer un dossier intitulé “Chutes”.
  • Y copier le fichier de départ suivant: https://drive.google.com/file/d/1EKi3gqAq9c1wzzy5Zpmxzi9M6EsdHsgz/view?usp=sharing
  • Ce modèle est tiré du livre “From the book Learn Blender Simulations The Right Way” de Stephen Pearson.
  • Vous pouvez modéliser votre propre chute à la place, mais attention de ne pas rendre votre scène trop complexe avec des résolutions de maillages trop élevés.
  • Le renommer Chutes.blend

Simulation - le Domaine

  • Créer un cube qui contient tous les objets, mais pas plus.
  • Apply Scale pour le cube (⌃ A → Scale), sinon les calculs de simulations seront déformés et conduiront à des comportements intensément zarbis.
  • Modifier le cube pour qu’il devienne le domaine d’une simulation de type “Fluid”. Domain Type devrait être “Liquid”

  • Changeons le “Resolution Divisions” à 64 (si votre CPU n’est pas très puissant, laisser la valeur à 32 jusqu’au rendu final où là vous l’augmenterez avant le bake.
  • Changeons le Time Scale à 0.5 pour créer un effet de ralenti.
  • On ne veut pas que le fluide entre en collision avec la bas du domaine, ni avec l’avant, sinon le cube va se remplir de liquide. On veut que la chute d’eau continue de “tomber” naturellement. Ainsi donc, dans “Border Collisions, retirer Front et Bottom du cube.
  • Fixons “Narrow Band Width” à 8 pour augmenter l’épaisseur du fluide, i.e. une plus grande densité de particules.
  • Activons “Fractional Obstacles” afin de nous assurer que les particules n’adhèrent pas aux objets effectors. Cela améliore la simulation près des bords des effectors, évidement, cela va nous coûter plus cher en calculs.
  • Dans la section “Particles”, activer le “Foam”, parce que c’est chouette la mousse!
  • Changer la valeur de “Potential Radius” et “Particle Update Radius” à 3. Cela rendra la simulation plus fluide et moins chaotique, mais, encore une fois, nous coûtera plus cher en calculs.
  • Enfin, augmenter le “Wave Crest Particle Sampling” à 300. Cela améliorera la simulation au sommet des vagues en y ajoutant plus de particules.

À noter qu’ici j’ai mis le Time Scale non pas à 0.5 mais à 0.2. J’ai alors agumenté le End Frame à 400, j’aime les chutes au ralenti. Si vous laissez le Time Scale à 0.5, 250 frames c’est suffisant.

  • Dans la section “Mesh”, activer celle-ci pour qu’une géométrie soit générée lors du calcul de la simulation.
  • “Upres Factor” a une valeur par défaut de 2, ce devrait être suffisant pour un look pas trop low poly. Si ce n’est pas assez, augmenter cette valeur, procéder par essai-erreur.
  • Le fait d’activer “Mesh” va créer une géométrie autour de chaque particule de la simulation, et le rayon de 2 de chaque particule est trop grand, cela va donner l’impression de ballons d’eau. Réduire donc la valeur “Particle Radius” à 1.
  • S’assurer d’activer “Use Speed Vectors”. Ainsi, les vecteurs de vitesse ainsi calculés et “baked” dans la simulation pourront être utilisés pour le motion blur lors du rendu.
  • Pour la Cache, Frame end: 250, s’assurer également que le type de Cache soit “Modular”. “Is Resumable” doit être activé, sinon Blender ne pourra pas générer de particules. Vous devriez voir un message à ce sujet au-dessus du bouton “Bake Data” quand “Is Resumable” n’est pas activé.
  • De mon côté, j’ai mis le Frame End à 400 et j’ai réduis le “Time Scale” à 0.2. Pour que ça aille plus vite, laissez le Time Scale à 0.5 et le Frame End à 250.
  • Le “Format Volumes” doit être ici du type “Uni Cache” au lieu de la valeur habituelle “Open VDB” car cette dernière ne traite pas les “Speed Vectors” qu’on a activé tout à l’heure pour avoir du Motion Blur. Seul Uni Cache sait quoi faire avec les Speed Vectors.
  • Ainsi donc:
  • Ne pas oublier de s’assurer que le nom du dossier qui contiendra la cache commence par // afin que ce dernier soit créé dans le même répertoire que le fichier .blend.

Simulation - Inflow et Effectors

  • Créer un mesh de type “Plane” de la taille approximative ci-dessous. Le placer au sommet et au début de la chute. S’assurer qu’il ne touche à aucun objet mais qu’il soit assez grand et, bien sûr, qu’il soit à l’intérieur des limites du domaine.

  • N’oubliez de faire Apply Scale!
  • Puisqu’on a tourné l’objet également, Apply Rotation aussi! Ainsi, en sélectionnant l’objet, dans le menu N, Item devrait montrer le vecteur [0,0,0] pour la rotation, et [1,1,1] pour l’échelle.
  • On pourrait créer deux objets Inflow, ou surélever celui-ci pour obtenir la simulation désirée.
  • Configurons le Plane en tant qu’Inflow. Dans les propriétés physiques, choisir Fluid.
PropriétéValeurDescription
Settings:
TypeFlow
Flow TyleLiquid
BehaviorInflow
Use FlowActivé
Flow Source:
Flow SourceMeshOn veut que le “Plane” en entier soit la source du fluide
Is PlanarActivéComme “Plane” n’est pas un solide (pas d’épaisseur), on doit dire à Blender que l’objet est un plan.
Initial Velocity:ActivéOn veut une vitesse initiale au fluide, dans la direction des Y négatifs
Y-1Plus la valeur est grande, plus la vitesse initiale du fluide le sera également.

  • Maintenant sélectionner le lit de la chute d’eau (la partie plane au milieu).

  • Lui conferrer la propriété physique “Fluid” également, mais le type est maintenant “Effector”, l’Effector Type est “Collision” et on doit activer “Is Planar”.

  • Répétons la même chose pour les pierres. Il faut le faire pour chaque objet. À noter que même si vous sélectionnez plusieurs objets, les propriétés que vous conférerez à ceux-ci ne s’appliqueront qu’à l’objet actif. Comment faire alors?

  • Soit on y va un par un, ou alors une fois les propriétés appliquées à un objet, on sélectionne tous les objets vers lesquels on veut copier les modifiers (⇧-Select), puis on ⇧-select l’objet qui contient les modifiers qu’on veut copier en dernier (c’est important!), et enfin ⌃ L puis “Copy Modifiers”.

  • Sélectionner le domaine, et, dans la section “Settings” des propriétés physiques, faire “Bake Data”.

  • Pour l’instant, la simulation est une série de points dans l’espace, faire “Play” pour avoir un aperçu de celle-ci.

  • On a besoin que chaque point dans l’espace simulé soit un objet (en ce moment ils sont montrés comme des “halos”, comme des points sans géométrie), mais il faut faire attention au type d’objet utilisé. Une UV Sphere par exemple a un maillage trop complexe, cela ralentirait énormément Blender.
  • D’abord, sélectionner le domaine (le gros cube) et ajouter un “Smooth by Angle” modifier. Ensuite cliquer droit sur le cube et choisir le sous-menu “Smooth by angle”.
  • Nous allons choisir l’objet de type cône, avec très peu de géométrie dedans.
  • Ajouter un cône et dans les propriétés de création, 3 pour Vertices. Changez également l’échelle à 0.02 et faites Apply Scale.
  • Vous devriez avoir un tout petit cône qui est en fait devenu une pyramide à 3 côtés et à base triangulaire:
  • Sélectionner le domaine et aller dans les propriétés “Particles”. En fait, vous constaterez que Blender, quand on a créé le domaine, a ajouté deux modifiers de type Particles System: un pour le liquide, et un pour la mousse.
  • Si vous faites “Render Image”, rien n’apparaîtra, ou plutôt vous devriez voir un cube qui cache tout! C’est qu’on n’a pas donné encore de texture au domaine, et pas non plus aux particules. C’est ce qu’on va faire maintenant.
  • Remarquez que dans les propriétés Particles, Blender a ajouté Liquid et Foam au domaine. On va associer le triangle au Foam.
  • Sélectionner le domaine, aller dans les propriétés Particles, et pour Foam, choisir Render As “Object” et choisir le cône comme Instance Object

Textures

  • Sélectionner le domaine et dans les propriétés Material, Cliquer sur New. Remplacer Principled BSDF par Glass BSDF.
  • Choisir une couleur légèrement bleutée pour l’eau, par exemple f8ffff
  • Réduire le Roughness à 0.
  • L’Indice de réfraction de l’eau (IOR) est d’environ 1.333
  • Si vous voulez connaître l’indice de réfraction de la majorité des medium, c’est par ici:

https://pixelandpoly.com/ior.html

  • On va donner un peu de volume à l’eau. Dans la section “Volume”, cliquer sur “None” et choisir “Principled Volume”.

  • Donner une couleur bleue à ce shader et fixer la densité à 0.5.

  • On a terminé avec la texture de l’eau. Maintenant passons à la mousse.

  • Sélectionner le cône, et dans la section Material, faire New. Dans le Principled BSDF, baisser le Roughness à 0.1. L’eau aura une belle propriété de réflexion. Techniquement, ça pourrait être plus transparent que ça, mais qu’est-ce que ça va coûter cher lors des rendus! À vous de jouer avec cette valeur.

  • On est prêt pour les bakes.

  • Sélectionner le domaine, et faire Bake Data dans la section Settings des propriétés physiques.

  • Ensuite faire Bake Particles dans la section Particles.

  • Puis faire Bake Mesh dans la section Mesh.

  • Aller à un frame assez loin (genre 200) et faite Render Image!

  • C’est joli quand même (mais tellement coûteux!). La taille du dossier cache est de 2.5 GB dans mon cas. Impossible d’envoyer la chose à SheepIt Render Farm (le max actuel toléré étant de 2GB). Je vais devoir donc générer l’animation pendant la nuit sur mon pauvre laptop.

Animation

  • Maintenant, pour l’animation, il est important d’avoir du Motion Blur sinon la chute d’eau aura l’air beaucoup trop fake, mais l’activer dans Cycles est encore plus coûteux pour une simulation de fluides. En fait tellement que mon Mac n’arrive pas à faire le rendu, Blender plante!
  • On va donc faire une approximation du motion Blur via le compositor grâce à l’information Vector Blur qu’on a activé au début en créant le domaine (Vous vous souvenez du ”Use Speed Vectors”?).
  • Dans les propriétés Render Layers. activer Vector et Z (Denoise Data est déjà activé).
  • On a déjà effectué le rendu d’une image un peu plus tôt. Sinon, faites-le maintenant, en choisissant un frame qui vous convient et faire Render → Render Image. Cela va nous permettre de voir, dans le Compositing, l’effet du compositing.
  • Après avoir fait un Render Image, aller dans l’espace de travail Compositing. Vous devriez déjà avoir tout ceci:
  • Ajoutons un noeud de type Vector Blur (⇧ A → Filter → Blur → Vector Blur)
  • Connecter la sortie Depth du Render Layer à l’entrée Z du Vector Blur et connecter la sortie Vector à l’entrée Speed.
  • Connecter la sortie Image du Render Layer à l’entrée Image du Vector Blur et c’est maintenant la sortie Image de ce dernier qu’on connecte à l’entrée image du noeud “Color Balance”.
  • Paramètres du Vector Blur:
ParamètreValeurDescription
Samples32
Blur0.5
Speed Min0
Speed Max40
  • Ça devrait ressembler à ceci:
  • Finalement, retirons la visibilité dans les rendus pour l’objet “Inflow”, on ne veut pas voir un plan blanc au début de la chute:
  • Ça y est, vous êtes prêts à rendre l’animation. S’assurer de générer des fichiers png et non pas une vidéo car on en demande beaucoup à Blender et à notre machine et on ne veut pas devoir tout recommencer si ça plante.
  • Voici le résultat, vous remarquerez que la qualité de la simulation qu’on a fixé fait en sorte, par exemple, que l’eau ne semble pas toucher au lit de la rivière et le débit n’est pas très élevé:

  • Voici un rendu de plus grand qualité (ça a pris toute la nuit sur mon MAC), format 4K, Sampling Substep réglé à 10 pour les effectors te les inflows, 400 frames avec un Time Scale de 0.3 et une Resolution Division de 128 pour le domaine):

  • Remarquez ici que maintenant, ce sont les effectors qui n’ont pas assez de géométrie (l’eau passe au travers de la première pierre en haut à droite) et l’eau tombe derrière, il aurait fallu que crée un effector à l’arrière de l’Inflow pour empêcher cela.

Améliorations

  • Changer le lit de la chute et l’émetteur pour des objets solides (Solidify modifier auxquels vous faite “apply” à la fin); retirer “Is Planar” desdits objets. La simulation sera plus précise, l’eau se rapprochera du lit.
  • Ajouter de la géométrie au lit et à l’émetteur avec un subdivide modifier appliqué.
  • Augmenter la géométrie des pierres (Subdivide Modifier sur lequel vous faite “Apply”).

Océan + Dynamic Paint

Modélisation

  • Créer un nouveau fichier blend dans son propre dossier.

  • Créer un “Plane”, lui ajouter un “Ocean Modifier”, changer le Size à 0.4 et pour la propriété Time, inscrire “#frame/20”. Si si, on peut animer n’importe quel paramètre en fonction du numéro du frame!

📌

Ça s’appelle un driver. Pour le retirer, il faut cliquer droit et faire “Delete Driver”.

  • Changer la résolution Viewport à 16 et celle du Render à 32.

  • Changer Repeat X à 2 et Repeat Y à 2.

  • Dans la section Waves, changer Scale à 0.4 et Choppiness à 3. Jouer avec ces valeurs pour obtenir l’effet désiré.

  • Activer la section Foam. Nommer le Data Layer de la section Foam “Ecume” et Coverage devrait avoir une valeur de 0.2 genre comme du coup (jouer avec ces valeurs).

  • Zoomer de manière à voir tout l’océan dans le viewport.

  • Faites “Play” juste pour voir, puisque nous avons indiqué que la variable Time est maintenant une fonction du numéro de Frame, l’animation est présente.

  • Vous pouvez changer le “Random Seed” pour changer la forme de l’océan et de ses vagues.

  • Dans le Shader Editor, ajouter un Principled BSDF. Changer la couleur pour obtenir un bleu de votre océan/mer préféré (moi c’est la Méditerrannée). Roughness à 0.3 genre, Transmission à 1 et IOR à 1.34 (une approximation de l’indice de réfraction de l’eau salée).

  • Ajouter noeuds “Add Shader”, “Emission”, “Attribute” et “Color Ramp”. Les connecter ainsi: Attribute à Color Ramp, Color Ramp à Emission et Emission à Add Shader.

  • Dans Attribute, inscrire “Ecume” (l’attribut du Foam).

  • Ajuster le Color ramp pour obtenir l’effet d’écume désiré. Comment fonctionne le Color Ramp? L’input est une valeur entre 0 et 1. À 0, c’est la couleur la plus à gauche qui apparaîtra, à 1, c’est la couleur la plus à droite.

  • Ajouter une caméra et l’ajuster de manière à ce qu’on ne voit pas les “bords” de l’océan. Vous savez comment faire maintenant.

  • À la place du HDRI dans les propriétés World, choisi un Sky Environment Texture

  • Ajuster les paramètres du Sky Environment Texture à votre guise.

  • Ajuster le nombre de frames (disons max 120) et faites un rendu de l‘animation

  • Voici le résultat

Dynamic Paint

  • Cliquer sur le bouton “Add Canvas”
  • Pour “Surface Type” dans la section “Surface”, choisir “Waves”
  • Changer “Smoothness” à 0.1 au lieu de 1.
  • Ajouter une UV Sphere. Donnez-lui la texture et couleur que vous voulez.

  • Lui ajouter une simulation de type Dynamic Paint également, et pour le type, choisir “Brush” au lieu de “Canvas”
  • Cliquer sur le bouton “Add Brush”.
  • En vous assurant que l’animation est en mode Play, déplacez la sphère selon le plan X et Y (G ⇧ Z) et admirez le résultat.
  • Ajouter un Smooth by Angle Modifier à la sphère, activer “Ignore Sharpness”.

Animation

  • Réduire grandement la turbulence de l’océan. Vous devriez être en mesure de le faire, essayez!

  • Passer en mode vue orthogonale en élévation (Numpad 7) et en mode Wireframe (Z → Wireframe)

  • On va tracer un chemin sur l’océan et demander à la sphère de le suivre.

  • Cliquer sur l’ocean et faire H pour le cacher.

  • Ajouter une courbe de type Path (⇧ A → Curve → Path).

  • Passer en mode Edit.

  • Déplacer les points du la courbe et en ajouter si nécessaire avec Extrude (E). Créer une chemin où le dernier point correspond au premier. S’assurer que le rayon de courbure du départ soit assez aligné avec celui de l’arrivée. Une manière de le faire est de sélectionner le point de départ et le point d’arriver (que vous avez fait coïncider du mieux possible) et les bouger de manière à adoucir et faire correspondre leur rayon de courbure respectif.

  • Passer en mode Object et en mode Camera View

  • Déplacer (attention seulement selon les axes Y et X, pas Z! - donc G puis ⇧ Z) et scaler le Path de manière à ce qu’il couvre grosso modo le cadre de la caméra.

  • Sélectionner la sphère puis le Path et faire ⌃ P puis choisir Object (Keep Transform) pour faire en sorte que la sphère soit un enfant du Path.

  • Avec la sphère sélectionnée, lui ajouter un Constraint Modifier (propriétés Constraint) de type “Follow Path”. Chosir le NurbsPath comme objet à suivre. La sphère devrait se déplacer sur le Path.

  • Le paramètre Offset permet de déplacer la sphère le long du chemin. À 0, la sphère est à sa position initiale, à -100%, elle aura parcouru tout le chemin jusqu’à la position finale qui, dans notre cas, coïncide avec l’initiale. Dependent des valeurs “Forward Axis”, ça peut aussi être +100%. Le Up doit être Z. Essayez pour voir en déplaçant le curseur de la souris de gauche à droite après avoir cliquer sur le champ “Offset”.

  • Keyframons l’animation. Au Frame 1, indiquer une valeur 0 dans Offset et cliquer sur le petit bouton à droite pour qu’il devienne un diamant.

  • Au dernier frame (250), inscrire la valeur -98% (à une valeur -100% dans mon cas, la sphère est un peu plus loin qu’au départ, jouer avec ces valeurs pour obtenir un mouvement le plus continu possible) et cliquer encore une fois sur le petit bouton blanc à droite du champ Offset.

📌

  • Ni cliquez pas sur Bake. Pour une raison que j’ignore, avec un Bake, l’océan ne bougera plus lors du rendu de l’animation via SheeptIt Render Farm. Une question de cache sans doute…
  • C’est terminé, animez le tout!

  • Voici le résultat avec un océan beaucoup plus calme.

📌

Comme vous pouvez le constater, et vous m’en voyez très fâché et contrarié, ça marche dans le viewport, mais pas très bien une fois l’animation générée. Je n’ai pas trouvé pourquoi, je pense que l’Ocean Modifier, n’étant pas une véritable simulation, a ses limites. Avec un Bake, ça bouge plus… Mais vous verrez, au prochain cours, on verra quand même l’avantage de ce modifier. Mais pour l’instant, utilisons ce qu’on a appris pour faire un meilleurs Dynamic Paint

En fait, je pense que la sphère n’est pas assez grande, mais tout de même, si on voit l’effet dans le Viewport, on devrait le voir dans le rendu. Oh well…

Dynamic Paint Prise 2

  • Créer un nouveau fichier Blender.

  • Ajouter Plane, triplez sa taille et faites Apply Scale (⇧ A → “Plane” ↩, S 3 ↩, ^ A → Scale ↩).

  • Ajouter un UV Sphere. Scale down à 0.1. Apply Scale.

  • Sur la UV Sphere, ajouter un Smooth by Angle Modifier et activer le checkbox “Ignore sharpness”

  • Aller au Frame 1, placez la sphère à gauche. Insert Frame.

  • Au frame 100, placer la sphère à droite. Insert Frame.

  • Ajouter une caméra, trouver un bon point de view dans le Viewport puis faire ⌃ ⌥ Numpad 0 pour aligner la caméra. Ajuster au besoin.

  • Sélectionner le plan et passer en mode Edit Edge. Sélectionner les 4 egdes (A). Cliquer droit et faire Subdivide. Dans le menu de création, mettez 40 pour la valeur “Number of cuts”.

  • Revenir en mode objet.

  • Ajouter un “Solidify Modifier”, donner une certaine épaisseur au Plane et faire Apply.

  • Dans les propriétés Physics, ajouter un Dynamic Paint de type Canvas.

  • Faire Add Canvas

  • Pour Surface Type, choisir Weight.

  • Un peu plus bas, dans output, cliquer sur + pour ajouter le vertex groupe prénommé “dp_weight”. La couleur rouge disparaîtra.

  • Maintenant sélectionner la sphère, et lui donner également un Dynamic Paint Modifier, mais de type Brush cette fois-ci.

  • Cliquer sur Add Brush.

  • Sélectionner le plan, passez en mode Weight Paint et faire play. Vous devriez voir l’impact de la brush sur le canvas.

  • Revenir en mode Object

  • Sélectionner le Plane, et dans le menu Object, choisir “Quick Effects” → “Quick Smoke”.

📌

Pourquoi le Plane (le canvas) et pas la sphère? La sphère n’est là que pour déformer (paint brush) le canvas (le Plane) et ainsi créer un Weight Paint Vertex group derrière elle, comme une traînée. C’est ce Vertex Group qui va prendre feu.

  • Un “Domain” avec le fameux voxel devrait apparaître, entourant complètement le Plane.

  • Sélectionner le Plane, on ne veut pas qu’il prenne entièrement feu, seulement son Vertex Group.

  • Assurez-vous que dans le stack des simulations, Fluid (qui vient d’apparaître, rappelez-vous que la fumée et le feu, se sont des fluides) soit après Dynamic Paint. En effet, on veut d’abord créer les Vertex Groups déformés par la sphère, et ensuite y mettre le feu

📌

Vous pouvez également changer l’ordre dans les propriétés Modifiers car les simulations sont des modifiers.

  • Dans les propriétés de la Fluid Simulation, sous Fluid → Settings, choisir le Vertex Group “dp_weight”.

  • Passer en mode Solid ou Render View et faites Play. Vous devriez voir un petit chouya de fumée (s’assurez dans le timeline que Drop Frames est à off (Playback → Sync → Play Every Frame)).

  • Vous devriez voir de la fumée derrière la sphère.

  • Activer “Initial Velocity. Modifier Source à 0 et Initial Y à -1. Comme notre balle se déplace de gauche à droite le long de l’axe des Y, on veut que la fumée va se déplace vers la gauche (Axe Y négatif).

  • Sélectionner le domaine (la grosse boîte à l’intérieur de laquelle la simulation a lieu). Vous devriez encore voir les propriétés physiques à droite, mais cette fois-ci, pour le domaine.

  • Pour ne pas demander une résolution trop grande, activons le Noise dans les propriétés physiques du domaine.

  • Augmenter la résolution à 64.

  • Sélectionner le Plane, et dans les propriétés Physics → Fluid, choisir “Fire + Smoke” pour le Flow Type.

  • Faire Play au complet une fois pour recalculer la simulation, puis s’arrêter au frame 60 environ. On va travailler le Shader.

  • Sélectionner le domaine.

  • Aller dans le Shader Editor, choisir Object. Vous devriez avoir déjà un Principled Volume Shader ajouté par le fait d’avoir choisi “Quick Smoke”.

  • Ajouter un Node Volume Info.

  • Connecter Density de ce noeud à Density du Principled Volume. Même chose pour Flame, à connecter à Emission Strength et Emission Color.

  • Insérer un Math node, type Multiply entre le lien Density. Ajuster la valeur à 7. Ça nous permet de contrôler la densité de la fumée.

  • Ajouter un Math Node de type Add entre Flame et Emission Strength. Valeur à genre 32.

  • Revenir au Frame 1, refaire Play pour exécuter derechef la simulation.

  • Une fois que les 100 frames ont joué, revenir au frame 60 environ. Tiens, changer la valeur du Multiply à 20 aussi, on veut une fumée plus dense.

  • Bon, une flamme blanche, c’est pas tout à fait ça. Changeons sa couleur.

  • On va pousser plus loin notre simulation du feu du premier cours. Avec un Color Ramp, on va pouvoir déterminer la couleur de la flamme en fonction de sa température, enfin presque, on va se baser sur l’info Flame du Volume Info.

  • Ajouter un noeud Color Ramp donc entre Flame et Emission Color et le configurer à peu près comme suit:

  • En fait amusez-vous, créez votre flamme préférée.

  • Donner une texture au Plane. Ah il faut aller dans le Object Properties du Plane, et changer Viewport Display → Display as → Solid (au lieu de Wireframe). Quand on a décidé que c’était un émetteur de feu, Blender change la manière dont il le montre dans le viewport.

  • Donner un look bleu métallique (New Material!) au Plane.

  • Maintenant, revenons en mode layout et aux propriétés physiques du domain.

  • Augmentons la résolution à 256. Heu non, le CPU n’est pas assez puissant, laisser à 64. Mais pour de vrai, pour le rendu final, Résolution à 256 ou plus!

  • Dans la section cache, End Frame devrait correspondre, donc 100.

  • Changer le type de cache à “All” car nous avons deux simulations à Baker, le dynamic paint et le feu. Ouf, ça va prendre du temps.

  • Cliquer sur “Bake All”.

  • Une fois baked, le truc cool, c’est qu’on peut jouer avec les valeurs du shader (vu que c’est un material non plus sur une simulation, mais sur une série de mesh, une par frame) sans avoir à refaire un nouveau bake.

  • Dans le compositor, désactiver (avec la touche M) le noeud “Glare”.

Résultat de la simulation

Devoir Votre signature avec du feu (ou autre) - [ ] Basez-vous sur le tutoriel Dynamic Paint - feu - [ ] Modéliser un stylo (impressionnez-moi!). Pas besoin de remplacer la sphère, assurez-vous plutôt qu’on ne voit pas la sphère mais qu’elle est encore là. Parentez votre stylo à la sphère afin qu’il se déplace avec celle-ci. - [ ] Le déplacer le long d’un chemin créé par une Curve de manière à ce qu’il imite votre signature, la première lettre de votre prénom, ou autre, sur le canvas. - [ ] Donc un follow curve quoi. - [ ] Modifiez les paramètres de la simulation à votre guise, soyez storytellers et créati.fs.ives!

Critères
- [ ] Un mouvement correspondant à votre signature ou à la première lettre de votre prénom, ou quelque chose d’original.
- [ ] Modélisation du stylo.
- [ ] Simulation avec paramètres différents.
- [ ] Ajouter des effets sonores et musique.
- [ ] Laisser aller votre imagination, surprenez-moi! J’accorde des points quand vous dépassez mes attentes. Vous le savez depuis le début c’est ce que je fais 😊

Lien vers l'original

Banque de cours - Optimisation Océan, corps souples

# Optimisation Océan, corps souples

Optimisation pour un océan “infini”

  • Dans un nouveau dossier, créer un nouveau fichier que vous nommerez ocean.blend
  • Créer un cube, lui donner un Ocean Modifier avec les paramètres suivants:
Resolution Viewport16
Render16
Waves → Choppiness0.9
Wind Velocity4 m/s

  • Dans les propriétés de l’output, changer le Frame rate à 30 et le End Frame à 300 (Note: ça va le changer automatiquement dans le timeline également).

  • Amener la tête de lecture au Frame 1. Dans le Ocean Modifier, enter la valeur 0 à Time et insérer un Keyframe.

  • Au frame 30, changer la valeur de Time à 0.5 et insérer un autre Keyframe.

  • Passer au Graph Editor. Assurez-vous de sélectionner la variable Time (Ocean).

  • Sélectionner tous les points (A) et changer l’interpolation à “Linear” (T puis choisir Linear). Vous devriez avoir ces deux points, l’un au frame 1, l’autre au frame 30:

  • On peut ajouter des modifiers dans le graph editor. Avec la souris dans le Graph Editor, Faites N pour faire apparaître le “N Menu”.

  • Cliquer sur un des points de la courbe (keyframe au frame 1 ou 30) pour le rendre actif (blanc).

  • Dans le tab vertical Modifier, ajouter un Cycles Modifier.

  • S’assurer que Before Mode et After Mode soient “Repeat with Offset”. Cela va créer un cycle mais avec un calcul du gradient entre la valeur de départ et celle de fin afin d’avoir un transition douce.

  • Revenir au Timeline et faire play.

  • Dans les propriétés du Ocean Modifier, changer le render à 32 au lieu de 16

  • Dans la section Bake, choisir votre dossier pour l’export (genre un dossier “Bake” dans le dossier de votre fichier blend: “//Bake\” )

  • Il est très important que le dossier de la cache soit au même endroit que le fichier .blend car on va, dans ce dossier, créer un autre fichier qui va utiliser cette cache.

  • Changer le End Frame à 300.

  • Cliquer sur “Bake” et attendre que la cache du bake soit générée. Le dossier de la cache devrait quand faire 1.5 GB, c’est pas rien. Imaginez si on avait mis la résolution du Render à 128 au lieu de 32…

  • Sauvegarder votre fichier Ocean.blend.

  • télécharger le fichier .blend suivant dans le même dossier que Ocean.blend: https://drive.google.com/file/d/1aCpLhRj8xtSq4O7-HvV4ZyzxgGXvLjXb/view?usp=sharing

  • Le nommer bateau.blend et l’ouvrir dans Blender. C’est un bateau que je suis allé chercher via Blenderkit, la version payante, donc s.v.p., ne pas utiliser en dehors du cadre pédagogique.

  • Ouvrir ledit fichier dans Blender

  • Sélectionner le plan et l’effacer.

  • Cliquer sur l’oeil à droite de la collection “Coast defense ship” pour cacher le bateau.

  • Ajouter un Plane, Scale à 1000 (S 1000 ↩)

📌

Attention, ne pas faire apply scale sur le plan, sinon la texture qu’on rajoutera tout à l’heure ne fonctionnera pas.

  • Dans le N Menu, choisir View et changer le Clip start à 0.1 et Clip End à 100 000. Ces valeurs déterminent quand la zoom in/zoom out clip et arrête de montrer l’information des objets dans le viewport.

  • Avec le Plane sélectionné, passer en mode Edit, cliquer droit et choisir Subdivide.

  • Dans les paramètres de création, changer le Number of Cuts à 100.

  • Revenir en mode Object.

  • Ajoutons un Material au Plane. Changer d’espace de travail, aller vers le Shading Editor.

  • Dans le shading Editor, dans la section où l’on voit l’objet, activer le N menu et changer le clipping de la camera dans l’onglet View, comme on l’a fait tout à l’heure. Ça ne le fait pas globalement. Donc encore une fois: Clip Start à 0.1 m et Clip End à 100000 m.

  • Choisir Object au lieu de World, faire New, sélectionner le Principled BDSF et faire ⌃ T. Cela va rajouter une Image Texture avec ses coordonnées et mappings.

  • Dans le noeud Image Texture, faire Open et choisir le premier .exr dans le dossier de la cache (moi je l’ai nommé ”Bake”). La première image devrait se nommer “disp_0001.exr”

  • Connecter la sortie Object de Texture Coordinate à l’entrée Vector de Mapping et, dans Mapping, changer le scale à 10 pour les trois axes.

  • Dans le noeud Image Texture qui est maintenant nommé “disp_0001.exr”, changer Single Image pour Image Sequence et mettre le nombre de Frames à 300.

📌

Saviez-vous que vous pouvez même mettre une vidéo à la place d’une image en guise de texture? Cela créera une texture animée! Ça peut être chouette pour des écrans de télé/pub genre à la Blade Runner.

  • Ici, l’aspect très important d’optimisation, c’est justement qu’il n’y a plus de simulation en jeu, l’océan a une texture animée.

  • Entre l’Image Texture et le Principled BSDF, ajoutons les noeuds suivants: Un Separate XYZ, un Combine XYZ dont vous connectez les 3 axes, i.e. les sorties X, Y et Z du Separate XYZ aux entrées X, Y et Z du Combine XYZ. Cela va transformer la couleur du texture en vecteurs [X,Y,Z].

  • Ajouter un noeud Vector Displacement et changer le scale à 0.01.

  • Enfin, connecter la sortie Displacement du noeud Vector Displacement à l’entrée Displacement du noeud Material Output.

  • Vous noterez que le Principled BSDF n’a pas de Base Color connecté en entrée, c’est normal.

  • Changer la couleur du Principled BSDF à noire, le Roughness à 0, l’IOR à 1.333 et le Weight de la Transmission à 1:

  • Revenir dans l’espace de travail “Layout”.

  • Assurez-vous que le Render soit Cycles.

  • Dans les propriétés Material, dans la section Settings, sous-section “Surface”, changer Displacement pour “Displacement and Bump”.

⚠️

Ce paramètre n’est visible que si le Render est en mode Cycles

  • Passer en mode Render EEVEE.

  • Passer en mode Render et zoomer sur le plan de manière à voir les vagues.

  • Dans les propriétés World, retirer le HDRI en choisissant Sky Texture dans Color et changer le Strength à 0.8.

  • Changer le renderer pour EEVEE au lieu de Cycles dans les propriétés Render.

  • Dans la section Color Management, changer Exposure pour 0.2 et Gamma pour 1.2. Changer la valeur du noeud Gamma dans le Compositing Editor à 1.2 également.

  • Revenir au Shading Editor pour le Plane, il y a trop de vagues, changer le scale du Vector Displacement à 0.001 plutôt que 0.01.

  • Dans le noeud Image Texture, activer Cyclic and Auto Refresh

  • Revenir au Layout Editor.

  • Dans les propriétés Modifiers du Plan, ajouter un Subdivision Modifier et changer le Render et Viewport à 4.

  • Faire unhide de la collection “Coast defense ship” et déplacer le bateau selon l’axe des Z de manière à ce qu’il ait l’air de flotter sur l’océan.

  • Se déplace dans le viewport de manière à obtenir une vue intéressante.

  • J’ai rajouté une caméra et baissé dans mon cas l’intensité du Sky Texture à 0.1, le soleil était trop aveuglant sinon. À vous de voir ce qui fonctionne pour vous.

  • Faites Render Image pour voir après avoir ajouté une caméra.

  • Maintenant vous pourriez vous amuser à animer le mouvement de la caméra avec une “follow path” par exemple.

  • Avec l’arrivée de EEVEE-NEXT (Blender 4.2), on pourra activer le Ray-tracing temps réel pour un look encore plus abouti! En attendant, voici le résultat en ajustant certains des paramètres de l’environnement Sky (soleil plus bas sur l’horizon).

Corps souples - théorie

Intro

📌

Cette documentation est tirée du livre “Learn Blender Simulations the Right Way” par Stephen Pearson

  • À l’instar de la simulation de tissus, les corps souples (ainsi que les corps rigides) ont besoin d’une géométrie également distribuée pour bien fonctionner.
  • Aussi, les corps souples (et corps rigides) font appel aux collisions pour interagir avec leur environnement.
  • En ajoutant un Collision Modifier, des paramètres apparaîtrons dans l’onglet Softbody & Cloth:
    | Field Absorption (absorption de champ) | Définit la capacité d’absorbtion de la force d’un champ. Par exemple, si un champ de force de vent traverse une collision avec une valeur d’Absorption de Champ fixée à 0,2, il absorbera 20% de la force du champ. Si la valeur est fixée à 1, il absorbera 100% du champ de force, et aucun vent ne pourra passer au travers. |
    | --- | --- |
    | Damping (amortissement) | La quantité de rebond qu’un corps mou aura lors d’une collision. 0 signifie aucune amortissement, il y aura donc beaucoup de rebonds. 1 signifie un amortissement maximal, auquel cas il y aura très peu de rebonds. |
    | Thickness Outer (épaisseur extérieure) | La taille de la zone à l’extérieur de la collision. Avec une valeur de 0,5, il y aura un assez grand écart entre la collision et le corps souple. Ce paramètre sert également de rembourrage pour la collision. Au lieu de frapper et de rebondir, il semblera que le corps souple frappe un oreiller. |
    | Inner (épaisseur intérieure) | La zone de collision à l’intérieur de l’objet. C’est essentiellement la distance de rembourrage, et si un corps souple entre dans cette zone, il essaiera de le forcer à sortir. Un exemple serait de placer un corps souple au milieu d’un plan. Comme la moitié du corps souple est à l’intérieur de la zone intérieure, il le poussera vers le haut et vers l’extérieur. Gardez à l’esprit que cela ne fonctionne pas pour une simulation de tissu, uniquement pour les corps souples. |

Banque de cours - Collision et direction des normales

📌

Une collision est basée sur la direction des normales à la surface. Les normales d’un objet sont la direction dans laquelle les faces sont orientées (un vecteur perpendiculaire à chaque plan). Il faut parfois recalculer les normales et voir dans quelle direction celles-ci pointent pour que la simulation fonctionne. Pour ce faire, en mode Édition avec l’objet sélectionné, appuyer sur A pour sélectionner tous les sommets sur le maillage (mesh) puis choisir le menu Mesh → Normals → Recalculate (⇧ N). On peut également activer la visualisation de l’orientation de chaque plan (face) dans le menu Overlays pour voir dans quelle direction les plans sont orientés.

Lien vers l'original

  • Quelques paramètres essentiels aux Softbodies:
    | Collision Collection | Contrôle quelles collections interagissent avec la simulation. Si rien n’est indiqué, chaque collision dans chaque collection interagira avec les corps souples. |
    | --- | --- |
    | Friction | Ce paramètre fonctionne un peu différemment de ce q’on pourrait croire. Il s’agit de la friction globale de toute la zone. Si vous augmentez cette valeur, cela amortira le mouvement du corps souple, le faisant ressembler à un mouvement au ralenti. |
    | Mass | Contrôle le poids de chaque sommet (Vertex) sur l’objet. Une valeur élevée de la masse des sommets fera s’effondrer sur lui-même l’objet souple vu que le poids des sommets est trop lourd pour maintenir la structure de l’objet. |
    | Control Point | Permet d’utiliser un groupe de sommets (Vertex Group) pour contrôler la valeur de Masse de l’objet. On peut peindre des valeurs entre 0 à 1 sur chaque sommet (rappelez-vous de la simulation du drapeau). |
    | Speed | Contrôle la vitesse de la simulation. Cette valeur est basée sur les images par seconde (FPS) de la scène. |
    | | |
    | Cache | Certaines de ces options devraient vous être familières car elles sont les mêmes que pour une simulation Mantaflow (le drapeau par exemple). Une chose qui est différente, cependant, est la possibilité d’avoir plusieurs caches. Vous pouvez cliquer sur le bouton + pour créer un autre cache et double-cliquez sur le cache pour le renommer. Vous pouvez ensuite en sélectionner une et modifier les paramètres comme vous le souhaitez avant de faire un Bake; cela n’affectera pas les autres caches. La chose est très utile pour prévisualiser rapidement certains paramètres dans la simulation. Pour basculer entre deux caches, assurez-vous de redémarrer la Timeline, puis sélectionnez la cache que vous voulez prévisualiser avant d’appuyez sur Play.

    Quelle est la différence entre une cache et un bake? La cache est le résultat de l’animation lorsqu’elle est jouée, une ligne orange indique la portée de la cache dans le timeline. Chaque fois que vous changez un paramètre dans la simulation, la cache disparaîtra et vous devrez rejouer l’animation pour la récupérer.

    Dans le cas d’un bake, le résultat de la simulation est verrouillé; ainsi vous ne pourrez pas changer les paramètres à moins de cliquer sur le bouton Free Bake. Dans le timeline, la portée du bake apparaît en rouge. |
    | Cache Step | Permet de sauter des images d’une simulation lors du bake. Au lieu de faire un bake de chaque Frame, on fera un bake d’une image sur deux si cette valeur est réglée à 2 par exemple. Évidemment, la simulation sera alors moins précise, mais le bake prendra moins de temps. |
    | Bake | |
    | Bake All Dynamics | Fera un bake de toutes les simulations de la scène. Si vous avez plusieurs corps souples, systèmes de particules ou simulations de tissu, tous seront “baked” en même temps. |

    Exemples de corps souples

    Effet du paramètre Mass:

    Vertex Group et Weight Painting:

Goal des corps souples

  • Quand on crée un corps souple et qu’on joue l’animation, l’objet flotte simplement et oscille de haut en bas. C’est parce que l’attribut “Goal” est coché dans les paramètres. Un Goal est essentiellement un moyen de fixer les sommets en place. Cela peut être utile lorsqu’on essaie de créer par exemple des couvertures suspendues à une ligne, des coins d’un drapeau fixés à un poteau, des personnages qui marchent…

  • Lorsque Goal est activé, tout l’objet va être “épinglé”. Si vous voulez que seulement certaines parties de l’objet utilisent le Goal, il faut créer un groupe de sommets (Vertex Group) et peindre les sommets en leur donnant une valeur entre 0 et 1 (Weight Paint).
  • Pour créer un Vertex Group, on doit manuellement peindre les sommets en appuyant sur Tab et en sélectionnant Weight Paint (ou régler les valeurs dans les propriétés du Vertex Group crée, comme on a fait pour le drapeau ou le coussin). On compte donc sur le fait que l’objet a suffisamment de géométrie pour utiliser la peinture de poids.

  • Comme on a justement vu avec le drapeau et l’oreiller, on peut créer un Vertex Group dans la section “Object Data Properties” et, en mode Edit, sélectionner les sommets de la géométrie qui servirent de “pin group”.
  • La raison pour laquelle l’objet fait des bonds lorsqu’on lance la simulation est que la valeur du Strength par défaut du Goal est réglée à 0,7; ainsi elle ne fixe les sommets qu’à environ 70%. Si cette valeur est réglée à 1, alors l’ensemble de l’objet, ou plutôt les sommets épinglés seront coincés en place et ne pourront pas bouger (le drapeau fixé au poteau).
  • Les valeurs Min et Max offrent un moyen d’ajuster précisément comment le Vertex Group affecte la simulation.
  • La valeur Min sera la force minimale pour le poids de sommet le plus bas.
  • Maintenant, c’est un peu compliqué à comprendre (je trouve!). Disons que vous assignez l’ensemble de l’objet avec un poids de groupe de sommet de 0 et que vous réglez la valeur Min à 1. Que pensez-vous qu’il va se passer ? L’objet va être complètement coincé car il utilise maintenant une valeur de force de 1 pour l’objectif. Après tout, c’est le minimum. Max fonctionne de la même manière - il contrôle la force d’épinglage de tous les sommets avec un poids de 1.
  • Le paramètre Stiffness (rigidité) contrôle à quel point l’épinglage sera rigide. Dans la capture d’écran suivante, la Rigidité à gauche est réglée à 0.2, et à droite, elle est réglée à 0.999.

  • Enfin, la valeur Damping (amortissement) amortira le mouvement du corps souple jusqu’à ce qu’il cesse de bouger. Plus vous augmentez cette valeur, plus l’objet cessera de bouger rapidement.
  • Le Goal du corps souple est très utile et peut être pratique lorsqu’on essaie de créer certaines simulations comme des drapeaux et tout autre chose qu’on doit épingler (pin).

Edge des corps souples

  • L’option Edges est ce qui donne une certaine structure à l’objet à corps souple. Ainsi, au lieu de s’effondrer sur lui-même, il gardera sa forme. En gros, lorsque les Edges sont activés, cela ajoute des ressorts virtuels à tous les bords (Edges ou arrêtes, i.e. les segments qui relient deux Vertex (sommets) entre eux) de l’objet.

SpringsPermet de contrôler où se trouvent les ressorts dans la géométrie (à l’instar du Vertex Group pour le goal ou le Pin Group).
PullLa valeur agit essentiellement comme un élastique pour la simulation. Plus cette valeur est élevée, plus l‘“élastique” est fort, ce qui signifie que les bords resteront collés ensemble plutôt que d’être étirés.
PushD’autre part, “Push” contrôle combien le corps souple résiste à être écrasé. Vous pouvez le considérer comme la force des ressorts à l’intérieur de quelque chose. Des valeurs plus élevées entraîneront une plus grande résistance.
PlasticityMa valeur la plus chouette des corps souples, cette valeur permet de déformer le maillage de manière permanente lorsqu’il rencontre une collision. Avec une valeur de 100, il restera déformé pour toujours, mais si vous le réglez sur une valeur plus basse, il reviendra alors lentement à sa forme originale.
BendingLes contrôles de flexion déterminent le degré de flexion dans la simulation. Avec un réglage à 0, il s’effondrera simplement sur lui-même, mais avec un réglage plus élevé, il conservera sa structure.
LengthLa longueur réduira ou étendra votre maillage selon la valeur que vous définissez. Par exemple, si la longueur est réglée à 70, alors le maillage se réduira à 70% de sa taille. Si la valeur est réglée à 150, alors le maillage s’étendra de 50% au-delà de sa taille originale.
Collision Edge et FaceLes checkboxes Collision Edge et Face permettront à la simulation de corps souples d’eentrer en collision avec les arêtes (edges) ou les plans (faces). Normalement, seuls les sommets entrent en collision, mais l’activation de Edge ou Face leur permettra également de participer à la simulation de collision. Gardez à l’esprit que lorsque vous activez Face, cela peut coûter très cher en ressources CPU et vous pourriez obtenir beaucoup de tremblements sur l’objet car le réglage Amortissement ne l’affecte pas. À utiliser donc avec parcimonie.
AerodynamicsL’aérodynamique permet à l’objet à corps souple d’avoir une certaine traînée aérienne dans la scène. La valeur du facteur contrôle la quantité de traînée aérienne. Pour voir cela en action, vous devrez régler la valeur du facteur assez haut (2000 ou plus). Cela rendra l’air autour de l’objet très dense, ce qui ralentira la chute de l’objet et le déformera.

Il existe deux types différents d’aérodynamique : Simple et Lift Force. Simple est plus rapide à calculer mais moins précis. Lift Force est plus lent, mais aura plus de réalisme.
StiffnessStiffness (rigidité) ajoute des ressorts virtuels aux bords (edges) d’une face, et Shear (la valeur de cisaillement) contrôle la rigidité de ces ressorts. Lorsqu’elle est activée, elle empêche l’objet de s’effondrer sur lui-même.

Il faut noter que la rigidité fonctionne uniquement avec les faces quadrilatérales (quads, i.e. 4 sommets (vertices) par plan (face)). Un plan à trois sommets ne fonctionnera pas, le réglage de la rigidité n’aura alors aucun effet.

C’est entre-autres de là que vient la manie de vouloir des quads dans nos maillages plutôt que des triangles (bien que les cartes graphiques aient été longtemps optimisées pour des calculs autour de plans constitués de trois sommets, i.e des triangles).

Effet du paramètre Pull

Effet du paramètre Push

Effet du paramètre Plasticity

Effet du paramètre Bending

Effet du paramètre Stiffness

Self Collision

  • Le Self Collision, lorsqu’activé, fera entrer l’objet simulé en collision avec lui-même. C’est utile lors de la création de tissus, ou de vêtements par exemple. Si le paramètre n’est pas activé, le corps passera simplement à travers lui-même sans tenir compte de collisions possibles.
  • Le Self Collision fonctionne en créant une petite balle virtuelle autour de chaque sommet et en l’utilisant pour les calculs de collision. La taille de cette balle virtuelle peut être contrôlée par le paramètre Ball Size.
  • Si la valeur de Ball Size est trop élevée, une zone de collision de sommet pourrait interférer avec une autre. Cela amène le corps souple à s’étirer pour compenser la zone de collision. Si vous constatez que votre objet à corps souple se dilate lorsque vous activez le Self Collision, vous devez probablement diminuer la valeur de la taille de la balle.

Avec et sans Self Collision

  • Le type de calcul définit comment la taille de la sphère de collision sera définie. Vous pouvez choisir parmi les options suivantes :
    • Manual vous permet de définir manuellement la taille de la sphère de collision.
    • Average prend la longueur moyenne de chaque arête et la multiplie par la valeur de la Taille de la sphère.
    • Minimal prend l’arête la plus petite de l’objet et la multiplie par la valeur de la Taille de la sphère.
    • Maximal fait l’inverse. Il prend la plus grande arête et la multiplie par la valeur de la Taille de la sphère pour déterminer la collision.
    • Enfin, Average Min & Max ajoute les deux, divise par 2, et multiplie le résultat par la valeur de la Taille de la sphère.
  • Dans la plupart des situations, vous n’avez pas besoin de changer ces paramètres, donc restez simplement avec Average.
  • La rigidité (Stiffness) contrôle comment la collision avec soi-même fonctionne lorsqu’un sommet entre dans la sphère de collision d’un autre sommet.
  • Lorsqu’elle est réglée à une valeur élevée, elle repoussera très rapidement le sommet. Lorsqu’elle est réglée à une valeur plus basse, elle le repoussera lentement.
  • L’amortissement (Dampening) est utilisé pour ralentir un sommet lorsqu’il se rapproche de la sphère de collision d’un autre sommet. Des valeurs élevées le ralentiront très rapidement.
  • La plupart du temps, tout ce que vous avez à faire est d’activer le Self Collision et tous les paramètres par défaut fonctionneront adéquatement.

Solver

  • L’onglet Solver aide à rendre la simulation plus précise. Parfois, avec des collisions rapides, la simulation aura du mal à calculer, et vous pourriez avoir quelques erreurs et problèmes avec les collisions. Cependant, dans cet onglet, vous pourrez modifier les paramètres afin d’obtenir une simulation plus précise et donc plus réaliste.
Step Size MinLorsque la simulation rencontre des erreurs ou si les collisions ne fonctionnent pas correctement, on peut augmenter le réglage Step Size Min. Cette valeur indique combien de fois la simulation sera calculée par image.
MaxLe nombre maximum de steps (passes) par frame dans le calcul.
Auto-StepBlender va se baser sur la vitesse de l’objet (Velocity) pour automatiquement régler le nombre de steps.
Error LimitPlus cette valeur est petit, plus la tolérance à l’erreur sera faible et plus précise sera la simulation.
DiagnosticOn peut imprimer les performances du solveur dans la console pour voir comment la simulation fonctionne. Sur Windows, il faut aller dans le menu “Windows → Toggle System Console. (La même console qu’on utilise pour troubleshooter des problèmes de programmes Python. Si si, on peut créer une scène au complet, avec animation, keyframes, simulations, et calculs, en écrivant du code Python.

Sur Mac, il faut démarrer Blender via un SHELL (Terminal) pour pouvoir voir ce qui est imprimé dans la console.
FuzzyLa valeur Fuzzy (flou) définit la précision d’une collision. Des valeurs élevées permettent un calcul de simulation plus rapide mais moins précis.
  • Si un objet pénètre à travers une collision, la simulation essaiera de le repousser avec une certaine vitesse. Cette dernière est contrôlée par les valeurs d’étranglement (Choke). Des valeurs plus élevées ralentiront le corps souple lorsqu’il sort d’une collision.

Field Weights

  • Le dernier onglet dans la simulation de corps mou est le Field Weights. Cela fonctionne exactement comme avec la simulation de fluide. Vous pouvez définir certaines forces pour certains champs de force et personnaliser quels champs de force fonctionneront dans votre simulation.
  • Si vous avez plusieurs champs de force dans votre scène, vous pouvez choisir quelle collection utiliser dans le menu Collection d’Effector. Ainsi, seuls les champs de force de cette collection affecteront la simulation.

Interaction entre plusieurs objets souples

  • Pour certaines simulations, plusieurs corps mous interagissent entre eux, il faut alors leur rajouter un Collision Modifier afin qu’ils puissent se heurter entre-eux adéquatement. Il est important que le Collision Modifier, dans la pile des modifiers, soit appliqué APRÈS le Softbody modifier.

Des corps souples interagissant ensemble

Pour en savoir plus

Une course à obstacles de corps souples

Création du soft body

  • Sélectionner l’objet nommé Soft Body Sphere et lui donner la propriété Soft Body dans les paramètres de propriétés Physiques.
  • Augmenter la Mass à 2 pour qu’elle soit un peu plus lourde.
  • Dans la section Cache, mettre End Frame à 600.
  • Pour l’instant, désactiver “Goal” afin que l’objet ne flotte pas. Plus tard on le réactivera.
  • Dans la section Edges, instaurer les valeurs suivantes:
    | Paramètre | Valeur | Description |
    | --- | --- | --- |
    | Push | 0.6 | Cela va donner une certaine structure et rigidité à la sphère, une résistance à l’étirement |
    | Pull | 0.6 | Ici une certaine résistance à l’écrasement |
    | Damp | 40 | Lorsque la sphère entrera en collision avec un objet, elle vibrera et rebondira beaucoup sans amortissement. On va lui demander de se calmer le pompon un peu |
    | Bending | 2.5 | Empêchera la sphère de s’écrouler sous l’effet de cisaillements (Shear) et ce faisant perdre sa structure. |

Ajout du Collision

  • Sélectionner la Soft Body Sphere et lui ajouter un modifier “Collision” (Add Modifier → Physics → Collision). S’assurer que Collision soit après Soft Body dans le stack des modifiers autant dans les modifiers( clé à mollette) que dans les propriétés physics.
  • Sélectionner l’objet Cylinder 1 (celui du haut, le premier du parcours) et lui attribuer la propriété physique “Collision”.
  • Dans les propriétés Modifiers, s’assurer que le modifier Collision est avant (au-dessus) le Solidify Modifier qui est déjà là.
  • Ici, il est très important de noter que nous au préalable inversé la direction des normales du Cylinder 1 pour qu’elles pointent vers l’intérieur puisque c’est là que se passe l’interaction avec la sphère. Par défaut, lorsqu’on crée un cylindre, ou tout autre objet “plein”, les normales pointent vers l’extérieur et non pas vers l’intérieur de l’objet.

Banque de cours - Collision et direction des normales

📌

Une collision est basée sur la direction des normales à la surface. Les normales d’un objet sont la direction dans laquelle les faces sont orientées (un vecteur perpendiculaire à chaque plan). Il faut parfois recalculer les normales et voir dans quelle direction celles-ci pointent pour que la simulation fonctionne. Pour ce faire, en mode Édition avec l’objet sélectionné, appuyer sur A pour sélectionner tous les sommets sur le maillage (mesh) puis choisir le menu Mesh → Normals → Recalculate (⇧ N). On peut également activer la visualisation de l’orientation de chaque plan (face) dans le menu Overlays pour voir dans quelle direction les plans sont orientés.

Lien vers l'original

  • Passons maintenant au Cylinder 3 (le cylindre 2 n’a pas besoin d’être un objet Collision). Sélectionner l’objet Cylinder 3 et lui ajouter un modifier Collision.

  • S’assurer que le modifier Collision soit le premier dans le stack des modifiers.

  • Régler Inner à 0.001 sinon le calcul de collision ne se fera pas correctement car il y aura “overlap” entre les bounding boxes de la sphère et ceux du cylindre (les fameux paramètres Inner et Outer).

  • Pour sauver du temps, le Cylinder 3 est déjà animé pour s’ouvrir et se fermer. Au frame 40, il commence à s’ouvrir, et il est complètement refermé au frame 80.

  • Faites “Play” pour voir?

⚠️

Pour aller un peu plus vite, vous pouvez rester dans les propriétés Modifier et faire “Add Modifier” puis choisir “Collision” et le remonter dans la stack des modifiers pour qu’il soit le premier.

  • Maintenant sélectionner Platform 1 et lui ajouter un paramètre Collision et, encore une fois, le déplacer pour qu’il soit le premier en haut dans la pile des modifiers.
  • Faire exactement la même chose pour Platform 2 et Platform 3.n
  • Même chose pour l’objet Gear Left.
  • Même chose pour l’objet Gear Right.

Rotation des engrenages.

  • Sélectionner Gear Right and ouvrir le N Panel (touche N). Dans la section Rotation, changer la valeur de Y pour “#frame/-25”. Cela va rajouter un “driver” de rotation où, essentiellement, l’engrenage va tourner vers la gauche (en vue orthogonale de face) d’une valeur de 1/25 du No du frame dans l’animation. Chouette non?
  • Notez que le champ Y Rotation est maintenant violet, i.e. il est devenu un driver d’animation.
  • Pour l’engrenage de gauche, faire la même chose mais changer le signe du diviseur, on veut diviser par +25 et non pas -25, pour que cet engrenage tourne vers la droite, donc Rotation Y = “#frame/25”
  • Faites Play et vous verrez les engrenages tourner.

  • Ajouter une collision au reste des objets, à l’exception de l’objet “Goal Guide”, et s’assurer bien de, à chaque fois, déplacer le Collision Modifier au sommet de la pile de modifiers pour chaque objet sinon vous pourriez obtenir des résultats étranges.
  • Pour le Glass Cylinder, réglez le Damping à 0.5 pour amortir la collision. Cela aidera la sphère à ne pas trop rebondir.

Simulation de tissu

  • Choisir l’objet Cloth 1. Dans les propriétés Physics, ajouter un “Cloth”.
  • Passer au mode Edit Faces, choisir les 4 faces qui forment les coins du tissu
  • Dans les propriétés Data, créer un nouveau Vertex Group et appuyer sur le bouton Assign.
  • Revenir en mode Object, aller dans la section propriétés Physiques et dans la section Shape, assigner le Vertex Group dans Pin Group.
  • Changer le End Frame dans Cache à 600.
  • Dans les propriétés Modifier et dans Physics, il est important que le Cloth Modifier soit avant Collision.
  • Faites exactement à Cloth 2 ce qu’on vient de faire pour Cloth 1 (vertex group, cloth sim, end frame à 600, pin group, …)

Soft Body Goal

Un peu de théorie (encore)

  • Activer le Goal pour un objet Soft Body indique à Blender d’utiliser la position (ou la position animée) d’un sommet dans la simulation. L’animation des sommets peut être effectuée de toutes les manières habituelles (courbes F, armatures, parents, treillis, etc.) avant l’application de la simulation de corps souple. Le Goal est la position finale souhaitée pour les sommets.
Vertex GroupGroupe de sommets pour permettre des poids de Goal par sommet (multipliés par l’objectif par défaut).
Setting
Stiffness
La rigidité du ressort pour le Goal. Une valeur faible crée des ressorts très faibles (attache plus flexible au Goal), une valeur élevée crée un ressort fort (une attache plus rigide au Goal).
Settings
Damping
Le coefficient de frottement pour le Goal. Des valeurs plus élevées donnent un amortissement de l’effet de ressort (fabiles secousses), et le mouvement s’arrête (s’amortit) rapidement.
Strengths
Default
Poids/force du Goal pour tous les sommets lorsqu’aucun groupe de sommets n’est assigné. Si vous utilisez un groupe de sommets, le poids d’un sommet définit son Goal.
Strengths
Min/Max
Lorsque vous utilisez un groupe de sommets, vous pouvez utiliser le Minimum et le Maximum pour affiner (limiter) les valeurs de poids. Le poids du sommet le plus bas devient le Minimum, la valeur la plus élevée devient le Maximum.
  • A “goal” is a shape that a soft body object tries to conform to. It acts like a pin on a chosen set of vertices, controlling how much of an effect soft body has on them.
  • Enabling Soft Body Goal tells Blender to use the position (or animated position) of a vertex in the simulation. Animating the vertices can be done in all the usual ways (F-Curves, armatures, parents, lattices, etc.) before the soft body simulation is applied. The “goal” is the desired end position for vertices. How a soft body tries to achieve this goal can be defined using stiffness forces and damping.

Goal Strength

  • La *Force du Goal *définit combien de mouvement d’un système d’animation est appliqué.
  • Une valeur Goal de 1.0 signifie qu’il n’y a pas de simulation de corps souple, l’objet agit comme n’importe quel objet animé régulier (c’est-à-dire que le sommet est maintenu à sa position originale). Lorsque Goal est réglé sur 0.0 (ou pas de but), le sommet est uniquement influencé par les lois physiques selon la simulation de corps souple.
  • En définissant des valeurs de Goal entre 0.0 et 1.0, vous pouvez effectuer un mélange entre l’effet de l’objet affecté uniquement par le système d’animation et l’effet de l’objet affecté uniquement par l’effet de corps souple.
  • Le Goal sert également de mémoire, pour s’assurer que les objets souples ne se déforment pas trop (pour ne pas aboutir à la forme animée non souple). En utilisant le système de poids Vertex Group, vous pouvez définir un poids Goal par sommet. Pour rendre cela plus naturel, des forces de ressort peuvent être définies pour contrôler jusqu’où les sommets peuvent se déplacer de leur position d’origine.

Détails techniques

  • Dans le monde des corps souples, les sommets des maillages sont traités comme des particules ayant une masse. Leur mouvement est déterminé par les forces qui les affectent. En plus d’autres forces, les particules individuelles peuvent interagir les unes avec les autres le long des arêtes en utilisant un modèle physique qui est très proche des amortisseurs utilisés dans les voitures. Les pièces fonctionnelles sont :
    • Un ressort essaye de maintenir les particules à une certaine distance. L’effort que le ressort fait pour cela est contrôlé par le paramètre de corps mou Rigidité.
    • Un élément d’amortissement pour calmer le mouvement. La résistance que l’élément construit contre le mouvement est contrôlée par le paramètre de corps souple Amortissement.
  • Nous allons apprendre comment utiliser le Soft Body Goal pour faire suivre une courbe à la sphère. Si vous vous souvenez du chapitre précédent, le Goal permet de fixer et d’animer un corps mou. Le Goal du corps souple est d’essayer de revenir à sa position originale, ou là où se trouve le point d’origine. C’est pourquoi, lorsqu’on active Goal, l’objet se balance simplement de haut en bas : il essaie de revenir au point d’origine.
  • Donc, ce que nous allons faire est d’activer le Goal lorsque la sphère entre dans l’objet Tube de Verre. Ensuite, la sphère suivra la courbe qui est à l’intérieur, rebondissant et frappant les murs jusqu’à ce qu’elle tombe de l’autre côté.
  • En premier, il faut trouver à quel frame la sphère entre dans le tube de verre. Ça devrait être autour du frame 430.

  • On ne peut pas animer Default de la section Strength, mais on peut animer Min et Max.
  • Déplacer la tête de lecture dans le timeline au frame 430.
  • Dans les propriétés physiques de la sphère, Activer “Goal”.
  • Ajuster les valeurs Min et Max dans la section Strength de Goal à 0 et activer le bouton keyframe pour en insérer un pour les deux valeurs (Min et Max).

  • Maintenant déplacer la tête de lecture au frame 431, et changer la valeur de Min et Max à 0.5.

  • Ne pas oublier de cliquer sur le bouton d’ajout de keyframe à droite des champs Min et Max.

  • Configurons la sphère pour qu’elle suive une courbe !

  • Dans le panneau des contraintes ajouter une contrainte de type Follow Path.

  • Dans Target, choisir l’objet “Goal Guide”, c’est une courbe déjà existante qui se promène à l’intérieur du tube de verre.

  • L’offset contrôle quand l’objet commence à suivre la courbe, dans notre cas indiquer 431.

  • Cliquer sur Animate Path.

  • En faisant Play, vous allez peut-être remarquer que la sphère est super loin à gauche!

  • Pour régler la chose, ajoutons des keyframes de positionnement pour la sphère. Essentiellement, quand on anime la sphère et qu’elle commence à suivre la courbe, son origine doit se trouver au début de la courbe.

  • Aller au Frame 1.

  • En mode vue orthogonale frontale (Numpad 1, pour éviter les déplacements selon l’Axe des Y), déplacer la sphère à l’intérieur du Cylinder 1, un peu au-dessus du Cylinder 3. Assurez-vous que la sphère soit bien à l’intérieur et n’intersecte aucun objet.

  • Au frame 1 donc, faites I pour insérer un Keyframe au frame 1.

  • Maintenant aller au Frame 429, i.e. juste avant les premiers keyframes du Goal de la sphère.

  • En mode vue orthogonale frontale toujours (Numpad 1), déplacer la sphère au début de la courbe guide et faire derechef I pour insérer un autre Keyframe.

⚠️

Pour bien le faire, cacher le Glass Cylinder pour bien voir la courbe Goal Guide et déplacer la sphère de manière à ce qu’elle coïncide avec le début du guide. vous êtes bien au frame 429 n’est-ce pas! Le cas échéant, faire I pour insérer un keyframe de positionnement de la sphère.

N’oubliez de “unhide” le Glass Cylinder en ouvrant l’oeil à gauche de l’objet dans la section Outline.

  • La sphère devrait alors, au frame 430, commencer à suivre le guide!

  • Maintenant, on veut arrête le Goal au moment où la sphère commence à sortir du tube (frame 517).

  • Aller au frame 517. Avec la sphère sélectionnée, dans les propriétés Physics, section Strength de Goal, on doit keyframé à 0.5 les valeurs Min et Max afin qu’elle restent constante depuis le frame de départ (431).

  • Cliquez donc sur les petits points blancs à droite des champs Min et Max.

  • Au frame suivant (518), mettre les valeurs de Min et Max à 0 et les keyframer derechef.

  • C’est comme si on avait désactivé le “Goal”.

  • On a terminé, cliquer, dans la section “Cache”, sur le bouton “Back All Dynamics”.

  • Faire Play!

Textures

  • Profitons-en pour utiliser EEVEE, le rendu temps-réel de Blender à la place de Cylces. En particulier, on va créer un Glass Shader en EEVEE. Je ne sais pas encore si ce sera encore nécessaire avec la venue de EEVEE-Next (Blender 4.2), ce sera encore nécessaire puisque ce dernier aura un Ray-tracer.

  • Dans les propriétés Render, choisir EEVEE à la place de Cycles.

  • Activer Raytracing

  • Activer Motion Blur.

  • Dans la section Color Management, choisir le Look Very High Contrast.

  • Sélection Cylinder 1 et aller dans le Shading Editor.

  • Faire New. Nommer le Material Glass.

  • Dans les propriétés Material, aller dans la section Settings.

  • Activer le Backface Culling (l’occlusion des faces arrière). En infographie, l’occlusion des faces arrière détermine si un polygone est dessiné à l’écran ou pas. C’est une étape dans le pipeline graphique qui teste si les points du polygone apparaissent dans le sens horaire ou anti-horaire lorsqu’ils sont projetés sur l’écran. Si l’utilisateur a spécifié que les polygones face à la caméra ont un enroulement dans le sens horaire, mais que le polygone projeté sur l’écran a un enroulement dans le sens anti-horaire, alors il a été tourné pour faire face à l’opposé de la caméra et ne sera pas dessiné.

  • Le processus rend le rendu des objets plus rapide et plus efficace en réduisant le nombre de polygones que le programme doit dessiner. Par exemple, dans une scène de rue de ville, il n’est généralement pas nécessaire de dessiner les polygones sur les côtés des bâtiments qui sont tournés loin de la caméra ; ils sont complètement occultés par les côtés qui font face à la caméra.

  • En général, il peut être supposé que l’élimination des faces arrière ne produit aucun artefact visible dans une scène rendue, à la condition que la scène ne contienne que des maillages fermés et opaques. Dans les scènes contenant des polygones transparents, les polygones orientés vers l’arrière peuvent devenir visibles à travers le processus de composition alpha et c’est ce que nous allons faire en changeant le Blend Mode (voir plus bas).

  • Ici, à gauche le Backface Culling est désactivé, à droite il est activé. Notez que ça ne donne pas les résultats escomptés dans le cas d’objets concaves, ou avec des trous comme ici un crâne. Dans le cas de Blender, comme le Show Backface est activé, l’intérieur du crâne sera montré.

  • Changer le Blend Mode pour Alpha Blend, justement pour compenser le backface culling sur les objets transparents.

  • Activer Raytrace Refraction.

  • Bon, ça commence à donner du résultat, mais on peut fire mieux!

  • Dans le Shading Editor, ajouter un Transparent BSDF (⇧ A Shader → Transparent BSDF)

  • Ajouter un Mix Shader afin de mixer les deux shaders, le Principled BSDF et le Transparent.

  • Pour contrôler où aura lieu la transparence, on va utiliser un input de type Fresnel. ⇧ A → Input → Fresnel.

  • Un noeud Fresnel éclaire les bords d’une surface tout en gardant le milieu plus sombre. Voici par exemple une sphère avec du Fresnel appliqué:

  • Dans notre cas, on veut appliquer de la transparence au milieu du cylindre tout en gardant ses bords intact, i.e. l’effet du Glass Shader. On se débarrassera du drôle d’étirement de la transparence qu’on a en ce moment.

⚠️

Si vous voulez en savoir plus sur le chouette effet Fresnel (qu’on retrouve beaucoup en photographie): https://www.dorian-iten.com/fresnel/

  • Changer l’IOR du noeud Fresnel à 1.45 (l’indice de réfraction de certains types de verres).
  • Nous avons maintenant un shader satisfaisant:
  • On peut maintenant réutiliser ce shader pour le Glass Cylinder et le Glass Tube et l’objet Box.
  • Pour ce faire, sélectionner Les trois objets puis Cylinder 1 en dernier (important!), aller dans le menu Object → Link/Transfer Data → Link Materials. Le shortcut et ⌃ L (ou ⌘ L sur Mac).
  •  Amusez-vous à changer les materials des autres objets si vous le désirez.

Tracking Caméra

  • Aller au Frame 1 et sélectionner la caméra

  • Ajouter une contrainte de type “Copy Location” à la caméra.

  • Dans le menu Target, choisir la Soft Body Sphere et désactiver Y axis ainsi que X Axis. On veut que la caméra suive seulement l’axe des Z (la hauteur) de la sphère.

  • Activer Offset. Cela permettra de ramener la caméra à sa position d’origine (avant la contrainte)

  • Par contre, ça ne fonctionne pas encore tout à fait car la caméra suit pour l’instant l’origine de la sphère et non pas sa géométrie (remember, it’s baked!).
  • On va rajouter un Vertex Group.
  • Sélectionner la sphère, aller en mode Vertex Edit Mode et créer un nouveau Vertex Group dans Object Data.
  • Sélectionner tous les sommets de la géométrie de la sphère et cliquer sur Assign dans Object Data.

  • Revenir en Object Mode.

  • Sélectionner la caméra et dans ses paramètres Constraints, choisir le nouveau Vertex Group.

  • Au frame 1, Déplacer la caméra à l’endroit désiré. La tourner également selon l’angle de vue désiré.

  • Sélectionner la sphère, aller dans Physics, et dans la section Cache, cliquer sur Delete All Bakes puis sur Bake All Dynamics.

  • Faites Play.

  • Modifier les paramètres d’output pour générer une vidéo avec un frame rate de 30 fps.

  • Faire Render Animation!

  • Avec EEVEE, les rendus sont en quasi temps réel. Mais c’est quand même 600 frames. À disons 1 seconde par frame, ça va quand même prendre 10 minutes!

Résultat

À vous de jouer

  • Ajouter un nouvel élément au parcours (par exemple en enlevant le plan à la base et en modifiant le maillage de la boîte de réception de la balle pour qu’elle puisse continuer son parcours
  • Ajouter un HDRI pour rendre le background plus intéressant
  • Jouer avec les textures et couleurs.
  • Une 2e balle?

Devoirs Aucun, vous êtes assez chargé.es comme ça!

Lien vers l'original

Banque de cours - Animation en boucle chaîne de montage

# Animation en boucle: chaîne de montage

📌

Un énorme merci à Roman Klco de Polygon Runway pour son tuto et son aimable permission de s’en inspirer.

Une animation de chaîne de montage en boucle continue

Modélisation - le convoyeur

💡

D’après un tutoriel de Roman Klčo et son excellente chaîne Youtube Polygon Runway, avec son aimable permission

  • Créer un nouveau dossier dans lequel on ajoute un fichier .blend nommé “Chaine Montage.blend”.

  • Ajouter un Plane, passer en Vertex Edit Mode, ajouter un loop cut (^ R) au milieu du plan le long de l’axe des X

  • Sélectionner les deux sommets de droite (du côté de l’axe des Y positif) et les effacer (X puis Delete Vertices).

  • Revenir en mode Object, vous devriez avoir ceci, avec le milieu de l’arrête de droite coïncidant avec l’origine du monde, où se trouve également le curseur. Cela sera important lors de l’animation

  • Revenir en Vertex Edit Mode

  • Sélectionner les 4 sommets, Extrude (E) vers l’axe des Z négatifs (le bas).

  • Sélectionner tous les sommets puis faire ⇧ N pour recalculer les normales (on veut être certains qu’elles soient dans la bonne direction).

💡

Pourquoi on doit faire ça? Parce qu’on est parti d’un plan (donc une surface 2D sans épaisseur), et il se peut que la normale du plan, qui n’a pas d’épaisseur, soit dirigée dans le même sens que l’extrusion qu’on vient de faire. Le cas échéant, les normales risquent de pointer vers l’intérieur de l’objet et ce n’est pas ce qu’on veut.

  • Pour voir la direction des normales, assurez-vous d’être en Edit Mode puis ouvrir le menu “Mesh Edit Mode” qui se trouve à droite du menu “Overlays”. Activer Face Normals. Vous devriez voir des petits cheveux bleus qui font 90 degrés par rapport à chaque surface. Assurez-vous que les normales pointent vers l’extérieur de l’objet.

  • Revenir on Mode Object.

  • Ajouter un “Array Modifier” à l’objet.

  • Changer le Count à 5 et la direction à -Y, donc un facteur de -1 sur le Factor Y, et 0 pour X et Z

  • Ajouter un Bevel Modifier, changer Amount à 0.03 et Segments à 2.

  • Dans la section Shading, activer “Harden Normals”.

  • Cliquer droit sur l’objet et faire Shade Smooth.

  • Ajouter un nouveau Plane. En mode Vertex Edit, Faire un Scale down de manière à ce que ce plan soit à peu près les 2/3 en longueur par rapport au premier Plane.

  • Faire ⌃ ⇧ B pour faire un Bevel des Vertex, bouger la souris pour créer le bevel et ajuster le nombre de segments avec la roulette de la souris (5 ou 6 segments).

⚠️

Vous pouvez aussi ajuster le nombre de segments dans les paramètres de création

  • Sélectionner tous les sommets, puis Extrude vers l’axe des Z positifs.
  • I pour inset un petit peu, puis E pour un autre Extrude vers l’axe positif des Z, mais plus court celui-là. Ça devrait donner ceci:
  • Ici je fais exprès de montrer les normales.
  • Pour être sûr, sélectionner tous les sommets puis faire ⇧N pour recalculer les normales.
  • Revenir en mode Object
  • Sur cet objet, on va imprimer un logo.
  • Sauvegarder le fichier

Modélisation - Le logo en SVG

⚠️

Ne pas faire de drag and drop, ça ne donnera pas le même résultat (Blender le traitera comme un Grease Pencil Object plutôt qu’une série de courbes)

  • Le SVG sera importé comme une série de courbes (c’est vectoriel un svg, ça tombe bien 😊 )

  • Sélectionner la première courbe de la collection (Nommée Curve dans la collection Blender_logo_no_text.svg)

  • Zoomer sur le SVG avec Numpad .

  • Avec l’objet Curve toujours Sélectionné, l’effacer (X), nous n’en avons pas besoin.

  • Sélectionner Curve.001 et dans les propriétés de la courbe, assurez-vous que “Fill mode” est à none: on ne veut que le contour.

  • Faites la même chose pour Curve.002

  • Vous devriez avoir ceci maintenant.

  • Sélectionner les deux courbes (Curve.001 et Curve.002) et dans le menu Object, choisir Convert → Mesh.

⚠️

Assurez-vous que X-Ray est activé!

  • Passer en mode Edit Vertex, vous devriez avoir ceci:

  • Revenir en mode Object. Sélection Curve.002 et passer en mode Edit Vertex

  • Avec la touche Alt maintenue, sélectionner le cercle intérieur de Curve.002

⚠️

Ce n’est pas le très petit cercle, celui-là appartient à Curve.001!

  • Cela devrait sélectionner tout les sommets du cercle.

  • Faire P pour Separate, choisir Selection et faire Enter. Cela va séparer la sélection (le cercle) et le faire devenir son propre objet.

  • Dans l’outliner, vous allez voir un objet Curve.003

  • Revenir en mode Object.

  • On va maintenant réduire la géométrie sur chaque objet, il y en a trop.

  • Sélectionner Curve.001 et passer en mode Edit Vertex.

  • Sélectionner tous les sommets (vertices), puis faire Mesh → Merge → By Distance (M puis choisir “By Distance”) et choisir 0.001 dans les propriétés du merge en bas à gauche

  • Refaire la même chose pour Curve.002

  • Et la même chose pour Curve.003

  • Dans le cas de Curve.003, un petit bobo apparaît ici:

  • Il suffit de sélectionner les deux sommets en litige, celui du coin et celui du milieu:

  • Et faire un autre Merge By Distance, avec une distance cette fois-ci de 0.01m pour que le merge se fasse correctement.

  • Sélectionner Curve.002 (le cercle avec les 3 tentacules), passer en mode Edit Vertex

  • Sélectionner tous les sommets (Vertex) et appuyer sur F pour “Fill” et créer une Face.

  • Revenir en mode Object

  • On va maintenant créer un objet solide avec le cercle intermédiaire (Curve.003).

  • Sélectionner Curve.003 et passer en Vertex Edit Mode

  • Sélectionner tous les sommets et faire F pour créer une face.

  • Tout sélectionner Extrude (E) un peu vers le haut

  • Tout sélectionner puis ⇧ N pour recalculer les normales.

  • Aller en mode Face Edit. Passer en vue orthogonale frontale et déplacer ce disque vers l’axe des Z négatifs (G Z puis bouger la souris vers le bas) de manière à ce qu’il se trouve à cheval avec les autres courbes au milieu

  • Revenir en mode Object.

  • Avec Curve.002 sélectionné, ajouter un Boolean Modifier. Dans Object, sélection le disque (Curve.003).

  • Si vous voyez un beau cercle, c’est que l’opération Boolean Difference a fonctionné. Sinon, faite un Scale selon l’axe des Z du disque, il est peut-être trop étroit.

  • On peut “appliquer” le Boolean Modifier

  • On efface le disque, on en a plus besoin (sélectionner Curve.003 puis faire X).

  • Sélectionner le cercle intérieur maintenant (Curve.001), passer en mode Vertex Edit, tout sélectionner et faire F pour créer une face.

  • Revenir en mode Object.

  • Sélectionner Curve.001 et Curve.002 et faire ⌘ J (^ J sur Windows) pour faire un merge des deux maillages. Nous avons maintenant un seul objet nommé Curve.002. Le renommer à “Blender Logo”.

⚠️

On aurait pu trouver ou créer un mesh directement plutôt que de passer par un svg. Mais voilà, maintenant vous savez quoi faire avec un SVG!
On peut également générer des SVG avec Blender, pour ce faire, activer le Addon Render: Freestyle SVG Exporter. En l’activant, une section “SVG Export” va apparaître dans les propriétés Render.

  • Enfin, on est prêt à donner une profondeur au logo.

  • Sélection Blender Logo, passer en mode Vertex Edit. Tout sélectionner.

  • Extrude (E) vers l’axe des Z positifs.

  • Tout sélectionner puis ⇧ N pour recalculer les normales.

  • Refaire apparaître les deux objets cachés (Plane et Plane.001).

  • Passer en vue orthogonale d’élévation (Numpad 7) et sélectionner Blender Logo.

  • Passer en mode Wireframe et déplacer + Scale du logo de manière à ce qu’il soit positionné ainsi:

⚠️

Notez bien la position du curseur dans le trou vide du logo.

⚠️

Pourquoi en déplace en mode Edit au lieu de mode Object? Ça permet de déplacer le mesh par rapport à l’origine, plutôt que de déplacer le mesh ET son origine!

  • Passer en vue orthogonale frontale (Numpad 1) et déplacer le logo (G Z) de manière à ce qu’il dépasse un peu le dessus de l’objet Plane.001.

  • Revenir en vue perspective, passer en mode Solid View (Z → Solid).

  • Sélectionner Plane.001, puis Shift-Select l’objet Plane. Dans le modifiers, choisir le menu du Bevel Modifier et faire Copy to Selected.

⚠️

Il est important de noter que l’on transfert ou copie le modifier du dernier objet sélectionné. C’est chouette de pouvoir ainsi transférer des modifiers d’un objet à l’autre.

  • Sélectionner Plane.001 et cliquer-droit pour faire Shade Smooth.

  • Dans le Bevel Modifier, baisser le “Amount” à 0.02

  • Dans Edit → Preferences, activer l’Addon “Object: Bool Tool” et s’assurer de faire save preferences si l’Autosave Preferences n’est pas activé par défaut (le hamburger menu en bas à gauche de la fenêtre des préférences)

  • Sélectionner le logo Blender, puis Shift-Select Plane.001 et faire ^ Numpad - (Control et le “-” dans le numpad)

  • Cela ajoutera un boolean modifier au Plane.001 avec une opération de différence Booléenne du Logo

⚠️

L’avantage de cette méthode via le Bool Tool (plutôt que de rajouter un Boolean Modifier manuellement) c’est que l’objet opérateur Booléen (le logo ici) est automatiquement caché après l’opération booléenne. Vous constaterez que le logo est maintenant exclu du Render (le pictogramme Caméra est désactivé dans l’outliner) et Blender a également modifié la propriété “Display as” dans la section “Viewport Display” des propriétés “Object” du logo pour qu’elle ait la valeur “Bounds”.

  • Ok, sélectionner le logo, puis Plane.001, faire ^ P et choisir “Object” pour créer une hiérarchie parent-enfant entre le logo et sa plateforme.

  • Vous devriez voir que Plane.001 a maintenant pour enfant Blender Logo

  • Assurons-nous mainenant que Plane.001 est un enfant du Plane (le convoyeur).

  • Sélectionner Plane.001 puis Shift-Select de Plane et faire encore une fois ^ P → Object.

  • Maintenant le convoyeur (Plane) a pour enfant Plane.001 qui a pour enfant le logo. Ainsi, si le convoyeur bouge, le reste va bouger avec.

⚠️

Si vous voulez un plus beau rendu (avec les occlusions) en mode Solid, activer Cavity

  • Sélectionner le logo Blender et clique-droit puis Shade Smooth
  • Ça va avoir l’air tout bizarre. Sélection Plane.001, ajouter un “Smooth by Angle” modifier, et changer l’angle à 45 degrés. Ça va régler le problème.
  • Ça avance, ça avance!
  • File → Save!

Modélisation - L’arche

  • Ajouter un Plane.
  • Passer en mode Vertex Edit
  • Tout sélectionner et tourner de 90 degrés par rapport à l’axe des X (R X 90 ↩)
  • Scale de 1.1 (s 1.1 ↩)
  • Sélectionner les deux sommets (vertices) du haut et les monter de 1 m (G Z 1 ↩)
  • Avec les deux sommets du haut sélectionnés, ⌃ ⇧ B pour un bevel, déplacer la souris pour créer le bevel et utiliser la roulette de la souris pour créer environ 6 à 7 segments.
  • Passer en mode Edges, sélectionner l’arrête du bas et l’effacer (X → delete edges)
  • La Face va automatiquement disparaître
  • Passer en mode Vertices et tout sélectionner
  • E pour extrude, Y pour contraindre le long de l’axe des Y et déplacer la souris vers l’axe des Y négatifs
  • Sélectionner tous les points, puis faire ⌥ E (Alt-E) et choisir extrude along normals
  • Appuyer sur S pour faire un “Even Scaling” et déplacer la souris de manière à faire un extrude vers l’extérieur de l’arche puis appuyer sur enter quand on est satisfait de l’épaisseur
  • Tout sélectionner à nouveau et faire ⇧ N pour recalculer les normales.
  • Revenir en mode objet

Modélisation - La presse

  • Ajouter un Cylinder.
  • Scale de 0.6 (S 0.6 ↩)
  • Puis scale selon l’axe des Z de 0.7 (S Z 0.7 ↩)
  • Déplacer le cylindre vers le haut de manière à ce que le sommet de l’arche passe au travers son milieu (G Z 2.2 ↩ à peu près). G Z et déplacer avec la souris, c’est plus facile et ça n’a pas besoin d’être très précis.
  • Le cylindre n’est pas centré selon l’axe des Y par rapport à l’arche; pas grave, on règlera ça plus tard
  • ⇧ S et choisir “Snap Cursor to Selected” pour déplacer le curseur à l’origine du cylindre. Cela fera en sorte que le prochain objet qu’on va créer se positionné par rapport au curseur ainsi déplacé.
  • Créer un nouveau cylinder
  • Passer en mode Edit puis faire un Scale selon les axes X et Y mais pas Z de 0.2 (S ⇧ Z 0.2 ↩)
  • Le cylindre a été crée à l’origine du premier puisqu’on a déplacé le curseur. Chouette.
  • Toujours en mode Edit, appuyer sur 3 pour passer en mode Face Select (1 pour Vertex Select, 2 pour Edge Select et 3 pour Face Select).
  • Sélectionner la face du haut et la déplacer vers le haut d’environ 1.5 m (G Z 1.5 ↩)
  • Maintenant sélectionner la face du bas et faire ⇧ S et choisir “Snap Cursor to Selected” pour amener le curseur au centre de cette face du bas du cylindre.
  • Revenir en mode Object.
  • Créer un Plane (il sera crée au niveau du curseur).
  • Passer en mode vue orthogonale d’élévation (Numpad 7) et en mode Wireframe.
  • Scale d’environ 0.8 (S 0.8 ↩) du Plane, on veut qu’il couvre un peu plus que la surface qui contient le logo.
  • Passer en mode Vertex Edit
  • ⌃ ⇧ B pour créer un Bevel similaire à la plateforme qui contient le logo
  • Revenir en vue perspective, faire un Extrude (E) vers l’axe des Z négatifs d’environ 0.27 (déplacer la souris vers le bas après avoir appuyer sur E puis ↩)
  • Inset (I) vers l’intérieur d’environ le quart, puis E (Extrude) vers l’intérieur d’environ le cinquième.
  • Tout sélectionner et faire ⇧ N pour recalculer les normales.
  • Revenir en mode objet.
  • Vous devriez avoir les objets suivants maintenant:
  • Ramener le curseur à l’origine du monde: ⇧ S → “Cursor to World Origin”
  • En mode vue orthogonale de côté (Numpad 3), sélectionner l’arche et la déplacer selon l’axe des Y (G Y) de manière à ce qu’elle soit centrée par rapport à la presse.

Un peu de parenting pour faciliter l’animation

  • Créer un Empty de type axes simples (⇧ A → Empty → Plain Axes). l’empty sera créé à l’origine, là où se trouve maintenant le curseur.
  • Sélectionner le convoyeur (Plane), puis l’empty et faire ^ P → Object pour créer une hiérarchie parent-enfant (Le convoyeur doit-être l’enfant de l’empty).
  • Sélectionner tous les objets nouvellement crées (donc pas l’empty, ni le convoyeur (Plane), ni l’objet qui contient le logo, mais tout le reste):
  • Shift-Select le convoyeur et dans les Modifiers, aller vers le menu déroulant du Bevel Modifier et faire “Copy to selected”.
  • Ensuite faites la même chose avec Smooth by Angle
  • Sélectionner Le long cylindre (Cylinder.002),puis Shift-Select de la partie cuboïde de la presse (Plane.003), ^ P → Object pour que le cylindre soit un enfant de la partie platte de la presse.
  • Maintenant, si on bouge l’empty, le convoyeur et la plateforme contenant le logo vont bouger et si l’on bouge la partie platte de la presse, le cylindre de la presse va bouger avec également.

Le convoyeur dubliqué

  • Sélectionner le convoyeur (Plane), puis Shift-Select de son enfant Plane.001 et encore Shift-Select de l’enfant de ce dernier (le rectangªle noir du Blender Logo). C’est plus facile si vous le faite dans l’outliner

  • On va dupliquer tout ce beau monde-là.

  • Faire ⌥ D (Alt-D pour Duplicate) puis Y puis 5 (pour 5 m). Cela va créer tout les enfants du empty en les déplaçant de 5 m sur l’axe des Y.

⚠️

Ce nouveau bout de convoyeur sera parenté à l’empty qui se trouve au centre du monde puisqu’il est une duplication de l’original. C’est pour ça qu’il était important de sélectionner tous les enfants de l’Empty, mais pas l’empty car on ne veut pas dupliquer l’empty.

  • Faire encore une fois Alt-D, Y et -10 ↩ cette fois-ci.
  • Puis encore une fois Alt-D et Y et -5 ↩
  • si vous déplacez l’empty, les 4 convoyeurs se déplaceront.
  • Sélectionner les 2 dernières plateformes qui contiennent le logo, et dans le Boolean Modifier, désactiver Viewport et Render.

Caméra et arrières-plans

  • Ajouter un Plane
  • Passer en mode Edit Vertex.
  • Scale d’un facteur de 42 (S 42 ↩)
  • Déplacer le plan vers le bas de manière à ce qu’il coïncide avec le bas des colones de l’arche (G Z, bouger la souris puis ↩)
  • Revenir en mode Objet.
  • Créer un autre Plane.
  • Tourner selon l’axe des Y de 90 degrés.
  • Scale selon l’axe des Y de 42 (S Y 42 ↩)
  • Scale selon l’axe des Z de 4 (S Z 4 ↩)
  • Déplacer de -5 M selon l’axe des X (G X -5 ↩)
  • Ce plan servira d’écran devant la caméra
  • Déplacez-vous dans le viewport de manière à obtenir la vue suivante. Puis ajouter une caméra et faire ⌥ ^ Numpad 0 (Alt-Ctrl Numpad 0) pour positionner la caméra selon le viewport.
  • Ajuster la distance focal de la caméra ou la distance/rotation de celle-ci par rapport à la scène pour obtenir la vue désirée:
    • Créer un empty de type sphere
    • Sélectionner la caméra et dans la section Depth of Foield, changer le FStop pour 0.3 et Focus Object, choisir Empty.001

Animation

  • Mettre le Endframe dans le timeline à 40
  • Aller au Frame 1.
  • Sélectionner l’Empty.
  • Activer le N Menu, et dans l’onglet Item, cliquer-droit sur le champ Y de Location, et choisir “Insert Keyframe”.
  • Aller au Frame 30. Donner une valeur de 5 à Location Y et cliquer-droit derechef sur le champ Y pour insérer un autre Keyframe.
  • Sélectionner les keyframes du frame 30, faire Shift-D pour les dupliquer et les déplacer avec la souris au frame 40
  • Dans le Timeline, faire A pour tout sélectionner, ensuite cliquer droit et choisir Interpolation Mode → Bézier
  • Cliquer droit et choisir Easing Mode → Automatic
  • Aller au frame 25 et Sélectionner la partie platte de la presse.
  • Au frame 25, faire I pour insérer un keyframe.
  • Au frame 40, déplacer la presse de manière à ce qu’elle appuie sur la plateforme du logo et faire I encore une fois pour insérer un autre Keyframe.
  • Changer le End frame à 50 en fait (40 ce n’est pas assez long)
  • Sélectionner les keyframes au frame 25, faire Shift-D pour les dupliquer et les déplacer avec la souris jusqu’au frame 50, de manière à ce que la presse revienne à sa position originale.
  • Si vous faites Play, vous verrez que la presse a un mouvement trop lent, on veut un impact plus important.
  • Passer au Graph Editor et isoler Z location seulement (fermer les yeux de toutes les autres variables).
  • Tout sélectionner avec A puis appuyer sur le dot (.) du Numpad. Cela fera un focus sur la courbe.
  • Vous pouvez également zoomer en appuyant sur la touche ^ (Ctrl) et en bougeant la souris avec le bouton du milieu appuyé.
  • Passer à Bézier comme mode d’interpolation (Right-Click, Interpolation Mode → Bézier).
  • Sélectionner le point du milieu au Frame 40 (celui le plus bas sur la courbe), Faire V et choisir Free pour libérer les points de contrôle.
  • Rapprocher les deux points de contrôle de ce keyframe de manière à obtenir un V (un peu comme pour la balle rebondissante):
  • Faire Play, vous verrez que le mouvement est plus sec.
  • Sélectionner, au frame 30, la plateforme du logo qui se trouve juste en-dessous de la presse.
  • Retourner au frame 1.
  • Dans les Modifiers, cliquer sur Viewport et Render du boolean modifier désacactiver le modifier.
  • Amener la souris au-dessus du pictogramme à droite Du Boolean Modifier qui indique Display Viewport et faire I pour insérer un keyframe.
  • Déplacer la souris sur le pictogramme du Render et faire la même chose pour insérer un keyframe là-aussi. On est en train de dire qu’au frame 1, ne pas monter le logo ni dans le viewport, ni dans le render.
  • Aller au frame 40, activer BTool_Blender Logo autant pour le Viewport que pour le Render et ajouter des keyframes respectifs comme tout à l’heure au frame 1.
  • Faire Play, on a terminé pour l’animation!

Matériel

  • Sélectionner la plateforme platte de la presse (Plane.003)

  • Créer un nouveau Material

  • Metallic à 1 et roughness à 0.3

  • Créer un autre Material (+ pour ajouter une nouveau Slot puis cliquer sur New Material.

  • Changer le nom du Material à Flash

  • Changer Principled BSDF à Emission.

  • Changer Strength à 20

  • Passer en mode Face Edit et sélectionner la face intérieure du bas de la plateforme platte de la presse.

  • Dans Material, choisir Light et cliquer sur “Assign”.

  • Revenir en mode Object.

  • Ajouter une Area Light.

  • Scale 2 (S 2).

  • La déplacer au-dessus de la scène le long de l’axe des Z (G Z bouger la souris vers le haut puis ↩)

  • La déplace le long de l’axe des Y négatifs de manière à ce qu’elle éclaire la scène par la gauche (G Y bouger la souris vers la gauche puis ↩).

  • Dans les propriétés Light, lui donner une puissance de 500 W et une couleur bleue froide.

  • Sélectionner la plateforme plate de la presse et dans Material, choisir une couleur un peu orange brûlé (oui je sais, encore les couleurs complémentaires bleu et orange 😇 ) pour le Material intitulé “Flash”.

  • Sélectionner l’Area light. Faire ⇧ D pour la dupliquer et la déplacer vers la droite, un peu plus basse

  • Réduire sa taille de 50% (S 0.5 ↩)

  • Réduire l’intensité à 150 W

  • Changer sa couleur pour quelque chose de rouge.

  • Assigner Material à tous les autres objets de la scène. Pour ce faire, sélectionner un objet et dans les propriétés Material, choisir le drop-down juste à gauche du bouton New Material et choisir “Material” (Ne pas oublier les deux plans).

  • Vous noterez que comme le convoyeur et la plateforme du logo ne sont q’une instance avec un array modifier, le modifier sur un seul objet le fera sur tous les objets de l’array.

  • Sélectionner la 2e Area Light (Area.001), déplacer la tête de lecture au Frame 1

  • Insérer un keyframe pour le wattage (150 W).

  • Sélectionner le keyframe, faire ⇧ D et le déplacer au frame 50.

  • Au frame 25, changer la puissance à 0 et insérer un keyframe.

  • Passer au Graph Editor.

  • Sélectionner tous les 3 keyframes de l’animation de la puissance de la lampe.

  • Changer l’interpolation à Bézier

  • Rendre plus sharp la descente à 0 W au keyframe 1 et la remontée à 150 W au frame 50 en bougeant les points de contrôle du keyframe 1 et du keyframe 50

⚠️

Sélectionner les keyframes avec A et faire Numpad . pour zoomer sur la courbe correctement (autrement, vous risquez de vous battre longtemps à tenter de bien voir la courbe puisque l’axe des Z va de 0 à 150 W.

  • Hmm, je donnerai une couleur plus rouge à cette area light puisqu’elle donne un sentiment d’alarme au moment de la fonte du logo.
  • Faire Shift-clique-droit et déplacer le curseur en-dessous de l’arche mais en dehors du cadre de la caméra.
  • Ajouter un “Point light” de 50W avec une couleur un peu jaunâtre. La lumière sera créée à l’endroit où se trouve le curseur.

Profondeur de champ

  • Remettre le curseur à l’origine (⇧ S → Cursor to World Origin).
  • Créer un nouvel Empty, cette fois-ci d’apparence Sphere.
  • Sélectionner la caméra
  • Activer le Depth of Field.
  • Dans Focus Object, choisir cet empty.
  • Régler le F-stop à quelque chose de très artificiel, genre 0.3
  • À vous de jouer! Modifier les paramètres du Compositing, ceux du HDRI (peut-être changer de HDRI?), ajouter des décors et objets, etc. En fait, commencez le devoir!

Résultat

Devoirs

  • Chaîne de montage, animation en boucle
    Critères:
    - [ ] Remettre l’animation finale sur votre Drive.
    - [ ] Utilisation d’au moins une des simulations qu’on a apprises ou une qu’on n’a pas vue comme Particles, Rigid Body, etc. Je vous conseille le coussin gonflable, une simulation de drapeau, un corps souple, de la fumée ou du feu. Évitez les fluides liquides, c’est compliqué.
    - [ ] Changer le logo Blender pour un mesh qui vous représente (essayer de faire un Mesh, pas un SVG)
    - [ ] Ajouter des éléments de décor (engrenage pour le convoyeur? Éléments de décor sur le mur et le plancher? Changer les matériaux, etc.)
    - [ ] Montage vidéo et sonore.
    - [ ] Surprenez-moi, soyez créatives et créatifs!
Lien vers l'original

Blender - Geo Nodes - Intro - Légo

Geo Nodes - Intro - Légo

Lien vers l'original

# Cours 10 (4h) - Introduction aux Simulation Nodes

  • TBD
Lien vers l'original