shader.SetGlobalVector ?

 
Post new topic   Reply to topic    Unity Community Index // ShaderLab
View previous topic :: View next topic  
Author Message
metervara



Joined: 15 Jun 2006
Posts: 201
Location: Copenhagen

PostPosted: Mon Jul 30, 2007 10:32 am    Post subject: shader.SetGlobalVector ? Reply with quote
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:

//shader
Properties {
   _Obstacle ("Obstacle", Vector) = (0,0,0,0)
}

//Object that affects shader
other.renderer.material.SetVector("_Obstacle", transform.position);



Then I remembered global shader properties, but it seems SetGlobalVector is missing Sad . 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
Back to top
View user's profile Send private message Visit poster's website
Aras
Unity Graphics Developer


Joined: 07 Nov 2005
Posts: 3316
Location: Unity Technologies, basement

PostPosted: Mon Jul 30, 2007 11:30 am    Post subject: Reply with quote
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.

_________________
homepage | blog | twitter
Back to top
View user's profile Send private message Visit poster's website
metervara



Joined: 15 Jun 2006
Posts: 201
Location: Copenhagen

PostPosted: Mon Jul 30, 2007 12:09 pm    Post subject: Reply with quote
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
Back to top
View user's profile Send private message Visit poster's website
Aras
Unity Graphics Developer


Joined: 07 Nov 2005
Posts: 3316
Location: Unity Technologies, basement

PostPosted: Mon Jul 30, 2007 1:45 pm    Post subject: Reply with quote
Gee, Patrik, you'll turn into a shader monster soon! Keep up the good work Smile
_________________
homepage | blog | twitter
Back to top
View user's profile Send private message Visit poster's website
drJones



Joined: 19 Oct 2005
Posts: 1342
Location: New Hampshire

PostPosted: Mon Jul 30, 2007 2:13 pm    Post subject: Reply with quote
wow that's really cool - i'm wondering how is the performance using regular meshes instead of billboards?
_________________
-O
Back to top
View user's profile Send private message
jeremyace



Joined: 12 Oct 2005
Posts: 1651
Location: Ontario, Canada

PostPosted: Mon Jul 30, 2007 10:15 pm    Post subject: Reply with quote
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. Wink

-Jeremy

_________________
Lead Developer
Ennanzus Interactive

Unity Feed Reader - version 1.5 released! Now parses all major news syndication formats.

GUI-eXtended - UI System and Visual Designer
Back to top
View user's profile Send private message Visit poster's website
metervara



Joined: 15 Jun 2006
Posts: 201
Location: Copenhagen

PostPosted: Tue Jul 31, 2007 8:19 am    Post subject: Reply with quote
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 Very Happy

Code:

