利用者:Phonybone/Hair

提供: wiki
移動先: 案内検索

Hair System

What is it for?

  • Separate hair code from particles
  • Clear distinction of render geometry ("children" -> "fibers") from coarser guide curves ("parents" -> "guide curves")
  • Improve realtime (OpenGL) rendering by utilizing GPU parallelism for hair interpolation
  • Simple API for making hair accessible, also for addons
  • Same functions for renderers and exporters
  • Experiment with alternative rendering features, like hair surfaces ("anime hair"), coloring, etc.

What is it NOT for?

  • Hair dynamics
  • Hair editing (aka. grooming)
  • Duplis
  • Anything particles, apart from

These features should be implemented in a higher-level system (see #Grooming). The hair code itself should stay small and manageable.

Code structure

Hair System

  • Guide curves ("parents")
  • Follicle points (track the mesh surface when it deforms)
  • Serialized data stored in blend files

Hair Export Cache

  • Temp. runtime data for generating rendered fibers ("children")
  • Can be updated repeatedly to reduce recalculation

Typical code sequence for exporting hair

  1. Create or update a hair export cache for the required data
  2. Create buffers for storing fiber data (vertex locations and curve start/count indices)
  3. Fill buffers through the API based on the export cache
  4. Destroy the export cache if no longer needed
OpenGL drawing skips steps 2 and 3 and actually interpolates fibers on the GPU


Typical code sequence for changing guide curves

// TODO several ways of using the API, clean this up and make it robust

Updating guide curves will typically invalidate hair export caches to some degree.

  • If only guide curve vertices are changed then fiber topology (vertex count) remains unchanged.
  • If guide curve vertex counts are changed (e.g. for lengthening hairs) then fiber data in export caches also becomes invalidated and is updated before next use.
For OpenGL 3.2 hair shaders this necessitates re-uploading vertex buffers
  • If guide curves are added/removed or if their placement is modified then follicle binding to parents becomes invalid. This requires subsequent re-binding to ensure that parent indices and weights for interpolation are correct.

Use cases for hair export

OpenGL hair cache and shaders

  • Generated from hair system through the export API
  • Hair interpolation is done on the GPU!
  • Guide curves encoded in textures
  • Vertex buffer
With GL 3.2 we cannot generate vertices efficiently, so have to create a dummy vertex buffer. Actual interpolation work on the GPU, so vbuf only needs uploading when hair topology changes, i.e. guide curves added/removed or vertex count changes. With 4.0 tessellation shaders could generate full vbuf on the GPU itself (cf. OpenSubDiv)


Cycles export

  • Generated from hair system through the export API
  • No functional changes to hair render code

Alembic export

  • TODO
  • Generated from hair system through the export API

Point density textures

  • TODO
  • Generated from hair system through the export API

Grooming

The Groom system is providing tools for modeling and editing hair geometry. It goes beyond the simple guide curve editing in particle systems by using higher-level structures ("bundles") to make the grooming process less tedious and more controllable.

It's important to note that the Groom object is only one possible way to generate hair geometry. Other systems can be added in the future, using the same underlying hair rendering system. That being said, the Groom object is designed with flexibility in mind and should be suitable for diverse human and animal character hair modeling needs.

Structure

Grooming is implemented as a separate object type, i.e. there is a "Groom" object along with "Mesh", "Curve", etc.. This deviates from the old particle system, which was built on top of an existing mesh object that acted as the scalp. The reason is that a separate object provides a cleaner context path for things like edit mode and operators, and generally keeps the code cleaner.

The groom object references a mesh object that is the designated "scalp". All hair curves will be generated on that scalp surface.

The first structural level of the groom data consists of scalp regions. These are partitions on the scalp surface - every point on the surface belongs to at most one scalp region. Each region generates hair curves using one of several methods.

  • Bundles are used for long hair styles. The are implemented as curves with a variable cross-section. All hairs for the respective region lie inside the volume of the bundle.
  • TODO add more types

Mesh Sampling

A very common requirement of hair geometry is to generate a set of points on a mesh surface, and then track that point after mesh deformation. This allows keeping a consistent placement of hairs on a "scalp" surface when the underlying mesh is animated.

Along with the hair system an independent code library for generating and evaluating such mesh points is added to BKE (the "blenkernel" code module). It has no dependencies on the hair code, so can be used separately for other purposes.

Tracking points on a mesh surface is done using simple vertex weight triplets. As long as the mesh topology does not change this allows a stable tracking of the surface under deformation. The local transformation of the point position, normal and tangent space is the same as that of the mesh surface.

In the future the system should support changes in mesh subdivision as well. This is possible in principle in the particle system code but has been a constant source of headache. A dedicated code module for handling mesh tracking should help write much more robust code for use of ORIG_INDEX.


A large part of this module is concerned with actually generating large sets of quasi-random points on meshes. There are many different algorithms for producing such sets, each with different qualities and tradeoffs.

  • Uniform random points can be generated very quickly and cheaply, with simple parallelization. The downside is that points have no restrictions on how close or far they are spaced.
  • Poisson-disk distribution is great for simulating natural processes, such as hair follicle growth or plant distribution. They guarantee a minimum distance between points, and typically create much more even spacing. Parallelizing is more difficult but possible.
  • Ray-cast and proximity methods create mesh points from ray intersections and closest-points respectively. They are useful for tools like "painting" particles and other specialized applications

Conversion functions exist to turn the current face-"uv" weights in particle data into the new mesh samples and vice versa.


ToDo List

  • Support different types of hair generation per region:
    • Bundles: extrude along a curve, as now
    • Fur: simple extrude along normal
    • Parents: directly edit guide hairs (good for converting legacy particle hair)
  • Decide how to implement subdivision consistently:
    • May want different subdiv levels for draw vs. render (export caches, COW)
    • For fibers: OpenGl 3.2 shaders need subdiv on guide curves, tessellation shaders won't need it
      Support transform feedback for hair fibers as well
    • Still want subdiv on guide curve vertex buffers for drawing overlays
    • Groom curve subdiv is separate yet again, used for drawing groom shapes and for certain tools (cutting)
  • General re-parameterization support for guide curves in hair
    Uniform segment length is better for both rendering and for physics
    Groom curves for editing can remain non-uniform
  • Support mesh subdivision in the mesh sample system.
    MeshSample stores the original indices, then needs to do a lookup or on-the-fly subdiv to get final locations on eval.
  • Mesh sampling with poisson disk generator is buggy. The distribution seems to violate the disk condition sometimes, particularly around face boundaries (?). Threading is also not really working yet - the required inter-thread communication can not be done with the simple task splitting model of BKE_threads so far.
  • FIX bundle shapes (seems to not match the face map contours)
    Only contiguous regions are supported (so shapes are one single loop). Write a check function to at least warn when a non-contiguous face map is used. Future region primitives can make that an invariant.
  • Better groom visualization (solid/semi-transparent shapes)
  • Consider: splitting hair system into follicles + guide curves, construct separately
    At this point the hair system is really just a struct combining these two parts
  • [DONE] Reduce influence of secondary parent guides based on the taper factor
  • Tools for editing groom bundles:
    • [DONE] add/remove regions
    • [DONE] extrude/draw/cut bundles
    • shape sculpting & reset
    • scale transform on curve sections, w/o need to select all verts
  • [DONE] Provice absolute (object-space) length values on fiber vertices, for accurate deformation parameters
  • [DONE] Render Cycles hair for groom objects
  • [DONE] Implement groom bundle constraining to the scalp surface
  • [DONE] Distinguish bundle from region:
    • Region is a scalp region (currentlu implemented via facemap)
    • Bundle is one way of creating hair in that region, there could be other types (fur, direct guides, etc.)