Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  4. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Important information regarding Mesh UV channels

Discussion in 'Documentation' started by Phong, Nov 29, 2015.

  1. Phong

    Phong

    Joined:
    Apr 12, 2010
    Posts:
    1,377
    The naming of UV sets in the official documentation is inconsistant, missleading, incorrect and incomplete. I would propose the following changes. Based on the information provided by Unity employees in the thread http://forum.unity3d.com/threads/quick-setup-for-starting-enlighten.309609/#post-2400531.

    1) In the Mesh page page http://docs.unity3d.com/ScriptReference/Mesh.html.
    • Mention that UV2 is used for realtime lightmapping but NOT baked lightmapping so don't try to use it for anything else if using any GI.
    • Mention that UV1 exists but it is not readable nor writable and that it is used for baked lightmapping. This is very important information. The API says that this channel is depricated which suggests it is not used anymore and does not exist. It does exist and is used for baked lightmaps. Without this information a developer could literally spend weeks trying to work with UV2 and baked lightmaps and have not idea why nothing is working.
    • The docs say that UV2 is the "second" UV set. This is not correct. It is the "third" UV set. The existing language suggests that there is no UV1 which leads developers to a false assumption and weeks of lost development time. Please NEVER refer to to uvs as "first", "second", "third" etc.. Please ALWAYS use uv, uv1, uv2, uv3, uv4.
    2) Unrwapping.GenerateSecondaryUV set does this generate a UV1 channel? I think it must because I can create baked lightmaps on procedural meshes after I call this. Please mention this.

    3) Renderer page please mention that Renderer.lightmapScaleOffset uses the UV1 channel. I have been wondering for months what mysterious set of lightmap UVs these correspond to. Also mention that Renderer.realtimeLightmapScaleOffset uses the UV2 channel.

    3) In the manual please mention that Unity uses different UV sets for realtime GI and baked GI. Please include the information in this document https://goo.gl/bHsCyq in the manual. There is not enough detail about GI in the regular manual. This is the best information on GI in unity I have seen so far and would have saved me weeks of development time.

    The inspector for the standard shader uses:



    Please name the UV sets correctly as UV3 and UV4. If a developer interprets the names in the inspector literally then they will waste many hours of development time.
     
  2. Laurakh

    Laurakh

    Unity Technologies

    Joined:
    Sep 29, 2015
    Posts:
    6
    Thank you for letting us know and giving us lots of suggestions; this is always helpful. We're investigating this and will make any updates as soon as we can. [Laura - Unity Docs Team]
     
    Last edited: Nov 30, 2015
    ModLunar and hopeful like this.
  3. sfjohansson

    sfjohansson

    Joined:
    Mar 12, 2013
    Posts:
    264
    Good Suggestion... unless a typo... don't use "uv" only for first set...extend the indexing also to that set and use "uv0"
     
    ModLunar, Zaelot, Zyl and 1 other person like this.
  4. duck

    duck

    Unity Technologies

    Joined:
    Oct 21, 2008
    Posts:
    356
    Ok, the problem here is that the docs appear to be inconsistent, but the real problem is that the C# Mesh class API and the Shader Code API are inconsistent with each other when referring to the UV sets. For this reason, in contrast to your advice, I would say the only unambiguous way to refer to a UV set is to use the ordinal form, "first", "second", etc. So, "uv1" isn't hidden or secret, or not readable/writable. It's just that the mesh property names are uv, uv2, uv3 & uv4, and so are not "zero indexed", whereas in the shader code API, the variables go from UV0 to UV3 and are zero indexed. So, there are 4 UV channels supported, and you can access them all.

    Hopefully this table should make it clear:

    0e01a43076bdb73743107d9638cee198a03095fcce.png
    (seems table bbcode isn't supported, so this is an image!)

    So what happened to mesh.uv1 ?

    In older versions of unity, the Mesh class used to only have 2 UV channels. These were referred to as mesh.uv and mesh.uv1. However, Unity introduced support for 2 more UV channels (now 4 in total), and changed the naming on the mesh class so the names were now .uv .uv2 .uv3 & .uv4.

    The old mesh property mesh.uv1 is now obsolete, and used to point to the 2nd UV layer. Old code that contains this property will be converted by the API auto updater to mesh.uv2.
     
    hopeful likes this.
  5. duck

    duck

    Unity Technologies

    Joined:
    Oct 21, 2008
    Posts:
    356
    That said, I'm going to make sure the documentation is improved where appropriate so that the docs are crystal clear on these despite the 2 Apis being different to each other. :)
     
  6. Phong

    Phong

    Joined:
    Apr 12, 2010
    Posts:
    1,377
    Hi Duck,

    Thanks for the fast response and for looking into this. I have a correction to make in your table.

    Mesh.uv3 is NOT used for Realtime GI data. It goes like this:

    uv Diffuse, Metal/Spec etc...
    uv1 (not readable, or writable) Used for Baked GI
    uv2 Used for realtime GI
    uv3 Whatever you want (can optionally be used for detail maps)
    uv4 Whatever you want (can optimally be used for detail maps)

    Mesh.uv1 is used internally by the GI system. It used to be read/writable in Unity 4 but has been hidden in Unity 5. This is a huge source of confusion for developers. It is important that you document that it exists so that users can understand when looking at the charts in the lighting window that they can be looking at either the UV1 chart or the UV2 chart. This doc explains it very well: https://goo.gl/bHsCyq

    This thread also has a lot of good information. http://forum.unity3d.com/threads/quick-setup-for-starting-enlighten.309609/#post-2400531.
     
  7. Phong

    Phong

    Joined:
    Apr 12, 2010
    Posts:
    1,377
    THIS IS NOT CORRECT!!!! PLEASE!! PLEASE!! PLEASE!! CORRECT THIS!!

    I CANNOT EMPHASIZE THIS ENOUGH!!!!!

    THIS IS TERRIBLE MISINFORMATION! A DEVELOPER WHO BELIEVES THIS IS ABOUT TO EMBARK ON A LONG, MISERABLE, UNPLEASANT, FRUSTRATING CODE JOURNEY.

    PLEASE, PLEASE, PLEASE READ THIS DOCUMENT WRITTEN BY UNITY DEVELOPERS WORKING ON GI WHICH EXPLAINS THAT mesh.uv1 IS STILL BEING USED BUT IS NOT READABLE OR WRITABLE. https://goo.gl/bHsCyq





     
  8. superpig

    superpig

    Quis aedificabit ipsos aedificatores? Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,063
    This is the implementation of Mesh.uv1:

    Code (csharp):
    1.  
    2. [Obsolete("Property Mesh.uv1 has been deprecated. Use Mesh.uv2 instead (UnityUpgradable)->uv2", true)]
    3. public Vector2[] uv1 { get { return null; } set { } }
    4.  
    You can see this for yourself if you disassemble UnityEngine.dll.

    The references to UV sets in the doc from the GI team are using 'shader-style' numbering (i.e. UV0, UV1, UV2, UV3) rather than scripting-style numbering (.uv, .uv2, .uv3, .uv4). When they talk about UV1, they're referring to the UV set accessed through script as .uv2.
     
  9. duck

    duck

    Unity Technologies

    Joined:
    Oct 21, 2008
    Posts:
    356
    Phong, your information is wrong. Please re-read my post, and what it says about the uv1 property of the Mesh class. There are only 4 UV channels. I think the reason you're confused is that the google doc you're referring to is referring to the UV channels by their Shader Code variable names. so UV0, UV1, UV2, UV3.

    The Mesh class refers to these same 4 UV channels as: Mesh.uv, Mesh.uv2, Mesh.uv3 & Mesh.uv4

    There is no UV channel that isn't read/writable.
     
  10. Phong

    Phong

    Joined:
    Apr 12, 2010
    Posts:
    1,377
  11. duck

    duck

    Unity Technologies

    Joined:
    Oct 21, 2008
    Posts:
    356
    I don't know whether you noticed, but both SuperPig & I also work at Unity, and we are very familiar with how Unity's UV channels work. We do actually know what we're talking about. I'm asking you to have a look at the table I made again.



    Notice that the Shader Variable Names and the Mesh Class property names differ, even though they point to the same UV channel. Your confusion is that you're not understanding the difference between the Shader Variable Names (as used in Kasper's google doc) and the Mesh Class property names (which omit uv1, and instead use .uv, uv2, uv3, uv4 to refer to the 4 UV channels).

    I have asked Kasper and Jesper to comment on this thread.
     
    Last edited: Nov 30, 2015
    antoripa likes this.
  12. duck

    duck

    Unity Technologies

    Joined:
    Oct 21, 2008
    Posts:
    356
    Perhaps you could tell us exactly what you are trying to do, or what you are actually seeing (as a result of your code) which leads you to your conclusion?
     
  13. mtalbott

    mtalbott

    Joined:
    Dec 21, 2011
    Posts:
    91
    I just want to say that this has been very entertaining... and informative. I too have struggled with the naming convention on the C# Mesh side and on the shader side.

    Would it be too disruptive now to rename the Mesh class properties to uv0, uv1, uv2, and uv3? While it would probably break a lot of scripts, it would go a long way to avoid this whole misunderstanding. Maybe your script upgrader could rename everyones Mesh.uvX to Mesh.uvX-1?

    While we're talking Mesh/UV documentation/confusion, I'd like to add a recent discovery of mine. While the new GUI system now accepts Meshes, any information in Mesh.uv3 and Mesh.uv4 is stripped out. While GUI's probably don't need the extra UV's for GI stuff, I am trying to get some extra data to a Vertex Shader Program and was disappointed to find the uv channels empty in the shader.

    Thanks @duck and @superpig for your help and attention.
     
  14. Phong

    Phong

    Joined:
    Apr 12, 2010
    Posts:
    1,377
    Hi Duck,

    I must say I am confused and do hope you are right. I am very puzzled however. If I am using a mix of baked and realtime lightmapping and I import a mesh and check the "Generate Lightmap UVs". Nothing is generated on the mesh.uv3 channel.

    Debug.Log(myMesh.uv3.Length)

    Prints "0". If I print this at runtime it still returns zero. However my object is realtime lightmapped so what UV channel is it using?

    Also, if I add a third set of UVs to my object and add a detail map to my object telling it to use uv3 for the detail map, then the object still works with realtime lightmapping. So how can the GI system be using uv3 for realtime lightmapping?
     
  15. duck

    duck

    Unity Technologies

    Joined:
    Oct 21, 2008
    Posts:
    356
    The realtime GI data is using the third UV channel (which is Mesh.uv3 in c#, & UV2 in shader code).

    However, you can't read that realtime GI data in your c# script - which may be partly the source of your confusion.

    This is because the realtime lightmapping data isn't provided back to you via the mesh class, because each instance of that mesh has different UV values for the realtime GI data, and this GI data is applied at a later stage in the rendering pipeline.

    What you have access to using the Mesh class API is the original mesh data, before it has had the realtime GI data applied to it. The realtime GI UVs are applied by the lighting system to the mesh as part of the rendering pipeline, while the mesh data is on its way to the GPU.

    So if your original mesh data (as exported from your 3D app) didn't have data in the 3rd UV channel, your script will return zero length for that channel. If you did export data in this channel from your 3d app, it will return your original data, and this data will be overwritten by realtime GI data during rendering. So if you try to read data from the 3rd UV channel in shader code, you'll get the GI realtime data, since this code will operate on the GPU and therefore is reading the data after the realtime lighting has been applied to each instance of this mesh.


    If your detail map UVs are in the 3rd UV layer, they'll be overwritten by realtime GI data (if you're using realtime GI).

    However the current standard shader only allows you to choose from the 1st or 2nd UV layer (which it calls UV0 and UV1 because it's using Shader Code terminology). So if you wanted to use the 3rd or 4th UV layer, you'd need to write a custom version of the standard shader.

    And if you wanted custom detail mapping, and baked lightmaps & realtime GI, your only option is to use the 4th UV channel (referred to as UV3 in shader code), since the first 3 are used for Albedo, Baked, & Realtime lighting respectively.
     
    twobob and Zaelot like this.
  16. Phong

    Phong

    Joined:
    Apr 12, 2010
    Posts:
    1,377
    Thank you so much for this information Duck each time I get some nuggets of information like this it is like finding gold! (I re-read this about six times).:)

    Yes I was being mislead by the fact that I can read from the mesh.uv3 channel and receive a zero length array but the channel has data! This is VERY misleading and needs to be documented. What happens if I write to it at runtime?

    Interesting about the detail maps I thought that this was working but now that I test it I see that the detail map does look funny.

    The project that led to all of this was trying to combine meshes preserving a lightmap bake. This used to work in Unity 4. I could read all the source mesh.uv2 channels combine them and write them to a combined mesh uv2 channel. I would need to adjust the renderer.lightmapScaleOffset so that it would encapsulate the lightmapScaleAndOffset of all the source objects and adjust the UV2 values to fit the new lightmapScaleAndOffset. This works for meshes that all share the same lightmap In Unity 4. It doen'st work in Unity 5.

    Does reading from the UV2 channel also report non-repacked UVs when read from? That would explain why this doesn't work.
     
    twobob likes this.
  17. Phong

    Phong

    Joined:
    Apr 12, 2010
    Posts:
    1,377
    I don't think I have ever rambled this much on a forum thread but there is another point beyond the difference between the shader naming and mesh naming that NEEDs to be documented.

    Based on Duck's explanation there ARE two hidden non-readable, non-writable uv channels in the mesh class. The repacked baked UVs and the repacked realtime UVs exist, and are used by the GI system. Any developer who thinks they can get this data by reading it from mesh.uv2 and mesh.uv3 is in for a miserable time.
     
  18. duck

    duck

    Unity Technologies

    Joined:
    Oct 21, 2008
    Posts:
    356
    They exist, but not in separate hidden channels. They use the 2nd and 3rd channels respectively. If they used separate hidden channels, any data you put into those channels initially (via your 3D authoring app) would be preserved. But it isn't - it's overwritten at runtime in a way that means if you try to read it in shader code, you'll get the baked & realtime uv data instead of your original data. So there aren't separate channels, but they may contain different data than you might have been expecting depending on how and where you try to read that information. (I'm going to try to find time to make a test project to demonstrate this.)
     
    twobob likes this.
  19. Phong

    Phong

    Joined:
    Apr 12, 2010
    Posts:
    1,377
    O.K. Just so I am clear on this, does it work like this?:
    • read from C# code mesh.uv2 at runtime get your original data back
    • read from 2nd channel in shader code get a repacked version of mesh.uv2
    • read from C# code mesh.uv3 at runtime get your original data back
    • read from 3rd channel in shader code get the repacked version of mesh.uv3
    Also one more question I have from all this is when does the UV repack occur for the realtime UVs. If I create a procedural mesh at runtime, are the UVs repacked on demand? On mesh creation? Is it when the UVs are assigned to the mesh? If it happens when UVs are assigned to the mesh then the order channels are assigned must matter beacuase:

    myMesh.uv3 = myUV3layout;
    myMesh.uv2 = myUV2layout;
    myMesh.uv = myUVLayout;

    The realtime lightmap UVs will be repacked once because uv3 takes precedence over uv and uv2. However if I assign in this order:

    myMesh.uv = myUV3layout;
    myMesh.uv2 = myUV2layout;
    myMesh.uv3 = myUVLayout;

    Then the repack will be triggered three times because each time I am assigning a channel with higher precedence. Is this a correct assumption I am making?
     
  20. superpig

    superpig

    Quis aedificabit ipsos aedificatores? Unity Technologies

    Joined:
    Jan 16, 2011
    Posts:
    4,063
    @Phong I think the vital piece you're missing is MeshRenderer.additionalVertexStreams.

    Much like lightmapTilingOffset in Unity 4, the lightmapping information for each renderer is unique, but - with realtime GI, at least - rather than it just being a scale and offset value, it's an entire new set of UVs. I can't remember offhand whether these extra UVs are actually available via MeshRenderer.additionalVertexStreams, but it's the same principle - a set of UVs are stored per-MeshRenderer which override the third UV channel when the data is actually passed to the GPU.
     
    twobob and hopeful like this.
  21. Phong

    Phong

    Joined:
    Apr 12, 2010
    Posts:
    1,377
    Ahhh! Thanks superpig! Another gold nugget! :)
     
  22. KEngelstoft

    KEngelstoft

    Unity Technologies

    Joined:
    Aug 13, 2013
    Posts:
    896
    Nice table @duck, did you copy it from the 5.3 docs :) This is exactly how it works but I agree the off by one difference between shader channels and C# API is confusing.
     
    twobob likes this.
  23. Tobias-Pott

    Tobias-Pott

    Joined:
    Aug 26, 2014
    Posts:
    7
    Actually, i had a hard time finding this information (Duck's table) to solve an issue I had with a custom shader utilizing UV channel 3 which got broken after realtime GI precomputation.

    But still I'm a bit confused what happens to the 2nd channel and which channels are used with specific options set on an object. In the "Lighting - Object" tab we have a "Preserve UVs" checkbox which tooltip says it would preserve the "lightmap uvs when generatnig realtime GI UVs". referring to the discussion above and the confusion about the exact use of words I wonder if the tooltip refers to the "Second" channel (marked as used by baked lightmaps) or the "Third". Or does it simply take whatever is available (and prioritize the third over the second).

    Back to the table and the information, it would be awesome to have that table inside the docs and not only at the mesh api (as description to the respective uv, uv2, uv3, uv4 members) and the manual for the mesh data structure (e.g. there as a hint of the uv different usages) but also somewhere in the shader manuals for providing data to own shaders and the lighting/GI manual (e.g. what uvs are used for which part of the GI solution)

    Gave me quite a headache, wrapping my mind around this, as only the parts with the custom shader got broken after precomputation and I started to ponder over weird solutions with duplicate objects and alpha or cutout shaders giving me a slight feeling of working around in a quick & dirty manner.
     
  24. Phong

    Phong

    Joined:
    Apr 12, 2010
    Posts:
    1,377
    Hi Tobias, did you find this document https://goo.gl/bHsCyq ? It was a big help for me understanding how this works.
     
    twobob likes this.
  25. LeagueOfMonkeys

    LeagueOfMonkeys

    Joined:
    Aug 13, 2012
    Posts:
    18
    lol
     
  26. LeagueOfMonkeys

    LeagueOfMonkeys

    Joined:
    Aug 13, 2012
    Posts:
    18
    I am completely confused AF !

    All this is explaining to me why my uv2 (out of 3DSMax is being destroyed at runtime). If uv2 is a dedicated channel set side for Baking why does the secondary map for a standard sharder only offer uv0 and uv1 (mesh uv and mesh uv2).

    All this is what Phong is talking about - maybe pop up dialogs should appear warning the developer of potential conflicts and restrictions when using specific uvs.
     

    Attached Files:

    JamesArndt likes this.
  27. White-Cat

    White-Cat

    Joined:
    May 3, 2015
    Posts:
    2
    Hi, I'm trying to write custom standard shader now, and find this in UnityStandardCore.cginc:
    Code (CSharp):
    1. VertexOutputForwardBase vertForwardBase (VertexInput v)
    2. {
    3.     // ...
    4.     o.tex = TexCoords(v);
    5.     // ...
    6.     UNITY_TRANSFER_SHADOW(o, v.uv1);
    7. }
    The TexCoords uses v.uv1 for detail map, and UNITY_TRANSFER_SHADOW uses v.uv1 for baked lightmap, how can v.uv1 be used for different purpose?
     
  28. mazenn25

    mazenn25

    Joined:
    Yesterday
    Posts:
    2
    Thank you for letting us know and giving us lots of suggestions; this is always helpful. We're investigating this and will make any updates as soon as we can

    This is because the realtime lightmapping data isn't provided back to you via the mesh class, because each instance of that mesh has different UV values for the realtime GI data, and this GI data is applied at a later stage in the rendering pipeline.