نينتندو دي إس وحدة التحكم وميزات مثيرة للاهتمام


أود أن أخبركم عن تشغيل وحدة تحكم Nintendo DS GPU ، واختلافاتها عن وحدات معالجة الرسومات الحديثة ، وأيضًا عن رأيي في سبب عدم استخدام Vulkan بدلاً من OpenGL في المحاكيات لن يجلب أي مزايا.

لا أعرف حقًا Vulkan ، ولكن مما قرأته ، يتضح لي أن Vulkan يختلف عن OpenGL في أنه يعمل على مستوى أقل ، مما يسمح للمبرمجين بإدارة ذاكرة GPU وأشياء مماثلة. يمكن أن يكون هذا مفيدًا لمحاكاة وحدات تحكم أكثر حداثة تستخدم واجهات برمجة تطبيقات رسومية خاصة تقدم مستويات تحكم غير متوفرة في OpenGL.

على سبيل المثال ، جهاز عرض أجهزة blargSNES - أحد حيله هو أنه خلال بعض العمليات باستخدام المخازن المؤقتة للألوان المختلفة ، يتم استخدام مخزن مؤقت للعمق / الاستنسل. في OpenGL ، هذا غير ممكن.

بالإضافة إلى ذلك ، لا يزال هناك قدر أقل من القمامة بين التطبيق ووحدة معالجة الرسومات ، مما يعني أنه إذا تم تنفيذها بشكل صحيح ، فسيكون الأداء أعلى. في حين أن برامج تشغيل OpenGL مليئة بالتحسينات لحالات الاستخدام القياسية وحتى لألعاب معينة ، في Vulkan يجب كتابة التطبيق نفسه جيدًا أولاً.

أي أن "المسؤولية الكبرى تأتي بقوة كبيرة".

لست متخصصًا في واجهة برمجة التطبيقات ثلاثية الأبعاد ، لذا دعنا نعود إلى ذلك. ما أعرفه جيدًا: وحدة تحكم GPU DS.

تمت كتابة العديد من المقالات بالفعل حول أجزائه الفردية ( حول كواده المعقدة ، حول الهراء مع إطار العرض ، حول الميزات الممتعة للقطعة وحول التنفيذ المذهل لمكافحة التعرج ) ، ولكن في هذه المقالة سننظر في الجهاز ككل ، ولكن مع جميع التفاصيل المثيرة. على الأقل هذا كل ما نعرفه.

إن وحدة معالجة الرسوميات (GPU) نفسها عبارة عن جهاز قديم وعفا عليه الزمن. يقتصر على 2048 مضلع و / أو 6144 قمة لكل إطار. القرار 256x192. حتى لو تضاعفت أربع مرات ، لن يكون الأداء مشكلة. في ظل الظروف المثلى ، يمكن لـ DS إخراج ما يصل إلى 122880 مضلعًا في الثانية ، وهو أمر مثير للسخرية وفقًا لمعايير وحدات معالجة الرسومات الحديثة.

الآن دعنا ننتقل إلى تفاصيل GPU. على السطح ، يبدو قياسيًا جدًا ، ولكن في أعماق عمله يختلف تمامًا عن عمل وحدات معالجة الرسومات الحديثة ، مما يجعل محاكاة بعض الوظائف أكثر تعقيدًا.

تنقسم وحدة معالجة الرسومات إلى قسمين: محرك الهندسة ومحرك التقديم. يقوم المحرك الهندسي بمعالجة القمم الناتجة ، ويبني المضلعات ويحولها حتى تتمكن من تمريرها إلى محرك العرض ، والذي (تخمينه) يرسم كل شيء على الشاشة.

محرك الهندسة


ناقل هندسي قياسي جدا.

من الجدير بالذكر أن جميع العمليات الحسابية تتم بأعداد صحيحة للنقاط الثابتة ، لأن DS لا يدعم أرقام الفاصلة العائمة.

يتم محاكاة المحرك الهندسي برمجيًا تمامًا (GPU3D.cpp) ، أي أنه لا يطبق كثيرًا على ما نستخدمه لتقديم الرسومات ، لكنني سأخبرك بالمزيد عن ذلك على أي حال.

1. التحول والإنارة. يتم تحويل القمم الناتجة وإحداثيات النسيج باستخدام مجموعات من مصفوفات 4x4. بالإضافة إلى ألوان الذروة ، يتم تطبيق الإضاءة. كل شيء قياسي جدًا هنا ، الشيء الوحيد غير القياسي هو كيفية عمل إحداثيات النسيج (1.0 = واحد DS texel). ومن الجدير بالذكر أيضًا نظام مكدسات المصفوفة بالكامل ، والذي يتم تطبيقه إلى حد ما أو آخر على أجهزة glPushMatrix ().

