Skip to main content

Controlling the Shape of Shadows

The factors that affect the shape of shadows mainly include Surface NormalsSelf-Shadowing, and Shadows of Other Objects.

The shadow generated by the surface normal refers to the fact that when light shines on the surface of an object, the larger the angle between the surface normal and the light direction, the less light energy per unit area received.

Therefore, the closer the normal and the light direction are to 90 degrees, the darker it is.

image-20230331023212540

Custom Shadows From Self or Other Objects

MooaToon offers both Ray Tracing and Shadow Bias methods to remove cluttered Self-Shadows and shadows casted from the scene.

The Ray Tracing method provides full functionality, and should be used in preference to Ray Tracing when performance allows. Shadow Bias is only an alternative when performance is low or equipment is too old.

- Ray Tracing

Thanks to Ray Tracing, specific material information can be obtained, and the behavior of Ray Tracing Shadows can be controlled through material properties.

MooaToon provides the function to disable Self-Shadowing and Shadow Casting to different IDs.

With these two functions, you can achieve: 

  • Disable Self-Shadowing for a character completely and receive projections from other characters or scenes

  • Divide the same character into several different parts, disable Self-Shadowing for each part, and receive shadows from other parts or scenes

To use these functions, you first need to set different IDs for different parts of the character.

Set IDs

MooaToon uses IDs to determine whether the material hit by the ray is part of the same part as the material at the starting point of the ray. You can choose one of the following two methods to set the ID:

- ID Map

ID Map refers to filling different parts of a character with different solid colors, making it easy to cut out textures during texture creation or post-production.

It is usually essential in the film workflow, and its resolution can be very low as long as it does not overflow the UV boundary.

image-20230402014946639

By using ID Map, you can precisely control the ID down to the pixel in a material:

image-20230402014748222

caution

Due to GBuffer bit depth limitations, there needs to be sufficient difference (8 / 255) between different IDs in the ID Map.

The color space of ID Map must be linear (uncheck sRGB in texture assets).

- Separate Materials and Set ID Offset

There is a simple way, you can set different materials for different parts of the character, and set different ID Offset for each material.

Although this method does not require an ID Map, it will generate more draw calls, slightly increasing rendering performance overhead. Please use it judiciously.

Disable Self-Shadowing

After setting the ID correctly, you can use Disable Self Shadow to disable Self-Shadowing of each part of the character:

image-20230402023037227image-20230402023133224

You can see that the messy Self-Shadowing of each part of the character has disappeared.

Disable Shadow Casting to Different IDs

Next, enable Disable Cast Shadow on Toon:

image-20230402023218899image-20230402023306508

Now you can see that all shadows other than normal shadows have disappeared.

- Shadow Bias

As an alternative to Ray Tracing, it is possible to simply offset the pixel depth when depth testing in the light space to remove all shadows at a certain distance.

You can find the Shadow Bias parameter at:

  • Post Process Volume > MooaToon > Shadow Bias
  • BP_MooaLookDevTool > Post Process > Shadow Bias

Increasing the Shadow Bias to remove shadows from obstructions at a certain distance. For example, setting the Shadow Bias to 200 means that objects within 200 cm from the surface of the character model will not cast shadows on the character:

Shadow Bias: 0Shadow Bias: 10Shadow Bias: 30Shadow Bias: 150
caution
  • Shadow Bias only works without Ray Tracing Shadow.
  • Shadows may suddenly appear beyond the Shadow Bias distance.
  • Due to UE's own algorithmic problems, Shadow Bias may not be consistent for different types of lights and different distances between the light and the camera.

Custom Hair Shadow

The hair shadow in the artwork usually matches the hair outline. MooaToon provides Screen Space Depth Test Hair Shadow to achieve hand-drawn hair shadow programmatically without modifying art assets.

You can also choose to use a translucent model as the hair shadow, which can be customized in shape but requires modifying artistic assets.

- Screen Space Hair Shadow 

First, you need to correctly set the IDs for the face and hair: 

Set IDs for the Face and the Hair 

If the face and hair use different materials, you can directly specify the face and hair through material parameters; otherwise, you need to use an ID Map.

- Material Parameters 

Enable Is Face on the face material, and enable Is Hair on the hair material.

- ID Map

Open your ID Map in DCC software, note the values of the ID channel corresponding to the face and hair IDs:

image-20230401223120786

Set Face ID and Hair ID to the corresponding values:

image-20230402014412616

Set Hair Shadow Parameters

After correctly setting the IDs for the face and hair, enable Use Screen Space Depth Test Hair Shadow on the face material:

image-20240804155249492

Hair shadow parameters can be globally adjusted through Console Variables, or adjusted in BP_MooaLookDevTool.

image-20230402034859479image-20230402034938125image-20230402035007699
Hair Shadow Width: 0.2
Hair Shadow Width: 0.3
Hair Shadow Width: 0.4

