Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

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:
    816
    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:
    816
    Perfect! Always happy to help :)