2. تكوين المضلعات. يتم تجميع القمم المحولة إلى مضلعات ، والتي يمكن أن تكون مثلثات ، رباعي الزوايا (كواد) ، خطوط مثلثات أو خطوط الزوايا. تتم معالجة Quads بشكل أصلي ولا يتم تحويلها إلى مثلثات ، وهو ما يمثل مشكلة كبيرة لأن وحدات معالجة الرسومات الحديثة تدعم المثلثات فقط. ومع ذلك ، يبدو أن شخصًا ما توصل إلى حل يجب اختباره.

3. إسقاط. يمكن التخلص من المضلعات اعتمادًا على الاتجاه على الشاشة ووضع الذبح المحدد. أيضا مخطط قياسي جدا. ومع ذلك ، أحتاج إلى معرفة كيفية عمل ذلك مع الكواد.

4. اقتطاع. يتم حذف المضلعات التي تتجاوز نطاق الرؤية. يتم اقتطاع المضلعات التي تمتد جزئيًا خارج هذه المنطقة. لا تؤدي هذه الخطوة إلى إنشاء مضلعات جديدة ، ولكنها تضيف القمم إلى المضلعات الموجودة. في الواقع ، يمكن لكل من طائرات الاقتطاع الست أن تضيف قمة واحدة إلى المضلع ، ونتيجة لذلك ، يمكننا الحصول على ما يصل إلى 10 رؤوس. في القسم الخاص بمحرك التقديم ، سأخبرك كيف تعاملنا مع هذا.

5. تحويل إلى إطار العرض. يتم تحويل إحداثيات X / Y إلى إحداثيات الشاشة. يتم تحويل الإحداثيات Z لتلائم فاصل المخزن المؤقت لعمق 24 بت.

ما هو مثير للاهتمام هو كيفية معالجة إحداثيات W: يتم "تطبيعها" لتناسب فاصل زمني 16 بت. لهذا ، يتم أخذ كل إحداثي W للمضلع ، وإذا كان أكبر من 0xFFFF ، فإنه يتم إزاحته إلى اليمين من خلال 4 مواضع لتناسب 16 بت. وبالعكس ، إذا كانت الإحداثيات أقل من 0x1000 ، فإنها تتحرك إلى اليسار حتى تقع في الفاصل الزمني. أفترض أن هذا ضروري للحصول على فترات جيدة ، مما يعني دقة أكبر أثناء الاستيفاء.

6. الفرز. يتم فرز المضلعات بحيث يتم رسم المضلعات الشفافة أولاً. ثم يتم فرزها حسب إحداثيات Y (نعم) ، وهي ضرورية للمضلعات الشفافة والشفافية بشكل اختياري.

بالإضافة إلى ذلك ، هذا هو سبب تقييد 2048 مضلعًا: للفرز ، يجب تخزينها في مكان ما. يوجد مصرفان للذاكرة الداخلية مخصصان لتخزين المضلعات والقمم. حتى أن هناك سجل يبين عدد المضلعات والرؤوس المخزنة.

محرك التقديم


وهنا تبدأ المتعة!

بعد تكوين كل المضلعات وفرزها ، يبدأ محرك العرض في العمل.

أول شيء مضحك هو كيف يملأ المضلعات. هذا يختلف تمامًا عن عمل وحدات معالجة الرسومات الحديثة التي تقوم بتعبئة البلاط وتستخدم خوارزميات محسنة بالمثلث. لا أعرف كيف تعمل جميعها ، لكنني رأيت كيف يتم ذلك في وحدة معالجة رسومات وحدة تحكم 3DS ، وكل شيء يعتمد على البلاط هناك.

كن على هذا النحو ، على DS ، يتم العرض في سلاسل نقطية. كان على المطورين القيام بذلك حتى يمكن إجراء العرض بالتوازي مع محركات البلاط ثنائية الأبعاد المدرسة القديمة ، والتي تؤدي الرسم على الخطوط النقطية. يوجد مخزن مؤقت صغير يحتوي على 48 خطًا نقطيًا يمكن استخدامه لضبط بعض الخطوط النقطية.

أداة التنقيط عبارة عن أداة تقديم للمضلعات المحدبة بناءً على سلاسل البيانات النقطية. يمكنه التعامل مع عدد عشوائي من القمم. يمكن عرضه بشكل غير صحيح إذا مررت إليه مضلعات ليست محدبة أو لها حواف متقاطعة ، على سبيل المثال:


المضلع عبارة عن فراشة. كل شيء صحيح ورائع.

ولكن ماذا لو قلبناها؟


عذرًا.

ما هو الخطأ هنا؟ لنرسم الخطوط العريضة للمضلع الأصلي لنكتشف:


يمكن لجهاز العرض ملء فجوة واحدة فقط لكل خط نقطي. تحدد الحواف اليسرى واليمنى بدءاً من أعلى القمم ، وتتبع هذه الحواف حتى تواجه قمم جديدة.

في الصورة الموضحة أعلاه ، يبدأ من أعلى قمة ، أي أعلى اليسار ، ويستمر في التعبئة حتى يصل إلى نهاية الحافة اليسرى (قمة اليسار السفلى). لا يعرف أن الحواف تتقاطع.

عند هذه النقطة ، يبحث عن القمة التالية على حافته اليسرى. من المثير للاهتمام أن نلاحظ أنه يعلم أنه لا يحتاج إلى أخذ رؤوس أعلى من التيار الحالي ، ويعرف أيضًا أن الحواف اليسرى واليمنى قد تبادلت. لذلك ، تستمر في امتلاءها حتى نهاية المكب.

أود أن أضيف بعض الأمثلة الأخرى للمضلعات غير المحدبة ، لكننا سننحرف كثيرًا عن الموضوع.

دعونا نفهم بشكل أفضل كيف يعمل تظليل وتركيب Gouraud مع عدد عشوائي من القمم. هناك خوارزميات ثنائية المركز تستخدم لتقريب البيانات على طول مثلث ، ولكن ... في حالتنا ، فهي غير مناسبة.

يوجد أيضًا عارض DS هنا. بعض الصور الأكثر إثارة للاهتمام.


رؤوس المضلع هي النقاط 1 و 2 و 3 و 4. الأرقام لا تتوافق مع ترتيب الاجتياز الحقيقي ، لكنك تفهم المعنى.

في خط البيانات النقطية الحالي ، يقوم جهاز العرض بتعريف القمم المحيطة مباشرة بالحواف (كما ذكر أعلاه ، يبدأ من أعلى قمم ، ثم يمر عبر الحواف حتى يكتمل). في حالتنا ، هذه هي الذروات 1 و 2 للحافة اليسرى ، و 3 و 4 للحافة اليمنى.

تُستخدم منحدرات الحواف لتحديد حدود الفجوة ، أي النقطتين 5 و 6. عند هذه النقاط ، يتم استيفاء سمات القمم بناءً على المواضع الرأسية في الحواف (أو المواضع الأفقية للحواف ، والتي تكون المنحدرات بشكل رئيسي على طول المحور X).

بعد ذلك ، بالنسبة لكل بكسل في الفجوة (على سبيل المثال ، للنقطة 7) ، يتم استيفاء السمات القائمة على الموضع X داخل الفجوة من السمات المحسوبة مسبقًا عند النقطتين 5 و 6.

هنا ، جميع المعاملات المستخدمة تساوي 50٪ لتبسيط العمل ، لكن المعنى واضح.

لن أخوض في تفاصيل استيفاء السمات ، على الرغم من أنه سيكون من المثير للاهتمام أيضًا الكتابة عن هذا الموضوع. في الواقع ، هذا الاستيفاء صحيح من وجهة نظر المنظور ، ولكن له تبسيطات وميزات مثيرة للاهتمام.

الآن دعونا نتحدث عن كيفية ملء DS للمضلعات.

ما قواعد التعبئة التي يستخدمها؟ هناك أيضًا الكثير من الأشياء المثيرة للاهتمام هنا!

أولاً ، هناك قواعد تعبئة مختلفة للمضلعات غير الشفافة والشفافة. ولكن الأهم من ذلك ، يتم تطبيق هذه القواعد بكسل تلو الآخر . يمكن أن تحتوي المضلعات الشفافة على وحدات بكسل غير شفافة ، وسوف تتبع نفس القواعد مثل المضلعات غير الشفافة. يمكنك تخمين أنه لمحاكاة مثل هذه الحيل على وحدات معالجة الرسومات الحديثة ، يلزم وجود عدة تصاريح.