The principle of this method is to sample depth by translating a distance from the current pixel towards the light source, and if the sampled pixel is hair and has a smaller depth, it is occluded.

Therefore, the shape of the hair shadow depends entirely on the shape of the hair from the current viewpoint:

- Translucent Model

This method does not require engine support. an artist creates a separate translucent model placed under the hair for shadow, allowing full control over the shape.

Please refer to this project: MIKONOTE Anime Toolbox Sample

image-20230331030055864

Custom Normal Shadow

In MooaToon, you can modify the shape of the normal shadow using the following methods:

Modify Normals

Modifying vertex normals is the most direct way to avoid ugly shadows and is applicable to different engines and renderers.

You can choose different methods to improve normal shadows: 

- Houdini Normal Transfer

This method replaces the normals of the original model with those of a simple model, achieving controlled and good results at a low cost, suitable for most scenarios.

This article documents how Arc System Works applies this technique in Guilty Gear:

image-20240805210100882image-20240805210104763
Shadows generated by original normalsShadows generated by replaced normals
image-20240805210147749image-20240805210159746
Simplified modelWrap the original model with a simplified model, then find and replace the normals of the original model with those of the nearest vertices

The Unity Chan model in the MooaToon example is processed in Houdini using this method, and all source files are included in the project.

Houdini is a commonly used DCC software in the film and game industry. Its powerful node-based workflow and geometry functions are ideal for making some procedural adjustments to characters, such as adjusting normals, baking AO / Curvature / any custom data to vertex color and UV, and each step is represented by nodes, allowing you to modify the order and parameters without breaking other modifications.

Install Houdini
  1. Download and install the latest Houdini 19.5, make sure to check SideFX Labs during the installation process.
  2. Activate Houdini. You can try Houdini Apprentice for free, but cannot export FBX files.
  3. Copy one and open MooaToon\MooaToon-Project\Art\Models\MooaToonHoudiniPipelineSample.hip
  4. In the bottom-right corner display settings, enable: Optimize > Remove Backfaces to display outlines: image-20240813000759820
Transfer Normals and Export Models 
tip

If you are new to Houdini, there are some tutorials that can help you get started quickly.

  1. Modify the File path in the Fbx Character Import node to import the model:image-20240813233236930
  2. (Optional) Enter the texture path in the mooa_setMaterials node, then double-click Load Textures to load the materials:image-20240813233325020
  3. Select the Group that needs to transfer normals in the mooa_normalTransfer node:image-20240813233541282
  4. Enable normal display, then press the D key to open Display Options, adjust Scale Normal to a suitable size:image-20240813233933009
  5. Select the transform1 node and set it as a Template, then press Enter to adjust the position and scale of the sphere in real-time and observe the changes in normals:image-20240813234211533
  6. Use the slider in the bottom left corner to adjust the lighting angle in real-time:image-20240813234819509
  7. Temporarily disable irrelevant nodes:image-20240813235054402
  8. Export the model using the OUTPUT_FBX or OUTPUT_OBJ node (Houdini Apprentice version only supports exporting OBJ format, cannot include vertex data other than normal):image-20240813235212726
Import the Model Into UE 

Import the model just exported into UE. To ensure the baked data is not corrupted, the following settings must be manually adjusted:

  • Disable Recompute Normals/Tangents
  • Enable Use High Precision Tangent Basis/Full Precision UVs

Set up materials for it and place it in the scene to check the effect:

The shadow shape of the model on the right side is much cleaner now.

- Blender Normal Transfer

image-20240804214407083

@aVersionOfReality introduces how to programmatically generate clean normals in Blender in this video, and how to use normal transfer in this video.

If you are more familiar with Blender, this method is lower cost and free.

- Manually Draw Normal Maps

見出し画像

Sometimes directly drawing normal maps can be easier than modifying vertex normals, and allows pixel-by-pixel control of normals.

The downside is limited by the resolution and compression accuracy of normal maps, flaws may appear at close distances.

@SFNA explains how to preview and paint normal maps in Substance 3D Painter in this article.

- Manually Edit Vertex Normals 

Manually editing vertex normals on high-polygon models can provide the highest precision results at any viewing distance, but the cost is that there are no smooth transitions between shadow shapes, and the artistic cost is very high, requiring a long time of experience accumulation to flexibly apply this technique.

Arc System Works used this technique in Guilty Gear:

image-20240805210543582image-20240805210559091
Original normalsCorresponding shadows
image-20240805210713480image-20240805210729703
Manually edited normalsCorresponding shadows, much cleaner

Modify Shadow Gradient

Arc System Works also used vertex colors to indirectly control shadow shapes in Guilty Gear:

