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): Shader "Multiple UV Sets" { Properties { _FirstTex ("Base (RGB)", 2D) = "" _SecondTex ("Second (RGB)", 2D) = "" //_ThirdTex ("Third (RGB)", 2D) = "" } Category { BindChannels { Bind "vertex", vertex Bind "texcoord", texcoord0 Bind "texcoord1", texcoord1 //Bind "texcoord2", texcoord2 } SubShader { Pass { SetTexture [_FirstTex] SetTexture [_SecondTex] { Combine texture Lerp(texture) previous } //SetTexture [_ThirdTex] { Combine texture Lerp(texture) previous } } } } } 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): Bind "texcoord2", texcoord2 Could it be that Bind supports a maximum of two uv sets (either values "texcoord" or "texcoord1")? Thanks, Kim.
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.
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.
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
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.
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.
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.
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.
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.
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.
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): 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.
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): Shader "Tutorial/Textured Colored" { Properties { _Color ("Main Color", Color) = (1,1,1,0.5) _MainTex ("Texture", 2D) = "white" { } } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" float4 _Color; sampler2D _MainTex; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; }; float4 _MainTex_ST; v2f vert (appdata_base v) { v2f o; o.pos = mul (UNITY_MATRIX_MVP, v.vertex); o.uv = TRANSFORM_TEX (v.texcoord, _MainTex); return o; } half4 frag (v2f i) : COLOR { half4 texcol = tex2D (_MainTex, i.uv); return texcol * _Color; } ENDCG } }Fallback "VertexLit" } 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
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
I know otherwise. More than 2 UV sets are quite close to hitting "trunk" codebase. So they are Fairly Close (tm).
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
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.
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 ; }
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?