【Unity】为网格生成顶点法线(Mesh.RecalculateNormals计算异常的解决方案)

这篇具有很好参考价值的文章主要介绍了【Unity】为网格生成顶点法线(Mesh.RecalculateNormals计算异常的解决方案)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

我们通过代码动态创建的网格,因为没有法线,不会接收到光照。

正常情况下调用Mesh.RecalculateNormals方法,重新生成法线即可。

但特定情况下通过此方法计算出的顶点发现都是(0, 0,0),这种情况下只能手动生成法线了

如下图,左边物体有正确的法线,可以接收光照信息,右侧物体无法线,无法接收光照。
unity顶点法线,Unity,unity,游戏引擎

RecalculateNormals计算异常的原因

经测试发现导致Mesh.RecalculateNormals计算异常的情况:
如果Mesh中的某个顶点,在三角形标号数组中,即画了正面的网格,又画了反面的网格,则会导致RecalculateNormals计算错误,该点法线计算结果为(0, 0,0)。

解决方法1

对于双面网格,将顶点数组增加一倍,用于绘制反面的网格,分别放入Mesh的三角形标号数组中,以保证每个点法线计算正确。

解决方法2

用下方的生成顶点法线算法,手动计算期望的法线数组。

原理

法线:法线是指始终垂直于某平面的直线。在几何学中,法线指平面上垂直于曲线在某点的切线的一条线。

网格的法线数组:法线数组存放Mesh每个顶点的法线,数组大小与顶点坐标对应,normals[i]对应顶点vertices[i]的法线。

在 Max Wagner 的 《Generating Vertex Normals》文章 中写到——严格意义上讲,点是没有法线的。点的法线是在使用Phone或Gouraud模型时计算光照使用。如果一个面上的所有法线都一样,他们的光照也就一样,就会产生 flatness 效果;而如果把每个顶点的法向设置不同,则更平滑。

我们通过代码创建的网格一般都是多边形,所以给每个顶点赋值他所在的平面的法线即可。

生成顶点法线算法

unity顶点法线,Unity,unity,游戏引擎
创建网格,并设定如上图的八个点位,三角形序列,uv

 		Mesh mesh = new Mesh();
        Vector3[] vertices = new Vector3[8];
        vertices[0] = new Vector3(0,0,0);
        vertices[1] = new Vector3(0,1,0);
        vertices[2] = new Vector3(1,0,0);
        vertices[3] = new Vector3(1,1,0);
        
        vertices[4] = new Vector3(1,0,0);
        vertices[5] = new Vector3(1,1,0);
        vertices[6] = new Vector3(2,0,1);
        vertices[7] = new Vector3(2,1,1);
        mesh.vertices = vertices;
        
        int[] triangles = new int[12];
        triangles[0] = 0;
        triangles[1] = 1;
        triangles[2] = 3;
        
        triangles[3] = 2;
        triangles[4] = 0;
        triangles[5] = 3;
        
        triangles[6] = 4;
        triangles[7] = 5;
        triangles[8] = 7;

        triangles[9] = 6;
        triangles[10] = 4;
        triangles[11] = 7;
        
        mesh.triangles = triangles;

        Vector2[] uv = new Vector2[8];
        uv[0] = new Vector2(0,0);
        uv[1] = new Vector2(0,1);
        uv[2] = new Vector2(1,0);
        uv[3] = new Vector2(1,1);
        
        uv[4] = new Vector2(0,0);
        uv[5] = new Vector2(0,1);
        uv[6] = new Vector2(1,0);
        uv[7] = new Vector2(1,1);
        mesh.uv = uv;

生成法线数组

 Vector3[] normals = new Vector3[8];
        Vector3 v1 = Vector3.Cross(vertices[0] - vertices[1], vertices[0] - vertices[3]);
        normals[0] = v1;
        normals[1] = v1;
        normals[2] = v1;
        normals[3] = v1;

        Vector3 v2 = Vector3.Cross(vertices[4] - vertices[5], vertices[4] - vertices[7]);
        normals[4] = v2;
        normals[5] = v2;
        normals[6] = v2;
        normals[7] = v2;
        mesh.normals = normals;
        //mesh.RecalculateNormals();

