आधुनिक OpenGL के साथ कई व्यूपोर्ट?


9

मैं SDL2 का उपयोग करता हूं

वर्तमान में मेरे एकमात्र shader में MVP मैट्रिक्स है , और इसके साथ बिंदुओं को बदल देता है।

मैं GLM वाले कैमरे के लिए अपने दृश्य और प्रोजेक्शन मैट्रिक्स की गणना करता हूं:

glm::lookAt(pos, pos + forward, up);
glm::perspective(fov, aspectRatio, zNear, zFar);

मैंने इसे खोजा, लेकिन मैं केवल कई दर्शकों के विरासत कार्यान्वयन को पा सकता हूं।

अगर मैं उदाहरण के लिए 4 कैमरे बनाता हूं और यह कहता हूं कि वे सभी समान हैं , तो हर कैमरे को रेंडर करने के लिए स्क्रीन की एक अलग तिमाही है । (इसलिए मैं एक ही सामग्री के साथ 4 व्यूपोर्ट चाहता हूं)

मैं यह कैसे कर सकता हूँ? क्षमा करें यदि मैंने पर्याप्त सूचना नहीं दी है, तो बेझिझक पूछें।


क्या आप विशेष रूप से 4 बार रेंडरिंग करने के लिए देख रहे हैं, या सिर्फ एक बार रेंडर करने और 4 अलग-अलग जगहों पर परिणाम प्रदर्शित करने के लिए?
ट्राइकोप्लाक्स

रेंडरिंग 4 बार करें। मैंने जो लिखा वह सिर्फ एक सरलीकृत उदाहरण है, उदाहरण के लिए मैं चाहता हूं कि मुख्य कैमरा एक कार को पूरी खिड़की पर रेंडर करे, और दूसरा कैमरा कार्नर में एक छोटे से वर्ग में साइड से कार को प्रस्तुत करे।
तुदवारी ११'१

अगर मुझे यह सही ढंग से समझ में आया है तो आपको अपनी खिड़की को 4 भागों के लिए विभाजित करने की आवश्यकता है और प्रत्येक भाग में उस तरह के दृश्य के अन्य भागों को प्रस्तुत करना है ?
नागरटेक्स

हाँ, लेकिन सख्ती से 4 भागों नहीं। मैं चाहता हूं कि यह लचीला हो। लचीले आकार और व्यूपोर्ट आयत की स्थिति।
तुदवारी ११'१ at बजे १ud:३

जवाबों:


8

एक ही स्क्रीन के अलग-अलग व्यूपोर्ट (भागों) तक पहुँचना निम्न प्रकार से किया जा सकता है:

उदाहरण के लिए स्क्रीन को चार भागों में विभाजित करना और एक ही दृश्य को हर कोने में चार बार अलग-अलग वर्दी और अलग-अलग व्यूपोर्ट के साथ प्रस्तुत करना:

bindFramebuffer();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
scene->setConstPerFrameUniforms();

//left bottom
glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(1);
scene->draw();

//right bottom
glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(2);
scene->draw();

//left top
glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(3);
scene->draw();

//right top
glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->setVarPerFrameUniforms(4);
scene->draw();

glViewport(0, 0, WindowWidth, WindowHeight); //restore default

तो glViewPort () के साथ मैं परिभाषित कर सकता हूं कि मैं आगे कहां आकर्षित करना चाहता हूं, और glBlendFunc के साथ मैं परिभाषित कर सकता हूं कि जीपीयू को एक दूसरे के साथ अतिव्यापी क्षेत्रों (फ्रेमबफर्स) को कैसे मिश्रण करना चाहिए। क्या मैं सही हूँ?
तुदवारी १५'१

1
हाँ, आप पैरामीट्रिज़ के लिए स्वतंत्र हैं। पैरामीटर के रूप viewportमें x हैं, chunk के बाएँ निचले कोने और y, chunk की ऊँचाई। सम्मिश्रण के साथ आप प्रयोग कर सकते हैं।
narthex

1
सम्मिश्रण क्यों? यह सवाल से कैसे संबंधित है?
रक्सवन

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

2
सम्मिश्रण का इससे कोई लेना-देना नहीं है और उत्तर को अधिक भ्रमित करता है। व्यूपोर्ट की स्थापना के लिए सभी की जरूरत है
डिफ़ॉल्ट

11

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

OpenGL 4.1 के बाद से विधि glViewportArrayv मौजूद है। यह व्यूपोर्ट की एक सरणी को परिभाषित कर सकता है। इस विधि द्वारा बनाए गए व्यूपोर्ट में एक इंडेक्स असाइन किया गया है।

इस इंडेक्स का उपयोग व्यूपोर्ट को उस दृश्य को सेट करने के लिए वर्टेक्स शेडर में किया जा सकता है। (आपको shader कोड में " ARB_shader_viewport_layer_array " एक्सटेंशन शामिल करना होगा )

