路径追踪:如何确保新的方向向量是相对于 BSDF 的有效方向向量?
Path tracing: how to ensure the new direction vector is a valid direction vector with respect to a BSDF?
给定世界space中交点的BSDF函数和Normal
向量,如何生成新的方向向量wi
有效吗?生成有效 wi
s 的方法是否根据 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
作为法线,并生成与其正交的 x
和 y
向量。
像这样生成坐标系的函数是:
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
向量),outFirst
和 outSecond
是您的 x
和 y
向量。
现在您有了切线 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
考虑了分布。
给定世界space中交点的BSDF函数和Normal
向量,如何生成新的方向向量wi
有效吗?生成有效 wi
s 的方法是否根据 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
作为法线,并生成与其正交的 x
和 y
向量。
像这样生成坐标系的函数是:
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
向量),outFirst
和 outSecond
是您的 x
和 y
向量。
现在您有了切线 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
考虑了分布。