Implementing Feathered Planes for Plane Detection in AR Foundation

Tutorial

·

intermediate

·

+0XP

·

15 mins

·

(57)

Unity Technologies

Implementing Feathered Planes for Plane Detection in AR Foundation

In this tutorial, we’ll implement feathered planes for plane detection in AR Foundation. Feathered planes fade out at the edges, giving your Scene a more polished appearance. This is achieved via a combination of custom Shader/Material and a new AR Plane Mesh Visualizer script that builds on the one included in AR Foundation.

Languages available:

1. Implementing Feathered Planes for Plane Detection in AR Foundation

This tutorial has been verified using Unity 2019.4 LTS, AR Foundation 2.1.10 and ARCore XR Plugin 2.1.12


In this tutorial, we’ll implement feathered planes for plane detection in AR Foundation. Feathered planes fade out at the edges, giving your Scene a more polished appearance. This is achieved via a combination of custom Shader/Material and a new AR Plane Mesh Visualizer script that builds on the one included in AR Foundation.


2. Setting up the Project

1. Open the Package Manager by going to Window > Package Manager (Figure 01).


Figure 01: Opening the Package Manager

Figure 01: Opening the Package Manager


2. In the Package Manager, make sure you are in the Unity Registry section and then install AR Foundation. This will also install the AR Subsystems package (Figure 02).


Figure 02: Installing the AR Foundation package

Figure 02: Installing the AR Foundation package


3. Now install either the ARCore XR Plugin (for Android) or the ARKit XR Plugin (for iOS). For this tutorial, we will be using ARCore.


3. Creating the Feathered Plane Shader

1. In the Project view, right-click and select Create > Shader > Unlit Shader. Name it FeatheredPlaneShader and open it in the Script Editor (Figure 03).


Figure 03: Creating an Unlit Shader

Figure 03: Creating an Unlit Shader


2. Our Shader will need the ability to set a tint for the plane Texture and a color for the plane. Inside Properties, add:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop


3. Our Shader needs to handle transparency a bit differently than the default unlit Shader. In Subshader, set the RenderType tag to Transparent, and add a queue tag with the same value:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

4. After LOD 100, add:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

5. We won’t need fog, so remove these two lines inside CGPROGRAM:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

6. Our Shader will use the second UV slot to hold information about where to begin feathering. Inside the struct appdata, add:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

7. Inside the v2f struct definition, replace the line:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop


with:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

8. In order to access the properties we’ve added to the Shader, including a property that will be set by the script later in this tutorial, add the following to the data members after the line float4 _MainTex_ST;:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

9. Remove the following line from the vertex function (vert):


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Instead, we’ll pass the extra UV containing the feathering information. In place of the removed line, add:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

10. Inside our fragment function (frag), we’ll modify the first line to use the tint as well as the Texture. Change it to:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

Remove:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

11. We want to interpolate between the tinted Texture and the chosen plane color based on the opacity of col. Add the following line immediately after the line from the previous step:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

12. Finally, we want to modulate the opacity of col using the information stored in the extra UV and the ShortestUVMapping variable, which will be covered in more detail later in this tutorial. After the line from Step 12, add:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

13. Without comments, the code should look like this:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

14. Save changes and return to the Unity Editor.


15. In the Project view, right-click and select Create > Material. Name it FeatheredPlaneMaterial. Set it to use our Shader by selecting Unlit/FeatheredPlaneShader from the Shader drop-down (Figure 04).


Figure 04: Custom Material and Shader for the FeatheredPlaneMeshVisualizer

Figure 04: Custom Material and Shader for the FeatheredPlaneMeshVisualizer


4. Creating the AR Feathered Plane Mesh Visualizer Script

The Feathered Plane Mesh Visualizer builds on, but does not directly extend, the default AR Plane Mesh Visualizer. It’s attached to the Plane Prefab, which also must contain the AR Plane, AR Mesh Visualizer, and MeshRenderer components. It monitors changes in the boundary of the AR Plane, and correspondingly sets properties in the MeshRenderer's Material so that the edges of the generated AR Plane Mesh are feathered. The width of this feathering is adjustable in the Inspector.


