给定世界空间Normal中交点的BSDF函数和wi向量,如何生成有效的新的方向向量wi?基于BSDF生成有效wi更改的方法吗?
这是我想为理想的漫射材料做的一个例子,BSDF:我生成一个新的方向向量wi,作为一个单位半球上的点,如下所示,然后用Normal向量计算产生的向量的dot积。如果dot乘积结果为正,则方向向量wi是有效的。否则,我将否定wi建议的here。
下面是我如何得到一个随机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;
}然而,基于我最近与某人的谈话,这似乎并不是正确的方法。显然,这种方式产生的新的方向矢量在某种程度上不是在正确的空间(不确定它是世界空间还是物体空间),并且只有当我的材料是理想的扩散时才能工作。因此,为了能够得到正确的wi,我必须应用一些转换。这是正确的吗?如果是这样的话,有人能提供一个解决方案,包括这样的转换吗?另外,是否有一种通用的方法来确保我生产的所有wi对于BSDF (不仅仅是理想的扩散)是有效的?
发布于 2021-02-03 05:29:41
您正在切线空间中生成wi,z沿着法线指向。它既不是世界也不是物体空间,你必须转换成世界空间,或者在切线空间中做所有的计算(或者阴影空间,它们都是相同的)。
你应该做的事情,因为它将使你的生活更容易做其他计算,是转换你的wo切线空间,并做所有的计算在其中。在这里,您将选择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向量。
既然有了切线空间向量,就可以将它们转换为by (wo在对象空间中):
Vector x, y;
GenerateCoordinateSystem(normal, x, y);
Vector tangentWo = Vector(Dot(wo, x), Dot(wo, y), Dot(wo, normal));然后,您将像上面这样生成您的wi。然后,要在对象空间中获取wi,您可以:
Vector objWi = wi.X * x + wi.Y * y + wi.Z * normal;如果你想把它们放在世界空间里,你显然必须用物体的变换矩阵来乘以它们。
均匀半球抽样确实确保您的wi对任何BSDF都有效,但是您必须确保BSDF的pdf考虑到分布。
https://stackoverflow.com/questions/66021096
复制相似问题