浅做一个MetaBall

 

Raymaching其实就是实时场景的一种渲染方法。主要原理网上有很多详细介绍。简单来说就是,以摄像机为原点,发射很多条射线,而每一条射线以步长为单位向前采样,同时以采样点和最近的物体像素的距离为半径进行一个球形检测。检测到摄像机和场景像素在当前射线方向的距离差小于某个值,就表示射线到达物体表面,然后画这个像素。

 

 

图片来源于以上链接视频

 

 

开始在unreal里面进行简单的实现

 

 

首先上才艺

 

 

 

图片仅供参考,具体以实物为准

1. custom节点算出球体

 

 

先上代码

 

 

float distance = length(pos-ObjectPosition)-50;

 

 

减去50表示小球的半径

 

 

 

 

 

 

 

 

 

 

2. 去掉被遮挡的部分

 

 

为了对算法进行优化,我们可以去掉球体被遮挡的部分,比如说地面以下的部分。

 

 

判断场景深度是否小于摄像机到物体像素的距离,小球处于地面以下后,深度值就会取平面的深度值,所以如果深度值小于摄像机到像素距离的话,不进行检测。

 

 

 

 

3. 添加法线

 

 

求法线就简单粗暴的对检测结果求一个梯度变化,设定一个值,求在这个值前后的检测结果的插值。最后把normal的信息也输出出来。具体结果如下

 

 

 

 

 

 

 

 

注意材质球的normal要取消勾选targent space normal,因为算出来的是一个世界法线

 

 

 

 

 

 

 

 

 

 

4. 跟地面的融合效果

 

主要就是一个分段函数,d1是检测出来的小球,d2是与其相交的一个物体的距离场,k表示两个相交的物体在相交那部分的一个过渡值,即达到这个值开始相交。

 

 

所以d1 = RM.RMSphere(pos-ObjectPosition);

 

 

而d2,这里用深度代替距离场,就等于射线方向上那个物体对应的场景深度减去摄像机到小球像素的距离

 

 

float d2 = SceneDepth - length(pos - CameraPosition);

 

 

这里混合d1和d2用lerp。

 

 

 

 

 

 

 

 

最终效果

 

 

 

 

 

 

调整采样步数等可以解决边缘锯齿,但是性能计算会更大,目前还没有找到一个更好的解决办法。

以上就是影晨文化对浅做一个MetaBall的简单介绍,记得持续关注我们哦,如有不足之处,希望大家可以一起交流学习,一起变得更强!如果有广州三维动画制作的需求,可以随时找到影晨文化哦!


标签为: