BRDF і сферичні координати в простеженні променів


9

Я розробив промінь для проміння, який використовує стандартну модель освітлення fong / blinn. Тепер я модифікую його для підтримки фізично заснованої візуалізації, тому я реалізую різні моделі BRDF. На даний момент я зосереджений на моделі Орен-Наяр та Торранс-Воробей. Кожна з них базується на сферичних координатах, які використовуються для вираження падаючого та вихідного напрямку світла.

Моє запитання: який спосіб правильно перетворити wi і wo з декартової координати в сферичну координату?

Я застосовуючи стандартну формулу повідомили тут https://en.wikipedia.org/wiki/Spherical_coordinate_system#Coordinate_system_conversions , але я не впевнений , що я роблю правильно, тому що мій вектор ні з хвостом в походженні декартової системи координат, але зосереджені на точці перетину променя з об’єктом.

Тут ви можете знайти мою поточну реалізацію:

Чи може хто-небудь допомогти мені дати пояснення правильного способу перетворення вектора wi і wo з декартової в сферичну координату?

ОНОВЛЕННЯ

Я копіюю тут відповідну частину коду:

обчислення сферичних координат

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 sigma = Utils::degreeToRadian(degree);
    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));

    return torranceSparrow;
}

ОНОВЛЕННЯ 2

Після деякого пошуку я знайшов цю реалізацію Oren-Nayar BRDF .

У реалізації вище тети для wi і wo отримують просто виконання дуг (wo.dotProduct (нормальний)) і arccos (wi.dotProduct (звичайний)). Мені це здається розумним, оскільки ми можемо використовувати норму точки перетину як напрямок зеніту для нашої сферичної системи координат і робити обчислення. Обчислення гамма = cos (phi_wi - phi_wo) роблять якусь проекцію wi і wo на те, що воно називає "дотичний простір". Якщо припустити, що в цій реалізації все правильно, чи можу я просто використовувати формули | Перегляд - Звичайний х (View.dotProduct (Нормальний)) | і | Світло - Нормальний х (Light.dotProduct (Нормальний)) | отримати координату фі (замість того, щоб використовувати арктан ("щось"))?


Хтось міг мені допомогти?
Фабріціо Дуроні

Чи можете ви показати точний фрагмент коду, а не всю репо?
concept3d

Схоже, це одне з найзагадковіших запитань про відстеження променів у всі часи: D
Фабріціо Дуроні

Я закликаю вас запитати тут computergraphics.stackexchange.com
concept3d

Готово @ concept3d. Ви можете знайти його тут computergraphics.stackexchange.com/questions/1799/…
Фабріціо Дуроні

Відповіді:


2

Насправді краще не використовувати сферичні координати (або будь-які кути з цього приводу) для реалізації BRDF, а скоріше працювати прямо в декартовій системі координат і використовувати косинус кута між векторами, який є звичайним крапковим виробом між одиничними векторами. Це і надійніше, і ефективніше.

Для Орен-Наяр ви можете подумати, що вам доведеться використовувати кути (через хв / макс кутів), але ви можете просто реалізувати BRDF прямо в декартовому просторі: https://fgiesen.wordpress.com/2010/10/21 / закінчити-свої-виводи - будь ласка

Для мікрофайлів BRDF Torrance-Sparrow або Cook-Torrance вам також не потрібно використовувати сферичні координати. У цих BRDF кут передається тригонометричній (зазвичай косинусовій) функції в термінах D / F / G та знаменнику BRDF, тому ви можете використовувати прямі або тригонометричні тотожності добутку без проходження сферичних координат.


1

Можна вказати систему координат, задану нормальним N та іншим вектором. Виберемо wi. Отже, будь-який вектор, який має той самий напрямок, що і wi, коли проектується на дотичну площину, матиме азимут 0

По-перше, ми проектуємо wi на площину дотичної: (при умові, що wi вже нормалізовано)

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

Тепер ми можемо зробити те ж саме і з wo:

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

Тепер дотепність і wot лежать як на площині, ортогональній N, так і дотичній до точки перетину.

Зараз ми можемо обчислити кут між двома:

azimuth = arcos ( dot(wit, wot) )

Який насправді азимут Wot щодо дотепності при проектуванні на дотичну площину.


0

Якщо ви знаєте точку перетину і точку походження, чи не буде це просто питання віднімання одного від іншого, щоб ви отримали результат так, ніби він був від початку?

Якщо ви не вірите в результат і хочете пройти туди довгим шляхом, ви також можете отримати перетворення обертання, щоб перейти з однієї точки в іншу за допомогою матриці LookAt, а потім розкласти її, щоб отримати обертальну складову. Ви також можете отримати кватерніон від нього, якщо хочете.

Результати рівні. Доказ трохи довгий, але не складний, і залишається за читачем.


Привіт @ Піжама Пінда дякую за вашу відповідь, але я не можу зрозуміти вашу відповідь. Я намагаюся уточнити: Якщо б у мене була точка перетину та точки зору, я можу розрахувати wi і wo. Тоді я можу використовувати нормальний як мій зенітний напрямок для обчислення, але я не в змозі знайти іншу вісь, необхідну для пошуку кута азимута на площині, ортогональній до зеніту. У наведеному вище фрагменті я просто застосував формули перетворення для сферичної координати на wi і wo, подані у світовій системі координат, але я не думаю, що це правильний спосіб обчислити тету та фі.
Фабріціо Дуроні
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.