Notes on Hair Making |
Feb 2007 |
The ideal way to create hair is to model the shape using NURBS patches, create hair curves out from them and the curves can be animated. The process can always let you go back to change the patches to adjust the shape and rebuilt hair mechanically with automation.
Maya Hair is used to create hair pose from which hair curves is extracted. These curves will be used to create Shave hair for rendering purposes. The reason is that Maya Hair is very good in dynamics while Shave is very bad in it when the hair is long. Another reason is that the result of rendering Maya Hair in mental ray is very bad. Even if it is rendered in Maya renderer (which can produce good result), there is still an anti-aliasing problem (see the following figure). To void this, Shave is used.

Maya Hair
The following is a procedure of how to create hair pose by modeling (and simulation).
- (Simulation only) Before generating hairs, you should have the head model, skeleton as well as the head's animation ready. Skeleton is required as it would be used to parent the follicles and hair constraints.
- Create NURBS patches with U running along the hair direction and U=0 being root of the hair. Number of span along V is 1. Both U and V ranges are from 0 to 1. Note that CV count along the U direction would affect stiffness of the hair.
- Select pathces and execute jcCreateHairClumps(n) to generate curves where n is the number of curves generated out from each patch.
- (Simulation only) Put all curves under a group which has a parent constraint (or parented) from the head joint.
- Select all curves or their parent group and choose Hair -> Make Selected Curves Dynamics. A hair system node would be created. Apply preset if there's any.
- (Simulation only) Select all curves or their parent group and choose Hair -> Convert Selection -> to Follicles. From the channel box choose Lock -> Base and Rest Pose -> Same As Start. Alternatively, this step can be done by exexuting jcModifyFolliclesbyGroup or jcModifyFolliclesbyCurves with preset.
- (Simulation only) From outliner, select Follicles corresponding to the hair curves of the inside layers and choose Simulation Method -> Passive from the channel box. Alternatively, this step can be done by executing jcModifyFolliclesbyGroup (if the curves are put under a group) with preset.
- Select hair system node, and choose Hair -> Assign Paint Effects Brush to Hair.
- Open hypergraph and delete paint effect brush created in previous step.
- (Simulation only) Select all curves and Hair -> Create Constraint -> Collide Sphere. Apply preset if there's any. Put constraints under groups which has parent constraint (or parented) from the corresponding joints (eg. head joint).
- (Simulation only) Apart from Collide Sphere and Cube constraints, hairs can be held by using transform constraint. Again, select all curves, choose Hair -> Create Constraint -> Transform. Move the constraint locator to the level about the same as the middle of the ear. Put it inside the group parented by the head joint. Adjust attributes (or apply preset) as follows:
- Stiffness = 0.2
- Glue Strength = 0.1
- Point Method = U Parameter
- U Parameter = 0.6
- (Simulation only) Choose Hair -> Create Cache to run simulation.
Hair Modeling Notes
- Hair Part
- Use Clump Flatness 1 at position 0 (or further if the position at head is not 0) to make the clump root flat and use Curl Twist to control its orientation so as to make the hair part at the top of the head straight. Note that the ramp scale position is relative to length of hair. If the hairs in front are shorter, the flatness along the part line will not be uniform. Use modeling technique (adjust the NURBS patches) to compensate.
- Roots
- Shave hairs tend to be stiff and straight at both ends even if the generation curves are very curly. Make sure the NURBS patch dig deep inside the head. Because the position at which the hairs bend sideways along the hair parting line is very close to the root.
- Tips
- The hair tips would not appear exactly where the NURBS patch ends. Make the patch longer.
- Edge
- Use dedicated curves to create edge hairs. Note that they should be thinner at root. But it may not be necessary to actually render these edge hairs if a blurry shadow is enough.
- Haircut
- Hairs at front are shorter. Long hairs resting on the chest are from the middle of the head.
- Clumps
- Hairs tend to be appear in clumps as you can see at the hair tips. Clumps appear to be uniform in width. Clumps should be modeled as NURBS patches rather than relying on the hair system to generate. It makes one clump per curve, which is wrong. One clump corresponds to one hair system and one Shave node. Use the hair clump parameters to do fine tuning only. Refer to photo reference to determine the number of clumps. The clump tips should be quite sharp. Make sure the ends of the patches are also sharp enough. In order to make the appearance of the clump tip look close to the paint effect curves, turn off Tip Frizz and Tip Kink in the corresponding shave node. Use suitable amount of Root Frizz to increase the overall thickness of the hair.
- As there're so many hair system and shave nodes in a scene, they should be grouped for different parts in the pose (eg. front, side, back) and those within a group would have the same attribute values. In this case, a master node for a group can be assigned to manage the member nodes. The attributes of the member nodes can be connected to those in the master node so that when the master node is updated, the member nodes will also be updated. The attributes can be connected by a simple script (jcConnectShaveNodes).
Shave and Haircut
Convert paint effect to curves and use them to create Shave hair. Detailed steps are as follows:
- Select pfxHair node and choose Edit -> Convert -> Paint Effect to curves. A group containing curves will be created.
- Select all curves and delete history. (Leaving history behind would make rendering fail.)
- Select each group of curves and choose Shave -> Create New Hairs. Choose the newly created shave nodes. Open attribute editor and make sure interpolation is off, multi-strand and rand scale are zero (or apply preset). The resultiing hair shape should be exactly the same as that generated by Maya Hair.
- If hair is not dense enough (eg. 1000), increase hair count (eg. 2000), turn on interpolation, increase hair passes (eg. 3) if you want.
Render Shadow
To render shadow in a separate pass:
- In Shave Global, setup the following parameters:
- Hair Render Mode = Buffer
- Compositing = off
- Shadows = Use Buffer.
- Hit render and the resulting image will include shadow but not hair.
FG has no effect on shadow as Shave just ignores non-spotlight lighting. If FG is to be used, it is necessary to convert hair into polygon so that shadow can be rendered correctly. But you must be able to control the polygon count so as to limit render time. Thus use the polygon objects converted from Maya Hair:
- Select hair system node, increase thickness of hair a few times to make sure its dense enough to cast shadow. Delete paint effect brush. If you don't delete it, polygon count to be converted will be much higher, render time will be increased significantly and the polygon hair will be very thick. (Use jcDeleteAllBrushes to delete the brushes.)
- Select pfxhair node, choose Modify -> Convert -> Paint Effect to Polygon with these options:
- Vertex Color Mode = None
- Quad Output = on
- Hide stroke = on
- Polygon count = (enough to include all hairs)
- Select the resulting polygon object, delete history (optional) and turn off Primary Visibility and Receive Shadow in its Render stat.
- Assign a black matt (black surface shader) to the polygon object and delete its hairtube shader. (Use jcHideMeshes to perform step 3 and 4.)
If the polygon count is too high, reduce it by reducing subSegments in the hairsystem node.
Make sure the meshes are outside the hair occlusion objects list in Shave Globals. (See note in next paragraph.) If "hairOcclusionObjects" is "all", Shave will try to cast shadow onto all the meshes and render will likely fail with message "PHEN 0.0 error: Shave: renderShadows -- shadow pass failed with status 1.".
Notes on Multi-Pass Rendering
Shave only obeys its hair occlusion objects list without considering render layer and visibility of objects. It ignores the object inclusion in render layer. This is intentional as Shave can render a separate hair pass even if the objects are visible. Its hair pass considers the hair occlusion objects list only so as to produce a correct alpha. With correct alpha, this hair pass can be used to overlay other render pass without doing z-depth compositing (like what Maya Hair does).
Put only those objects which would affect hair alpha and shadow into hairOcclusionObjects attribute (which does not accept selection set). To do this create a selection set called hairOcclusionObjects to include objects you want. In outliner, expand the set and highlight the objects under it. Then open script editor and you'll see the object list in the most recent select command. Copy and paste that object list into the hairOcclusionObjects attribute. Or use the following mel script:
if (`objExists hairOcclusionObjects` && `objExists shaveGlobals`)
{
string $s[], $a, $cmd;
select -r hairOcclusionObjects;
$s = `pickWalk -d down`;
$cmd = "setAttr -type \"string\" shaveGlobals.hairOcclusionObjects \"";
for ($a in $s)
{
$cmd += $a + " ";
}
$cmd += "\"";
eval($cmd);
};
For the same reason, make sure the visibility of the shave display object (mesh node) is off under other render layers even if it is not included in those layers. Otherwise, it'll be rendered. Alternatively, you can use render override to turn off the active attributes of the Shave nodes.