PROJET AUTOBLOG


blog.fevrierdorian.com

source: blog.fevrierdorian.com

⇐ retour index

Mise à jour

Mise à jour de la base de données, veuillez patienter...

fxguide et le deep compo

mercredi 15 octobre 2014 à 22:07

fxguide_tn.pngComme vous le savez peut être, je travaille principalement sur des longs métrages d'animation. Il m'arrive de participer à des discussions (formelles ou informelles) entre la RnD et la production concernant les difficultés techniques (principalement coté lighting) des projets en cours et/ou qui pourraient arriver.

Je dois admettre que j'entends souvent que le deep compositing c'est super, utilisé partout etc... J’avoue avoir une vision plus nuancé de la chose que je ne considère pas comme une "petite" feature et que, bien qu'il puisse se révéler utile dans des cas bien particuliers, il entraine plus de complications qu'il ne résout de problèmes, tout particulièrement si son usage est généralisé (et sur un long métrage d'animation il est souvent nécessaire de "sur-généraliser" les usages pour garder une consistance dans les données générées).

Mais cela faisant, je me retrouve face à pas mal de "Hein? Mais fxguide dit que c'est utilisé dans tous les studios d'animation! Dreamworks, Disney, toussa..." :tuComprendRien:

Je ne m'étalerais pas sur le fait que les projets sur lesquels je travaille ne sont pas fait dans de tels studios. Je ne parlerais même pas de la différence de budget. Je vais simplement citer un propos rapporté par fxguide et prier pour que tout superviseur, actuel et futur, ait l'occasion de prendre ça en considération.

Cet article ne vise pas a cracher sur fxguide (J'y vais souvent et je trouve qu'ils font un travail de titan!) mais à attirer l’attention de ceux qui prennent ses articles comme parole d'évangile sans prendre la mesure des implications techniques que peut avoir l'utilisation d'outils aussi complexes et évolués dans une production et en particulier sur un long métrage d'animation.

fxguide est un des sites de news CGI le plus connu. C'est un des quelques sites (le seul?) a fournir autant d'articles et d'interviews de personnes et des logiciels utilisé dans la CGI.

Il y a quelques jours, je lisais cet article.

J'ai tendance à prendre ce que rapporte fxguide avec des pincettes car il offusque souvent des détails qui sont importants dans le cas d'une production (toute les questions qui pourraient commencer par "Ok, mais qu'est ce qui ce passe si..."). Il y a une sorte de syndrome: "tout est allé pour le mieux dans le meilleur des mondes car la flexibilité ainsi que la polyvalence de nos outils internes, nous a permis de livrer dans les temps limité et à cout très faible, des plans d'une qualité sans commune mesure dans l'histoire de notre industrie". Ce type de discours n'est pas surprenant ni vraiment choquant dans notre milieu, même si la réalité du terrain ressemble souvent plus à ça qu'autre chose:

PicassoGuernica_800.jpg

Guernica from Pablo Picasso

C'était une blague (Vous pouvez rigoler :jdicajdirien: ).

Mais pour la première fois, fxguide semble rapporter des propos autour du deep compositing dans le cadre d'un long métrage d'animation. Et ces mots viennent de Hank Driskill, Superviseur Technique sur Big Hero 6 (le prochain Disney). Si vous êtes un superviseur, veuillez prendre note de ces sages paroles:

The renderer and pipeline can render with deep data. It was not used on all shots, however. “We use it sparingly just because of the data management concerns,” says Driskill, referring to the huge data sets complex deep data rendering can produce.

Sans déconner... Il n'y a que Weta pour faire un format de fichier aussi massif a stocker, lourd a l'usage et fou que le deep data. Mais la vérité c'est qu'on est pas souvent à Weta et qu'on ne travail pas avec les même budgets.

Notez les propos de fxguide "It was not used on all shots" suivis de ceux de Dirskill, beaucoup plus contrastés: "We use it sparingly". Les deux phrases veulent dires la même chose, mais chacun aborde le problème d'une manière différente (verre a moitié vide VS verre à moitié plein).

Il y a un fossé énorme entre ce que fxguide rapporte et le quotidien des graphistes, les vas et viens incessants entre la RnD et la production avec les deadlines qui approchent quand un outil ne fonctionne pas. Il y a une bonne raison à ça: La CGI est très timide quand vient le temps de communiquer. Il n'y a rien de mal à ça. La plupart des grosses compagnies qui travaillent pour de gros client adopte une approche similaire. Rien n'est calculé et personne n'est réellement briefé mais ce qui est dit sera souvent "doux" vis-avis du studio, de la prod et des collègues. Il faut en être conscient quand de tels informations sont rapportées: fxguide, et par extension, vous, n'avez jamais toute l'histoire.

Ceci amène fxguide à faire une grosse abstraction de comment les choses tournent réellement dans un studio et à quel point la réalité peut être plus nuancé. Mais quel superviseur digne de ce nom pourrait dire publiquement: "Ça été une bordel monstre cette prod! Les outils internes sont tous à foutre à la poubelle, il n'y a rien a en tirer!". Pourtant de tels propos peuvent arriver en off sur une prod un peu difficile. C'est quelque chose que vous devez garder à l'esprit quand vous vous appuyez sur des articles de fxguide pour choisir vos outils et la manière dont vous voulez travailler. Vous devez être tout particulièrement vigilant si vous avez pas/peu d’expérience en long métrage qui implique un management de la consistance des données colossale.

Tout ceci peut sembler évident pour beaucoup de monde mais dans la mesure ou j'ai entendu pas mal de superviseurs prendre fxguide comme référence de ce qui ce fait dans l'industrie, je me dis qu'un brin de retenue vis-à-vis de la vision de l'industrie renvoyée par de tels sites ne serait pas fortuite: Vous êtes des artistes. Prenez les outils que vous connaissez et foncez! (D’où l’intérêt de connaitre les outils à l'avance et de ne pas attendre d'avoir un long sur les bras pour faire un saut qui pourrait être fatal)

Et pour le fun:

fxguide_batman_robin.jpg

Vous avez plus de chances de sortir un film, avec des mauvais outils que vous maitrisez qu'avec les outils super évolués auxquels vous ne pipez rien. C'est quelque chose à prendre en compte quand on dispose de ressources limitées. :redface:

J'espère que cet humble billet vous sera utile. N'hésitez pas à commentez, surtout si vous n'êtes pas d'accord! :)

Dorian

:marioCours:

Multithreading for Visual Effects book review

dimanche 24 août 2014 à 19:14

multithreading_for_vfx_review_tn.pngIn programming, nothing is better than a good book. You will often ear that from many experienced programmers.

Today I want to share my humble review of Multithreading for Visual Effects.

This book has been created after the Multithreading and VFX courses session at Siggraph 2013 where some companies were presenting how they used multithreading in their tools. The results where so interesting they decide to gather them and make a book.

As this kind of niche book is rare in the CGI, let's talk about it! :enerve:

multithreading_for_vfx_review_001.jpg

Chapter 1: Introduction and Overview (by James Reinders)

The prologue is an ode to multithreading (What a surprise :siffle: ). James Reinders is an engineer from Intel and we can say he know his job!

What I'd really liked is that multiple faces of multithreading are presented (multi task vs multi thread, vectorization, etc...), explaining technically how they work and giving pros and cons for each of them.

I must talk about how TBB is presented. In general TBB is considered as a serious choice for multithreading programs (Almost every program in the book use it). And from what I've read from the documentation, it deserves it. To be honest, TBB make we want to master C++ templates and I totally understand you would choose TBB if you are familiar with them.

But I regret James didn't spend more time and love presenting alternatives. I know it's a Intel guy but clearly, TBB receive a lot of emphasis and it totally hides the others. I think it's quiet a shame because a lot of chapters talk about TBB too. Alternatives are "presented" but not as in depth than TBB.

Anyway, you get the message: TBB is good, eat some! :banaeyouhou:

Chapter 2: Houdini: Multithreading Existing Software (by Jeff Lait)

houdini_black.png

A lot of multithreading informations you can find here and there, even on books (including this one), are very academic. They explain how you should write code.

This chapter is interesting because it take the invert approach: How convert old code to modern multithreading. Jeff present different concrete problems and how they choosed to solve them, what they lost doing so and how, if it was possible, they can still save what can be.

What I really love in this chapter is how unacademic it is. Some example's code solution make you realize: "Yeah! I could do that... It's weird but it works pretty well!". The best examples are how Houdini handles the thread creation time (because create a thread is long actually) where the datas to compute doesn't worth the threads creation time. Easy trade of: If data_count < 5000 : compute in the main thread! :IFuckTheWorld:

You will never see this kind of solution on an academic book but you will never have more efficient that this! :D

Each case is interesting. While not relevant for a general experience, read them all train your brain in why you should avoid to do things like this and how to react when you see them.

I must confess I'd read the original Side Effect paper after the Siggraph 2013. This make me realize some work has been done to reorganize and better explain the examples. I remember I were pretty lost with some examples in the original paper but it was not a problem with the book so I guess this examples where better explained (or my general programming skills has increase from that time).

This chapter was frustrating for me because I wanted to know more! More examples, more tricky problems to solve, more "here boys is what you've got if you write code this way".

If you want to know more about how Houdini works under the hood you can find this very interesting post

Chapter 3: The Presto Execution System: Designing for Multithreading (by George ElKoura)

Interactivity is the key of this chapter.

