# レイトレーシングにおけるBRDFおよび球座標

9

ここに私の現在の実装を見つけることができます：

ここにコードの関連部分をコピーします。

``````float Vector3D::sphericalTheta() const {

float sphericalTheta = acosf(Utils::clamp(y, -1.f, 1.f));

return sphericalTheta;
}

float Vector3D::sphericalPhi() const {

float phi = atan2f(z, x);

return (phi < 0.f) ? phi + 2.f * M_PI : phi;
}``````

オーレンナヤル

``````OrenNayar::OrenNayar(Spectrum<constant::spectrumSamples> reflectanceSpectrum, float degree) : reflectanceSpectrum{reflectanceSpectrum} {

float sigmaPowerTwo = sigma * sigma;

A = 1.0f - (sigmaPowerTwo / 2.0f * (sigmaPowerTwo + 0.33f));
B = 0.45f * sigmaPowerTwo / (sigmaPowerTwo + 0.09f);
};

Spectrum<constant::spectrumSamples> OrenNayar::f(const Vector3D& wi, const Vector3D& wo, const Intersection* intersection) const {

float thetaI = wi.sphericalTheta();
float phiI = wi.sphericalPhi();

float thetaO = wo.sphericalTheta();
float phiO = wo.sphericalPhi();

float alpha = std::fmaxf(thetaI, thetaO);
float beta = std::fminf(thetaI, thetaO);

Spectrum<constant::spectrumSamples> orenNayar = reflectanceSpectrum * constant::inversePi * (A + B * std::fmaxf(0, cosf(phiI - phiO) * sinf(alpha) * tanf(beta)));

return orenNayar;
}``````

トーランス-スズメ

``````float TorranceSparrow::G(const Vector3D& wi, const Vector3D& wo, const Vector3D& wh, const Intersection* intersection) const {

Vector3D normal = intersection->normal;
normal.normalize();

float normalDotWh = fabsf(normal.dot(wh));
float normalDotWo = fabsf(normal.dot(wo));
float normalDotWi = fabsf(normal.dot(wi));
float woDotWh = fabsf(wo.dot(wh));

float G = fminf(1.0f, std::fminf((2.0f * normalDotWh * normalDotWo)/woDotWh, (2.0f * normalDotWh * normalDotWi)/woDotWh));

return G;
}

float TorranceSparrow::D(const Vector3D& wh, const Intersection* intersection) const {

Vector3D normal = intersection->normal;
normal.normalize();

float cosThetaH = fabsf(wh.dot(normal));

float Dd = (exponent + 2) * constant::inverseTwoPi * powf(cosThetaH, exponent);

return Dd;
}

Spectrum<constant::spectrumSamples> TorranceSparrow::f(const Vector3D& wi, const Vector3D& wo, const Intersection* intersection) const {

Vector3D normal = intersection->normal;
normal.normalize();

float thetaI = wi.sphericalTheta();
float thetaO = wo.sphericalTheta();

float cosThetaO = fabsf(cosf(thetaO));
float cosThetaI = fabsf(cosf(thetaI));

if(cosThetaI == 0 || cosThetaO == 0) {

return reflectanceSpectrum * 0.0f;
}

Vector3D wh = (wi + wo);
wh.normalize();

float cosThetaH = wi.dot(wh);

float F = Fresnel::dieletricFresnel(cosThetaH, refractiveIndex);
float g = G(wi, wo, wh, intersection);
float d = D(wh, intersection);

printf("f %f g %f d %f \n", F, g, d);
printf("result %f \n", ((d * g * F) / (4.0f * cosThetaI * cosThetaO)));

Spectrum<constant::spectrumSamples> torranceSparrow = reflectanceSpectrum * ((d * g * F) / (4.0f * cosThetaI * cosThetaO));

}``````

アップデート2

Fabrizio Duroni 2015年

リポジトリ全体ではなく、正確なコードスニペットを表示できますか？
concept3d

これは、常にレイトレーシングに関する最も神秘的な質問の1つであるようです：D
Fabrizio Duroni

@ concept3dを完了しました。あなたはここでそれを見つけることができますcomputergraphics.stackexchange.com/questions/1799/...
ファブリツィオDuroni

2

それは実際に良いです 、BRDFを実装するために球座標（またはその点では任意の角度）を使用するのではなく、デカルト座標系でまっすぐに機能し、ベクトル間の角度の余弦を使用する方が良いです。これは、より堅牢で効率的です。

Torrance-SparrowまたはCook-TorranceのマイクロファセットBRDFの場合、球面座標を使用する必要もありません。これらのBRDFでは、角度はD / F / G項およびBRDF分母で三角関数（通常はコサイン）関数に渡されるため、球座標を介さずに内積直線または三角関数のアイデンティティを使用できます。

1

まず、接平面にwiを投影します（wiは既に正規化されていると仮定）。

``wit = normalize(wi - N * dot(wi, N))``

``wot = normalize(wo - N * dot(wo, N))``

ここで、ウィットとウォットは、Nに直交する平面上にあり、交点に接しています。

ここで、2つの間の角度を計算できます。

``azimuth = arcos ( dot(wit, wot) )``

これは、接平面に投影したときの、ウィットに対するウォットの方位角です。

0

こんにちは@Panda Pajama回答ありがとうございます。回答を理解できません。明確にしようとします。交差点と視点があれば、wiとwoを計算できます。次に、法線を天頂方向として使用して計算できますが、天頂に直交する平面上の方位角を見つけるために必要な他の軸を見つけることができません。上記の抜粋では、世界座標系で与えられたwiとwoの球面座標の変換式を単に適用しましたが、これがシータとファイを計算する正しい方法ではないと思います。
Fabrizio Duroni