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).
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.
Learn Blender Simulations the Right Way: Create attractive and realistic animations with Mantaflow, rigid and soft bodies, and Dynamic Paint Paperback – Nov. 18 2022
Blender 3D By Example - Second Edition: A project-based guide to learning the latest Blender 3D, EEVEE rendering engine, and Grease Pencil – Illustrated, May 29 2020
Taking Blender to the Next Level: Implement advanced workflows such as geometry nodes, simulations, and motion tracking for Blender production pipelines – May 30 2022
Sculpting the Blender Way: Explore Blender’s 3D sculpting workflows and latest features, including Face Sets, Mesh Filters, and the Cloth brush – Jan. 28 2022
Hands-On Unity 2022 Game Development: Learn to use the latest Unity 2022 features to create your first video game in the simplest way possible, 3rd Edition
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.
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.
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
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.
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.!
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
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.
Le modifier en EEVEE avec du NPR shading (Non Photorealistic Rendering):
Glass toon shader pour les cylindres afin de voir au travers
Toon shader pour les autres composantes (y compris le plancher!)
Ajouter des petites simulations de fluides pour
Intake (entrée des gaz, essence et air)
Compression (compression des gaz, changement de la couleur vers l’orange)
Kaboom (explosion, feu)
Exhaust (sortie fumée noir)
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é.
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.
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 :
Nœud Math — Les sockets circulaires indiquent une compatibilité dynamique avec les valeurs uniques, les champs, les listes, etc.
Nœud Triangulate — Entrées à valeur unique avec une sélection évaluée en tant que champ
Nœud Set Position — Une entrée géométrie unique plus plusieurs entrées de type champ (toutes de forme identique)
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.
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 m3 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!
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.
Dé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ération
30 %
Critères d’évaluation
Un 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)
Ce fichier contient une collection d’assets représentant des buildings
Ajoutez des geo nodes afin d’obtenir une distribution de building random selon une distribution de Poisson:
Évaluation et pondération
Pondération
35 %
Critères d’évaluation
Distribution 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)
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.
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.
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.
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?
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.
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)
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.
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: x=cos(Longitude)∗cos(Latitude)∗c y=sin(Longitude)∗cos(Latitude)∗c z=sin(Latitude)∗c
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!
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.
→ 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.
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!
Dé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ération
30 %
Critères d’évaluation
Un 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)
Ce fichier contient une collection d’assets représentant des buildings
Ajoutez des geo nodes afin d’obtenir une distribution de building random selon une distribution de Poisson:
Évaluation et pondération
Pondération
35 %
Critères d’évaluation
Distribution 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)
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
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 bpydef 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.
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 n :
A=(A1,A2,…,An)
B=(B1,B2,…,Bn)
Le produit scalaire est défini par :
A⋅B=A1B1+A2B2+…+AnBn
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 :
A⋅B=∣A∣∣B∣cos(θ)
Exemple de calcul:
Si A=(3,−4,2),B=(1,2,5)
Alors A⋅B=(3)(1)+(−4)(2)+(2)(5)=3−8+10=5
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.
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:
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 tension
Contrôle la rigidité du tissu.
Ressorts de Compression
Contrô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”
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é
Valeur
Description
Quality Steps
7
Un 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 Multiplier
1
Le facteur influençant la durée du temps écoulé. 1 = “temps réel”.
Stiffness → Tension
15
Contrôle la rigidité du tissu.
Stiffness → Compression
15
Contrôle la force requise pour compresser, plier ou froisser le tissu.
Stiffness → Shear
5
Contrôle la déformation angulaire du tissu.
Stiffness → Bending
2
Contrôle la résistance du tissu au pliage ou au froissement.
Damping → Tension
5
Mê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 → Compression
5
Damping → Shear
5
Damping → Bending
2
Caching → Simulation Start
1
début de la simulation
Caching → Simulation End
500
Fin de la simulation.
Collision → Quality
6
Contrô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 Collision
Activé
On veut que l’objet entre en collision avec les autres objets de manière réaliste.
Distance
0.01
Self Collision
Activé
On ne veut pas que l’objet passe à travers lui-même.
Distance
0.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é
Valeur
Description
Shape
Plane
La forme selon laquelle le vent sera calculée
Strength
30 000
La puissance du vent
Flow
1
La facteur “vitesse” du fluide “air”. 1 = réaliste.
Affect → Location
Oui
Affect → Rotation
Oui
Noise Amount
0.5
Histoire de ne pas avoir un vent qui ne varie jamais.
Seed
21
Changer le seed changera la génération des nombres aléatoires
Absorbtion
Oui
Une partie de l’énergie du vent est absorbée par les objets ayant la propriété Collision
Wind Factor
1
Le degré avec lequel l’énergie du vent est absorbée par des tissus
Falloff
Pas 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:
À 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.
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 bpyfor 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
import bpy# Select all objects in the scenebpy.ops.object.select_all(action='SELECT')# Delete all selected objectsbpy.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 bpyimport random# Clear the current scene by selecting and deleting all objectsbpy.ops.object.select_all(action='SELECT')bpy.ops.object.delete()# Define the number of primitives to create along X and Y axesgrid_size_x = 5grid_size_y = 5spacing = 3# Create primitives in a gridfor 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 camerabpy.ops.object.camera_add(location=(10, -15, 10))camera = bpy.context.objectcamera.rotation_euler = (1.1, 0, 0.8)# Adjust lightingbpy.ops.object.light_add(type='POINT', radius=1, location=(10, 10, 10))light = bpy.context.objectlight.data.energy = 1000
## Sinusoïdale#import bpyimport math# Clear the current scene by selecting and deleting all objectsbpy.ops.object.select_all(action='SELECT')bpy.ops.object.delete()# Animation settingsframe_start = 1frame_end = 250bpy.context.scene.frame_start = frame_startbpy.context.scene.frame_end = frame_end# Define the grid size and spacinggrid_size_x = 10grid_size_y = 10spacing = 2# Create a list to store the spheresspheres = []# Create spheres in a grid patternfor 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 effectfor 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 animationbpy.ops.object.camera_add(location=(12, -20, 15))camera = bpy.context.objectcamera.rotation_euler = (1.1, 0, 0.8)# Set active camerabpy.context.scene.camera = camera# Add lighting to the scenebpy.ops.object.light_add(type='SUN', location=(15, -10, 20))light = bpy.context.objectlight.data.energy = 5
## Petit robot avec Material#import bpy# Clear the current scene by selecting and deleting all objectsbpy.ops.object.select_all(action='SELECT')bpy.ops.object.delete()# Function to create a material with a given colordef 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 robotbody_material = create_material("BodyMaterial", (0.1, 0.5, 0.8, 1)) # Blueishhead_material = create_material("HeadMaterial", (0.8, 0.8, 0.8, 1)) # Light Greyeye_material = create_material("EyeMaterial", (0, 0, 0, 1)) # Blackarm_leg_material = create_material("ArmLegMaterial", (0.3, 0.3, 0.3, 1)) # Dark Greyantenna_material = create_material("AntennaMaterial", (1, 0, 0, 1)) # Red# Create the robot bodybpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 1))body = bpy.context.objectbody.scale = (1, 0.6, 1.5) # Reshape the cube to form the bodybody.data.materials.append(body_material) # Apply material# Create the robot headbpy.ops.mesh.primitive_uv_sphere_add(radius=0.75, location=(0, 0, 3.25))head = bpy.context.objecthead.data.materials.append(head_material) # Apply material# Create the robot eyesfor 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 armsfor 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 legsfor 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 antennabpy.ops.mesh.primitive_cylinder_add(radius=0.05, depth=1.5, location=(0, 0, 4.5))antenna = bpy.context.objectantenna.data.materials.append(antenna_material) # Apply material# Create the antenna top spherebpy.ops.mesh.primitive_uv_sphere_add(radius=0.1, location=(0, 0, 5.25))antenna_top = bpy.context.objectantenna_top.data.materials.append(antenna_material) # Apply material# Set up lightingbpy.ops.object.light_add(type='AREA', radius=5, location=(5, -5, 6))light = bpy.context.objectlight.data.energy = 1000 # Increase light intensity# Set up camerabpy.ops.object.camera_add(location=(7, -7, 5))camera = bpy.context.objectcamera.rotation_euler = (1.1, 0, 0.8)# Set the camera as the active camerabpy.context.scene.camera = camera
## Fibonnaci#import bpyimport math# Clear the current scene by selecting and deleting all objectsbpy.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)
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 2typedef 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...
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
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 1typedef 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:
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.
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
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))
Exploration
Marquer la cellule courante comme “visitée”
Obtenir la liste des cellules voisines non visitées
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
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 quetoutes 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:
Élégance conceptuelle - L’idée de “creuser” des tunnels en explorant puis en revenant en arrière est intuitive
Simplicité d’implémentation - Quelques dizaines de lignes suffisent
Qualité esthétique - Produit des labyrinthes avec de longs passages sinueux, visuellement satisfaisants
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:
Pile (Stack):
Stocke le chemin parcouru
Permet de revenir en arrière (backtracking)
Structure LIFO (Last In, First Out)
Boucle principale:
Continue tant qu’il reste des cellules dans la pile
Gère deux cas: exploration et backtracking
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:
Collecter tous les murs du périmètre
Mélanger aléatoirement la liste
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_sizepos_y = y × cell_sizeExemple: 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:
Création d’un cube avec primitive_cube_add
Positionnement au centre du mur
Mise à l’échelle pour obtenir les bonnes dimensions
Application du matériau bleu
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)
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)
# Entrée en bleu au lieu de vertbsdf.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éebpy.ops.mesh.primitive_uv_sphere_add( radius=0.5, location=(entrance_pos[0], entrance_pos[1], 0.5))# Cône pour la sortiebpy.ops.mesh.primitive_cone_add( radius1=0.5, depth=1.0, location=(exit_pos[0], exit_pos[1], 0.5))
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
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
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
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)
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:
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 objetsinstance = template_wall.copy()instance.data = template_wall.data # Partage la géométrieinstance.location = (x, y, z)
Fusion des murs adjacents:
# Au lieu de créer un mur par segment,# fusionner les murs alignés en un seul mesh
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 principalmaze = MazeGenerator(20, 20)maze.generate_maze()maze.create_entrance_exit()maze.create_maze_geometry("MyMaze")# Accéder aux donnéesentrance_cell = maze.entranceprint(f"Entrée en position: {entrance_cell}")
Génération Procédurale dans un Jeu
# Générer un nouveau niveau à chaque partieimport timeseed = 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
Algorithmes de Labyrinthes:
“Mazes for Programmers” par Jamis Buck
“Think Labyrinth!” par Walter D. Pullen
Backtracking et Graphes:
“Introduction to Algorithms” par Cormen et al. (CLRS)
“The Algorithm Design Manual” par Steven Skiena
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 GeneratorA Python script to generate 3D mazes in Blender using recursive backtracking algorithm."""import bpyimport randomclass 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 executionif __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 GeneratorA Python script to generate 3D mazes in Unreal Engine using recursive backtracking algorithm.Requires: Unreal Engine with Python Editor Script Plugin enabled"""import unrealimport randomclass 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 executionif __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()")
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.
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 :
Nœud Math — Les sockets circulaires indiquent une compatibilité dynamique avec les valeurs uniques, les champs, les listes, etc.
Nœud Triangulate — Entrées à valeur unique avec une sélection évaluée en tant que champ
Nœud Set Position — Une entrée géométrie unique plus plusieurs entrées de type champ (toutes de forme identique)
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.
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.
Dé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ération
30 %
Critères d’évaluation
Un 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)
Ce fichier contient une collection d’assets représentant des buildings
Ajoutez des geo nodes afin d’obtenir une distribution de building random selon une distribution de Poisson:
Évaluation et pondération
Pondération
35 %
Critères d’évaluation
Distribution 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)
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.
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.
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.
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.
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?
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.
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)
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
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
(Je vous montrerai au prochain cours comment appliquer les autres fichiers (bump map, roughness maps, normal maps, etc.)
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.
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 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:
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”:
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 bpydef 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.
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.
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:
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 tension
Contrôle la rigidité du tissu.
Ressorts de Compression
Contrô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”
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é
Valeur
Description
Quality Steps
7
Un 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 Multiplier
1
Le facteur influençant la durée du temps écoulé. 1 = “temps réel”.
Stiffness → Tension
15
Contrôle la rigidité du tissu.
Stiffness → Compression
15
Contrôle la force requise pour compresser, plier ou froisser le tissu.
Stiffness → Shear
5
Contrôle la déformation angulaire du tissu.
Stiffness → Bending
2
Contrôle la résistance du tissu au pliage ou au froissement.
Damping → Tension
5
Mê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 → Compression
5
Damping → Shear
5
Damping → Bending
2
Caching → Simulation Start
1
début de la simulation
Caching → Simulation End
500
Fin de la simulation.
Collision → Quality
6
Contrô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 Collision
Activé
On veut que l’objet entre en collision avec les autres objets de manière réaliste.
Distance
0.01
Self Collision
Activé
On ne veut pas que l’objet passe à travers lui-même.
Distance
0.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é
Valeur
Description
Shape
Plane
La forme selon laquelle le vent sera calculée
Strength
30 000
La puissance du vent
Flow
1
La facteur “vitesse” du fluide “air”. 1 = réaliste.
Affect → Location
Oui
Affect → Rotation
Oui
Noise Amount
0.5
Histoire de ne pas avoir un vent qui ne varie jamais.
Seed
21
Changer le seed changera la génération des nombres aléatoires
Absorbtion
Oui
Une partie de l’énergie du vent est absorbée par les objets ayant la propriété Collision
Wind Factor
1
Le degré avec lequel l’énergie du vent est absorbée par des tissus
Falloff
Pas 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:
À 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.
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é
Valeur
Description
Settings:
Type
Flow
Flow Tyle
Liquid
Behavior
Inflow
Use Flow
Activé
Flow Source:
Flow Source
Mesh
On veut que le “Plane” en entier soit la source du fluide
Is Planar
Activé
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
-1
Plus 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:
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ètre
Valeur
Description
Samples
32
Blur
0.5
Speed Min
0
Speed Max
40
Ç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 😊
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 Viewport
16
Render
16
Waves → Choppiness
0.9
Wind Velocity
4 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…
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.
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.
Springs
Permet 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).
Pull
La 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.
Push
D’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.
Plasticity
Ma 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.
Bending
Les 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.
Length
La 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 Face
Les 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.
Aerodynamics
L’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.
Stiffness
Stiffness (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 Min
Lorsque 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.
Max
Le nombre maximum de steps (passes) par frame dans le calcul.
Auto-Step
Blender va se baser sur la vitesse de l’objet (Velocity) pour automatiquement régler le nombre de steps.
Error Limit
Plus cette valeur est petit, plus la tolérance à l’erreur sera faible et plus précise sera la simulation.
Diagnostic
On 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.
Fuzzy
La 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.
Le sauvergader dans un nouveau dossier nommé “Course Obstacles”.
Ouvrir le fichier .blend
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.
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 Group
Groupe 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.
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!
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.
Faire File → Import → Scalable Vector Graphics (.svg) et choisir le fichier svg que vous venez de télécharger
⚠️
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!