Chapter VIII of the more complex lighting (6)

@

Unified management of attenuation of light and shadow

In the foregoing, we already know how to calculate the attenuation of the light path prior to the rendering of UnityShader - in Base Pass, the parallel light attenuation factor is always equal to 1, and in the Additional Pass, we need to determine the source process Pass type, and then the built-in macro variables used to calculate the attenuation factor. In fact, is essentially the same attenuation effects of light and shadow on the final result of rendering objects - we are the light attenuation factor of light and shadow values and the result obtained by multiplying the final rendering results. So is there a way to calculate two messages at the same time it? The good news is, Unity provides such features Shader years, primarily achieved through built-in macro UNITY_LIGHT_ATTENUATION.
The key code is as follows:
(1) comprising a first header into the desired file.

//Need these files to get built-in macros
#include "Lighting.cginc"
#include "Autolight.cginc"

(2) using the built-in macro statement shadow SHADOW_COORDS coordinates v2f structural body:

struct v2f{
float4 pos:SV_POSITION
float3 worldNormal:TEXCOORD0
float3 worldPos:TEXCOORD1
SHADOW_COORDS(2)
};

(3) using the built-in macro TRANSFER_SHADOW fragment shader is calculated and transmitted shadow vertex shader coordinates:

v2f vert(a2v v){
v2f o;
...
TRANSFER_SHADOW(o);
return o;
}

(4) and the previous different ways, we compute the attenuation of light and shadows using the built-in macro UNITY_LIGHT_ATTENUATION fragment shader

fixed4 frag(v2f i):SV_Target
...
//UNITY_LIGHT_ATTENUATION not only compute attenuation,but also shadow infos
return fixed4(ambient+(diffuse+specular)*atten,1.0);

UNITY_LIGHT_ATTENUATION Unity is built used to calculate the attenuation of light and shadow macro, we can find them relevant statements in the built-in AutoLight.cginc. It accepts three parameters, it will store the result of light attenuation and shadow multiplied value to the first parameter. Note that we did not declare the first parameter atten in the code, because UNITY_LIGHT_ATTENUATION will help us to declare this variable. Its second argument is a structure v2f, this parameter is passed to SHADOW_ATTENUATION, used to calculate the shadow value. And the third argument is the world space coordinates, as we speak in front of that, the parameter for calculating coordinates of source space, then the attenuation of the light attenuation of light texture sample obtained. We strongly recommend checking AutoLight.cginc in UNITY_LIGHT_ATTENUATION statements, readers can find, Unity for different types of light sources, such as whether to enable different situations cookie declared multiple versions of UNITY_LIGHT_ATTENUATION. These different versions of the declaration is to ensure that we can get the right result by such a simple code key.
(5) Since we are using UNITY_LIGHT_ATTENUATION, and our Base Pass Additional Pass code to unity - we do not need a separate process in the shadow Base Pass, the light source does not need to determine the type Additional Pass processed light attenuation, everything It can only be done by UNITY_LIGHT_ATTENUATION. This is built Unity charm file. If we hope to add a shadow effect Additional Pass, you need to use compiler directives #pragma multi_compile_fwdadd_fullshadows instead of #pragma multi_compile_fwdadd directive Additional Pass in. Thus, these shadow Unity also calculate additional source pixel by pixel, and passed to Shader.

Transparent object of shadow

We emphasize from the outset, he wanted to make objects cast shadows in Unity to other objects, be sure to provide a LightMode to ShadowCaster's Pass in Unity Shader its use. In the previous example, we use the built-in VertexLit ShadowCaster provided to cast shadows. VertexLit ShadowCaster very simple to achieve in that it would normally render the entire object, then outputs the result to a depth of the depth map or the shadow map texture. You can find the relevant files in the built-in file.
For most opaque objects, the Fallback to the VertexLit can get the right shade. But for transparent objects, we need to carefully deal with its shadow. Transparent object implementations typically use to test the transparency or alpha blending, we have to be careful to set Fallback these objects.
Process transparency test is relatively simple, but if we still used directly VertexLit, Diffuse, Specular, etc. as callback, are often unable to get the right shade. This is because the need to discard some of the transparency of the test fragments in fragment shader, and the shadow cast VertexLit texture and not to conduct such operations.
(1) First, include the header file into the needs of:

#include ''Lighting.cginc''
#include "AutoLight.cginc"

(2) using the built-in macro SHADOW_COORDS statement shadow texture coordinates v2f in:

struct v2f{
float4 pos:SV_POSITION;
float3 worldNormal:TEXCOORD0;
float3 worldPos:TEXCOORD1;
float2 uv:TEXCOORD2;
SHADOW_COORDS(3)
};

