• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by mine12345super · Mar 17, 2018 at 08:53 AM · vertex shader

tanh of Unity shader does not work with a large argument,

The tanh() function of shaderlab does not work with a large argument, such as 100.

My environment is Unity 2017.2.03f (WIndows 64bit).

Here is minimum sample code using vertex shader in order to shift an object.

 Shader "Custom/tanh_test" {
     Properties{
         _MainTex("Texture", 2D) = "white" {}
         _Value("Value", float) = 1.0
     }
 
     SubShader {
         Tags {
             "RenderType" = "Opaque"
             "Queue" = "Background"
         }
 
         CGPROGRAM
 
         #pragma surface surf Lambert vertex:vert addshadow
         #pragma target 5.0
         #include "UnityCG.cginc"
 
         struct Input {
             float2 uv_MainTex;
         };
         sampler2D _MainTex;
         float _Value;
 
         void vert(inout appdata_full v) {
             v.vertex.z = v.vertex.z + tanh(_Value);
         }
 
         void surf(Input IN, inout SurfaceOutput o) {
             o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
         }
 
         ENDCG
     }
     Fallback "Diffuse"
 }

If the "_Value" becoms large like 100, the tanh(_Value) returns zero. Is this bug of Unity ??

Comment
Add comment · Show 3
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image hexagonius · Mar 17, 2018 at 09:13 AM 0
Share

just a thought since I have no idea, but could it be that for performance reasons and tanh approaching its upper bound at 1 quickly, that it's implemented using half or even fixed? since I don't know what happens in shaders passing larger values, it's just a guess.

avatar image hrishihawk · Mar 17, 2018 at 09:40 AM 0
Share

@$$anonymous$$e12345super how did you find you are getting a zero ?

avatar image mine12345super · Mar 17, 2018 at 09:50 AM 0
Share

Thanks for your answers.

Value is not fixed in my development, and want to change from around 1 to 250.

I use "if" state for checking the returned value becomes zero.

 if (tanh(_Value) == 0) {
 // do something
 }

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Bunny83 · Mar 17, 2018 at 01:02 PM

Well, indeed tanh seems to be only defined within some arbitrary range of about (+- 174.6733) after which it returns 0. This is probably due to the fact how tanh is implemented. The usual reference implementation is this:

 float tanh(float x)
 {
   float exp2x = exp(2*x);
   return (exp2x - 1) / (exp2x + 1);
 }

However the problem is that exp(2* 174) is around the limit of double floating point range. That means that the expression would turn in either huge / +inf which is 0 or (+inf / +inf) which is NaN (probably fixed to 0).


Does it have to be tanh? Usually it's simpler to use x/(1+abs(x)) which has a similar distribution but doesn't grow so fast. Look at those two images:

Tanh(x) vs x/(1+x)

Here's the same at a scale of 100

scale 100

The shader i used simply does this:

 fixed4 frag (v2f i) : SV_Target
 {
     float v = _Factor * i.worldPos.x;
     if (i.worldPos.y > 0)
         v = tanh(v);
     else
         v = v / (1+abs(v));
     fixed4 col = fixed4(v,-v,0,1);
     return col;
 }


tanhx-vs-x-over1absx.png (37.9 kB)
tanhx-vs-x-over1absx-100.png (16.7 kB)
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Mar 17, 2018 at 01:38 PM 0
Share

I've run a little test with System.$$anonymous$$ath.Tanh. It doesn't return to 0 so it most likely does some range checking before it calculates the result. Actually tanh(9) already saturates to 1. So it probably checks the parameter and if it's beyond +-10 it simply returns +-1.


So if you want to use tanh because you need the value to saturate to 1 you may just clamp the parameter of tanh between +-10 using tanh(clamp(x,-10,10))

avatar image mine12345super Bunny83 · Mar 17, 2018 at 02:55 PM 0
Share

Thanks for your answer.

I understood the internal limitation of float.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

76 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Rotating/Jiggling lots of coins using a Vertex shader 0 Answers

How to compute shadows in custom Surface Shaders? 0 Answers

Combine Vertex / Fragment and Surface Shader 0 Answers

Weird shader behavior , when displacing vertices. 1 Answer

Changing the color of individual particles 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges