当前位置:   article > 正文

Unity学习2:如何实现个性化渲染平面(图文详细)_unity 个性化设计

unity 个性化设计

Unity学习2:如何实现个性化渲染平面(图文详细)

AR Plane Manager(平面追踪对象管理器)

平面管理器是一种可跟踪的管理器。

平面管理器为环境中每个检测到的平面创建游戏对象。平面是由位姿、尺寸和边界点表示的平面。边界点是凸的(每个检测出来的边界角都是大于90°)。

环境中可以被检测为平面的特征示例包括水平桌子、地板、工作台面和垂直墙壁。

负责管理平面以及管理检测出的这些平面,但不负责渲染平面,由其Plane Prefab属性指定的预制体负责

两个属性组件:

  1. Plane Prefab:平面预制体,不赋值的会自动实例化一个空对象
  2. Detection Mode:设置平面检测方式,如水平平面(Horizontal),垂直平面(Vertical),水平和垂直平面(Everything),不检测平面(Nothing)

image-20220109095249440

可视化平面

要可视化平面,您需要创建一个 Prefab 或 GameObject,其中包含一个订阅 ARPlane 的 boundaryChanged 事件的组件。 ARFoundation 提供了一个 ARPlaneMeshVisualizer。该组件从边界顶点生成网格并将其分配给 MeshCollider、MeshFilter 和 LineRenderer(如果存在)。

要创建一个新的 GameObject,然后您可以使用它来创建您的 Prefab,请在您的 Scene 视图中单击鼠标右键,然后从出现的上下文菜单中选择 GameObject > XR > AR Default Plane

新建一个AR Default Plane对象作为预制体(默认平面预制体)

其中各属性的说明:

AR Plane:负责各类属性事宜,如是否在移除平面时销毁此实例化对象

AR Plane Mesh Visualizer:主要从边界特征点和其他特征点三角化生成一个平面网格

Mesh Renderer:使用Mesh Renderer采用合适材质渲染平面

Line Renderer:负责渲染平面可视化后的边界连线

image-20220109095216797

演示视频:默认浅黄色的平面,黑色的边界线

https://www.bilibili.com/video/BV1pZ4y1f7Ru?spm_id_from=333.999.0.0

创建 AR Default Plane 后,将其分配给 ARPlaneManager 的 Plane Prefab 字段。您可以直接使用它,也可以通过将AR Default Plane 拖到 Assets 文件夹中来创建 Prefab。默认平面如下所示:

image-20220109195607721

个性化渲染平面

