使用波状顶点着色器计算整个球体的法线
Calculating Normals across a sphere with a wave-like vertex shader
我一直在尝试为我正在使用顶点着色器弄乱的球体获取正确的法线。该算法可以简单地归结为
vert.xyz += max(0, sin(time + 0.004*vert.x))*10*normal.xyz
这会导致波浪在球体上滚动。
为了使我的法线正确,我还需要对它们进行转换。我可以取给定 x、y、z 处的切线向量,得到垂直向量 (0, -vert.z, vert.y),然后将切线与 perp 向量相交。
虽然我在数学上遇到了一些问题,但此时它已成为个人恩怨。我已经解决了数百次导数,但我一直不正确。我怎样才能得到切线?
分解上面的行,我可以做一个数学函数
f(x,y,z) = max(0, sin(time + 0.004*x))*10*Norm(x,y,z) + (x,y,z)
其中 Norm(..) 是 Normalize((x,y,z) - CenterOfSphere)
After applying f(x,y,z), unchanged normals
正确的 f '(x,y,z) 是多少?
我已经解释了 f(...) 中的最大值引起的怪异,所以这不是问题。
编辑:我目前最成功的算法如下:
正切vector.x = 0.004*10*cos(0.004*vert.x + 时间)*norm.x + 10*sin(0.004*vert.x + 时间) + 1
正切vector.y = 10*sin(0.004*vert.x + 时间) + 1
正切vector.z = 10*sin(0.004*vert.x + 时间) + 1
2 次切线 vector.x = 0
第二切线vector.y = -norm.z
第二切线vector.z = norm.y
将两者归一化,并执行 Cross(Tangent2, Tangent1)。再次归一化,完成(应该是 Cross(Tangent1, Tangent2),但这似乎有更好的结果......更多提示我的数学问题!)。
这会产生 this
如果您的曲面点呈非线性分布和/或存在某些数学奇点,或者如果您犯了数学错误(99.99% 的情况就是这种情况),则通过函数导数获取 tangent/normal 有时会失败。不管怎样,你总是可以使用几何方法:
1.你可以通过
轻松获得切线
U(x,y,z)=f(x+d,y,z)-f(x,y,z);
V(x,y,z)=f(x,y+d,z)-f(x,y,z);
- 其中
d
是足够小的步长
- 和
f(x,y,z)
是你当前的表面点计算
- 不确定为什么要使用 3 个输入变量我只使用 2
- 但是因此如果移动点与未移动点相同
- 改用这个
=f(x,y,z+d)-f(x,y,z);
- 最后不要忘记将
U,V
大小归一化为单位向量
2。下一步
- 如果项目符号 1 导致正确的法线
- 那么你可以简单地用代数方法求解 U,V
- 所以将
U(x,y,z)=f(x+d,y,z)-f(x,y,z);
重写为完整的等式
- 将
f(x,y,z)
代入表面点方程
- 并简化
[注释]
- 有时选择得当
d
可以简化归一化以乘以常数
- 你应该像这样添加法线可视化:
- 实际查看实际情况(用于调试目的)
我一直在尝试为我正在使用顶点着色器弄乱的球体获取正确的法线。该算法可以简单地归结为
vert.xyz += max(0, sin(time + 0.004*vert.x))*10*normal.xyz
这会导致波浪在球体上滚动。 为了使我的法线正确,我还需要对它们进行转换。我可以取给定 x、y、z 处的切线向量,得到垂直向量 (0, -vert.z, vert.y),然后将切线与 perp 向量相交。
虽然我在数学上遇到了一些问题,但此时它已成为个人恩怨。我已经解决了数百次导数,但我一直不正确。我怎样才能得到切线? 分解上面的行,我可以做一个数学函数
f(x,y,z) = max(0, sin(time + 0.004*x))*10*Norm(x,y,z) + (x,y,z)
其中 Norm(..) 是 Normalize((x,y,z) - CenterOfSphere)
After applying f(x,y,z), unchanged normals
正确的 f '(x,y,z) 是多少?
我已经解释了 f(...) 中的最大值引起的怪异,所以这不是问题。
编辑:我目前最成功的算法如下:
正切vector.x = 0.004*10*cos(0.004*vert.x + 时间)*norm.x + 10*sin(0.004*vert.x + 时间) + 1
正切vector.y = 10*sin(0.004*vert.x + 时间) + 1
正切vector.z = 10*sin(0.004*vert.x + 时间) + 1
2 次切线 vector.x = 0
第二切线vector.y = -norm.z
第二切线vector.z = norm.y
将两者归一化,并执行 Cross(Tangent2, Tangent1)。再次归一化,完成(应该是 Cross(Tangent1, Tangent2),但这似乎有更好的结果......更多提示我的数学问题!)。
这会产生 this
如果您的曲面点呈非线性分布和/或存在某些数学奇点,或者如果您犯了数学错误(99.99% 的情况就是这种情况),则通过函数导数获取 tangent/normal 有时会失败。不管怎样,你总是可以使用几何方法:
1.你可以通过
轻松获得切线U(x,y,z)=f(x+d,y,z)-f(x,y,z);
V(x,y,z)=f(x,y+d,z)-f(x,y,z);
- 其中
d
是足够小的步长 - 和
f(x,y,z)
是你当前的表面点计算 - 不确定为什么要使用 3 个输入变量我只使用 2
- 但是因此如果移动点与未移动点相同
- 改用这个
=f(x,y,z+d)-f(x,y,z);
- 最后不要忘记将
U,V
大小归一化为单位向量
2。下一步
- 如果项目符号 1 导致正确的法线
- 那么你可以简单地用代数方法求解 U,V
- 所以将
U(x,y,z)=f(x+d,y,z)-f(x,y,z);
重写为完整的等式 - 将
f(x,y,z)
代入表面点方程 - 并简化
[注释]
- 有时选择得当
d
可以简化归一化以乘以常数 - 你应该像这样添加法线可视化:
- 实际查看实际情况(用于调试目的)