I’m woking on UI shaders and noticed that the uvs I get from a simple image as input differ from the ones from a 9-sliced image. This totally makes sense, but I wasn’t expecting it. I’m wondering if there is a way to still get the simple uv data in the shader.
Comparison:
Nope, I didn’t need it in the end. But from working quite a bit on ui shaders,I recommend checking out MeshModifiers: https://docs.unity3d.com/ScriptReference/UI.BaseMeshEffect.html
With those you should be easily able to do what you want to do (e.g. put the original uv information in the vertex color).
Unity’s 9 slice UI elements work by actually slicing the mesh into 9 quads, so it’s a mesh with 16 vertices, not 4, hence why this isn’t solvable by applying a shader to a sprite already set to use the built in 9-slice support. It’ll also break on any atlased sprite as their UVs are not necessarily in a 0.0 to 1.0 range, so that 0.5 test won’t work there either.
Yeah, as I played around with it more I discovered it’s a truly flimsy solution. :-/
Seems like there should be an easier way to do this…
I guess one way would be to calculate bottom-left, top-right vertex in CS, then set those values on the material and use them to infer the UV in the vertex shader.
As already pointed out, ui elements have a very nice base class with which you can do all kind of magic without the need of setting material properties
Here’s one that works for me
Just make sure in the shader you are looking at vertex color channel Red instead of U coordinates.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Pool;
using UnityEngine.UI;
public class ImageSliceWithUV : BaseMeshEffect
{
protected ImageSliceWithUV()
{}
public override void ModifyMesh(VertexHelper vh)
{
List<UIVertex> verts = new List<UIVertex>();
vh.GetUIVertexStream(verts);
var orderedVerts = verts.OrderBy(v => v.position.x).ToList();
var minX = orderedVerts.First().position.x;
var maxX = orderedVerts.Last().position.x;
for (int i = 0; i < verts.Count; i++)
{
UIVertex vertex = verts[i];
Vector3 position = vertex.position;
vertex.color.r = (byte)(Mathf.InverseLerp(minX, maxX, position.x) * 255);
verts[i] = vertex;
}
vh.Clear();
vh.AddUIVertexTriangleStream(verts);
}
}