Shader "Nature/Windy Grass" {
   Properties {
      _Color ("Main Color", Color) = (.5, .5, .5, 0)
      _Color2 ("Fade Color", Color) = (1, .9, .8, 0)
      _MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}
      _Cutoff ("Base Alpha cutoff", Range (0,1)) = .5
   }
   SubShader {
      Tags { "Queue" = "Transparent" }
      BindChannels {
         Bind "Color", color
         Bind "Vertex", vertex
         Bind "TexCoord", texcoord
      }

      Pass {
         Lighting On
CGPROGRAM
// vertex Vertex

#include "waves.cginc"      // Get in the helper wave functions
#include "UnityCG.cginc"      // Get standard Unity constants

struct Appdata {
   float4 vertex;
   float3 normal;
   float4 texcoord;
   float4 color;
};

struct v2f {
   float4 pos : POSITION;
   float4 color : COLOR0;
   float4 uv : TEXCOORD0;
   float fog : FOGC;
};

uniform float4 _Color, _Color2, _SkyLight;
uniform float4 _Obstacle; // OBSTACLE AVOIDANCE

v2f Vertex(Appdata v) {
   v2f o;

   const float4 _waveXSize = float4(0.012, 0.02, -0.06, 0.048) * 2;
   const float4 _waveZSize = float4 (0.006, .02, -0.02, 0.1) * 2;
   const float4 waveSpeed = float4 (0.3, .3, .08, .07) * 4;

   float4 _waveXmove = _waveXSize * waveSpeed * 25;
   float4 _waveZmove = _waveZSize * waveSpeed * 25;
   
   // We model the wind as basic waves...

   // Calculate the wind input to leaves from their vertex positions....
   // for now, we transform them into world-space x/z positions...
   // Later on, we should actually be able to do the whole calc's in post-projective space
   float3 worldPos = mul ((float3x4)_Object2World, v.vertex);
   
   // OBSTACLE AVOIDANCE CALC
   float3 bendDir = normalize (float3(worldPos.x,0,worldPos.z) - float3(_Obstacle.x,0,_Obstacle.z));//direction of obstacle bend
   float distLimit = 3;// how far away does obstacle reach
   float distMulti = (distLimit-min(distLimit,distance(float3(worldPos.x,0,worldPos.z),float3(_Obstacle.x,0,_Obstacle.z))))/distLimit; //distance falloff
   //OBSTACLE AVOIDANCE END
   
   // This is the input to the sinusiodal warp
   float4 waves;
   waves = worldPos.x * _waveXSize;
   waves += worldPos.z * _waveZSize;

   // Add in time to model them over time
   waves += _Time.x * waveSpeed;

   float4 s, c;
   waves = frac (waves);
   FastSinCos (waves, s,c);

   float waveAmount = v.texcoord.y;
   s *= waveAmount;

   // Faste winds move the grass more than slow winds
   s *= normalize (waveSpeed);

   s = s * s;
   float fade = dot (s, 1.3);
   s = s * s;
   float3 waveMove = float3 (0,0,0);
   waveMove.x = dot (s, _waveXmove);
   waveMove.z = dot (s, _waveZmove);
   
   v.vertex.xz -= mul ((float3x3)_World2Object, waveMove).xz;
   v.vertex.xz += bendDir.xz*distMulti*v.texcoord.y*v.texcoord.y*1.5; //ADD OBSTACLE BENDING
   
   o.pos = mul(glstate.matrix.mvp, v.vertex);
   o.fog = o.pos.w;
   o.uv = v.texcoord;
   o.color = lerp (_Color, _Color2, fade.xxxx);
//   o.color *= _SkyLight;
   return o;
}
ENDCG
         AlphaTest Greater [_Cutoff]
         Cull Off
         SetTexture [_MainTex] { combine texture * primary double, texture}
         
      }
   }   
   SubShader {   
      Tags { "Queue" = "Transparent" }
      Pass {
         Blend SrcAlpha oneMinusSrcAlpha
         AlphaTest Greater [_Cutoff]
         Cull Off
         color [_Color]
         ZTest Less
         SetTexture [_MainTex] { combine texture * primary DOUBLE, texture}
      }

   }
}


/P
Back to top
View user's profile Send private message Visit poster's website
jeremyace



Joined: 12 Oct 2005
Posts: 1651
Location: Ontario, Canada

PostPosted: Tue Jul 31, 2007 9:13 am    Post subject: Reply with quote
Awesome. Thanks a lot for sharing and also for explaining it. Much appreciated. Wink

-Jeremy

_________________
Lead Developer
Ennanzus Interactive

Unity Feed Reader - version 1.5 released! Now parses all major news syndication formats.

GUI-eXtended - UI System and Visual Designer
Back to top
View user's profile Send private message Visit poster's website
metervara



Joined: 15 Jun 2006
Posts: 201
Location: Copenhagen

PostPosted: Tue Jul 31, 2007 9:47 am    Post subject: Reply with quote
Would love to see implementations or variations of it Smile

/P
Back to top
View user's profile Send private message Visit poster's website
rawrman2381238



Joined: 28 Jan 2008
Posts: 122