我下载的是官方的demo

  1. 首先将AR Default Plane对象下的Line Renderer组件移除

  2. 编写一个c#脚本ARFeatheredPlaneMeshVisualizer,并将其作为组件添加到AR Default Plane对象上

    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.XR.ARFoundation;
    
    /// <summary>
    /// This plane visualizer demonstrates the use of a feathering effect
    /// at the edge of the detected plane, which reduces the visual impression
    /// of a hard edge.
    /// </summary>
    [RequireComponent(typeof(ARPlaneMeshVisualizer), typeof(MeshRenderer), typeof(ARPlane))]
    public class ARFeatheredPlaneMeshVisualizer : MonoBehaviour
    {
        [Tooltip("The width of the texture feathering (in world units).")]
        [SerializeField]
        float m_FeatheringWidth = 0.2f;
    
        /// <summary>
        /// The width of the texture feathering (in world units).
        /// </summary>
        public float featheringWidth
        { 
            get { return m_FeatheringWidth; }
            set { m_FeatheringWidth = value; } 
        }
    
        void Awake()
        {
            m_PlaneMeshVisualizer = GetComponent<ARPlaneMeshVisualizer>();
            m_FeatheredPlaneMaterial = GetComponent<MeshRenderer>().material;
            m_Plane = GetComponent<ARPlane>();
        }
    
        void OnEnable()
        {
            m_Plane.boundaryChanged += ARPlane_boundaryUpdated;
        }
    
        void OnDisable()
        {
            m_Plane.boundaryChanged -= ARPlane_boundaryUpdated;
        }
    
        void ARPlane_boundaryUpdated(ARPlaneBoundaryChangedEventArgs eventArgs)
        {
            GenerateBoundaryUVs(m_PlaneMeshVisualizer.mesh);
        }
    
        /// <summary>
        /// Generate UV2s to mark the boundary vertices and feathering UV coords.
        /// </summary>
        /// <remarks>
        /// The <c>ARPlaneMeshVisualizer</c> has a <c>meshUpdated</c> event that can be used to modify the generated
        /// mesh. In this case we'll add UV2s to mark the boundary vertices.
        /// This technique avoids having to generate extra vertices for the boundary. It works best when the plane is 
        /// is fairly uniform.
        /// </remarks>
        /// <param name="mesh">The <c>Mesh</c> generated by <c>ARPlaneMeshVisualizer</c></param>
        void GenerateBoundaryUVs(Mesh mesh)
        {
            int vertexCount = mesh.vertexCount;
    
            // Reuse the list of UVs
            s_FeatheringUVs.Clear();
            if (s_FeatheringUVs.Capacity < vertexCount) { s_FeatheringUVs.Capacity = vertexCount; }
    
            mesh.GetVertices(s_Vertices);
    
            Vector3 centerInPlaneSpace = s_Vertices[s_Vertices.Count - 1];
            Vector3 uv = new Vector3(0, 0, 0);
            float shortestUVMapping = float.MaxValue;
    
            // Assume the last vertex is the center vertex.
            for (int i = 0; i < vertexCount - 1; i++)
            {
                float vertexDist = Vector3.Distance(s_Vertices[i], centerInPlaneSpace);
    
                // Remap the UV so that a UV of "1" marks the feathering boudary.
                // The ratio of featherBoundaryDistance/edgeDistance is the same as featherUV/edgeUV.
                // Rearrange to get the edge UV.
                float uvMapping = vertexDist / Mathf.Max(vertexDist - featheringWidth, 0.001f);
                uv.x = uvMapping;
    
                // All the UV mappings will be different. In the shader we need to know the UV value we need to fade out by.
                // Choose the shortest UV to guarentee we fade out before the border.
                // This means the feathering widths will be slightly different, we again rely on a fairly uniform plane.
                if (shortestUVMapping > uvMapping) { shortestUVMapping = uvMapping; }
    
                s_FeatheringUVs.Add(uv);
            }
    
            m_FeatheredPlaneMaterial.SetFloat("_ShortestUVMapping", shortestUVMapping);
    
            // Add the center vertex UV
            uv.Set(0, 0, 0);
            s_FeatheringUVs.Add(uv);
    
            mesh.SetUVs(1, s_FeatheringUVs);
            mesh.UploadMeshData(false);
        }
    
        static List<Vector3> s_FeatheringUVs = new List<Vector3>();
    
        static List<Vector3> s_Vertices = new List<Vector3>();
    
        ARPlaneMeshVisualizer m_PlaneMeshVisualizer;
    
        ARPlane m_Plane;
    
        Material m_FeatheredPlaneMaterial;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111

    image-20220114204629357

  3. 在project窗口的Assets下新建一个文件夹Shaders,在其中右键-》create-》shader-》Unlit Shader创建一个shader文件,并命名为FeatheredPlaneShader

    Shader "Unlit/FeatheredPlaneShader"
    {
        Properties
        {
            _MainTex("Texture", 2D) = "white" {}
            _TexTintColor("Texture Tint Color", Color) = (1,1,1,1)
            _PlaneColor("Plane Color", Color) = (1,1,1,1)
        }
            SubShader
            {
                Tags { "RenderType" = "Transparent" "Queue" = "Transparent" }
                LOD 100
                Blend SrcAlpha OneMinusSrcAlpha
                ZWrite Off
    
                Pass
                {
                    CGPROGRAM
                    #pragma vertex vert
                    #pragma fragment frag
    
                    #include "UnityCG.cginc"
    
                    struct appdata
                    {
                        float4 vertex : POSITION;
                        float2 uv : TEXCOORD0;
                        float3 uv2 : TEXCOORD1;
    
                        UNITY_VERTEX_INPUT_INSTANCE_ID
                    };
    
                    struct v2f
                    {
                        float4 vertex : SV_POSITION;
                        float2 uv : TEXCOORD0;
                        float3 uv2 : TEXCOORD1;
    
                        UNITY_VERTEX_OUTPUT_STEREO
                    };
    
                    sampler2D _MainTex;
                    float4 _MainTex_ST;
                    fixed4 _TexTintColor;
                    fixed4 _PlaneColor;
                    float _ShortestUVMapping;
    
                    v2f vert(appdata v)
                    {
                        v2f o;
    
                        UNITY_SETUP_INSTANCE_ID(v);
                        UNITY_INITIALIZE_OUTPUT(v2f, o);
                        UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    
                        o.vertex = UnityObjectToClipPos(v.vertex);
                        o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                        o.uv2 = v.uv2;
                        return o;
                    }
    
                    fixed4 frag(v2f i) : SV_Target
                    {
                        UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
    
                        fixed4 col = tex2D(_MainTex, i.uv) * _TexTintColor;
                        col = lerp(_PlaneColor, col, col.a);
                        // Fade out from as we pass the edge.
                        // uv2.x stores a mapped UV that will be "1" at the beginning of the feathering.
                        // We fade until we reach at the edge of the shortest UV mapping.
                        // This is the remmaped UV value at the vertex.
                        // We choose the shorted one so that ll edges will fade out completely.
                        // See ARFeatheredPlaneMeshVisualizer.cs for more details.
                        col.a *= 1 - smoothstep(1, _ShortestUVMapping, i.uv2.x);
                        return col;
                    }
                    ENDCG
                }
            }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    image-20220114205946065

  4. 然后在Materials文件下创建一个新的材质,右键-》create-》material,并命名为Plane Mat,其下有一属性Shader,在其中搜索刚写好的shader脚本代码,添加进来

    image-20220114214752472

  5. 在project窗口的Assets下新建一个文件夹Textures,将一个png格式的渲染图片拖到此文件夹下,自动生成一个同名的(Texture 2D)文件image-20220114215225434image-20220114215338632

    PlanePatternDot

  6. 选中Plant Mat,在Inspector窗口下,有一个Texture属性,选择我们刚拖进来的png图片,其中Texture Tint Color为纹理显示的颜色,Plane Color为平面的颜色,再将这个材质拖动添加到AR Default Plane对象上去,

    image-20220114215818976

    image-20220114221646761

  7. 至此个性化渲染平面已经制作完成,总结一下:不同于默认的黄色平面,黑色边界线,自定义的平面效果可以设置Shader脚本渲染Texture图片纹理属性,并将Texture图片设置在一个新材质material上,material可以设置纹理颜色和平面背景颜色(一般是透明),最终在Android手机上跑一下效果:
    https://www.bilibili.com/video/BV16P4y1j7Po?spm_id_from=333.999.0.0

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/118066
推荐阅读
相关标签
  

闽ICP备14008679号