It noted that, because we have occupied three interpolation register (use TEXCOORD0, TEXCOORD1 and TEXCOORD2 modified variable), so SHADOW_COORDS incoming parameter is 3, which means shadow texture coordinates will occupy the fourth interpolation register TEXCOORD3.
(3) Then, using the vertex shader to the fragment shader passed the built-in macro TRANSFER_SHADOW shadow texture coordinates calculated:

v2f vert(a2v v){
v2f o;
...
//Pass shadow coordinates to pixel shade
TRANSFER_SHADOW(o);
return o;
}

(4) the fragment shader, a built-in macro UNITY_LIGHT_ATTENUATION computing shadows and light attenuation:

fixed4 frag(v2f i):SV_Target{
...
//UNITY_LIGHT_ATTENUATION not only compute attenuation,but also shadow infos
UNITY_LIGHT_ATTENUATION(atten,i,i.worldPos);
return fixed(ambient+diffuse*atten,1.0);
}

(5) This time, we change its Fallback, VertexLit use it as a callback Shader:

Fallback"VertexLit"

We can get an effect similar to the following:
Here Insert Picture Description
Attentive readers may find hollow areas there has been an abnormal shadow, cube looks like this is the same as an ordinary cube. And this is not what we want, we want to have some light should be able to pass through these hollow areas, and these areas should not have shadows. This occurs because, we are using the built-in VertexLit ShadowCaster provided to cast shadows, and this without any transparency Pass the test calculations, and therefore, it will render the entire object depth information to the depth map and shadow map texture. So, if we want to get the shadow effect after a transparency test, you need to provide a transparency test function ShadowCaster Pass. Of course, we can write such a self-Pass, but here we still choose to use the built-in UnityShader to reduce the amount of code.
In order to use object transparency test to get the right shadow effects, we only need to change one line of code in Unity Shader, that the Fallback is set to Transparent / Cutout / VertexLit. You can find the file in the built-in code Unity Shader, it ShadowCaster Pass transparency test were also calculated, and therefore the depth information of the object will write cutting depth map texture mapping and shading. But note that, due Transparent / Cutout / VertexLit calculated transparency test, using a property named _Cutoff to carry out transparency test, therefore, it requires Shader we must also provide a property named _Cutoff. Otherwise, the same can not get the right shadow effects.
After changing Fallback, we can get results in the following figure:
Here Insert Picture Description
However, this result still some problems, such as some of the few should not transmit light. The reason for this is that, by default, the object is rendered to the depth map and shadow map texture consider only positive object. But for this embodiment cube, since some of the surface facing away from the light source completely, so there is no depth information is added to the surface texture mapping in the shadow calculation. In order to obtain correct results, we can Cast Shadows property Mesh Renderer cube assembly is in Two Sided, Unity force calculating depth information on all surfaces in the calculation of the shadow map texture. The following figure shows the result of rendering is set correctly.
Here Insert Picture Description
Compared with object transparency test, you want to add a shadow using alpha blending objects is a more complicated matter. In fact, all the built-in transparency mixed Unity Shader, such as Transparent / VertexLit the like, containing no shadow casting Pass. This means that these objects will not participate in the depth calculation translucent FIGS shadow mapping and texture, that is, they do not cast shadows to other objects, and as such they will not receive shadows from other objects. We use the transparency + learning before mixing method to render the shadow of a cube, calculated on adding shadows, and it's Fallback is a built-in Transparent / VertexLit, the figure below shows the results of rendering:
Here Insert Picture Description
Unity this treatment would be translucent object has its reasons. Transparency needs to close due to mixing depth is written, the resulting problems also affect the generation of shadows. Generally speaking, in order to produce these transparent translucent object right shadow, still need to be rendered in strict accordance with the order from the back of each light source in space, it makes the shadow processing becomes very complicated and can affect performance . Thus, in the Unity, all translucent Shader is built without any shadow effect. Of course, we can use some dirty trick to force the generation of the shadow of the object is translucent, this may be accomplished by setting their Fallback VertexLit, Diffuse these UnityShader opaque object used, such Unity will find a shadow projected on its Fallback Pass then we can control whether to cast or receive shadows from other objects by Cast shadows and Receive shadows option on the Mesh Render components of the object. The following figure shows the rendering VertexLit Fallback to open and shadows cast shadows and reception of the translucent objects.
Here Insert Picture Description
As can be seen, when the shadow is projected onto a plane on the right side on the translucent cube, but it will not penetrate the shadow cube projected onto a plane below, this is actually not correct. Meanwhile, the cube can be projected onto their shadows below the plane.

Guess you like

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