image-20240805211352356image-20240805211404295image-20240805211412949
Vertex color channel, similar to Ambient Occlusion. 
Shadows are more likely to appear in darker areas
Original shadowsShadows after adjustments, notice shadows are more likely to appear between pants and muscles
image-20240805211700600image-20240805211715701image-20240805211724208
ILM texture G channel, 
Shadows are more likely to appear in darker areas
Original shadowsShadows after adjustments, notice shadows are more likely to appear under the skirt

In MooaToon, you can achieve the same effect by adjusting the Shadow Gradient.

Shadow Gradient basically refers to the angle between the normal direction and the light direction:

image-20240806003947179image-20240806004000030
Rendering resultCorresponding Shadow Gradient,
Can be understood as the angle between the normal direction and the light direction

MooaToon's shader uses Shadow Gradient as UV sampling for Diffuse Color Ramp (which will be detailed in the following article), calculating the final shadow range and color based on the Ramp.

You can modify the shadow shape in the material in two different ways by adjusting the Shadow Gradient:

Normal rendering result of a cylinderimage-20240806010123259
Toon rendering result of a cylinderimage-20240806010229814
Sampling result of Noise textureimage-20240806010318153
Use Noise as AO (Ambient Occlusion):
- The smaller the Noise value, the stronger the shadow intensity;
- Does not change the position of light-shadow boundaries;
- Can produce soft shadows;
image-20240806010402021
Use Noise as Diffuse Ramp Offset:
- The closer the Noise value is to 1, the easier it is to enter lights;
- The closer the Noise value is to 0, the easier it is to enter shadows;
- Changes the position of light-shadow boundaries;
- The softness of shadows depends on the RGB channels of the Diffuse Ramp;
image-20240806010826689

As shown in the figure, precise control of shadow shapes can be achieved through AO and Diffuse Ramp Offset.

In Toon materials, you can select specific channels as AO and Diffuse Ramp Offset in the Global Mask Map:

image-20240806213209007

The following tutorial demonstrates how to directly paint Mask Maps on models using Substance 3D Painter:

tip

Path to the example file: MooaToon\MooaToon-Project\Art\Models\NewTextures\ShadowMap.spp

You can also create textures in other DCC software, such as Blender or C4D.

Draw Mask Maps

Now you can draw a Shadow Mask to add AO to characters, such as under the neck.

First, import the model into Substance 3D Painter according to this tutorial.

Then draw AO in the intrinsic color channel with white as the background:

image-20240806222344526

After painting, export the textures according to this tutorial, then import the textures into UE and disable sRGB:

image-20240806222810608

tip

All non-color textures must disable sRGB, otherwise the correct values cannot be sampled.

Then set the texture as Global Mask Map, now there is AO near the neck.

image-20240806223649243

Distance Field Facial Shadow 

Distance Field Facial Shadow refers to directly drawing the shape of facial shadows in a specific direction as a texture, then merging multiple textures into a Distance Field texture, allowing for fully customizable facial shadow shapes at various lighting angles.

First, bake the Face Forward Direction:

- Baking Face Direction in UE

  1. Save all changes
  2. Right-click on the Skeletal Mesh: Scripted Asset Actions > Mooa Toon > Bake Face Forward Direction
caution

UE may crash when baking certain specific models, please save all changes in advance!
If a crash occurs, try baking immediately after restarting UE.

- Baking Face Direction in Houdini

Bake using the mooa_bakeFaceForwardDirToUV23 node.

Check Baked Data

  1. Check Enable Feature Distance Field Facial Shadow on the face material
  2. If the baked data is correct, you can see the face's World Tangent displayed as a solid color in the Debug View:
  3. You can also use BP_MooaLookDevTool to check the baked data after correctly setting up the Outline Material. The colors represent directions, for example, the +X direction is represented as (255, 128, 128), and the -X direction is represented as (0, 128, 128):

Generate Distance Field Texture

Next, you need to generate a Distance Field texture. Please refer to this open-source project. The steps are as follows:

  1. Place the drawn Shadow Mask into the MooaToon-Project\Art\DistanceFieldFacialShadowSamples\InputShadowMasks directory:
  2. Return to the parent directory, drag the InputShadowMasks folder onto gen.bat:
  1. The result can be seen in the output directory:
  2. Import the SDF map into UE, set the compression format to Half Float (R16F), and set Mip Gen to No Mipmaps:
  3. Set the SDF texture to Distance Field Shadow Map in the face material, then rotate the light to see the result:
  1. Supports multi-light interaction:

Migrate Lighting from Base Color to Mask Map

Some old workflows directly paint lighting changes into the base color map, which is not conducive to clean visuals and is not suitable for dynamic shadows and global illumination. This article explains how to repaint it into a clean texture:

image-20230408181355855

In MooaToon, you can use Mask Map to split the static lighting in the left image into dynamic Base Color + Shadow Color + Specular Color.