The first part is not very interesting. George explain the technical goals and constrains they had. This is good, but he spend too much time on things you often know without explain what where the specific implication in Presto ("vectorization is important because blah blah", "you should organized you data because blah blah"). Its kind of redundant with the first chapter. I would have put every general multithreading stuff explained in the first chapter and let the study case focus on implementation.

However, the second part is very interesting. Here are the smart choices they had to do. The way they handle threads in Presto (especially how graph computation is separate) is very different than an "academic" graph network. Indeed, Presto had to deal with "time" because time is the animator toy. He also talk about interactivity and the relation betweens "batch" threads (responsive of math computation) and UI threads and how they tried to avoid any kind of lag in interactivity (interrupt or not interrupt, that is the question). It's very well explained while not enough detailed for my taste. They finish with a small (2 pages) concrete code example of how a "naive" geometric deformer code can be multithreaded. It's an interesting code snippet because it present a general problem (but he give a "general" solution).

If you want to have an overview of how Presto work under the hood, you will like this chapter. The word overview is a good word here because George only focus on multithreading (it's what this book is supposed to do so...) but he often talk about things implicitly that (I guess) you could understand if you were familiar with Presto (what a rig look like in Presto?!). This "abstraction" of some technical details can be frustrating. :injures:

I also felt a "everything were fine and rosy" like if there was no complications, no multithreading specific "problems", no "what a silly idea we had there". I mean, in development, there is always moments where the vision and abstracted concepts face reality and involve serious trade of, moments where the academic approach can't be applied as it. This is even more glaring when you compare to the following chapter.

Chapter 4: LibEE: Parallel Evaluation of Character Rigs (by Martin Watt)

This one surprise me a lot! It shine in many places!

From the first pages of the chapter I was not very excited. LibEE is presented as a multithreaded Dependency Graph... You could almost read "Maya DG is not relevant anymore so there was no alternative: We have to write our own". I'm not a big fan of the classic "Dependency" Graph pattern. I'm not sure it's a good approach for multithreading and more I was reading the chapter more it confirm my humble opinion (but you know, I'm not working at Dreamwork so there is maybe a lot of valid reasons...). While the Dreamwork team seems to have done a big job to bypass some of the limitations a Dependency Graph could have, many sections make me realize "why" DG is not straightforward for massive multithreading. I tend to prefer a compiled approach like VEX or what Presto team choosed but reading the rest of the chapter, I'm not sure the Dreamwork RnD team has all the needed discretion (and resources?) to choose a such approach.

And this is one point where this chapter is amazing: You "feel" the production. I mean, the deadlines, riggers ranting over the new tools because-it-was-better-to-use-the-old-shitty-Maya-DG-before. I'm a big fan of various few line examples of discussions betweens various peoples involved (copy of rigger mails make me ROFL). It also explained how they have to train riggers to think multithreaded. The various bench tools they provided to riggers to find where the critical paths were and when "cut" them (yet another point to stay away from DG IMHO). LibEE follow the typical VFX situation where tools are developed and used at the same time (unlike Presto team that seems to have worked far away the production before release even if this is not clearly stated). Handle such situation is an art from a development perspective as goals often change and this chapter explain (a little) how handle this.

The second impressive point is the experience they share with the tests they did in production. I was sad the Presto chapter where only mentioning few technical points to be aware of in general (NUMA, bandwith, Hyperthreading, etc...) without provide any graph or so, while the Dreamworks team not only explain, but show where this points are problematics, how they bench them and what they observed. And they became very far at this point. Once again, this is not academic, this is true use cases decorticates.

So a very cool and clear chapter! One of the most valuable of this book. I would have love the same level of in depth discussion with Presto.

Chapter 5: Fluids: Simulation on the CPU (by Ronald D. Henderson)

lol this one is massive. If you love code, maths and computer science, you would love it! :aupoil:

There is some interesting OpenMP/TBB comparison codes (with TBB C++11 lambdas, first time I read such! :gne2: ). If you are not comfortable with C++, that's gonna be hard (and kind of disrupting).

About maths, I must admit I've smiled a lot each time I realize "I don't get anything! :baffed: " after read some lines.

In others chapters of the book, a lot of explanation is often presented with sentences like: "We measure the core efficiency by dividing the bench time by the number of core" (you know, something humanly readable). In this chapter, such sentence are actually presented by a tiny mathematical formulation following by: "Where p is the relational infrastructured derived of the inversed logarithm's result of the number of core and n is the time of the benchmark expressed in second (ISU-CIPM 1967)". Yeah, I exaggerate of course but as I'm not used to mathematical formulations this is exactly the feel I had reading this kind of sentences for the first time. And I laugh even more when, after some digging minutes, I realize all of this could be said with a simple sentence. Haha! :smileFou:

But I had the opportunity to work with mathematicians (or peoples loving maths in general) and they tend to use math equations to model anything (even such trivial things than the average time peoples spend at lunch or to be late at a meeting) so it reminded me all this funny moments. :jdicajdirien:

I'd also really loved the quick OpenVDB presentation. I had often heard about OpenVDB and never know how it was working under the hood. This tiny presentation was perfect. There is a lot of widely open source libraries used in the CGI but they lack of easy-to-get presentations and there is a lot of CG artists, while not true developers, are very technical and would benefit of advanced presentations of such libraries in their day to day work. So VFX artists, this presentation is for you!

For the rest, it was too mathematics for me. If you find it hard to read mathematics equation you would be lost in this chapter. I did so I can't really comment how valuable it is. Actually, I think you could be right with it if you are familiar with all "fluid/liquid" simulation maths.

Chapter 6: Bullet Physics: Simulation with OpenCL (by Erwin Coumans).

Bullet_Physics_Logo.svg.png

What a cool chapter I was not expecting. :bravo:

I'm not so much interested by physics in general but I must admit Erwin did a great work to decorticate his nice library. It's also the only chapter talking about OpenCL and GPU low level computation. While it's a very fast overview, it's well described and every steps of the various collision detection/repulsion computation of the Bullet libs that have been parallelized are well highlighted. This give a very interesting overview of how a physic engine can work which is something pleasant to know in VFX.

There is also a lot of tiny and very clear schema. I tend to prefer a lot of tiny, one problem focused, schema than bigger ones, you can see in the Presto eating places where some other schemas could have been interesting.

It finished on more advanced principles.

One of the clearest and pleasant chapter to read. :marioCours:

Chapter 7: OpenSubdiv: Interoperating GPU Compute and Drawing (by Manuel Kraemer)

I was waiting for this one impatiently and I've not been disappointed, very cool chapter. It's composed of two parts.

The first part talk about the iterative Catmull Clark subdivision, its history, why a "universal-matching" subdivision is needed, how it was working and how they multithread it. If you are not familiar with geometry hard edge data structure you will certainly be lost. They also give some shy benchmarks and conclude iterative subdivision design, while a need for off-line rendering, does not fit well to realtime constraints. I've been surprised they didn't talk about how they organize the memory to improve cache and benefit vectorization. I'm not an expert but after have read the previous chapters, I wonder if there was not other things to do to improve performances. I guess they are just not presented because the benefit where not such interesting who know... But to have distantly followed OpenSubdiv development I have the impression they quickly jump to the GPU side as it was maybe a more important step for the studio (Presto seems to rely on it), leaving the CPU code as "good enough".

The second part talk about how OpenSubdiv use GPU (and OpenGL) to offer realtime subdivision using realtime tessellation shaders available with OpenGL. Once again, I enjoyed the GPU presentation and how you are supposed to organize your batchs to benefit from it (and deal with strong GPU limitation). Edge Crease (a pivotal point of OpenSubdiv) seems to have been a problem (so does the triangle/quad/polygon) but I really like how they handle it: They separate each set of the geometry to apply different algorithms. The separation process is done once as the topology doesn't change, and the GPU simply recompute the tessellation shader according to the face set. Interesting and pragmatic approach to apply the most efficient algorithm to various part of a single geometry (while I guess it should complicate the code).

Off topic, I wonder if creases were a good idea for an open subdiv library. It fit very well with the surface limit concept dear to Renderman but:

If you can't subdivide for hell, a last option could be to represent creases modifying the normal but you would have to deal with shading stuff and this is not what OpenSubdiv is supposed to do (beside all the troubles you could have to "merge" the other shading normals).

So I wonder if creases where not something Pixar (and mainly Pixar) absolutely needs and this would explain while a such "exotic" concept fall in OpenSubdiv.

Notice the next OpenSubdiv is coming and seems to have some other studios contributions. It's a good thing as it seems to became a strong part of Maya. :)

Conclusion

Well... Good book! :D

There is inconsistencies between chapters. Some are very deep (LibEE, Fluids, Bullets), and others just touch the surface and finish too soon (Houdini, Presto).

So this book is exactly what it states: Multithreading for Visual Effects. And it focus on how multithreading can be/is used in VFX. But as the chosen softwares are very interesting (Seriously, Side Effect, Pixar, Dreamworks!) it can be sometime frustrating!

The book is very nice (hard cover!) while a bit pricey (hard cover?). But it's about a specific domain so it's ok (is there any book that talk about such softwares?). Most of the time it will be your studio that will buy it so... :P

Does it worth it? If you have to code on VFX softwares, don't hesitate. You will not find massive "ready to use" resources but it's like if you had talks with this guys sharing their experience, they explain how their babies works, what is important and what is a mess. Not sure you can find such infos everywhere.