आपके मामले में मैं निम्नलिखित करने का सुझाव दूंगा:

  • वेदरटेक्स वाइल्डर में रखने के लिए एक शैडर स्टोरेज बफर (मैट 4 का एरे) में 4 कैमरा मैट्रीस स्टोर करें
  • अनुक्रमित ड्राइंग का उपयोग करें , उदाहरण के लिए: glDrawElementsInstanced
  • कैमरा मैट्रिक्स सरणी का उपयोग करने के लिए वर्टेक्स शेडर के gl_InstanceID में बिल्ड का उपयोग करें
  • वैरिएंट में वैरिएबल आउटपुट वैरिएबल gl_ViewportIndex का निर्माण gl_InstanceID में सेट करें। (विवरण के लिए ARB_fragment_layer_viewport देखें )

" इस इंडेक्स का उपयोग व्यूपोर्ट को उस दृश्य को सेट करने के लिए वर्टेक्स शेडर में किया जा सकता है जिसमें दृश्य प्रस्तुत किया गया है। " नहीं, यह नहीं हो सकता। खैर, ARB_shader_viewport_layer_array एक्सटेंशन, या AMD समकक्षों के बिना नहीं। उन में से कोई भी जीएल 4.5 में मानक नहीं है। आप शायद ज्योमेट्री शेड्स के बारे में सोच रहे हैं।
निकोल बोलस

@ नाइकोल, इस संकेत के लिए धन्यवाद! मैं उल्लेख करना भूल गया, कि आपको विस्तार को शामिल करना है। मैं अपने उत्तर को संपादित करूंगा।
क्रिश्चियन_बनाते

5

यह @ narthex के उत्तर की एक प्रति है, केवल व्यूपोर्ट को छोड़कर, क्योंकि आपको इसकी आवश्यकता है। मुझे यकीन नहीं है कि फ्रेम बफर / ब्लेंड सामान उसके उत्तर में शामिल क्यों है।

//left bottom
glViewport(0, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

//right bottom
glViewport(WindowWidth*0.5, 0, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

//left top
glViewport(0, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

//right top
glViewport(WindowWidth*0.5, WindowHeight*0.5, WindowWidth*0.5, WindowHeight*0.5);
scene->draw();

glViewport(0, 0, WindowWidth, WindowHeight); //restore default

1

ये सभी अच्छे उत्तर हैं, और फिर भी एक और तरीका है: (क्या हमेशा नहीं है?)

आभासी वास्तविकता की बढ़ती लोकप्रियता के कारण, OculusVR के लोगों ने "मल्टीव्यू" एक्सटेंशन की तिकड़ी विकसित की है, जिसे कहा जाता है:

  1. OVR_multiview ,
  2. OVR_multiview2 , और
  3. OVR_multiview_multisampled_render_to_texture

ये एक्सटेंशन एक ही दृश्य के कई दृश्यों को एक ड्रॉ कॉल में प्रस्तुत करने की अनुमति देते हैं, प्रत्येक दृश्य के दृष्टिकोण से एक ही दृश्य में एक ही दृश्य को प्रस्तुत करने की अतिरेक को समाप्त करते हैं। हालांकि वीआर के उद्देश्य के लिए बनाया गया है, डेवलपर केवल दो विचारों तक सीमित नहीं है। बल्कि, यह एक्सटेंशन MAX_VIEWS_OVR के रूप में कई दृश्यों के लिए अनुमति देता है ।

इन एक्सटेंशन का उपयोग करने से पहले, डेवलपर को निम्नलिखित कोड जोड़कर उपयोगकर्ता के ग्राफिक्स ड्राइवर में उनके समर्थन की जांच करनी चाहिए:

const GLubyte* extensions = GL_CHECK( glGetString( GL_EXTENSIONS ) );
char * found_extension = strstr( (const char*)extensions, "GL_OVR_multiview" );
if (NULL == found_extension)
{
     exit( EXIT_FAILURE );
}

वहां से, इस सुविधा का उपयोग करने के लिए अपने फ्रेमबफ़र को स्थापित करने की बात है:

glFramebufferTextureMultisampledMultiviewOVR = PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEDMULTIVIEWOVR(eglGetProcAddress("glFramebufferTextureMultisampleMultiviewOVR"));
glFramebufferTextureMultisampledMultiviewOVR (GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0, 0, 2);

और इसी तरह shader में:

#version 300 es
#extension GL_OVR_multiview : enable

layout(num_views = 2) in;
in vec3 vertexPosition;
uniform mat4 MVP[2];

void main(){
    gl_Position = MVP[gl_ViewID_OVR] * vec4(vertexPosition, 1.0f);
}

सीपीयू-बाउंड एप्लिकेशन में, यह विस्तार नाटकीय रूप से प्रतिपादन समय को कम कर सकता है , विशेष रूप से अधिक जटिल दृश्यों के साथ :

मल्टीव्यू और नियमित स्टीरियो के बीच सापेक्ष CPU समय।  X- अक्ष पर क्यूब्स की संख्या और y- अक्ष पर सापेक्ष समय के साथ बेहतर छोटा है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.