The AR Feathered Plane Mesh Visualizer uses the following data members:


  • s_FeatheringUVs: List of Vector3s that contain information about where feathering begins. This list is generated when the AR Plane boundary changes and is passed to the Material.

  • m_PlaneMeshVisualizer: Stores a reference to the required ARPlaneMeshVisualizer script, which creates and controls the Plane Mesh we're feathering.

  • s_Vertices: List of boundary vertices. This is populated by the ARPlaneMeshVisualizer script’s Mesh and updated when the ARPlane boundary changes.

  • m_Plane: Stores a reference to the ARPlane component, which holds information about the plane we're visualizing. When the boundaries of this plane change, the boundaryChanged event is fired (outside of this script).

  • m_FeatheredPlaneMaterial: This is the Material whose properties are updated by the ARFeatheredPlaneMeshVisualizer whenever the boundary changes.

  • m_FeatheringWidth: This controls the width of the feathering, adjustable via the featheringWidth field.

1. Inside the Project view, right-click and select Create > C# Script. Name it ARFeatheredPlaneMeshVisualizer and open it in the Script Editor.


2. Add the AR Foundation namespace:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

3. Because our script requires the ARPlaneMeshVisualizer, MeshRenderer, and ARPlane components to be on the same GameObject to which it’s attached, add the following line just before the class definition:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

4. Inside the class definition, add the following data members:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

5. The first thing our script needs to do is store references to the required components. Change Start to Awake, and to it add:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

6. In order to know when to update visualization, we will subscribe the event handler method, ARPlane_boundaryUpdated, to the boundaryChanged event when the ARFeatheredPlaneMeshVisualizer’s GameObject is enabled. To prevent orphaned events, we unsubscribe when the GameObject is disabled. Add:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

7. Next, we define ARPlane_boundaryUpdated.


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

8. Finally, we define GenerateBoundaryUVs, the star of the ARFeatheredPlaneMeshVisualizer show. This method retrieves the list of vertices from m_PlaneMeshVisualizer, which stores them in s_Vertices. It assumes that the last vertex is at the plane’s center. It then iterates through the vertices, setting the mapping value for a corresponding feathering UV based on the distance of the vertex from the plane’s center and the desired feathering width. With each iteration, it checks to see if this mapping value is the shortest and, if so, stores it. In either case, it stores the calculated UV mapping in s_FeatheringUVs. After looping through all vertices, it sets the shortest UV mapping property in the Material, creates and adds a feathering UV set at the center, sets the second UV channel to use s_FeatheringUVs and uploads the Mesh data.


9. Add the GenerateBoundaryUVs method:


[@portabletext/react] Unknown block type "code", specify a component for it in the `components.types` prop

10. Save changes and return to the Unity Editor.


11. Load or create a Scene with an AR Session and AR Session Origin, with the AR Session Origin having an attached AR Plane Manager component. Set the AR Plane Manager’s Plane Prefab to the new Prefab.


12. Create or load a Prefab based on the AR Default Plane (or one that satisfies the requirements). If you need more help with this step, please refer to the Configuring Plane Detection for AR Foundation tutorial.


13. Change the Material for the MeshRenderer to the one created earlier in this tutorial. Add the AR Feathered Plane Mesh Visualizer component and save the Prefab (Figure 05).


Figure 05: The completed AR Default Plane Prefab

Figure 05: The completed AR Default Plane Prefab


14. Assign this new Prefab to the Plane Prefab variable in the AR Plane Manager script on the AR Session Origin object (Figure 06).


Figure 06: Setting the Plane Prefab in the AR Plane Manager script

Figure 06: Setting the Plane Prefab in the AR Plane Manager script


15. Save the Scene and build the project. Make sure to have the ARCore XR Foundation package installed if building for Android. If you need more help with this step, please refer to the Configuring Plane Detection for AR Foundation tutorial.


16. Launch the app on your device. Move the device around to capture information about your environment. Notice how the feathered edges allow your detected planes to exist more naturally in the environment.


5. Conclusion

Feathered planes give a more professional appearance to your AR project, allowing a smoother transition between the virtual and physical worlds.


Complete this tutorial