• Godot Help3D
  • Lost at step one and two on this official tutorial

I'm trying to follow a tutorial at
https://docs.godotengine.org/en/stable/tutorials/performance/vertex_animation/animating_thousands_of_fish.html

and I'm lost at the first step:

//time_scale is a uniform float
float time = TIME * time_scale;

Where and how are TIME and time_scale defined? Is this code meant to go in a script or in the shader? It throws up various errors in each place as I try to work with it.

The next step is equally vague:

//side_to_side is a uniform float
VERTEX.x += cos(time) * side_to_side;

Where is this code going? I'm very frustrated, this tutorial is like a lot of tutorials I've seen where it is assumed you know things you don't. Progress is very slow most days I get to use Godot becuase of this 🙁

  • lincore and Haystack replied to this.
  • valid code:

    shader_type spatial;
    
    uniform float time_scale = 0.5;
    uniform float side_to_side = 0.5;
    
    void vertex() {
    	VERTEX.x += cos(time_scale * TIME) * side_to_side;
    }

    Apparently, there must be a specific value in the uniforms — it becomes available in the inspector.

    ScoutMoreOften
    Yes, this is shader code. I think this is a somewhat advanced tutorial where it's expected that you know how to write the boilerplate code. Not every tutorial can be for everybody or they would all have the length of an encyclopedia. When you learn something complex like game development, it's your responsibility to decide what material is for you at what time. Then again, it would be nice if the tutorial clearly stated what you should know before trying it.

    I don't know much about shaders, but the comment seems to suggest that you should provide time_scale as a uniform float. That is a bit like a global variable that you can change from outside the shader. TIME is a built-in variable that godot provides.

    If you really want to understand this tutorial, maybe you should start a bit simpler with Godot's shader documentation: https://docs.godotengine.org/en/stable/tutorials/shaders/index.html
    But then again, maybe you're just not ready for shaders and need to learn other things first, I couldn't tell.

    TIME could be like the delta from _process(). Or it might even be entire TIME from shader start, I forget which.
    time_scale very well could be anything you would like it to be. using a value of 1.0 for 1 whole second.
    side_to_side should be a distance value, at least this is what it looks like.

    You may have to create your own time_scale and side_to_side.

    EDIT: yes, I think TIME is entire shader start to end loop for each part of the drawing process. So giving it a time_scale makes sense.

    @ScoutMoreOften

    I had the same problem with water shader tutorial before.
    https://godotforums.org/d/30053-confuse-on-the-doc-s-your-second-3d-shader-water-tutorial/6

    As for the school of fish I don't know but for the basic idea for the Shader script:
    -float is like var
    -uniform is like export var
    -codes in void vertex() are for controlling the shape (3d model's vertices)
    -codes in void fragment() are for controlling appearance (color, texture..etc)

    so VERTEX.x += cos(time) * side_to_side; should be placed in vertex()..etc

    But yea they should've included the final codes or example project for us to study.

      Gowydot I had the same problem with water shader tutorial before.

      Yep, there are problems with that tutorial.

      ScoutMoreOften

      Where and how are TIME and time_scale defined?

      I found the following by entering "TIME" and "time_scale" into the search box of the Godot docs.

      https://docs.godotengine.org/en/stable/tutorials/shaders/shader_reference/canvas_item_shader.html?highlight=time_scale#global-built-ins

      Built-in

      Description

      in float TIME

      Global time since the engine has started, in seconds (always positive). It's subject to the rollover setting (which is 3,600 seconds by default). It's not affected by time_scale or pausing, but you can override the TIME variable's time scale by calling VisualServer.set_shader_time_scale() with the desired time scale factor as parameter (1.0 being the default).

        Haystack I think (I could be wrong) that's for 2d only? Regardless, I cannot seem to access TIME automatically in a vertex shader. My code right now is:

        shader_type spatial;
        
        uniform float time = TIME * time_scale;
        uniform float time_scale = 0.5
        uniform float side_to_side = 0.5
        
        void vertex() {
        	VERTEX.x += cos(time) * side_to_side;
        }

        And my error message is

        error(3): unknown identifier in expression: TIME

          valid code:

          shader_type spatial;
          
          uniform float time_scale = 0.5;
          uniform float side_to_side = 0.5;
          
          void vertex() {
          	VERTEX.x += cos(time_scale * TIME) * side_to_side;
          }

          Apparently, there must be a specific value in the uniforms — it becomes available in the inspector.

          Thanks all for your contributions, this is a very supportive community and the occasional moments of frustration with Godot are compensated for by the assistance recieved here 🙂

          LOL sadly, I'm back already. I just can't get this code to work. The bit I really want is the 4th picture where a wave goes along the body of the fish. It's an incredible look. I have the code working, it just doesn't perform as expected...

          
          shader_type spatial;
          
          uniform float TIME;
          uniform float time_scale = 3; // + means more speed
          uniform float wave = 0.5;
          
          
          void vertex() {
          	float time = TIME * time_scale;
          	float body = (VERTEX.x + 1.0) / 2.0; //for a fish centered at (0, 0) with a length of 2
          	VERTEX.x += cos(time + body) * wave;

          I could be wrong (as usual) but I don't think the earlier bits of code in the tutorial affect this stage. Help me Obi-Wan you're my only hope!

            ScoutMoreOften uniform float time = TIME * time_scale;

            The reason this declaration doesn't work is b/c the initializer expression (the part to the right of the equals sign) must be resolvable at compile time.

            The value of TIME is not known at compile time. It's not known until runtime, and changes every frame. So you can use it inside a shader function, but you can't use it to initialize the default value of a uniform.

            ScoutMoreOften have the code working, it just doesn't perform as expected...

            So how does it perform? What's different between what it does now vs what you were expecting? It's hard to make suggestions without knowing more details about the issues you are hitting.

            shader_type spatial;
            
            uniform float time_scale = 0.5;
            uniform float side_to_side = 0.5;
            uniform float pivot = 0.5;
            uniform float wave = 0.5;
            
            
            void vertex() {
            	float time = TIME * time_scale;
            	float body = (VERTEX.z + 1.0) / 2.0;
            //	VERTEX.x += cos(time) * side_to_side;
            	float pivot_angle = cos(time) * 0.1 * pivot;
            	mat2 rotation_matrix = mat2(vec2(cos(pivot_angle), -sin(pivot_angle)), vec2(sin(pivot_angle), cos(pivot_angle)));
            //	VERTEX.xz = rotation_matrix * VERTEX.xz;
            	VERTEX.x += cos(time + body) * wave;
            }

            If you uncomment the strings, the motion pattern will change.

              Tomcat Thanks for your efforts on this Tomcat. But I'm still not seeing an effect similar to the 4th fish picture, just below the text
              "This looks very similar to the side to side motion we defined above, but in this one, by using body to offset cos each vertex along the spine has a different position in the wave making it look like a wave is moving along the fish."

              When I use your code, my mesh just sort of slides backwards and forwards as a solid block. As opposed to the effect shown which is more like a ripple making it's way along the mesh. If it's working for you, then there must be something else I am doing wrong? Hmm...

                Hmm, the plot thickens. I had been using a generic cylinder mesh which wasn't working. I am now using the suggested mesh from the tutorial (didn't realise it would matter, my bad) and the effect is now partially working on most of the mesh. Will go through the tutorial and see if I can see why part of the fish is static...

                I suspect a deep dive into meshes is in my future... looks like the shader effect is only applying to the first material, and there are a total of three...

                (Tomcat i'm on 3.4.4 stable)

                  ScoutMoreOften looks like the shader effect is only applying to the first material,

                  Yep. Or rather, it is applied to the selected material.

                    Tomcat Thanks, I applied it individually to all 3 and now everything works and lovely it looks too ! Huge thanks for your input mate! One last q, is one shader for each material like this efficient or can/should I try to sort it so that one shader is applying to all 3 materials?

                    I'm new at all this so aware I need my code to be efficient but don't know what causes issues or not. I'm thinking if I had loads of fish on screen for example.

                    Animating_Fish (Godot 3.5.1)

                    I've just started studying shaders too, so I can't answer exactly. 🙂 In my example, I assigned a shader to each material separately, but it's probably possible to assign a general motion with color preservation. But it does get a bit confusing.