• 模仿王者荣耀的实时阴影


    概述

    该demo是模仿王者荣耀的实时阴影,读者可以从中理解到实时阴影的实现原理。

    详细

    一、准备工作

    解压ShadowDemo.zip压缩包,用Unity 5.3.7f1 (64-bit)及以上版本打开项目,打开Demo场景,就可以测试了。以下为压缩包的结构:

    QQ截图20171127135218.png

    二、实现原理

    原理:可能有点复杂,为了简单些,转化为2d视角来分析。阴影的产生正如下图所示

    20170227143031726.png

    由上图可知,阴影的a点与遮挡物的b点在光照方向的垂直面上其实映射的是同一个点d。这很容易让我们联想到MVP当中的投影变换。其实是一样的。我们将于光照方向当做照相机的视线,而与光照方向垂直的面,就是投影变换最后的盒子的正面。这意味着我们可以制作一个正交照相机,使得它与光照方向一致,再将地面模型的各个顶点投影到该照相机上,这时候照相机的纹理UV坐标范围是0~1,地面投影到了照相机,也将其坐标映射到0~1之间,由此与照相机的纹理一一对应,于是将照相机照出来的纹理叠加在地面上,就形成了阴影。

    三、程序实现

    using UnityEngine;
    using System.Collections;
    
    public class Shadow : MonoBehaviour {
        public Camera m_ShadowCamera;
        private RenderTexture m_RT;
        public Material m_Mat;
        
        void Start()
        {
        //创建一个纹理,用来捕获照相机的看到的(该纹理既为我们需要的影子的源纹理)
            m_RT = new RenderTexture(Screen.width, Screen.height, 0, RenderTextureFormat.ARGB32);
            m_RT.anisoLevel = 8;
            m_ShadowCamera.targetTexture = m_RT;
            //将上面的纹理传入材质球中,用来将它处理为影子
            m_Mat.SetTexture("_MainTex", m_RT);
        }
    
        void Update()
        {
        //实时将生成影子需要的纹理的照相机的矩阵传入材质球,这两个矩阵在下面的着色器代码中使用
            m_Mat.SetMatrix("_WorldToCameraMatrix", m_ShadowCamera.worldToCameraMatrix);
            m_Mat.SetMatrix("_ProjectionMatrix", m_ShadowCamera.projectionMatrix);
        }
    }

    上面c#代码需要用的shader

    // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    
    // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
    
    Shader "Hidden/Shadow"
    {
    	Properties
    	{
    		_MainTex("Texture", 2D) = "white" {}
    	}
    		SubShader
    	{
    		Tags
    	{
    		"Queue" = "Transparent+100"
    	}
    	zwrite off
    		Pass
    	{
    		Blend SrcAlpha OneMinusSrcAlpha
    		CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    
    #include "UnityCG.cginc"
    		uniform float4x4 _WorldToCameraMatrix;
    		uniform float4x4 _ProjectionMatrix;
    
    		struct appdata
    		{
    			float4 vertex : POSITION;
    			float2 uv : TEXCOORD0;
    		};
    
    		struct v2f
    		{
    			float2 uv : TEXCOORD0;
    			float4 vertex : SV_POSITION;
    		};
    
    		v2f vert(appdata v)
    		{
    			v2f o;
    			o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
                            //将该模型投影到影子生成的纹理的照相机的空间中,便可以将纹理一一对应上
    			float4 worldCoord = mul(_Object2World, v.vertex);
    			float4 cameraCoord = mul(_WorldToCameraMatrix, worldCoord);
    			float4 projectionCoord = mul(_ProjectionMatrix, cameraCoord);
    			o.uv = projectionCoord / projectionCoord.w;
    			o.uv = 0.5f*o.uv + float2(0.5f, 0.5f);
    			return o;
    		}
    
    		sampler2D _MainTex;
    
    		fixed4 frag(v2f i) : SV_Target
    		{
    			float dis = (i.uv.x - 0.5f)*(i.uv.x - 0.5f) + (i.uv.y - 0.5f)*(i.uv.y - 0.5f);
    			fixed4 col = tex2D(_MainTex, i.uv);
    			if(col.r + col.g + col.b + col.a > 0)
    			{
    				col.a = 1.0f;
    			}
    			col.rgb = 0;
    			//这里将纹理沿着边缘虚幻处理
    			col.a = (col.a - dis*4.0f)*0.3f;
    			if (i.uv.y < 0.0f || i.uv.y > 1.0f || i.uv.x < 0.0f || i.uv.x > 1.0f)
    			{
    				discard;
    			}
    			return col;
    		}
    			ENDCG
    		}
    	}
    }

    王者荣耀的阴影做了一个细节上的处理,所以我在这里也做了同样的处理,既阴影往边界虚化的效果。

    三、运行效果

    QQ截图20171127142334.pngQQ截图20171127142341.png

    四、项目截图

    3r.jpg

    注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

  • 相关阅读:
    我这里面所用的DBHelper
    同时向主表和从表里面导入execl数据 (asp.net webform)
    在asp.net webform中的 gridview 里面的一些基本操作
    在ASP.NET WEBFORM 中后台实现gridview全选功能
    asp.net webform 发送电子邮件
    Asp.Net中的三种分页方式
    asp.net获取客户端浏览器及主机信息
    在asp.net webfrom 中上传execl (读取单个sheet的数据)
    Linux五种IO模型性能分析
    epoll/poll/select的原理
  • 原文地址:https://www.cnblogs.com/demodashi/p/8491137.html
Copyright © 2020-2023  润新知