Search Unity

Update vertex colors in script and show it through shader.

Discussion in 'Shaders' started by den.jmpr, Jan 18, 2013.

  1. den.jmpr

    den.jmpr

    Joined:
    Jan 18, 2013
    Posts:
    8
    Hi! My name is Denis. I'm newbie in Unity, but i need help. I want to generate vertex colors of my mesh and show it through shader, but I'm stuck.
    Please, help me with my code.

    My .cs file is:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class TeapotBehavior : MonoBehaviour
    5. {
    6.     void Start ()
    7.     {
    8.  
    9.     }
    10.    
    11.     void Update ()
    12.     {
    13.         if (GetComponent<MeshFilter> ()) {
    14.             Mesh mesh = GetComponent<MeshFilter> ().mesh;
    15.             Vector3[] vertices = mesh.vertices;
    16.             Color[] colors = new Color[vertices.Length];
    17.             for (int i = 0; i < vertices.Length; i++) {
    18.                 colors [i] = Color.Lerp(Color.green, Color.red, Time.time);
    19.             }
    20.             mesh.colors = colors;
    21.         }
    22.     }
    23. }
    And my .shader file is:

    Code (csharp):
    1. Shader "Custom/PaintShader" {
    2.     Properties {
    3.     }
    4.     SubShader {
    5.         Tags { "RenderType" = "Opaque" }
    6.         CGPROGRAM
    7.         #pragma surface surf Lambert
    8.         struct Input {
    9.             float4 color: Color;
    10.         };
    11.  
    12.         void surf (Input IN, inout SurfaceOutput o) {
    13.             o.Albedo = IN.color.rgb;
    14.         }
    15.         ENDCG
    16.  
    17.     }
    18.  
    19.     FallBack "Diffuse"
    20. }
    21.  
    When i press play, there is nothing happend, my teapot doesn't change color during time.
     
  2. Martin-Kraus

    Martin-Kraus

    Joined:
    Feb 18, 2011
    Posts:
    617
    I think Lerp expects a third argument between 0 and 1. Time.time will usually be greater than 1; thus, this is probably clamped to 1 which then will appear like it is a constant value.
     
  3. den.jmpr

    den.jmpr

    Joined:
    Jan 18, 2013
    Posts:
    8
    I tried to pass 0 or 1 as third argument, but teapot is white, not green or red. I think that something wrong in "connection mechanism" between colors of mesh vertices and colors in shader.
     
  4. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    Think this should do it (bit faster too - cache everything you can in these cases).

    Martin's right in that Time.time will (after the first second of the game, at least) always be greater than 1. So you'll need to slow it down a bit if you want it visible.

    Also changed it to mesh.colors32 as it's faster.

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class TeapotBehavior : MonoBehaviour
    6. {
    7.     private Mesh mesh;
    8.     private int numVerts;
    9.     private Color32[] colors;
    10.     int seconds = 5;
    11.    
    12.     void Start ()
    13.     {
    14.         if (GetComponent<MeshFilter> ()) {
    15.             mesh = GetComponent<MeshFilter> ().mesh;
    16.             if (mesh != null) {
    17.                 numVerts = mesh.vertexCount;
    18.                 colors = new Color32[numVerts];
    19.             }
    20.         }
    21.     }
    22.  
    23.     void Update ()
    24.     {
    25.         if (mesh != null) {
    26.             for (int i = 0; i < numVerts; i++) {
    27.                 colors [i] = Color32.Lerp(Color.green, Color.red, Time.time / seconds);
    28.             }
    29.             mesh.colors32 = colors;
    30.         }
    31.     }
    32. }
    33.  

    Edit: Oh, not sure you can get vertex colour through surface shaders as easily as that.

    You might want to add;
    Code (csharp):
    1.  
    2. #pragma surface surf Lambert vertex:vert
    3.  
    Code (csharp):
    1.  
    2. void vert (inout appdata_full v, out Input o) {
    3.     UNITY_INITIALIZE_OUTPUT(Input,o);
    4.     o.color = v.color;
    5. }
    6.  
     
    Last edited: Jan 18, 2013
  5. den.jmpr

    den.jmpr

    Joined:
    Jan 18, 2013
    Posts:
    8
    Thanks! It works, but the problem was that i attached script to prefab, not to object. I'm stupid. Thanks to all for your time!
     
  6. julienrobert

    julienrobert

    Joined:
    Sep 15, 2014
    Posts:
    65
    I have the same problem. Tried with an empty scene with only a cylinder mesh, directional light and camera. Put the script (the one from the Unity API mesh.colors) and a vertex color shader like this one http://wiki.unity3d.com/index.php?title=VertexColor or the one from this thread on the cylinder. Don't understand what does not work. Can it be my graphic card? I have a Macbook pro with a NVIDIA GeForce 9400M 256 Mo.
    cheers