opengl
बुनियादी प्रकाश व्यवस्था
खोज…
फोंग लाइटिंग मॉडल
नोट: यह उदाहरण WIP है, इसे आरेख, चित्र, अधिक उदाहरण आदि के साथ अपडेट किया जाएगा।
फोंग क्या है?
फोंग सतहों के लिए एक बहुत ही बुनियादी, लेकिन वास्तविक दिखने वाला प्रकाश मॉडल है जिसमें तीन भाग होते हैं: परिवेश, फैलाना और स्पेक्युलर लाइटिंग।
परिवेश प्रकाश व्यवस्था:
परिवेश प्रकाश को समझने और गणना करने के लिए तीन भागों में से सबसे सरल है। परिवेश प्रकाश प्रकाश है जो दृश्य को बाढ़ता है और सभी दिशाओं में समान रूप से वस्तु को रोशनी देता है।
परिवेश प्रकाश में दो चर परिवेश की शक्ति और परिवेश के रंग हैं। आपके टुकड़े टुकड़े में, निम्नलिखित परिवेश के लिए काम करेगा:
in vec3 objColor;
out vec3 finalColor;
uniform vec3 lightColor;
void main() {
float ambientStrength = 0.3f;
vec3 ambient = lightColor * ambientStrength;
finalColor = ambient * objColor;
}
प्रसार प्रकाश:
डिफ्यूज़ लाइटिंग थोड़ी अधिक जटिल होती है, फिर परिवेश। डिफ्यूज़ लाइटिंग दिशात्मक प्रकाश है, अनिवार्य रूप से इसका अर्थ है कि प्रकाश स्रोत की ओर आने वाले चेहरे बेहतर रोशन होंगे और दूर की ओर इशारा करते हुए चेहरे गहरे होंगे कि कैसे प्रकाश उन्हें मार रहा है।
नोट: फैलाना प्रकाश प्रत्येक चेहरे के लिए मानदंडों का उपयोग करने की आवश्यकता होगी जो मैं नहीं दिखाऊंगा कि यहां कैसे गणना की जाए। यदि आप यह सीखना चाहते हैं कि यह कैसे करना है, तो 3D गणित पृष्ठ देखें।
कंप्यूटर ग्राफिक्स में प्रकाश के प्रतिबिंब को मॉडल करने के लिए एक द्विदिश परावर्तन वितरण समारोह (BRDF) का उपयोग किया जाता है। BRDF एक फ़ंक्शन है जो एक आउटगोइंग दिशा के साथ प्रतिबिंबित प्रकाश और एक आने वाली दिशा से प्रकाश घटना के बीच संबंध देता है।
एक संपूर्ण विसरित सतह में एक BRDF होता है, जिसमें सभी घटनाओं और आउटगोइंग दिशाओं के लिए समान मूल्य होता है। यह गणनाओं को काफी हद तक कम कर देता है और इस प्रकार आमतौर पर इसका उपयोग सतहों को फैलाने के लिए किया जाता है क्योंकि यह भौतिक रूप से प्रशंसनीय है, भले ही वास्तविक दुनिया में कोई शुद्ध फैल सामग्री नहीं है। इस बीआरडीएफ को लैंबर्टियन प्रतिबिंब कहा जाता है क्योंकि यह लैंबर्ट के ब्रह्मांड नियम का पालन करता है।
लैम्बर्टियन प्रतिबिंब को अक्सर फैलाने वाले प्रतिबिंब के लिए एक मॉडल के रूप में उपयोग किया जाता है। यह तकनीक सभी बंद बहुभुजों (जैसे कि एक 3D मेष के भीतर एक त्रिकोण) का कारण बनता है जब सभी दिशाओं में समान रूप से प्रकाश को प्रतिबिंबित करने के लिए प्रदान किया जाता है। प्रसार गुणांक की गणना सामान्य वेक्टर और प्रकाश वेक्टर के बीच के कोण से की जाती है।
f_Lambertian = max( 0.0, dot( N, L )
जहां N
सतह का सामान्य वेक्टर है, और L
प्रकाश स्रोत की ओर का वेक्टर है।
यह काम किस प्रकार करता है
सामान्य तौर पर 2 वैक्टरों का डॉट उत्पाद दोनों वैक्टरों के परिमाण (lenght) द्वारा गुणा किए गए 2 वैक्टरों के बीच के कोण के कोसाइन के बराबर होता है।
dot( A, B ) == length( A ) * length( B ) * cos( angle_A_B )
यह इस प्रकार है, कि 2 यूनिट वैक्टर का डॉट उत्पाद 2 वैक्टर के बीच के कोण के कोसाइन के बराबर है, क्योंकि एक यूनिट वेक्टर की लंबाई 1 है।
uA = normalize( A )
uB = normalize( B )
cos( angle_A_B ) == dot( uA, uB )
अगर हम कोण -90 ° और 90 ° के बीच कॉस (x) फ़ंक्शन पर एक नज़र डालते हैं तो हम देख सकते हैं कि इसमें 0 ° के कोण पर अधिकतम 1 है और यह 90 ° के कोण पर 0 से नीचे चला जाता है और -90 °।
यह व्यवहार ठीक वैसा ही है जैसा हम प्रतिबिंब मॉडल के लिए चाहते हैं। जब सतह के नोमल वेस्टर और प्रकाश स्रोत के लिए विखंडन एक ही दिशा में होते हैं (बीच का कोण 0 ° होता है) तो हम प्रतिबिंब का अधिकतम भाग चाहते हैं। इसके विपरीत, यदि वैक्टर एक ओर्थोनॉर्मलाइज़्ड (बीच में कोण 90 °) है, तो हम न्यूनतम प्रतिबिंब चाहते हैं और हम 0 ° और 90 ° की दो सीमाओं के बीच एक चिकनी और निरंतर कार्यात्मक चाहते हैं।
यदि प्रकाश की गणना प्रति शीर्ष पर की जाती है, तो प्रतिबिंब की गणना आदिम के प्रत्येक कोने के लिए की जाती है। प्राइमेटिव्स के बीच में रिफ्लेक्शंस अपने बैरिएट्रिक निर्देशांक के अनुसार प्रक्षेपित होते हैं। एक गोलाकार सतह पर परिणामी प्रतिबिंब देखें:
ठीक है, इसलिए हमारे टुकड़े टुकड़े के साथ शुरू करने के लिए, हमें चार इनपुट की आवश्यकता होगी।
- वर्टेक्स मानदंड (बफर में होना चाहिए और वर्टेक्स विशेषता बिंदुओं द्वारा निर्दिष्ट किया जाना चाहिए)
- फ्रैगमेंट पोजीशन (वर्टेकर शेडर से नाज़ुक शैडर में आउटपुट की जानी चाहिए)
- प्रकाश स्रोत की स्थिति (वर्दी)
- हल्के रंग (समान)
in vec3 normal;
in vec3 fragPos;
out vec3 finalColor;
uniform vec3 lightColor;
uniform vec3 lightPos;
uniform vec3 objColor;
मुख्य के अंदर वह जगह है जहाँ हमें कुछ गणित करने की आवश्यकता है। फैलाना प्रकाश की पूरी अवधारणा सामान्य और प्रकाश दिशा के बीच के कोण से आधारित है। अधिक से अधिक कोण, कम प्रकाश वहाँ 90 ° तक है जहाँ कोई प्रकाश नहीं है।
इससे पहले कि हम प्रकाश की मात्रा की गणना शुरू कर सकें, हमें प्रकाश दिशा वेक्टर की आवश्यकता होती है। इसे केवल खंड स्थिति से प्रकाश की स्थिति को घटाकर प्राप्त किया जा सकता है जो खंड की स्थिति की ओर इशारा करते हुए प्रकाश की स्थिति से एक वेक्टर लौटाता है।
vec3 lightDir = lightPos-fragPos;
इसके अलावा, आगे बढ़ें और normal
और lightDir
vectors को normal
ताकि वे उसी लंबाई के साथ काम कर सकें।
normal = normalize(normal);
lightDir = normalize(lightDir);
अब जब हमारे पास हमारे वैक्टर हैं, तो हम उनके बीच के अंतर की गणना कर सकते हैं। ऐसा करने के लिए, हम डॉट उत्पाद फ़ंक्शन का उपयोग करने जा रहे हैं। असल में, यह 2 वैक्टर लेता है और गठित कोण के कॉस () को वापस करता है। यह सही है क्योंकि 90 डिग्री पर यह 0 और 0 डिग्री पर यह उपज देगा। परिणामस्वरूप, जब प्रकाश वस्तु पर सीधे इंगित कर रहा है तो यह पूरी तरह से जलाया जाएगा और इसके विपरीत।
float diff = dot(normal, lightDir);
एक और बात है जो हमें परिकलित संख्या के लिए करना है, हमें यह सुनिश्चित करने की आवश्यकता है कि यह हमेशा सकारात्मक हो। यदि आप इसके बारे में सोचते हैं, तो एक नकारात्मक संख्या के संदर्भ में कोई मतलब नहीं है क्योंकि इसका मतलब है कि प्रकाश चेहरे के पीछे है। हम एक if स्टेटमेंट का उपयोग कर सकते हैं, या हम max()
फ़ंक्शन का उपयोग कर सकते हैं जो max()
दो इनपुट देता है।
diff = max(diff, 0.0);
उस के साथ, हम अब टुकड़े के लिए अंतिम आउटपुट रंग की गणना करने के लिए तैयार हैं।
vec3 diffuse = diff * lightColor;
finalColor = diffuse * objColor;
विशेष प्रकाश व्यवस्था:
प्रोग्रेस में काम करें, बाद में वापस जांचें।
संयुक्त
कार्य प्रगति पर है, बाद में वापस जांचें।
नीचे दिए गए कोड और छवि इन तीन प्रकाश अवधारणाओं को संयुक्त रूप से दिखाते हैं।