发现一篇好博客http://jamie-wong.com/2016/07/15/ray-marching-signed-distance-functions/
signed distance function
首先,假设我们要生成一个三维球体,那么三维空间里的哪些点在这个球体内部呢?
比如这个球的中心点坐标是(0,0,0),半径是1,那么对于任意一点x,y,z可以用以下公式判断
如果结果小于0说明在内部,大于0说明在球体外边,这就是符号(signed)的含义。写成程序就是这样
float sphereSDF(vec3 p) {
return length(p) - 1.0;
}
法向量
简便起见,先说二维的。比如一条紫色曲线的A点(x0 = 10,y0 = 10),怎么知道那点的法向量?
答案是选择一个很小的量。简单起见,这里选一个比较大的量s = 1,计算f(B)= f(x1 = x0 + s = 11,y1 = y0 = 10),C在另一方向上类似。
三维方向上则是
写成代码
vec3 estimateNormal(vec3 p) {
return normalize(vec3(
sceneSDF(vec3(p.x + EPSILON, p.y, p.z)) - sceneSDF(vec3(p.x - EPSILON, p.y, p.z)),
sceneSDF(vec3(p.x, p.y + EPSILON, p.z)) - sceneSDF(vec3(p.x, p.y - EPSILON, p.z)),
sceneSDF(vec3(p.x, p.y, p.z + EPSILON)) - sceneSDF(vec3(p.x, p.y, p.z - EPSILON))
));
}
RayMarching
图解如下。网上资料很多这里就不再赘述了。实际更常用的算法是RayTracing。