# Barley field with 1,000,000 strands

 Thread Tools Search this Thread Display Modes
 04 April 2013 #1 jjpous New Member   portfolio Jean-Julien Pous CG Artist Seoul, France   Join Date: Apr 2013 Posts: 6 Barley field with 1,000,000 strands Dear CGSociety members, I'm currently helping my wife working on a 2d animation film, about a little girl wandering in the country side, in barley fields. 118BG.jpg My task is to create those fields for 15 large shots. Some of them are low angle, with a lot of perspective, and some are high angle. That's been more than a month that I'm struggling on this task, I asked several friends and colleagues, but couldn't find any help, so I'm turning to you. I would like from you some ideas or strategies about how to tackle those barley fields. They have to be brushed by the wind. On half the shots, I'm estimating that I need about 1 million strands. Shot 47. Here are my attempts below: - Attempt 1 http://www.jjpous.com/files/boriya/3d/solution1-beauty.mp4 http://www.jjpous.com/files/boriya/3d/solution1-dof.mp4 viewport.jpg It works great for 10,000 strands, with perfect animation, unfortunately each time I'm trying to increase this number, Maya crashes quickly. I simply created a very basic mesh on which I apply a single barley strand drawing, then a bend deformer inside. I created an asset, and duplicated it 10,000 times, scattered these randomly across a field. Each bend Deformer is looking up a pixel on a fractal noise texture to know if it should bend -60 degrees for a black pixel, up to a 60 degrees for a white pixel, every single frame. This is a little slow, but looks perfect in real time with Viewport 2, so the render times are still super quick. You can see it in the video attached and the still jpg attached. The final look should be somehow close to 117BG.jpg. My script running on each frame to bend the barley: int \$nbPlants = 10000; int \$gridSize = 100; for (\$i=1;\$i<=\$nbPlants;\$i++) { float \$x = getAttr ("plant"+\$i+".translateX") / \$gridSize; float \$z = getAttr ("plant"+\$i+".translateZ") / \$gridSize; float \$color[] = `colorAtPoint -u \$x -v \$z -o "RGB" fractal1`; // print(" color at "+\$x+","+\$z+"="+\$color[0]); setAttr("bend"+\$i+".envelope") \$color[0]; } - Attempt 2 I tried to use Shave and Hair Cut, for the 1 million strand version I need for some high-angle shots. But the animation is very bad, the render times are crazy long, even if this solution is quite flexible to set-up. - Attempt 3 I tried using a texture sequence of the barley bending from -60 to +60, and instances. With a Maya shader Switch utility, I could assign random image start numbers to each instance, making the scene a bit lighter with only 1 real object, all others intances. But still, above 10,000 instances, it gets too slow to be workable. - Attempt 4 I tried with a height map, a noise deformer plugin from a japanese website, to have a single object, with each strand extruded from a plane. It's interesting, but doesn't look right as it's not bending, and keeps crashing regularly, especially when trying to edit UVs. - Attempt 5 The animation result isn't working so great, there are a lot of artifacts: I'm animating a fractal noise map in After Effect, and color-key each value of this map from white to black, cutting it in 50 different zones. Then, I use it to mask a sequence of barleys rendered, moving from -60 degrees to +60 degrees. The result is closer to solution 1, much lighter because it is very easy to change the animation​. But still not quite there yet, and I can't clean the artifacts coming from the key on the noise, resulting in a moiré pattern. - Attempt 6 I'm now trying with rendering a sequence of bending barleys, and using it on sprite and nParticles. I would like to use again a script on each particle, on each frame, to look up the fractal noise map, to know which sprite sequence number it should display. I'm quite new to Melscript, although I have basis in C/C++ programming. I'm desperate to find a solution, I'm working on it everyday without making clear progress... Your help would be really welcomed. Kind regards, Jean-Julien. Last edited by jjpous : 06 June 2013 at 12:34 PM. share quote
 04 April 2013 #2 jgibz Lord of the posts   portfolio Jack Gibbons USA   Join Date: Nov 2003 Posts: 787 117BG.jpg. I'm assuming that you're only rendering for the foreground in this shot? If the camera is moving then I can understand rendering more, but you may be better suited rendering in chunks and combining in comp. evaluating a script every frame seems a bit intensive, also there must be an easier way to get noise using turbulence without using a texture. have you not tried paintfx? I think billboards are good for your mid and background elements but rendering that much alpha might hurt your render time. share quote
 04 April 2013 #3 beverins Frequenter Richard Hagen Brooklyn, US   Join Date: Sep 2003 Posts: 105 You will need to go for a layered method using matte paintings, billboards, low poly objects, Alembic caches and compositing. You are not going to be able to pull this shot off in Maya straight from camera by brute forcing a real landscape.... unless you use Vue Xstream which DOES allow you to do this (though that's extra expense and you have to learn how to use Vue Xstream). For the "hero" barley one idea is to use Alembic Cache it after you've animated it. Do it in chunks. Layer the chunks back into the scene and remove the original geometry. For stuff that's farther away from the camera you should use lowpoly objects and farther still you need to use billboards. For the background mattepaintings are your best bet. One thing to note that if you want to go ahead and brute force this scene (either by trying to do it all in camera in Maya or via Vue Xstream) you are going to have a lot of high frequency detail which will flicker like mad unless you really turn up the anti-aliasing.... which will make the rendertimes go up. share quote
 04 April 2013 #4 jjpous New Member   portfolio Jean-Julien Pous CG Artist Seoul, France   Join Date: Apr 2013 Posts: 6 Hi Beverins, Jgibz, thank you for your input. Jgibz, I'm rendering the whole shot, not only the foreground. I tried with Shave&Hair Cut, + a turbulence field, but I can't get a nice animation with it. It's very hard to control I find. Plus, the Shave&Hair cut strands are bending from the root to the top, they are not looking like barley, which only the top moves. I tried PaintFX, but I can't assign a custom texture on each strand with it, right? Guys, by billboards do you mean a rectangle texture with several strands on it ? Like a group of 50 strands for instance ? The animation won't be as nice as wind blowing on each of them individually... Beverins, I understand your point. There are some wide shots with high-angle, with very little difference of size between the background and the foreground. On those shots, I guess brute-forcing is the only method? If I use a software like Vue Xstream, can I input my own texture on each barley strand? I tried to use Alembic cache on my scene, but as with Geometry Cache it was always crashing. I just asked my wife, the director , and she said if there are matte paintings, they should move. But how to make the barley move on the matte painting ? I recently approached the scene with a new method, using sprites nParticles, which allows me to create hundreds of thousands of barley strands in one scene. Each sprite has an animated sequence, which is driven by this fractal noise for animating it. The result is great. Bad news today: it takes more than 1 hour to render one frame with Mental Ray. And Maya 2013, even 2014, still doesn't support the sprites in Viewport 2. And with Viewport 1, it has a transparency sorting issue, showing the background sprites in the foreground. I'm now testing with Furryball, but I'm not sure if I'm heading in the right direction... I will also try rebuilding the scene with billboards for the background, thanks for the suggestion. Any idea how to fix the transparency sorting of sprites in real-time? Or a plugin that would display particles in realtime? Ps: I just found a useful checkbox for nParticles: under the Shading section, "Depth Sort" with a Treshold. Checking and unchecking "Use lighting" updates the viewport, and tadaa, the sprites are now correctly sorted in depth. That's a good thing. I still need to do the billboards approach. Last edited by jjpous : 04 April 2013 at 03:11 AM. share quote
 04 April 2013 #5 Bilgames Veteran portfolio Bilgames Sao paulo, USA   Join Date: Apr 2012 Posts: 44 You'll need to use proxies to render more objects using less ram share quote
 04 April 2013 #6 jjpous New Member   portfolio Jean-Julien Pous CG Artist Seoul, France   Join Date: Apr 2013 Posts: 6 Thank you, but I can't use proxies with particles sprites, can I? share quote
 04 April 2013 #7 jgibz Lord of the posts   portfolio Jack Gibbons USA   Join Date: Nov 2003 Posts: 787 Yes, billboards are essentially sprites, a polygon with a transparency on it. Again, I'm not sure what your camera is doing, but rendering individual barley for anything past the road isn't practical. At that distance there's not much reason to do anything more complicated than a matte painting. It might be worth a bit of research in finding out what paint fx can do for you, Honestly I've never used it in production, but I know it's meant for this kind of thing. Sometimes rendering at home just isn't worth the time. A company I used to work for was on a serious budget, and we used http://garagefarm.net/. A startup render farm based in south korea, relativly cheap and they had excellent support over Skype and they had no problems re rendering scenes that were wrong on our end for free. Last edited by jgibz : 04 April 2013 at 08:52 PM. share quote
 06 June 2013 #8 jjpous New Member   portfolio Jean-Julien Pous CG Artist Seoul, France   Join Date: Apr 2013 Posts: 6 Hi Jgibz, thank you for your last advice. It helped me to break down the scene in billboards. Now I have new issues with the Expression Editor, Runtime before dynamics and Script Nodes. 1. The foreground strands are made of planes with 5 subdivisions in height, bended vertically by a bend deformer. 2. The middle and background strands are nParticle sprites, showing billboards of 5,10,20, and 50 barley strands together. 3. I put a script node at Open to initialize the coordinates of the foreground strands and global variables: ``````global proc int init{ global int \$nbPlants = 1000; global matrix \$coord[10000][2]; global float \$color[]; global float \$tmpcoord[]; global string \$alphabet[] = {"a","b","c","d","e","f","g","h","i","j"}; global float \$fractalScale; \$fractalScale = getAttr("previewFractal.scaleX")/2; for (\$j=0;\$j<10;\$j++){ for (\$i=\$j*\$nbPlants;\$i<(\$j+1)*\$nbPlants;\$i++){ \$obj = "barley"+\$alphabet[\$j]+(1+\$i%\$nbPlants); \$tmpcoord = `xform -ws -q -t \$obj`; \$coord[\$i][0] = (\$tmpcoord[0]+(\$fractalScale/2)) / \$fractalScale; \$coord[\$i][1] = (\$tmpcoord[0]+(\$fractalScale/2)) / \$fractalScale; } } }`````` 4. To animate those fg strands, there's an expression: ``````if(!\$fractalScale){init();} // that was to force the execution of the node, but it still doesn't work. for (\$j=0;\$j<10;\$j++){ for (\$i=\$j*\$nbPlants;\$i<(\$j+1)*\$nbPlants;\$i++){ \$color = `colorAtPoint -u \$coord[\$i][0] -v \$coord[\$i][1] -o "RGB" fractal`; setAttr("bend"+\$alphabet[\$j]+(1+\$i%\$nbPlants)+".curvature") ((\$color[0] - 0.5) * 1.2); } }`````` 5. Then to animate all the nParticle strands, each of them (billboard of 5, 10, 20... strands) have their own Runtime Before Dynamics which looks like this: ``````float \$pos1[] = particule_gBackShape.position; \$pos1[0] = (\$pos1[0]+(\$fractalScale/2)) / \$fractalScale; \$pos1[2] = (\$pos1[2]+(\$fractalScale/2)) / \$fractalScale; float \$color1[] = `colorAtPoint -u \$pos1[0] -v \$pos1[2] -o "RGB" fractal`; particule_gBackShape.spriteNumPP = int(\$color1[0]*200);`````` 6. Here are the issues: - Sometimes, Maya doesn't load the script node when the scene opens: none of the variables are initialized, nothing works. - On a network rendering accross 20 computers, frames are frozen, skipped... Not even a single frame is usable. - It is very slow (about 30 seconds per frame for a playblast). There are 10,000 close up strands, and about 200,000 sprites. 7. I understood from replies on this post http://www.creativecrash.com/forums...ipt-every-frame that it's not efficient to use a script on the Runtime before dynamics, and other expressions that would run on each frame, but rather use a script inside the script editor, that would vary with the time. But I don't know how to write such a script. Any precious help in mel script would be very welcomed. share quote
 06 June 2013 #9 jjpous New Member   portfolio Jean-Julien Pous CG Artist Seoul, France   Join Date: Apr 2013 Posts: 6 ps: thank you for the renderfarm link. I'll consider them once everything works fine share quote
 06 June 2013 #10 jgibz Lord of the posts   portfolio Jack Gibbons USA   Join Date: Nov 2003 Posts: 787 Originally Posted by jjpous: - Sometimes, Maya doesn't load the script node when the scene opens: none of the variables are initialized, nothing works. You could use userSetup.mel. Usually it's more for setting up paths and importing packages, but you could use it to setup variables. These would be accessible from every maya scene you open though, so it's probably something that you should remove after this project is done. I'm curious if you could instead just make a control in your render scene with custom attributes that you can set by hand that will be gathered by your expression. Originally Posted by jjpous: It is very slow (about 30 seconds per frame for a playblast).. I'm by no means familiar with using expressions. But using a loop every frame seems to be what's causing your performance issue. As stated here: http://www.polyextrude.com/tutorial...ter7/hints.html __________________ gibby3d.com share quote
 06 June 2013 #11 jjpous New Member   portfolio Jean-Julien Pous CG Artist Seoul, France   Join Date: Apr 2013 Posts: 6 Thank you for the link, it helped me a lot to improve the script. Here's the new version below: // initialize barley scene // 1. SET THE previewFRACTAL SCALE global float \$previewFractalScale = 150; // done. script below \$deleteExpressions = `delete -expressions -all`; global proc float singleValue(float \$value[]){ return \$value[0]; } global int \$nbPlants = 1000; global string \$alphabet[] = {"a","b","c","d","e","f","g","h","i","j"}; string \$myScriptNode = `scriptNode -st 1 -bs ("global string \$alphabet[] = {\"a\",\"b\",\"c\",\"d\",\"e\",\"f\",\"g\",\"h\",\"i\",\"j\"};\nglobal proc float singleValue(float \$value[]){return \$value[0];}") -n "initNode"`; for (\$j=0;\$j<10;\$j++){ for (\$i=\$j*\$nbPlants;\$i<(\$j+1)*\$nbPlants;\$i++){ \$id = \$alphabet[\$j]+(1+\$i%\$nbPlants); setAttr("bend"+\$id+".envelope") 0.6; expression -s ("bend"+\$id+".curvature = singleValue(eval (\"colorAtPoint -u \" + (((barley"+\$id+".translateX + barleys.translateX)+("+\$previewFractalScale+"/2))/"+\$previewFractalScale+") + \" -v \" + (((barley"+\$id+".translateZ + barleys.translateZ)+("+\$previewFractalScale+"/2))/"+\$previewFractalScale+") + \"-o \\\"RGB\\\" fractal\"))") -o ("bend"+\$id) -ae 1 -uc all; } print(((\$j+1)*10)+" %\n"); } print("\n DONE.\n"); share quote
 06 June 2013 #12 CGTalk Moderation Expert   Join Date: Sep 2003 Posts: 1,066,473 Thread automatically closed This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum. share quote

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts vB code is On Smilies are On [IMG] code is On HTML code is Off CGSociety Society of Digital Artists www.cgsociety.org Powered by vBulletinCopyright ©2000 - 2006, Jelsoft Enterprises Ltd.