Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Shader world position questions

Discussion in 'Shaders' started by svaldenegro, Mar 23, 2018.

  1. svaldenegro

    svaldenegro

    Joined:
    Feb 22, 2014
    Posts:
    26
    Hi, i'm trying to recreate a Zelda like grass in unity, has been very easy to create wind movement so i decided to test to create grass bend but it has become a hell to me.
    Something so easy as vertexPos - playerPos dosn't work in the right way, also seems like the camera is affecting the direction of my vertex addition.

    Code (CSharp):
    1.  
    2.             v2f vert (appdata v)
    3.             {
    4.                 v2f o;
    5.                 float4 vertex = UnityObjectToClipPos(v.vertex);
    6.                 float4 dir = mul(unity_ObjectToWorld, v.vertex) - _PlayerPos;
    7.                 vertex += dir * v.color.r;
    8.                 o.vertex = vertex;
    9.                 //o.vertex = vertex + sin(_Time * _Speed) * normalize(_WindDir) * v.color.r * .5;
    10.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    11.                 UNITY_TRANSFER_FOG(o,o.vertex);
    12.                 return o;
    13.             }
    How i'm supposed to get vertex positions or add playerPos in the right way so the grass can bend against the direction of the player?
    Also, the player pos is provided by a C# script. inb4 thanks for your time!
     
  2. Remy_Unity

    Remy_Unity

    Unity Technologies

    Joined:
    Oct 3, 2017
    Posts:
    703
    The output of the vertex shader is a vertex position in clip space ( that's what UnityObjectToClipPos(v.vertex); does ).
    You're adding a world space calculated vector to this clip space position, that's probably why you have issues with the camera view.
    Convert your dir vector to clip space and it should do the trick :
    Code (CSharp):
    1. float4 dir = mul(unity_ObjectToWorld, v.vertex) - _PlayerPos;
    2. dir = mul( UNITY_MATRIX_VP, dir );
    3. vertex += dir * v.color.r;
     
    svaldenegro likes this.
  3. svaldenegro

    svaldenegro

    Joined:
    Feb 22, 2014
    Posts:
    26
    Thanks it don't make the trick but it fixed the camera problem (so i can keep working on it until make it work) and now i understand what clip space mean.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    You can’t do this and expect useful results. Clip space is non-linear when using a non-orthographic projection, so a vector offset of even a fixed value will be significantly different depending on where the camera is relative to the vertex, which isn’t what you want. You need to do all of the vertex manipulation in local object, world, or view space.

    Code (CSharp):
    1. float3 worldPos = mul(unity_ObjectToWorld, float4(v.vertex.xyz, 1)).xyz;
    2. float3 playerToVertexVec = worldPos - _PlayerPos.xyz;
    3. float3 playerToVertexDir = normalize(playerToVertexVec);
    4. float playerToVertexDist = length(playerToVertexVec);
    5. worldPos += playerToVertexDir * (1 - saturate(playerToVertexDist / _BendRange)) * _BendStrength;
    6. o.vertex = mul(UNITY_MATRIX_VP, float4(worldPos, 1));
     
  5. Misscelan

    Misscelan

    Joined:
    Mar 8, 2013
    Posts:
    176
    Sorry to bring this up. I'm trying to do this with a Surface shader but I guess I'm preparing the vertices por an incorrect space. How would you add add an offset to a vertex base on the direction and distance to the player (like the example above) but on surface shader?

    Code (CSharp):
    1.     void vert(inout appdata_full i, out Input o)
    2.         {
    3.             UNITY_INITIALIZE_OUTPUT(Input, o);
    4.  
    5.             float y_bend = i.vertex.y * 3;
    6.             float4 worldpos = mul(unity_ObjectToWorld, i.vertex);
    7.          
    8.             float3 playerToVertexVec = worldPos - _PlayerPos.xyz;
    9.             float3 playerToVertexDir = normalize(playerToVertexVec);
    10.             float playerToVertexDist = 1 - saturate(length(playerToVertexVec)) ;
    11.             i.vertex += playerToVertexDir  * playerToVertexDist * y_bend;
    12.  
    13.         }