घर / छत / ओपनजीएल प्रकाश व्यवस्था। ऐरे () प्रोग्रामिंग पाठ और उदाहरण। प्रकाश व्यवस्था कैसे काम करती है

ओपनजीएल प्रकाश व्यवस्था। ऐरे () प्रोग्रामिंग पाठ और उदाहरण। प्रकाश व्यवस्था कैसे काम करती है

जैसा कि आप देख सकते हैं, हमने एक अतिरिक्त सामान्य मैट्रिक्स पेश किया है, यह वस्तु के स्थानीय समन्वय प्रणाली से वस्तु के सामान्य समन्वय को दुनिया में अनुवाद करने के लिए आवश्यक है, यह विश्व समन्वय प्रणाली में प्रकाश की गणना के लिए आवश्यक है।

यह ध्यान दिया जाना चाहिए कि एफएफपी ओपनजीएल का उपयोग करते समय, प्रकाश की गणना विश्व समन्वय प्रणाली में नहीं, बल्कि दृश्य में की गई थी। मेरी राय में, यह बहुत सुविधाजनक नहीं है, क्योंकि. दृश्य समन्वय प्रणाली कैमरे से जुड़ी हुई है, और विश्व समन्वय प्रणाली में प्रकाश स्रोतों को सेट करना सुविधाजनक है, और यह वहां है कि पूरी गणना की जाती है।

प्रकाश गणना

इस ट्यूटोरियल में प्रकाश गणना के लिए फोंग शेडिंग का उपयोग किया जाता है। मॉडल का मुख्य अर्थ यह है कि वस्तु की अंतिम रोशनी में तीन घटक होते हैं:

  • पृष्ठभूमि प्रकाश (परिवेश)
  • बिखरी हुई रोशनी (फैलाना)
  • परावर्तित प्रकाश (स्पेक्युलर)

इन मापदंडों के अलावा, हम अपनी स्वयं की सामग्री चमक (उत्सर्जन) जोड़ देंगे, यह पैरामीटर आपको वस्तु को उजागर करने की अनुमति देता है, भले ही वह किसी भी प्रकाश स्रोत द्वारा प्रकाशित न हो।

तदनुसार, प्रत्येक घटक की गणना प्रकाश स्रोत के मापदंडों और वस्तु की सामग्री को ध्यान में रखकर की जाती है। आप इस नोट में इस प्रकाश मॉडल के बारे में अधिक जानकारी प्राप्त कर सकते हैं।

प्रकाश गणना या तो प्रति-शीर्ष प्रकाश व्यवस्था या प्रति-पिक्सेल प्रकाश व्यवस्था हो सकती है। इस पाठ में, हम पिक्सेल-दर-पिक्सेल प्रकाश व्यवस्था पर विचार करेंगे, यह आपको बहुभुज मॉडल में विवरण की कमी को दूर करने और वस्तु के प्रत्येक बिंदु पर रोशनी की अधिक सटीक गणना करने की अनुमति देता है। मुख्य प्रति-पिक्सेल प्रकाश गणना फ्रैगमेंट शेडर में होती है।

प्रकाश गणना के साथ आगे बढ़ने से पहले, वर्टेक्स शेडर से फ्रैगमेंट शेडर तक कुछ वर्टेक्स पैरामीटर की गणना करना और पास करना आवश्यक है:

  • शीर्ष पर वस्तु की सतह का सामान्य (सामान्य)
  • आपतित प्रकाश की दिशा, शीर्ष से प्रकाश स्रोत तक (प्रकाश दिशा)
  • दिशा देखें, शीर्ष से प्रेक्षक तक (दिशा देखें)
  • बिंदु प्रकाश स्रोत से शीर्ष तक की दूरी (दूरी)

वस्तु की सतह के सामान्य और आपतित प्रकाश की दिशा का उपयोग विसरित (डिफ्यूज) और परावर्तित (स्पेक्युलर) प्रकाश की गणना के लिए किया जाता है, हालांकि, परावर्तित प्रकाश की गणना करने के लिए, आपको पर्यवेक्षक की टकटकी की दिशा भी जानना आवश्यक है। . समग्र क्षीणन कारक की गणना के लिए शीर्ष से प्रकाश स्रोत तक की दूरी की आवश्यकता होती है। वर्टेक्स शेडर इस तरह दिखेगा:

#संस्करण 330 कोर #VERT_POSITION 0 परिभाषित करें #VERT_TEXCOORD 1 #परिभाषित करें VERT_NORMAL 2 लेआउट (स्थान = VERT_POSITION) को vec3 स्थिति में परिभाषित करें; लेआउट (स्थान = VERT_TEXCOORD) vec2 texcoord में; लेआउट (स्थान = VERT_NORMAL) vec3 सामान्य में; // परिवर्तन पैरामीटरसमान संरचना रूपांतरण (mat4 मॉडल; mat4 व्यूप्रोजेक्शन; mat3 सामान्य; vec3 व्यूपोजीशन; ) रूपांतरण; // बिंदु प्रकाश स्रोत पैरामीटरसमान संरचना पॉइंटलाइट (vec4 स्थिति; vec4 परिवेश; vec4 फैलाना; vec4 स्पेक्युलर; vec3 क्षीणन; ) प्रकाश; // खंड शेडर के लिए पैरामीटरआउट वर्टेक्स (vec2 texcoord; vec3 सामान्य; vec3 लाइटडिर; vec3 व्यूडिर; फ्लोट दूरी; ) वर्ट; शून्य मुख्य(शून्य ) ( // शीर्ष निर्देशांक का विश्व समन्वय प्रणाली में अनुवाद करें vec4 वर्टेक्स = ट्रांसफॉर्म.मॉडल * vec4(स्थिति, 1 .0 ); // विश्व समन्वय प्रणाली में शीर्ष से प्रकाश स्रोत तक की दिशा vec4 लाइटडिर = प्रकाश.स्थिति - शीर्ष; // फ्रैगमेंट शेडर को कुछ पैरामीटर पास करें // बनावट निर्देशांक पास करें vert.texcoord = texcoord; // विश्व समन्वय प्रणाली में सामान्य को पास करेंलंबवत.सामान्य = परिवर्तन.सामान्य * सामान्य; // प्रकाश स्रोत को दिशा दें Vert.lightDir = vec3(lightDir); // विश्व समन्वय प्रणाली में शीर्ष से पर्यवेक्षक तक दिशा पास करें Vert.viewDir = ट्रांसफ़ॉर्म.व्यूपोज़िशन - vec3(vertex); // शीर्ष से प्रकाश स्रोत तक की दूरी पार करें Vert.distance = लंबाई(lightDir); // शीर्ष निर्देशांक को सजातीय में बदलें gl_Position = ट्रांसफॉर्म.व्यूप्रोजेक्शन * वर्टेक्स; )

प्रकाश स्रोत के बिना, छवि दिखाई नहीं देती है। स्रोत को आरंभ करने और वस्तुओं पर स्रोत के प्रभाव की गणना के लिए हैंडलर को सक्षम करने के लिए, निम्नलिखित आदेशों को निष्पादित करना पर्याप्त है: glEnable(gl_lighting); // प्रकाश विश्लेषण मोड सक्षम करें

GlEnable(gl_light0); // दृश्य में एक विशिष्ट (शून्य) स्रोत को उसकी विशेषताओं के साथ शामिल करें

स्रोत को अक्षम करने के लिए Disable() फ़ंक्शन का उपयोग किया जाता है। डिफ़ॉल्ट प्रकाश स्रोत निर्देशांक (0,0,∞) के साथ अंतरिक्ष में स्थित है। आप छवि स्थान में किसी भी बिंदु पर एक प्रकाश स्रोत बना सकते हैं।

ओपनजीएल लाइब्रेरी में चार प्रकार के प्रकाश स्रोत समर्थित हैं:

  • पृष्ठभूमि प्रकाश (परिवेश प्रकाश),
  • बिंदु स्रोत,
  • सर्चलाइट (स्पॉटलाइट),
  • दूरस्थ प्रकाश स्रोत (दूरस्थ प्रकाश)।
प्रत्येक प्रकाश स्रोत की अपनी विशेषताओं का समूह होता है।
प्रकाश स्रोत की विशेषताएं फोंग मॉडल के मापदंडों के अनुरूप हैं।
वेक्टर पैरामीटर सेट करने के लिए, glLightfv() फ़ंक्शन का उपयोग किया जाता है, जिसका प्रारूप निम्न है:

