Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

BindChannels: maximum two uv sets?

Discussion in 'Shaders' started by covert, Apr 9, 2013.

  1. covert

    covert

    Joined:
    Nov 29, 2012
    Posts:
    16
    Hey guys,

    I'm trying to make a shader that renders textures on a mesh using three uv sets.
    This is what I have so far, based off of Jessy Catterwaul's much appreciated ShaderLab documentation:

    (http://www.youtube.com/watch?v=xK-1uMYUYkc&list=UUqkCSwxg2LUkhM0-7M79c9Q)

    Code (csharp):
    1.  
    2. Shader "Multiple UV Sets" {
    3.  
    4.     Properties {
    5.         _FirstTex ("Base (RGB)", 2D) = ""
    6.         _SecondTex ("Second (RGB)", 2D) = ""
    7.         //_ThirdTex ("Third (RGB)", 2D) = ""
    8.     }
    9.  
    10.     Category
    11.     {
    12.         BindChannels {
    13.             Bind "vertex", vertex
    14.  
    15.             Bind "texcoord", texcoord0
    16.             Bind "texcoord1", texcoord1
    17.             //Bind "texcoord2", texcoord2
    18.         }
    19.  
    20.         SubShader {
    21.             Pass {
    22.                 SetTexture [_FirstTex]
    23.                 SetTexture [_SecondTex] { Combine texture Lerp(texture) previous }
    24.                 //SetTexture [_ThirdTex] { Combine texture Lerp(texture) previous }
    25.             }
    26.         }
    27.     }
    28. }
    29.  
    The above code works when using a mesh that has two uv sets,
    but when I try uncommenting for three uv sets, this line gives me an error:

    Code (csharp):
    1. Bind "texcoord2", texcoord2
    Could it be that Bind supports a maximum of two uv sets (either values "texcoord" or "texcoord1")?

    Thanks,
    Kim.
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Unity doesn't currently support more than 2 UV sets.

    --Eric
     
  3. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    And when it does, I bet there won't even be fixed function support for them.
     
  4. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    I think it's only fair to point out (in case anyone's holding their breath), that Unity has supported 2 UV sets for many years, and their response to people asking for more has always been "why?". Unless someone knows otherwise, I don't think it's very high on their list of priorities.
     
  5. covert

    covert

    Joined:
    Nov 29, 2012
    Posts:
    16
    Thanks for the quick follow-up. Looking back at our UV sets and the faces they map, we've decided to try and fit everything into two: a base plus a detail one. More UV sets could have been useful to describe other areas of details, but for now two really is enough.
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Technically it's possible to achieve the functionality of more than 2 UV sets by appropriating unused mesh data (say, mesh.colors if you're not using vertex colors) and packing UV data into that, and of course writing appropriate code in the shader to handle it.

    --Eric
     
  7. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    While this is true in theory, I think the precision and range limitations of vertex colours make it impractical to use them for UV data.
     
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Vertex colors are 4 floats, and UVs are 2 floats, so just use half of a vertex color, yes?

    --Eric
     
  9. Daniel_Brauer

    Daniel_Brauer

    Unity Technologies

    Joined:
    Aug 11, 2006
    Posts:
    3,355
    Although they can be read and interpolated as floating point values in for use in shader programs, the actual vertex colours are packed into 8 bits per channel.
     
  10. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    There's always tangents, if you're not using those....

    --Eric
     
  11. Ippokratis

    Ippokratis

    Joined:
    Oct 13, 2008
    Posts:
    1,521
    I *think (no prove available, sorry), that 3 uv sets is possible using the tangents channel.
    A small correction though, uv is not 2 floats. It is 4, because z and w are used to achieve tilling and offset.
    And, consuming the tangents channel means that you cannot use normal maps.
     
  12. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    664
    I am not quite sure about the w and z value, but UVs are always stored as float2, the other values wouldn't make any sense to me to be used per-vertex. Besides 3D UVW coords.
     
  13. Ippokratis

    Ippokratis

    Joined:
    Oct 13, 2008
    Posts:
    1,521
    The x and y components are set from mesh data.
    The z and w components are set from the engine via tile - offset properties and used in the vertex shader of the surface shaders.
     
  14. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    664
    Thought that, but wouldn't it then be possible to use this for the secound uv so we would came up with four uv sets? Assuming that the tiling and offset is 1 and 0.
     
  15. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    This is not true, and couldn't work. You can see what a surface shader does in the background, and what you need to do manually in other languages, by looking at the compiled shader's hideous auto-generated GLSL:

    Code (csharp):
    1. xlv_TEXCOORD0 = ((_glesMultiTexCoord0.xy * _MainTex_ST.xy) + _MainTex_ST.zw);
    Every texture gets its own tiling and offset vectors, as you can see in the Inspector for a Material. They don't all need their own UV channel. Not only would you not be able to store data for multiple textures in the .zw of a UV set, but two floats don't provide enough data for tiling and offset anyway. Tiling and offset are each a Vector2; you need a full Vector4 for them both. (So, _MainTex_ST should be called _MainTex_STPQ, but I don't care, because I never use those letters anyway.)

    Even though Unity does only allow you to store Vector2s, however, for your two UV sets, if you don't need 32-bit precision, then you could store, for example, two 16-bit sets in those bits, and decode that in your shaders. However, I've never seen a 3D app that had ready-made tools to export that for you.
     
    Last edited: Apr 13, 2013
  16. Ippokratis

    Ippokratis

    Joined:
    Oct 13, 2008
    Posts:
    1,521
    Hi Jessy,
    Thanks for the feedback. You are right.

    Here as some findings, for completeness :
    The http://docs.unity3d.com/Documentation/Manual/ShaderTut2.html describes a functional cg shader that handles offset and tile.
    [
    Code (csharp):
    1.  
    2.  
    3. Shader "Tutorial/Textured Colored"
    4. {
    5.  Properties
    6.  {
    7.     _Color ("Main Color", Color) = (1,1,1,0.5)
    8.     _MainTex ("Texture", 2D) = "white" { }
    9.  }
    10.  
    11.  SubShader
    12.  {
    13.    
    14.  Pass
    15.  {
    16.  
    17.  CGPROGRAM
    18.  #pragma vertex vert
    19.  #pragma fragment frag
    20.  #include "UnityCG.cginc"
    21.  
    22.  float4 _Color;
    23.  sampler2D _MainTex;
    24.  
    25.  struct v2f
    26.  {    
    27.   float4  pos :   SV_POSITION;    
    28.   float2  uv : TEXCOORD0;
    29.  };
    30.  
    31.  float4 _MainTex_ST;
    32.  
    33.  v2f vert (appdata_base v)
    34.  {    
    35.   v2f o;    
    36.   o.pos = mul (UNITY_MATRIX_MVP, v.vertex);    
    37.   o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);    
    38.   return o;
    39.  }
    40.  
    41.  half4 frag (v2f i) : COLOR
    42.  {    
    43.    half4 texcol = tex2D (_MainTex, i.uv);    return texcol * _Color;
    44.  }
    45.  
    46. ENDCG    
    47.  }
    48.  
    49.  }Fallback "VertexLit"
    50.  
    51. }
    So what happens here is that
    contains the tiling and offset parameters that are set in the inspector for the _MainTex texture. For each texture property, Unity offers such a float4 uniform with the ending “_ST”. This uniform holds the x and y components of the Tiling parameter in _MainTex_ST.x and _MainTex_ST.y, while the x and y components of the Offset parameter are stored in _MainTex_ST.w and _MainTex_ST.z

    TRANSFORM_TEX is a macro that lies inside the UnityCG.cginc, as follows :
    So the produced code will be

    What happens here is that texture coordinates are multiplied with the tiling parameters and the offset parameters are added.

    References :
    http://en.wikibooks.org/wiki/Cg_Programming/Unity/Textured_Spheres
    http://answers.unity3d.com/questions/33404/accessing-uv-offset-in-cg-shader.html

    Kind regards,
    -Ippokratis
     
    Last edited: Apr 14, 2013
  17. psantoki

    psantoki

    Joined:
    Oct 24, 2012
    Posts:
    17
    Terrain shader with atlasing + light map

    In this case standard mapping goes into TexCoord0, light mapping UV's go into TexCoord1, and atlasing goes into TexCoord2


     
  18. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    What's that?
     
  19. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    As in, a texture atlas (putting multiple textures into one texture).
     
  20. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    I know what an atlas is. What is being atlased? Why can't the terrain be in it?
     
  21. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    I know otherwise. More than 2 UV sets are quite close to hitting "trunk" codebase. So they are Fairly Close (tm).
     
  22. nerik

    nerik

    Joined:
    Nov 8, 2011
    Posts:
    22
    Hi Aras,

    I'm currently running into an issue importing a mesh with 3 UV channels, and let's just say that editing the artist's model is problematic...
    Any idea what "Fairly Close (tm)" could mean in practical ? :) (the deadline for the project I'm working on is 2 weeks)

    Also, is that solution on Unity Answers possibly valid?
    http://answers.unity3d.com/questions/214842/can-you-use-3-or-more-uv-sets.html

    Thanks !

    Erik
     
  23. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Certainly not in two weeks; and certainly not in Unity 4.2 (which isn't out yet). So best case scenario is Unity 4.3 (which is at least several months away).[/quote]


    No. Well the shader is fine, but you'll have no way of putting the actual 3rd UV set into the Mesh.
     
  24. nerik

    nerik

    Joined:
    Nov 8, 2011
    Posts:
    22
    Aight. Thanks!
     
  25. lcambiaghi

    lcambiaghi

    Joined:
    Sep 27, 2012
    Posts:
    41
    Any news about having more than 2 uvs on a mesh?
     
  26. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Will be in 5.0. But hey, I made broken promises in the past...
     
  27. Ippokratis

    Ippokratis

    Joined:
    Oct 13, 2008
    Posts:
    1,521
    4 of them !!! :)
    -Closed Unity 5 beta-
     
    maart likes this.
  28. lcambiaghi

    lcambiaghi

    Joined:
    Sep 27, 2012
    Posts:
    41
    4 could be enought....for now :p
     
  29. noetic_wxb

    noetic_wxb

    Joined:
    Mar 4, 2015
    Posts:
    5
    not work in Unity 2017.2.0f3 (64-bit) . Editor is ok. but in mobile device, failed.

    struct appdata
    {
    fixed4 vertex : POSITION;
    fixed2 uv : TEXCOORD0;
    };

    struct v2f
    {
    fixed2 uv0 : TEXCOORD0;
    fixed2 uv1 : TEXCOORD1;
    fixed2 uv2 : TEXCOORD2;
    fixed4 vertex : SV_POSITION;
    };

    sampler2D _MainTex;
    sampler2D _AlphaTex;
    fixed4 _MainTex_ST;

    v2f vert(appdata v)
    {
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.uv0 = TRANSFORM_TEX(v.uv, _MainTex);
    o.uv1 = v.uv;
    o.uv2 = v.uv;
    return o;
    }

    fixed4 frag(v2f i) : SV_Target
    {
    // sample the texture
    fixed4 col = tex2D(_MainTex, i.uv0);
    col.a = tex2D(_AlphaTex, i.uv1).a;
    col.a *= tex2D(_AlphaTex, i.uv2).a;
    return col ;
    }
     
  30. leci

    leci

    Joined:
    Nov 19, 2012
    Posts:
    8
    Didn't tink about it until recently, but...

    ¿Shouldn't be possible to generate other uv sets "manually" (a.k.a. by code) then pass them to a shader that would replace your 2nd UV with the new one?

    Another doubt about is, ¿What would be a good practical use for more than 2 uv sets, knowing that we can unwrap meshes completely in the 2nd set for everything (AO, Lightmaps, Gloss, Dirty, Specular, Normal, etc) ?

    I can only think about the typical case of a Terrain, honestly... But for characters?