जीजीएक्स ज्यामिति शब्द का सही रूप


9

मैं अपनी किरण में एक माइक्रोफेट बीआरडीएफ को लागू करने की कोशिश कर रहा हूं, लेकिन मैं कुछ मुद्दों में भाग रहा हूं। बहुत सारे कागजात और लेख जो मैंने पढ़े हैं, वे आंशिक ज्यामिति शब्द को देखने और आधे वैक्टर के कार्य के रूप में परिभाषित करते हैं: G1 (v, h)। हालाँकि, इसे लागू करते समय मुझे निम्नलिखित परिणाम मिले:

आधा वेक्टर का उपयोग करके GGX ज्यामिति शब्द

(नीचे पंक्ति खुरदरापन 1.0 - 0.0 के साथ ढांकता हुआ है, शीर्ष पंक्ति खुरदरापन 1.0 - 0.0 के साथ धात्विक है)

किनारों के चारों ओर एक अजीब आकर्षण है और nl == के आसपास एक कट-ऑफ है। 0. मैं वास्तव में यह पता नहीं लगा सका कि यह कहां से आता है। मैं अपने रेंडर को जांचने के लिए एक संदर्भ के रूप में यूनिटी का उपयोग कर रहा हूं, इसलिए मैंने उनके शेडर स्रोत की जांच की कि वे क्या उपयोग करते हैं और जो मैं बता सकता हूं कि उनका ज्यामिति शब्द अर्ध वेक्टर द्वारा पैराट्राइज्ड नहीं है! इसलिए मैंने एक ही कोड की कोशिश की, लेकिन आधे वेक्टर के बजाय सामान्य सतह का उपयोग किया और निम्न परिणाम प्राप्त किया:

सामान्य सतह का उपयोग करते हुए GGX ज्यामिति शब्द

मेरी अप्रशिक्षित आंख के लिए यह वांछित परिणाम के करीब लगता है। लेकिन मुझे लग रहा है कि यह सही नहीं है? मेरे द्वारा पढ़े गए अधिकांश लेखों में आधे वेक्टर का उपयोग होता है, लेकिन उन सभी का नहीं। क्या इस अंतर का कोई कारण है?

मैं अपने ज्यामिति शब्द के रूप में निम्नलिखित कोड का उपयोग करता हूं:

float RayTracer::GeometryGGX(const Vector3& v, const Vector3& l, const Vector3& n, const Vector3& h, float a)
{
    return G1GGX(v, h, a) * G1GGX(l, h, a);
}

float RayTracer::G1GGX(const Vector3& v, const Vector3& h, float a)
{
    float NoV = Util::Clamp01(cml::dot(v, h));
    float a2 = a * a;

    return (2.0f * NoV) / std::max(NoV + sqrt(a2 + (1.0f - a2) * NoV * NoV), 1e-7f);
}

और संदर्भ के लिए, यह मेरा सामान्य वितरण कार्य है:

float RayTracer::DistributionGGX(const Vector3& n, const Vector3& h, float alpha)
{
    float alpha2 = alpha * alpha;
    float NoH = Util::Clamp01(cml::dot(n, h));
    float denom = (NoH * NoH * (alpha2 - 1.0f)) + 1.0f;
    return alpha2 / std::max((float)PI * denom * denom, 1e-7f);
}

जवाबों:


5

TL; DR: आपका फॉर्मूला गलत है।G1


बस भ्रम से बचने के लिए, मैं बीआरडीएफ, आइसोटोपिक संस्करण का स्मिथ संस्करण माइक्रोफ़ैसेट मॉडल (जैसा कि वी-कैविटी मॉडल के विपरीत), और जीजीएक्स माइक्रोफैसेट वितरण मान रहा हूं।

Heitz 2014 के अनुसार , का मास्किंग / छायांकन शब्द हैG1

χ+(ωvωm)21+1+αo2tan2θv

और वाल्टर 2007 के अनुसार , सूत्र है

χ+(ωvωgωvωm)21+1+α2tan2θv

जहाँ माइक्रोफ़ेसेट सामान्य दिशा ( वेक्टर) है, मुख्य (ज्यामितीय) सामान्य दिशा (सामान्य) है, आने वाली या जाने वाली दिशा है, isotropic है खुरदरापन पैरामीटर, और सकारात्मक विशेषता फ़ंक्शन है, या हीविसाइड चरण फ़ंक्शन (एक अगर और शून्य अन्यथा) के बराबर है ।ωmωgωvαχ+(a)a>0

जैसा कि आप देख सकते हैं, आधा वेक्टर का उपयोग केवल यह सुनिश्चित करने के लिए किया जाता है कि शून्य है यदि ज्यामितीय कॉन्फ़िगरेशन निषिद्ध है। अधिक सटीक रूप से, यह सुनिश्चित करता है कि की पिछली सतह के सामने की ओर स्थित दिशा से कभी दिखाई नहीं देती है और इसके विपरीत (बाद वाला मामला तभी सार्थक होता है जब अपवर्तन भी समर्थित हो)। यदि कॉलिंग कोड इसकी गारंटी देता है, तो आप स्पष्ट रूप से इस पैरामीटर को छोड़ सकते हैं। शायद यही कारण है कि उन्होंने एकता में ऐसा किया।ωmG1ωv

