Unity uses RenderTexture to achieve real-time shadow drawing

foreword

Generally, real-time shadows mainly appear on the soles of characters and monsters' feet. In order to make the scene more realistic, these three methods are mainly used for implementation : place a shadow image on the sole of the foot to follow the main character, draw and display it through the camera's RenderRexture, and use it directly. Unity's Projector component. In 2D scenes, for the sake of convenience, the game usually puts a quick gray background in a straightforward manner. Although the effect achieved is a little less realistic, it is still sufficient.

However, if you want to draw foot shadows in a 3D scene, it is not suitable to put the shadow map directly. In order to make the shadow effect more realistic, let me introduce the effect of real-time shadow drawing using RenderTexture.

The basic idea is actually to use an extra camera, and the camera will present the content of the protagonist you need to photograph on a separate patch, which is placed lower than the person as its shadow. Looks like a simple version of a minimap: a minimap with just the protagonist.

The objects required in the scene are shown in the figure. For the map node where the RenderTexteure is displayed, only an empty shader is required, and the content illuminated by the camera should be presented. You can use the Plane object or the Quad object directly.

In addition, in order to make the shadow real, the patch showing the shadow is generally gray and transparent, and we have to set it separately, otherwise the character shown by the default camera is the world we really see:

Next we need a script to tell the camera to write the content to our map patch.

Bind the script ShadowScript on the display node in the scene:

public class ShadowScript : MonoBehaviour {
public GameObject display; //角色形象
private GameObject ShadowCamera;
private GameObject map;
private RenderTexture mTex = null; //即为显示阴影的RenderTexutre
public int AntiAliasing = 4;
Transform child;
// Use this for initialization
void Start () {
child = this.transform.FindChild(“qiangu1”);
map = child.FindChild(“child/map”).gameObject;
ShadowCamera = child.FindChild(“child/camera”).gameObject;
if (!display)
display = this.transform.parent.gameObject;
mTex = new RenderTexture(2000, 2000, 0);
mTex.name = “Shadow” + GetInstanceID();
Camera mCamera = ShadowCamera.GetComponent<Camera>();
mCamera.cullingMask = GetLayerMask(display.gameObject.layer);
mCamera.targetTexture = mTex;
}
public LayerMask GetLayerMask(int layer)
{
LayerMask mask = 0;
mask |= 1 << layer;
return mask;
}
// Update is called once per frame
void Update ()
{
if(display!=null)
{
mTex.anisoLevel = AntiAliasing;
}
map.renderer.maternTexture = mTex;
}
}

Simple, right? You can see the real-time shadow effect directly when you run!

I made an animation of the sword for the small bone model! However, I couldn't find a good-looking sword model for a while, so I had to find a jpg sword buckle, which was a lot of trouble, but it can be seen that the shadow effect is better, because the shadow as an independent GameObject directly lacks a lot of adjustment levels. Trouble, now it only shows the effect of the shadow of the protagonist.

But when I adjusted the patch layer where the sword map is located to be the same as the protagonist model, I found that I still couldn't see the shadow of the sword.

At this time, I also wrote a Shader specifically for the map (patch that displays shadows) material, so the default Transparent/Diffuse cannot be used, and the final transparent texture of the sword needs to use Unlit/Transparent, the newly added Shader detailed code as follows:

///作为带Alpha通道的模型贴图的shader
Shader “MyShader/AlphaSkinShader”
{
Properties
{
_Color(“Main Color”,Color)=(1,1,1,1)
_MainTex (“Base (RGB)”, 2D) = “white” {}
_Cutoff(“Base Alpha cutoff”,Range(0,0.9))=0.2
}
SubShader
{
Tags { “Queue”=“Transparent” }
LOD 200
Lighting Off
ZWrite Off
Cull off
Blend SrcAlpha OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include “UnityCG.cginc”
struct appdata_t
{
float4 vertex:POSITION;
float4 color:COLOR;
float2 texcoord:TEXCOORD;
};
struct v2f
{
float4 vertex:SV_POSITION;
float4 color:COLOR;
float2 texcoord:TEXCOORD;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _Cutoff;
v2f vert(appdata_t v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
o.color=v.color;
o.texcoord=TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
float4 _Color;
half4 frag(v2f i):SV_Target
{
half4 col = tex2D(_MainTex,i.texcoord);
if(col.a<_Cutoff)
{
clip(col.a-_Cutoff);
}
else
{
col.rgb=col.rgb*float3(0,0,0);
col.rgb=col.rgb+_Color;
col.a=_Color.a;
}
return col;
}
ENDCG
}
}
FallBack “Diffuse”
}

Beautiful running effect after modification:

Guess you like

Origin blog.csdn.net/bycw666/article/details/123683522