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:
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.
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:
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.
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.