glLightfv(स्रोत, पैरामीटर, पॉइंटर_टू_एरे);

चार वेक्टर पैरामीटर हैं जो स्रोत किरणों की स्थिति और दिशा और उसके घटकों की रंग संरचना - पृष्ठभूमि, प्रसार और स्पेक्युलर निर्धारित करते हैं।
OpenGL में स्केलर पैरामीटर सेट करने के लिए, glLightf() फ़ंक्शन का उपयोग करें:

glLightf(स्रोत, पैरामीटर, मान);

उदाहरण के लिए, दृश्य में स्रोत GL_LIGHT0 को शामिल करना आवश्यक है, जो बिंदु (1.0, 2.0, 3.0) पर स्थित होना चाहिए। स्रोत की स्थिति को प्रोग्राम में सजातीय निर्देशांक में एक बिंदु के रूप में संग्रहीत किया जाता है:

GLfloatlight0_pos=(1.0, 2.0, 3.0, 1.0);

यदि इस बिंदु का चौथा घटक शून्य के बराबर है, तो बिंदु स्रोत दूर में बदल जाता है, जिसके लिए केवल किरणों की दिशा महत्वपूर्ण है:

जीएलफ्लोट लाइट0_डीआईआर=(1.0, 2.0, 3.0, 0.0);

इसके बाद, स्रोत की पृष्ठभूमि, प्रसार और स्पेक्युलर घटकों की रंग संरचना निर्धारित की जाती है। यदि इस उदाहरण में स्रोत में एक सफेद स्पेक्युलर घटक है, और पृष्ठभूमि और प्रसार घटक लाल होना चाहिए, तो स्रोत बनाने वाला प्रोग्राम टुकड़ा इस तरह दिखता है:

GLfloat diffise0= (1.0, 0.0, 0.0, 1.0);

जीएलफ्लोट परिवेश0=(1.0, 0.0, 0.0, 1.0);

जीएलफ्लोट स्पेक्युलर0=(1.0, 1.0, 1.0, 1.0);

GlEnable(GL_LIGHTING);

GlEnable(GL_LIGHT0);

GlLightfv(GL_LIGHT0, GL_POSITION,light0_pos);

GlLightfv(GL_LIGHT0, GL_AMBIENT, ambient0);

GlLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse0);

GlLightfv(GL_LIGHT0, GL_SPECULAR, specular0);

आप दृश्य में वैश्विक पृष्ठभूमि प्रकाश व्यवस्था भी शामिल कर सकते हैं, जो किसी विशेष प्रकाश स्रोत से संबद्ध नहीं है। यदि, उदाहरण के लिए, आप दृश्य में सभी वस्तुओं को सफेद रंग से धुंधला करना चाहते हैं, तो आपको अपने प्रोग्राम में निम्नलिखित कोड स्निपेट शामिल करना चाहिए:

GLfloat ग्लोबल_एंबिएंट=(0.1, 0.1, 0.1, 1.0);

GlLightModelfv(GL_LIGHT_MODEL_AMBIENT, ग्लोबल_एम्बिएंट);

प्रकाश मॉडल में, स्रोत से दूरी को ध्यान में रखने वाले शब्द का रूप इस प्रकार है:

के= 1/(ए+ बी*डी+ सी*डी^2)

और स्थिर, रैखिक और द्विघात घटक। प्रत्येक स्रोत के लिए संबंधित गुणांक स्केलर पैरामीटर सेटिंग फ़ंक्शन का उपयोग करके व्यक्तिगत रूप से सेट किए जाते हैं, उदाहरण के लिए:

GlLightf(GL_LIGHT0, GL_CONSTANT_ATTENATION, a);

किसी बिंदु स्रोत को स्पॉटलाइट में बदलने के लिए, आपको स्पॉटलाइट बीम दिशा (GL_SPOT_DIRECTION), तीव्रता वितरण फ़ंक्शन सूचकांक (GL_SPOT_EXPONENT) और बीम प्रसार कोण (GL_SPOT_CUTTOF) निर्दिष्ट करने की आवश्यकता है। ये पैरामीटर glLightf() और glLightfv() फ़ंक्शंस का उपयोग करके सेट किए गए हैं।

डिफ़ॉल्ट प्रकाश स्रोतों के लिए निर्धारित पैरामीटर तालिका 3 में दिखाए गए हैं।

रोशनी के लिए डिफ़ॉल्ट सेटिंग्स

टेबल तीन

मापदण्ड नाम डिफ़ॉल्ट मान संतुष्ट
GL_AMBIENT (0.0, 0.0, 0.0, 1.0) प्रकाश की परिवेशीय आरजीबीए तीव्रता
GL_DIFFUSE (1.0, 1.0, 1.0, 1.0) प्रकाश की फैलाना RGBA तीव्रता
GL_स्पेक्युलर (1.0, 1.0, 1.0, 1.0) प्रकाश की स्पेक्युलर आरजीबीए तीव्रता
GL_POSITION (0.0, 0.0, 1.0, 0.0) (x, y, z, w) प्रकाश की स्थिति
GL_SPOT_दिशा (0.0, 0.0, -1.0) (x, y, z) स्पॉटलाइट की दिशा
GL_SPOT_EXPONENT 0.0 स्पॉटलाइट प्रतिपादक
GL_SPOT_CUTOFF 180.0 स्पॉटलाइट कटऑफ कोण
GL_CONSTANT_ATTENUATION 1.0 निरंतर क्षीणन कारक
GL_LINEAR_ATTENUATION 0.0 रैखिक क्षीणन कारक
GL_QUADRATIC_ATTENUATION 0.0 द्विघात क्षीणन कारक

ओपनजीएल ईएस में प्रकाश व्यवस्था एक अच्छी सुविधा है जो 3डी गेम्स को एक अच्छा स्पर्श दे सकती है। इस कार्यक्षमता का उपयोग करने के लिए, हमें सबसे पहले OpenGL ES लाइटिंग मॉडल को समझना होगा।

प्रकाश व्यवस्था कैसे काम करती है

आइए विचार करें कि प्रकाश व्यवस्था कैसे काम करती है। सबसे पहले हमें एक प्रकाश स्रोत की आवश्यकता है जो प्रकाश उत्सर्जित करता हो। आपको एक प्रकाशित वस्तु की भी आवश्यकता होगी। अंत में, हमें आंखों या कैमरे की तरह एक सेंसर की भी आवश्यकता होती है, जो प्रकाश स्रोत द्वारा भेजे गए और वस्तु द्वारा परावर्तित फोटॉनों को प्राप्त करता है। प्रकाश किसी वस्तु के कथित रंग को निम्न के आधार पर बदलता है: प्रकाश स्रोत का प्रकार; प्रकाश स्रोत का रंग या तीव्रता; प्रकाश स्रोत की स्थिति और प्रकाशित वस्तु के सापेक्ष उसकी दिशा; वस्तु की सामग्री और बनावट।

किसी वस्तु द्वारा प्रकाश जिस तीव्रता से परावर्तित होता है वह कई कारकों पर निर्भर करता है। सबसे महत्वपूर्ण कारक जिस पर हम ध्यान देते हैं वह वह कोण है जिस पर प्रकाश किरण सतह से टकराती है। यह कोण समकोण के जितना करीब होगा, वस्तु से प्रकाश उतनी ही अधिक तीव्रता से परावर्तित होगा। इसे चित्र में बताया गया है। 11.1.

एक बार जब कोई प्रकाश किरण किसी सतह से टकराती है, तो वह दो अलग-अलग दिशाओं में उछलेगी। अधिकांश प्रकाश विसरित रूप से परावर्तित होगा। इसका मतलब यह है कि परावर्तित प्रकाश किरणें वस्तु की सतह पर असमान रूप से और बेतरतीब ढंग से बिखरी हुई हैं। कुछ किरणें स्पेक्युलर रूप से परावर्तित होती हैं। इसका मतलब यह है कि प्रकाश की किरणें इस तरह वापस लौटेंगी जैसे कि वे किसी आदर्श दर्पण से टकरा रही हों। अंजीर पर. चित्र 11.2 विसरित और स्पेक्युलर प्रतिबिंब के बीच अंतर दिखाता है।

चावल। 11.1. कोण समकोण के जितना करीब होगा, परावर्तित प्रकाश की तीव्रता उतनी ही अधिक होगी।

चावल। 11.2. फैलाना और स्पेक्युलर प्रतिबिंब

