📜 ⬆️ ⬇️

Shadows of the characters in the video The Blacksmith

One fine morning last fall, we learned the long-awaited news: the antagonist is ready!
It was just a rough model: no hair, skin and the appropriate setting of materials, but we were still very happy. Someone immediately suggested: “Let's quickly stick materials to it! I can't wait to see this guy on the screen! ”

So we did. But something went wrong ... "Stop, and we just set it up to get dynamic shadows?" That's right. But the result did not meet our expectations at all.



Problem
')
Having rummaged in the shader, we found the essence of the problem: half of the shadows were not displayed in principle, and the second half was not displayed correctly.



“What is the matter?” You ask. - “What about the new filtering algorithm in Unity 5, which makes the shadows softer and more realistic?”. But the fact is that in some scenes the camera was at a distance of up to 3000 meters, and we wanted the shadows to be displayed on each pixel within its field of view. Of course, we specifically set up cascade splits and offset parameters for high-quality display of shadows both directly in front of the camera and at a great distance.

The problem is that we didn’t foresee a close-up of the character in such a large-scale scene. Not only did we lack resolution for creating soft shadows, so the depth offset that we set up for the stage was so big that the character was left without shadows. It turns out that the soft shadow cast by a leather strap on the armor is very different from the soft shadow cast by a large cobblestone on the surface of the earth. Who would have thought!

So, we needed to find a solution to this problem. We could bring the first cascade as close as possible to the camera, but then we would have to sacrifice the general cascade for the whole shot. Such an option would be suitable only for scenes with a very close-up, which in principle was required.

Decision

Nevertheless, we decided to apply a more traditional technology: make separate shadow maps for the characters. Two hundred lines of code - and voila! Here's what we got:



At this stage, we already had enough data to apply almost any shadow filter. But there was not enough time for its fine tuning, so we decided to stop at a simple sampling, taking into account the distance, similar to the Nvidia PCSS shadow technology [1].

In addition, we have the opportunity to collect data from static objects that are outside the close-up and cast shadows on dynamic objects, that is, on characters. Static objects were projected onto the front plane of the rendering camera, which provided the maximum distance of the Blocker-to-Receiver in the soft shadow filtering scheme.

It remains only to integrate our solution into the overall pipeline rendering. Having a little puzzled over this issue, we found a very simple way of replacing the functions of shadows used in almost all standard Unity shaders. After several iterations, we simplified it to two lines of code:

#pragma multi_compile _ UNIQUE_SHADOW UNIQUE_SHADOW_LIGHT_COOKIE
#include "UniqueShadow_ShadowSample.cginc"


Please note that for this function to work correctly, the #include line must be written before any other #include lines in the code. If you plan to use this method for similar purposes, please note that the entire complexity of the replacement lies in the code hidden in the include file:

#if SOME_CONDITION_ENABLING_OUR_FEATURE
#include "AutoLight.cginc"
#undef SHADOW_COORDS
#undef TRANSFER_SHADOW
#undef SHADOW_ATTENUATION
#define SHADOW_COORDS(i) SOME_OTHER_COORD(i)
#define TRANSFER_SHADOW SOME_OTHER_TRANSFER
#define SHADOW_ATTENUATION(i) SOME_OTHER_ATTEN(i)
#endif


In this case, we have 2 conditions: whether support for unique shadows is enabled and whether a source of directional light is rendered. The second condition allows to combine this function with other light sources that cast shadows.

Result

So, have we managed to achieve satisfactory results? See for yourself! Here is the same render with unique shadows and without them:



Conclusion

Do not forget that additional shadow maps, like any other rendering functions, require additional resources. They take up more video memory, use more render calls when rendering, and also require more bandwidth and processing power for use in the shader.

For The Blacksmith video, we specifically added the ability to turn on and off unique shadows depending on how far away the characters are from the camera. Thus, the system load was increased only during the rendering of close-up shots. In games where the approach of the camera to the player is not foreseen in principle, this function can be added only for individual close-ups in splash screens.

To better demonstrate this feature, we have created a small demo project that can be downloaded from the Asset Store. Using the example from the movie scene, you can see how to maintain a high detail of a close-up of the character in a large open space. Despite the fact that the first cascade covers only 1% of total Shadow Distance, the difference is obvious: a model with unique shadows on the left looks much better than a model with cascading shadows on the right.



References

Source: https://habr.com/ru/post/272673/


All Articles