I am only speaking about the code in vertexDataFunc at the bottom. Seems changing the value to like 2 or 0 works, but if i want to slooowly change it every frame, by doing something like -=0.01 then it produces wrong results
CODE
Shader "Sassy/Trees"
{
Properties
{
_MainTexture("_MainTexture", 2D) = "white" {}
_WindPower("WindPower", Float) = 0
}
SubShader
{
Tags{ "RenderType" = "Opaque" "Queue" = "AlphaTest+0" "IgnoreProjector" = "True" "DisableBatching" = "True" "IsEmissive" = "true" }
Cull Off
Stencil
{
Ref 0
}
CGPROGRAM
#include "UnityShaderVariables.cginc"
#pragma target 3.0
#pragma instancing_options procedural:setup
#pragma multi_compile GPU_FRUSTUM_ON __
#include "VS_indirect.cginc"
#pragma surface surf Standard keepalpha addshadow fullforwardshadows vertex:vertexDataFunc
struct Input
{
float2 uv_texcoord;
};
uniform sampler2D _MainTexture;
float _WindPower;
float4 CalculateContrast( float contrastValue, float4 colorTarget )
{
float t = 0.5 * ( 1.0 - contrastValue );
return mul( float4x4( contrastValue,0,0,t, 0,contrastValue,0,t, 0,0,contrastValue,t, 0,0,0,1 ), colorTarget );
}
void vertexDataFunc( inout appdata_full v, out Input o )
{
UNITY_INITIALIZE_OUTPUT( Input, o );
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
float dist = distance(_WorldSpaceCameraPos.xyz, worldPos);
if (dist < 7)
{
if (_WindPower < 10) _WindPower += 0.01; // its not slowly increasing the value
}
else if (dist > 0)
{
if (_WindPower > 0) _WindPower -= 0.01 ;// its not slowly decreasing the value
}
Because the value of _WindPower is thrown away after each invocation of the shader. It’s a local copy of the value that’s used for the lifetime one pixel or vertex and no more. The only values that are kept are those the vertex or pixel shader output. Vertex shaders output a screen position, UVs, and maybe some extra data that gets passed onto the fragment shader. The fragment shader usually outputs a single color. Everything else is thrown away. So the value the vertex or pixel shader gets from _WindPower is always only the value you’ve set on the material and anything you do to that value in either the vertex or fragment shader only affects the value for that one vertex or fragment shader invocation.
If you think about how vertex shaders work a bit more it’ll make sense why it doesn’t. If you have a mesh with 100 vertices, that function is running once for each vertex. If your += 0.1 on _WindPower is saved, it would mean by the time you’ve gotten through your mesh it’ll have added to that value 100 times. It also would mean the GPU would have to calculate each vertex in serial, one after the other. The whole idea with GPUs is they’re massively parallel. The GPU could be calculating all 100 vertices at once in parallel.
If you want the value to increase, you’ll want to increase it on the material using a c# script, or use _Time.y * 0.1 to add to it, which is the game time since last level load.
oh it makes more sense now, its actually one of the things I assumed the issue would be.
The thing is I cant really use material bcuz this is shader of terrain trees, even if i somehow was able to access such material, would i be able to send each tree’s position to c# script?
How do you recommend to use time in this case? game time is constantly changing value but i need value that will go from current value to 0 slowly when player gets close, i cant imagine how can I use Time in this case
If you need to access the individual materials of each tree, then no, you can’t use the Unity terrain tree system because you do not have access to the individual tree materials.
A purely shader based approach would be to use _Time to animate some property of the vertex, and use the camera’s distance from the vertex to scale how much of the animation is applied.
// get world space distance to vertex
float3 worldPos = mul(unity_ObjectToWorld, float4(v.vertex.xyz, 1.0)).xyz;
float dist = length(worldPos - _WorldSpaceCameraPos.xyz);
// 0.0 at <=1 unit, 1.0 at >=5 units
float animStrength = smoothstep(1.0, 5.0, dist);
// simple anim
float sinWave = sin(_Time.y * 0.1);
v.vertex.x += sinWave * animStrength;