Chapter VIII of the more complex lighting (4)

@

Unity shadow

In order to make the scene look more realistic, with depth information, we usually want to put some light can cast shadows of objects on other objects. In this section, we'll learn how to make an object in Unity cast shadows to other objects, and how to make an object receive shadows from other objects.

1. How shadows are generated

We can first consider how the real-life shadow produced. When a light source emits a light encounters an opaque object, it can not continue rays illuminate other objects (the emitted light is not considered here). Thus the object will cast shadows to other objects, those which produce a shaded area because the light does not reach these areas.
In real-time rendering, we most often use a technique called Shadow Map of. This technique is very simple to understand, it will first be placed in the position of the camera coincides with the light source position, then the shaded area of the light source in the scene are those cameras out of sight, and Unity is the use of such technology.
Rendering the forward path, if the scene of the most important open parallel light shadow, shadow Unity will calculate its map texture (ShadowMap) for the light source. This texture is mapped on the nature of the shadow is a depth map, which records the starting position from the light source, the scene can be seen in its distance from the nearest surface of the position (depth information).
So, in the calculation of the shadow map texture, how do we determine its distance from the nearest surface location of it? A process is placed on the camera and the light source position, and then the normal rendering process, i.e. calls Base Pass Additional Pass and update the depth information, a shadow map texture. But this method will cause some performance wasted, because in fact we only need depth information, but rather the Base Pass and Additional Pass often involves many complicated lighting model calculations. Unity therefore chose to use a special extra Pass to update the shadow map texture source, this is LightMode Pass Pass tag is set to the Shadowcaster. Pass this goal is not to render the frame buffer, but the shadow map texture (texture or depth). Unity camera is first placed on the light source position, and then call the Pass, obtained by the spatial position of the light source after the vertex transformation, and outputs the depth information accordingly to the shadow map texture. Therefore, when the shadows of the light source is turned on, the underlying rendering engine renders the first object found in the current UnityShader LightMode as ShadowCaster's Pass, if not, it will continue to look at Fallback specified Unity Shader, if still not found , can not cast shadows on the object to other objects (but it can still receive the shadow of other objects). When it finds a LightMode ShadowCaster after the Pass, Unity will be used to update the shadow map texture Pass source.
In the shadow of traditional texture mapping, we can transform the vertex position of the normal rendering Pass to the next light source in the space, to give it dimensional position information in the source space. We then use the xy component of the shadow map texture sampling the texture map to obtain depth information in the shading position. If the value is less than the depth value of the depth of the vertex (typically obtained from the z-component), it indicates that the point is in a shadow. However, in the Unity5, Unity uses a different sampling techniques such conventional shadow, the shadow mapping technique i.e. the screen space (Screenspace Shadow Map). Shadow mapping screen space originally intended to cast a shadow of delayed rendering. It should be noted that not all platforms Unity will use this technology. This is because the shadow map screen space required graphics support MRT, and some mobile platform does not support this feature.
When the shadow mapping technique using screen space, Unity will first of Pass ShadowCaster to obtain light shadows cast shadows of texture mapping a texture camera and a depth by calling LightMode. Then, texture mapping and shading a texture depth camera to obtain a light shadow map screen space. If the surface is a depth camera in FIG converted to the shadow record is greater than the depth of the texture mapping values, it shows that although the visible surface, but in the shadow of the light source. In this way, shadow map contains all regions of the hatched screen space. If we want an object receive shadows from other objects, just to sample the shadow maps in the Shader. Since the shadow map is a screen space, we need to first surface coordinate transformation from model space to screen space, and then use this coordinate to be sampled shadow FIG.
To summarize, a shadow object received from other objects, and it is a shadow of the object projected onto the other two processes.
● If we want a shadow object received from other objects, it is necessary to sample the shadow map texture (including screen space of the shadow map) in Shader, the sampling results and the final result of the multiplication to produce a light shadow effect.
● If we want to cast shadows of an object to another object, the object must be added to the calculation of the shadow mapping textures light source, so that when the shadow of other objects the texture mapping samples may get information of the object. In Unity, this is achieved by a process for the object is performed LightMode ShadowCaster the Pass. If you use the screen space projection mapping techniques, Unity will use the Pass to generate a camera depth texture. In the following sections, we will learn how to implement the above two processes in Unity.

2. The shadow of an opaque object

To make the scene can cast a shadow, we first need to make parallel light shading information can be collected. This requires in turn hatched in Light source assembly, as shown in FIG. In this example, we chose soft shadows (Soft Shadows).
Here Insert Picture Description