بالإضافة إلى ذلك ، يمكن أن تؤثر سمات المضلع المختلفة في العرض بطرق مختلفة ومثيرة للاهتمام. بالإضافة إلى المخازن المؤقتة للألوان والعمق القياسية إلى حد ما ، فإن جهاز العرض يحتوي أيضًا على مخزن مؤقت للسمة يتتبع جميع أنواع الأشياء المثيرة للاهتمام. وهي: معرف المضلع (بشكل منفصل للمضلعات الشفافة والشفافة) ، وشفافة البكسل ، والحاجة إلى تطبيق الضباب ، وما إذا كان هذا المضلع موجهًا إلى الكاميرا أو منها (نعم ، هذا أيضًا) ، وما إذا كانت البكسل على حافة المضلع. وربما شيء آخر.

إن مهمة محاكاة مثل هذا النظام لن تكون تافهة. تحتوي وحدة معالجة الرسومات الحديثة العادية على مخزن مؤقت للاستنسل يقتصر على 8 بت ، وهو أبعد ما يكون عن كل شيء يمكنه تخزين مخزن مؤقت للسمات. نحن بحاجة إلى التوصل إلى حل صعب.

دعونا نكتشف ذلك:

* تحديث المخزن المؤقت للعمق: مطلوب للبيكسلات المعتمة ، واختيارية للبيكسلات الشفافة.

* معرفات المضلع: يتم تعيين معرفات 6 بت للمضلعات ، والتي يمكن استخدامها لعدة أغراض. يتم استخدام معرفات مضلع غير شفافة لتمييز الحواف. يمكن استخدام معرف المضلعات الشفافة للتحكم في مكان رسمها: لن يتم رسم وحدة بكسل شفافة إذا كان معرف المضلع مطابقًا لمعرف المضلع الشفاف الموجود بالفعل في مخزن السمات المؤقت. أيضا ، يتم استخدام كلا معرفات المضلع بالمثل للتحكم في عرض الظل. على سبيل المثال ، يمكنك إنشاء ظل يغطي الأرضية وليس الحرف.

(ملاحظة: الظلال هي مجرد تطبيق لمخزن الاستنسل ، لا يوجد شيء رهيب هنا.)

تجدر الإشارة إلى أنه عند عرض وحدات البكسل الشفافة ، يتم حفظ المعرّف الحالي للمضلع المعتم ، بالإضافة إلى أعلام حافة المضلع المعتم الأخير.

* علم الضباب: يحدد ما إذا كان سيتم تطبيق تمرير الضباب لهذه البكسل. تعتمد عملية تحديثها على ما إذا كانت البكسل الواردة معتمة أو شفافة.

* علم الخط الأمامي: هنا توجد مشاكل معه. ألق نظرة على لقطة الشاشة:


رمال التدمير ، شاشات هذه اللعبة عبارة عن مجموعة من الحيل. فهم لا يغيرون إحداثياتهم Y فقط للتأثير على الفرز Y. ربما تكون الشاشة الموضحة في لقطة الشاشة هذه هي الأسوأ.

تستخدم حالة حدود اختبار العمق: تأخذ وظيفة المقارنة "أقل من" قيمًا متساوية إذا قامت اللعبة برسم مضلع ينظر إلى الكاميرا فوق وحدات البكسل المعتم للمضلع الموجهة بعيدًا عن الكاميرا . نعم بالضبط. والقيم Z لجميع المضلعات صفر. إذا لم تحاكي هذه الميزة ، فستفقد بعض العناصر على الشاشة.

أعتقد أنه تم القيام بذلك بحيث كان الجانب الأمامي من الكائن مرئيًا دائمًا على الجانب الخلفي ، حتى عندما تكون مسطحة لدرجة أن قيم Z هي نفسها. مع كل هذه الاختراقات والحيل ، فإن جهاز عرض DS مشابه لإصدار الأجهزة من أجهزة عرض عصر DOS.

كن على هذا النحو ، كان من الصعب محاكاة هذا السلوك من خلال وحدة معالجة الرسومات. ولكن هناك حالات حدودية أخرى مماثلة لاختبار العمق ، والتي تحتاج أيضًا إلى اختبارها وتوثيقها.

* أعلام الأضلاع: يتتبع العارض موقع حواف المضلعات. يتم استخدامها في الممرات الأخيرة ، وبالتحديد عند وضع علامات على الحواف ومقاومة التعرج. هناك أيضًا قواعد خاصة لملء المضلعات غير الشفافة مع تعطيل الصقل. يوضح الرسم البياني أدناه هذه القواعد:


ملاحظة: يتم تقديم الإطارات السلكية بملء الحواف فقط! خطوة ذكية للغاية.

