I started trying to use shaders yesterday wanting to implement non uniform scaling in a shader, the following is what works in unityscript, every frame the object’s scale either goes up or down a step.
var scale : float = 1.0;
var step : float = 0.1;
var lowerBound : float = 1.0;
var upperBound : float = 5.0;
function Update () {
var randomchoiceAnim : float = Random.value;
if (randomchoiceAnim < 0.5)
{
scale += step;
}
else
{
scale -= step;
}
scale = Mathf.Clamp(scale,lowerBound,upperBound);
transform.localScale.y = scale;
}
I have read a lot of posts but wanted to clarify a few questions I have about shaders.
- Is there a way to declare a variable outside the shader then update it every time the shader runs?
as in UnityScript
var myInt : int = 1;
Update()
{
myInt +=1;
Debug.Log(myInt); // myInt keeps getting bigger
}
-
Alternatively is there a way to get hold of the most recently updated vertex positions? So v.vertex.y *= 1.1 would keep scaling everything up. In my attempts it seems that the shader is passed the original vertex positions when it starts up and only has access to those- is this correct?
-
If neither of the above are possible is there a third way - I really don’t want to have to run my logic in Unityscript and send the scale value using renderer.material.setFloat… this is running on 10k objects and the appeal of shaders was their speed.
-
If none of the above work _Time seems like the only variable which a shader has access to that is constantly changing. I have found a pseudo random number generator but can’t figure out the correct combination of _Time, possibly fmod and or lerp to produce the desired results- does anyone have any ideas or at least know if this is logically possible? -I’m happy to bang my head against a wall if I know it’s logically possible.
Here is what I’ve got so far
Shader "VertexInputSimple" {
Properties {
_ScaleInput ("_ScaleInput", Float) = 1 // sets up a variable in the inspector that can be accessed from unityscript
}
SubShader {
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float _ScaleInput; // sets up variable to be used in the shader
struct v2f {
float4 pos : SV_POSITION;
fixed4 color : COLOR;
};
float rand_1_05(in float2 uv) // pass it 2 floats and you get a pseudo random float between 0 and 1
{
float2 noise = (frac(sin(dot(uv ,float2(12.9898,78.233)*2.0)) * 43758.5453));
return abs(noise.x + noise.y) * 0.5;
}
v2f vert (appdata_base v)
{
v2f o;
float2 seed = ( _Time , _Time * 100 ); // create a float2 as a seed
float random = rand_1_05( seed ); // pass the float2 to the function rand_1_05, which returns between 0 and 1
float mod = fmod(_Time.y,4.0) + 1; // Time.y is the time in seconds, +1 to bring into range 1 to 5
float value;
if ( random > 0.5 )
{
value = smoothstep(1,5,mod)+1;
}
else
{
value = smoothstep(5,1,mod+1);
}
v.vertex.y *= mod;
//v.vertex.y *= value;
//v.vertex.y *= _ScaleInput; //This way scales according to the value in the inspector ( and is very slow 50ms vs 10ms on 10k objects )
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.color.xyz = v.normal * 0.5 + 0.5;
o.color.w = 1.0;
return o;
}
fixed4 frag (v2f i) : COLOR0 { return i.color; }
ENDCG
}
}
}