PostPosted: Fri Mar 20, 2009 3:51 am    Post subject: Reply with quote
Can someone make a unity package as I am unsure how to se this up... It looks awesome though!
Back to top
View user's profile Send private message
God at play



Joined: 03 Nov 2006
Posts: 105
Location: Des Moines, IA

PostPosted: Sat Jul 04, 2009 7:07 am    Post subject: Reply with quote
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:
Shader "Dynamic Grass"
{
   Properties
   {
      _Color ("Main Color", Color) = (.055, .094, .082, 1)
      _Color2 ("Fade Color", Color) = (.09, .157, .137, 1)
      _WaveX ("Wave X", Vector) = (.07, .01, .01, 0.01)
      _WaveZ ("Wave Z", Vector) = (-.07, .01, .01, 0.01)
      _WaveSpeed ("Wave Speed", Vector) = (1, 1.5, 1.1, .9)
   }
   SubShader
   {
      Tags { "Queue" = "Transparent" }
      
      Pass
      {
         Lighting On
         
         CGPROGRAM
         #pragma vertex Vertex
         
         #include "waves.cginc"      // Get in the helper wave functions
         #include "UnityCG.cginc"    // Get standard Unity constants
         
         struct v2f
         {
            float4 pos : POSITION;
            float4 color : COLOR0;
            float4 uv : TEXCOORD0;
            float fog : FOGC;
         };
         
         uniform float4 _Color, _Color2, _WaveX, _WaveZ, _WaveSpeed;
         uniform float3 _obstacle;
         uniform float _affectDist, _bendAmount;
         
         v2f Vertex(appdata_base v)
         {
            v2f o;
            
            const float4 _waveXSize = _WaveX * 2;
            const float4 _waveZSize = _WaveZ * 2;
            const float4 waveSpeed = _WaveSpeed * 4;
            
            float4 _waveXmove = _waveXSize * waveSpeed * 25;
            float4 _waveZmove = _waveZSize * waveSpeed * 25;
            
            // Calculate the wind input to leaves from their vertex positions....
            float3 worldPos = mul ((float3x4)_Object2World, v.vertex);
            
            // OBSTACLE AVOIDANCE CALC
            float3 bendDir = normalize (float3(worldPos.x,0,worldPos.z) - float3(_obstacle.x,0,_obstacle.z));//direction of obstacle bend
            float distLimit = _affectDist;// how far away does obstacle reach
            float distMulti = (distLimit-min(distLimit,distance(float3(worldPos.x,0,worldPos.z),float3(_obstacle.x,0,_obstacle.z))))/distLimit; //distance falloff
            //OBSTACLE AVOIDANCE END
            
            // This is the input to the sinusiodal warp
            float4 waves;
            waves = worldPos.x * _waveXSize;
            waves += worldPos.z * _waveZSize;
            
            // Add in time to model them over time
            waves += _Time.x * waveSpeed;
            
            float4 s, c;
            waves = frac (waves);
            FastSinCos (waves, s,c);
            
            float waveAmount = v.texcoord.y;
            s *= waveAmount;
            
            // Faste winds move the grass more than slow winds
            s *= normalize (waveSpeed);
            
            s = s * s;
            float fade = dot (v.texcoord.y * v.texcoord.y, 2);
            s = s * s;
            float3 waveMove = float3 (0,0,0);
            waveMove.x = dot (s, _waveXmove);
            waveMove.z = dot (s, _waveZmove);
            
            v.vertex.xz -= mul ((float3x3)_World2Object, waveMove).xz;
            v.vertex.xz += bendDir.xz * distMulti * v.texcoord.y * v.texcoord.y * _bendAmount; //ADD OBSTACLE BENDING
            
            o.pos = mul(glstate.matrix.mvp, v.vertex);
            o.fog = o.pos.w;
            o.uv = v.texcoord;
            o.color = lerp (_Color, _Color2, fade.xxxx);
            return o;
         }
         ENDCG
         
         AlphaTest Greater [_Cutoff]
         Cull Off
      }
   }
   
   SubShader
   {
      Tags { "Queue" = "Transparent" }
      Pass
      {
         Blend SrcAlpha oneMinusSrcAlpha
         AlphaTest Greater [_Cutoff]
         Cull Off
         color [_Color]
         ZTest Less
      }
   }
}


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:
#pragma strict