स्पेक्युलर प्रतिबिंब वस्तुओं पर हाइलाइट के रूप में दिखाई देगा। प्रकाश किसी वस्तु से स्पेक्युलर तरीके से उछलेगा या नहीं, यह उस सामग्री पर निर्भर करता है जिससे वह बनाई गई है। असमान या खुरदरी त्वचा जैसी सतहों वाली वस्तुओं में स्पेक्युलर हाइलाइट्स न होने की संभावना अधिक होती है। जिन वस्तुओं की सतह चिकनी होती है, जैसे कांच या संगमरमर, उनमें ये हल्की कलाकृतियाँ दिखाई देंगी। बेशक, कांच या संगमरमर पूरी तरह से चिकने नहीं होते हैं, लेकिन लकड़ी या मानव त्वचा की तुलना में, वे होते हैं।

जब प्रकाश किसी सतह से टकराता है, तो उसका प्रतिबिंब भी प्रकाशित होने वाली वस्तु की रासायनिक संरचना के आधार पर रंग बदलता है। जो वस्तुएँ हमें लाल दिखाई देती हैं वे प्रकाश के केवल लाल भाग को परावर्तित करती हैं और अन्य सभी आवृत्तियों को अवशोषित करती हैं। एक काली वस्तु वह होती है जो उस पर पड़ने वाले लगभग सभी प्रकाश को अवशोषित कर लेती है।

ओपनजीएल ईएस आपको प्रकाश स्रोतों और वस्तु सामग्रियों को परिभाषित करके वास्तविक जीवन व्यवहार का अनुकरण करने की अनुमति देता है।

प्रकाश के स्रोत

हम विभिन्न प्रकार के प्रकाश स्रोतों से घिरे हुए हैं। सूर्य लगातार अपने फोटॉन भेज रहा है। मॉनिटर प्रकाश उत्सर्जित करते हैं जो रात में एक सुखद चमक के साथ हमें घेर लेते हैं। प्रकाश बल्ब और हेडलाइट्स हमें अंधेरे में विभिन्न वस्तुओं से टकराव से बचने में मदद करते हैं। ओपनजीएल ईएस आपको चार प्रकार के प्रकाश स्रोत बनाने की अनुमति देता है।

बैकलाइट. यह स्वयं प्रकाश का स्रोत नहीं है, बल्कि अन्य प्रकाश स्रोतों से फोटॉन की उपस्थिति का परिणाम है। साथ में, ये यादृच्छिक फोटॉन कुछ स्थिर स्तर की रोशनी बनाते हैं जिसकी कोई दिशा नहीं होती है और सभी वस्तुओं को समान रूप से प्रकाशित करता है।

बिंदु प्रकाश स्रोत. वे अंतरिक्ष में एक स्थान रखते हैं और सभी दिशाओं में प्रकाश उत्सर्जित करते हैं। उदाहरण के लिए, एक प्रकाश बल्ब प्रकाश का एक बिंदु स्रोत है।

दिशात्मक प्रकाश स्रोत. OpenGL ES में निर्देशों के रूप में व्यक्त किया गया। उन्हें असीम रूप से दूर माना जाता है। आदर्श रूप से, सूर्य ऐसा स्रोत हो सकता है। हम यह मान सकते हैं कि पृथ्वी और सूर्य के बीच की दूरी के कारण सूर्य से आने वाली सभी प्रकाश किरणें एक ही कोण पर पृथ्वी से टकराती हैं।

हे दीपक! ये लाइटें बिंदु लाइटों के समान हैं, क्योंकि अंतरिक्ष में उनकी एक निश्चित स्थिति होती है। इसके अलावा, उनकी एक दिशा होती है जिसमें वे प्रकाश किरणें उत्सर्जित करते हैं। वे एक निश्चित त्रिज्या द्वारा सीमित एक प्रकाश शंकु बनाते हैं। ऐसे प्रकाश स्रोत का एक उदाहरण स्ट्रीट लैंप है।

हम केवल बैकलाइट, साथ ही बिंदु और दिशात्मक प्रकाश स्रोतों पर विचार करेंगे। ओपनजीएल ईएस में जिस तरह से प्रकाश की गणना की जाती है, उसके कारण एंड्रॉइड उपकरणों के सीमित जीपीयू पर रोशनी का उपयोग करना अक्सर मुश्किल होता है। आप जल्द ही समझ जाएंगे कि ऐसा क्यों है.

प्रकाश स्रोत की स्थिति और दिशा के अलावा, ओपनजीएल ईएस आपको प्रकाश के रंग या तीव्रता को परिभाषित करने की अनुमति देता है। ये विशेषताएँ RGBA रंग का उपयोग करके व्यक्त की जाती हैं। हालाँकि, OpenGL ES को एक ही स्रोत के लिए केवल एक के बजाय चार अलग-अलग रंगों को परिभाषित करने की आवश्यकता होती है।

हाइलाइट - वह तीव्रता/रंग जो वस्तु की छाया में योगदान देता है। प्रकाश स्रोत के सापेक्ष उसकी स्थिति या अभिविन्यास की परवाह किए बिना, वस्तु को सभी दिशाओं से समान रूप से प्रकाशित किया जाएगा।

डिफ्यूज़ - प्रकाश की तीव्रता/रंग जो डिफ्यूज़ प्रतिबिंब की गणना के बाद वस्तु को रोशन करेगा। वस्तु के वे किनारे जो प्रकाश स्रोत का सामना नहीं कर रहे हैं, वास्तविक जीवन की तरह ही प्रकाशित नहीं होंगे।

स्पेक्युलर - तीव्रता/रंग विसरित रंग के समान। हालाँकि, यह केवल वस्तु के उन बिंदुओं को प्रभावित करता है जिनका प्रकाश स्रोत और सेंसर के संबंध में एक निश्चित अभिविन्यास होता है।

एमिसिव एक बहुत ही जटिल रंग गणना है जिसका वास्तविक विश्व भौतिकी अनुप्रयोगों में बेहद सीमित उपयोग है, इसलिए हम इसे यहां कवर नहीं करेंगे।

अक्सर, हम प्रकाश स्रोत की विसरित और स्पेक्युलर तीव्रता का उपयोग करेंगे, और हम अन्य दो के लिए डिफ़ॉल्ट मान निर्दिष्ट करेंगे। साथ ही, अधिकांश समय हम डिफ्यूज़ और स्पेक्युलर तीव्रता दोनों के लिए एक ही आरजीबीए रंग का उपयोग करेंगे।

सामग्री

हमारी दुनिया की सभी वस्तुएँ किसी न किसी पदार्थ से बनी हैं। प्रत्येक सामग्री यह निर्धारित करती है कि किसी वस्तु से टकराने वाला प्रकाश किस प्रकार परावर्तित होगा और परावर्तित प्रकाश का रंग कैसे बदलेगा। ओपनजीएल ईएस आपको किसी सामग्री के लिए प्रकाश स्रोत के समान चार आरजीबीए रंगों को परिभाषित करने की अनुमति देता है।

हाइलाइट - एक रंग जो दृश्य में किसी भी प्रकाश स्रोत के पृष्ठभूमि रंग के साथ मिश्रित होता है।

फैला हुआ - एक रंग जो किसी भी प्रकाश स्रोत के फैले हुए रंग के साथ मिल जाता है।

स्पेक्युलर - एक रंग जो किसी भी प्रकाश स्रोत के स्पेक्युलर रंग के साथ मेल खाता है। इसका उपयोग किसी वस्तु की सतह पर हाइलाइट्स बनाने के लिए किया जाता है।

उत्सर्जक - हम इस प्रकार के रंग को अनदेखा करना जारी रखते हैं, क्योंकि यह व्यावहारिक रूप से हमारे संदर्भ में उपयोग नहीं किया जाता है।

चित्र 11.3 पहले तीन प्रकार की सामग्री/प्रकाश गुणों को दर्शाता है: बैकलाइट, डिफ्यूज़ और स्पेक्युलर।

चावल। 11.3. विभिन्न प्रकार की सामग्री/लाइटें: केवल बैकलाइट (बाएं), केवल डिफ्यूज़ (मध्य), बैकलाइट और स्पेक्युलर हाइलाइट्स के साथ डिफ्यूज़ रंग (दाएं)

