Back from Digital Domain

January 5th, 2010

Just got back from Digital Domain internship.

The 3 months internship was awesome and I learned a lot. I got involved a lot of stuff and met so many awesome people that make things happen. I really appreciate the experience.

Basically I worked on one shot in Tron 2.

Wrote and maintained several pipe line shelf buttons(with python) to help lighters in my sequence.

Created and maintained the render template for my sequence (100+ shots)

Got into some Maya API stuff, and I will continue working on it this quarter.

Worked on some look dev for my sequence.

Thanks to all the DD folks!

Preparing for Siggraph

July 31st, 2009

I updated my demo reel a little bit, and kicked out some old stuff out of my reel.

Since I used the accumulated displacement technique in my recent centipede shot 02, I could remove this one below from my reel:

accumulated displacement

Hope I could get some good feedback  at Siggraph..

More about Occlusion(part III)

July 22nd, 2009

There is a siggraph 2002 paper talking about how the ILM uses “Reflective Occlusion” and “Bent normal” techniques to generate fast and reasonablely accurate fake GI passes for light.

First we start with a reflective occlusion pass, actually it’s very easy to set up in the mib_amb_occlusion:

ref occ

Reflective Occ shader set up

This shader set up makes sure we are using “reflective occlusion” instead of ambient occlusion.
The image below shows the difference of normal Ambient Occlusion and Reflective occlusion. Obviously the reflective occlusion is more rely on camera angle and the surrounding objects:

occ compare

compare of Reflective Occ and Ambient Occlusion

And below is the compare of a same reflective occ pass with 2 different reflection passes:

ref occ result

result of reflective Occlusion

Then, it comes to the bent normal part. The goal of using this technique is to get a flexible fake GI pass (or indirect light pass) based on the given environment image.

Before we use the mib_bent_normal_env shader in MR, we need to do:

a. Bake(use mib_lightmap_write) the ambient occlusion into texture, before that we need to UV the geometry properly , in my case is the skull  model, without too many overlapping areas.

b. Bake(same as “a”) the bent normal into texture, just change the mode from 0 to 2(world space ) or 3 (object space) in the mib_amb_occlusion shader.

Then set up the mib_bent_normal_env as below:

ref occ

mib_bent_normal_env set up

And the render of mib_bent_normal_env will look like a GI pass based on the env map we provided:

Here is the result:

result_all

result of bent normal render and usage with reflection pass and a key light pass

In the siggraph paper, mighty ILM people were using customized Renderman shader to generate the reflective occlusion, baked AO and bent normal, and shader to use the baked textures. I tested with Mib_ambient_occlusion instead, but the whole idea is pretty mucn the same.

Be to noticed: this technique is not suitablt for a deforming object, and dramatic camera movement may also cause problem because of the baked textures.

Originally I did this test just for a fake GI test for a student film project I am working on. But I also had fun while was playing this, which is important ^____^.

mib_bent_normal_env shader

A recent project

July 13th, 2009

centipede project shot01

centipede project shot01

Updates comming soon

More about Occlusion(part II)

June 17th, 2009

3D collab class I helped with

The shot above was from the 3D collab class I helped with last quarter.

Since there were all Animation kids in their class, they needed some VSFX help.

I helped them set up almost everything such as lighting, shading, render passes, and compositing.

And a interesting stuff for me was to set up the Occlusion pass with correct refraction in it.

Usually when render the occlusion pass, we exclude all the “glass” and any other “transparency” objects from the render layer.

However, the master layer has been rendered with all the objects(including the refracted objects behind the machine’s glass containner in the shot above), so when it comes to the Occlusion pass, if the Occlusion haven’t been refracted, the final comp will not look correctly.

There are two ways to add the occlusion into the master layer.

1. One easy way to do it is using Mental Ray’s Mia-x material, and turn on the Ambient Occlusion on:

AO in Mia material

AO in Mia material

And all the occlusions will be rendered in the master layer.

2. If user were not using Mia material, it will be a huge pain to change all the shaders to Mia materials..

So the second way to achieve the “occlusion with refraction” is to :

a. Assign the “miLabel” to objects in the scene.

b. Don’t exclude the glass container of the machine. Instead, assign a miLable to the glass such as 2, then set the mib_AO shader’s attribute “ID Nonself” the same as the glass’s miLabel(in this case is 2). When set up like this,  the glass container will not cause any occlusion to other objects in the scene.

c. Instead of connect the mib_AO shader to the surface shader directly, connect it to a mib_refract shader(can be found in the sample composition tab) like this:

use mib_refract shader

use mib_refract shader

set the Refraction value to 1(or lower than one for not 100% transparanted glass), and set the “Index of Refraction” value exactly the same as your glass shader’s IOR value in the master layer(You could even write an expression to connect this two values if you are geeky enough).

After this, we will get the “refracted Occlusion”:

Result of Refracted Occlusion

Result of Refracted Occlusion

Hope this will help.


A little more..

Also, with similar set up, we can play with Occlusion even more. For example, I created the model of the feathers by overlaping poly planes with transparency maps. And with proper set up, I can render the occlusion like this:

AO in Mia material

Feather AO by using similar set up

Give it a try if you want, it’s really fun ^______^.

More about occlusion (part I)

June 16th, 2009

For example, I have a scene in the image below:

screen shoot of the examplescene

screen shoot of the examplescene

when using the MR shader mib_amb_occlusion node, if we want to render a pass that has the occlusion of the sphere rendered with out display it, normally we can just turn the sphere’s “primary visibility” off. It fits 90% percent of this kind of situations.

However, if user want not only the sphere’s occlusion be rendered, but also none of the boxes generate occlusion, it will be problem because if I turn “primary visibility” of all the boxes off, nohing will be rendered, and if not, the occlusion of sphere on boxes and the occlusion of boxes themselves will be rendered altogether, below is the undesirable result I got if just turnning the “primary visiblitiy” off:

rendered image with spheres pri visibility off

rendered image with sphere's "pri visibility" off

Obviously, the occlusion inbetween the gaps of the boxes are sometimes not we want…

This is when the “ID Inclexcl” “ID Noself” attribute come into handy.
Actually, the djx blog has a really good explain to this:

click here

One important thing to notice is that the “miLabel” attribute is case sensitive.

And for sake of  saving time, I wrote a script for assign the “miLabel” attr to all the selected objects.

Again, since it’s a reall small script, I wrote it with Python in Maya:

Click here

Copy the code into the Python tab of the script editor and use it….

After assign the miLabel to the boxes and sphere, I assign all the boxes’ miLabel =3, and assign the miLabel of the sphere to 1.

Moreover, correspondingly, assign the mib_amb_occlusion shader like this:

assign the ID correctly

assign the ID correctly

Then we will get the desired result:

result of correct ID set up in the shader

result of correct ID set up in the shader

With this set up, we can have only the sphere’s occlusion that affect the evironment…..

A little script to add the light annotations

June 4th, 2009

Inspired by my Friend Al Torres, I wrote a script to add annotations to all the lights in the scene.

Also, if lights’ names have been changed by usrs, re-run the script will update the annotations.

Since it’s very small script, and I don’t want people bother too much to install pymel, I wrote it with default python for Maya script.       This scriptif for usr has a lot of lights in the scene and might have a hard time to remember which light is for what…

Also, name the lights properly before using this script will be a good choice.

create annotations and updated names

annotations added and updated

Here is the script:

ling_addLights_annotation

Copy the codes and run in scripts editor. Hope this will help

Update: The last version of script has some bug: if a light in the scene has more than one children node, the script will not working due to my cheesy approach of finding the annotation node. For example:


Sometimes when duplicating the light an annoying camera node will be created

annoying camrea with the light

Sometimes Maya attaches a camera node to a light when duplicating it, the refined version of the script will delete the camera nodes attached to the light. Also, the script will check each children node of a light, make sure there is an annotation node in it. If yes, just update the light’s name when necessary. If not, create the annotaion.

Here is the refined version: ling_annotation_refine

Go Crazy with Dynamic Hair( Part II)

May 28th, 2009

Since the result for the puffer ball dosen’t look to bad, I wanted to do more with the dynamic hairs. I am taking Independent study with Prof. Bridge Gaynor, so I can free free to do what I want to achieve. The video below is the result. In this project, for the dynamic part I am pretty satisfied. However, for the lighting and intergration part, since I had a lot of trouble with the hair cache(which is famously known as bad), I did not  have much time do make the lighting look good…. I will re-light the scene during the summer.

Anyway, here is the result for right now:

result for right now

BG and Look development:

I shot the BG plate at the Jepson center of Savannah, and I wanted to create a senario that things are a little different than normal. I want to create the CG jelly fishes floating and “swimming” in the air. Beside the jellyfish, I want some CG water coming down the steps. With these two major different CG elements, I need use Maya, MEL, Pymel, Houdini, which makes this project really exiting to me.