आपका कार्यान्वयन, दूसरी ओर, माइक्रोफ़ैसेट के संबंध में दिशा के कोसाइन की गणना करने के लिए आधे वेक्टर का उपयोग करता है , जो प्रस्तुत किए गए सूत्रों की तुलना में कुछ और की गणना की ओर जाता है।ωv

यदि यह किसी मदद का है, तो यह मेरे कारक का कार्यान्वयन है :G1

float SmithMaskingFunctionGgx(
    const Vec3f &aDir,  // the direction to compute masking for (either incoming or outgoing)
    const Vec3f &aMicrofacetNormal,
    const float  aRoughnessAlpha)
{
    PG3_ASSERT_VEC3F_NORMALIZED(aDir);
    PG3_ASSERT_VEC3F_NORMALIZED(aMicrofacetNormal);
    PG3_ASSERT_FLOAT_NONNEGATIVE(aRoughnessAlpha);

    if (aMicrofacetNormal.z <= 0)
        return 0.0f;

    const float cosThetaVM = Dot(aDir, aMicrofacetNormal);
    if ((aDir.z * cosThetaVM) < 0.0f)
        return 0.0f; // up direction is below microfacet or vice versa

    const float roughnessAlphaSqr = aRoughnessAlpha * aRoughnessAlpha;
    const float tanThetaSqr = Geom::TanThetaSqr(aDir);
    const float root = std::sqrt(1.0f + roughnessAlphaSqr * tanThetaSqr);

    const float result = 2.0f / (1.0f + root);

    PG3_ASSERT_FLOAT_IN_RANGE(result, 0.0f, 1.0f);

    return result;
}

आपके जवाब के लिए धन्यवाद। मैंने आपके द्वारा दिए गए फॉर्मूले को लागू कर दिया है और मुझे अपने स्वयं के साथ (मैक्रोसुरफेस सामान्य का उपयोग करते समय) समान परिणाम मिला है। तो ऐसा लगता है कि यह सिर्फ एक अलग रूप है (मुझे यह मिल गया: ग्राफ़िकरेंट्स ।blogspot.nl / 2013 / 08 / specular-brdf-reference.html ) मैं आधे वेक्टर के बारे में उलझन में था क्योंकि SIGGRAPH 2015 पीबीएस गणित पाठ्यक्रम ज्यामिति को बताता है। कार्य दृश्य, प्रकाश और आधा वैक्टर पर निर्भर करता है। तो यह स्लाइड्स में एक त्रुटि है?
इरविन

@ इरविन, अब जो आपने फॉर्मूला भी प्रदान किया है, वह बहुत स्पष्ट है। अगली बार शुरुआत में ही सही, इससे मदद मिलती है। हां, दोनों संस्करण (मेरा और आपका) बराबर हैं, लेकिन उनमें से कोई भी कंप्यूटिंग साइन या स्पर्शरेखा फ़ंक्शन के लिए आधे रास्ते वेक्टर का उपयोग नहीं करता है। यह बजाय का उपयोग करता है जैसा कि आपने अपने कार्यान्वयन में किया था - जो कि गलती प्रतीत होती है। मुझे संदेह है कि आपने नए कार्यान्वयन के साथ भी यही गलती की थी। nvhv
ivokabel

मैंने अपने नए कार्यान्वयन में एन डॉट वी का उपयोग किया, जिसने मुझे पोस्ट की दूसरी छवि के समान परिणाम दिए। लेकिन मैं अभी भी स्पष्ट नहीं हूं कि पीबीएस कोर्स स्लाइड क्यों कहता है कि आधे रास्ते के वेक्टर का उपयोग किया जाना चाहिए (देखें: blog.selfshadow.com/publications/s2015-shading-course/hoffman/… , स्लाइड 88)।
इरविन

क्या मैं इसे सही ढंग से समझता हूं कि बजाय का उपयोग करना समस्या थी? में आधे रास्ते के वेक्टर के उपयोग के बारे में : वास्तव में इसका उपयोग उन दोनों संस्करणों में किया जाता है जिन्हें मैंने पोस्ट किया था (लाटेक्स फार्मूले का निर्माण करते समय मैंने एक गलती की थी और पहले एक में भू-सामान्य लिखा था, मैं इसे जल्द ही ठीक कर दूँगा), लेकिन बिंदु यह है कि आधे रास्ते के सदिश का उपयोग कोसाइन मान की गणना करने के लिए नहीं किया जाता है (अर्थात कोई उपयोग नहीं किया जाता है)। hvnvG1hv
इवोकेलबेल

हां, यही समस्या थी। लेकिन मेरा मुख्य सवाल यह था कि क्या आधा वेक्टर का उपयोग किया जाता है, क्योंकि यह फ़ंक्शन परिभाषा में दिखाई देता है। जहाँ तक मैं समझता हूँ अब यह केवल जाँच में उपयोग किया जाता है यदि H डॉट V पॉजिटिव है। उत्तर लिखने के लिए समय निकालने के लिए धन्यवाद।
इरविन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.