Search Unity

Vertex shader that rotates around the center

Discussion in 'Shaders' started by PMerlaud, Oct 12, 2017.

  1. PMerlaud

    PMerlaud

    Joined:
    Apr 9, 2013
    Posts:
    64
    I have the following shader that allows me to apply a color gradient :
    Code (CSharp):
    1.  Shader "Custom/LinearGradient"
    2. {
    3.      Properties{
    4.          _TopColor("Color1", Color) = (1,1,1,1)
    5.          _BottomColor("Color2", Color) = (1,1,1,1)
    6.          _MainTex ("Main Texture", 2D) = "white" {}
    7.          _Rotation("Rotation", Float) = 0
    8.      }
    9.          SubShader
    10.      {
    11.          Tags { "RenderType" = "Transparent" "Queue" = "Transparent" "PreviewType" = "Plane"}
    12.          Pass
    13.          {
    14.              ZWrite Off
    15.              Blend SrcAlpha OneMinusSrcAlpha
    16.  
    17.              CGPROGRAM
    18.              #pragma vertex vert
    19.              #pragma fragment frag
    20.              #include "UnityCG.cginc"
    21.  
    22.              sampler2D _MainTex;
    23.              float4 _MainTex_ST;
    24.              fixed4 _TopColor;
    25.              fixed4 _BottomColor;
    26.              half _Value;
    27.              float4x4 _Rotation;
    28.  
    29.              struct v2f {
    30.                  float4 position : SV_POSITION;
    31.                  fixed4 color : COLOR;
    32.                  float2 uv : TEXCOORD0;
    33.              };
    34.  
    35.              v2f vert (appdata_full v)
    36.              {
    37.                  v2f o;
    38.                  o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
    39.                  v.texcoord.xy = mul(_Rotation, v.texcoord.xy);
    40.                  o.position = mul (UNITY_MATRIX_MVP, v.vertex);
    41.                  o.color = lerp (_TopColor,_BottomColor, v.texcoord.y);
    42.                  return o;
    43.              }
    44.  
    45.              fixed4 frag(v2f i) : SV_Target
    46.              {
    47.                  float4 color;
    48.                  color.rgb = i.color.rgb;
    49.                  color.a = tex2D (_MainTex, i.uv).a * i.color.a;
    50.                  return color;
    51.              }
    52.              ENDCG
    53.          }
    54.      }
    55. }
    Looks like this in Unity when applied to a sprite :
    Capture d’écran 2017-10-12 à 11.56.26.png

    I'm also calling the following code from Update() to adjust the rotation of the gradient :
    Code (CSharp):
    1.  
    2.     Vector2 pivot = new Vector2(0.5f, 0.5f);
    3.     float rotateSpeed = 30f;
    4.     Material m;
    5.  
    6.     void Update()
    7.     {
    8.         if (m != null)
    9.         {
    10.             Matrix4x4 t = Matrix4x4.TRS(-pivot, Quaternion.identity, Vector3.one);
    11.  
    12.             Quaternion rotation = Quaternion.Euler(0, 0, Time.time * rotateSpeed);
    13.             Matrix4x4 r = Matrix4x4.TRS(Vector3.zero, rotation, Vector3.one);
    14.  
    15.             Matrix4x4 tInv = Matrix4x4.TRS(pivot, Quaternion.identity, Vector3.one);
    16.             sprites[0].material.SetMatrix("_Rotation", tInv * r * t);
    17.         }
    18.     }
    The only thing is that it doesn't rotate from the center of the sprite but from a point located here :
    Capture d’écran 2017-10-12 à 11.56.26.png

    Any idea on how I could offset the rotation point?
     
  2. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Hm, if it really is the green point than I would change it like this:

    Code (CSharp):
    1.              v2f vert (appdata_full v)
    2.              {
    3.                  v2f o;
    4.                  o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
    5.                  v.texcoord.x = v.texcoord.x + 0.5;
    6.                  v.texcoord.xy = mul(_Rotation, v.texcoord.xy);
    7.                  v.texcoord.x = v.texcoord.x - 0.5;
    8.                  o.position = mul (UNITY_MATRIX_MVP, v.vertex);
    9.                  o.color = lerp (_TopColor,_BottomColor, v.texcoord.y);
    10.                  return o;
    11.              }
    From my feeling however I would have guessed you need to move u and v in +0.5 before rotating.
     
    PMerlaud likes this.
  3. PMerlaud

    PMerlaud

    Joined:
    Apr 9, 2013
    Posts:
    64
    Thanks a lot for your answer!
    I just had to offset xy by -0.5 before rotating then add 0.5 back like so:
    Code (CSharp):
    1. v2f vert (appdata_full v)
    2.              {
    3.                  v2f o;
    4.                  o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
    5.                  v.texcoord.xy -= float2(0.5, 0.5);
    6.                  v.texcoord.xy = mul(_Rotation, v.texcoord.xy);
    7.                  v.texcoord.xy += float2(0.5, 0.5);
    8.                  o.position = mul (UNITY_MATRIX_MVP, v.vertex);
    9.                  o.color = lerp (_TopColor, _BottomColor, v.texcoord.y);
    10.                  return o;
    11.              }
     
    Last edited: Oct 13, 2017
  4. Johannski

    Johannski

    Joined:
    Jan 25, 2014
    Posts:
    826
    Perfect! Always happy to help :)