Math 快速、不精确的正弦函数,无需查找

Math 快速、不精确的正弦函数,无需查找,math,trigonometry,shader,Math,Trigonometry,Shader,对于海洋着色器,我需要一个快速函数来计算非常近似的sin(x)值。唯一的要求是它是周期性的,大致类似于正弦波 sin的泰勒级数太慢了,因为我需要计算x的9次方才能得到一个完整的周期 有什么建议吗 编辑:对不起,我没有提到,我不能使用查找表,因为这是在顶点着色器上。查找表将涉及纹理示例,该示例在顶点着色器上比内置的sin函数慢。 它不一定要精确,只是要好看。使用查找表可能是控制速度和精度之间权衡的最佳方法。您可以使用某些值的sin值创建查找表,并在这些值之间使用线性插值。根据需要对尽可能多的项使用

对于海洋着色器,我需要一个快速函数来计算非常近似的sin(x)值。唯一的要求是它是周期性的,大致类似于正弦波

sin的泰勒级数太慢了,因为我需要计算x的9次方才能得到一个完整的周期

有什么建议吗

编辑:对不起,我没有提到,我不能使用查找表,因为这是在顶点着色器上。查找表将涉及纹理示例,该示例在顶点着色器上比内置的sin函数慢。
它不一定要精确,只是要好看。

使用查找表可能是控制速度和精度之间权衡的最佳方法。

您可以使用某些值的sin值创建查找表,并在这些值之间使用线性插值。

根据需要对尽可能多的项使用近似值。如果您的输入角度被约束为良好的(-π..+π或0..2π),那么这尤其容易,因此您不必首先将参数减少到合理的值。你可以用2个或3个术语代替9个。

好吧,你没有说你需要它有多准确。正弦可以近似为区间[0,pi/2]、[pi/2,3*pi/2]、[3*pi/2,2*pi]上斜率为2/pi和-2/pi的直线。在减少角度mod 2*pi后,可以对乘法和加法进行此近似。

对于sin(x),从0到π/2有效的有理代数函数近似为:

f = (C1 * x) / (C2 * x^2 + 1.) 
使用常数:

c1 =   1.043406062 
c2 =  .2508691922 
这些常数通过最小二乘曲线拟合得到。(使用子程序DHFTI,由劳森和汉森编写)

如果输入在[0,2π]之外,则需要取x mod 2π
要处理负数,您需要编写以下内容:

t = MOD(t, twopi)
IF (t < 0.) t = t + twopi
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

结果应该在实际正弦值的5%以内。

泰勒级数在0和π/2之间的x慢吗?如果它是可接受的,那么你可以使用sin的对称性来计算其他值。对于切比雪夫+1,这是最好的方法。然而,如果可能的话,距离缩小是一个巨大的优势。嗯,比这更精确:P从这个意义上说,它不需要是“精确的”,我不关心找到给定角度的近似正弦。我只是想找到一个看起来像波的平滑函数。@Hannesh:哈,好吧,至少我没有说它可以用函数f(x)=0.-1来近似,因为我想这在今天不是真的,尤其是当时钟频率在未来更高的时候future@super标题经过编辑。你读过编辑/历史吗?:)这个答案的历史呢?我编辑了我的答案以回应这些批评。为了澄清,有理函数f=(c1*x)/(c2*x^2+1)对于π/2是有效的。约化IF块将其扩展到0到2π,但必须事先这样做。你必须先取模2π。劳森和汉森编写了一个最小二乘子程序,它有助于找到常数,任何最小二乘子程序都可以达到这个目的。如果你能把13行修正码压缩成一行,给我看看。与绝对错误相反:
float sin_rational(float a){return(1.01815748f*a)/(0.23133484f*a*a+1.0f)}
Andy,我收回了我的反对票,因为我感谢你的回答。我会在有时间的时候给你回复剩下的事情。很抱歉,如果实现正确,这个函数确实可以工作,而我最初没有做到。然而,我的基准测试表明,它比在现代PC上运行的Java内置的
Math.sin()
函数要慢得多,并且我测试了它的精确度如何明显低于另一种方法(请参阅),而另一种方法恰好比Java的内置函数快得多。
f = (C1 * x) / (C2 * x*x + 1.0)
IF (t > pi) f = -f