If you are an artists enjoying technical stuff, I wouldn't recommend this book. It's very focus on development, you will not find multithreading tricks that will enhance your work. Anyway, I encourage to prick it to your RnD and see by yourself! :P

After reading this book, I'm sure I could pay for books (even with soft cover!) that focus on in depth architecture of a specific VFX software from a dev point of view (Houdini, Presto, Maya, Nuke). How datas are managed, what data structures look like, how a specific kind of operations are done etc... And not just an overview!

From the time I've been on the artistic side, I've tried to understood how softwares where technically working (because most of the time they were working bad/not as expected/I DIDN'T SAVE MY WORK!!!! etc...). I'm now able to understand the "logic" part of them so I want to read such high end code more!

Unfortunately, I missed a lot of valuable informations because of my lack of mathematic skills. I'm more familliar with computer science in general. I mean, I know what 4x4 matrices are, what they are used to, I know what a dot/cross product is and how it can be used to achieve various stuff but thats pretty much all. I was angry against myself to not be able to read and understand some advanced part of the code (I skip a lot of the Fluids chapter. :( ).

What is also interesting is to gather interesting Siggraph courses to make a book. I really like the idea while I would suggest to favor courses that go more in depth or with a lot of implementation studies (Once again, Presto is very frustrating). I also tend to prefer books than pdf.

I don't know about the success of this book but I've heard many peoples interested in it so we could hope for... Let say... "Alembic/OpenVDB/OpenEXR code review and use cases" with a lot of in depth explanation of the foundation and infrastructure of each of this libs. :D

Hope you enjoyed this humble review! I would be very interesting to ear your opinion if you also read this book so feel free to comment. :)

Dorian

:marioCours:

Le livre Multithreading for Visual Effects

dimanche 24 août 2014 à 19:13

multithreading_for_vfx_review_tn.pngEn code, rien ne vaut un bon bouquin. Vous entendrez souvent ce conseil de la part de développeurs expérimentés.

Aujourd'hui je vous propose un billet sur le livre Multithreading for Visual Effects.

Ce livre a été publié après la session de cours Multithreading and VFX au Siggraph 2013 où un certain nombre de studios présentaient comment ils avaient utilisés le multithreading dans leur outils. Les papers étaient suffisamment intéressant pour qu'ils décident de les rassembler en un livre.

Dans la mesure ou ce type de livre fait parti du marche de niche que sont les VFX, parlons en! :enerve:

multithreading_for_vfx_review_001.jpg

Chapitre 1: Introduction et vue d'ensemble (par James Reinders)

Le prologue est une ode au multithreading (Sans blagues :siffle: ). James Reinders est ingénieur pour Intel et on peut dire qu'il connait son boulot!

J'ai pas mal apprécié comment les multiples facettes du multithreading sont présentées (multi tache vs multi thread, vectorisation, etc...) ainsi que les explications techniques sur comment chacune d'elle fonctionne, avec leurs avantages et inconvénients.

