光线追踪中软阴影采样错误的问题

4
你好,我正在学习光线追踪算法,但是在蒙特卡罗算法方面遇到了困难。在没有区域光的情况下渲染输出是正确的,但是当我添加区域光实现生成软阴影的源代码时,遇到了问题。
以下是变化前后的输出图像。

enter image description here

当我将蓝色球向下移动时,问题仍然存在(请注意,当球沿着白色虚线移动时,伪影仍然存在)。 请注意,该球体和区域光具有相同的z偏移量。当我将蓝色球移到屏幕前面时,伪影消失了。我认为问题是由于均匀采样锥或采样球函数引起的,但不确定。
以下是函数:
template <typename T>
CVector3<T> UConeSample(T u1, T u2, T costhetamax,
const CVector3<T>& x, const CVector3<T>& y, const CVector3<T>& z) {
   T costheta = Math::Lerp(u1, costhetamax, T(1));
   T sintheta = sqrtf(T(1) - costheta*costheta);
   T phi = u2 * T(2) * T(M_PI);

   return cosf(phi) * sintheta * x +
          sinf(phi) * sintheta * y +
          costheta * z;
}

我正在从van Der Corput序列中生成随机浮点数u1、u2值。这是球体采样方法。

CPoint3<float> CSphere::Sample(const CLightSample& ls, const CPoint3<float>& p, CVector3<float> *n) const {
   // translate object to world space
   CPoint3<float> pCentre = o2w(CPoint3<float>(0.0f));
   CVector3<float> wc = Vector::Normalize(pCentre - p);
   CVector3<float> wcx, wcy;
   //create local coordinate system from wc for uniform sample cone
   Vector::CoordinateSystem(wc, &wcx, &wcy);

   //check if inside, epsilon val. this is true?
   if (Point::DistSquare(p, pCentre) - radius*radius < 1e-4f)
      return Sample(ls, n);

   // Else outside evaluate cosinus theta value
   float sinthetamax2 = radius * radius / Point::DistSquare(p, pCentre);
   float costhetamax = sqrtf(Math::Max(0.0f, 1.0f - sinthetamax2));

   // Surface properties
   CSurfaceProps dg_sphere;
   float thit, ray_epsilon;
   CPoint3<float> ps;

   //create ray direction from sampled point then send ray to sphere
   CRay ray(p, Vector::UConeSample(ls.u1, ls.u2, costhetamax, wcx, wcy, wc), 1e-3f);
   // Check intersection against sphere, fill surface properties and calculate hit point
   if (!Intersect(ray, &thit, &ray_epsilon, &dg_sphere))
      thit = Vector::Dot(pCentre - p, Vector::Normalize(ray.d));

   // Evaluate surface normal
   ps = ray(thit);
   *n = CVector3<float>(Vector::Normalize(ps - pCentre));

   //return sample point
   return ps;
}

有人有什么建议吗?谢谢。


Math::Lerp的定义是什么?我期望它可以计算出类似于:u1 + 1*(costhetamax-u1)这样的东西,它总是会返回costhetamax(根据浮点运算)。这符合你的要求吗? - Ari Hietanen
模板<typename T> T Lerp(T t, T v1, T v2) { return (T(1) - t) * v1 + t * v2; } - user5044221
请注意,下方的图像天花板和侧墙顶部更亮,这表明问题可能出在其他地方 - 您是否多次计算了一些光线? - Miloslaw Smyk
@MiloslawSmyk:感谢您的回复。亮度过高的原因可能是由于光乘数器和/或采样点处的光密度(pdf)相关,或者是区域光形状大小增加时引起的。我认为伪影是由光采样引起的,但问题在哪里呢?在我看来,问题特别是锥形采样算法引起的。因为伪影沿着白线(或沿着一个不可见的锥体)走。 - user5044221
1个回答

1

我解决了这个问题。

光线追踪需要更复杂的RNG(其中之一为"Mersenne Twister"伪随机数生成器)和良好的洗牌算法。

enter image description here

我希望它能有所帮助。感谢所有发表评论的人。


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