अंजीर पर. 11.3 रंग पर सामग्रियों और प्रकाश स्रोतों के विभिन्न गुणों के प्रभाव को दर्शाता है। बैकलाइट आकार को समान रूप से प्रकाशित करता है। बिखरी हुई रोशनी उस कोण के आधार पर परावर्तित होगी जिस पर प्रकाश किरणें वस्तु पर पड़ती हैं; जो क्षेत्र सीधे प्रकाश स्रोत के सामने हैं वे अधिक रोशन होंगे, जिन क्षेत्रों में प्रकाश नहीं पहुंच सकता वह अंधेरा हो जाएगा। सही छवि में, आप बैकलाइट, परिवेश और स्पेक्युलर लाइट का संयोजन देख सकते हैं। स्पेक्युलर प्रकाश गोले पर सफेद हाइलाइट्स के रूप में प्रकट होता है।

ओपनजीएल ईएस प्रकाश की गणना कैसे करता है: वर्टेक्स नॉर्मल्स

आप जानते हैं कि किसी वस्तु से परावर्तित प्रकाश की तीव्रता वस्तु पर उसके आपतन कोण पर निर्भर करती है। ओपनजीएल ईएस प्रकाश की गणना के लिए इस तथ्य का उपयोग करता है। इसके लिए यह वर्टेक्स नॉर्म्स का उपयोग करता है, जिसे कोड में बनावट निर्देशांक या वर्टेक्स रंगों की तरह ही परिभाषित किया जाना चाहिए। अंजीर पर. चित्र 11.4 एक गोले और उसके शीर्ष के मानदण्डों को दर्शाता है।

चावल। 11.4. गोला और उसका शीर्ष सामान्य

सामान्य इकाई वेक्टर होते हैं जो सतह की दिशा को इंगित करते हैं। हमारे मामले में, सतह एक त्रिकोण है। एक सतह सामान्य को परिभाषित करने के बजाय, हम एक शीर्ष सामान्य को परिभाषित करते हैं। इन मानदंडों के बीच अंतर यह है कि शीर्ष सामान्य सतह सामान्य के समान दिशा में इंगित नहीं कर सकता है। यह स्पष्ट रूप में चित्र में दिखाई देता है। 11.4, जहां प्रत्येक शीर्ष सामान्य उन सभी त्रिभुजों का औसत सामान्य है, जिनसे शीर्ष संबंधित है। यह औसत वस्तु की एक सहज छायांकन बनाने के लिए किया जाता है।

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

यह बहुत डरावना लगता है, लेकिन वास्तव में यह उतना बुरा नहीं है। हमें प्रकाश के उपयोग को सक्षम करने और प्रकाश स्रोतों, प्रस्तुत वस्तु की सामग्री और शीर्ष मानदंडों को परिभाषित करने की आवश्यकता है (शीर्ष मापदंडों के अतिरिक्त जिन्हें हम सामान्य रूप से परिभाषित करते हैं, जैसे स्थिति या बनावट निर्देशांक)। आइए देखें कि OpenGL ES के साथ यह कैसे किया जा सकता है।

अभ्यास पर

आइए अब OpenGL ES का उपयोग करके प्रकाश व्यवस्था के साथ काम करने के लिए आवश्यक सभी चरण पूरे करें। आइए कुछ छोटे सहायक वर्ग बनाएं जो रोशनी के साथ काम करना थोड़ा आसान बना देंगे और उन्हें .androi dgames.framework.gl के साथ com. Badlogi पैकेज में डाल देंगे।

प्रकाश की अनुमति एवं निषेध

अन्य ओपनजीएल ईएस राज्यों की तरह, नामित कार्यक्षमता को पहले सक्षम किया जाना चाहिए। इसे इस प्रकार किया जा सकता है:

उसके बाद, सभी प्रस्तुत वस्तुओं पर प्रकाश व्यवस्था लागू की जाएगी। परिणाम प्राप्त करने के लिए, आपको प्रकाश स्रोतों और सामग्रियों, साथ ही शीर्ष मानदंडों को परिभाषित करने की आवश्यकता है। जैसे ही हम सभी आवश्यक वस्तुओं का चित्र बनाना समाप्त कर लेते हैं, प्रकाश व्यवस्था बंद कर दी जा सकती है:

प्रकाश स्रोतों का निर्धारण

ओपनजीएल ईएस 4 प्रकार के प्रकाश स्रोत प्रदान करता है: बैकलाइट, पॉइंट, डायरेक्शनल और ल्यूमिनेयर। आइए देखें कि पहले तीन की पहचान कैसे करें। फिक्स्चर के प्रभावी होने और अच्छे दिखने के लिए, प्रत्येक मॉडल में बड़ी संख्या में त्रिकोण होने चाहिए। आज के कई मोबाइल उपकरणों के लिए, यह संभव नहीं है।

ओपनजीएल ईएस आपको एक ही समय में अधिकतम 8 रोशनी, साथ ही एक वैश्विक प्रकाश स्रोत को परिभाषित करने की अनुमति देता है। 8 लाइटों में से प्रत्येक की एक आईडी है, GL10.GL LIGHT0 से GL10.GL LIGHT7 तक। यदि आप इनमें से किसी एक लाइट के गुणों को बदलना चाहते हैं, तो आप संबंधित आईडी को परिभाषित करके ऐसा कर सकते हैं।

आप निम्नलिखित सिंटैक्स का उपयोग करके प्रकाश स्रोतों को सक्षम कर सकते हैं:

इसके बाद, ओपनजीएल ईएस इस प्रकाश स्रोत के गुणों को प्राप्त करेगा और उन्हें सभी प्रदान की गई वस्तुओं पर लागू करेगा। यदि हमें प्रकाश स्रोत को अक्षम करने की आवश्यकता है, तो हम निम्नलिखित कथन के साथ ऐसा कर सकते हैं:

हाइलाइट करना एक विशेष मामला है क्योंकि इसमें कोई आईडी नहीं है। प्रत्येक OpenGL ES दृश्य में केवल एक हाइलाइट हो सकता है। आइए इस प्रकाश स्रोत पर अधिक विस्तार से विचार करें।

बैकलाइट

बैकलाइट एक विशेष प्रकार की प्रकाश व्यवस्था है। इसकी कोई स्थिति या दिशा नहीं है, केवल एक रंग है जो सभी प्रकाशित वस्तुओं पर समान रूप से लागू होता है। ओपनजीएल ईएस आपको वैश्विक हाइलाइट को इस तरह परिभाषित करने की अनुमति देता है:

एम्बिएंटकॉल या एरे में हल्के रंग के आरजीबीए मान होते हैं, जिन्हें 0 से 1 तक के फ्लोटिंग पॉइंट नंबरों के रूप में दर्शाया जाता है। जीएल लाइटमॉडल एफवी विधि अपने पहले पैरामीटर के रूप में एक स्थिरांक लेती है जो निर्दिष्ट करती है कि हम पृष्ठभूमि का रंग सेट करना चाहते हैं प्रकाश स्रोत, फ़्लोटिंग पॉइंट संख्याओं की एक सरणी जिसमें स्रोत का रंग होता है, और फ़्लोट्स की सरणी के लिए ऑफसेट होता है जिससे विधि आरजीबीए मान पढ़ना शुरू कर देगी। आइए इस समस्या को हल करने वाले कोड को एक छोटी कक्षा में रखें। इसका कोड लिस्टिंग 11.2 में दिखाया गया है।

सूची 11.2. एम्बिएंटलाइट.जावा क्लास। सरल ओडेनजीएल ईएस वैश्विक हाइलाइटिंग अमूर्तन

हम जो कुछ कर रहे हैं वह हाइलाइट रंग को फ्लोट्स की एक श्रृंखला में संग्रहीत करना है और दो तरीके प्रदान करना है, एक रंग सेट करने के लिए उपयोग किया जाता है और दूसरा ओपनजीएल ईएस को उस विशेष रंग का उपयोग करने के लिए कहता है। डिफ़ॉल्ट रंग ग्रे है.

बिंदु प्रकाश स्रोत

बिंदु रोशनी में एक स्थिति और पृष्ठभूमि, फैलाना और स्पेक्युलर रंग/तीव्रता होती है (हम उत्सर्जक रंग/तीव्रता पर विचार नहीं करते हैं)। आप विभिन्न प्रकार के रंगों को इस प्रकार परिभाषित कर सकते हैं:

पहला पैरामीटर प्रकाश स्रोत का पहचानकर्ता है। इस मामले में, हम चौथे स्रोत का उपयोग करते हैं। अगला पैरामीटर उस विशेषता को निर्दिष्ट करता है जिसे हम बदलना चाहते हैं। तीसरा पैरामीटर आरजीबीए मानों वाले फ्लोट्स की एक सरणी है, और अंतिम इस सरणी में एक ऑफसेट है। स्रोत स्थिति निर्धारित करना उतना ही आसान है:

