如何在GLSL/HLSL中实现SLERP

11

我正在尝试从GLSL进行SLERP(如果我针对Unity3D,则HLSL也可以)。

我找到了这个页面:http://www.geeks3d.com/20140205/glsl-simple-morph-target-animation-opengl-glslhacker-demo

它包含以下代码:

#version 150
in vec4 gxl3d_Position;
in vec4 gxl3d_Attrib0;
in vec4 gxl3d_Attrib1;
out vec4 Vertex_Color;
uniform mat4 gxl3d_ModelViewProjectionMatrix;
uniform float time;

vec4 Slerp(vec4 p0, vec4 p1, float t)
{
  float dotp = dot(normalize(p0), normalize(p1));
  if ((dotp > 0.9999) || (dotp<-0.9999))
  {
    if (t<=0.5)
      return p0;
    return p1;
  }
  float theta = acos(dotp * 3.14159/180.0);
  vec4 P = ((p0*sin((1-t)*theta) + p1*sin(t*theta)) / sin(theta));
  P.w = 1;
  return P;
}

void main()
{
  vec4 P = Slerp(gxl3d_Position, gxl3d_Attrib1, time);
  gl_Position = gxl3d_ModelViewProjectionMatrix * P;
  Vertex_Color = gxl3d_Attrib0;
}

数学内容可以在SLERP的维基百科页面上找到:http://en.wikipedia.org/wiki/Slerp

但我对其中这行内容提出了疑问:

  float theta = acos(dotp * 3.14159/180.0);

那个数字是2π/360,即DEG2RAD。而dotp,又称cos(theta),不是一个角度,即DEG2RAD它没有意义。括号不是错了吗?
float DEG2RAD = 3.14159/180.0;
float theta_rad = acos(dotp) * DEG2RAD;

即使这样,我怀疑acos()函数返回的是角度制而非弧度制。

有人能提供GLSL中正确实现SLERP的代码吗?


好问题,可惜没有答案。我同意,你发布的实现看起来有问题。acos肯定返回弧度。 - user3703887
你找到了这个的正确实现吗? - M Zeinstra
1
https://www.shadertoy.com/view/4sV3zt有一个vec2的实现,应该很容易推广到vec3/vec4。而且,acos接受弧度值,并返回区间[0, pi]中的值-例如,请参见https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/acos.xhtml - skalarproduktraum
不必使用'if ((dotp > 0.9999) || (dotp<-0.9999))'语句,您可以在以下行中使用clamp函数来代替:'float theta = acos(clamp(dotp,-1,1));' - Thomas
1个回答

1

所有的代码看起来都没问题。只需删去 "* 3.14159/180.0 " 就可以了,变为:

float theta = acos(dotp);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接