最终效果

unity顶点法线,Unity,unity,游戏引擎

(此案例中,使用Mesh.RecalculateNormal,也可生成正确法线。)文章来源地址https://www.toymoban.com/news/detail-639941.html

完整代码,增加了点位, 注释部分为增加了背部网格

   public Mesh CreatMeshTest()
    {
        Mesh mesh = new Mesh();
        Vector3[] vertices = new Vector3[12];
        vertices[0] = new Vector3(0,0,0);
        vertices[1] = new Vector3(0,1,0);
        vertices[2] = new Vector3(1,0,0);
        vertices[3] = new Vector3(1,1,0);
        
        vertices[4] = new Vector3(1,0,0);
        vertices[5] = new Vector3(1,1,0);
        vertices[6] = new Vector3(0.5f,0,1);
        vertices[7] = new Vector3(0.5f,1,1);
        
        vertices[8] = new Vector3(0.5f,0,1);
        vertices[9] = new Vector3(0.5f,1,1);
        vertices[10] = new Vector3(0,0,0);
        vertices[11] = new Vector3(0,1,0);
        mesh.vertices = vertices;
        
        int[] triangles = new int[18];
        triangles[0] = 0;
        triangles[1] = 1;
        triangles[2] = 3;
        
        triangles[3] = 2;
        triangles[4] = 0;
        triangles[5] = 3;
        
        triangles[6] = 4;
        triangles[7] = 5;
        triangles[8] = 7;

        triangles[9] = 6;
        triangles[10] = 4;
        triangles[11] = 7;
        
        triangles[12] = 8;
        triangles[13] = 9;
        triangles[14] = 11;

        triangles[15] = 10;
        triangles[16] = 8;
        triangles[17] = 11;
        
        // triangles[18] = 0;
        // triangles[19] = 3;
        // triangles[20] = 1;
        //
        // triangles[21] = 2;
        // triangles[22] = 3;
        // triangles[23] = 0;
        //
        // triangles[24] = 4;
        // triangles[25] = 7;
        // triangles[26] = 5;
        //
        // triangles[27] = 6;
        // triangles[28] = 7;
        // triangles[29] = 4;
        //
        // triangles[30] = 8;
        // triangles[31] = 11;
        // triangles[32] = 9;
        //
        // triangles[33] = 10;
        // triangles[34] = 11;
        // triangles[35] = 8;
        
        mesh.triangles = triangles;

        Vector2[] uv = new Vector2[12];
        uv[0] = new Vector2(0,0);
        uv[1] = new Vector2(0,1);
        uv[2] = new Vector2(1,0);
        uv[3] = new Vector2(1,1);
        
        uv[4] = new Vector2(0,0);
        uv[5] = new Vector2(0,1);
        uv[6] = new Vector2(1,0);
        uv[7] = new Vector2(1,1);
        
        uv[8] = new Vector2(0,0);
        uv[9] = new Vector2(0,1);
        uv[10] = new Vector2(1,0);
        uv[11] = new Vector2(1,1);
        mesh.uv = uv;
        
        Vector3[] normals = new Vector3[12];
        Vector3 v1 = Vector3.Cross(vertices[0] - vertices[1], vertices[0] - vertices[3]);
        normals[0] = v1;
        normals[1] = v1;
        normals[2] = v1;
        normals[3] = v1;

        Vector3 v2 = Vector3.Cross(vertices[4] - vertices[5], vertices[4] - vertices[7]);
        normals[4] = v2;
        normals[5] = v2;
        normals[6] = v2;
        normals[7] = v2;
        
        Vector3 v3 = Vector3.Cross(vertices[8] - vertices[9], vertices[8] - vertices[11]);
        normals[8] = v3;
        normals[9] = v3;
        normals[10] = v3;
        normals[11] = v3;
        mesh.normals = normals;
        //mesh.RecalculateNormals();
        return mesh;

    }

