Search Unity

Which variable is changing in shader when animation is looping through sliced sprites?

Discussion in 'Shaders' started by milanhenkrich, Sep 22, 2019.

  1. milanhenkrich

    milanhenkrich

    Joined:
    Jul 26, 2018
    Posts:
    31
    Hey Guys.

    I spent hours trying to figure out this one.

    So: I have animation of character- one sprite consisting of 6 sliced sprites. Sprite mode is set to multiple. I am playing animation where I am looping through sliced sprites.

    Now: I have shader where I would like to apply different effect based on current sliced sprit.

    In other words, could I somehow detect in shader which sliced sprite is currently showed?

    Or

    Which variable is changing in shader when animation is looping through sliced sprites?

    Thanks guys.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    Nothing is changing in the shader. It has no idea which sprite is being displayed. It’s just displaying the sprite mesh it’s given, which has its UVs set to show a specific sprite. If you’re using auto-atlas sprites, there’s no real way to know which sprite is being shown in the shader since the UV range each sprite is in isn’t something the shader knows, or even cares about.

    If you want to apply effects based on a particular sprite with no c# code, you’ll have to manually create your atlases so you can know and hardcode the UV range to look for in the shader.

    However I highly recommend not doing that and just adding a c# script that swaps the material based on the sprite.
     
    milanhenkrich likes this.
  3. milanhenkrich

    milanhenkrich

    Joined:
    Jul 26, 2018
    Posts:
    31
    Thank you for you answer.

    Exactly! This is noticed. Let's say I have 5 sliced sprites inside of one. So when I am displaying the 1st one UV.x is from 0 to o.2. When displaying the 2nd one UV.x is from 0.2 to 0.4. etc.

    My problem is that I want to apply only for sliced sprite something like:

    Code (CSharp):
    1. uv.y = uv.y + abs(sin(3.14*(uv.x)))
    However, this is applied through whole texture (so from UV.x -0 ->1, not only for sliced texture).
    In order to get desired effect I have to modify equation to:

    Code (CSharp):
    1. uv.y = uv.y + abs(sin(CountOfSlicedSprites*3.14*(uv.x)))
    And I don't know how to get this CountOfSlicedSprites inside of shader. At least if there would be offset of the first sliced sprite then I could calculate it.

    Why MyTex_ST.z doesn't have this value?

     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    The shader doesn’t know what slice is being rendered, just like it doesn’t know what sprite is being rendered. Sliced sprites are done by the sprite renderer building a mesh with multiple parts. Just like determining what sprite you are rendering, you’d have to not use an auto atlased sprite and hard code the UV ranges.

    Alternatively you could implement the sliced sprite in a custom shader that applies to a quad (though you’d still need to use a non-auto atlased sprite). Unity 2018 and prior had some c# classes for modifying the sprite / UI mesh that would let you modify the mesh used to add extra data to help out, but they appear to have been removed in 2019.
     
  5. milanhenkrich

    milanhenkrich

    Joined:
    Jul 26, 2018
    Posts:
    31
    I see now.

    I am just beginner now and trying to get my head around this.

    Is there any way how could I remap UVs of MainText? So the current slice would have UV.x 0 -> 1? But to do it in shader. I would prefer not to use sprite atlas. Just in case here is my code, so we understand each other.


    Code (CSharp):
    1.  
    2.  
    3. Shader "Customs/Squash"
    4. {
    5. Properties
    6. {
    7. _MainTex("Sprite Texture", 2D) = "white" {}
    8. Squash_1("Squash", Range(-1, 4)) = 0.252
    9. _SpriteFade("SpriteFade", Range(0, 1)) = 1.0
    10. }
    11.  
    12. SubShader
    13. {
    14.  
    15. Tags {"Queue" = "Transparent" "IgnoreProjector" = "true" "RenderType" = "Transparent" "PreviewType"="Plane" "CanUseSpriteAtlas"="True" }
    16. ZWrite Off Blend SrcAlpha OneMinusSrcAlpha Cull Off
    17.  
    18. Pass
    19. {
    20. Name "BASE"
    21.  
    22. CGPROGRAM
    23. #pragma vertex vert
    24. #pragma fragment frag
    25. #pragma fragmentoption ARB_precision_hint_fastest
    26. #include "UnityCG.cginc"
    27.  
    28. struct vertexInput{
    29. float4 vertex   : POSITION;
    30. float2 texcoord : TEXCOORD0;
    31.  
    32. };
    33.  
    34. struct vertexOutput
    35. {
    36. float4 vertex   : SV_POSITION;
    37. float2 uvmain : TEXCOORD2;
    38.  
    39. };
    40.  
    41. sampler2D _MainTex;
    42.  
    43. float _SpriteFade;
    44. float4 _MainTex_ST;
    45. float Squash_1;
    46.  
    47.  
    48. const float pi = 3.14;
    49.  
    50. vertexOutput vert(vertexInput v)
    51. {
    52.             vertexOutput o;
    53.             o.vertex = UnityObjectToClipPos(v.vertex);  
    54.             o.uvmain = TRANSFORM_TEX( v.texcoord, _MainTex );
    55.             return o;
    56. }
    57.  
    58. float2 Squash(float2 uv, float value)
    59. {
    60. uv.y = uv.y + value *(uv.y/5  * sin(3.14*uv.x)* 5*abs(sin(uv.x*3.14)));
    61. return uv;
    62. }
    63.  
    64. float4 frag (vertexOutput i)
    65. {
    66. float2 SquastResult = Squash(i.uvmain,Squash_1);
    67. return FinalResult = tex2D(_MainTex,SquastResult);
    68.  
    69. }
    70.  
    71. ENDCG
    72. }
    73. }
    74. Fallback "Sprites/Default"
    75. }
    76.  
    Thanks.
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    Try a google search for 9 slicer shader. You should find several examples.