Cartoon rendering lighting model under PBR lighting system

date
May 29, 2023
slug
post2
status
Published
tags
Graphics
summary
Cartoon rendering is a completely different thing. Please do not think about it in terms of PBR!!!
type
Post
Cartoon rendering lighting model under PBR lighting system
Recently I have been working on a cartoon rendering for a UE4 game. The scene is more realistic and I have encountered some problems that I plan to record here.

Multiple lighting models

Single light source:
Where the , determined by two parameters to determine the softness and hardness of the lighting transition.
If sampling a Ramp map, replace the binarization coefficient with the sampling result of the Ramp.
The need to divide by PI is an empirical conclusion. If not divided, the bright part will appear too bright. This is because only a small area of a normal object can produce full brightness, while the entire front of the binarized lighting is at maximum brightness, which will appear too bright in terms of perception.
The additional highlight part refers to edge light, GGX highlight and some forcibly specified highlights. It is generally multiplied by LightColor to determine the basic brightness. This part has a small area and does not have a large impact on the overall brightness. It feels reasonable when compared with non-highlight parts. As long as single-layer superposition is reasonable, multi-layer superposition results are also reasonable.
In the case of multiple light sources, simply add all lighting results.
Where ambient light and baked light are treated as a separate light source in the same direction as the main light source, obtaining R0 from the lighting probe (the specific method is to set the input normal to (0,0,0) when obtaining lighting probe data), and then multiply PI * PI as LightColor in the above formula. Use sky light direction or a specified direction as L and perform a complete calculation (including highlights etc.)
In actual environments, there are generally only two types of lighting: one is outdoor during the day where objects are illuminated by sky light and ambient light half and half; one is indoor and night where objects are basically only affected by ambient light.
But in these two environments, the results of cartoon rendering should be similar, so objects must have normal intensity changes in dark and light even in environments where ambient light is dominant. Therefore, ambient light can only be treated as an ordinary linear light.
Multiplying PI twice is also an empirical conclusion. In the end it can make objects have reasonable brightness in most actual environments without being too bright or too dark.
However, obviously because the above formula will also illuminate the back of an object (just multiplied by dark color but dark color will not be very dark), this approach will still produce overexposure under multiple high-brightness dynamic lighting conditions such as placing a point light source in front of and behind a character. Therefore, parameters need to be added to the light source to ignore dark parts when calculating cartoon lighting for these additional light sources and lower overall brightness.
But usually there are not many dynamic lights and most are temporary special effects lights so it doesn't matter even if it's not processed.
But whether it's UE or Unity it's not too difficult to add parameters to a light source. And as long as there are parameters on the light source it's easy to handle compatibility issues with materials in different environments. Many parameters such as binarization blur can be placed on the light source to distinguish different functional lights. The main light source can have clear edges while auxiliary point lights can be blurred.
Adding parameters to a light source still makes sense but only solves basic brightness problems in different environments and generally does not need to be adjusted.
Note that all calculations above are for radiance of physical lighting. If your game is LDR this may not necessarily be correct.

Separation of internal and external shadows

Each light source has shadow occlusion. If an object is under ShadowMap's shadow all lighting must be completely removed otherwise it would be completely unreasonable for an object indoors to be affected by external light sources. But self-shadowing (such as arm hair casting shadows on body) needs to blend with object's own dark parts to avoid messy lines. Directly removing lighting can easily appear too dark so self-shadowing and external shadowing must be treated differently using completely different methods.
Self-shadowing requires creating a Pre-Object ShadowMap based on an atlas which also solves precision problems while external uses ordinary CSM. Since their functions are completely different they can be calculated separately and superimposed.
But CSM will still take effect on self-shadowing producing double shadow calculations so CSM's self-shadowing part must be shielded. Adjusting bias will always have problems under certain conditions so I directly draw Mask into Shadowmap then filter shadows according to Mask.
Mask can actually be directly marked with Stencil of ShadowMap without additional cost. But Resolve Stencil requires a certain API version and eventually a normal color channel is needed as a fallback.
This problem is not simple and most games now choose to avoid it. Either unable to normally cast external CSM onto characters or causing external CSM to affect characters unable to achieve correct brightness unable to seamlessly switch between indoors and outdoors.
Or... only use normal CSM and normally remove lighting calculations resulting in a dead black self-shadowing of characters.
The most reliable thing inside is to completely shield self-shadowing.
But why not it's not unsolvable.
I also implemented a separate PASS to draw object depth/stencil to RT then used offset sampling to do fake shadows or called Mesh Shadows. Because there is a way to mark objects it can also be easily used to do semi-transparent eyes.
It can better handle shadows that ShadowMap cannot generate that do not conform to physics. And its algorithm is actually a simplified material version of contact shadow so it can also be used as a supplement for some position precision.
SSAO needs to be shielded only leaving the outside. UE directly judges ShadeModeId.
Can SSAO be used internally to assist in processing the boundary between light and dark? ...It should be possible but normal AO drawn on the map can handle most situations (and Mesh Shadow can be used) adding this dynamic part adds unstable factors...
Maybe it's useful but I shielded it anyway.

