2016-07-09 8 views
5

मैं खेल Antichamber की तरह कुछ को लागू करने की कोशिश कर रहा है पिछले सप्ताह के (अधिक precisly इस चाल नीचे दिखाया गया है) जो मैं उम्मीद कर रहा हूं उसका वीडियो (भले ही यह अवास्तविक इंजन 4 के साथ किया गया हो; मैं इसका उपयोग नहीं कर रहा हूं): https://www.youtube.com/watch?v=Of3JcoWrMZsओपन कैसे लागू करने के लिए "पोर्टल प्रतिपादन"

मैंने ऐसा करने का सबसे अच्छा तरीका देखा और मुझे स्टैंसिल के बारे में पता चला बफर। this लेख और this कोड ("drawPortals()" फ़ंक्शन) के बीच में मैंने ऑनलाइन पाया कि मैं इसे लगभग कार्यान्वित करने में कामयाब रहा।

यह एक पोर्टल के साथ एक और कमरे में अच्छी तरह से काम करता है (एक क्रॉस करने योग्य पोर्टल नहीं, जिसका अर्थ है कि आप इसके माध्यम से नहीं चल सकते हैं और दूसरे कमरे में टेलीपोर्ट किया जा सकता है)। मेरे उदाहरण में मैं एक साधारण वर्ग वाले कमरे में एक क्षेत्र के साथ एक पोर्टल खींच रहा हूं; पोर्टल के पीछे एक और क्षेत्र है, कि मैं चाहे गहराई बफर सही ढंग से काम कर रहा था और पोर्टल के पीछे यह ड्राइंग जाँच करने के लिए प्रयोग किया है: जब मैं एक और पोर्टल जोड़ने

front

side

समस्याओं

उठता है कि इस के पास है उस मामले में मैं अन्य पोर्टल सही ढंग से प्रदर्शित करने के लिए प्रबंधन (प्रकाश बंद है, लेकिन सही पर क्षेत्र है कि यह एक और क्षेत्र है दिखाने के लिए एक अलग रंग का है):

enter image description here

लेकिन अगर मैं बारी कैमरा इतना है कि पहले पोर्टल दूसरा एक से अधिक तैयार हो गया है, तो पहले एक की गहराई गलत हो जाता है, और दूसरा पोर्टल इस तरह पहले से अधिक तैयार हो जाता है,:

enter image description here

जबकि यह ऐसा कुछ होना चाहिए:

enter image description here

तो, यह समस्या है। मैं शायद गहराई बफर के साथ कुछ गलत कर रहा हूं, लेकिन मुझे क्या नहीं मिल रहा है।

प्रतिपादन भाग के लिए मेरे कोड काफी यह है:

glClear(GL_DEPTH_BUFFER_BIT); 
glEnable(GL_STENCIL_TEST); 

// First portal 
glPushMatrix(); 

// Disable writing to the color and depht buffer; disable depth testing 
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 
glDepthMask(GL_FALSE); 
glDisable(GL_DEPTH_TEST); 

// Make sure that the stencil always fails 
glStencilFunc(GL_NEVER, 1, 0xFF); 

// On fail, put 1 on the buffer 
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP); 

// Enable writing to the stencil buffer 
glStencilMask(0xFF); 

// Clean the buffer 
glClear(GL_STENCIL_BUFFER_BIT); 

// Finally draw the portal's frame, so that it will have only 1s in the stencil buffer; the frame is basically the square you can see in the pictures 
portalFrameObj1.Draw(); 

/* Now I compute the position of the camera so that it will be positioned at the portal's room; the computation is correct, so I'm skipping it */ 

// I'm going to render the portal's room from the new perspective, so I'm going to need the depth and color buffers again 
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 
glDepthMask(GL_TRUE); 
glEnable(GL_DEPTH_TEST); 
glClear(GL_DEPTH_BUFFER_BIT); 

// Disable writing to the stencil buffer and enable drawing only where the stencil values are 1s (so only on the portal frame previously rendered) 
glStencilMask(0x00); 
glStencilFunc(GL_EQUAL, 1, 0xFF); 

// Draw the room from this perspective 
portalRoomObj1.Draw(); 

glPopMatrix(); 


// Now the second portal; the procedure is the same, so I'm skipping the comments 
glPushMatrix(); 
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); 
glDepthMask(GL_FALSE); 
glDisable(GL_DEPTH_TEST); 

glStencilFunc(GL_NEVER, 1, 0xFF); 
glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP); 
glStencilMask(0xFF); 
glClear(GL_STENCIL_BUFFER_BIT); 

portalFrameObj2.Draw(); 

/* New camera perspective computation */ 

glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 
glDepthMask(GL_TRUE); 
glEnable(GL_DEPTH_TEST); 
glClear(GL_DEPTH_BUFFER_BIT); 

glStencilMask(0x00); 
glStencilFunc(GL_EQUAL, 1, 0xFF); 

portalRoomObj2.Draw(); 

glPopMatrix(); 


// Finally, I have to draw the portals' frames once again but this time on the depth buffer, so that they won't get drawn over; first off, disable the stencil buffer 
glDisable(GL_STENCIL_TEST); 

// Disable the color buffer 
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 