@script ExecuteInEditMode

var affectDist : float = 8;
var bendAmount : float = 5;

private var myTransform : Transform;

function Awake()
{
   SetBend();
   
   myTransform = transform;
}

function Update() : void
{
   Shader.SetGlobalVector("_obstacle", myTransform.position);
   
   if (Input.GetButton("Jump"))
   {
      if (affectDist < 22)
      {
         affectDist += 3;
         bendAmount += 0.3;
         
         SetBend(affectDist, bendAmount);
      }
      
      if (affectDist > 20)
      {
         affectDist = 20;
         bendAmount = 6.2;
         
         SetBend(affectDist, bendAmount);
      }
   }
   else
   {
      if (affectDist > 8)
      {
         affectDist -= 4;
         bendAmount -= 0.6;
         
         SetBend(affectDist, bendAmount);
      }
      else
      {
         SetBend();
      }
   }
}

function SetBend(_affectDist : float, _bendAmount : float) : void
{
   Shader.SetGlobalFloat("_affectDist", _affectDist);
   Shader.SetGlobalFloat("_bendAmount", _bendAmount);
}

function SetBend() : void
{
   SetBend(8, 5);
}


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.



Picture 1.png


_________________
/////////////////////////
God at play - http://www.godatplay.com
Part of the Intuition collective
Portfolio
@godatplay
/////////////////////////
Back to top
View user's profile Send private message Visit poster's website
larzie



Joined: 18 Mar 2008
Posts: 34
Location: Copenhagen

PostPosted: Sat Jul 25, 2009 6:54 pm    Post subject: Reply with quote
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
Back to top
View user's profile Send private message Visit poster's website
showoff



Joined: 28 Apr 2009
Posts: 170
Location: Atlanta, Ga

PostPosted: Tue Aug 04, 2009 12:19 am    Post subject: Reply with quote
Im also having problems with the shader aswell. I cant seem to get either of the shaders working either.
_________________
________________________________

3D Graphic Artist
http://www.andresmaximumcgi.com/
________________________________
Back to top
View user's profile Send private message Visit poster's website
God at play



Joined: 03 Nov 2006
Posts: 105
Location: Des Moines, IA

