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

Wind in grass, object vs. vertex displacement...

Discussion in 'Shaders' started by Zenchuck, Oct 27, 2015.

  1. Zenchuck

    Zenchuck

    Joined:
    Jun 2, 2010
    Posts:
    296
  2. Zenchuck

    Zenchuck

    Joined:
    Jun 2, 2010
    Posts:
    296
    I have tried

    float4 objectOrigin = mul(_Object2World, float4(0.0,0.0,0.0,1.0) );

    but for some reason that doesn't seem to give me unique values for each object, it appears to give me world position of 0,0,0.

    This is the key sentence in the gpu gems article:

    "To make this possible, each vertex must know the center position of its object, either relative to its position or absolute in the world. The grass object position vector needed for this information must be in the vertex format (that is, stored in texture coordinates), because the vertex shader has to read this value."

    I could pass world coordinates in through a vertex colour - this just makes the system much less flexible and I don't really want to go down this route. I just don't understand why calculating a vertex position of (0,0,0,1) in world space wouldn't give me the object world location.
     
    Last edited: Oct 27, 2015
  3. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,021
    It has to do with batching (dynamic or static). If the objects batch they don't have a unique origin point anymore so (0,0,0) is the same for all of them.

    Dynamic batching ON
    Screen Shot 2015-10-27 at 22.06.55.png

    Dynamic batching OFF
    Screen Shot 2015-10-27 at 22.06.48.png

    (shader is doing o.color = mul(_Object2World, float4(0.0,0.0,0.0,1.0) ).xyz; in vert and c*=i.color in frag)
     
  4. Zenchuck

    Zenchuck

    Joined:
    Jun 2, 2010
    Posts:
    296
    Thanks for the answer!

    I will just live with the per vertex displacement for now. Giving up batching is not an option. I could probably set the world location in through script, but then lose batching again if I'm not using a shared material.

    I'll post here again if I come up with anything.

    Cheers,

    Andrew
     
  5. Wompipomp

    Wompipomp

    Joined:
    Aug 31, 2014
    Posts:
    24
    Hi,

    I am doing the same tutorial at the moment.
    Do want to use the object origin to differ in waving?
    Here is my vertex shader:

    Code (CSharp):
    1. v2f o;
    2.                 if(v.uv.y >= 0.9)
    3.                 {
    4.                     float3 objectPos = mul(_Object2World, float4(0, 0, 0, 1));
    5.                     float3 dir = mul(_World2Object, _WindDirection) * (sin((_Time.x + objectPos.x) * 15)) * _WindStrength;
    6.                     v.vertex += float4(dir,0);
    7.                 }
    8.                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    9.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    10.                 float3 worldNormal = mul(float4(v.normal, 0), _World2Object).xyz;
    11.                 o.NdotL = saturate(dot(worldNormal, normalize(_WorldSpaceLightPos0).xyz));
    12.                 return o;
    Cheers,
    Mark
     
    Last edited: Oct 27, 2015
  6. Zenchuck

    Zenchuck

    Joined:
    Jun 2, 2010
    Posts:
    296
    Does batching work with your shader? I have to say I'm confused a bit by the if statement. What are you storing in the uv?
     
  7. Wompipomp

    Wompipomp

    Joined:
    Aug 31, 2014
    Posts:
    24
    Hi, good point with the batching. Sorry I am still a newbie with shader programming :)

    If I put 5 instances of my Grass in the scene, with dynamic batching it is the same behavior (always the same coords) :(

    The if statement is in the code of the article because only the upper both vertices should be transformed.
    Usually the vertices of a quad have on the bottom uv.y == 0 and on the upper side uv.y = 1 (I think this is not in all versions of unity like this, someone correct this please if I am mistaken). I don't exactly know why mostly for this the uvs are used because you could do the same with the y coord.
     
    Last edited: Oct 28, 2015
  8. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    That is actually the way to go. Just store the world position in the second (or other) set of uv coordinates. Then it works with or without batching.

    Or, what I usually do for a simple plane. Use the uv coordinates to determine which vertex you are. If you make the plane 1 by 1 and apply planar mapping, you can determine the pivot position based on the vertex position and uv mapping. In the vertex shader:
    Code (csharp):
    1.  
    2. float3 pos_pivot = pos_world; // Vertex position
    3. pos_pivot.x -= uv.x - 0.5; // Could also be z or positive, depending on your model
    4. pos_pivot.y -= uv.y; // Or 1.0 - uv.y, depending on your model
    5. // Then after this you would rotate the plane around the y axis to face the camera
    6.  
     
    Zenchuck likes this.
  9. Wompipomp

    Wompipomp

    Joined:
    Aug 31, 2014
    Posts:
    24
    It seems that if you use dynamic batching the input coords in the vertex shader are already in world space.
    Found this here coincidentally http://aras-p.info/blog/2015/01/06/divide-and-conquer-debugging/:

    I tested it and it seems to be correct.

    Cheers
     
  10. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    It's true that batching sets the object matrix to the unit matrix and essentially makes object space the same as world space. That's good for the vertex position, but that doesn't allow you to obtain the pivot/origin position of the original object. The idea here is to use the pivot position as an input to make the entire object behave the same.
     
  11. Wompipomp

    Wompipomp

    Joined:
    Aug 31, 2014
    Posts:
    24
    Now I think I understood. I think in my case it is the best option to go with the second uv because I have a mesh with 3 quads each already rotated by 60 degrees. So there would be no possibility to determine the pivot point.

    Thank you very much :)
     
  12. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    There actually might still be by also including the normals in the calculations.

    If you go for a uv set, note that you can only store 2 values in there. You can usually skip the height (y), so this is not an issue.
     
    Wompipomp likes this.
  13. Zenchuck

    Zenchuck

    Joined:
    Jun 2, 2010
    Posts:
    296
    I stepped away from this for a bit but I'm interested in taking another crack at.

    This is clever. I need to try this out. Great solution for quads. My meshes unfortunately are more "tree-like" in nature.