كيف تتفاعل وحدة المعالجة المركزية ووحدة معالجة الرسومات لتقديم رسومات الكمبيوتر؟
تتفاعل وحدة المعالجة المركزية للكمبيوتر (CPU) ووحدة معالجة الرسومات (GPU) في كل لحظة تستخدم فيها الكمبيوتر الخاص بك لتوفر لك واجهة مرئية واضحة ومتجاوبة. تابع القراءة لفهم كيفية عملهم معًا بشكل أفضل.
الصورة من تصوير sskennel.
تأتي جلسة الأسئلة والأجوبة اليوم مقدمة من SuperUser-a subdivision of Stack Exchange ، وهي مجموعة مجتمعية للمواقع على شبكة الإنترنت Q & A.
السؤال
طرح قارئ SuperAser Sathya السؤال:
يمكنك هنا مشاهدة لقطة شاشة لبرنامج C ++ صغير يسمى Triangle.exe مع مثلث دوار على أساس OpenGL API.
من المسلم به أنه مثال أساسي للغاية ولكن أعتقد أنه ينطبق على عمليات بطاقات الرسومات الأخرى.
كنت أشعر بالفضول وأردت معرفة العملية بأكملها من النقر المزدوج على Triangle.exe تحت Windows XP حتى أتمكن من رؤية المثلث الذي يدور على الشاشة. ماذا يحدث ، كيف تتفاعل وحدة المعالجة المركزية (التي تتعامل أولاً مع .exe) ووحدة معالجة الرسومات (التي تخرج في النهاية المثلث على الشاشة)?
أعتقد أن المشاركة في عرض هذا المثلث الدائري هو في الأساس الأجهزة / البرامج التالية:
المعدات
- HDD
- ذاكرة النظام (ذاكرة الوصول العشوائي)
- وحدة المعالجة المركزية
- ذاكرة الفيديو
- GPU
- عرض شاشات الكريستال السائل
البرمجيات
- نظام التشغيل
- DirectX / OpenGL API
- سائق نفيديا
يمكن لأي شخص أن يفسر هذه العملية ، ربما مع نوع من الرسم البياني للتدفق?
لا ينبغي أن يكون التفسير المعقد الذي يغطي كل خطوة (تخمين أن يتجاوز نطاق) ، ولكن التفسير الذي يمكن أن يتبعه رجل تقنية معلومات وسيط.
أنا متأكد من أن الكثير من الأشخاص الذين قد يطلقون على أنفسهم خبراء تكنولوجيا المعلومات لا يمكنهم وصف هذه العملية بشكل صحيح.
الاجابة
على الرغم من أن العديد من أعضاء المجتمع المحلي قد أجابوا على السؤال ، فإن أوليفر سالزبورغ قد قطعوا المسافة الإضافية وأجابوا عليها ليس فقط برد مفصل ولكن الرسومات المصاحبة الممتازة.
الصورة بواسطة JasonC ، متوفرة كخلفية هنا.
هو يكتب:
قررت أن أكتب قليلا عن جانب البرمجة وكيف تتحدث المكونات مع بعضها البعض. ربما سوف يلقي بعض الضوء على مناطق معينة.
العرض
ما الذي يتطلبه الأمر حتى الحصول على تلك الصورة المفردة ، التي نشرتها في سؤالك ، مرسومة على الشاشة?
هناك طرق عديدة لرسم مثلث على الشاشة. من أجل البساطة ، دعونا نفترض أنه لم يتم استخدام أي مخازن رأسية. (ا عازلة قمة الرأسهي مساحة من الذاكرة حيث تقوم بتخزين الإحداثيات.) لنفترض أن البرنامج أخبر ببساطة خط أنابيب معالجة الرسومات عن كل قمة رأس (قمة الرأس هي مجرد تنسيق في الفضاء) في صف واحد.
لكن, قبل أن نتمكن من رسم أي شيء ، علينا أولاً تشغيل بعض السقالات. سوف نرى لماذا ا في وقت لاحق:
// مسح الشاشة والعامل العيني glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)؛ // Reset The Model Modelview Matrix glMatrixMode (GL_MODELVIEW)؛ glLoadIdentity ()؛ // الرسم باستخدام مثلثات glBegin (GL_TRIANGLES)؛ // أحمر glColor3f (1.0f، 0.0f، 0.0f)؛ // Top Of Triangle (Front) glVertex3f (0.0f، 1.0f، 0.0f)؛ // Green glColor3f (0.0f، 1.0f، 0.0f)؛ // Left Of Triangle (Front) glVertex3f (-1.0f، -1.0f، 1.0f)؛ // blue glColor3f (0.0f، 0.0f، 1.0f)؛ // Right Of Triangle (Front) glVertex3f (1.0f، -1.0f، 1.0f)؛ // Done Drawing glEnd ()؛
إذن ماذا فعل ذلك?
عندما تكتب برنامجًا يريد استخدام بطاقة الرسومات ، ستختار عادةً نوعًا ما من الواجهة إلى برنامج التشغيل. بعض واجهات معروفة للسائق هي:
- برنامج OpenGL
- Direct3D
- CUDA
على سبيل المثال ، سنتمسك بـ OpenGL. الآن لك واجهة للسائق هو ما يمنحك جميع الأدوات التي تحتاجها لإنشاء برنامجك حديث إلى بطاقة الرسومات (أو السائق ، الذي بعد ذلك محادثات على البطاقة).
لا بد هذه الواجهة تعطيك معينة أدوات. تأخذ هذه الأدوات شكل واجهة برمجة التطبيقات التي يمكنك الاتصال بها من برنامجك.
واجهة برمجة التطبيقات تلك هي ما نراه يتم استخدامه في المثال أعلاه. دعونا نلقي نظرة فاحصة.
السقالات
قبل أن تتمكن فعلاً من رسم أي رسم فعلي ، يجب عليك تنفيذ اقامة. يجب تحديد منفذ العرض (المنطقة التي سيتم عرضها فعليًا) ، وجهة نظرك ( الة تصوير في عالمك) ، ما تنعيم ستستخدمه (للتخلص من حافة المثلث الخاص بك) ...
لكننا لن ننظر إلى أي من ذلك. سنلقي نظرة على الأشياء التي عليك فعلها كل إطار. مثل:
مسح الشاشة
خط أنابيب الرسومات لن يتم مسح الشاشة لك كل إطار. سيكون عليك إخبارها لماذا ا؟ هذا هو السبب:
إذا لم تقم بمسح الشاشة ، فسوف ببساطة رسم أكثر كل إطار. لهذا السبب نسميه glClear
مع الGL_COLOR_BUFFER_BIT
جلس. الجزء الآخر (GL_DEPTH_BUFFER_BIT
) يخبر OpenGL لمسح عمقمتعادل. يتم استخدام هذا المخزن المؤقت لتحديد البيكسلات الموجودة أمام (أو خلف) وحدات البكسل الأخرى.
تحويل
مصدر الصورة
التحول هو الجزء الذي نأخذ فيه جميع إحداثيات المدخلات (رؤوس المثلث) ونطبق مصفوفة ModelView الخاصة بنا. هذه هي المصفوفة يشرح كيف لنا نموذج (الرؤوس) يتم تدويرها وتغيير حجمها وترجمتها (نقلها).
بعد ذلك ، نطبق مصفوفة الإسقاط. هذا ينقل كل الإحداثيات بحيث يواجهون كاميرتنا بشكل صحيح.
الآن نتحول مرة أخرى ، مع مصفوفة Viewport لدينا. نحن نفعل هذا لتوسيع نطاق عملنا نموذج إلى حجم الشاشة لدينا. الآن لدينا مجموعة من القمم التي هي على استعداد لتقديمها!
سوف نعود للتحول قليلا في وقت لاحق.
رسم
لرسم مثلث ، يمكننا ببساطة إخبار OpenGL لبدء عملية جديدة قائمة المثلثات بالاتصال glBegin
مع ال GL_TRIANGLES
ثابت.
هناك أيضًا أشكال أخرى يمكنك رسمها. مثل شريط مثلث أو مروحة مثلث. هذه هي التحسينات في المقام الأول ، لأنها تتطلب اتصالات أقل بين وحدة المعالجة المركزية ووحدة معالجة الرسومات لرسم نفس مقدار المثلثات.
بعد ذلك ، يمكننا تقديم قائمة من مجموعات من 3 القمم التي ينبغي أن تشكل كل المثلث. يستخدم كل المثلث 3 إحداثيات (كما نحن في الفضاء ثلاثي الأبعاد). بالإضافة إلى ذلك ، أنا أيضا توفير اللون لكل قمة ، عن طريق الاتصالglColor3f
قبل دعوة glVertex3f
.
يتم حساب الظل بين الرؤوس الثلاثة (الأركان الثلاثة للمثلث) بواسطة OpenGLتلقائيا. سيؤدي إلى استيفاء اللون على الوجه الكلي للمضلع.
التفاعل
الآن ، عند النقر فوق النافذة. التطبيق لديه فقط لالتقاط رسالة النافذة التي تشير إلى النقر. ثم يمكنك تشغيل أي إجراء في البرنامج الذي تريده.
هذا يحصل على قطعة أرض أكثر صعوبة بمجرد أن تبدأ في التفاعل مع المشهد ثلاثي الأبعاد الخاص بك.
يجب عليك أولاً أن تعرف بوضوح البكسل الذي نقر عليه المستخدم على النافذة. ثم ، مع الأخذ إنطباعفي الاعتبار ، يمكنك حساب اتجاه شعاع ، من نقطة النقر بالماوس في المشهد الخاص بك. يمكنك بعد ذلك حساب أي كائن في المشهد الخاص بك يتقاطع مع هذا الشعاع. الآن أنت تعرف ما إذا كان المستخدم قد نقر على كائن.
لذا ، كيف تجعلها تدور?
تحويل
أنا على دراية بنوعين من التحولات التي يتم تطبيقها بشكل عام:
- التحويل القائم على المصفوفة
- التحول القائم على العظام
الفرق هو ذلك العظام تؤثر على واحد الرؤوس. المصفوفات دائما تؤثر على جميع القمم المرسومة بنفس الطريقة. لنلقي نظرة على مثال.
مثال
في وقت سابق ، قمنا بتحميل لدينا مصفوفة الهوية قبل رسم مثلثنا. مصفوفة الهوية هي التي توفر ببساطة لا تحول على الاطلاق. لذلك ، أيا كان رسم ، يتأثر فقط من وجهة نظري. لذا ، لن يتم تدوير المثلث على الإطلاق.
إذا كنت أرغب في تدويرها الآن ، فبإمكاني إما إجراء العملية بنفسي (على وحدة المعالجة المركزية) والاتصال ببساطة glVertex3f
معآخر إحداثيات (التي يتم تدويرها). أو يمكنني السماح لوحدة معالجة الرسومات (GPU) بالقيام بكل العمل ، عن طريق الاتصال glRotatef
قبل الرسم:
// Rotate The Triangle On The Y axis glRotatef (amount، 0.0f، 1.0f، 0.0f)؛
كمية
هو ، بطبيعة الحال ، مجرد قيمة ثابتة. أذا أردت حي, عليك أن تتبع كمية
وزيادة كل إطار.
لذا ، انتظر ، ما حدث لكل الكلام عن المصفوفة في وقت سابق?
في هذا المثال البسيط ، لا يتعين علينا الاهتمام بالمصفوفات. نحن ببساطة ندعو glRotatef
ويعتني بكل ذلك بالنسبة لنا.
glRotate
ينتج دورانزاوية
درجة حول ناقلات x y z. يتم ضرب المصفوفة الحالية (seeglMatrixMode) بواسطة مصفوفة دوران مع استبدال المنتج للمصفوفة الحالية ، كما لو تم استدعاء ifglMultMatrix مع المصفوفة التالية كوسيطة لها:x 2 1 - c + cx y 1 - c - z sx z 1 - c + y s 0 y x 1 - c + z sy 2 1 - c + cy z 1 - c - x 0 s 0 x z 1 - c - y sy z 1 - c + x sz 2 1 - c + c 0 0 0 0 1
حسنا ، شكرا على ذلك!
استنتاج
ما أصبح واضحًا هو أن هناك الكثير من الكلام إلى برنامج OpenGL. لكن هذا لا يعني لنا اى شى. أين التواصل?
الشيء الوحيد الذي تخبرنا به OpenGL في هذا المثال هو عندما تنتهي. كل عملية تستغرق فترة زمنية معينة. تستغرق بعض العمليات فترة طويلة بشكل لا يصدق ، وبعضها الآخر سريع بشكل لا يصدق.
ارسال قمة الرأس إلى GPU سوف تكون سريعة جدا ، وأنا لا أعرف حتى كيفية التعبير عن ذلك. إن إرسال آلاف القمم من وحدة المعالجة المركزية إلى وحدة معالجة الرسوميات ، على الأرجح ، لا يمثل أي إطار على الإطلاق أي مشكلة على الإطلاق.
مسح الشاشة يمكن أن تستغرق ملي ثانية أو ما هو أسوأ (ضع في اعتبارك أنك لا تملك عادة سوى حوالي 16 مللي ثانية من الوقت لرسم كل إطار) ، اعتمادًا على مدى حجم إطار العرض لديك. لإلغاء تحديدها ، يجب على OpenGL رسم كل بكسل في اللون الذي تريد مسحه ، قد يكون ملايين من وحدات البكسل.
بخلاف ذلك ، يمكننا فقط أن نسأل OpenGL عن إمكانات مهايئ الرسومات الخاص بنا (الدقة القصوى ، الصقل الأقصى ، عمق اللون الأقصى ، ...).
ولكن يمكننا أيضًا ملء نسيج بوحدات البكسل بحيث يكون لكل لون لون معين. وبالتالي فإن كل بكسل يحمل قيمة ونسيج هو "ملف" عملاق مملوء بالبيانات. يمكننا تحميل ذلك في بطاقة الرسومات (عن طريق إنشاء مخزن مؤقت) ، ثم نقوم بتحميل تظليل ، ونعلم أن shader يستخدم نسيجنا كمدخل ، ونقوم بتشغيل بعض الحسابات الثقيلة للغاية على "ملفنا"..
يمكننا بعد ذلك "تقديم" نتيجة حسابنا (في شكل ألوان جديدة) في نسيج جديد.
هذه هي الطريقة التي يمكنك بها جعل وحدة معالجة الرسوميات تعمل لصالحك بطرق أخرى. أفترض أن CUDA يؤدي نفس الأداء ، لكن لم تتح لي الفرصة للعمل معه.
نحن حقا فقط تطرق قليلا الموضوع كله. برمجة الرسومات ثلاثية الأبعاد هي جحيم وحش.
مصدر الصورة
هل لديك شيء تضيفه إلى الشرح؟ الصوت قبالة في التعليقات. هل ترغب في قراءة المزيد من الإجابات من مستخدمي Stack Exchange الآخرين المحترفين بالتكنولوجيا؟ تحقق من موضوع المناقشة الكامل هنا.