到了这里,关于【Unity】为网格生成顶点法线(Mesh.RecalculateNormals计算异常的解决方案)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity网格篇Mesh(一)

    创建网格坐标 使用携程计算他们位置 利用三角形确定一个面 自动生成法线 添加纹理坐标和切线 这篇教程中我们将利用顶点和三角面创建一个网格。 原英文篇 如果你想要在Unity显示一些东西,你需要一个网格。他可以是一个3D模型从另一个程序倒入的(3dmax,maya)。它也可

    2024年02月03日
    浏览(38)
  • Unity中实时获取网格上点的位置,还有对应的面和法线

    在Unity中,可以使用Mesh类来获取一个网格上点的位置以及对应的面和法线。以下是具体步骤: 在脚本中,需要先获取要操作的网格对象。可以使用以下代码: Mesh mesh = GetComponentMeshFilter().mesh; 其中,GetComponentMeshFilter()用于获取该游戏对象上的MeshFilter组件,mesh属性用于获取该

    2024年02月08日
    浏览(36)
  • 论文解读Nerf2Mesh:基于Nerf的网格资产生成

    论文标题 Delicate Textured Mesh Recovery from NeRF via Adaptive Surface Refinement 简单翻译:通过Nerf恢复网格结构 论文下载地址,点这里 1:网格知识点介绍(可跳过): 3D模型有三种表达方式, 体素(Voxel),网格(Mesh),点云(Point Cloud) 、SDF等,但在实际渲染应用中,主流的表达方

    2024年02月02日
    浏览(50)
  • 关于unity粒子系统renderer设为mesh(网格)模式后无法旋转的问题

     将其中的render alignment设为local就可以了

    2024年02月12日
    浏览(36)
  • unity C# 读取shp并生成mesh(ShpLoader使用)

    声明 使用 : Unity读取并解析Shapefile地图文件_SuperWiwi的博客-CSDN博客_unity读取shp 结构参考: 文件头_GIS基础工具篇01C#读写shp矢量文件_贱贱猪66的博客-CSDN博客 github:  https://github.com/EIdeallab/ShpLoader 注意问题:拿到数据后先Arcgis打开 1 编码格式   更多情况是数据来源自其它地方

    2024年02月11日
    浏览(29)
  • VCG 网格顶点聚类

    顶点聚类方法将落在给定大小体素中的所有顶点集中到单个顶点之上,其过程有点类似于点云体素下采样,之后再基于聚类之后的顶点重新连接面片,以达到网格简化的目的。

    2024年01月15日
    浏览(32)
  • 【unity】RenderFeature的应用(生成水平面的网格线)

    在URP里RenderFeature是用于后处理效果上的,也还可以实现一些特殊的效果,比如生成网格线。我们可以使用 CommandBuffer来创建地面网格,这样的话可以通过调整 CommandBuffer的参数来控制地面网格的密度。 实现效果 创建流程 创建RenderFeature模板 编写CommandBuffer生成网格方法 增加到

    2024年02月12日
    浏览(22)
  • UE4 顶点网格动画播放后渲染模糊问题

    问题描述:ABC格式的顶点网格动画播放结束后,改模型看起来显得很模糊有抖动的样子 解决办法:关闭逐骨骼动态模糊

    2024年02月07日
    浏览(30)
  • 虚幻UE 材质-顶点/网格体绘制、Megascans材质混合

    首先很高兴大家能够关注我,提前在2023年结束达到百粉! 然后这篇文章是使用虚幻UE 的网格体/顶点绘制模式来对Megascans材质进行混合的实验。 注意:以下材质都是指材质实例,网格体绘制和顶点绘制一个意思 1、顶点绘制模型: 需要模型的面数尽量多一点,官方的立方体面

    2024年02月03日
    浏览(34)
  • 服务网格Service Mesh和Istio

    服务网格是一种用于处理微服务架构中服务间通信的网络基础架构。它通过在应用程序的每个服务之间插入代理(通常称为Sidecar代理),来实现服务间通信的控制和管理。这种方式将通信逻辑从应用程序代码中解耦出来,使得开发人员可以专注于业务逻辑而无需担心网络通信

    2024年02月22日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包