【Unity】如何解决自建Mesh显示的贴图受光照问题——法线

结论:本文解决自建Mesh时,因为法线的问题而导致的贴图受光照问题。

本文的代码前瞻(成功创建Mesh并且可以赋予贴图的也许不必要观看):https://blog.csdn.net/weixin_47220117/article/details/147404303?spm=1001.2014.3001.5501

1.先理解法线

法线就是垂直于一个面的一条向量,它对该面的受光照程度影响较大。

2.如何创建法线

第一种方式:

遇到这样的问题时,明显就是贴图的受光照计算受到了影响,对于自建的Mesh中可以这么写:

//法线
Vector3[] normals = new Vector3[4];
Vector3 edge1 = vertices[1] - vertices[0];
Vector3 edge2 = vertices[0] - vertices[3];
Vector3 normal = Vector3.Cross(edge1, edge2).normalized;
//由于只有一个面,所以四条法线是一样的,赋予相同的即可
for(int i = 0; i < normals.Length; i ++)
{
    normals[i] = normal;
}

//这里是赋予你的Mesh这四条法线,几个顶点就有几条法线

mesh.normals = normals;

完整代码:

using UnityEngine;

public class AMesh : MonoBehaviour
{
    public MeshFilter meshFilter;//网格拥有者组件

    [ContextMenu(nameof(Create))]
    public void Create()
    {   
        //顶点坐标
        Vector3[] vertices = new Vector3[]
        {
           new Vector3(-0.5f, 0, -0.5f),//左下角
           new Vector3(0.5f, 0, -0.5f),//右下角
           new Vector3(0.5f, 0, 0.5f),//右上角
            new Vector3(-0.5f, 0, 0.5f),//左上角
        };

        //需要顺时针构建三角形
        int[] triangle = new int[] 
        { 
            0, 2, 1,//第一个三角形
            0, 3, 2,//第二个三角形
        };

        //UV
        Vector2[] uv = new Vector2[]
        {
            new Vector2(0, 0),//左下角
            new Vector2(1, 0),//右下角
            new Vector2(1, 1),//右上角
            new Vector2(0, 1),//左上角
        };

        //法线
        Vector3[] normals = new Vector3[4];
        Vector3 edge1 = vertices[1] - vertices[0];
        Vector3 edge2 = vertices[0] - vertices[3];

        //进行叉积运算
        Vector3 normal = Vector3.Cross(edge1, edge2).normalized;
        //由于只有一个面,所以四条法线是一样的,赋予相同的即可
        for(int i = 0; i < normals.Length; i ++)
        {
            normals[i] = normal;
        }

        //构建Mesh实例
        Mesh mesh = new Mesh();
        mesh.vertices = vertices;
        mesh.triangles = triangle;
        mesh.uv = uv;
        mesh.normals = normals;
        meshFilter.mesh = mesh;

    }
}

!!! 如果你发现写完后,光照计算还是出现问题,那么很可能就是法线是背光的,叉积计算遵循右手定则!!!遇到这个问题的解决办法是:

把这句代码:Vector3 normal = Vector3.Cross(edge1, edge2).normalized;

改成:Vector3 normal = -Vector3.Cross(edge1, edge2).normalized;

这样法线就不会背光了。

第二种方式:

一句搞定,还基本不会出错!

即可直接使用Unity自带的api:

mesh.RecalculateNormals();

完整代码:

using UnityEngine;

public class AMesh : MonoBehaviour
{
    public MeshFilter meshFilter;//网格拥有者组件

    [ContextMenu(nameof(Create))]
    public void Create()
    {   
        //顶点坐标
        Vector3[] vertices = new Vector3[]
        {
           new Vector3(-0.5f, 0, -0.5f),//左下角
           new Vector3(0.5f, 0, -0.5f),//右下角
           new Vector3(0.5f, 0, 0.5f),//右上角
            new Vector3(-0.5f, 0, 0.5f),//左上角
        };

        //需要顺时针构建三角形
        int[] triangle = new int[] 
        { 
            0, 2, 1,//第一个三角形
            0, 3, 2,//第二个三角形
        };

        //UV
        Vector2[] uv = new Vector2[]
        {
            new Vector2(0, 0),//左下角
            new Vector2(1, 0),//右下角
            new Vector2(1, 1),//右上角
            new Vector2(0, 1),//左上角
        };

        //构建Mesh实例
        Mesh mesh = new Mesh();
        mesh.vertices = vertices;
        mesh.triangles = triangle;
        mesh.uv = uv;
        mesh.RecalculateNormals();
        meshFilter.mesh = mesh;

    }
}

解决后的效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值