java - ओपनजीएल(जोजीएल) का उपयोग कर अच्छा 3 डी विस्फोट और कण प्रभाव?



opengl 3d (1)

मैं इसे कुछ समय के लिए लिखना चाहता हूं ... विश्वविद्यालय के लिए एक परियोजना के रूप में, मैंने लिखा है (एक मित्र के साथ) एक खेल है जिसमें अच्छे विस्फोट और कण प्रभाव की आवश्यकता होती है। हमने कुछ समस्याओं का सामना किया है, जो हमने काफी सुन्दरता से हल किया (मुझे लगता है), और मैं ज्ञान को साझा करना चाहता हूं।

ठीक है, तो हमने यह ट्यूटोरियल पाया: एक कण विस्फोट प्रभाव बनाओ जो जावा के साथ JOGL का उपयोग करने के लिए काफी आसान था। इससे पहले कि मैं इस ट्यूटोरियल को हम वास्तव में कैसे कार्यान्वित करता हूँ, इस बारे में उत्तर दूंगा, मैं बताता हूं कि रेंडरिंग कैसे किया जाता है:

कैमरा : सिर्फ एक सामान्य आधार है, जिसका मूल रूप से 3 सामान्यीकृत ऑर्थोगोनल वैक्टर होते हैं, और 4 वें वेक्टर जो कैमरे की स्थिति का प्रतिनिधित्व करते हैं। rendering gluLookAt का उपयोग किया जाता है:

glu.gluLookAt(cam.getPosition().getX(), cam.getPosition().getY(), cam.getPosition().getZ(), 
              cam.getZ_Vector().getX(), cam.getZ_Vector().getY(), cam.getZ_Vector().getZ(), 
              cam.getY_Vector().getX(), cam.getY_Vector().getY(), cam.getY_Vector().getZ());

जैसे कि कैमरे का z वेक्टर वास्तव में लक्ष्य है, y वेक्टर "अप" वेक्टर है, और स्थिति ठीक है ... स्थिति।

इसलिए (यदि इसे किसी प्रश्न शैली में डाल दिया जाए), तो अच्छा कण प्रभाव कैसे लागू किया जाए?

पीएस: सभी कोड नमूने और इन-गेम स्क्रीनशॉट (दोनों जवाब और प्रश्न में) खेल से ली गई हैं, जो यहां होस्ट की गई हैं: एस्ट्रॉयड शूटर


ठीक है, हम देखते हैं कि हम कणों के क्रियान्वयन से पहले किस तरह दृष्टिकोण करते हैं: हमारे पास एक सार वर्ग Sprite जो एक कण का प्रतिनिधित्व करते थे:

protected void draw(GLAutoDrawable gLDrawable) {
    // each sprite has a different blending function.
    changeBlendingFunc(gLDrawable);

    // getting the quad as an array of length 4, containing vectors
    Vector[] bb = getQuadBillboard();
    GL gl = gLDrawable.getGL();

    // getting the texture
    getTexture().bind();

    // getting the colors
    float[] rgba = getRGBA();
    gl.glColor4f(rgba[0],rgba[1],rgba[2],rgba[3]);

    //draw the sprite on the computed quad
    gl.glBegin(GL.GL_QUADS);
    gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3d(bb[0].x, bb[0].y, bb[0].z);
    gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3d(bb[1].x, bb[1].y, bb[1].z);
    gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3d(bb[2].x, bb[2].y, bb[2].z);
    gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3d(bb[3].x, bb[3].y, bb[3].z);
    gl.glEnd();
}

हमारे पास अधिकांश विधि कॉल बहुत ज्यादा समझदार हैं, कोई आश्चर्य नहीं है रेंडरिंग काफी सरल है display पद्धति पर, हम पहले सभी अपारदर्शी वस्तुओं को आकर्षित करते हैं, फिर, हम सभी Sprite लेते हैं और उन्हें सॉर्ट करते हैं ( कैमरे से स्क्वायर दूरी ), फिर कणों को खीचें, जैसे कि कैमरे से अधिक दूर पहले खींचा जाता है लेकिन असली बात यह है कि हमें इसमें गहराई से देखना होगा विधि getQuadBillboard हम यह समझ सकते हैं कि प्रत्येक कण को ​​विमान पर "बैठना" है जो कैमरे की स्थिति के लिए सीधा है, यहां की तरह: जिस तरह से एक सीधा विमान की गणना करने का तरीका मुश्किल नहीं है:

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

  2. हवाई जहाज़ पर कैमरे के Y वेक्टर के प्रक्षेपण को सामान्य करने के द्वारा, ट्रैक्टर की "ऊंचाई" की गणना करें आप प्रक्षेपित वेक्टर को कम्प्यूटिंग द्वारा प्राप्त कर सकते हैं: H = cam.Y - normal * (cam.Y dot normal)

  3. क्वाड की "चौड़ाई" बनाओ, कंप्यूटिंग द्वारा W = H cross normal

  4. 4 अंक / वैक्टर वापस करें: {position+H+W,position+HW,position-HW,position-H+W}

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

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

आप इन सभी वाकई शांत 3 डी स्ट्रीट कला को जानते हैं? यहां एक ऐसी छवि है जो इस विचार पर जोर देती है:

हमने सोचा कि यह विचार हमारे खेल में लागू किया जा सकता है, इसलिए स्प्रीट एक-दूसरे को एक दूसरे को एक दूसरे से अलग नहीं करेंगे इस विचार को स्पष्ट करने के लिए यहां एक छवि है:

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

जब 4 वैक्टर एक क्वाड बिलबोर्ड का प्रतिनिधित्व करते हैं, और कण की स्थिति में, हमें मूल ट्रैड बिलबोर्ड का प्रतिनिधित्व करने वाले 4 वैक्टर के एक नए सेट को आउटपुट करना होगा। यह कैसे करना है यह विचार, यहां महान बताया गया है: एक विमान और एक रेखा के चौराहे हमारे पास "रेखा" है जो कैमरे की स्थिति से परिभाषित है, और 4 वैक्टर में से प्रत्येक हमारे पास विमान है, क्योंकि हम अपने कैमरे Z वेक्टर को सामान्य के रूप में इस्तेमाल कर सकते हैं, और कण की स्थिति भी, एक छोटा बदलाव sprites सॉर्ट करने के लिए तुलना समारोह में होगा। यह अब सजातीय मैट्रिक्स का उपयोग करना चाहिए, जिसे हमारे कैमरे के आधार पर परिभाषित किया गया है, और वास्तव में, अभिकलन कंप्यूटिंग के रूप में आसान है: cam.getZ_Vector().getX()*pos.getX() + cam.getZ_Vector().getY()*pos.getY() + cam.getZ_Vector().getZ()*pos.getZ(); । एक और बात हमें नोटिस करनी चाहिए, यह है कि अगर कण कैमरे के देखने वाले कोण से बाहर हो, यानी कैमरे के पीछे, हम इसे देखना नहीं चाहते हैं, और विशेषकर, हम इसे प्रक्षेपण की गणना नहीं कर सकते कुछ बहुत अजीब और साइकेडेलिक प्रभाव में परिणाम ...) और सभी को छोड़ दिया गया है अंतिम Sprite श्रेणी दिखाने के लिए

परिणाम बहुत अच्छा है:

उम्मीद है कि यह मदद करता है, इस "लेख" (या खेल पर:}, जो आप का पता लगाने, कांटा, और आप चाहते हैं हालांकि उपयोग कर सकते हैं पर अपनी टिप्पणी प्राप्त करना चाहेंगे ...)