Lighting direction correction

In fact the source of this problem is "dead dark on the back" and "yin-yang face" and these two things have always existed in PBR.
Lighting only has brightness changes on the front and of course it will only have a "flat" inherent color when turned to the back. Now that there is global lighting the back also has a rough lighting effect but still lacks some characteristics (such as self-shadowing SSS) and still causes the back not as good-looking as the front. So even now in 2023 during cutscenes and character focus shots fill light is still given to characters for better looks.
If there is no global lighting there is no need to say more you can only keep fill light on for a slightly better result for characters.
But cartoon rendering under binarized lighting cannot simply fill light and binarization will also magnify the unsightly parts of lighting.
In order for characters to look good lighting angles must be limited as much as possible using front light. But even with front light the elevation angle also has a big difference. Generally 45 degrees looks better but 45 degrees will create yin-yang face on the face. And forcibly using front light will also allow players to find that character lighting lacks changes when the lens rotates. Good dynamic lighting becomes dead lighting and the same front and back is a small matter.
My solution first allows customization of the lighting elevation angle for each part. Generally users will not care too much about whether the elevation angle of lighting is reasonable or synchronized with daylight direction.
Secondly give lighting a horizontal deflection angle expanding its proportion of being in the visual front. Even if the lighting is on the front and back you can still see enough proportion of illuminated parts and quickly turn to the other side at a certain angle.
Another common solution is to make the lighting biased towards the top so that at least the top part is always illuminated. But doing so can easily cause some angled objects (such as skirts) to always be bright so manual adjustment is required. But since you fixed the elevation angle you can see all possible lighting results by rotating around so it's relatively easy to handle.
The above are all directions for determining the basic lighting of characters' main light sources. Auxiliary light sources that emphasize directionality may need to remove elevation angle restrictions (light appearing on top cannot always be horizontal) but horizontal adjustments can still be retained. In any case all this needs to be distinguished by setting parameters on light sources.
In addition as mentioned above what players cannot accept is not "front and back lighting always the same" but "when perspective and lighting change character light and shadow does not change" so like War Twins always ensuring that lighting shoots out from camera but giving delay when changing allowing players to see a process of changing lighting although completely "physically wrong" it is also an acceptable design. But I haven't used this plan yet let's talk about it when my current plan really doesn't work because when shaking the lens wildly flaws are too obvious. It's just a matter of adding scripts if you want to add them.
Another common solution is edge light. This edge light is not some kind of Fresnel effect but an automatic backlight for the back. Generally speaking single-sided edge light following lighting changes will look better. If you want both sides you can hit another light source (my edge light is bound with light source and its generation direction is related to lighting direction so different edge light colors can be hit on both sides).
Edge light requires a relatively fixed coverage area. I have tried 100% fixed angle edge light but it feels very unnatural in actual use. Edge light with coverage that varies with perspective looks more natural even if the coverage area becomes smaller at some angles.
Because it is actually backlight so reasonable edge light should cast shadows to avoid light leakage... but generally not willing to pay this cost (it can actually run after all it is not point light source projection just another low-precision Pre-Object projection) and a certain degree of light leakage may look better and no one cares if it is physically correct.
Edge light has a new technology which uses depth contrast to generate edge light with fixed width at the edge which can produce very thin and persistent edge light even for block objects. But if the entire model has no thickness changes this kind of edge light is still not very good and will lose the feeling of backlight but can be drawn like stroke thickness with texture.
But we still have to remember that edge light itself is still a simulation of backlight not just a means of outlining edges. If it is too bright and too thick but there is no backlight around it it will not work. For example if your character is in a dark scene but the whole person is wrapped in a big white edge it will definitely not work. And if it's a daytime scene adding this is nothing wrong after all you can't tell if there's light or no light behind it. But if the daytime environment is basically white and you wrap people in a purple backlight it still won't work. So edge light should be an attribute of a light source not a material. What the material needs to do is only handle the differences between different parts under the same light source.
Self-shadowing also needs to control direction. Since Pre-Object shadowing is used above this is easy to implement just temporarily modify the lighting direction during generation.

