Search Unity

Interpolation of Vertex Data

Discussion in 'Shaders' started by Plutoman, Dec 13, 2014.

  1. Plutoman

    Plutoman

    Joined:
    May 24, 2013
    Posts:
    257
    I've been searching around for information on this with no success. Unlike other threads, I'm not trying to stop interpolation. However, what I am trying to get - is consistent interpolation.

    I've noticed that, when assigning the same data, the UV and UV1, the tangents, and the color channel, the values are all interpolated differently when interpreted in the surface shader.

    Here I provide data to the mesh; I deliberately have given them the same info for testing.
    Code (CSharp):
    1.  
    2. if (colors != null && colorCounter == verticeCounter)
    3. {
    4.        mesh.colors = colors.ToArray<Color>(colorCounter); //resizes from static array (used to avoid GC)
    5.        mesh.tangents = colors.ToArray(colorCounter); //converts colors to vector4's
    6.        mesh.uv1 = colors.ToArray(colorCounter, false); //takes the latter two values from the color array
    7.        mesh.uv = colors.ToArray(colorCounter, true); //takes the front two values from the color array
    8. }
    9.  
    Code (CSharp):
    1.  
    2. struct Input
    3. {
    4.        //...
    5.        float4 colors;
    6.        // ....
    7. };
    8.  
    9. void vert (inout appdata_full v, out Input o)
    10. {
    11.        //grabs  from UV coordinates
    12.     o.colors.xy = v.texcoord.xy;
    13.     o.colors.zw = v.texcoord1.xy;
    14.  
    15.        //grabs from vertex color
    16.     o.colors.xyzw = v.color.xyzw;
    17.  
    18.        //grabs from tangents
    19.     o.colors.xyzw = v.tangent.xyzw;
    20. }
    21. void surf (Input IN, inout SurfaceOutput o)
    22. {
    23.        //.....
    24.        fixed4 tex;
    25.        tex.xyzw = IN.colors.xyzw;
    26.        o.Albedo = tex.rgb;
    27.        //.....
    28. }
    29.  
    The color set results in an even interpolation;
    https://www.dropbox.com/s/g01ggyqehj4uxek/Screenshot 2014-12-12 22.48.20.png?dl=0

    The UV and tangents sets result in an odd interpolation, far different from the color channels...
    UV's: https://www.dropbox.com/s/mhpamaklboo3g6c/Screenshot 2014-12-12 22.47.40.png?dl=0
    Tangents: https://www.dropbox.com/s/iqeom4mpg4759mj/Screenshot 2014-12-12 22.47.08.png?dl=0

    The UV set is fairly close, but still off.

    I'm essentially using a tri-planar shader and blending between multiple textures. I calculate the tangents, and UV's are based upon world position. I'd like to use these color channels for additional blends, but with the interpolation being incorrect, that is nearly impossible.

    Does anyone know the reason for this, and potentially, have additional ideas on how to blend multiple texture sets and information?
     
  2. GGeff

    GGeff

    Joined:
    Nov 11, 2014
    Posts:
    40
    If you want two things to interpolate the same thing then just label them the same, ie in your v2f structure just make them all TEXTURE0, TEXTURE1 etc or COLOR0, COLOR1 etc

    Example in your case:

    struct Input
    {
    float4 colors : TEXTURE0;
    float4 uvs : TEXTURE1;
    ...
    }
     
  3. Plutoman

    Plutoman

    Joined:
    May 24, 2013
    Posts:
    257
    That's separate; this is with the same data.

    In each case, I'm using the same structure (and commenting the others out). As in, I take the float4 and fill it with information from the tangents, or I fill with information from the two sets of UV's, or I fill with data from the vertex colors. The vert(..) method would only have one set grabbed at a time. If they blended the same, I would have multiple sets brought down into the surf, but this is the same float4 array, filled from different sources, getting different end results, with the different sources that should be identical.

    In each case, the results end up different. They're close enough that I don't see Unity as messing with the tangents or UV's (I could be wrong?), but yet it ends up different enough that it is nigh unusable.

    On another note, marking float4 tangents : COLOR; breaks the whole thing and always ends up pure black.

    Edit:

    After some testing, using

    float4 color : COLOR;

    And then assigning any different values into that (from the tangents or the UV's) works fine, but adding anything else marked as a COLOR, or even renaming it, breaks it. Using any other values ends up with the same problem as above. I need more than 4 textures available; it would be extraordinarily limiting to only be able to blend 4 textures, and due to the scale of the procedural generation, a splat map is also not appropriate.

    For each 1x1 section in Unity, on the images, it is a mesh that is tiled based upon world positioning. Adding a splat map for every 1x1 section (which can all blend in different ways - it is procedural) would kill memory.
     
    Last edited: Dec 13, 2014
  4. cician

    cician

    Joined:
    Dec 10, 2012
    Posts:
    233
    Just throwing some ideas to try:
    - If you're saving the mesh as opposed to constructing at runtime disable mesh optimization and compression on it.
    - Try disabling batching to check if it's meddling with things. See http://forum.unity3d.com/threads/passing-extra-vertex-data-to-a-shader.190448/
    - Since I didn't use much with vertex colors in Unity yet, I'm not sure if that may be the case, but try switching between linear and gamma (requires pro) to see if that makes a difference.
     
  5. Plutoman

    Plutoman

    Joined:
    May 24, 2013
    Posts:
    257
    Run-time generation, so no optimization or cression. I just disabled the dynamic batching, but it didn't do anything; I imagine since my meshes are all resized.

    The linear and gamma definitely changes it, but there's still a difference; in that linear is a far smoother, longer, transition, whereas gamma is harder (makes sense), but there's still the drastic difference between the two sets of normals.

    I made a few small changes to my internal algorithm that assigns color data; there were a few cases where negative numbers had been assigned to the colors. This fixed the UV, UV1 channels, and those are now identical to the Color channels.

    Now I have two identical ones, yet the tangents are still different. However, in this situation, under linear lighting, the tangents may be usable as they at least blend now, just at a sharper rate.

    Is there any reason the tangents data would be changed, scaled, be messed up, in any circumstances?

    Edit: As I wrote this, I continued testing...

    If I normalize a the v.color.xyz, or the uv values, the colors change. However, if I normalize the incoming tangent vector, it is not. Could the tangents be auto-normalized by unity?

    Edit #2: This appears to be my answer. The tangents are all auto-normalized, however, adding the noted #pragma glsl_no_auto_normalization does not affect anything. The tangents are still normalized.
     
    Last edited: Dec 13, 2014
  6. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    I'm sorry that I don't have an answer about the tangents' normalization, but I'll be watching this thread to see if anyone has that answer. Thanks for exploring.

    However, I noticed your variable name "verticeCounter". Vertice is not a word. My main team has taken the John Carmack approach of saying vertexes instead of vertices to keep this simpler.
     
  7. Plutoman

    Plutoman

    Joined:
    May 24, 2013
    Posts:
    257
    Hah, good catch. I'll refactor that. That would make sense.

    I may be able to do some clever swapping, in that, with the color channels and the UV channels, I have 8 channels available. Since the meshes are no larger than 1x1 individually (or close enough, since it's a MC/DC algo at the heart), I will not really be able to blend more than 5-6 textures into one place, so if I do some checks to see when smoothing has opened up a channel (ie, when my normalization lowers a value below a certain margin) I can swap in new textures.

    The idea behind it is a dungeon-crawler, procedural, w/ themes.. so the themes need blending where they collide together (tomb's bricks to a cave's stone), and then additional detail textures over the top (ie, grass on dirt, dirt on stone, more outlandish options for other themes), and lake beds, that sort of stuff.

    I'm going to take a dig through the Unity include next to see if I can get those 4 channels. Otherwise, I'll see how it works to pack more data into the UV's floats, since the color is only 4 bytes.