2.1 allow objects to cast shadows

In Unity, we can choose whether to allow a body cast or receive shadows. This is done by setting Cast Shadows and Receive Shadows Mesh Renderer assembly properties achieved. As shown below:
Here Insert Picture Description
Cast Shadows may be set to ON (On) or off (Off). If the attribute is turned on Cast Shadows, Unity will then calculate the shadow of the object light source is added to the texture map, so that when the shadow of other objects in the texture mapping samples may give information about the object. As said before, this is achieved by the process for performing LightMode object of the ShadowCaster Pass. Receive Shadows you can choose whether to make an object receive shadows from other objects. If you do not open the Receive Shadows, then when we call Unity's built-in macro variables and calculate shadows (later we'll see how), these macros are not enabled by determining the function of receiving the shadow of the object, it does not count for us internally shadow.
We cube and Cast Shadows and Receive Shadows two planes are set to open state, the effect can be obtained in the following figure:
Here Insert Picture Description
it can be found from the chart, even though we did not make any changes to Chapter9-ForwardRendering cube used, but still can cube cast shadows below the plane. Some readers may be in doubt, not to say that before LightMode to Pass ShadowCaster Unity to use to render the shadow map texture and depth map it? But Chapter9-ForwardRendering and there is no such a Pass ah. Yes, we define only two Pass-- a Base Pass in Chapter-ForwardRendering of SubShader, a Additional Pass. Why it can cast shadows it? In fact, the secret lies in one of the Fallback semantics.

Fallback"Specular"

我们为Fallback指定了一个用于回调的Unity Shader,即内置的Specular。虽然Specular本身也没有包含这样一个Pass,但是由于它的Fallback调用了VertexLit,它会继续回调,并最终回调到内置的VertexLit。我们可以在Unity内置的着色器里找到它:builtin-shaders-xxx->DefaultResourcesExtra->NormalVertexLit.shader。打开它,我们可以看到传说中的LightMode为ShadowCaster的Pass了:

//Pass to render object as a shadow caster
Pass{
Name"ShadowCaster"
Tags{"LightMode"="ShadowCaster"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct v2f{
V2F_SHADOW_CASRER;
};
v2f vert(appdata_base v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
float4 frag(v2f i):SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}

上面的代码非常短,尽管有一些宏和指令是我们之前没有遇到的,但它们的用处实际上就是为了把深度信息写入渲染目标中。在Unity5中,这个Pass的渲染目标可以是光源的阴影映射纹理,或是摄像机的深度纹理。
如果我们把Fallback注释掉,就会发现正方体不会再向平面投射阴影了。当然,我们可以不依赖Fallback,而自行在SubShader中定义自己的LightMode为ShadowCaster的Pass。这种自定义的Pass可以让我们更加灵活的控制阴影的产生。但由于这个Pass的功能是可以在多个Unity Shader间通用的,因此直接Fallback是一个更加方便的用法。在之前的章节中,我们有时也在Fallback中使用内置的Diffuse,虽然Diffuse本身也没有包含这样的一个Pass,但是由于它的Fallback调用了VertexLit,因此Unity最终还是会找到一个LightMode为ShadowCaster的Pass,从而可以让物体产生阴影。在下小结中我们可以看到LightMode为ShadowCaster的Pass对产生阴影的重要性。
上图中还有一个有意思的现象,就是右侧的平面并没有向最下面的平面投射阴影,尽管它的Cast Shadows已经被开启了。
在默认情况下,我们在计算光源的阴影映射纹理时会剔除掉物体的背面,但对于内置平面来说,它只有一个面,因此在本例中计算阴影映射纹理时,由于右侧的平面在光源下没有任何正面(front face),因此就不会添加到阴影映射纹理中。我们可以将Cast Shadows设置为Two Sided来允许对物体的所有面都计算阴影信息。下图给出了当把右侧平面的Cast Shadows设置为Two Sided后的结果。
Here Insert Picture Description
In the present embodiment, the reason why the plane of the lowermost receiver shadows can be built because it uses Standard Shader, and this was related to the built-in operation of receiving Shader shadow. But because Chapter-9-ForwardRendering cube is not used for shading any treatment, so it does not show the right side of the plane to cast shadows in the next section we will learn how to make a cube also receive shadows.

Guess you like

Origin www.cnblogs.com/xiegaosen/p/12004785.html