Search Unity

Mesh Smoothing angle on mesh created at runtime

Discussion in 'Scripting' started by petey, Feb 8, 2016.

  1. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,824
    Hi there,

    I'm creating a mesh at runtime and I was wondering how you control it's smoothing angle (like you would with an imported mesh)?



    Thanks,
    Pete
     
    lavos2300 likes this.
  2. Bump. Also need to know.
     
  3. Teejay5

    Teejay5

    Joined:
    Feb 26, 2010
    Posts:
    106
    I'm in dire need of a solution to this as well, I'll let you know if I find anything!
     
  4. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    For meshes created at runtime you need to control this yourself with the mesh normals. In order to get a hard edge you also need to duplicate vertices and create unique normals. There is nothing built in that does this automatically in runtime as far as I know.
     
  5. Teejay5

    Teejay5

    Joined:
    Feb 26, 2010
    Posts:
    106
    Thanks for the reply. Duplicate vertices? Does every vertex need to be duplicated or only particular ones? Is this to cancel out/split the averaging of the normals?
     
  6. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    838
    The way smoothing works on meshes is as follows: any two triangles that share vertices have their lighting smoothed across the edges. So if you break apart the default cube, you'll see that the faces don't stick together (which makes them hard shaded). Apply this shader to objects to see the idea:

    Code (csharp):
    1.  
    2. Shader "Unlit/VertexOffset"
    3. {
    4.     Properties
    5.     {
    6.         _MainTex ("Texture", 2D) = "white" {}
    7.         _Offset("Offset", Range(0, 2)) = 1
    8.     }
    9.     SubShader
    10.     {
    11.         Tags { "RenderType"="Opaque" }
    12.         LOD 100
    13.  
    14.         Pass
    15.         {
    16.             CGPROGRAM
    17.             #pragma vertex vert
    18.             #pragma fragment frag
    19.             // make fog work
    20.             #pragma multi_compile_fog
    21.            
    22.             #include "UnityCG.cginc"
    23.  
    24.             struct appdata
    25.             {
    26.                 float4 vertex : POSITION;
    27.                 float2 uv : TEXCOORD0;
    28.                 float4 normal : NORMAL;
    29.             };
    30.  
    31.             struct v2f
    32.             {
    33.                 float2 uv : TEXCOORD0;
    34.                 UNITY_FOG_COORDS(1)
    35.                 float4 vertex : SV_POSITION;
    36.             };
    37.  
    38.             sampler2D _MainTex;
    39.             float4 _MainTex_ST;
    40.             float _Offset;
    41.            
    42.             v2f vert (appdata v)
    43.             {
    44.                 v2f o;
    45.                 v.vertex += _Offset * v.normal;
    46.                 o.vertex = UnityObjectToClipPos(v.vertex);
    47.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    48.                 UNITY_TRANSFER_FOG(o,o.vertex);
    49.                 return o;
    50.             }
    51.            
    52.             fixed4 frag (v2f i) : SV_Target
    53.             {
    54.                 // sample the texture
    55.                 fixed4 col = tex2D(_MainTex, i.uv);
    56.                 // apply fog
    57.                 UNITY_APPLY_FOG(i.fogCoord, col);
    58.                 return col;
    59.             }
    60.             ENDCG
    61.         }
    62.     }
    63. }
    64.  
    So instead of just having 8 vertices, this cube has 4 * 6 = 24 vertices, which allows it to retain the hard edge.
     
  7. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,824
    Ha, I had no idea that was how it worked internally. Thanks for posting this, it's been bugging me for a while.
    I'm not great with shaders though, what part of that shader code breaks up the mesh? I was just looking to break some of the very high angles, would it be possible to add that sort of control to a shader or is that something that would be better as a mesh operation while rebuilding the mesh?
     
    Krypton_Games_sro likes this.
  8. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    838
    That shader is just for demonstrating how meshes work by moving the vertices outwards. To do "auto smoothing" like in the importer, just make sure your mesh at runtime makes duplicate vertices for faces you want smoothed. To check if an edge between two triangles should be smoothed, you can calculate the normal of a triangle defined by points A, B and C by taking Cross(A - B, A - C). Then you can compare two normals and see if they should be joined.
     
    Last edited: Dec 8, 2016
  9. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,824
    Okay cool, I'll have a go at that next time I'm messing with the scene and post some results up here.
    Thanks!
    P.
     
  10. Melnikovv

    Melnikovv

    Joined:
    Oct 21, 2016
    Posts:
    8
    It is simple to convert a smooth mesh to the edged mesh. You need to go through triangle array and for each triangle create a unique vertex with the position of previous vertex.

    Code (CSharp):
    1. /*
    2. vert - vertices of smooth mesh
    3. trig - triangles of smooth mesh
    4.  
    5. outVertices - vertices of edged mesh
    6. outTriangles - triangles of edged mesh
    7. */
    8.  
    9. void RemakeMeshToDiscrete(Vector3[] vert, int[] trig) {
    10.         Vector3[] vertDiscrete = new Vector3[trig.Length];
    11.         int[] trigDiscrete = new int[trig.Length];
    12.         for (int i = 0; i < trig.Length; i++) {
    13.             vertDiscrete[i]=vert[trig[i]];
    14.             trigDiscrete[i] = i;
    15.         }
    16.         outVertices = vertDiscrete;
    17.         outTriangles = trigDiscrete;
    18.     }
     
    Last edited: May 23, 2019
    petey, Jasonface900 and triforcely like this.