2016-02-28 4 views
6

मेरे पास एक प्रश्न है कि कैसे (सही ढंग से) glewInit() का उपयोग करें।प्रत्येक प्रतिपादन संदर्भ के लिए एक बार glewInit कॉल करें? या पूरी ऐप के लिए बिल्कुल एक बार?

मान लें कि मेरे पास एक बहु-विंडो एप्लिकेशन है, क्या मुझे glewInit() को एप्लिकेशन (यानी वैश्विक) स्तर पर बिल्कुल एक बार कॉल करना चाहिए? या प्रत्येक विंडो के लिए glewInit() पर कॉल करें (यानी, प्रत्येक OpenGL प्रतिपादन संदर्भ)?

उत्तर

6

पर Glew निर्विवाद विधि का इस्तेमाल किया जा रहा है का निर्माण निर्भर करता है glewInit हर संदर्भ परिवर्तन के बाद कॉल करने के लिए है!

एक्स 11/जीएलएक्स फ़ंक्शन पॉइंटर्स के साथ वेरिएंट हैं।

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

: प्रत्येक विंडो के लिए

(संपादित स्पष्टीकरण के लिए अनुरोध के कारण), (यानी, प्रत्येक ओपन प्रतिपादन संदर्भ)?

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

तो यह वैध है:

HWND wnd = create_a window() 
HDC dc = GetDC(wnd) 
PIXELFORMATDESCRIPTOR pf = select_pixelformat(); 
SetPixelFormat(dc, pf); 

HGLRC rc0 = create_opengl_context(dc); 
HGLRC rc1 = create_opengl_context(dc); 

wglMakeCurrent(dc, rc0); 
draw_stuff(); // uses rc0 

wglMakeCurrent(dc, rc1); 
draw_stuff(); // uses rc1 

और इसलिए इस

HWND wnd0 = create_a window() 
HDC dc0 = GetDC(wnd) 
HWND wnd1 = create_a window() 
HDC dc1 = GetDC(wnd) 

PIXELFORMATDESCRIPTOR pf = select_pixelformat(); 
SetPixelFormat(dc0, pf); 
SetPixelFormat(dc1, pf); 

HGLRC rc = create_opengl_context(dc0); // works also with dc1 

wglMakeCurrent(dc0, rc); 
draw_stuff(); 
wglMakeCurrent(dc1, rc); 
draw_stuff(); 

है यहाँ जहां एक्सटेंशन चित्र दर्ज करें। glActiveTexture जैसे फ़ंक्शन ओपनजीएल विनिर्देश का हिस्सा नहीं है जिसे विंडोज़ एप्लिकेशन बाइनरी इंटरफेस (एबीआई) में पिन किया गया है। इसलिए आपको रनटाइम पर फ़ंक्शन पॉइंटर प्राप्त करना होगा। यही वह है जो GLEW करता है। आंतरिक रूप से ऐसा लगता है:

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

typedef void (*PFNGLACTIVETEXTURE)(GLenum); 
extern PFNGLACTIVETEXTURE glew_ActiveTexture; 
#define glActiveTexture glew_ActiveTexture; 

glewInit में समारोह सूचक चर का उपयोग कर wglGetProcAddress (पठनीयता के कारण मैं प्रकार कास्टिंग छोड़ देते हैं) प्राप्त मूल्यों की तैयारी में हैं।

int glewInit(void) 
{ 
    /* ... */ 

    if(openglsupport >= gl1_2) { 
    /* ... */ 
     glew_ActiveTexture = wglGetProcAddress("glActiveTexture"); 
    /* ... */ 
    } 

    /* ... */ 
} 

अब महत्वपूर्ण हिस्सा: ओपन प्रतिपादन संदर्भ कि बुला के समय में वर्तमान है साथ wglGetProcAddress काम करता है। तो जो कुछ भी पहले wglMakeCurrent कॉल से पहले किया गया था। जैसा कि पहले ही समझाया गया है, एक्सटेंशन फ़ंक्शन पॉइंटर्स उनके ओपनजीएल संदर्भ से बंधे हैं और विभिन्न ओपनजीएल संदर्भ एक ही फ़ंक्शन के लिए अलग-अलग फ़ंक्शन पॉइंटर्स दे सकते हैं।

तो अगर आप ऐसा करते हैं

wglMakeCurrent(…, rc0); 
glewInit(); 
wglMakeCurrent(…, rc1); 
glActiveTexture(…); 

यह विफल हो सकता है। तो सामान्य रूप से, जीएलईडब्लू के साथ, wglMakeCurrent पर प्रत्येक कॉल को तुरंत glewInit द्वारा पालन किया जाना चाहिए। जीएलईडब्ल्यू के कुछ निर्माण बहु संदर्भ जागरूक हैं और आंतरिक रूप से ऐसा करते हैं। अन्य नहीं हैं। हालांकि यह glewInit को कई बार कॉल करने के लिए पूरी तरह से सुरक्षित है, इसलिए सुरक्षित होने का सुरक्षित तरीका यह सुनिश्चित करने के लिए है।

+0

लेकिन मैं अभी भी पूरी तरह से समझ नहीं पा रहा हूं। क्या आप संदर्भ "परिवर्तन" पर थोड़ी अधिक व्याख्या कर सकते हैं? –

+0

@ChanggongZhang: मेरा अपडेट देखें। – datenwolf

+0

मैंने अभी देखा है कि glew भी [glew32mx.lib, glew32mx.dll] प्रदान करता है। क्या इसका मतलब यह है कि यदि मैं एक बहु-खिड़की ऐप बनाना चाहता हूं, तो मुझे glew32.dll के बजाय glew32mx.dll का उपयोग करना चाहिए? और एक और अनुवर्ती प्रश्न। क्या आप @datenwolf बहु-डीसी-सिंगल-आरसी और एकल-डीसी-एकाधिक-आरसी के लिए वास्तविक एप्लिकेशन examplex प्रदान कर सकते हैं? –

संबंधित मुद्दे