glClear(GL_DEPTH_BUFFER_BIT); 

// Draw portals' frames 
portalFrameObj1.Draw(); 
portalFrameObj2.Draw(); 

// Enable the color buffer again 
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 


/* Here I draw the rest of the scene */ 

अद्यतन

मैं पता लगाने के लिए कि समस्या क्या है में कामयाब रहे, लेकिन मैं अभी भी इसे हल करने में सक्षम नहीं हूँ। यह वास्तव में गहराई बफर से संबंधित नहीं है, लेकिन स्टैंसिल के लिए।

असल में, जिस तरह से मैं पहला पोर्टल खींच रहा हूं वह यह है: 1) स्टैंसिल बफर में 1 एस के साथ पोर्टल फ्रेम की बिट्स भरें; पोर्टल के बाहर केवल 0s 2) पोर्टल रूम बनाएं जहां स्टैंसिल के पास 1 है (ताकि यह फ्रेम के पोर्टल

पर खींचा जाए और मैं इसे दूसरे पोर्टल के लिए दोहरा दूं।तब मैं
enter image description here

:

पहले पोर्टल के लिए, मैं पर चरण 1 कुछ इस तरह तो (बेवकूफ चित्र क्षमा, मैं आलसी हूँ) मिलती है: enter image description here

फिर 2 चरण के बाद दूसरे पोर्टल के साथ शुरू:
enter image description here

लेकिन अब, चरण 1 और 2 के बीच, मैं स्टेंसिल बता केवल आकर्षित करने के लिए जहां बिट्स 1s कर रहे हैं; चूंकि बफर अब साफ़ हो गया है, इसलिए मैंने पहले पोर्टल के 1 एस का ट्रैक खो दिया है, इसलिए यदि दूसरे पोर्टल के फ्रेम का हिस्सा पिछले फ्रेम के पीछे है, तो दूसरे फ्रेम के 1 एस को अभी भी दूसरे पोर्टल के कमरे के साथ खींचा जाएगा, भले ही गहराई बफर एक तरह से इस छवि में पसंद: enter image description here

अगर मैं इसे सही समझाने में कामयाब मैं नहीं जानता ...

उत्तर

0

अब यह एक समय हो गया है। चूंकि वहां नहीं होने वाले हैं (शायद) मैं अब जिस कामकाज का उपयोग कर रहा हूं उसके बारे में लिख रहा हूं।

मैंने विभिन्न स्टैंसिल फ़ंक्शंस का उपयोग करके समस्या को हल करने की कोशिश की और जब मैं एक नया पोर्टल प्रस्तुत करता हूं तो स्टैंसिल बफर को खाली नहीं करता; विचार इस तथ्य का फायदा उठाना था कि मुझे स्टैंसिल बफर को देखकर पता था जहां पिछले पोर्टलों को प्रस्तुत किया जा रहा था।

अंत में, मैं इसे करने में सक्षम नहीं था; उदाहरणों में मैंने अपने मूल प्रश्न में पोस्ट किया है, 2 पोर्टलों में से एक हमेशा दूसरे के हिस्सों को अस्पष्ट करता है।

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

छद्म कोड में, मैं यह कर:

for(var i = 0; i < PORTALS_NUMBER; i++) 
{ 
    // I get the normal to the portal's frame and its position 
    var normal = mPortalFramesNormals[i]; 
    var framePos = mPortalFrames[i].GetPosition(); 

    // I compute the scalar product between the normal and the direction vector between the camera's position and the frame's position 
    var dotProduct = normal * (currentCameraPosition - framePos); 

    // If the dot product is 0 or positive, the portal is visible 
    if(dotProduct >= 0) 
    { 
     // I render the portal 
     DrawPortal(mPortalFrames[i], mPortalRooms[i]); 
    } 
} 

glDisable(GL_STENCIL_TEST); 

// Now I draw the portals' frames in the depth buffer, so they don't get overwritten by other objects in the scene 
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 
glDepthMask(GL_TRUE); 
glEnable(GL_DEPTH_TEST); 
glClear(GL_DEPTH_BUFFER_BIT); 

for(var i = 0; i < PORTALS_NUMBER; i++) 
{ 
    mPortalFrames[i].Draw(); 
} 

glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 

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

मुझे पता है कि केवल स्टैंसिल बफर का उपयोग करके ऐसा करने का एक और शानदार तरीका है, लेकिन अभी यह मेरे लिए काम करता है।

अगर कोई ऐसा करने का बेहतर तरीका जानता है, तो मुझे अभी भी जानने में रुचि है!

संपादित करें: मैं स्टेंसिल कार्यों के अन्य संस्करणों के बारे में पता चला गया है (जैसे कि, glStencilFuncSeparate, glStencilOpSeparate, glStencilMaskSeparate) कि पीठ और सामने चेहरों के साथ अलग अलग काम करने की अनुमति देते हैं। ऐसा लगता है कि मैंने जो समस्याओं का वर्णन किया है, उन्हें हल करने की आवश्यकता होगी, लेकिन मैं जल्द ही इसे आजमाने की कोशिश नहीं कर पाऊंगा। मैं बस उस व्यक्ति को इंगित कर रहा हूं जिसकी कोई समस्या है, यहां घूमती है।

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