हम फिर से उस विशेषता को परिभाषित करते हैं जिसे हम बदलना चाहते हैं (इस मामले में स्थिति), बनाई जा रही दुनिया में प्रकाश स्रोत के x-, y- और z-समन्वय वाले चार तत्वों की एक सरणी। ध्यान दें कि यदि प्रकाश स्रोत की स्थिति है तो सरणी का चौथा तत्व एक के बराबर होना चाहिए। आइए इसे सहायक वर्ग में रखें। इसका कोड लिस्टिंग 11.3 में है।

सूची 11.3. प्वाइंट.लाइट.जावा क्लास, एक सरल ओपनजीएल ईएस प्वाइंट लाइट एब्स्ट्रैक्शन

हमारे सहायक वर्ग में प्रकाश की पृष्ठभूमि, फैलाना और स्पेक्युलर रंग घटक, साथ ही स्थिति (चौथा तत्व एक है) शामिल है। इसके अलावा, हम किसी दिए गए स्रोत के लिए उपयोग किए गए अंतिम पहचानकर्ता को संग्रहीत करते हैं, इसलिए एक disableO विधि बनाना संभव हो जाता है जो आवश्यक होने पर प्रकाश बंद कर देगा। हमारे पास EnableO विधि भी है, जो GL10 क्लास और एक लाइट आईडी (उदाहरण के लिए, GL10.GL LIGHT6) का उदाहरण लेती है। यह प्रकाश के उपयोग को सक्षम बनाता है, इसकी विशेषताओं को निर्धारित करता है, और उपयोग किए गए पहचानकर्ता को संग्रहीत करता है। DisableO विधि सक्षम विधि में सेट किए गए 1ast.Ligh.tId वर्ग सदस्य का उपयोग करके प्रकाश के उपयोग को अक्षम कर देती है।

क्लास सदस्य सरणियों को आरंभ करते समय हम पृष्ठभूमि, फैलाना और स्पेक्युलर रंगों के लिए उचित डिफ़ॉल्ट का उपयोग करते हैं। प्रकाश सफ़ेद होगा और कोई चमक पैदा नहीं करेगा क्योंकि इसका स्पेक्युलर घटक काला है।

दिशात्मक प्रकाश स्रोत

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

हम इसे एक वेक्टर में बदल सकते हैं:

बाकी विशेषताएँ, जैसे पृष्ठभूमि या परिवेश का रंग, बिंदु प्रकाश के समान हैं। सूची 11.4 दिशात्मक रोशनी बनाने के लिए उपयोग किए जाने वाले एक छोटे सहायक वर्ग के लिए कोड दिखाती है।

सूची 11.4. Directi onLi ght.java वर्ग, OpenGL ES में दिशात्मक रोशनी का एक सरल सार

यह सहायक वर्ग पॉइंटलाइट वर्ग के लगभग समान है। फर्क सिर्फ इतना है कि डायरेक्टी ऑन ऐरे में चौथा तत्व एक है। इसके अलावा, सेटपोज़िशन विधि के बजाय, सेटडायरेक्टी ऑन विधि दिखाई दी है। यह आपको दिशा निर्दिष्ट करने की अनुमति देता है, उदाहरण के लिए: (-1; 0; 0), इस मामले में, प्रकाश दाईं ओर से आएगा। विधि के अंदर, सभी वेक्टर घटक अपना चिह्न बदलते हैं, इसलिए हम दिशा को ओपनजीएल ईएस द्वारा अपेक्षित प्रारूप में परिवर्तित करते हैं।

हम सामग्री को परिभाषित करते हैं

एक सामग्री को कई विशेषताओं द्वारा परिभाषित किया जाता है। किसी भी अन्य ओपनजीएल ईएस ऑब्जेक्ट की तरह, एक सामग्री एक ऐसी स्थिति है जो तब तक सक्रिय रहेगी जब तक हम इसे दोबारा नहीं बदलते या ओपनजीएल ईएस संदर्भ खो जाने तक सक्रिय रहेगा। वर्तमान सामग्री विशेषताओं को सेट करने के लिए, हम निम्नलिखित कार्य कर सकते हैं:

हमेशा की तरह, हमें आरजीबीए पृष्ठभूमि, फैलाना और स्पेक्युलर रंगों को परिभाषित करने की आवश्यकता है। इसे पहले की तरह ही किया जा सकता है - चार तत्वों से युक्त फ्लोटिंग पॉइंट नंबरों की सरणियों का उपयोग करके।

इन क्रियाओं को एक सहायक वर्ग में संयोजित करना बहुत आसान है। आप परिणाम लिस्टिंग 11.5 में देख सकते हैं।

सूची 11.5. सामग्री जावा वर्ग, ओपनजीएल ईएस सामग्री का एक सरल सार

यहां भी कोई आश्चर्य की बात नहीं है. हम केवल तीन घटकों को रखते हैं जो सामग्री का वर्णन करते हैं, और उनके मूल्यों को सेट करने के लिए फ़ंक्शन प्रदान करते हैं और एक सक्षम विधि प्रदान करते हैं जो उन्हें ओपनजीएल ईएस में भेजती है।

जब सामग्री की बात आती है तो ओपनजीएल ईएस के पास एक और तरकीब है। यह आमतौर पर glMaterialfvO विधि के बजाय सामग्री रंग नामक किसी चीज़ का उपयोग करता है। इसका मतलब यह है कि glMaterial al fv विधि द्वारा परिभाषित पृष्ठभूमि और विसरित रंगों के बजाय, OpenGL ES सामग्री के पृष्ठभूमि और विसरित रंगों के रूप में हमारे मॉडल के शीर्ष रंग को लेगा। इस सुविधा को सक्षम करने के लिए, आपको बस इसे कॉल करना होगा:

मैं आमतौर पर यही करता हूं, क्योंकि पृष्ठभूमि और फैले हुए रंग अक्सर एक जैसे होते हैं। चूँकि मैं अपने अधिकांश गेम और डेमो में स्पेक्युलर हाइलाइट्स का उपयोग नहीं करता, इसलिए मैं आसानी से इस पद्धति का उपयोग कर सकता हूं और glMaterial fv को कॉल नहीं कर सकता। आप कौन सी विधि का उपयोग करते हैं यह आप पर निर्भर है।

सामान्य को परिभाषित करना

ओपनजीएल ईएस में काम करने के लिए प्रकाश व्यवस्था के लिए, आपको मॉडल के प्रत्येक शीर्ष के लिए शीर्ष मानदंडों को परिभाषित करने की आवश्यकता है। शीर्ष सामान्य एक इकाई वेक्टर होना चाहिए जो (आमतौर पर) उस दिशा की ओर इशारा करता है जिस सतह पर शीर्ष का सामना करना पड़ रहा है। अंजीर पर. चित्र 11.5 हमारे घन के लिए शीर्ष मानदण्डों को दर्शाता है।

चावल। 11.5. हमारे घन के प्रत्येक शीर्ष के लिए शीर्ष मानदंड

स्थिति या रंग की तरह, शीर्ष सामान्य शीर्ष का एक और गुण है। शीर्ष मानदंडों का लाभ उठाने के लिए, हमें Vertices3 वर्ग को फिर से संशोधित करने की आवश्यकता है। ओपनजीएल ईएस को यह बताने के लिए कि वह प्रत्येक शीर्ष के लिए मानक कहां पा सकता है, हम जीएल नॉर्मल पॉइंटरओ विधि का उपयोग करेंगे, जैसे हमने पहले जीएल वर्टेक्सपॉइंटर या जीएल कोल या पॉइंटर विधियों का उपयोग किया था। सूची 11-6 Vertices3 वर्ग का अंतिम संस्करण दिखाती है।

सूची 11.6. Vertices3.Java वर्ग, सामान्यों का समर्थन करने वाला अंतिम संस्करण

वर्ग में एक नया सदस्य hasNormal.s है जो इस बात पर नज़र रखता है कि शीर्षों में मानक हैं या नहीं।

कंस्ट्रक्टर अब hasNormals पैरामीटर को भी स्वीकार करता है। हमें अभी भी जहां संभव हो, प्रति शीर्ष तीन फ़्लोट्स जोड़कर vertexSize सदस्य की गणना को संशोधित करने की आवश्यकता है।

जैसा कि आप देख सकते हैं, setVertices और setIndices विधियाँ अपरिवर्तित रहती हैं।

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

जैसा कि आप देख सकते हैं, ड्रा विधि भी नहीं बदली है; सभी क्रियाएँ बाइंड विधि O में होती हैं।

अंत में, हम unbindO विधि को थोड़ा संशोधित करते हैं। हम सामान्य पॉइंटर्स के उपयोग को अक्षम कर देते हैं, यदि कोई हो, तो तदनुसार ओपनजीएल ईएस स्थिति को साफ़ कर देते हैं।

संशोधित Verti ces3 क्लास को लागू करना पहले की तरह ही आसान है। एक छोटे से उदाहरण पर विचार करें:

हम तीन शीर्षों को रखने के लिए फ़्लोट्स की एक सरणी बनाते हैं, प्रत्येक की एक स्थिति होती है (प्रत्येक पंक्ति पर पहले तीन नंबर) और एक सामान्य (प्रत्येक पंक्ति पर अंतिम तीन नंबर)। इस मामले में, हम xy तल में एक त्रिभुज को परिभाषित करते हैं, जिसके मानक सकारात्मक z-अक्ष की दिशा में इंगित करते हैं।

हमें बस Vertices3 वर्ग का एक उदाहरण बनाना है और शीर्ष मान सेट करना है। बहुत आसान है, है ना?

बाइंडिंग, ड्राइंग और अनबाइंडिंग का सारा काम ठीक उसी तरह से किया जाता है जैसे कक्षा के पिछले संस्करण में किया गया था। पहले की तरह, हम शीर्ष रंग और बनावट निर्देशांक जोड़ सकते हैं।

यह सब एक साथ डालें

आइए इसे सब एक साथ रखें। हमें एक ऐसा दृश्य बनाने की ज़रूरत है जिसमें वैश्विक रोशनी, बिंदु और दिशात्मक प्रकाश स्रोत हों। वे मूल स्थान पर स्थित घन को प्रकाशित करेंगे। हमें gl uLookAt विधि को भी कॉल करने की आवश्यकता है। कैमरे की स्थिति निर्धारित करने के लिए. अंजीर पर. 11.6 हमारी दुनिया का स्वरूप दर्शाता है।

अन्य सभी उदाहरणों के लिए, हम एक क्लास बनाएंगे जिसे लाइटटेस्ट कहा जाएगा, हमेशा की तरह GLGame क्लास का विस्तार। यह getStartScreenO विधि का उपयोग करके लाइटस्क्रीन क्लास का एक उदाहरण लौटाएगा। लाइटस्क्रीन क्लास जीएलस्क्रीन क्लास (सूची 11-7) से विरासत में मिली है।

चावल। 11.6. हमारा पहला रोशन मंच

सूची 11.7. LightTest.java वर्ग के टुकड़े। OpenGL ES के साथ प्रकाश व्यवस्था बनाना

आइए कक्षा के कुछ सदस्यों का वर्णन करके शुरुआत करें। कोण सदस्य y-अक्ष के चारों ओर घन के वर्तमान घूर्णन के बारे में जानकारी संग्रहीत करता है। Vertices3 सदस्य क्यूब मॉडल के शीर्षों को संग्रहीत करता है, जिसे हम शीघ्र ही परिभाषित करेंगे। इसके अलावा, हमारे पास एंबिएंटलाइट, पॉइंटलाइट और डायरेक्शनल लाइट क्लास के उदाहरण हैं, साथ ही मटेरियल क्लास का एक उदाहरण भी है।

इसके बाद कंस्ट्रक्टर आता है। यहीं पर क्यूब मॉडल के शीर्ष बनाए जाते हैं और बॉक्स बनावट भी लोड की जाती है। हम रोशनी और सामग्री भी प्रारंभ करते हैं। रोशनी का रंग हल्का हरा है. दिशात्मक स्रोत लाल है और हमारी दुनिया के बिंदु (3; 3; 0) पर स्थित है। दिशात्मक प्रकाश स्रोत का रंग नीला फैला हुआ है, प्रकाश बाईं ओर से गिरता है। सामग्री के लिए, डिफ़ॉल्ट मानों का उपयोग करें (कुछ हद तक पृष्ठभूमि, फैलाना घटक के लिए सफेद और स्पेक्युलर घटक के लिए काला)।

बायोडाटा विधि में, हम यह सुनिश्चित करते हैं कि यदि संदर्भ खो गया है तो हमारी बनावट (पुनः) लोड की गई है।

createCube विधि पिछले उदाहरणों से बहुत अधिक नहीं बदली है। हालाँकि, इस बार हम प्रत्येक शीर्ष के लिए मानक जोड़ते हैं, जैसा कि चित्र में दिखाया गया है। 11.5. इसके अलावा, सब कुछ वैसा ही रहता है.

अद्यतन विधि में, हम बस घन के घूर्णन कोण को बढ़ाते हैं।

यह यहाँ अधिक दिलचस्प है. पहली कुछ पंक्तियाँ रंग और गहराई बफ़र को साफ़ करने, गहराई परीक्षण सक्षम करने और दायरा निर्धारित करने के लिए बॉयलरप्लेट हैं।

इसके बाद, हम gl uPerspective विधि का उपयोग करके प्रोजेक्शन मैट्रिक्स को परिप्रेक्ष्य प्रक्षेपण मैट्रिक्स के बराबर सेट करते हैं, और हम मॉडल-व्यू मैट्रिक्स पर gl uLookAt विधि का भी उपयोग करते हैं, ताकि कैमरा चित्र के समान ही काम करे। 11.6.

फिर हम प्रकाश के उपयोग की अनुमति देते हैं। इस बिंदु पर, अभी तक किसी भी रोशनी को परिभाषित नहीं किया गया है, इसलिए हम उन्हें रोशनी और सामग्रियों के लिए एक विधि कॉल के साथ अगली कुछ पंक्तियों में परिभाषित करते हैं।

हमेशा की तरह, हम टेक्सचरिंग को भी सक्षम करते हैं और बॉक्स के टेक्सचर को बाइंड करते हैं। अंत में, हम क्यूब को घुमाने के लिए gl RotatefC) विधि को कॉल करते हैं और फिर Vertices3 क्लास में अच्छी तरह से रखे गए इंस्टेंस कॉल के साथ इसके कोने बनाते हैं।

विधि के अंत में, हम बिंदु और दिशात्मक रोशनी बंद कर देते हैं (याद रखें, हाइलाइटिंग एक वैश्विक स्थिति है), साथ ही बनावट और गहराई परीक्षण भी बंद कर देते हैं। OpenGL ES में प्रकाश व्यवस्था के लिए बस इतना ही।

शेष कक्षा खाली है; विराम की स्थिति में हमें कुछ भी करने की आवश्यकता नहीं है। अंजीर पर. 11.7 प्रोग्राम का परिणाम दिखाता है.

चावल। 11.7. चित्र में दिखाया गया दृश्य. 11.6 OpenGL ES के साथ प्रस्तुत किया गया

ओपनजीएल ईएस में प्रकाश व्यवस्था पर कुछ नोट्स

हालाँकि प्रकाश का उपयोग आपके खेल में निखार ला सकता है, लेकिन इसकी अपनी सीमाएँ और खामियाँ हैं। कुछ चीजें हैं जिनके बारे में आपको अवगत होना चाहिए।

प्रकाश का उपयोग करने से बहुत अधिक संसाधनों की खपत होती है, विशेष रूप से धीमे उपकरणों पर ध्यान देने योग्य। प्रकाश सावधानी से लगाएं। आप जितनी अधिक रोशनी का वर्णन करेंगे, दृश्य को प्रस्तुत करने में उतनी ही अधिक गणनाएँ लगेंगी।

कैमरा मैट्रिसेस लोड होने के बाद और वस्तुओं को स्थानांतरित करने और घुमाने के लिए मॉडल-व्यू मैट्रिक्स को किसी अन्य मैट्रिसेस से गुणा करने से पहले बिंदु/दिशात्मक प्रकाश स्रोतों की स्थिति/दिशा निर्धारित की जानी चाहिए। यह महत्वपूर्ण है. इन दिशानिर्देशों का पालन करने में विफलता के परिणामस्वरूप अस्पष्टीकृत प्रकाश कलाकृतियाँ हो सकती हैं।

किसी मॉडल का आकार बदलने के लिए gl Seal ef विधि का उपयोग करते समय, इसके मानदंडों को भी स्केल किया जाएगा। यह बुरा है क्योंकि ओपनजीएल ईएस दी गई इकाइयों में सामान्य होने की उम्मीद करता है। इस समस्या को हल करने के लिए, आप glEnable(GL10.GL NORMALIZE) कमांड का उपयोग कर सकते हैं, या कुछ परिस्थितियों में gl Enable(GL10 .GL RESCALE N0RMAL) का उपयोग कर सकते हैं। मुझे लगता है कि पहले कमांड का उपयोग किया जाना चाहिए क्योंकि दूसरे में सीमाएँ और नुकसान हैं। समस्या यह है कि सामान्यीकरण या सामान्यीकरण में बहुत अधिक प्रसंस्करण शक्ति की आवश्यकता होती है। प्रदर्शन की दृष्टि से सबसे अच्छा समाधान प्रबुद्ध वस्तुओं को मापना नहीं है।

इस पाठ में, हम सीखेंगे कि अपने 3डी मॉडल को प्रकाश और छाया कैसे दें। हम जो सीखेंगे उसकी एक सूची यहां दी गई है:

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

दूसरे शब्दों में, सबसे सरल प्रकाश व्यवस्था और छायांकन।

नॉर्मल्स

पिछले पाठ में, हमने सामान्य मानदंडों के साथ काम किया, लेकिन यह समझे बिना कि आखिर उनकी आवश्यकता क्यों है।

त्रिभुज सामान्य

किसी समतल का अभिलंब एक इकाई वेक्टर होता है जो उस समतल के लंबवत होता है।

किसी त्रिभुज का अभिलंब त्रिभुज के लंबवत निर्देशित एक इकाई वेक्टर होता है। त्रिभुज की दोनों भुजाओं के क्रॉस उत्पाद का उपयोग करके सामान्य की गणना बहुत सरलता से की जाती है (यदि आपको याद हो, तो दो वैक्टरों का क्रॉस उत्पाद हमें दोनों के लिए लंबवत एक वेक्टर देता है) और सामान्यीकृत किया जाता है: इसकी लंबाई एक पर सेट की जाती है।

यहाँ सामान्य गणना छद्मकोड है:

त्रिकोण(v1, v2, v3)
पार्श्व1=v2-v1
पार्श्व2=v3-v1
त्रिकोण.सामान्य = वेक्टप्रोडक्ट(साइड1, साइड2).नॉर्मलाइज़()

शीर्ष सामान्य

यह गणना की सुविधा के लिए शुरू की गई सामान्य बात है। यह दिए गए शीर्ष के चारों ओर के त्रिभुजों के अभिलंबों का संयुक्त अभिलंब है। यह बहुत सुविधाजनक है, क्योंकि वर्टेक्स शेडर्स में हम शीर्षों से निपट रहे हैं, त्रिभुजों से नहीं। किसी भी मामले में, में ओपनजीएल में, हम लगभग कभी भी त्रिकोणों से निपटते नहीं हैं।

शीर्ष v1, v2, v3, ....
त्रिकोण tr1, tr2, tr3 // वे सभी शीर्ष v1 का उपयोग करते हैं
v1.सामान्य = सामान्यीकरण(tr1.सामान्य + tr2.सामान्य + tr3.सामान्य)

ओपनजीएल में वर्टेक्स नॉर्म्स का उपयोग करना

ओपनजीएल में मानदंडों का उपयोग करना बहुत सरल है। सामान्य केवल एक शीर्ष विशेषता है, बिल्कुल स्थिति, रंग या यूवी निर्देशांक की तरह... इसलिए सीखने के लिए कुछ भी नया नहीं है... यहां तक ​​कि हमारा सरल लोडओबीजे फ़ंक्शन पहले से ही सामान्य लोड करता है।

ग्लिंट नॉर्मलबफ़र;
glGenBuffers(1, &सामान्यबफ़र);

glBufferData(GL_ARRAY_BUFFER, Norms.size() * sizeof(glm::vec3), &norms, GL_STATIC_DRAW);

// तीसरा गुण बफर: सामान्य
glEnableVertexAttribArray(2);

glBindBuffer(GL_ARRAY_BUFFER, नॉर्मलबफ़र);
glVertexAttribPointer(
2, // गुण
3, // आकार
GL_FLOAT, //प्रकार
GL_FALSE, // सामान्यीकृत?
0, // चरण
(शून्य*)0 // बफर ऑफसेट
);

और यह आरंभ करने के लिए पर्याप्त है:


फैला हुआ प्रकाश

सतह का महत्व सामान्य

जब कोई प्रकाश किरण किसी सतह से टकराती है, तो उसका अधिकांश भाग सभी दिशाओं में परावर्तित हो जाता है। इसे "विस्तारित घटक" कहा जाता है। हम बाकी घटकों को थोड़ी देर बाद देखेंगे।

किरण के गिरने के बाद, सतह अलग-अलग तरीकों से प्रकाश को परावर्तित करती है, यह उस कोण पर निर्भर करता है जिस पर यह किरण सतह पर गिरती है। यदि किरण सतह पर लंबवत गिरती है, तो यह एक छोटे से क्षेत्र पर केंद्रित होती है, यदि यह स्पर्शरेखा होती है, तो यह बहुत बड़ी सतह पर बिखर जाती है:


कंप्यूटर ग्राफ़िक्स के दृष्टिकोण से, पिक्सेल का रंग प्रकाश की दिशा के कोण और सतह के सामान्य कोण में अंतर पर बहुत निर्भर होता है।


//
//
फ्लोट कॉसथीटा = डॉट(एन,एल);

इस कोड में, "n" सामान्य है, और "l" इकाई वेक्टर है जो सतह से प्रकाश तक जाता है (इसके विपरीत नहीं, हालांकि यह भ्रामक लग सकता है)

संकेत से सावधान रहें

कई बार हमारा फॉर्मूला काम नहीं करेगा. उदाहरण के लिए, जब प्रकाश त्रिभुज के पीछे है, n और l विपरीत होंगे, इसलिए n.l ऋणात्मक होगा। और अंत में, हमारे पास किसी प्रकार का नकारात्मक रंग होगा, और परिणामस्वरूप, किसी प्रकार की बकवास होगी। इसलिए, हम क्लैंप फ़ंक्शन का उपयोग करके सभी नकारात्मक संख्याओं को 0 में बदल देंगे।

// सामान्य और प्रकाश दिशा के बीच कोण की कोज्या
// 1 - यदि प्रकाश त्रिभुज के लंबवत है
// 0 - यदि प्रकाश त्रिभुज के समानांतर है
// 0 - यदि प्रकाश त्रिभुज के पीछे है
फ्लोट कॉसथीटा = क्लैंप(डॉट(एन, एल), 0.1);
रंग = हल्का रंग * कॉसथीटा;

सामग्री का रंग

बेशक, वस्तु का रंग काफी हद तक सामग्री के रंग पर निर्भर होना चाहिए। सफ़ेद प्रकाश के तीन घटक होते हैं - लाल, नीला और हरा। जब प्रकाश लाल सतह से टकराता है, तो हरा और नीला घटक अवशोषित हो जाता है और लाल परावर्तित हो जाता है।



हम इसे एक साधारण गुणन के साथ मॉडल कर सकते हैं:

रंग = मटेरियलडिफ्यूज़ कलर * लाइट कलर * कॉसथीटा;

प्रकाश मॉडलिंग

आइए मान लें कि हमारे पास एक बिंदु प्रकाश स्रोत है जो मोमबत्ती की तरह सभी दिशाओं में प्रकाश उत्सर्जित करता है।

ऐसे प्रकाश स्रोत के साथ, सतह की रोशनी का स्तर प्रकाश स्रोत की दूरी पर निर्भर करेगा: जितना दूर, उतना गहरा। इस निर्भरता की गणना इस प्रकार की जाती है:

रंग = मटेरियलडिफ्यूज़कलर * लाइटकलर * कॉसथीटा / (दूरी*दूरी);

जल्द ही हमें प्रकाश की तीव्रता के स्तर को नियंत्रित करने के लिए एक और पैरामीटर की आवश्यकता होगी - प्रकाश का रंग, लेकिन अभी के लिए, मान लें कि हमारे पास एक निश्चित शक्ति (उदाहरण के लिए, 60 वाट) के साथ एक सफेद प्रकाश बल्ब है।

रंग = मटेरियलडिफ्यूज़कलर * लाइट कलर * लाइटपावर * कॉसथीटा / (दूरी*दूरी);

यह सब एक साथ डालें

इस कोड को काम करने के लिए, हमें मापदंडों के एक निश्चित सेट (रंग और शक्ति) और कुछ अतिरिक्त कोड की आवश्यकता होती है।

मटेरियलडिफ्यूज़कलर - हम इसे सीधे बनावट से ले सकते हैं।

लाइट कलर और लाइट पावर को जीएलएसएल यूनिफॉर्म का उपयोग करके शेडर में सेट करने की आवश्यकता होगी।

CosTheta वेक्टर n और l पर निर्भर करेगा। इसकी गणना किसी भी स्थान के लिए की जा सकती है, कोण समान होगा। हम कैमरा स्पेस का उपयोग करेंगे, क्योंकि यहां प्रकाश स्रोत की स्थिति की गणना करना बहुत आसान है:

// कैमरा स्पेस में फ्रैगमेंट सामान्य
vec3 n = सामान्यीकरण(Normal_cameraspace);
// प्रकाश की दिशा (टुकड़े से प्रकाश स्रोत तक
vec3 l = सामान्यीकरण(लाइटडायरेक्शन_कैमरास्पेस);

सामान्य _कैमरास्पेस और लाइटडायरेक्शन _कैमरास्पेस शीर्ष शेडर में गणना की जाती है और आगे की प्रक्रिया के लिए टुकड़े शेडर को भेज दिया जाता है:

// कैमरा स्पेस में शीर्ष की स्थिति: एमवीपी * स्थिति
gl_स्थिति= एमवीपी * vec4(vertexPosition_modelspace,1);
// विश्व अंतरिक्ष में शीर्ष की स्थिति: एम * पद
पोजीशन_वर्ल्डस्पेस = (एम * वीईसी4(वर्टेक्सपोजिशन_मॉडलस्पेस,1)).xyz;
// वेक्टर जो ऊपर से आता हैकैमरा स्पेस में कैमरा
// कैमरा स्पेस में, कैमरा स्थिति (0,0,0) पर है
वी.ई.सी 3 शीर्षस्थिति _ कैमरास्पेस = ( वी * एम * वी.ई.सी 4( शीर्षस्थिति _ मॉडलस्पेस ,1)). xyz ;
EyeDirection_cameraspace = vec3(0,0,0) - vertexPosition_cameraspace;
// एक वेक्टर जो कैमरा स्पेस में शीर्ष से प्रकाश स्रोत तक जाता है।
//आव्यूह एम छोड़ दिया गया, क्योंकि यह इस स्थान में एकल है।
vec3 लाइटपोजिशन_कैमरास्पेस = (वी * vec4(LightPosition_worldspace,1)).xyz;
लाइटडायरेक्शन_कैमरास्पेस = लाइटपोजिशन_कैमरास्पेस +
आईडायरेक्शन_कैमरास्पेस;
// सामान्य चोटियों वी अंतरिक्ष कैमरा
नॉर्मल_कैमरास्पेस = (वी * एम * वीईसी4(वर्टेक्सनॉर्मल_मॉडलस्पेस,0)).xyz; // इच्छा काम केवल वी आयतन मामला , कब आव्यूह मॉडल नहीं परिवर्तन उसकी आकार .

पहली नज़र में, कोड जटिल और भ्रमित करने वाला लग सकता है, लेकिन वास्तव में, यहां कुछ भी नया नहीं है जो पाठ 3: मैट्रिसेस में नहीं था। मैंने प्रत्येक वेरिएबल को सार्थक नाम देने का प्रयास किया ताकि आपके लिए यह समझना आसान हो कि क्या हो रहा है और कैसे हो रहा है।

प्रयास अवश्य करें!!!

एम और वी मॉडल और व्यू मैट्रिसेस हैं जो हमारे अच्छे पुराने एमवीपी की तरह ही शेडर को पास किए जाते हैं।

परीक्षण समय

मैंने आपको वह सब कुछ बता दिया है जो आपको विसरित प्रकाश व्यवस्था बनाने के लिए जानना आवश्यक है। आगे बढ़ें, इसे आज़माएँ।

परिणाम

केवल एक फैले हुए घटक के साथ, हमें यहां ऐसी तस्वीर मिलती है (बदसूरत बनावट के लिए मुझे क्षमा करें)।



ऐसा लगता है कि यह पहले से बेहतर है, लेकिन अभी भी बहुत कुछ गायब है। समस्या विशेष रूप से अप्रकाशित भागों के साथ ध्यान देने योग्य है। हमारे प्रिय बंदर सुजैन के सिर का पिछला हिस्सा पूरी तरह से काला है (आखिरकार हमने क्लैंप() का इस्तेमाल किया)।

परिवेश प्रकाश व्यवस्था

परिवेशीय प्रकाश व्यवस्था शुद्ध धोखा है।

सुज़ैन के सिर का पिछला भाग पूरी तरह से काला नहीं होना चाहिए, क्योंकि वास्तविक जीवन में दीपक की रोशनी दीवार, फर्श, छत पर गिरनी चाहिए, आंशिक रूप से उससे परावर्तित होनी चाहिए और वस्तु के छाया वाले हिस्से को रोशन करना चाहिए।

हालाँकि, वास्तविक समय में ऐसा करना कम्प्यूटेशनल रूप से बहुत महंगा है। और इसीलिए हम कुछ स्थिर घटक जोड़ेंगे। यह ऐसा है मानो वस्तु स्वयं कुछ प्रकाश उत्सर्जित कर रही हो ताकि पूरी तरह से काली न हो जाए।

vec3 मटेरियलएम्बिएंट कलर = vec3(0.1,0.1,0.1) * मटेरियलडिफ्यूज कलर;
रंग=
// व्यापक प्रकाश : अनुकरण अप्रत्यक्ष प्रकाश
मटेरियल एम्बिएंट कलर +
// बिखरा हुआ : " रंग " वस्तु ही
मटेरियल डिफ्यूज़ कलर * लाइट कलर * लाइट पावर * कॉसथीटा /
(दूरी*दूरी);

परिणाम

यहीं पर यह थोड़ा बेहतर हो जाता है। सर्वोत्तम परिणाम प्राप्त करने के लिए आप गुणांकों (0.1, 0.1, 0.1) के साथ खेल सकते हैं।



परावर्तित प्रकाश

प्रकाश का जो भाग परावर्तित होता है वह मुख्यतः सतह की ओर परावर्तित किरण की ओर परावर्तित होता है।



जैसा कि हम चित्र में देख सकते हैं, परावर्तित प्रकाश एक प्रकाश बिंदु बनाता है। कुछ मामलों में, जब फैला हुआ घटक शून्य होता है, तो यह प्रकाश स्थान बहुत संकीर्ण होता है (सारा प्रकाश पूरी तरह से एक दिशा में परावर्तित होता है) और हमें एक दर्पण मिलता है।

(हालांकि, आप दर्पण प्राप्त करने के लिए मापदंडों को बदल सकते हैं, हमारे मामले में यह केवल हमारे प्रकाश स्रोत के प्रतिबिंब को ध्यान में रखेगा। इसलिए यह एक अजीब दर्पण बन जाएगा)


// टकटकी वेक्टर (कैमरे की ओर)
vec3 E = सामान्यीकरण(आईडायरेक्शन_कैमरास्पेस);
//दिशा जिसमें त्रिभुज प्रकाश को प्रतिबिंबित करता है
वी.ई.सी 3 आर = प्रतिबिंबित होना (- एल , एन );
// दृश्य वेक्टर और परावर्तन वेक्टर के बीच के कोण की कोज्या को काट दिया गया यदि आवश्यक हो तो शून्य
// - सीधे प्रतिबिंब को देखें -> 1
// - हम कहीं दूसरी दिशा में देखते हैं -\u003e< 1
फ्लोट कॉसअल्फा = क्लैंप(डॉट(ई,आर), 0.1);
रंग=
// परिवेश प्रकाश: अप्रत्यक्ष प्रकाश का अनुकरण करें
सामग्रीपरिवेशरंग +
// बिखरा हुआ : " रंग " वस्तु ही
मटेरियल डिफ्यूज़ कलर * लाइट कलर * लाइट पावर * कॉसथीटा /
(दूरी*दूरी);
// प्रतिबिंबित: दर्पण की तरह प्रतिबिंबित प्रतिबिंब
मटेरियल स्पेक्युलर कलर * लाइट कलर * लाइट पावर * पाउ(कॉसअल्फा,5) /

अगले पाठ में, हम विश्लेषण करेंगे कि हम अपने वीबीओ के प्रतिपादन को कैसे तेज़ कर सकते हैं।