Search Unity

Vertex position/color change using shader

Discussion in 'Scripting' started by Zimennik, Nov 28, 2018.

  1. Zimennik

    Zimennik

    Joined:
    Nov 7, 2014
    Posts:
    5
    Hi guys.
    I making a game, the level of which consists of cells (20x20, 40x40, etc.). Each cell can be vertically stretched from 1 to 5.
    At first I tried to make each cell a separate GameObject, but I realized that it consumes too much memory to render. And then I learned how to generate meshes through the code and merge them (it was cool!). Now I have a task to animate the rise of these cells. Through the code, it looks like this:

    Code (CSharp):
    1.  IEnumerator SetHeights()
    2.     {
    3.         var verts = Plane.GetComponent<MeshFilter>().mesh.vertices;
    4.         float t = 0;
    5.  
    6.         int cellsCount = verts.Length / 24;
    7.  
    8.         while (t < 1)
    9.         {
    10.             for (int i = 0; i < cellsCount; i++)
    11.             {
    12.                 float r = verts[i * 24 + 2].y;
    13.  
    14.  
    15.                 r = Mathf.Lerp(0, heights[i], t);
    16.  
    17.                 verts[i * 24 + 2].y = r; //top right back
    18.                 verts[i * 24 + 8].y = r;
    19.                 verts[i * 24 + 22].y = r;
    20.  
    21.                 verts[i * 24 + 3].y = r; //top left back
    22.                 verts[i * 24 + 9].y = r;
    23.                 verts[i * 24 + 17].y = r;
    24.  
    25.                 verts[i * 24 + 4].y = r; //top right front
    26.                 verts[i * 24 + 10].y = r;
    27.                 verts[i * 24 + 21].y = r;
    28.  
    29.                 verts[i * 24 + 5].y = r; //top left front
    30.                 verts[i * 24 + 11].y = r;
    31.                 verts[i * 24 + 18].y = r;
    32.             }
    33.  
    34.             t = t + Time.deltaTime;
    35.  
    36.             Plane.GetComponent<MeshFilter>().mesh.vertices = verts;
    37.             yield return new WaitForSeconds(0.01f);
    38.         }
    39.     }
    I do the same with color change. Combined mesh consists of cubes, each of which has 24 vertices. In this code, I move only the top vertices on each cube. And everything would be fine, but this animation consumes too many resources.
    I thought that the best solution would be to write a shader that takes as input an array of heights, an array of colors and of some float variable from 0 to 1 that I can change through the code.
    The problem is that I have never written shaders before. To be honest, I don’t even know if it’s really possible to do this with shaders.

    I will be very grateful if you can help me with this.
     
  2. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,408
    this page has basic example for moving vertices in shader,
    see "Normal Extrusion with Vertex Modifier"

    magic happens at this line, where it moves each vertex to vertex normal direction, multiplied by amount.
    v.vertex.xyz += v.normal * _Amount;

    and you can use texture there also, and for example extrude based on red color (0-1) amount
    http://answers.unity.com/answers/641995/view.html
     
  3. Zimennik

    Zimennik

    Joined:
    Nov 7, 2014
    Posts:
    5
    Nice! So you CAN move vertices like this! Ok, i'm gonna try to dig into it.
    But one more question. I don't need to move each vertices. Just every 2,3,4,5,8,9,10,11,17,18,21 and 22. Can I do this from shader?
     
  4. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,408
  5. Zimennik

    Zimennik

    Joined:
    Nov 7, 2014
    Posts:
    5
    Thank you so much! It turned out almost what we need. I will try to optimize it a bit (I don’t like this "if" at all) and redo it under a large mesh.

    Code (CSharp):
    1. SubShader
    2.     {
    3.         Pass
    4.         {
    5.             CGPROGRAM
    6.             #pragma vertex vert
    7.             #pragma fragment frag
    8.  
    9.             struct v2f {
    10.                 float4 pos : SV_POSITION;
    11.             };
    12.             float _Amount;
    13.          
    14.          
    15.             v2f vert (
    16.                 float4 vertex : POSITION, // vertex position input
    17.                 uint vid : SV_VertexID // vertex ID, needs to be uint
    18.                 )
    19.             {
    20.                 v2f o;
    21.                 o.pos = UnityObjectToClipPos(vertex);
    22.                 float f = (float)vid;
    23.                 if(f==2 || f ==3 ||f==4 || f ==5 ||f==8 || f ==9 ||f==10 || f ==11 ||f==17 || f ==18 ||f==21 || f ==22)
    24.                 {
    25.                     o.pos.y+=_Amount;
    26.                 }
    27.                
    28.                 return o;
    29.             }
    30.  
    31.             fixed4 frag (v2f i) : SV_Target
    32.             {
    33.                 return i.pos;
    34.             }
    35.             ENDCG
    36.         }
    37.     }
    vertices.gif
     
    mgear likes this.