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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

problem moving vertexes in shader

Discussion in 'Shaders' started by frappydan, Oct 2, 2018.

  1. frappydan

    frappydan

    Joined:
    Aug 15, 2014
    Posts:
    4
    Have torus model indicating a landing zone on a tile in my game. Animates upward to indicate the destination of the player.

    Managed to make a shader that moves the vertices of my model from zero in the y to a limit (making if lift off the ground) then it's suppose to reset to 0 on the y and repeat the process. The raising up part works fine but after it resets the vertex.y to 0 it just seems to stop instead of adding the _scrollpos value to the vertex.y as it did initially. I have stared at this logic and for the life of me think it should work but I guess I'm missing something here.

    _ScrollY is range for the Limit to scroll vertexes

    _ScrollS is the amount to move the vertex each pass

    _scrollpos stores the value to be applied to vertex.y

    I've also tried to omit _scrollpos and used vertex.y += t and same result. Help!?

    void vert(inout appdata v, out Input o) {

    UNITY_INITIALIZE_OUTPUT(Input, o);

    if (_ScrollY != 0 && _ScrollS != 0) {

    float t = _Time * _ScrollS;

    _scrollpos += t;

    if (_ScrollY > 0 && _scrollpos > _ScrollY) {

    _scrollpos = 0;

    }

    else if (_ScrollY < 0 && _scrollpos < _ScrollY) {

    _scrollpos = 0;

    }

    }

    v.vertex.y = _scrollpos;

    }

    void surf(Input IN, inout SurfaceOutput o) {

    o.Albedo = tex2D(_MainTex, IN.uv_MainTex);

    }
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,230
    Shaders don't work like that. Outside of the local scope of each invocation of a shader (each vertex or pixel each frame) no data is retained apart from what's passed to the next shader stage (which is thrown out after that) or the final output color (which is also thrown out after being displayed on screen).

    To put it another way, the vertex data and shader properties that the vertex shader gets is a copy of that data, not a reference, and is thrown out as soon as the function returns. You can't write back to the original mesh, nor accumulate values in shader properties over multiple runs of the shader.

    Well, technically you can with creative usage of compute buffers and DX11, but then each vertex is accumulating to the same variable, so the rate then depends on the number of visible meshes using the shader, and their vertex counts, as to how fast the value accumulates.

    Also _Time is a float4, not a single float. It's also not the time delta, but total time since the last level load, divided by 20, unmodified, multiplied by two, and multiplied by three.
    https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html

    Instead you should be using a modulo (%) or frac(), like this:

    v.vertex.y = frac(_Time.y * _ScrollS) * _ScrollY;

    If you want it to always start at zero when it starts to animate you'll need to pass in the current time to the shader as an offset, like this:
    // c#
    myMaterial.SetFloat("_ScrollStartTime", Time.timeSinceLevelLoad);

    // shader
    v.vertex.y = frac((_Time.y - _ScrollStartTime) * _ScrollS) * _ScrollY;
     
    Duong216 likes this.
  3. Duong216

    Duong216

    Joined:
    Nov 21, 2021
    Posts:
    3
    Thanks @bgolus, this helped me fix a glitch in my shader when using frac() to scroll textures.