मैंने एक किरण अनुरेखक विकसित किया जो मानक फोंग / ब्लिन फोंग प्रकाश मॉडल का उपयोग करता है। अब मैं इसे शारीरिक रूप से आधारित प्रतिपादन का समर्थन करने के लिए संशोधित कर रहा हूं, इसलिए मैं विभिन्न बीआरडीएफ मॉडल लागू कर रहा हूं। फिलहाल मैं ऑरेन-नायर और टोरेंस-स्पैरो मॉडल पर ध्यान केंद्रित कर रहा हूं। इनमें से हर एक घटना निर्देशांक पर आधारित है, जिसका उपयोग घटना wi और आउटगोइंग wo प्रकाश दिशा को व्यक्त करने के लिए किया जाता है।
मेरा सवाल यह है कि कौन सा तरीका सही है जो वाई और वू को कार्टेशियन समन्वय से गोलाकार समन्वय में परिवर्तित करता है?
मैं मानक सूत्र यहाँ रिपोर्ट को लागू करने कर रहा हूँ https://en.wikipedia.org/wiki/Spherical_coordinate_system#Coordinate_system_conversions लेकिन मुझे नहीं यकीन है कि मैं सही काम कर रहा हूँ कर रहा हूँ, क्योंकि मेरे वेक्टर पूंछ के साथ की उत्पत्ति पर नहीं हैं कार्टेशियन समन्वय प्रणाली, लेकिन ऑब्जेक्ट के साथ किरण के प्रतिच्छेदन बिंदु पर केंद्रित है।
यहाँ आप मेरे वर्तमान कार्यान्वयन पा सकते हैं:
https://github.com/chicio/Multispectral-Ray-tracing/tree/brdf/RayTracing/RayTracer/Objects/BRDF
https://github.com/chicio/Multispectral-Ray-tracing/blob/brdf/RayTracing/RayTracer/Math/Vector3D.cpp
क्या कोई मुझे कार्टियर से गोलाकार समन्वय के लिए वाई और वू वेक्टर को बदलने के सही तरीके की व्याख्या देने में मदद कर सकता है?
अपडेट करें
मैं यहां कोड के प्रासंगिक भाग की प्रतिलिपि बनाता हूं:
गोलाकार समन्वय गणना
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;
}
Torrance-गौरैया
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;
}
अद्यतन २
कुछ खोज के बाद मुझे ओरेन-नायर बीआरडीएफ का यह कार्यान्वयन मिला ।
Wi और wo के लिए थीटा के ऊपर कार्यान्वयन में केवल arccos (wo.dotProduct (सामान्य)) और arccos (wi.dotProduct (सामान्य)) कर रहे हैं। यह मेरे लिए उचित लगता है, क्योंकि हम अपने गोलाकार समन्वय प्रणाली के लिए चौराहे के बिंदु को सामान्य दिशा के रूप में उपयोग कर सकते हैं और गणना कर सकते हैं। गामा = cos (phi_wi - phi_wo) की गणना कुछ प्रकार के वाई और वू के प्रक्षेपण को करती है जिसे "स्पर्शरेखा स्थान" कहते हैं। इस कार्यान्वयन में सबकुछ सही होने पर, क्या मैं केवल सूत्रों का उपयोग कर सकता हूं? देखें - सामान्य x (View.dotProduct (सामान्य))) और | प्रकाश - सामान्य x (Light.dotProduct (सामान्य)) | phi निर्देशांक प्राप्त करने के लिए (arctan ("कुछ" का उपयोग करने के बजाय))?