ملاحظة أخرى ممتعة حول التخزين المؤقت للعمق:

هناك وضعان ممكنان للتخزين المؤقت للعمق في DS: التخزين المؤقت Z والتخزين المؤقت W. يبدو هذا قياسيًا جدًا ، ولكن فقط إذا لم تدخل في التفاصيل.

* يستخدم التخزين المؤقت على شكل Z إحداثيات Z المحولة لملاءمة فاصل تخزين مؤقت بعمق 24 بت. يتم استكمال الإحداثيات Z بشكل خطي عبر المضلعات (مع بعض الشذوذ ، لكنها ليست مهمة بشكل خاص). لا يوجد شيء غير قياسي هنا أيضًا.

* في التخزين المؤقت W ، يتم استخدام إحداثيات W "كما هي". عادة ما تستخدم وحدات معالجة الرسومات الحديثة 1 / W ، لكن DS يستخدم الحساب ذو النقطة الثابتة فقط ، لذا فإن استخدام القيم التبادلية ليس مناسبًا جدًا. كن على هذا النحو ، في هذا الوضع ، يتم إحداثيات إحداثيات W مع تصحيح المنظور.

إليك ما تبدو عليه تصاريح العرض النهائية:

* علامة الحافة: يتم تعيين لون مأخوذ من الجدول وتحديد وحدات البكسل التي تحتوي على أعلام الحافة بناءً على معرف مضلع غير شفاف.

ستكون حواف ملونة من المضلعات. تجدر الإشارة إلى أنه إذا تم رسم مضلع شفاف فوق مضلع معتم ، فستظل حواف المضلع ملونة.

من الآثار الجانبية لمبدأ الاقتطاع: سيتم تلوين الحدود التي تتقاطع عندها المضلعات مع حدود الشاشة. يمكنك على سبيل المثال ملاحظة ذلك في لقطات شاشة Picross 3D.

* الضباب: يتم تطبيقه على كل بكسل بناءً على قيم العمق المستخدمة لفهرسة جدول كثافة الضباب. كما قد تخمن ، فإنه ينطبق على وحدات البكسل التي تم تعيين إشارات الضباب عليها في المخزن المؤقت للسمة.

* مضاد الحواف (تنعيم): يتم تطبيقه على حواف المضلعات (غير الشفافة). بناءً على منحدرات الحواف عند عرض المضلعات ، يتم حساب قيم تغطية البكسل. في التمرير الأخير ، يتم خلط وحدات البكسل هذه مع وحدات البكسل الموجودة تحتها باستخدام الآلية الصعبة التي وصفتها في منشور سابق.

لا يجب (ولا يمكن) مكافحة التحيز بهذه الطريقة على GPU ، لذلك هذا ليس مهمًا هنا.

باستثناء أنه في حالة تطبيق علامات الحواف ومقاومة التعرج على وحدات البكسل نفسها ، فإنها تحصل على حجم الحافة فقط ، ولكن مع عتامة 50٪.

يبدو أنني قد وصفت عملية التقديم بشكل أو بآخر. لم نتعمق في خلط القوام (الجمع بين قمة الرأس وألوان الملمس) ، ولكن يمكن محاكاته في تظليل جزء. وينطبق الشيء نفسه على تمييز الحواف والضباب ، بشرط أن نجد طريقة حول هذا النظام بأكمله باستخدام مخزن مؤقت للسمات.

ولكن بشكل عام ، أردت نقل ما يلي: لن يساعد OpenGL أو Vulkan (بالإضافة إلى Direct3D أو Glide أو أي شيء آخر) هنا. تمتلك وحدات معالجة الرسومات الحديثة لدينا طاقة أكثر من كافية للعمل مع المضلعات الخام. المشكلة هي تفاصيل وخصائص التنقيط. ولا يتعلق الأمر بمثالية وحدات البكسل ، على سبيل المثال ، ما عليك سوى إلقاء نظرة على أداة تتبع المشكلات في محاكي DeSmuME لفهم المشكلات التي يواجهها المطورون عند العرض من خلال OpenGL. علينا أيضا أن نتعامل مع هذه المشاكل نفسها بطريقة أو بأخرى.

ألاحظ أيضًا أن استخدام OpenGL سيسمح لنا بنقل المحاكي ، على سبيل المثال ، للتبديل (لأن مستخدم Github المسمى Hydr8gon بدأ في إنشاء منفذ لمحاكينا على Switch ).

لذا ... أتمنى لي التوفيق.

Source: https://habr.com/ru/post/ar429160/


All Articles