Search Unity

Resolved Recorder Writting Exr Files With Time Based Shader Are Wrong

Discussion in 'Shader Graph' started by kFreezer, Apr 16, 2019.

  1. kFreezer

    kFreezer

    Joined:
    Mar 15, 2019
    Posts:
    29
    Hi everyone,

    I initially posted this thread elsewhere but I think it is more accurate to post it here as it is more a shader issue than a Recorder/Timeline one.

    I'm working on a film project done with unity and I'm investigating into the Unity recorder to do EXR exports and I noticed that my time based water shader was way too fast than it should be.

    In my test I'm rendering an image sequence at 4K 24fps 16:9, which gives me 0.5 fps in the Game View because of the time to write the exr files.

    I assume the rendered water shader is too fast because the game clock is running even if i'm stuck at 0.5 fps. So is there a way to render something like this without a time node but with something that takes in account the framerate I'm rendering at?

    What would be great is that the recorder records the result I get when I'm running the sequence in Game Mode without recording.

    @jasonm_unity3d answered me with this
    Now my problem is that I don't code at all and that I've done the shader with shadergraph. Sadly it seems like there's only the Time node with the following values:
    Yesterday I fake fixed my issue by reducing the speed of the water but it isn't a good way to work as I must guess the speed. Plus it means I would have to change the value each time I want to switch between render or preview in real time.

    So now I've been trying to research and understand what these do but I can't find a way to replicate it and fix my problem.

    Thanks
     
  2. alexandral_unity

    alexandral_unity

    Unity Technologies

    Joined:
    Jun 18, 2018
    Posts:
    163
    Have you tried driving it with Delta time instead of Time? That's my first guess that might help, otherwise this is something we'd need an official bug reported for to test and fix.
     
  3. Jesus

    Jesus

    Joined:
    Jul 12, 2010
    Posts:
    504
    Instead of time (defined in the shader by that node) you can set an variable in the shader, call it FunctionalTime or something (up to you) and then manually set it by shader.setfloat or shader.setglobalfloat with a c# script.

    That allows you to integrate it with any other time scripting you've got going on that works at 0.5fps.

    IE if you're going for 24fps, then after each frame is rendered it would increase the FunctionalTime value by (1/24).
     
  4. kFreezer

    kFreezer

    Joined:
    Mar 15, 2019
    Posts:
    29
    I already tried with delta time (and smoothed) and the movement of the water goes back and forth in position in a very laggy way. I might be doing something wrong as I'm pretty new at using the shader graph.
    Every tutorials I've looked at use the following technique to animate. Is changing the Time node to Delta Time requires to do something more? As it only counts the seconds between each frame.
    upload_2019-4-17_9-58-16.png


    (Also I noticed I haven't said which version of Unity I'm working with; 2018.3.2 with HDRP 4.6.0 so it may be the reason of it not working correctly. I'm going to try with a newer version of Unity and see if I get the same result).
     
  5. kFreezer

    kFreezer

    Joined:
    Mar 15, 2019
    Posts:
    29
    I think I get what you're telling me but I'm sorry I'm not a tech artist and I have no knowledge of c# to do what you proposed, I will see with my team if someone has some time to try and do this.
     
  6. kFreezer

    kFreezer

    Joined:
    Mar 15, 2019
    Posts:
    29
    Alright the issue can be recreated in 2019.1 Delta Time doesn't offset the texture and Time makes the water go crazy fast when rendering 4k exr files

    [edit] I tried also with the visual effect graph and I'm glad it doesn't have the same issue, it renders correctly
    I suppose the vfx graph is clocked with another timer than the shader graph which is puzzling me. Is it because one is calculated on GPU and not the other?
     
    Last edited: Apr 17, 2019
  7. Jesus

    Jesus

    Joined:
    Jul 12, 2010
    Posts:
    504
    Here's some more info on setglobalfloat:

    https://docs.unity3d.com/ScriptReference/Shader.SetGlobalFloat.html

    In your shader graph, you create a variable like any other, a vector1. Then you make it a property that moves it to the blackboard. The exposed button, you want to UN-TICK that. Also note the internal shader name (forget what they call it, but it's not the main name of the value, usually it'll be FLOAT+01231324 or something).

    I'm out of date with the Unity recorder, but if you can access the script, then you want to add a new float called FunctionalTime or ManualTime or something you can remember.

    Then you want to add to the value on pre or post-render.
     
  8. kFreezer

    kFreezer

    Joined:
    Mar 15, 2019
    Posts:
    29
    Thanks a lot for your help! Combined to some tutorials on YT I managed to write a super basic c# script:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class FunctionRenderTime : MonoBehaviour
    6. {
    7.     public Material waterOffset;
    8.     public float timingValue;
    9.     public float timer;
    10.     // Start is called before the first frame update
    11.     void Start()
    12.     {
    13.         waterOffset.SetFloat("Vector1_3236E2C5", timer);
    14.     }
    15.  
    16.     // Update is called once per frame
    17.     void Update()
    18.     {
    19.         timer += timingValue * Time.deltaTime;
    20.         waterOffset.SetFloat("Vector1_3236E2C5", timer);
    21.     }
    22. }
    23.  
    Now it renders at the same speed in both Game Mode and in the exr render

    [edit] the naming is very specific but it is very easy to make this script flexible
     
    Last edited: Apr 17, 2019
  9. eeddddd

    eeddddd

    Joined:
    Nov 13, 2017
    Posts:
    5
    @kevinFreezer would you mind elaborating on how you connected your script to shader graph.
    I'm getting the following error:
    UnassignedReferenceException: The variable waterOffset of FunctionRenderTime has not been assigned. You probably need to assign the waterOffset variable of the FunctionRenderTime script in the inspector.
    I've updated the code to reflect Vector1_4A80CB37.
    See attached image for SG workflow.
    I'm using Unity 2019.1.3f1 and Shader Graph 5.13.0.
    Any suggestions would be awesome!

    Screen Shot 2019-05-26 at 3.18.28 pm.jpg
     
  10. Jesus

    Jesus

    Joined:
    Jul 12, 2010
    Posts:
    504
    In this case waterOffset is a material, you have to assign it to its slot in the script, wherever that is in your Scene.

    And since you can, you should change Vector1_13123087r1 to an actual name, both in the script and the shader graph. Click the field called Reference in SGE and call it something descriptive, usually the same as the variable (or WaterOffsetVector). You might end up expanding on things later, so keeping hings readable can help.
     
    kFreezer likes this.
  11. eeddddd

    eeddddd

    Joined:
    Nov 13, 2017
    Posts:
    5
    @Jesus !! Amazing thanks so much, just missed that last bit.
    I've attached as screenshot and SGE for others to reference.

    Screen Shot 2019-05-27 at 4.53.05 pm.jpg

    Screen Shot 2019-05-27 at 2.06.22 pm.jpg
     
  12. ArchVizPRO

    ArchVizPRO

    Joined:
    Apr 27, 2014
    Posts:
    457
    Worked for me too. Thank you so much !