BindChannels: maximum two uv sets?

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)

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:

Bind "texcoord2", texcoord2

Could it be that Bind supports a maximum of two uv sets (either values “texcoord” or “texcoord1”)?

Thanks,
Kim.

Unity doesn’t currently support more than 2 UV sets.

–Eric

And when it does, I bet there won’t even be fixed function support for them.

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.

Vertex colors are 4 floats, and UVs are 2 floats, so just use half of a vertex color, yes?

–Eric

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.

There’s always tangents, if you’re not using those…

–Eric

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:

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](http://Hi Jessy, Thanks for the feedback. I recently had the chance to dive into surface shaders - they are surprisingly flexible btw - so here as some findings : The http://docs.unity3d.com/Documentation/Manual/ShaderTut2.html) describes a functional cg shader that handles offset and tile.
[

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

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

What’s that?

As in, a texture atlas (putting multiple textures into one texture).

I know what an atlas is. What is being atlased? Why can’t the terrain be in it?