Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fast, inaccurate sin function without lookup

For an ocean shader, I need a fast function that computes a very approximate value for sin(x). The only requirements are that it is periodic, and roughly resembles a sine wave.

The taylor series of sin is too slow, since I'd need to compute up to the 9th power of x just to get a full period.

Any suggestions?

EDIT: Sorry I didn't mention, I can't use a lookup table since this is on the vertex shader. A lookup table would involve a texture sample, which on the vertex shader is slower than the built in sin function. It doesn't have to be in any way accurate, it just has to look nice.

like image 638
Hannesh Avatar asked Aug 23 '11 15:08

Hannesh


3 Answers

Use a Chebyshev approximation for as many terms as you need. This is particularly easy if your input angles are constrained to be well behaved (-π .. +π or 0 .. 2π) so you do not have to reduce the argument to a sensible value first. You might use 2 or 3 terms instead of 9.

like image 179
Jonathan Leffler Avatar answered Oct 06 '22 22:10

Jonathan Leffler


You can make a look-up table with sin values for some values and use linear interpolation between that values.

like image 30
Mircea Ispas Avatar answered Oct 06 '22 22:10

Mircea Ispas


A rational algebraic function approximation to sin(x), valid from zero to π/2 is:

f = (C1 * x) / (C2 * x^2 + 1.) 

with the constants:

c1 =   1.043406062 
c2 =  .2508691922 

These constants were found by least-squares curve fitting. (Using subroutine DHFTI, by Lawson & Hanson).

If the input is outside [0, 2π], you'll need to take x mod 2 π.
To handle negative numbers, you'll need to write something like:

t = MOD(t, twopi)
IF (t < 0.) t = t + twopi

Then, to extend the range to 0 to 2π, reduce the input with something like:

IF (t  < pi) THEN
  IF (t < pi/2) THEN
    x = t
  ELSE
      x = pi - t
   END IF
 ELSE 
   IF (t < 1.5 * pi) THEN
     x = t - pi
  ELSE
     x = twopi - t
   END IF
END IF

Then calculate:

f = (C1 * x) / (C2 * x*x + 1.0)
IF (t > pi) f = -f

The results should be within about 5% of the real sine.

like image 42
andy_a Avatar answered Oct 06 '22 22:10

andy_a