BRDF dan Spherical mengkoordinasikan ray tracing

9

Saya mengembangkan pelacak sinar yang menggunakan model pencahayaan phong / blinn phong standar. Sekarang saya memodifikasinya untuk mendukung rendering berbasis fisik, jadi saya mengimplementasikan berbagai model BRDF. Saat ini saya sedang fokus pada model Oren-Nayar dan Torrance-Sparrow. Masing-masing didasarkan pada koordinat bola yang digunakan untuk mengekspresikan kejadian dengan arah cahaya keluar.

Pertanyaan saya adalah: jalan mana yang benar mengkonversi wi dan wo dari koordinat kartesius ke koordinat bola?

Saya menerapkan rumus standar yang dilaporkan di sini https://en.wikipedia.org/wiki/Spherical_coordinate_system#Coordinate_system_conversions tapi saya tidak yakin saya melakukan hal yang benar, karena vektor saya tidak dengan ekor pada asal-usul sistem koordinat kartesius, tetapi berpusat pada titik persimpangan sinar dengan objek.

Di sini Anda dapat menemukan implementasi saya saat ini:

Adakah yang bisa membantu saya memberikan penjelasan tentang cara yang benar untuk mengkonversi vektor wi dan wo dari cartesian ke koordinat bola?

MEMPERBARUI

Saya salin di sini bagian kode yang relevan:

perhitungan koordinat bola

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;
}

Oren Nayar

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;
}

Torrance-Sparrow

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;
}

PEMBARUAN 2

Setelah beberapa pencarian saya menemukan implementasi BRDF Oren-Nayar ini .

Dalam implementasi di atas theta untuk wi dan wo diperoleh cukup melakukan arccos (wo.dotProduct (Normal)) dan arccos (wi.dotProduct (Normal)). Ini masuk akal bagi saya, karena kita dapat menggunakan titik persimpangan normal sebagai arah puncak untuk sistem koordinat bola kita dan melakukan perhitungan. Perhitungan gamma = cos (phi_wi - phi_wo) melakukan semacam proyeksi wi dan wo pada apa yang disebutnya "ruang singgung". Dengan asumsi semuanya sudah benar dalam implementasi ini, dapatkah saya menggunakan rumus | View - Normal x (View.dotProduct (Normal)) | dan | Cahaya - Normal x (Light.dotProduct (Normal)) | untuk mendapatkan koordinat phi (alih-alih menggunakan arctan ("sesuatu"))?

Fabrizio Duroni
sumber
Adakah yang bisa membantu saya?
Fabrizio Duroni
Bisakah Anda menunjukkan potongan kode yang tepat, bukan seluruh repo?
concept3d
Sepertinya ini adalah salah satu pertanyaan paling misterius tentang penelusuran sinar kali: D
Fabrizio Duroni
Saya mendorong Anda untuk bertanya di sini computergraphics.stackexchange.com
concept3d
Selesai @ concept3d. Anda dapat menemukannya di sini computergraphics.stackexchange.com/questions/1799/…
Fabrizio Duroni

Jawaban:

2

Sebenarnya lebih baik tidak menggunakan koordinat bola (atau sudut apa pun dalam hal ini) untuk mengimplementasikan BRDF, tetapi bekerja langsung dalam sistem koordinat Cartesian dan menggunakan cosinus sudut antara vektor, yang merupakan produk titik polos antara vektor satuan seperti yang Anda ketahui. Ini lebih kuat dan efisien.

Untuk Oren-Nayar Anda mungkin berpikir Anda harus menggunakan sudut (karena min / maks dari sudut), tetapi Anda dapat menerapkan BRDF langsung di ruang Cartesian: https://fgiesen.wordpress.com/2010/10/21 / selesaikan-derivasi Anda-tolong

Untuk microfacet Torrance-Sparrow atau Cook-Torrance, Anda tidak perlu menggunakan koordinat bola juga. Dalam BRDF ini, sudut diteruskan ke fungsi trigonometrik (biasanya kosinus) dalam istilah D / F / G & penyebut BRDF, sehingga Anda dapat menggunakan identitas titik produk lurus atau trigonometrik tanpa melalui koordinat bola.

JarkkoL
sumber
1

Anda dapat menentukan sistem koordinat yang diberikan N normal dan vektor lainnya. Kami akan memilih wi. Jadi setiap vektor yang memiliki arah yang sama dengan wi ketika diproyeksikan ke bidang garis singgung akan memiliki azimuth 0

Pertama, kami memproyeksikan wi pada bidang tangen: (dengan asumsi wi sudah dinormalisasi)

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

sekarang, kita bisa melakukan hal yang sama dengan wo:

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

Sekarang, kecerdasan dan kebohongan terletak pada bidang yang ortogonal ke N, dan bersinggungan dengan titik persimpangan.

Kita dapat menghitung sudut antara keduanya sekarang:

azimuth = arcos ( dot(wit, wot) )

Yang benar-benar azimuth wot sehubungan dengan kecerdasan ketika diproyeksikan pada bidang singgung.

Gato
sumber
0

Jika Anda tahu titik persimpangan, dan titik asal, bukankah itu hanya soal mengurangi satu dari yang lain sehingga Anda mendapatkan hasilnya seolah-olah itu dari titik asal?

Jika Anda tidak percaya hasilnya, dan ingin sampai di sana melalui jalan panjang, Anda juga bisa mendapatkan transformasi rotasi untuk berpindah dari satu titik ke titik lain melalui matriks LookAt, dan kemudian menguraikannya untuk mendapatkan komponen rotasi. Anda juga bisa mendapatkan angka empat dari itu jika Anda mau.

Hasilnya sama. Buktinya agak panjang, tapi tidak rumit, dan diserahkan kepada pembaca.

Piyama Panda
sumber
Hai @Panda Pajama terima kasih atas jawaban Anda, tetapi saya tidak dapat memahami jawaban Anda. Saya mencoba mengklarifikasi: Jika saya memiliki titik persimpangan dan sudut pandang saya dapat menghitung wi dan wo. Maka saya dapat menggunakan normal sebagai arah zenith saya untuk menghitung, tetapi saya tidak dapat menemukan sumbu lain yang diperlukan untuk menemukan sudut azimuth pada bidang ortogonal ke zenith. Dalam potongan di atas saya hanya menerapkan rumus konversi untuk koordinat bola pada wi dan wo yang diberikan dalam sistem koordinat dunia, tetapi saya tidak berpikir ini adalah cara yang tepat untuk menghitung theta dan phi.
Fabrizio Duroni