路径追踪:如何确保新的方向向量是相对于 BSDF 的有效方向向量?

Path tracing: how to ensure the new direction vector is a valid direction vector with respect to a BSDF?

给定世界space中交点的BSDF函数和Normal向量,如何生成新的方向向量wi 有效吗?生成有效 wis 的方法是否根据 BSDF 发生变化?

这是我想为理想漫反射 material BSDF 做的事情的示例:我生成一个新的方向向量 wi 作为单位半球上的点,如下所示,然后计算dot 生成的向量与 Normal 向量的乘积。如果 dot 乘积结果为正,则方向向量 wi 有效。否则我会按照建议 here.

否定 wi

以下是我如何获得随机 wi:

float theta = 2 * M_PI * uniform01(generator);
float phi = acos(uniform01(generator));
float x = sin(phi) * cos(theta);
float y = sin(phi) * sin(theta);
float z = cos(phi);
Vector3f wi(x, y, z);

if (dot(wi, Normal) > 0){
    return wi;
}
else{
    return -wi;
}

但是,根据我最近与某人的谈话,这似乎不是正确的方法。显然,以这种方式产生的新方向向量在某种程度上不正确 space(不确定它是世界还是物体 space)并且只有在我的 material 是理想的漫反射时才能工作。所以我将不得不应用一些转换才能获得正确的 wi。这个对吗?如果是这样,有人可以提供包括进行此类转换的解决方案吗?此外,是否有一种通用方法可以确保我生成的所有 wi 都对 BSDF(不仅仅是理想的漫反射)有效?

您正在生成 wi 切线 space,z 指向法线。它既不是世界也不是对象 space,你将不得不转换成世界 space 或在切线 space(或阴影 space 中进行所有计算,它们都是一样)。

您应该做的是将您的 wo 转换为切线 space,并在其中进行所有计算,因为这会让您在进行其他计算时更加轻松。在这里,您可以选择 z 作为法线,并生成与其正交的 xy 向量。

像这样生成坐标系的函数是:

void GenerateCoordinateSystem(const Vector& normalized, Vector& outFirst, Vector& outSecond)
{
    if (std::abs(normalized.x) > std::abs(normalized.y))
    {
        outFirst = Vector(-normalized.z, 0, normalized.x) /
            std::sqrt(normalized.x * normalized.x + normalized.z * normalized.z);
    }
    else
    {
        outFirst = Vector(0, normalized.z, -normalized.y) /
            std::sqrt(normalized.z * normalized.z + normalized.y * normalized.y);
    }
    outSecond = Cross(normalized, outFirst);
}

其中 normalized 是该点的法线(z 向量),outFirstoutSecond 是您的 xy 向量。

现在您有了切线 space 向量,您可以通过(wo 在对象 space 中):

Vector x, y;
GenerateCoordinateSystem(normal, x, y);
Vector tangentWo = Vector(Dot(wo, x), Dot(wo, y), Dot(wo, normal));

然后您将像上面那样生成 wi。 然后,要在对象 space 中获取 wi,您将:

Vector objWi = wi.X * x + wi.Y * y + wi.Z * normal;

如果你想在世界 space 中使用它们,你显然必须将它们乘以对象的变换矩阵。

均匀半球采样确实确保您的 wi 对任何 BSDF 都有效,但是,您必须确保 BSDF 的 pdf 考虑了分布。