Je me dois de parler de la manière dont TBB est présenté. TBB est généralement considéré comme une (la?) librairie de choix pour des logiciels multithreadés (Presque tous les logiciels du livre l'utilisent). Et de ce que j'ai pu lire de la documentation, c'est mérité. Pour être tout à fait honnête, TBB me donne réellement envie de maitriser les templates C++ et je comprends parfaitement qu'on puisse se tourner vers TBB rien que pour ça.

Mais je trouve dommage que James n'ai pas passé autant de temps et d'amour à présenter les alternatives. Je sais bien, c'est un bonhomme d'Intel mais clairement, TBB reçoit tellement d'éloge dans ce chapitre (et tout au long du livre) qu'il en occulte complètement les autres librairies (qui sont "présentées" mais pas de manière aussi clair que TBB).

Bref, vous comprenez assez vite le message: TBB cay bon, mangez-en! :banaeyouhou:

Chapitre 2: Houdini: Multithreader un logiciel existant (par Jeff Lait)

houdini_black.png

Bon nombre des informations qu'on peut trouver ici et la, y compris dans les livres (celui ci inclus), sont très académiques. Elles expliquent comment vous devriez écrire du code.

Ce chapitre est très intéressant car il prend l'approche inverse: Comment convertir du vieux code en un code scalable (qui se parallélise efficacement). Jeff présente différents problèmes concrets, la ou les les méthodes qu'ils ont choisis pour les résoudre, ce qu'ils ont perdus au passage et ce qu'il ont pu sauver.

Ce que j'adore dans ce chapitre est à quel point il est anti-académique. Certains code d’exemples m'ont vraiment fait réagir: "Je pourrais faire ça... Ça serait bizarre mais ça marcherait plutôt pas mal!". Le meilleur exemple est la façon dont Houdini gère la latence de création des threads (car créer un thread est assez long) quand la quantité de données a calculer ne vaux pas le temps de création des threads. Accrochez vous: If data_count < 5000 : compute in the main thread! :IFuckTheWorld:

Vous ne trouverez jamais ce genre de "solutions" dans un livre académique mais vous ne trouverez jamais plus efficace que ça sans avoir à modifier le code à milles endroits! :D

Chaque exemple est intéressant (bien que souvent très spécifique). Les lires entraine votre cerveaux sur pourquoi vous devriez faire les choses de tel ou tel façon et comment réagir quand vous voyez un truc qui semble louche.

Je dois avouer que j'avais lu le paper original de Side Effect après le Siggraph 2013. J'ai d'ailleurs remarqué qu'un petit travail de réorganisation a été fait et certains exemples m'ont paru mieux expliqué. Je me rappel avoir été un peu perdu avec certains des exemples du paper original mais je n'ai eu aucun soucis à comprendre ceux du livre. J'en conclu donc qu'une bonne relecture a été faite (ou que je suis plus capable de lire du code qu'avant ce qui est fort probable).

J'ai été super frustré par la fin du chapitre qui arrive trop vite... On en veut encore! :grenadelauncher: Plus d'exemples, plus de problèmes tordu (mais concrets) à résoudre!

Si vous souhaitez en savoir plus sur comment Houdini fonctionne sous le capot, j'avais traduis un post très intéressant que je vous invite à lire.

Chapitre 3: Le système d’exécution de Presto: Architecturer pour le Multithreading (par George ElKoura)

L'interactivité est le mot clef de ce chapitre.

La première partie n'est pas particulièrement intéressante. George explique les ambitions et les contraintes techniques. C'est chouette pour la partie animation (temps de latence, interactivité, etc...), mais il passe définitivement trop de temps sur des choses que tu connais souvent déjà sans vraiment expliquer les implications spécifiques à Presto ("La vectorisation du code est importante car blabla", "Il faut organiser ces données comme ça sinon blabla"). Le coté très général des conseils fait presque redondance avec le premier chapitre. Il aurait peut être été préférable de développer tout ces points dans le premier chapitre (plutôt que de brosser TBB dans tous les sens :trollface: ) et laisser chacun des autres chapitre se focaliser sur l’implémentation.

Cela dit, la second partie est vraiment superbe! Vous y trouverez pleins de petites choses qu'il faut avoir en tête si vous souhaitez développer pour des logiciel d'animation. La gestion des threads dans Presto (tout particulièrement la manière dont le graph d'evaluation est compilé puis exécuté) m'a semblé vraiment moderne, bien pensé et concret. Par concret j'entends qu'on est pas dans des choses génériques mais vraiment spécifiques. La gestion du temps (cache des géométries), la gestion de l'interface utilisateur avec une anticipation des valeurs modifié pour mieux préparer les "batchs" de thread (si un utilisateur modifie les contrôleurs d'un personnage, on peut vraisemblablement penser qu'il ne modifiera pas le cache des autres, inutile d’arrêter leurs threads car un thread coute cher à lancer rappelez vous). Chaque détail permettant d'éviter des ralentissements et d'augmenter le "rendement" des graphs est présenté.

Tout ceci est très clairement expliqué même si ça manque un peu de détails à mon gout (j'aime bien avoir des explications de cas un peu tordu).

Ils finissent avec un petit exemple de code (2 pages) sur comment multithreader un déformer géométrique simple. C'est un exemple intéressant car il présente un cas assez général mais qu'on peu rencontrer souvent en prod quand on est rigger. Vous vous en doutez, la solution est tout aussi "général".

Si vous souhaitez avoir un survole de comment Presto fonctionne sous le capot il y a de fortes chances que vous appreciez ce chapitre. Le mot "survol" est le bon terme car George ne se focalise que sur l'aspect multithreading (c'est le titre du livre donc difficile de le lui reprocher...) mais il parle souvent de choses implicites qu'il est difficile de cerner si on n'est pas habitué a Presto (j'imagine). A la fin du chapitre, on ne sais pas vraiment a quoi ressemble un rig dans Presto (relation entre les nodes et la UI, les nodes les plus bizarres/spéciaux/gros, etc...). Cette "abstraction" de certains détails techniques est souvent frustrante. :injures:

J'ai également ressenti une sorte de "tout va pour le mieux dans le meilleur des mondes". Comme si il n'y avait jamais eu de complication, aucun souci spécifique au multithreading (qui est pourtant un techno assez jeune en terme de paradigme), aucun "on a pensé faire ça car blabla mais on c'est rabattu sur ça car blabla". Sincèrement, en développement il y a toujours des moments ou la vision "abstraite" des concepts (vision nécessaire à l’architecture général d'un logiciel, surtout dans les premières années) se mange les cas non prévus de la réalité dans les dents. Des moments ou un juste milieu, un moindre mal est nécessaire. C'est d'autant plus flagrant quand on compare avec le chapitre suivant.

Chapitre 4: LibEE: Évaluation en Parallèle des Rigs des Personnages (par Martin Watt)

Celui là m'a littéralement surpris! Il se lit comme une histoire!

J’avoue que les premières page ne m'ont pas particulièrement fait sauté au plafond . LibEE est présenté comme un graph de dépendance (Dependency Graph ou DG) multithreadé... On pourrais presque lire entre les lignes "Le DG de Maya est totalement à l'Ouest alors on l'a réécrit". Le problème c'est qu'un graph de dépendance "a la Maya" ne rime pas forcément avec performance, surtout dans le cas d'un rig. Le fait que chaque node soit exécuté indépendamment puis passe son résultat au node suivant via des attributs, le tout badigeonné d'une dépendance inter-attributs (ou certains attributs d'entrés peuvent modifier certains des attributs de sortie mais pas tous) et vous obtenez un graph qui passe plus de temps a évaluer les dépendances pour savoir quel node exécuter qu’exécuter réellement les calculs des nodes (avouez que c'est con quand le node ne fait au final qu'une simple addition :siffle: ). Et c'est vrai pour Maya comme pour n'importe quel autre implémentation qui suit cette approche. La vitesse d’exécution d'un graph dépend souvent énormément de son "allure" et il n'est pas rare qu'un graph un peu tordu plombe drastiquement les performances. J'ai tendance à préférer l'approche compilé d'un VEX ou d'un Presto mais en lisant le reste du chapitre, je ne suis pas sur que la RnD de Dreamworks ait pu disposer de toute la latitude (et des ressources?) nécessaires.

Après, je ne suis pas dev a Dreamworks et il y a peut être un autre paquet de bonnes raisons... :dentcasse:

Mais bien que l'équipe de Dreamworks semble avoir fait un travail colossale pour contourner les limitations qu'implique ce type de DG, plusieurs sections tendrons a confirmer mes (humbles) hypothèses.

Et quand je parle de travail colossale je ne suis pas en dessous de la vérité. C'est la raison principal pour laquelle ce chapitre est exceptionnel: Vous "sentez" la production. Vous savez, les deadlines, les riggers qui râle sur les nouveaux outils "car-le-vieu-DG-de-Maya-il-aytay-mieu". Je suis un gros fan des quelques exemples de discussions entre les différentes personnes impliquées dans le projet (avec une petite copie d'un mail bien senti lol). Il explique aussi comment ils on eu à apprendre à leurs riggers à penser multithreadé (chose qui n'était pas prévu au départ). La présentation des différents outils de bench fourni au riggers pour qu'ils puissent trouver eu même les critical paths de leur code et qu'ils les "coupe" ou "blend" la logique en un seul node (un autre argument pour se tenir loin d'un DG IMHO). LibEE semble avoir suivi la situation typique d'une prod de VFX/anim ou les outils sont développé et utilisé en même temps (à l'inverse de Presto ou l'équipe semble avoir travaillé loin de la production, même si ce n'est pas clairement dit, avant de relâcher leurs outils). D'un point de vu développement, gérer une tel situation est un art en soit dans la mesure ou les objectifs/contraintes changent au fil du temps et ce chapitre explique (un petit peu) comment gérer ça.

Si vous êtes développeur et que vous pensez que les studios de VFX échouent car ils ne sont pas assez carré, passez ce chapitre, vous allez détester car c'est vraiment des situations de terrain, du vécu. Les autres, si vous voulez bosser en VFX il y a vraiment de quoi vous inspirer (ou vous faire fuir, au choix!). Et les derniers, ceux qui bossent déjà en VFX habitué des patchs-en-prod-parce-que-cay-super-plus-urgent-que-les-autres-urgences, vous allez vous sentir moins seul! :baffed:

Le second point concerne les expériences et tests qu'ils ont effectués en prod ou de manière plus formel. J’étais déçu que le chapitre Presto ne mentionne que quelques points techniques souvent assez connus (effet NUMA, bande passante de la RAM, Hyperthreading, etc...) sans fournir aucun graph ou expliquer en quoi ces problèmes impactaient directement Presto. Ici, non seulement les gars de Dreamworks expliquent ce qui les amènes à faire tel ou tel test mais ils fournissent une quantité de détails impressionnant qui explique, de manière très clair, comment et pourquoi tel ou tel effet apparait. Et on peut dire qu'ils ont poussé le bouchon très loin. Une fois encore, tout ces exemples ne sont pas académiques, ce sont de vrais use cases décortiqués et analysés très clairement. Certains tests expliquent même pourquoi un effet attendu n'est, en pratique, pas un problème.

C'est donc un chapitre super chouette! Un des plus intéressant du livre. J'aurais aimé que le chapitre de Presto sois aussi poussé.

Chapitre 5: Fluides: Simulation sur le CPU (par Ronald D. Henderson)

lol celui la est massif. Si vous aimez le code et les maths vous allez être servi! :aupoil:

Il y a quelques codes de comparaison entre OpenMP et TBB (avec du lamdbas C++11, première fois que j'en vois! :gne2: ). Si vous n'êtes pas à l'aise avec le C++, ça risque d'être assez dure (et un peu déroutant).

Pour ce qui est des maths, je dois admettre que j'ai pas mal rigolé chaque fois que je me disais "tin mais je capte rien! :baffed: " après quelques équations (et leur magistrales explications).

Dans les autres chapitres du livre, beaucoup d'explications se font sous la forme de phrases assez basiques tel que: "Nous mesurons l’efficacité des cores en divisant le temps de calcul par le nombre de core" (enfin un truc compréhensible quoi...). Dans ce chapitre, de tel phrases serait plutôt présenté sous la forme d'une petite équation de math bien senti suivi d'un: "Ou p est la dérivé relationnel d'infrastructure de la logarithme du nombre de core et n est le temps de calcul exprimé en second (ISU-CIPM 1967)". Bien sûr j'exagère mais dans la mesure ou je ne suis pas habitué aux équations mathématiques c'est exactement l'effet que ça m'a fait à la première équation. Et j'ai d'autant plus rie quand, après m’être bien trituré pour déchiffrer et comprendre tout ça j'ai réalisé qu'on pouvait résumer ça en une phrase... Haha! :smileFou:

Mais j'ai eu l’opportunité de travailler avec des matheux (ou des gens qui apprécient les maths d'une manière général) et ils ont cette tendance à jouer avec les équations mathématiques partout, y compris pour des trucs anodins (comme le temps moyen que passe les gens à la cantines en fonction des menus proposé, ou bien le temps de retards moyen des réunions suivant les dates de livraison) et ça m'a rappelé tout ces moments assez drôles. :jdicajdirien:

J'ai également apprécié la petite présentation de OpenVDB. J'ai souvent entendu parlé de OpenVDB mais je n'ai jamais compris comment il marchait sous le capot. Cette petite présentation est parfaite! Il y a un bon nombre de librairies open source utilisé dans en CGI mais elles manques souvent de présentations faciles à comprendre alors qu'il y a beaucoup de graphistes qui, bien qu'il ne soit pas développeurs, sont assez techniques et pourrais bénéficier d'une meilleur compréhension de ces librairies dans leur travail au quotidien. Donc les VFX boys, cette présentation est pour vous!

Pour le reste, c'était malheureusement trop mathématiques pour moi. Si vous trouvez difficile de lire des équations mathématiques, vous serez perdu dans ce chapitre. Ça été le cas en ce qui me concerne et je ne peut pas vraiment dire si ce qui est présenté dans le reste du chapitre est intéressant ou classique. En fait, je pense que vous pourriez vous en tirer si vous êtes un temps soit peu habitué au solver de fluides/liquides.

Chapitre 6: Bullet Physics: Simulation avec OpenCL (par Erwin Coumans).

Bullet_Physics_Logo.svg.png

Un chapitre bien sympa auquel je ne m'attendais pas vraiment. :bravo:

Je ne suis pas spécialement intéressé par la physique (au sens mécanique) mais je dois admettre qu'Erwin a fait un gros travail pour décortiquer et présenter sa librairie. C'est un des deux chapitre à aborder OpenCL et le calcul GPU (le second étant le chapitre sur OpenSubdiv) mais c'est surement celui qui le fait le mieux. Bien que l'aperçu soit assez rapide, il décrit très bien les différentes étapes de créations des batchs de calcul pour le GPU et revient dessus à chacune des (très) nombreuses étape de détection de collision/calcul de répulsion. C'est d’ailleurs un très bon aperçu de comment fonctionne un moteur physique ce qui est quelque chose de très intéressant à savoir quand bon bosse en VFX.

Il y a aussi beaucoup de petits schémas qui sont tous très clair, chacun ne se focalisant que sur un seul problème. J'ai tendance à préférer cette approche plutôt que peu de gros schémas qui essaient d’expliquer milles choses.

Il fini sur des choses plus avancés.

Surement le chapitre le plus clair et plaisant à lire. :marioCours:

Chapitre 7: OpenSubdiv: Interoperating GPU Compute and Drawing (par Manuel Kraemer)

J'attendais ce chapitre avec impatience et je n'ai pas été décu. Très chouette, il est composé de deux parties.

La première partie explique succinctement comment la subdivision itérative Catmull Clark fonctionne, sont histoire, pourquoi une "subdivision universelle" était nécessaire, et comment ils ont choisi de la multithreader. Si vous n'êtes pas familier avec la structure de donnée géométrique en arc dur (dite hard edge data structure) vous allez surement être un peu paumé. Manuel donne quelques benchs timides et conclu que le design itératif de la subdivision Catmull Clark, bien que nécessaire pour le rendu non temps réelle (off-line rendering), ne s'adapte pas très bien au contraintes du temps réel. J'ai été assez surpris qu'il n'aborde pas du tout comment ils organisent leur données dans la mémoire pour améliorer le cache et bénéficier d'une meilleur vectorisation. Je ne suis pas un expert, mais après avoir lu les chapitres précédents, je me demande sérieusement si il n'y avait pas d'autres axes de recherche pour améliorer les performances. Je suppose que Manuel n'en parle pas car les gains n'était pas substantiels. Qui sait... Mais pour avoir suivi le développement d'OpenSubdiv de loin, j'ai l'impression qu'ils ont rapidement sauté sur le GPU. Comme si c'était quelque chose de plus important pour le studio (Presto semble s'appuyer dessus) et que le code CPU serait "suffisant". Les nouvelles versions de Renderman s'appuyant massivement sur du raytracing (et donc, une subdivision CPU), j'en viens à me demander si Renderman s'appuie réellement sur OpenSubdiv.

La seconde partie présente comment OpenSubdiv utilise le GPU (et OpenGL) pour permettre un rendu d'une subdivision temps réelle en utilisant les shaders de tesselation. Une fois encore, j'ai bien apprécié la présentation du fonctionnement d'un GPU, leurs différences (contraintes surtout) par rapport à un CPU et comment organiser et préparer ces batchs pour en bénéficier. Les Edges Creases (un "truc" très présent dans OpenSubdiv) semble avoir été un problème (tous comme la gestion des triangles/quads/polys le sont dans une algo de subdivision) mais je trouve qu'ils ont été assez ingénieux dans la façon de le gérer: Ils ont séparé chaque set de géométrie pour lui appliquer différents algorithmes. Dans la mesure ou la topologie ne change pas, le processus de séparation est fait une seul fois et le GPU ne fait que recalculer les position des points avec le shader de tesselation associé à son "set de topologie". Une approche intéressante et pragmatique pour appliquer différents algorithmes de subdivision à une seule géométrie (bien que ça semble pas mal compliquer le code).

Je dérive un peu pour étaler mon point de vu: Je me demande vraiment si il était pertinent de garder les Creases dans OpenSubdiv. Le concept s’accommode parfaitement avec le principe de surface limite cher aux rendu REYES. Mais:

Une des dernière alternative que je vois au coté gourmand (en géométrie) du Creases si on ne peut pas subdiviser à tout va c'est de modifier la normale au niveau de l'edge (pouah! Le temps de calcul du truc). Mais cela faisant, vous devez prendre l'information en compte au niveau du shading et ce n'est pas ce que OpenSubdiv est supposé faire (sans compter les petits soucis qu'on pourrait avoir pour "blender" les normales). Mais il faut avouer que ça marcherait pas mal!

Bref, je me demande si les Creases n'était pas un truc dont Pixar (et seulement Pixar) a besoin. Ça pourrait expliquer pourquoi un concept aussi "exotique" se retrouve dans OpenSubdiv.

Notez que la prochaine version de OpenSubdiv arrive et semble avoir bénéficier des contributions et feedbacks d'autres studios (Dreamworks?). On dirait qu'ils ont isolés la partie algorithme de la partie structure de donnée ce qui est clairement une bonne chose car devoir passer sa géométrie dans une structure de donnée externe pour la récupérer ensuite est vraiment contre productif. Je suis content de voir qu'OpenSubdiv semble aller dans la bonne direction. C'est d'autant plus important qu'il devient une partie intégrante de Maya. :)

Conclusion

Et bien... Un très bon livre! :D

Il y a une inconsistance entre les chapitres. Certains vont vraiment au bout des choses (LibEE, Fluids, Bullets), et d'autres ne font qu'effleurer la surface (Houdini, mais surtout Presto).

Donc ce livre est exactement ce qu'il prétend être: Multithreading for Visual Effects. Et il ne se focalise que là dessus, laissant certains points, qui mériteraient aussi d’être abordé, de coté. Mais les logiciels choisis son tellement intéressants (Sérieusement: Side Effect, Pixar, Dreamworks!) que ça en est frustrant!

Le livre est super classe (hard cover! :laClasse: ) bien que le prix me semble un chouilla élevé (hard cover? :ideenoire: ). Mais il s'agit d'un domaine de niche donc on va pas cracher dans la soupe (vous en connaissez vous des livres à lire dans votre canap' qui parle des logiciels les plus cools du monde? :sauteJoie: ). Et puis faut bien l'avouer, la plupart du temps c'est votre studio qui va l'acheter... :P

Est ce qu'il vaut le coup? Si vous avez à coder des softwares lié au VFX, n'hésitez pas une seconde! Vous n'y trouverez pas de ressources "clef en main" mais c'est un peu comme si vous aviez une discussion avec des gars brillants qui partage leur expériences autour de leur logiciel. Pas sur que vous puissiez trouver de tels infos ailleurs.

Si vous êtes un graphiste un peu technique, je ne vous recommanderais pas forcément de le prendre. Il est vraiment tourné autour du développement, vous n'y trouverez pas de trucs et astuces en multithreading pour améliorer votre travail. Cela dit, je vous encourage à le piquer à votre RnD ( :IFuckTheWorld: ) et à le feuilleter. Le début de chacun des chapitre est souvent assez clair.

Après avoir lu ce livre, je me dis que je pourrais bien payer pour d'autres du même genre qui passe en revu et en profondeur (un truc advanced j'entends) l'architecture des logiciels de VFX (Houdini, Presto, Maya, Nuke). Comment les données transitent, a quoi ressemble les structures de données utilisées, comment un type spécifique d'opération s’exécute, etc... Et pas juste un aperçu. Les docs des logiciels sont souvent trop timide sur le sujet.

Avant, j'étais incapable de lire et comprendre de tels codes. Je tentais de déduire le fonctionnement et la logique sous-jacente des logiciels que j'utilisais par dichotomie. Maintenant que je sais lire du code, autant y aller et voir directement le code des dis logiciels! :D

Malheureusement, je suis passé à coté de pas mal d'informations intéressantes à cause de mon incapacité à lire des équations de mathématiques. Je veux dire, je sais ce qu'est une matrice 4x4, les raisons pour lesquelles ont pourrait les utiliser, je sais ce qu'est un dot product, un produit en croix et comment je peut les utiliser pour obtenir un effet souhaité mais c'est à peut près tout... Je m’énervais contre moi même de n'être pas capable de déchiffrer les équations (qui au final ne semblaient pas super compliqué :nervous: ). Idem pour certains morceaux de code que j'ai eu du mal a comprendre :gne: . Je suis passé à coté de pas mal de choses dans le chapitre des Fluids.... :triste:

Ce qui est très intéressant c'est d'avoir rassemblé des cours d'une session Siggraph sur un sujet donnée et d'en faire un livre. J'adore l'idée car je passe des heures derrière un ordi et j'apprécie de pouvoir lire ce genre de chose sur du papier plutôt que mon écran de PC (lire un PDF me fatigue assez vite).

Je n'ai aucune idée du succès du livre mais j'ai entendu pas mal de gens intéressé donc on pourrait imaginé... Je ne sais pas... "Alembic/OpenVDB/OpenEXR under the hood and use cases" avec un maximum d'explications sur les fondations et l'infrastructure, jusqu'aux points clefs du code. :smileFou:

J'espère que vous avez apprécié cette humble review! N'hésitez pas à commentez si vous avez vous aussi lu ce livre. Je serais curieux de savoir ce que vous en pensez. :sourit:

Dorian

:marioCours:

Mental ray for Maya: Decrease Final Gather flicking

samedi 20 juillet 2013 à 17:30

fg_diminuer_flicking_tn.pngIn this ticket, I present a simple way hack (keep in mind we are talking about mental ray for Maya :baffed: ) to drastically decrease Final Gather flicking.

You will see this method is a little tricky but it simply aims to reproduce the Interp. samples Vray's option behavior.

Foreword

Before start, know that it's truly Vray which prompted me to put my nose in mental ray, especially Final Gather map merging. While everything is very simple in Vray, in mental ray, it's a pain (as usual :septic: ).

Basically you will have to inject scripts in the Pre render frame MEL and Post render frame MEL ​​to recreate the behavior of Vray.

Mental ray actually provide a way to merge Final Gather maps, but Maya integration doesn't do it temporally (no Final Gather map with frame number name).

The scene

I took the typical kind of scene that brings Final Gather to its knees (and most GI caching methods in general):

fg_diminuer_flicking_001.png

fg_diminuer_flicking_003.png

Keep in mind: This is an extreme case. :papi:

fg_diminuer_flicking_002.png

The Final Gather diffuse bounces number is high to increase visual artectacts. Everything is here to have something awful. :aupoil:

Final Gather without interpolation

There is a render of the scene with Final Gather generated for each frame, without interpolation (Mode Automatic):

fg_anim_001.gif

As you can see, there is a lot of flicking. :ideenoire:

How to solve this? fg_copy is your friend! :dentcasse: (Specially the -f flag).

Well, acutally, there is already a way to give Final Gather maps to Maya to make them merged before render. This way will be the foundation to our "temporal interpolation".

Interpolate frames?

Basically, the idea is simply to "mix" several Final Gather maps together to mitigate the effect of flicking.

For a frame n, we merge Final Gather maps n-2, n-1, n, n+1, and n+2 (two before, two after).

In practice, mental ray will merge Final Gather points with similar normal using Min Radius of the scene. Two Final Gather points having a similar normal (I suppose the Normal Tolerance of the Final Gather Quality section is used to control that) and where the distance doesn't execeed the Min Radius of the scene (if set to zero is 10% of the whole scene bouding box) have their color and position merged.

You can see the scene size mental ray is rendering using the log:

RC   0.2     41 MB info : scene extent: (-12.34,-0.45,-17.07) : (15.83,10.96,12.07)

This approach is far from perfect and you will see it doesn't solve all problems. The ghosting you can have, better than a by frame flicking though, is still unsightly, particularly on renders with few texture/color variations (diffuse surfaces). That said, this effect may go unnoticed on some sequences (especially camera movements), it really depends on what you've got.

Bake Final Gather

To be able to merge Final Gather maps before render (5 maps in our case) you must, as a first step, generate all of them. And this is what we will do. :enerve:

As we have a range of 101-110 and we will generate two frame before and two frame after, the final Final Gather maps sequence will be 99-112.

Personnally, I use RenderLayers overriding Pre render frame MEL and Post render frame MEL scripts to generate fg map names using the current frame (eg: fgmap.0012.fgmap) just before render start.

fg_diminuer_flicking_004.png

For example, I override the RenderLayer that will be used to generate fg maps with this:

python("import preframe\nreload(preframe)\npreframe.updateFgFiles()")
python("import preframe\nreload(preframe)\npreframe.cleanFgParams()")

Ok, that's not really sexy but as you know, Pre render frame MEL and Post render frame MEL only execute... MEL... So we ask MEL to execute Python! :baffed:

In a "readeable" mode, the two calls are followings:

import preframe
reload(preframe)
preframe.updateFgFiles()

And:

import preframe
reload(preframe)
preframe.cleanFgParams()

Of course, there is a little preframe.py in your: maya\scripts.

The script

Here is the contents of preframe.py, contents that I will explain, function by function.

import maya.cmds as cmds
import os
 
def cleanFgParams():
 
	cmds.setAttr("miDefaultOptions.finalGatherFilename", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[0]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[1]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[2]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[3]", "", type="string")
 
def updateFgFiles():
 
	cleanFgParams()
 
	frame = int(cmds.currentTime( query=True ))
	fgmapFile = "fgmap.%s.fgmap" % str(frame).zfill(4)	# "fgmap.0012.fgmap"
 
	print "Set fgmap file for frame %s -> %s" % (frame, fgmapFile)
	cmds.setAttr("miDefaultOptions.finalGatherRebuild", 1)	# Rebuild On
	cmds.setAttr("miDefaultOptions.finalGatherFilename", fgmapFile, type="string")
 
 
def prepareFgFiles():
 
	cleanFgParams()
 
	frame = int(cmds.currentTime( query=True ))
	cmds.setAttr("miDefaultOptions.finalGatherRebuild", 2)	# Freeze
	cmds.setAttr("miDefaultOptions.finalGatherFilename", "fgmap.%s.fgmap" % str(frame-2).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[0]", "fgmap.%s.fgmap" % str(frame-1).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[1]", "fgmap.%s.fgmap" % str(frame).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[2]", "fgmap.%s.fgmap" % str(frame+1).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[3]", "fgmap.%s.fgmap" % str(frame+2).zfill(4), type="string")

You can copy this in a file in maya/scripts/preframe.py.

cleanFgParams()
def cleanFgParams():
 
	cmds.setAttr("miDefaultOptions.finalGatherFilename", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[0]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[1]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[2]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[3]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[4]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[5]", "", type="string")

This function clears the Final Gather file attributes (put an empty string). It's called just before setting the name of the Final Gather maps to save, and just after render, in Post render frame, to be sure to clear text fields.

updateFgFiles()
def updateFgFiles():
 
	cleanFgParams()
 
	frame = int(cmds.currentTime( query=True ))
	fgmapFile = "fgmap.%s.fgmap" % str(frame).zfill(4)	# "fgmap.0012.fgmap"
 
	print "Set fgmap file for frame %s -> %s" % (frame, fgmapFile)
	cmds.setAttr("miDefaultOptions.finalGatherRebuild", 1)	# Rebuild On
	cmds.setAttr("miDefaultOptions.finalGatherFilename", fgmapFile, type="string")

This function is set in the Pre render frame attribute of the RenderLayer and is used to give a correct name to the Final Gather map to save. It gets the current frame and generates a fg map name with the frame number.

The little "hack":

str(frame).zfill(4)

Used to generate the frame number with padding. Converting it to string first then apply a zero fill of 4, to make "10" to "0010" for example.

prepareFgFiles()
def prepareFgFiles():
 
	cleanFgParams()
 
	frame = int(cmds.currentTime( query=True ))
	cmds.setAttr("miDefaultOptions.finalGatherRebuild", 2)	# Freeze
	cmds.setAttr("miDefaultOptions.finalGatherFilename", "fgmap.%s.fgmap" % str(frame-2).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[0]", "fgmap.%s.fgmap" % str(frame-1).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[1]", "fgmap.%s.fgmap" % str(frame).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[2]", "fgmap.%s.fgmap" % str(frame+1).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[3]", "fgmap.%s.fgmap" % str(frame+2).zfill(4), type="string")

And the last function, in Pre render frame of the RenderLayer, used to fill every text fields with Final Gather maps to merge during final render. This is the same method we used to generate Final Gather map name but we generate two before and two after.

This is where you put Final Gather mode to Freeze to ensure you will merge your files before using them as such.

Render layers

There is a little description of my RenderLayers. :)

fg_diminuer_flicking_005.png

Don't worry about FG_RAW, it's only used to render in Automatic mode.

masterLayer

The main RenderLayer is prepared in order to get Secondary FinalGather Maps.

fg_diminuer_flicking_009.png

Note that, as all Maya's multi-attributes, if this values are empty, blocks are removed while reopening the scene. That's why I put the temp words in it. In any case, I remove this values just before frame render start (using the cleanFgParams() function). That's only to prevent Maya to remove entries (Workaround time!).

Important: Each entry has a temp with a different number just so I can render the FG_RAW RenderLayer avoiding mental ray to try to merge a fg map it is actually generating.

But there shouldn't ever be any Final Gather map named "temp" in your fg map folder. If there is, something has gone wrong during our process. :zinzin:

FGMAPONLY

This RenderLayer will be the first started. It's the one that will generate Final Gather maps (with two frames before and two frames after).

Pre render frame MEL and Post render frame MEL to override (using Create Layer Override) are followings:

python("import preframe\nreload(preframe)\npreframe.updateFgFiles()")
python("import preframe\nreload(preframe)\npreframe.cleanFgParams()")

Don't forget to put this RenderLayer in Multiframe (Optimize for Animation in Maya). But the attribute can't be override from the Render Settings. :trollface:

fg_diminuer_flicking_006.png

You must go through the miDefaultOptions node you can select typing this MEL command:

select miDefaultOptions

And looking for Final Gather Mode in Extra Attributes:

fg_diminuer_flicking_007.png

Easy as 1-2-3... :mayaProf:

As there is no interest to keep the image rendered during this process, you can override Render Mode to make mental ray compute only Final Gather:

fg_diminuer_flicking_005a.png

RENDERONLY

It's in this RenderLayer the "real" render will be done. The idea is to set the differents fg maps (n-2, n-1, n, n+1 et n+2) to make mental ray merging them in Freeze (no rebuild), and compute the final render.

python("import preframe\nreload(preframe)\npreframe.prepareFgFiles()")
python("import preframe\nreload(preframe)\npreframe.cleanFgParams()")

I encourage you to read the prepareFgFiles() function to fully understand what we do.

Command line

And it's time to start rendering! :popcorn:

I give you my two batch command line to help you:

"C:\Program Files\Autodesk\Maya2013\bin\render.exe" -mr:v 4 -mr:rt 4 -cam camera1 -rl FGMAPONLY -s 99 -e 126 -preFrame "python(\"import preframe\nreload(preframe)\npreframe.updateFgFiles()\")" -postFrame "python(\"import preframe\nreload(preframe)\npreframe.cleanFgParams()\")" -proj "D:\3D\VracProject" "D:\3D\VracProject\scenes\tuto_flick_mr_maponly.ma"
"C:\Program Files\Autodesk\Maya2013\bin\render.exe" -mr:v 4 -mr:rt 4 -cam camera1 -rl RENDERONLY -preFrame "python(\"import preframe\nreload(preframe)\npreframe.prepareFgFilesNoAnim()\")" -postFrame "python(\"import preframe\nreload(preframe)\npreframe.cleanFgParams()\")" -proj "D:\3D\VracProject" "D:\3D\VracProject\scenes\tuto_flick_mr_maponly.ma"

Notice: I've personally encounter few problems with Pre render frame MEL and Post render frame MEL overrides. That's the reason why I "hard" write them in the commande line.

Generating Final Gather maps (first line)

In the end of the first line execution, you should have the folder renderData/mentalray/finalgMap with something like:

fg_diminuer_flicking_008.png

Second line, render!

Aaaaaaaand:

Before: fg_anim_001.gif

After: fg_anim_002.gif

FG Merge. Because I'm worth it. :smileFou:

Ok, I admit gif is not the best thing to assess the image quality but you will notice it's a lot more stable. You will notice too, on the right wall, the ghosting effect I was talking about.

Once again, it's an extreme case:

There is the scene so you can see parameters and try all of this yourself.

Important: Keep an eye on you logs because (and I don't think it's "good" :pasClasse: ) Freeze mode is not as stupid it seems to be (see the doc). If a Final Gather map don't exists, it create it anyway. You will so have the impression, when the two batch lines will ends, that everything passed well (Final Gather maps are there and images so) but everything will flick...

Few informations you should keep an eye on (example for the frame 123):

RC   0.2     26 MB info : option:   rebuild         freeze
RC   0.2     26 MB info : option:   files           D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0121.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0122.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0123.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0124.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0125.fgmap
RCFG 0.2     27 MB info : finalgather map is frozen, using loaded from file(s)

I encourage you, as a first step, to start these two lines separately and check everything passed well between them.

I insist on the fact that you will not necessary succeed the first time. There is actually a lot of things to do. So persevere and keep in mind "this is possible". :hehe:

Variant

As you can see, flicking of animated objects (spheres and cube) don't change too much. We can consider many variant to solve this problem.

The first approach is to generate two distinct Final Gather maps sequence:

We can also go a step up in complexity (while we're there... :pasClasse: ) and use the fg_copy command to merge animated object Final Gather maps with a higher radius to to get farther Final Gather points. That said, I'm not sure this approach produces better results but it has to be tested.

And last but not least, you can combine this with importons to have better Final Gather points. :)

Conclusion

I was thinking it was impossible but we can actually "immitate" the Interp. samples Vray option in mental ray. :sourit:

Of course, doing it this way is not necessarily easy, and it's again unfortunate having to fight to benefit a feature available using a simple slider in Vray... :redface:

However, I hope this post have interest you and that you've learned things. I think if you can put this kind of system in place, you solve the main concerns about Final Gather (or similar techniques) in animations.

Don't hesitate to feedbacks in comments if I missed some points/explaination you would like to have. :dentcasse:

See you guys!

Dorian

:marioCours:

Mental ray for Maya: Diminuer le flicking du Final Gather

samedi 20 juillet 2013 à 17:11

fg_diminuer_flicking_tn.pngDans ce billet je vous propose d'utiliser une méthode simple un bricolage (on parle de mental ray for Maya là :baffed: ) visant à diminuer le flicking du Final Gather.

Vous allez voir que l'approche est un peu particulière mais elle vise tout bêtement à reproduire le comportement de l'option Interp. samples de Vray.

Avant propos

Avant de commencez sachez que c'est vraiment Vray qui m'a poussé à remettre mon nez dans mental ray, en particulier le merge des maps de Final Gather. Alors que tout est très simple dans Vray, dans mental ray, c'est la douleur (comme d'hab :septic: ).

En gros on va devoir injecter du script dans les Pre render frame MEL et Post render frame MEL pour recréer le comportement de Vray.

Mental ray permet déjà de "merger" des maps de Final Gather, mais l’intégration dans Maya ne permet pas de faire ça de manière temporelle simplement.

La scène

J'ai pris le genre typique de scène qui met à genou le Final Gather (et la plupart des méthodes de chaching de GI de manière générale):

fg_diminuer_flicking_001.png

fg_diminuer_flicking_003.png

C'est un cas extrême, ne l’oublions pas. :papi:

fg_diminuer_flicking_002.png

Le nombre de rebonds diffus du Final Gather est volontairement élevés pour gonfler les artefacts. Tout est présent pour avoir quelque chose de bien dégueulasse. :aupoil:

Final Gather sans interpolation

Voici un rendu de la scène avec un Final Gather calculé à chaque frame, sans interpolation (Mode Automatic):

fg_anim_001.gif

Comme vous pouvez le voir, ça flick pas mal. :ideenoire:

Comment résoudre ça? fg_copy est ton amis! :dentcasse: (Plus spécifiquement, l'option -f).

Bon, en fait il est déjà possible de donner des maps de Final Gather à Maya pour qu'il les merges avant rendu. C'est d’ailleurs cette approche qui va servir de base à notre "interpolation temporelle".

Interpoler les frames?

En gros, le principe consiste simplement à "mélanger" plusieurs maps de Final Gather entre elles pour atténuer l'effet de flicking.

Pour une frame n, on merge les maps de Final Gather n-2, n-1, n, n+1, et n+2 (deux avants, deux après).

Dans la pratique, mental ray va mélanger les points de Final Gather ayant des normales similaires en utilisant le Min Radius de la scène. Deux points de Final Gather ayant une normale similaire (Je suppose que c'est le paramètre Normal Tolerance de la section Final Gather Quality qui est utilisé) et dont la distance n’excède pas le Min Radius de la scène (qui, si il est à zéro, correspond à 10% du diamètre de la scène) voient leur couleur et leur position mélangées.

Vous pouvez voir la taille de la scène que mental ray utilise dans le log:

RC   0.2     41 MB info : scene extent: (-12.34,-0.45,-17.07) : (15.83,10.96,12.07)

Cette approche est loin d'être parfaite et vous verrez qu'elle ne résout pas tous les problèmes. En effet, l'effet de ghosting qu'elle génère, bien que plus acceptable qu'un flicking par frame, reste particulièrement disgracieux, en particulier sur les rendus avec peu de textures/variations de couleurs (surfaces "douces"). Cela dit, cet effet peut passer totalement inaperçu sur certaines séquences (notamment les mouvements de caméra), c'est donc au cas par cas.

Baker le Final Gather

Pour pouvoir merger les maps de Final Gather avant rendu (5 maps dans notre cas) il faut, dans un premier temps, toutes les générer. Et c'est ce qu'on va faire. :enerve:

Comme il va s'agir de deux fg maps avant et deux fg maps après, pour un frame range de 101 à 110, on a donc les maps de Final Gather de l'image 99 à l'image 112.

Personnellement, je procède par RenderLayers en overridant les scripts Pre render frame MEL et Post render frame MEL pour entrer le nom de la fg maps à la valeur de la frame courante (fgmap.0012.fgmap par exemple) juste avant que le rendu ne se lance.

fg_diminuer_flicking_004.png

Par exemple, pour le RenderLayer qui va générer les fg maps, j'override avec ça:

python("import preframe\nreload(preframe)\npreframe.updateFgFiles()")
python("import preframe\nreload(preframe)\npreframe.cleanFgParams()")

Bon, c'est pas super sexy mais comme vous le savez, les Pre render frame MEL et Post render frame MEL ne supporte que... Le MEL... On demande donc à du MEL d’exécuter du Python! :baffed:

En mode "lisible", les deux appels sont les suivants:

import preframe
reload(preframe)
preframe.updateFgFiles()

Et:

import preframe
reload(preframe)
preframe.cleanFgParams()

Et bien entendu, il y a un petit fichier preframe.py à placer dans votre: maya\scripts.

Le script

Voici le contenu du preframe.py, contenu que je vais détailler, fonction après fonction.

import maya.cmds as cmds
import os
 
def cleanFgParams():
 
	cmds.setAttr("miDefaultOptions.finalGatherFilename", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[0]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[1]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[2]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[3]", "", type="string")
 
def updateFgFiles():
 
	cleanFgParams()
 
	frame = int(cmds.currentTime( query=True ))
	fgmapFile = "fgmap.%s.fgmap" % str(frame).zfill(4)	# "fgmap.0012.fgmap"
 
	print "Set fgmap file for frame %s -> %s" % (frame, fgmapFile)
	cmds.setAttr("miDefaultOptions.finalGatherRebuild", 1)	# Rebuild On
	cmds.setAttr("miDefaultOptions.finalGatherFilename", fgmapFile, type="string")
 
 
def prepareFgFiles():
 
	cleanFgParams()
 
	frame = int(cmds.currentTime( query=True ))
	cmds.setAttr("miDefaultOptions.finalGatherRebuild", 2)	# Freeze
	cmds.setAttr("miDefaultOptions.finalGatherFilename", "fgmap.%s.fgmap" % str(frame-2).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[0]", "fgmap.%s.fgmap" % str(frame-1).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[1]", "fgmap.%s.fgmap" % str(frame).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[2]", "fgmap.%s.fgmap" % str(frame+1).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[3]", "fgmap.%s.fgmap" % str(frame+2).zfill(4), type="string")

Vous pouvez vous copier ça dans un maya/scripts/preframe.py.

cleanFgParams()
def cleanFgParams():
 
	cmds.setAttr("miDefaultOptions.finalGatherFilename", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[0]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[1]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[2]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[3]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[4]", "", type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[5]", "", type="string")

Cette fonction vide les entrées des attributs de file du Final Gather (met une chaine de caractère vide). Elle est utilisée juste avant de setter les noms des maps de Final Gather à sauver, et juste après (en Post render frame), pour être sur de vider les champs de texte.

updateFgFiles()
def updateFgFiles():
 
	cleanFgParams()
 
	frame = int(cmds.currentTime( query=True ))
	fgmapFile = "fgmap.%s.fgmap" % str(frame).zfill(4)	# "fgmap.0012.fgmap"
 
	print "Set fgmap file for frame %s -> %s" % (frame, fgmapFile)
	cmds.setAttr("miDefaultOptions.finalGatherRebuild", 1)	# Rebuild On
	cmds.setAttr("miDefaultOptions.finalGatherFilename", fgmapFile, type="string")

Cette fonction est utilisé en Pre render frame du RenderLayer et sert à donner un nom correct de map de Final Gather à sauver. Elle récupère le numéro de la frame courante et génère un nom de fg map à la frame.

Le petit "bricolage":

str(frame).zfill(4)

Sert à transformer le numéro de la frame en chaine de caractère (string) puis de lui appliquer un zero fill de 4, pour transformer "10" en "0010" par exemple.

prepareFgFiles()
def prepareFgFiles():
 
	cleanFgParams()
 
	frame = int(cmds.currentTime( query=True ))
	cmds.setAttr("miDefaultOptions.finalGatherRebuild", 2)	# Freeze
	cmds.setAttr("miDefaultOptions.finalGatherFilename", "fgmap.%s.fgmap" % str(frame-2).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[0]", "fgmap.%s.fgmap" % str(frame-1).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[1]", "fgmap.%s.fgmap" % str(frame).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[2]", "fgmap.%s.fgmap" % str(frame+1).zfill(4), type="string")
	cmds.setAttr("miDefaultOptions.finalGatherMergeFiles[3]", "fgmap.%s.fgmap" % str(frame+2).zfill(4), type="string")

Et dernière fonction, en Pre render frame du RenderLayer, qui sert à remplir tous les champs de maps à merger lors du rendu finale. C'est le même mécanisme de génération des numéros de frame mais on en génère deux avant et deux après.

A ce moment là, vous avez un Final Gather en mode Freeze, qui va merger vos fichiers avant de les utiliser tel quel.

Les render layers

Voici une petite description de mes RenderLayers. :)

fg_diminuer_flicking_005.png

Oubliez FG_RAW qui ne servait qu'à rendre en mode Automatic.

masterLayer

Le RenderLayer de base est préparé de manière à recevoir les Secondary FinalGather Maps.

fg_diminuer_flicking_009.png

Notez que, comme tous les multiattributs de Maya, si ces valeurs sont vides, les blocs sont supprimés à l'ouverture de la scène. C'est la raison pour laquelle je met le mot temp dedans. Dans tous les cas, je supprime ces valeurs juste avant le rendu de la frame (via la fonction cleanFgParams() si vous avez suivi). C'est uniquement pour empêcher Maya de supprimer les entrées (Workaroundman! :nousfesonslemal: ).

Note: Chaque entrée à un temp avec un numéro différent juste pour que je puisse rendre le RenderLayer FG_RAW sans que mental ray tente de merger une fg map qu'il est en train de générer.

Mais en principe, jamais une map de Final Gather nommé "temp" ne devrait être créé durant notre process. Si c'est le cas c'est que quelque chose ne marche pas. :zinzin:

FGMAPONLY

Ce RenderLayer sera le premier lancé. C'est celui qui générera les maps de Final Gather (avec deux frames avant et deux frames après).

Les Pre render frame MEL et Post render frame MEL à overrider (via Create Layer Override) sont les suivants:

python("import preframe\nreload(preframe)\npreframe.updateFgFiles()")
python("import preframe\nreload(preframe)\npreframe.cleanFgParams()")

Il ne faut pas oublier de passer ce RenderLayer en Multiframe (Optimize for Animation dans Maya). Mais l'attribut n'est pas overrideable depuis l'interface. :trollface:

fg_diminuer_flicking_006.png

Il faut passer par le node miDefaultOptions que vous pouvez sélectionnez en tapant la commande MEL suivante:

select miDefaultOptions

Et en allant chercher le Final Gather Mode dans les Extra Attributes:

fg_diminuer_flicking_007.png

Simple comme bonjours... :mayaProf:

Comme l'image rendue à ce moment là ne nous sert pas, vous pouvez overrider le Render Mode pour ne rendre que l'étape de Final Gather:

fg_diminuer_flicking_005a.png

RENDERONLY

C'est dans ce RenderLayer que sera fait le "vrai" rendu. L'idée étant de setter les différentes fg maps (n-2, n-1, n, n+1 et n+2) pour que mental ray les merges en Freeze (pas de rebuild), et nous calcule le résultat final.

python("import preframe\nreload(preframe)\npreframe.prepareFgFiles()")
python("import preframe\nreload(preframe)\npreframe.cleanFgParams()")

Je vous invite à relire la fonction prepareFgFiles() pour bien comprendre ce qu'on fait.

La ligne de commande

Et vient le moment de lancer le rendu! :popcorn:

Je vous donne les deux lignes de batch pour que vous puissiez vous en inspirer:

"C:\Program Files\Autodesk\Maya2013\bin\render.exe" -mr:v 4 -mr:rt 4 -cam camera1 -rl FGMAPONLY -s 99 -e 126 -preFrame "python(\"import preframe\nreload(preframe)\npreframe.updateFgFiles()\")" -postFrame "python(\"import preframe\nreload(preframe)\npreframe.cleanFgParams()\")" -proj "D:\3D\VracProject" "D:\3D\VracProject\scenes\tuto_flick_mr_maponly.ma"
"C:\Program Files\Autodesk\Maya2013\bin\render.exe" -mr:v 4 -mr:rt 4 -cam camera1 -rl RENDERONLY -preFrame "python(\"import preframe\nreload(preframe)\npreframe.prepareFgFilesNoAnim()\")" -postFrame "python(\"import preframe\nreload(preframe)\npreframe.cleanFgParams()\")" -proj "D:\3D\VracProject" "D:\3D\VracProject\scenes\tuto_flick_mr_maponly.ma"

Note: J'ai personnellement rencontré quelques soucis avec les overrides des Pre render frame MEL et Post render frame MEL. C'est la raison pour laquelle je les écris "en dur" dans la ligne de commande.

La génération des maps de Final Gather (première ligne)

A la fin de l’exécution de la première ligne, vous deviez avoir quelque chose dans le dossier renderData/mentalray/finalgMap qui ressemble à ça:

fg_diminuer_flicking_008.png

Seconde ligne, le rendu!

Ne tergiversons pas.

Avant: fg_anim_001.gif

Après: fg_anim_002.gif

FG Merge. Parce que je le vaux bien. :smileFou:

Bon, j’admets que le gif n'est pas ce qu'il y a de mieux pour juger de la qualité d'une image mais vous remarquerez que c'est beaucoup plus stable. Vous remarquerez aussi sur le mur droit, l'effet de ghosting dont je parlais précédemment.

Encore une fois, on est dans un cas extrême:

Voici la scène pour que vous puissiez voir un peu les paramètres.

Important: Suivez bien vos logs car (et je ne trouve pas ça super :pasClasse: ) le mode Freeze n'est pas aussi bête qu'il en a l'air (voir doc). Si une map de Final Gather n'existe pas pas, il la créé quand même. Vous aurez donc l'impression qu'à la fin de ces deux lignes tout c'est bien passé (les map de Final Gather sont là ainsi que les images) mais tout flickera...

Quelques infos à vérifier (exemple pour le calcule de la frame 123):

RC   0.2     26 MB info : option:   rebuild         freeze
RC   0.2     26 MB info : option:   files           D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0121.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0122.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0123.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0124.fgmap
RC   0.2     26 MB info : option:                   D:/3D/VracProject/renderData/mentalray/finalgMap/fgmap.0125.fgmap
RCFG 0.2     27 MB info : finalgather map is frozen, using loaded from file(s)

Je vous invite donc, dans un premier temps, à lancer ces deux lignes séparéments et à vous assurer du résultat entre chacune.

J'insiste sur le fait que vous n'y arriverez pas forcément du premier coup. Il y a pas mal de choses à faire mine de rien. Donc persévérez et sachez que c'est possible. :hehe:

Variante

Comme vous pouvez le constater, le flicking des objets animés (sphères et cube) ne change pas des masses. On peut donc envisager plusieurs variantes pour résoudre le soucis.

La première approche consiste à générer deux séquence de fg map distinctes:

On peut aussi aller un cran au dessus dans la complexité (au point ou on en est :pasClasse: ) et utiliser la commande fg_copy pour merger les fg maps d'anim avec un radius plus élevé pour aller chercher les points de Final Gather plus loins dans l'espace. Cela dit, je ne suis pas sur que cette méthode offre de meilleurs résultats mais c'est à tester.

Et enfin, vous pouvez combiner ça avec les importons pour avoir de meilleur points de Final Gather. :)

Conclusion

Je pensais que c'était impossible mais finalement, on peut bien "faker" l'option Interp. samples de Vray dans mental ray. :sourit:

Bien sur, faire ça de cette manière n'est pas forcément super évident, et il est une fois de plus regrettable de devoir se battre à ce point pour profiter d'un feature accessible via un simple slider dans Vray... :redface:

Toutefois, j'espère que ce billet vous aura intéressé et que vous y avez appris des choses. Je pense que si on arrive à mettre ce genre de système en place, on diminue pas mal l'un des principaux soucis du Final Gather (ou techniques similaires) dans les animations.

N'hésitez pas à me faire des retours dans les commentaires si il manque des éléments. :dentcasse:

A bientôt!

Dorian

:marioCours: