Search Unity

shader.SetGlobalVector ?

Discussion in 'Shaders' started by metervara, Jul 30, 2007.

  1. metervara

    metervara

    Joined:
    Jun 15, 2006
    Posts:
    203
    Digging myself deeper and deeper into the ShaderLab hole...

    I have a lot of objects with the same shader. The shader needs to know the position of another object.

    First attempt has an exposed Vector property for the shader. This works, but with many objects it gets inconvenient:

    Code (csharp):
    1.  
    2. //shader
    3. Properties {
    4.    _Obstacle ("Obstacle", Vector) = (0,0,0,0)
    5. }
    6.  
    7. //Object that affects shader
    8. other.renderer.material.SetVector("_Obstacle", transform.position);
    9.  
    10.  
    Then I remembered global shader properties, but it seems SetGlobalVector is missing :( . I can use SetGlobalFloat for x,y,z, that should work fine, I'm just wondering if there's a 'proper' way of getting a position like this into the shader?

    /P
     
  2. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    For now use SetGlobalColor, we'll add SetGlobalVector in the future release.

    SetGlobalColor will just work; as vectors and colors internally are the same thing (four floating point numbers); and Colors can have components outside of the usual 0..1 range.
     
  3. metervara

    metervara

    Joined:
    Jun 15, 2006
    Posts:
    203
    SetGlobalColor works great. Managed to hack the Windy Grass shader to make the grass bend to avoid an obstacle.



    Still need to fix issues when the obstacle is inside the grass geometry as this will stretch the grass unnaturally. (Btw, I'm using geometry instead of billboards so I can have the camera close to the grass)

    /P
     
  4. Aras

    Aras

    Unity Technologies

    Joined:
    Nov 7, 2005
    Posts:
    4,770
    Gee, Patrik, you'll turn into a shader monster soon! Keep up the good work :)
     
  5. drJones

    drJones

    Joined:
    Oct 19, 2005
    Posts:
    1,351
    wow that's really cool - i'm wondering how is the performance using regular meshes instead of billboards?
     
  6. jeremyace

    jeremyace

    Joined:
    Oct 12, 2005
    Posts:
    1,661
    Looks awesome metervara!

    Any chance you could share you code for that? Pretty please? I'd like to learn how to do this stuff in a shader instead of the mesh interface. ;-)

    -Jeremy
     
  7. metervara

    metervara

    Joined:
    Jun 15, 2006
    Posts:
    203
    Here is the most basic version. It has some problems when the obstacle is inside the geometry. One fix is to move the grass slightly away from the obstacle as it gets close, but it looks weird if the ground is visible. Works when you only see the top of the grass though.

    It's a few additions to the standard Windy Grass shader from the Nature pack:

    Firts off there's a global shader color: _Obstacle. Use Shader.SetGlobalColor to get the obstacle position to the shader.

    Then the main block (/OBSTACLE AVOIDANCE CALC). The windy grass shader already calculates the world position for vertices so use that and compare with obstacle position to get bend direction vector. Also calculate distance falloff.

    Finally we add the bend offset exponentially - v.vertex.xz += ...

    We could also swap v.texcoord.y for let's say v.color.r and paint the 'bendyness' into the model using vertex colors to have some parts softer than others. Doesn't really make sense for a simple thing like a grass straw though, but could be cool for more complex models.

    Note:
    And all this is not really bending, but stretching or skewing so the geometry can look strange sometimes. Feel free to fix :D

    Code (csharp):
    1.  
    2. Shader "Nature/Windy Grass" {
    3.     Properties {
    4.         _Color ("Main Color", Color) = (.5, .5, .5, 0)
    5.         _Color2 ("Fade Color", Color) = (1, .9, .8, 0)
    6.         _MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}
    7.         _Cutoff ("Base Alpha cutoff", Range (0,1)) = .5
    8.     }
    9.     SubShader {
    10.         Tags { "Queue" = "Transparent" }
    11.         BindChannels {
    12.             Bind "Color", color
    13.             Bind "Vertex", vertex
    14.             Bind "TexCoord", texcoord
    15.         }
    16.  
    17.         Pass {
    18.             Lighting On
    19. CGPROGRAM
    20. // vertex Vertex
    21.  
    22. #include "waves.cginc"      // Get in the helper wave functions
    23. #include "UnityCG.cginc"        // Get standard Unity constants
    24.  
    25. struct Appdata {
    26.     float4 vertex;
    27.     float3 normal;
    28.     float4 texcoord;
    29.     float4 color;
    30. };
    31.  
    32. struct v2f {
    33.     float4 pos : POSITION;
    34.     float4 color : COLOR0;
    35.     float4 uv : TEXCOORD0;
    36.     float fog : FOGC;
    37. };
    38.  
    39. uniform float4 _Color, _Color2, _SkyLight;
    40. uniform float4 _Obstacle; // OBSTACLE AVOIDANCE
    41.  
    42. v2f Vertex(Appdata v) {
    43.     v2f o;
    44.  
    45.     const float4 _waveXSize = float4(0.012, 0.02, -0.06, 0.048) * 2;
    46.     const float4 _waveZSize = float4 (0.006, .02, -0.02, 0.1) * 2;
    47.     const float4 waveSpeed = float4 (0.3, .3, .08, .07) * 4;
    48.  
    49.     float4 _waveXmove = _waveXSize * waveSpeed * 25;
    50.     float4 _waveZmove = _waveZSize * waveSpeed * 25;
    51.    
    52.     // We model the wind as basic waves...
    53.  
    54.     // Calculate the wind input to leaves from their vertex positions....
    55.     // for now, we transform them into world-space x/z positions...
    56.     // Later on, we should actually be able to do the whole calc's in post-projective space
    57.     float3 worldPos = mul ((float3x4)_Object2World, v.vertex);
    58.    
    59.     // OBSTACLE AVOIDANCE CALC
    60.     float3 bendDir = normalize (float3(worldPos.x,0,worldPos.z) - float3(_Obstacle.x,0,_Obstacle.z));//direction of obstacle bend
    61.     float distLimit = 3;// how far away does obstacle reach
    62.     float distMulti = (distLimit-min(distLimit,distance(float3(worldPos.x,0,worldPos.z),float3(_Obstacle.x,0,_Obstacle.z))))/distLimit; //distance falloff
    63.     //OBSTACLE AVOIDANCE END
    64.    
    65.     // This is the input to the sinusiodal warp
    66.     float4 waves;
    67.     waves = worldPos.x * _waveXSize;
    68.     waves += worldPos.z * _waveZSize;
    69.  
    70.     // Add in time to model them over time
    71.     waves += _Time.x * waveSpeed;
    72.  
    73.     float4 s, c;
    74.     waves = frac (waves);
    75.     FastSinCos (waves, s,c);
    76.  
    77.     float waveAmount = v.texcoord.y;
    78.     s *= waveAmount;
    79.  
    80.     // Faste winds move the grass more than slow winds
    81.     s *= normalize (waveSpeed);
    82.  
    83.     s = s * s;
    84.     float fade = dot (s, 1.3);
    85.     s = s * s;
    86.     float3 waveMove = float3 (0,0,0);
    87.     waveMove.x = dot (s, _waveXmove);
    88.     waveMove.z = dot (s, _waveZmove);
    89.    
    90.     v.vertex.xz -= mul ((float3x3)_World2Object, waveMove).xz;
    91.     v.vertex.xz += bendDir.xz*distMulti*v.texcoord.y*v.texcoord.y*1.5; //ADD OBSTACLE BENDING
    92.    
    93.     o.pos = mul(glstate.matrix.mvp, v.vertex);
    94.     o.fog = o.pos.w;
    95.     o.uv = v.texcoord;
    96.     o.color = lerp (_Color, _Color2, fade.xxxx);
    97. //  o.color *= _SkyLight;
    98.     return o;
    99. }
    100. ENDCG
    101.             AlphaTest Greater [_Cutoff]
    102.             Cull Off
    103.             SetTexture [_MainTex] { combine texture * primary double, texture}
    104.            
    105.         }
    106.     }  
    107.     SubShader {
    108.         Tags { "Queue" = "Transparent" }
    109.         Pass {
    110.             Blend SrcAlpha oneMinusSrcAlpha
    111.             AlphaTest Greater [_Cutoff]
    112.             Cull Off
    113.             color [_Color]
    114.             ZTest Less
    115.             SetTexture [_MainTex] { combine texture * primary DOUBLE, texture}
    116.         }
    117.  
    118.     }
    119. }
    120.  
    /P
     
    Hadronomy likes this.
  8. jeremyace

    jeremyace

    Joined:
    Oct 12, 2005
    Posts:
    1,661
    Awesome. Thanks a lot for sharing and also for explaining it. Much appreciated. ;-)

    -Jeremy
     
  9. metervara

    metervara

    Joined:
    Jun 15, 2006
    Posts:
    203
    Would love to see implementations or variations of it :)

    /P
     
  10. rawrman2381238

    rawrman2381238

    Joined:
    Jan 28, 2008
    Posts:
    122
    Can someone make a unity package as I am unsure how to se this up... It looks awesome though!
     
  11. God-at-play

    God-at-play

    Joined:
    Nov 3, 2006
    Posts:
    330
    Here's a version that works in Unity 2.5. Please note, I customized it to my own situation, which means the texture has been removed.

    Code (csharp):
    1. Shader "Dynamic Grass"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Main Color", Color) = (.055, .094, .082, 1)
    6.         _Color2 ("Fade Color", Color) = (.09, .157, .137, 1)
    7.         _WaveX ("Wave X", Vector) = (.07, .01, .01, 0.01)
    8.         _WaveZ ("Wave Z", Vector) = (-.07, .01, .01, 0.01)
    9.         _WaveSpeed ("Wave Speed", Vector) = (1, 1.5, 1.1, .9)
    10.     }
    11.     SubShader
    12.     {
    13.         Tags { "Queue" = "Transparent" }
    14.        
    15.         Pass
    16.         {
    17.             Lighting On
    18.            
    19.             CGPROGRAM
    20.             #pragma vertex Vertex
    21.            
    22.             #include "waves.cginc"      // Get in the helper wave functions
    23.             #include "UnityCG.cginc"    // Get standard Unity constants
    24.            
    25.             struct v2f
    26.             {
    27.                 float4 pos : POSITION;
    28.                 float4 color : COLOR0;
    29.                 float4 uv : TEXCOORD0;
    30.                 float fog : FOGC;
    31.             };
    32.            
    33.             uniform float4 _Color, _Color2, _WaveX, _WaveZ, _WaveSpeed;
    34.             uniform float3 _obstacle;
    35.             uniform float _affectDist, _bendAmount;
    36.            
    37.             v2f Vertex(appdata_base v)
    38.             {
    39.                 v2f o;
    40.                
    41.                 const float4 _waveXSize = _WaveX * 2;
    42.                 const float4 _waveZSize = _WaveZ * 2;
    43.                 const float4 waveSpeed = _WaveSpeed * 4;
    44.                
    45.                 float4 _waveXmove = _waveXSize * waveSpeed * 25;
    46.                 float4 _waveZmove = _waveZSize * waveSpeed * 25;
    47.                
    48.                 // Calculate the wind input to leaves from their vertex positions....
    49.                 float3 worldPos = mul ((float3x4)_Object2World, v.vertex);
    50.                  
    51.                 // OBSTACLE AVOIDANCE CALC
    52.                 float3 bendDir = normalize (float3(worldPos.x,0,worldPos.z) - float3(_obstacle.x,0,_obstacle.z));//direction of obstacle bend
    53.                 float distLimit = _affectDist;// how far away does obstacle reach
    54.                 float distMulti = (distLimit-min(distLimit,distance(float3(worldPos.x,0,worldPos.z),float3(_obstacle.x,0,_obstacle.z))))/distLimit; //distance falloff
    55.                 //OBSTACLE AVOIDANCE END
    56.                  
    57.                 // This is the input to the sinusiodal warp
    58.                 float4 waves;
    59.                 waves = worldPos.x * _waveXSize;
    60.                 waves += worldPos.z * _waveZSize;
    61.                
    62.                 // Add in time to model them over time
    63.                 waves += _Time.x * waveSpeed;
    64.                
    65.                 float4 s, c;
    66.                 waves = frac (waves);
    67.                 FastSinCos (waves, s,c);
    68.                
    69.                 float waveAmount = v.texcoord.y;
    70.                 s *= waveAmount;
    71.                
    72.                 // Faste winds move the grass more than slow winds
    73.                 s *= normalize (waveSpeed);
    74.                
    75.                 s = s * s;
    76.                 float fade = dot (v.texcoord.y * v.texcoord.y, 2);
    77.                 s = s * s;
    78.                 float3 waveMove = float3 (0,0,0);
    79.                 waveMove.x = dot (s, _waveXmove);
    80.                 waveMove.z = dot (s, _waveZmove);
    81.                  
    82.                 v.vertex.xz -= mul ((float3x3)_World2Object, waveMove).xz;
    83.                 v.vertex.xz += bendDir.xz * distMulti * v.texcoord.y * v.texcoord.y * _bendAmount; //ADD OBSTACLE BENDING
    84.                
    85.                 o.pos = mul(glstate.matrix.mvp, v.vertex);
    86.                 o.fog = o.pos.w;
    87.                 o.uv = v.texcoord;
    88.                 o.color = lerp (_Color, _Color2, fade.xxxx);
    89.                 return o;
    90.             }
    91.             ENDCG
    92.            
    93.             AlphaTest Greater [_Cutoff]
    94.             Cull Off
    95.         }
    96.     }
    97.    
    98.     SubShader
    99.     {
    100.         Tags { "Queue" = "Transparent" }
    101.         Pass
    102.         {
    103.             Blend SrcAlpha oneMinusSrcAlpha
    104.             AlphaTest Greater [_Cutoff]
    105.             Cull Off
    106.             color [_Color]
    107.             ZTest Less
    108.         }
    109.     }
    110. }
    This script is attached to a cube that acts as my obstacle. I've rigged it up so that it increases how far it affects the grass and how much the grass bends when you're pressing the Jump button.

    Code (csharp):
    1. #pragma strict
    2.  
    3. @script ExecuteInEditMode
    4.  
    5. var affectDist : float = 8;
    6. var bendAmount : float = 5;
    7.  
    8. private var myTransform : Transform;
    9.  
    10. function Awake()
    11. {
    12.     SetBend();
    13.    
    14.     myTransform = transform;
    15. }
    16.  
    17. function Update() : void
    18. {
    19.     Shader.SetGlobalVector("_obstacle", myTransform.position);
    20.    
    21.     if (Input.GetButton("Jump"))
    22.     {
    23.         if (affectDist < 22)
    24.         {
    25.             affectDist += 3;
    26.             bendAmount += 0.3;
    27.            
    28.             SetBend(affectDist, bendAmount);
    29.         }
    30.        
    31.         if (affectDist > 20)
    32.         {
    33.             affectDist = 20;
    34.             bendAmount = 6.2;
    35.            
    36.             SetBend(affectDist, bendAmount);
    37.         }
    38.     }
    39.     else
    40.     {
    41.         if (affectDist > 8)
    42.         {
    43.             affectDist -= 4;
    44.             bendAmount -= 0.6;
    45.            
    46.             SetBend(affectDist, bendAmount);
    47.         }
    48.         else
    49.         {
    50.             SetBend();
    51.         }
    52.     }
    53. }
    54.  
    55. function SetBend(_affectDist : float, _bendAmount : float) : void
    56. {
    57.     Shader.SetGlobalFloat("_affectDist", _affectDist);
    58.     Shader.SetGlobalFloat("_bendAmount", _bendAmount);
    59. }
    60.  
    61. function SetBend() : void
    62. {
    63.     SetBend(8, 5);
    64. }
    IMPORTANT: The values here are set to blades of grass that are approximately 1 unit wide and 8 units tall or so. It's very important that the grass blade mesh has UV coordinates such that the grass blade looks "upright," which a planar projection along the Z would get you. A screenshot is attached. Note, that cube is a default cube created by Unity.
     

    Attached Files:

  12. larsjessen

    larsjessen

    Joined:
    Mar 17, 2008
    Posts:
    44
    I am having trouble getting the shader to work. When I use the shader on my planes no color is added and they remain invisible. Would it be possible by any chance for you to upload the Unity project?

    many thanks,
    Lars
     
  13. showoff

    showoff

    Joined:
    Apr 28, 2009
    Posts:
    273
    Im also having problems with the shader aswell. I cant seem to get either of the shaders working either.
     
  14. God-at-play

    God-at-play

    Joined:
    Nov 3, 2006
    Posts:
    330
    I've attached the waves.cginc file, which I have in my Materials folder along with the shader.

    Dynamic Grass shader applied as a material to grass blade meshes with UV coordinates with optional bending on the y:

    Code (csharp):
    1. Shader "Dynamic Grass"
    2. {
    3.     Properties
    4.     {
    5.         _Color ("Main Color", Color) = (.055, .094, .082, 1)
    6.         _Color2 ("Fade Color", Color) = (.09, .157, .137, 1)
    7.         _WaveX ("Wave X", Vector) = (.07, .01, .01, 0.01)
    8.         _WaveZ ("Wave Z", Vector) = (-.07, .01, .01, 0.01)
    9.         _WaveSpeed ("Wave Speed", Vector) = (1, 1.5, 1.1, .9)
    10.     }
    11.     SubShader
    12.     {
    13.         Tags { "Queue" = "Transparent" }
    14.        
    15.         Pass
    16.         {
    17.             Lighting On
    18.            
    19.             CGPROGRAM
    20.             #pragma vertex Vertex
    21.            
    22.             #include "waves.cginc"      // Get in the helper wave functions
    23.             #include "UnityCG.cginc"    // Get standard Unity constants
    24.            
    25.             struct v2f
    26.             {
    27.                 float4 pos : POSITION;
    28.                 float4 color : COLOR0;
    29.                 float4 uv : TEXCOORD0;
    30.                 float fog : FOGC;
    31.             };
    32.            
    33.             uniform float4 _Color, _Color2, _WaveX, _WaveZ, _WaveSpeed;
    34.             uniform float3 _obstacle;
    35.             uniform float _affectDist, _bendAmount;
    36.            
    37.             v2f Vertex(appdata_base v)
    38.             {
    39.                 v2f o;
    40.                
    41.                 const float4 _waveXSize = _WaveX * 2;
    42.                 const float4 _waveZSize = _WaveZ * 2;
    43.                 const float4 waveSpeed = _WaveSpeed * 4;
    44.                
    45.                 float4 _waveXmove = _waveXSize * waveSpeed * 25;
    46.                 float4 _waveZmove = _waveZSize * waveSpeed * 25;
    47.                
    48.                 // Calculate the wind input to leaves from their vertex positions....
    49.                 float3 worldPos = mul ((float3x4)_Object2World, v.vertex);
    50.                  
    51.                 // OBSTACLE AVOIDANCE CALC
    52.                 float3 bendDir = normalize (float3(worldPos.x,worldPos.y,worldPos.z) - float3(_obstacle.x,_obstacle.y,_obstacle.z));//direction of obstacle bend
    53.                 float distLimit = _affectDist;// how far away does obstacle reach
    54.                 float distMulti = (distLimit-min(distLimit,distance(float3(worldPos.x,worldPos.y,worldPos.z),float3(_obstacle.x,_obstacle.y,_obstacle.z))))/distLimit; //distance falloff
    55.                 //OBSTACLE AVOIDANCE END
    56.                  
    57.                 // This is the input to the sinusiodal warp
    58.                 float4 waves;
    59.                 waves = worldPos.x * _waveXSize;
    60.                 waves += worldPos.z * _waveZSize;
    61.                
    62.                 // Add in time to model them over time
    63.                 waves += _Time.x * waveSpeed;
    64.                
    65.                 float4 s, c;
    66.                 waves = frac (waves);
    67.                 FastSinCos (waves, s,c);
    68.                
    69.                 float waveAmount = v.texcoord.y;
    70.                 s *= waveAmount;
    71.                
    72.                 // Faste winds move the grass more than slow winds
    73.                 s *= normalize (waveSpeed);
    74.                
    75.                 s = s * s;
    76.                 float fade = dot (v.texcoord.y * v.texcoord.y, 2);
    77.                 s = s * s;
    78.                 float3 waveMove = float3 (0,0,0);
    79.                 waveMove.x = dot (s, _waveXmove);
    80.                 waveMove.z = dot (s, _waveZmove);
    81.                  
    82.                 v.vertex.xz -= mul ((float3x3)_World2Object, waveMove).xz;
    83.                 v.vertex.xz += bendDir.xz * distMulti * v.texcoord.y * v.texcoord.y * _bendAmount; //ADD OBSTACLE BENDING
    84.                
    85.                 //optional y bending
    86.                 //v.vertex.xyz += bendDir.xyz * distMulti * v.texcoord.y * v.texcoord.y * _bendAmount; //ADD OBSTACLE BENDING
    87.                
    88.                 o.pos = mul(glstate.matrix.mvp, v.vertex);
    89.                 o.fog = o.pos.w;
    90.                 o.uv = v.texcoord;
    91.                 o.color = lerp (_Color, _Color2, fade.xxxx);
    92.                 return o;
    93.             }
    94.             ENDCG
    95.            
    96.             AlphaTest Greater [_Cutoff]
    97.             Cull Off
    98.         }
    99.     }
    100.    
    101.     SubShader
    102.     {
    103.         Tags { "Queue" = "Transparent" }
    104.         Pass
    105.         {
    106.             Blend SrcAlpha oneMinusSrcAlpha
    107.             AlphaTest Greater [_Cutoff]
    108.             Cull Off
    109.             color [_Color]
    110.             ZTest Less
    111.         }
    112.     }
    113. }
    Bend affect script attached to obstacle object:

    Code (csharp):
    1. #pragma strict
    2.  
    3. @script ExecuteInEditMode
    4.  
    5. var affectDist : float = 20;
    6. var bendAmount : float = 5;
    7.  
    8. private var myTransform : Transform;
    9.  
    10. function Awake()
    11. {  
    12.     myTransform = transform;
    13. }
    14.  
    15. function Update()
    16. {
    17.     Shader.SetGlobalVector("_obstacle", myTransform.position);
    18.    
    19.     Shader.SetGlobalFloat("_affectDist", _affectDist);
    20.     Shader.SetGlobalFloat("_bendAmount", _bendAmount);
    21. }
     

    Attached Files:

  15. RaphMa

    RaphMa

    Joined:
    Nov 9, 2012
    Posts:
    7
  16. echologin

    echologin

    Joined:
    Apr 11, 2010
    Posts:
    1,078
    if i see another float in a frag shader where id doesn't need to be i think i will exorcist vomit
     
  17. antislash

    antislash

    Joined:
    Apr 23, 2015
    Posts:
    646
    hi, sorry to necro this...
    i'm trying to get collision info in a shader and the examples i see always rely on old unity versions
    i'm on 5 and Wonder witch changes have been made in code to deal with collisions et setglobalvector

    i use this code with no success :

    collisionInfo.gameObject.GetComponent<Renderer>().material.SetVector("_CollisionPoint", contact.point);

    thanks
     
  18. Leoo

    Leoo

    Joined:
    May 13, 2013
    Posts:
    96
    This seems to not be working at all on unity 5 Terrain, sad face :'(

    Probably something is done differently on the Grass Shader itself, when you do it line by line, you see that everything gets weird when you multiply wordPos * waveXsizes instead of vertex * waveXsizes..

    Code (csharp):
    1.  
    2. waves = worldPos.x * _waveXSize;    
    3. waves += worldPos.z * _waveZSize;
    4.  
    5.     waves = vertex.x * _waveXSize;
    6.     waves += vertex.z * _waveZSize;
    7.  
    8.  
     
    Last edited: Nov 24, 2016