Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Using the surf function to lerp a value by DeltaTime

Discussion in 'Shaders' started by jethrogillgren, May 19, 2018.

  1. jethrogillgren

    jethrogillgren

    Joined:
    Jan 11, 2017
    Posts:
    28
    Hi All,
    I want to lerp towards a value, using unity_DeltaTime. I put the following line in the surf function of my shader.

    Code (CSharp):
    1. theValue= lerp(theValue, targetValue, unity_DeltaTime );
    However, the result seems to be as if surf gets called once only. Is that right?
    I cannot find any documentation on the surf function.
     
  2. jethrogillgren

    jethrogillgren

    Joined:
    Jan 11, 2017
    Posts:
    28
    In case it helps, this is is the full Custom shader I expected would lerp the value.


    Code (Boo):
    1. Shader "Custom/TempTestShader" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.         _Glossiness ("Smoothness", Range(0,1)) = 0.5
    6.         _Metallic ("Metallic", Range(0,1)) = 0.0
    7.  
    8.         _LerpTest ("Test Lerp Target", Range(0,1)) = 1
    9.     }
    10.     SubShader {
    11.         Tags { "RenderType"="Opaque" }
    12.         LOD 200
    13.  
    14.         CGPROGRAM
    15.         // Physically based Standard lighting model, and enable shadows on all light types
    16.         #pragma surface surf Standard fullforwardshadows
    17.  
    18.         // Use shader model 3.0 target, to get nicer looking lighting
    19.         #pragma target 3.0
    20.  
    21.         sampler2D _MainTex;
    22.  
    23.         struct Input {
    24.             float2 uv_MainTex;
    25.         };
    26.  
    27.         half _Glossiness;
    28.         half _Metallic;
    29.         fixed4 _Color;
    30.  
    31.         half _LerpTest;
    32.         half _LerpTest_Current = 0;
    33.  
    34.         // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
    35.         // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
    36.         // #pragma instancing_options assumeuniformscaling
    37.         UNITY_INSTANCING_BUFFER_START(Props)
    38.             // put more per-instance properties here
    39.         UNITY_INSTANCING_BUFFER_END(Props)
    40.  
    41.         void surf (Input IN, inout SurfaceOutputStandard o) {
    42.             // Albedo comes from a texture tinted by color
    43.             fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
    44.             o.Albedo = c.rgb;
    45.             // Metallic and smoothness come from slider variables
    46.             o.Metallic = _Metallic;
    47.             o.Smoothness = _Glossiness;
    48.  
    49.             _LerpTest_Current = lerp (_LerpTest_Current, _LerpTest, unity_DeltaTime.x);
    50.             o.Alpha = _LerpTest_Current;
    51.         }
    52.         ENDCG
    53.     }
    54.     FallBack "Diffuse"
    55. }
    56.  
    I also tried adding my own Global Property (using a uniform float) and setting it via C# script using
     Shader.SetGlobalFloat ( "Unity_Delta_Time", Time.deltaTime );
     
    Last edited: May 19, 2018
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    You cannot accumulate values in a shader across frames. All of those variables are temporary per-frame, and per-vertex / per-pixel and are thrown out as soon as each fragment shader draws to screen.
     
  4. jethrogillgren

    jethrogillgren

    Joined:
    Jan 11, 2017
    Posts:
    28
    Thank-you, that would explain it!

    So is the only way to achieve the effect is to Lerp in C#, and set a shader Property every frame?

    When I tested that I found my shader was very slow with Device.present when on a mobile platform.

    Is setting Shader properties every frame generally a done thing? Or is too costly for mobile platforms?
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    It is a way, and it works perfectly fine. The alternative is to pass a start time to the shader. The _Time.y value is equivalent to Time.timeSinceLevelLoad, so you can pass a begin time along with the duration, start, and end values. Then you only have to set it the one time when it starts.

    o.Alpha = lerp(_StartAlpha, _EndAlpha, saturate((_Time.y - _BeginTime) / _LerpDuration));