Nrjwolf / unity-shader-sprite-radial-fill

Radial fill mask for sprite
174 stars 28 forks source link

Atlas Support #3

Open Reahreic opened 2 years ago

Reahreic commented 2 years ago

The current solution doesn't support sprites that are part of an atlas. AFAIK there's no shader-only way to resolve this, but the following will at least enable atlas sprite support.

Add a component to the SpriteRenderer, that sends the sprite's uv space Rect to the material. This can be triggered myltiple ways, with the easiest on Awake.

//Calculates the sprite's position in the atlas (in uv space) and sends that data to the material.
void PopulateAtlasInfo() {
      SpriteRenderer rend = GetComponent<SpriteRenderer>();
      Rect sprite = rend.sprite.textureRect;

      Vector4 spriteData = new Vector4(
            sprite.x / rend.sprite.texture.width,
            sprite.y / rend.sprite.texture.height,
            sprite.width / rend.sprite.texture.width,
            sprite.height / rend.sprite.texture.height
      );

      rend.material.SetVector("_SpriteData", spriteData);
}

Next, add a property to the shader to hold the sprite data. _SpriteData("X, Y, Width, Height", Vector) = (1, 1, 1, 1)

Lastly, in the frag function after you sample the sprite calculate your (x,y) uv's for the atan using the sprite data.

//Convert UV coordinate space to cartesian coordinate space (0;1) to (-1;1) While taking into account the sprite's position in the texture and centering it around the cartesian origin.
float x = lerp(-1, 1, (IN.uv0.x - _SpriteData.x) / _SpriteData.z);
float y = lerp(-1, 1, (IN.uv0.y - _SpriteData.y) / _SpriteData.w);

//Calculate angle, convert to degrees
float angle = atan2(x, y) * 57.2958;