Dealing with color cast

All HDR cartoon rendering games will encounter this problem: saturation decreases after ToneMaping. Worse texture contrast also decreases causing the image to lose a lot of detail even the mouth cannot be seen.
Usually can only increase saturation and contrast in reverse on the texture but very unintuitive and severe loss of precision. Saturation can be added back later but contrast has no way.
I used my own trick: inverse operation of fitting ACES formula.
This is a simplified formula for ACES only guaranteeing basic brightness. I used Excel to fit its inverse operation with the following result:
Not accurate but almost there. Then use it to process the incoming inherent color map and choose an appropriate mixing ratio by lerp with the original map color to restore almost the same result as the original map on the final display.
Its disadvantage is that under the same parameters in dark places contrast will appear somewhat too high and perfect adjustment still needs to adjust lerp ratio according to lighting intensity (note that lighting intensity rather than final radiance because we want to ensure texture content contrast after multiplying texture original contrast cannot be known)
If you can avoid color cast problems then you can directly use original painting results when drawing textures. Unlike PBR cartoon rendering is an extremely dependent on original painting ability subject you do not have a fixed material library available nor any predetermined parameters determining whether the result is beautiful or not depends on texture quality and color cast is fatal.
And the phenomenon of high contrast in dark parts also proves that this problem cannot be solved by simply changing texture colors.
And materials that look good under ACES require very high contrast and are very ugly and generally difficult for artists to directly draw or select colors that meet requirements everyone uses experience values of palette for color selection actual operation cannot meet ACES's color cast requirements at all.
So this may be the most valuable thing in this article.
Of course a smarter approach would be not to use ACES at all or even ToneMaping. A cartoon rendering game with fixed brightness and no indoor/outdoor switching does not need ToneMaping at all everything can be painted as it is after all physical lighting rules are meaningless for it.
Strictly speaking even linear space is not needed. In cartoon rendering actually gamma space lighting results are more beautiful otherwise PS would not use gamma as layer blending method.
But if you still want to use PBR methods to save artist workload and hope to use PBR's "good things" you need to keep ToneMaping and correct physical lighting model. The current correction color scheme is a compromise.

Custom Bloom

This is basically something that every cartoon rendering game will do but this time I separately processed the front and back Bloom of the object which can make the bright part produce Bloom effect alone.
From a "physically correct" perspective this is actually necessary. Because the strength of Bloom actually represents the strength of light received but the intensity of cartoon rendering lighting is not fully expressed through color. In order to maintain the saturation of the picture the actual brightness of the bright part is not too high and the brightness of the dark part often cannot be too dark.
Therefore separating Bloom from color is more "physically correct".
Cartoon rendering also particularly likes to give hair and skin higher Bloom intensity making them look more glossy.
And in order to maintain the saturation of glowing objects actual color values cannot be too high so high Bloom values need to be used to make up for the original floodlight.
I also thought about whether it is possible to directly separate actual brightness and color under lighting system and treat brightness as a fourth color component besides RGB then use "brightness" value to directly calculate Bloom which is more convenient when processing Additive objects (now I directly shielded Additive object's Bloom value writing).
But there are many things to change all parts involving lighting need to be changed and this requires Bloom value to be an HDR value... so I haven't moved for the time being.
If you really want to do it seriously that might be the perfect solution.

Epilogue

There are still many things to say but many have been said by others or I have already said them myself.
This article mainly deals with PBR lighting.
So that's it.
Cartoon rendering is a completely different thing. If you still think about problems with PBR thinking it's basically a dead end especially for those who only know how to recite books but don't understand why PBR does it. And most people are like this so you will mostly see many weird games born.
Basically card rendering is painting a dynamic painting. Original painting ability comes first. What technology needs to do is to naturally present original painting results in 3D world. It can be considered that all "physics" are meaningless especially those related to color.
But in actual operation it is inevitable that PBR methods need to be used to reduce costs... I can only say that it must be clear which one is primary.
The first nature of card rendering is always the picture that original painting thinks in mind. Even if what original painting wants we can never do it but that does not prevent us from moving in that direction. In fact PBR's rendering part can also be regarded as a low-end fitting towards NPR results. The target is ambiguous and unclear and doing things with PBR's "rules" will always result in four different things neither side will please.
And this is currently difficult to avoid.
(Don't think I'm shocking I've heard things like "original paintings also want to paint as realistically as possible but they can't paint like they are now." Don't overestimate people now.)

© Yuay 2022 - 2023 Next.js & Notion