Search Unity

  1. Unity 2020.1 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

HLSL sine/cosine

Discussion in 'Shaders' started by Cherubim79, Aug 26, 2018.

  1. Cherubim79

    Cherubim79

    Joined:
    May 3, 2014
    Posts:
    55
    Is there a way to get doubles to work with sine and cosine on GPU compute shaders? I suppose you could roll your own functions to support doubles, but I just wonder if they're using anything faster than a Taylor series or CORDIC on the GPU for calculation of sine/cosine?

    I discovered a new mathematical formula based on the Discrete Fourier transform that lets you output any array size of frequency domain for a given input array of time based samples, allowing me to get music frequencies based on piano pitches rather than an even distribution that the DFT/FFT normally produces, especially with the FFT requiring powers of 2, for complex number analysis of music.

    So I'm basically rebuilding Unity's FFT on the GPU, and it works, but I want to test with doubles. The sine and cosine operations on HLSL intrinsic functions only output floats though.
     
  2. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    195
  3. Cherubim79

    Cherubim79

    Joined:
    May 3, 2014
    Posts:
    55
  4. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    195
    Code (CSharp):
    1. double mod(double a,double b)
    2. {
    3.     return (a>0) ? a-(((int)(a/b))*b) : -a+(((int)(a/b))*b);
    4. }
    5.  
    6. double sinus(double theta)
    7. {
    8.     double PI = 3.14159265358979323846;
    9.     theta = mod(theta+PI/2.0, PI*2.0)-PI/2.0;
    10.     if (theta > PI/2.0)
    11.         theta = PI - theta;
    12.     double x3 = (theta*theta*theta);
    13.     double x5 = (x3*theta*theta);
    14.     return theta - x3/6.0 + x5/120.0;
    15. }
     
    Cherubim79 likes this.
  5. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    195
    Fix for mod function:
    Code (CSharp):
    1. double mod(double a,double b)
    2. {
    3.     return (a>0)?a-b*((int)(a/b)):-(-a+b*(((int)(a/b))));
    4. }
     
    Cherubim79 likes this.
  6. Cherubim79

    Cherubim79

    Joined:
    May 3, 2014
    Posts:
    55
    This is wonderful thank you very much Przemyslaw_Zaworski!
     
  7. Przemyslaw_Zaworski

    Przemyslaw_Zaworski

    Joined:
    Jun 9, 2017
    Posts:
    195
    It seems there is an inconsistency between C++ fmod and GLSL mod. So next fix and there is the final code :

    Code (CSharp):
    1. double sinus(double theta)
    2. {
    3.     double PI = 3.14159265358979323846;
    4.     double a = theta+PI/2.0, b = PI*2.0;
    5.     theta = ((a>0)?a-b*((int)(a/b)):(-a+b*(((int)(a/b)))))-PI/2.0;
    6.     if (theta > PI/2.0)
    7.         theta = PI - theta;
    8.     double x3 = (theta*theta*theta);
    9.     double x5 = (x3*theta*theta);
    10.     return theta - x3/6.0 + x5/120.0;
    11. }
    12.  
    13. double cosinus(double x)
    14. {
    15.     return sinus(x+1.57079632679489661923);
    16. }
     
unityunity