Here is the BG shot:

shot with HVX200 and tracked with PFTrack

shot with HVX200 and tracked with PFTrack

I shot the scene with HVX200 camera, tracked it with PFTrack, and created proxy geometry for houdini as collision objects for the water.

Jelly Dynamic:

Attempt 1: In the beginning I planned to create dynamic hair, then use pointOnCurveInfo node to position joints, also add a expression to each joint(force the joint translate with the curve’s certain U value). Then after this, skin the pre-modeled jellyfish geometry with the number of joints….here is a test result:

with joints created, not very efficient way

with joints created, not very efficient way

As people can easily imagine, this approach is very inefficient, too many non-properly used nodes such as expression node, pointOnCurveInfo node have been added into the construction history. And the playback is really slow even just with one jellyfish in the scene.

Attempt 2: Instead of using joints to deform the geometry, simulate the hair curves and then loft a surface based on the curves is much easier and straigt forward. So I deleted the hand modeled geometry, twicked the script to automatically duplicate hair curves, then create a loft based on the hair curves. As a result, as long as the hair curves are dynamic, the surface is moving correspondingly.

here is the result:

lofted surface version is much faster than joints skin version

lofted surface version is much faster than joints skin version

In addition, I changed the curves from 2 skin curves to one skin curve, which will prevent the penetration issue in the later on dynamic simulation stagest(the self collide will help the hair curves reduce the likeness of penetration)

Attempt 3: To get a better control of simulation, make the rest curve pre-animated or pre-defined is better. So I created a blendshape for the rest curve, and when the blend value chage from 0 to 1, the rest curve will change from close position to open position, which represent the open and close motion of the jelly skin.

blendshape animation

Attempt4: After this, I lofted the surface, and based on the surface’s U value, I attached 600 folicles onto the surface, then each folicle has been attached a dynamic hair curve. 600 is pretty decent for the density of small curves on the edge of the skin. All these folicles and hairs are go with a new hair system that gives a seperate hair behavior control.

What’s more,  I added another hair system and some dynamic hairs to represent the long organic skin. Three other surfaces have been lofted based on the motion of the hair curves. Addition to this, a simple cluster and a circle as a controller created as a easy rig. As a result, the controller moves the shape node of the rest curves, causing all the dynamic system to response.

And here is the result:

all hair systems for a jelly created

all hair systems for a jelly created

Attemp 5: For the sake of better control of simulation tweaking, I wrote the UI for the tool:

As user can see, I can set and key random value to the open_close value of the jelly’s skin, which brings the jelly to live. Also, to get individule jelly’s corresponding hair system and cache them, some helper funcion such as “select hair system” and “set start frame” added:

UI to get better control and simulation

UI to get better control and simulation

Final result for the simulation part:

playblast of dynamics


Problems:

a. The dynamic hair cach system in Maya has been offering a really bad time. I ‘ve tried to customize the hair cache a litlle by constructing my own cache command. However, after this, Maya would never find the correct cache file again. I searched online for a while but no good anwser…. Which make me really unhappy was, since Maya can’t find the right cache, before it go to batch render the frames, it will re-simulate all the systems. This problem has been enlarged 10 times because I set up at least 10 render passes in my maya scene. As a result, even though the local render time was 3-10 second per frame per pass in average, I could not render my sequence within 2 hours per frame on the render farm, In the end, I have batch render locally, which consumed my time should be decicated to the lighting part.

b. another problem is a little weird but I think is fixable:

I wrote all the script in Windows. It works fine and the UI works perfectly. However, when I worked on Linux, the UI dosen’t display correctly. Except all the framelayouts, I lost all the buttons, fieldgrps, and instruction texts… Weird…Will looking into it later.

And the here is the lighting breakdown so far:

lighting breakdown

Special Thanks:
I need to appreciate Prof. Bridget Gaynor and prof. Ken Huff, without their greate suggestions I would finish this with more unnecessary pains.

Go Crazy with Dynamic Hair( Part I)

May 28th, 2009

This started from the script I wrote for Mr. Hanwei Wu, he did the lighting part of the puffer ball. He wanted a puffy ball for his TD comp class.

Here is the final result:

result , and lighting done by Hanwei Wu

To do this, I came up with an idea that use dynamic hair system to control the shape node of the  geometry, treat the hair system as the deformer of the tips of puffy ball.

put a folicle on each poly face, then create a dynamic hair based on it

puffer ball algorithm

To actually do this, I figured out how Maya attaches dynamic hair curves onto geometries.

a. create a hair system. Connect certain nodes to it such as Time node.

b. create a folicle node, which act as the bridget of hair system and the hair curves, also, with the help of : folicleShape.outTrans and folicleShape.outRotate, it can xform its transform node, so that the folicle can stick to the geometry.

c. create a rest pose curve, connect it to the hair system also.

d. create a curve as a dynamic hair, connect the hair system to the hair curve.

e. connect the folicle to the hair system and also the hair curves.

the steps above sounds a little confusing, the actual codes from my scripts can be easier to explain the steps:

connectAttr( ‘time1.outTime’, (hairSystemName+’.currentTime’),f =1)

connectAttr(geoShapeName[0] +’.outMesh’, follicleName + ‘.inputMesh’)
connectAttr(geoShapeName[0] +’.worldMatrix[0]‘, follicleName + ‘.inputWorldMatrix’)
connectAttr(follicleName  +’.outRotate’, follocleTrans[0] + ‘.rotate’)
connectAttr(follicleName  +’.outTranslate’, follocleTrans[0] + ‘.translate’)
## connect rest curve
connectAttr( (curveName + ‘.worldSpace[0]‘), (follicleName + ‘.startPosition’),f =1 )
## connect follicle to hair system
connectAttr( (follicleName + ‘.outHair’), (hairSystemName+ ‘.inputHair['+ str(i)+']‘),f =1 )
## connect hair system to follicle
connectAttr( (hairSystemName + ‘.outputHair[' +str(i) +']‘), (follicleName + ‘.currentPosition’) ,f =1)
## connect follicle to hair curve
connectAttr( (follicleName + ‘.outCurve’), (hairCurveName[0] + ‘.create’),f =1 )

notice:  “i” is the the index of curves in an curves array. codes in green color are used in a for loop.

Here is the result:

all nodes created and connected

all nodes created and connected

Then do a extrusion based on dynamic hair and its corresponding poly surface.With this set up, When I move the controller curve,the extruded geometry will act the same as dynamic hair curves.

Then it comes a really big and currently unsolvable problem for me: The extrusion nodes has limitaion:

a.Because my approach needs the “extrude along curve” option of the extrude node, the node need to specify the face to be extruded, and the curve to extrude along with. The problem is, with the “exturde along the curve ” option on,  every extude node only take one face and one curve to extrude with. As a result, each face on the geometry creates a extrude node in the construction history.

b. According to the real puffer ball, I need at least 400 hundred faces extruded, which means 400 extrude node in the history. I tried with this number and it took about 10 minute to open the hypergraph.

Instead, I decide use 96 (which is a box smoothed twice) faces to get the better performance.

Notes:

Before I know how the folicle node works, I came up a hard way to attach the rest curve to the move geometry.

what I did are :

Create a pointOnSurfaceInfo (or pointOnMeshInfo node in bonus tool), assign a certain UV value (certain poly face index also in the case on pointOnMeshInfo), then get the corresponding (x,y,x) value automatically.

Aassign a expression to the rest curve, which connect the position data of pointInfo node to the tranform node of the curve.

compares to the steps above,  folicles is very handy, given the U and V value of connected mesh/surface, the folicle node can automatically know where the corresponding postion of a UV point on a surface/mesh. With this method I can save two other nodes: pointOnSurfaceInfo and a expression node(when assign an expression, an expression node will be  created) . For the efficiency wise, I am very happy with the folicle rather than the others.

Also, the folicle node can be capable of position object onto the surface, such as do the same thing as the famous “rivot” MEL scripts does, and  it can be used to stick object to either dynamic simulated or keyed surface.

A little script to generate a nautilus

May 8th, 2009

To help my friend to generate a nautilus shell model, I’ve tried to write a script to model it.

And I found the math referrence here

screenshot of generated model

screenshot of generated model

According to the math, the shape of the nautilus majorly depends on two constant value a and b

and the the corresponding pymel codes are:

r = a*exp(radians(Delta_angle*n)*cot(b))
x = r*cos(radians(Delta_angle*n))
if(n ==0):
y = 0
else:
y = 10*(rBefore -r)
z = r*sin(radians(Delta_angle*n))

Then the rest are just create circle based on the calculated point positions, then do a loft

What’s funny was before I finish this script my friend had already done his model by hand….

At least is was fun though.

And two days after this, Sandro asked me how to write a spiral ST coloration in RSL,

showed him the algorithm in 5 minutes, happy coincidence.