PostPosted: Fri Aug 14, 2009 10:18 pm    Post subject: Reply with quote
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:
Shader "Dynamic Grass"
{
   Properties
   {
      _Color ("Main Color", Color) = (.055, .094, .082, 1)
      _Color2 ("Fade Color", Color) = (.09, .157, .137, 1)
      _WaveX ("Wave X", Vector) = (.07, .01, .01, 0.01)
      _WaveZ ("Wave Z", Vector) = (-.07, .01, .01, 0.01)
      _WaveSpeed ("Wave Speed", Vector) = (1, 1.5, 1.1, .9)
   }
   SubShader
   {
      Tags { "Queue" = "Transparent" }
      
      Pass
      {
         Lighting On
         
         CGPROGRAM
         #pragma vertex Vertex
         
         #include "waves.cginc"      // Get in the helper wave functions
         #include "UnityCG.cginc"    // Get standard Unity constants
         
         struct v2f
         {
            float4 pos : POSITION;
            float4 color : COLOR0;
            float4 uv : TEXCOORD0;
            float fog : FOGC;
         };
         
         uniform float4 _Color, _Color2, _WaveX, _WaveZ, _WaveSpeed;
         uniform float3 _obstacle;
         uniform float _affectDist, _bendAmount;
         
         v2f Vertex(appdata_base v)
         {
            v2f o;
            
            const float4 _waveXSize = _WaveX * 2;
            const float4 _waveZSize = _WaveZ * 2;
            const float4 waveSpeed = _WaveSpeed * 4;
            
            float4 _waveXmove = _waveXSize * waveSpeed * 25;
            float4 _waveZmove = _waveZSize * waveSpeed * 25;
            
            // Calculate the wind input to leaves from their vertex positions....
            float3 worldPos = mul ((float3x4)_Object2World, v.vertex);
            
            // OBSTACLE AVOIDANCE CALC
            float3 bendDir = normalize (float3(worldPos.x,worldPos.y,worldPos.z) - float3(_obstacle.x,_obstacle.y,_obstacle.z));//direction of obstacle bend
            float distLimit = _affectDist;// how far away does obstacle reach
            float distMulti = (distLimit-min(distLimit,distance(float3(worldPos.x,worldPos.y,worldPos.z),float3(_obstacle.x,_obstacle.y,_obstacle.z))))/distLimit; //distance falloff
            //OBSTACLE AVOIDANCE END
            
            // This is the input to the sinusiodal warp
            float4 waves;
            waves = worldPos.x * _waveXSize;
            waves += worldPos.z * _waveZSize;
            
            // Add in time to model them over time
            waves += _Time.x * waveSpeed;
            
            float4 s, c;
            waves = frac (waves);
            FastSinCos (waves, s,c);
            
            float waveAmount = v.texcoord.y;
            s *= waveAmount;
            
            // Faste winds move the grass more than slow winds
            s *= normalize (waveSpeed);
            
            s = s * s;
            float fade = dot (v.texcoord.y * v.texcoord.y, 2);
            s = s * s;
            float3 waveMove = float3 (0,0,0);
            waveMove.x = dot (s, _waveXmove);
            waveMove.z = dot (s, _waveZmove);
            
            v.vertex.xz -= mul ((float3x3)_World2Object, waveMove).xz;
            v.vertex.xz += bendDir.xz * distMulti * v.texcoord.y * v.texcoord.y * _bendAmount; //ADD OBSTACLE BENDING
            
            //optional y bending
            //v.vertex.xyz += bendDir.xyz * distMulti * v.texcoord.y * v.texcoord.y * _bendAmount; //ADD OBSTACLE BENDING
            
            o.pos = mul(glstate.matrix.mvp, v.vertex);
            o.fog = o.pos.w;
            o.uv = v.texcoord;
            o.color = lerp (_Color, _Color2, fade.xxxx);
            return o;
         }
         ENDCG
         
         AlphaTest Greater [_Cutoff]
         Cull Off
      }
   }
   
   SubShader
   {
      Tags { "Queue" = "Transparent" }
      Pass
      {
         Blend SrcAlpha oneMinusSrcAlpha
         AlphaTest Greater [_Cutoff]
         Cull Off
         color [_Color]
         ZTest Less
      }
   }
}


Bend affect script attached to obstacle object:

Code:
#pragma strict

@script ExecuteInEditMode

var affectDist : float = 20;
var bendAmount : float = 5;

private var myTransform : Transform;

function Awake()
{   
   myTransform = transform;
}

function Update()
{
   Shader.SetGlobalVector("_obstacle", myTransform.position);
   
   Shader.SetGlobalFloat("_affectDist", _affectDist);
   Shader.SetGlobalFloat("_bendAmount", _bendAmount);
}



waves.cginc.zip
 Description:
waves.cginc file

Download
 Filename:  waves.cginc.zip
 Filesize:  1.21 KB
 Downloaded:  228 Time(s)


_________________
/////////////////////////
God at play - http://www.godatplay.com
Part of the Intuition collective
Portfolio
@godatplay
/////////////////////////
Back to top
View user's profile Send private message Visit poster's website
Post new topic   Reply to topic    Unity Community Index // ShaderLab All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum