मैं वेबजीएल के लिए बहुत नया हूं, लेकिन जावास्क्रिप्ट या कैनवास नहीं। अनिवार्य रूप से, मुझे किसी भी समन्वय पर कैनवास पर पिक्सेल के रंग को बदलने में सक्षम होने के लिए एक बहुत तेज़ तरीका चाहिए। मुझे लगता है कि यह वेबजीएल खंड शेडर्स का उपयोग करके किया जा सकता है। क्या यह संभव है, और क्या कोई बेहतर तरीका है? मैं ऐसा कैसे कर पाऊंगा?मैं WebGL का उपयोग कर कैनवास पर पिक्सेल का रंग कैसे सेट कर सकता हूं?
उत्तर
यह प्रतिपादन के लिए एक संपूर्ण गाइड नहीं है क्योंकि इसमें शेडर प्रबंधन के बारे में बिट्स शामिल नहीं हैं; इसके बजाए यह ध्यान केंद्रित करता है कि वेबजीएल प्राइमेटिव्स का चित्र वास्तव में कैसे किया जाता है, और स्क्रीन पर सटीक स्थिति को सटीक स्थिति के लिए ऑर्थोग्राफिक प्रक्षेपण का उपयोग कैसे किया जाता है।
WebGL करता वर्टेक्स बफर ऑब्जेक्ट (VBOs) के साथ अपने ड्राइंग के सभी है, तो:
अधिक जानकारी के लिए, मैं अत्यधिक इन स्रोतों की सिफारिश आपको अपने सभी डेटा को 3 डी शिखर में संकलित करने की आवश्यकता है और उन्हें जितनी संभव हो सके वीबीओ में वीडियो कार्ड पर भेजना होगा (perfo को अधिकतम करने के लिए rmance)।
एक VBO तो जैसे WebGL में बनाया जा सकता है:
var vbo = gl.createBuffer();
तो फिर तुम, बफर करने के लिए नीचे डेटा भेजने के लिए आम तौर पर एक Float32Array
के रूप में की जरूरत है। यदि आपके पास पहले से ही एक नियमित जावास्क्रिप्ट सरणी के रूप में आपका डेटा है, तो jsArray
की सामग्री से Float32Array
प्रारंभ करने के लिए आप new Float32Array(jsArray)
का उपयोग कर सकते हैं। यद्यपि यह शायद ही कभी करने की कोशिश करो। टाइप किए गए सरणी बहुत तेज़ होते हैं, लेकिन बहुत धीरे-धीरे शुरू होते हैं। उन्हें एक बार बनाना और जब भी संभव हो उनका पुन: उपयोग करना सबसे अच्छा है।
बार जब आप एक Float32Array
है, तो आप तो जैसे बफर करने के लिए नीचे डेटा पास कर सकते हैं:
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, float32Data, gl.DYNAMIC_DRAW);
आप एक bufferData
या bufferSubData
कॉल हर बार प्रदर्शन करने के लिए डाटा परिवर्तन की आवश्यकता होगी।
इस समय डेटा ग्राफिक्स कार्ड पर है करके, ताकि आप केवल वास्तव में आकर्षित करने के लिए जरूरत है यह:
// bind the VBO to be drawn if you haven't already
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
// send the vertex data to the shader program
gl.vertexAttribPointer(vertexAttributeLocation, 3, gl.FLOAT, false, 0, 0);
// draw the buffer
gl.drawArrays(gl.POINTS, 0, float32Data.length/3);
ध्यान दें कि हालांकि ग्राफिक्स कार्ड काफी कुछ VBOs पकड़ कर सकते हैं, आप के रूप में इस्तेमाल करना चाहिए उनमें से कुछ संभव है, क्योंकि drawArrays
कॉल करने के लिए आपको कॉल करना है, धीमी चीजें मिल रही हैं। दरअसल, यदि आप किसी दिए गए वीबीओ में एक समय में केवल एक पिक्सेल प्रस्तुत करते हैं, तो यह चलाने में बहुत धीमी गति होगी।
Float32Array
की लंबाई 3 से विभाजित है क्योंकि प्रत्येक एकल डेटा तत्व एक 3 डी (एक्स, वाई, जेड) समन्वय है, इसलिए प्रत्येक डेटा तत्व में 3 फ्लोट घटक होते हैं। ध्यान दें कि gl.drawArrays
पर पहला तर्क gl.POINTS
था। यह सरणी में प्रत्येक आइटम के लिए एक बिंदु (डिफ़ॉल्ट रूप से, आकार में एक पिक्सेल आकार) खींचने के लिए ग्राफिक्स कार्ड को निर्देशित करता है। आकर्षित करने के अन्य तरीके हैं, और यदि आपको को पिक्सेल के समूह को भरने की आवश्यकता है, तो अन्य ड्रॉ मोड (उदा। gl.TRIANGLES
) में से एक आपकी पसंद के लिए अधिक हो सकता है।
विशिष्ट पिक्सल को प्रकाश देने के लिए, यह शेडर लिखे जाने पर निर्भर करता है, लेकिन सबसे अधिक संभावना आप मॉडलव्यू मैट्रिक्स और प्रक्षेपण मैट्रिक्स का उपयोग कर रहे हैं। मॉडलव्यू मैट्रिक्स खींचे गए बिंदुओं के सापेक्ष कैमरे के अभिविन्यास का प्रतिनिधित्व करता है, और प्रक्षेपण मैट्रिक्स कैमरा आयामों का प्रतिनिधित्व करता है (चौड़ाई और ऊंचाई, दृश्य का क्षेत्र, निकटतम और सबसे दूर दृश्यमान श्रेणियां, आदि)। इसलिए यदि आप विशिष्ट पिक्सेल को प्रकाश देना चाहते हैं, तो आपकी सबसे अच्छी शर्त ऑर्थोग्राफिक प्रोजेक्शन मैट्रिक्स को लागू करने के लिए चौड़ाई और ऊंचाई कैनवास की चौड़ाई और ऊंचाई के बराबर है; और पहचान के लिए सेट एक मॉडलव्यू मैट्रिक्स (कोई परिवर्तन नहीं)। ऑर्थोग्राफिक प्रोजेक्शन में, ऑब्जेक्ट्स कम नहीं होते क्योंकि वे कैमरे से आगे निकलते हैं, इसलिए वे स्क्रीन के सापेक्ष सटीक स्थिति निर्दिष्ट करने के लिए बहुत उपयोगी होते हैं। साथ ही, यदि आप उन्हें उचित आयाम देते हैं, तो आप चाहें तो लंबवत स्थिति विशिष्ट पिक्सेल पर कर सकते हैं।
विभिन्न मैट्रिक्स पुस्तकालयों अलग अलग तरीकों से काम करते हैं, लेकिन उदाहरण के लिए, gl-matrix में एक ओर्थोग्रफिक मैट्रिक्स स्थापित करने के लिए, तो आप इस तरह ऐसा कर सकते हैं:
var ortho = mat4.ortho(left, right, bottom, top, near, far);
सटीक संख्या आपकी पसंद पर निर्भर करती है; यदि आप मूल देना चाहते हैं (0, 0) कैनवास के निचले बाएं पर, आप तो इस तरह करते हैं: प्रत्येक बिंदु के Z मूल्य अभी भी झूठ है
var ortho = mat4.ortho(0, canvas.width, 0, canvas.height, 0.01, 200);
ध्यान दें कि near
और far
के बीच प्रस्तुत करने के लिए, और near
मान 0
पर सेट नहीं किया जा सकता है।
मुझे बताएं कि इनमें से किसी को स्पष्टीकरण की आवश्यकता है या नहीं।
यदि आप केवल एकल पिक्सल खींचना चाहते हैं तो आप शायद कैनवास 2 डी का उपयोग करके बेहतर हो सकते हैं।
अन्यथा आप शायद इस ट्यूटोरियल से इसे समझ सकते हैं जो पिक्सेल इकाइयों में आयतों को खींचता है ताकि चौड़ाई और ऊंचाई को 1x1 पर सेट किया जा सके और आपको सिंगल पिक्सेल मिले।
आप GL_POINTS इस्तेमाल कर सकते हैं जब ड्राइंग। मूल रूप से आप रंगों और पदों के साथ, GPU को बिंदुओं की एक सरणी पारित करेंगे। फिर आप सही डेटा के साथ drawArrays कहते हैं।
यह भी अन्य चीजों से बंधा हो सकता है, लेकिन यह आपकी मदद कर सकता है:
https://github.com/funkaster/ChesterGL/blob/master/chesterGL/primitivesBlock.js#L126
https://github.com/funkaster/ChesterGL/blob/master/chesterGL/primitivesBlock.js#L260
है कि कैसे मैं chesterGL के लिए आदिम ब्लॉक में कई अंक प्रस्तुत करना।
बस एक सिंगल पिक्सेल? या बहुत सारे पिक्सल? एक पिक्सल के लिए केवल कॉल ओवरसहेड कैनवास 2 डी का उपयोग करने से भी बदतर हो सकता है। –
बहुत सारे पिक्सल। यह imageData के साथ काम करने योग्य है, लेकिन 400x400 पिक्सेल के लिए बहुत धीमी है। – nondefault
आपको पिक्सेल डेटा कहां से मिलता है? यदि आप एक बैच में शेडर में मूल्यों की गणना कर सकते हैं, तो वेबजीएल तेज होगा। यदि आप किसी सरणी से डेटा प्राप्त करते हैं, तो WebGL छवि डेटा से अधिक तेज़ नहीं हो सकता है। –