BRDF và tọa độ hình cầu trong dò tia


9

Tôi đã phát triển một máy dò tia sử dụng mô hình chiếu sáng phong / phong chuẩn. Bây giờ tôi đang sửa đổi nó để hỗ trợ kết xuất dựa trên vật lý, vì vậy tôi đang triển khai các mô hình BRDF khác nhau. Hiện tại tôi đang tập trung vào mô hình Oren-Nayar và Torrance-Sparrow. Mỗi một trong số này được dựa trên tọa độ hình cầu được sử dụng để thể hiện sự cố wi và hướng ánh sáng đi ra.

Câu hỏi của tôi là: cách nào là đúng khi chuyển đổi wi và wo từ tọa độ cartesian sang tọa độ hình cầu?

Tôi đang áp dụng công thức tiêu chuẩn được báo cáo ở đây https://en.wikipedia.org/wiki/Spherical_coordinate_system#Coordinate_system_conversions nhưng tôi không chắc chắn mình đang làm đúng, vì vectơ của tôi không có đuôi ở gốc của hệ tọa độ cartesian, nhưng tập trung vào điểm giao nhau của tia với vật.

Ở đây bạn có thể tìm thấy triển khai hiện tại của tôi:

Ai đó có thể giúp tôi đưa ra lời giải thích về cách chính xác để chuyển đổi vectơ wi và wo từ cartesian sang tọa độ hình cầu không?

CẬP NHẬT

Tôi sao chép ở đây phần có liên quan của mã:

tính toán tọa độ hình cầu

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

Chim sẻ-chim sẻ

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

CẬP NHẬT 2

Sau một số tìm kiếm, tôi thấy triển khai này của Oren-Nayar BRDF .

Trong quá trình thực hiện ở trên, theta cho wi và wo thu được chỉ đơn giản là thực hiện arccos (wo.dot SẢNt (Bình thường)) và arccos (wi.dot SẢNt (Bình thường)). Điều này có vẻ hợp lý với tôi, vì chúng ta có thể sử dụng bình thường của điểm giao nhau làm hướng thiên đỉnh cho hệ tọa độ hình cầu của mình và thực hiện phép tính. Việc tính toán gamma = cos (phi_wi - phi_wo) thực hiện một số loại hình chiếu của wi và wo trên cái mà nó gọi là "không gian tiếp tuyến". Giả sử mọi thứ đều đúng trong triển khai này, tôi có thể chỉ sử dụng các công thức | Chế độ xem - Bình thường x (View.dotSản phẩm (Bình thường)) | và | Ánh sáng - Bình thường x (Light.dotSản phẩm (Bình thường)) | để có được tọa độ phi (thay vì sử dụng arctan ("cái gì đó"))?


Bất cứ ai có thể giúp tôi?
Fabrizio Duroni

Bạn có thể hiển thị đoạn mã chính xác, không phải toàn bộ repo không?
Concept3d

Có vẻ như đây là một trong những câu hỏi bí ẩn nhất về phương pháp dò tia của thời gian: D
Fabrizio Duroni

Tôi khuyến khích bạn hỏi ở đây computergraphics.stackexchange.com
concept3d

Xong @ concept3d. Bạn có thể tìm thấy nó ở đây computergraphics.stackexchange.com/questions/1799/
triệt

Câu trả lời:


2

Thực sự tốt hơn là không sử dụng tọa độ hình cầu (hoặc bất kỳ góc nào cho vấn đề đó) để thực hiện BRDF, mà hoạt động thẳng trong hệ tọa độ Cartesian và sử dụng cosin của góc giữa các vectơ, là sản phẩm chấm đơn giản giữa các vectơ đơn vị như bạn biết. Điều này là cả mạnh mẽ và hiệu quả hơn.

Đối với Oren-Nayar bạn có thể nghĩ rằng bạn phải sử dụng các góc (do tối thiểu / tối đa các góc), nhưng bạn chỉ cần thực hiện BRDF thẳng trong không gian Cartesian: https://fgiesen.wordpress.com/2010/10/21 / kết thúc-phái sinh của bạn-xin vui lòng

Đối với microfacet Torrance-Sparrow hoặc Cook-Torrance, bạn không cần phải sử dụng tọa độ hình cầu. Trong các BRDF này, góc được chuyển đến hàm lượng giác (thường là cosine) theo thuật ngữ D / F / G và mẫu số BRDF, do đó bạn có thể sử dụng các nhận dạng thẳng hoặc lượng giác của sản phẩm chấm mà không cần đi qua tọa độ hình cầu.


1

Bạn có thể chỉ định một hệ tọa độ cho N bình thường và một vectơ khác. Chúng tôi sẽ chọn wi. Vì vậy, bất kỳ vectơ nào có cùng hướng với wi khi chiếu lên mặt phẳng tiếp tuyến sẽ có góc phương vị bằng 0

Đầu tiên, chúng tôi chiếu wi trên mặt phẳng tiếp tuyến: (giả sử wi đã được chuẩn hóa)

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

Bây giờ, chúng ta có thể làm tương tự với wo:

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

Bây giờ, wit và wot nằm cả hai trên một mặt phẳng trực giao với N và tiếp tuyến với điểm giao nhau.

Bây giờ chúng ta có thể tính góc giữa hai:

azimuth = arcos ( dot(wit, wot) )

Đó thực sự là phương vị của wot đối với sự dí dỏm khi được chiếu trên mặt phẳng tiếp tuyến.


0

Nếu bạn biết điểm giao nhau và điểm gốc, thì đó không phải là câu hỏi trừ điểm này để bạn nhận được kết quả như thể nó là từ điểm gốc?

Nếu bạn không tin vào kết quả và muốn đạt được điều đó trong suốt chặng đường dài, bạn cũng có thể chuyển đổi xoay để đi từ điểm này sang điểm khác thông qua ma trận LookAt, sau đó phân tách nó để có được thành phần quay. Bạn cũng có thể có được một bộ tứ từ nó nếu bạn muốn.

Kết quả là như nhau. Bằng chứng là một chút dài, nhưng không phức tạp, và để lại cho người đọc.


Xin chào @Panda Pajama cảm ơn câu trả lời của bạn, nhưng tôi không thể hiểu câu trả lời của bạn. Tôi cố gắng làm rõ: Nếu tôi có điểm giao nhau và điểm nhìn tôi có thể tính wi và wo. Sau đó, tôi có thể sử dụng hướng bình thường như hướng thiên đỉnh của mình để tính toán, nhưng tôi không thể tìm thấy trục khác cần thiết để tìm góc phương vị trên mặt phẳng trực giao với thiên đỉnh. Trong đoạn trích ở trên, tôi chỉ đơn giản áp dụng các công thức chuyển đổi cho tọa độ hình cầu trên wi và wo được đưa ra trong hệ tọa độ thế giới, nhưng tôi không nghĩ rằng đây là cách đúng để tính theta và phi.
Fabrizio Duroni 7/12/2015
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.