横版2D光影系统

来源:互联网 发布:ubuntu16 软件源 编辑:程序博客网 时间:2024/04/29 23:45

因为项目需求,做了一个适用于横版2D的光影系统,包括地上的光及墙上的光,效果如图

大体思路就是通过射线来检测光路,通过改变mesh网格来实现光路

首先,我定义了3个摄像机,

GroundCameraDepth-1,用于显示背景

ShadowCameraDepth0,用于显示阴影及阴影遮罩,clear flags设置为Dont Clear

BuidingCameraDepth1,用于显示其他物体,如人物,建筑

我先建立了阴影及其遮罩 ,如图,注意位置关系,遮罩需包含1mesh组件及一个包含mesh组件的子物体

遮罩shader如下

Shader "Masked/Mask" {
    SubShader {
        // Render the mask after regular geometry, but before masked geometry and
        // transparent things.
        Tags {"Queue" = "Geometry+10" }
        // Don't draw in the RGBA channels; just the depth buffer
        ColorMask 0
        ZWrite On
        // Do nothing specific in the pass:
        Pass {}
    }
} 

这个shader的效果为,他会把mesh范围内的所有物体隐藏,因为设置了clearflags,所以会显示较低层级的图像

在运行后,在每一帧获取视野范围内碰撞体的顶点,然后用射线进行检测,

检测方法大体分为两种,一种是已光源为中心,从0度开始发射射线,一次加1

还有就是向碰撞体的顶点方向及其正负0.1度发射射线

此处采用第二种方法

碰撞信息采用结构体记录,包括位置,射线角度,碰撞体是否为地面,法线

public struct HLSHitInfo {
    public Vector2 point;
    public float angle;
    public bool isGround;
    public Vector2 normal;
    public HLSHitInfo(Vector2 point,float angle,bool isGround = false)
    {
        this.point = point;
        this.angle = angle;
        this.isGround = isGround;
        normal = Vector2.zero;
    }
    public HLSHitInfo(Vector2 point,float angle,bool isGround,Vector2 normal)
    {
        this.point = point;
        this.angle = angle;
        this.isGround = isGround;
        this.normal = normal;
    }

} 

依据角度进行排序以方便拼接

角度计算函数为

public float GetDegree(Vector2 dir)
        {
            if (dir.y == 0) {
                if (dir.x > 0) {
                    return 0f;
                } else {
                    return 180f;
                }
            }
            float oppo = dir.y;
            float hy = dir.magnitude;
            float degree = Mathf.Asin (oppo / hy) * ToDegree;
            if (dir.x < 0 && dir.y > 0)
                return 180f - degree;
            if (dir.x <= 0 && dir.y < 0)
                return 180f - degree;
            if (dir.x > 0 && dir.y < 0)
                return 360f + degree;
            return degree;
        } 

之后将顶点和面片信息录入,0顶点为光源位置

加入顶点数组如图为{0,1,2,3,4,5}

则面片数组为{0,2,1…………}3个位置为1个三角面,数组大小为面数*3

注意,组合面片时必须按顺时针组合,否则法线会反

下面说墙体光,墙体光使用了一个不同于地面光的mesh

这里要发射一条向右的线,否则在0度会出现一些问题

顺序遍历射线信息list当法线方向改变或碰撞的对象(障碍物碰撞体,地形碰撞体)改变时,记录改变点

再加入将改变点y值提高后的点,使每4个点组成两个面,

然后如图组合

0 0