RenderTexture实现实时阴影绘制

这篇学习总结主要是在今天学习了姜雪伟实现的实时阴影的方式做一个整理。
原课程地址: http://edu.csdn.net/course/detail/607/7961?auto_start=1
一般实时阴影主要还在出现在角色、怪物的脚底为了然场景表现的更加逼真,实现起来通常有三种方式:脚底放个阴影图片跟着主角动,通过摄像机的RenderRexture绘制显示,直接使用Unity的Projector组件。
很不幸的是在我们的游戏中直截了当的放了一坨灰背景,实现的效果虽然少了几分逼真性,但如果是2D场景的话也足够用了。
但是如果想要在3D场景绘制脚底阴影,直接放图有点粗暴。本文里的RenderTexture方式实现较为简单效果也会很逼真。
基本思路其实就是多用了一个摄像机,将照相机把你需要照到的主角的内容呈现到一张单独的面片上,这个面片就摆在人较低作为它的阴影。看起来像简单版的一个小地图:只有主角的小地图。
场景中所需要的对象如图,对于map节点显示RenderTexteure的地方只要空的材质球就行了,要呈现摄像机照射的内容。直接用Plane对象或Quad对象都可以的。
RenderTexture实现实时阴影绘制_第1张图片
此外,为了让阴影真实点,显示阴影的面片一般是灰色透明的,我们还要单独设置下,不然默认摄像机照出来的角色就是我们真实看到的世界:

RenderTexture实现实时阴影绘制_第2张图片

紧接着还需要一个脚本告诉摄像机把内容写到我们的map面片上。
在场景中的display节点身上绑定脚本ShadowScript:


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;
    }
}

很简单吧?跑起来直接就可以看到实时的阴影效果了!!
自己给小骨模型做了一个御剑的动画!!然而一时找不到好看的剑模型,我只好找了张jpg的剑扣一个出来,也是大费周折,不过可以看出来阴影效果比较好,因为阴影作为一个独立的GameObject直接少了很多调层级的麻烦,现在是只显示主角阴影的效果。
RenderTexture实现实时阴影绘制_第3张图片
但是当我把剑贴图所在的面片layer调整的也和主角模型一样的时候,发现居然还是看不到剑的阴影。
这个时候还对专门针对map(显示阴影的面片)材质写一个Shader,就不能用默认的Transparent/Diffuse了,并且最终剑这种透明贴图的还需要使用Unlit/Transparent,新添加的Shader详细代码如下:

///作为带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"
}

修改之后靓丽的运行效果:
RenderTexture实现实时阴影绘制_第4张图片

具体资源地址可以到我的github下载哦,package可以直接导入一个空工程使用。
点击到我的github

你可能感兴趣的:(unity,阴影,渲染)