(引擎篇)【第五节:Ray Marching&SDF简单运用】

1

主题

5

帖子

7

积分

新手上路

Rank: 1

积分
7
发表于 2022-12-10 07:24:00 | 显示全部楼层
一,What is Ray Marching

光线从起点出发,一步步前进,每到达一步,光线就停下来做一次计算,然后继续前进,直到逼近重点.
注意:不同场景,光线步进指代的内容不同,从摄像机向屏幕上的每一个像素发射一条光线,光线按照一定步长前进,检测当前光线距离物体表面的距离,并且根据这个距离调整光线的步长,直到抵达物体表面




二,How to do Ray marching





首先我们看到这张图,我们可以发现,构建RM需要大致四步
1.定义摄像机的位置,光线的方向;
2.定义场景:场景包含一个球体和平面;
3.定义灯光的方向;
4.计算法线的方向;
可以简单理解为:定位摄像机,由摄像机发出射线,根据一定的频率(步长)检测射线周围有无物体(这一部分叫射线检测,检测的是方向和深度,方向是由像素点决定的)。然后这里这个球,叫做球形检测,球形检测会基于当前的像素点作为圆心,进行画圆,这里就引入了RM的核心公式
float RayMarching(vec3 ro vec3 rd)//ro=cameraposition rd = cameravector
{
  float do = 0;//射线长度
  for(int i = 0;i <MAX_STEPS;i++)
  {
    vec3 p = ro +do * rd;
    float  ds = GetDist(p);//自定义一个用来获取当前监测点到物体距离深度的函数
    do += ds;
    if(ds <SUPFACE_DIST||do>MAX_DIST)
      break;
  }
  return do;
}



然后我们说一下这里自定义的GetDist函数,就是这张图片的这两个公式,求一个plane以及Sphere,主要目的就是:输入空间中某一点的坐标,返回此点与空间中最近物体的距离
float GetDist(vec3 p)//先定义一个p值
{
  vec4 sphere = vec4(0,1,6,1);//再定义一个圆心坐标
  float ds = length(p-sphere.xyz)-sphere.w;//w作为缩放值
  float dp = p.y;
  float d = min(ds,dp);//利用plane和sphere的深度,取一个离摄像机最近的距离
  return d;
}三,SDF

SDF Signed Distance Field, 在RayMarching中,我们使用的GetDist实际上就是一个有向距离场,它描述空间中的任一点到达最近的物体的距离



可以简单粗暴的理解为,我们需要给这个rm限制一个距离场,这里可以用于指定其形状,常用物体的SDF方程,大家都可以在网络上搜得到
四,案例:基于Ray marching的史莱姆

这里直接拿之前做的独立游戏比赛的案例在讲解
https://zhuanlan.zhihu.com/p/587209449



我们根据之前的理论知识点,确定这个自定义节点需要输入哪些东西,再通过代码进行一个编写,代码主要分为几个部分

  • 确定好物体的形状





  • 确定法线





  • 定义输入量





  • 开始RM





  • 注意,这里需要一个额外的算法,这个算法可以自己去尝试一下,为什么这里能做到平滑



最后就能得到这样的效果


https://www.zhihu.com/video/1583072795034107904
回复

举报 使用道具

您需要登录后才可以回帖 登录 | 立即注册
快速回复 返回顶部 返回列表