تحويل إطار عمل NeHe's VC OPENGL المترجم بواسطة CKER إلى إصدار دلفي.
آمل أن يكون مفيدًا للإخوة الذين يستخدمون دلفي لتعلم لغة OPENGL.
لا أعرف السبب، لكن لا يمكن تشغيله مباشرة في بيئة دلفي الخاصة بي، ولكن يبدو أنه جيد على الأجهزة الأخرى.
يمكن لجهازي تجميع ملفات EXE وتشغيلها فقط.
شكرًا لـ NeHe لتوفير هذا الإطار الجيد، وشكرًا لـ CKER لترجمة معلومات VC.
مشروع البرنامج1؛
الاستخدامات
برنامج,
النوافذ,
رسائل؛
ثابت
WND_TITLE = 'إطار عمل OPenGl الأساسي';
فار
//================================================================================================ ======================================================
// كل برنامج OpenGL متصل بسياق التظليل. يربط جدول سياق التظليل كافة استدعاءات OpenGL
// احصل على سياق الجهاز (جدول وصف الجهاز) وحدد جدول وصف تظليل OpenGL على أنه hRC، حتى يتمكن البرنامج من ذلك
// إذا كان رسم النافذة كافيًا، فأنت بحاجة أيضًا إلى إنشاء جدول وصف الجهاز، ويتم تعريف جدول وصف جهاز Windows على أنه hDC.
// يقوم DC بتوصيل النافذة بـ GDI (واجهة جهاز الرسومات). ويقوم RC بتوصيل OpenGL
// إلى العاصمة.
//================================================================================================ ======================================================
h_RC: HGLRC؛ // سياق العرض (جدول وصف التظليل).
h_DC: HDC // سياق الجهاز (جدول وصف الجهاز)
h_Wnd: HWND؛ // مقبض النافذة
h_Instance: HINST; // مثيل البرنامج (مثيل).
المفاتيح: صفيف [0..255] منطقي؛ // صفيف لإجراءات لوحة المفاتيح
{$R *.res}
//================================================================================================ =============================================================
// إعادة تعيين حجم مشهد OpenGL بغض النظر عما إذا كان حجم النافذة قد تغير (بافتراض عدم استخدام وضع ملء الشاشة).
// حتى عندما لا يمكن تغيير حجم النافذة (على سبيل المثال في وضع ملء الشاشة)، فإنها ستظل تعمل مرة واحدة على الأقل ————————
// قم بتعيين المنظور في بداية البرنامج. سيتم ضبط حجم مشهد OpenGL على حجم النافذة التي يتم عرضه فيها.
//================================================================================================ =============================================================
الإجراء glResizeWnd(Width, Height: Integer); // إعادة ضبط حجم نافذة GL وتهيئته
يبدأ
إذا (الارتفاع = 0) ثم // منع الارتفاع من أن يكون 0 ويسبب استثناء القسمة على 0.
الارتفاع := 1;
glViewport(0, 0, Width, Height); // إعادة تعيين إطار العرض الحالي (منفذ العرض)
// الأسطر التالية تقوم بإعداد شاشة المنظور. وهذا يعني أن الأشياء البعيدة تبدو أصغر. القيام بذلك يخلق واقعا
// مشهد المظهر. يتم حساب المنظور هنا بزاوية عرض تبلغ 45 درجة بناءً على عرض النافذة وارتفاعها. 0.1f، 100.0f هي
// نقطة البداية ونقطة النهاية للعمق الذي يمكننا رسمه في المشهد.
يحدد //glMatrixMode(GL_PROJECTION) أن السطرين التاليين من التعليمات البرمجية سيؤثران على مصفوفة الإسقاط.
// مصفوفة الإسقاط مسؤولة عن إضافة منظور إلى مشهدنا.
//glLoadIdentity() يشبه إعادة التعيين. فهو يعيد حالة المصفوفة المحددة إلى حالتها الأصلية.
// بعد استدعاء glLoadIdentity () قمنا بتعيين منظور المشهد.
glMatrixMode(GL_PROJECTION); // حدد مصفوفة الإسقاط
glLoadIdentity(); // إعادة تعيين مصفوفة الإسقاط
gluPerspective(45.0, Width / Height, 0.1, 100.0); // احسب نسبة مظهر النافذة
يحدد //glMatrixMode(GL_MODELVIEW) أن أي تحويل جديد سيؤثر على مصفوفة عرض النموذج (مصفوفة مراقبة النموذج).
// يتم تخزين معلومات كائننا في مصفوفة مراقبة النموذج.
glMatrixMode(GL_MODELVIEW); //حدد مصفوفة مراقبة النموذج
glLoadIdentity(); // إعادة تعيين مصفوفة مراقبة النموذج
// إذا كنت لا تفهم ما تعنيه هذه المصطلحات حتى الآن، فلا تقلق.
// فقط اعلم أنه يتعين عليك القيام بذلك إذا كنت ترغب في الحصول على مشهد منظور رائع.
نهاية؛
//================================================================================================ =============================================================
// قم بإجراء كافة الإعدادات لبرنامج OpenGL. اضبط اللون لمسح الشاشة، وقم بتشغيل ذاكرة التخزين المؤقت للعمق،
// تمكين التظليل السلس (تجانس الظل)، وما إلى ذلك. لا يتم استدعاء هذا الروتين حتى يتم إنشاء نافذة OpenGL.
// سيكون لهذه العملية قيمة إرجاع. لكن التهيئة هنا ليست بهذا التعقيد، ولا داعي للقلق بشأن القيمة المرجعة بعد.
//================================================================================================ =============================================================
الإجراء glInit();
يبدأ
// اضبط اللون المستخدم عند مسح الشاشة. إذا لم تكن متأكدًا من كيفية عمل اللون، فإليك شرحًا سريعًا.
// تتراوح قيم اللون من 0.0f إلى 1.0f. يمثل 0.0f الموقف الأكثر ظلمة، و1.0f هو الوضع الأكثر سطوعًا.
// المعلمة الأولى بعد glClearColor هي كثافة اللون الأحمر (مكون أحمر)، والثانية باللون الأخضر، والثالثة باللون الأزرق.
// الحد الأقصى للقيمة هو أيضًا 1.0f، وهو ما يمثل الحالة الأكثر سطوعًا لمكون لون معين. المعلمة الأخيرة هي قيمة ألفا.
// عند استخدامه لمسح الشاشة، لا تهتم بالرقم الرابع. الآن فليكن 0.0f.
// من خلال مزج ثلاثة ألوان أساسية (الأحمر والأخضر والأزرق)، يمكنك الحصول على ألوان مختلفة
// لذا، استخدم glClearColor(0.0f,0.0f,1.0f,0.0f) باللون الأزرق لمسح الشاشة.
// إذا كنت تستخدم glClearColor(0.5f,0.0f,0.0f,0.0f)، فسيتم استخدام اللون الأحمر المتوسط لمسح الشاشة.
// ليس ألمع (1.0f)، ولا أحلك (0.0f). للحصول على خلفية بيضاء، يجب ضبط جميع الألوان على درجة سطوعها (1.0f).
// إذا كنت تريد خلفية سوداء، فاضبط جميع الألوان على اللون الأغمق (0.0f).
glClearColor(0.0, 0.0, 0.0, 0.0); // خلفية سوداء
// تجانس الظل يمزج الألوان بدقة من خلال المضلعات وينعم الضوء الخارجي.
glShadeModel(GL_SMOOTH); // تمكين تجانس الظل
// الشيء التالي الذي يجب القيام به هو ما يتعلق بالمخزن المؤقت للعمق. فكر في المخزن المؤقت للعمق كطبقة خلف الشاشة.
// يتتبع المخزن المؤقت للعمق بشكل مستمر مدى عمق دخول الكائن إلى الشاشة. هذا البرنامج في الواقع لا يستخدم ذاكرة التخزين المؤقت العميقة.
// لكن جميع برامج OpenGL تقريبًا التي تعرض مشاهد ثلاثية الأبعاد على الشاشة تستخدم مخازن مؤقتة للعمق. يحدد ترتيبها الكائن الذي سيتم رسمه أولاً.
// بهذه الطريقة لا ترسم مربعًا خلف دائرة على الدائرة. يعد المخزن المؤقت للعمق جزءًا مهمًا جدًا من برنامج OpenGL.
glClearDepth(1.0); // تعيين المخزن المؤقت للعمق
glEnable(GL_DEPTH_TEST); // تمكين اختبار العمق
glDepthFunc(GL_LESS); // نوع اختبار العمق الذي تم إجراؤه
// ثم أخبر OpenGL أننا نريد أفضل تصحيح ممكن للمنظور.
// سيؤثر هذا على الأداء بشكل طفيف جدًا. ولكن يجعل المنظور يبدو أفضل قليلا.
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // تصحيح منظور جيد حقًا
نهاية؛
//================================================================================================ =============================================================
// كل كود الرسم. أي شيء تريد عرضه على الشاشة سيظهر في هذا الكود.
// سيضيف كل برنامج مستقبلي رمزًا جديدًا هنا.
//================================================================================================ =============================================================
الإجراء glDraw();
يبدأ
glClear(GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT); // مسح الشاشة والمخزن المؤقت للعمق
glLoadIdentity(); // إعادة تعيين مصفوفة مراقبة النموذج الحالي
نهاية؛
الدالة WndProc(hWnd: HWND; // مقبض النافذة
رسالة: UINT؛ // رسالة النافذة
wParam: WPARAM؛ // محتوى الرسالة الإضافية
lParam: LPARAM // محتوى الرسالة الإضافية
): LRESULT;
يبدأ
النتيجة := 0;
حالة (رسالة) من // التحقق من رسائل Windows
WM_ACTIVATE: // مراقبة رسالة تنشيط النافذة
يبدأ
نهاية؛
WM_CREATE: // إنشاء
يبدأ
نهاية؛
WM_CLOSE: // إغلاق
يبدأ
PostQuitMessage(0); //أرسل رسالة خروج
النتيجة: = 0
نهاية؛
WM_KEYDOWN: // تم الضغط على المفتاح
يبدأ
key[wParam] := True; // إذا كانت الإجابة بنعم، فاضبط على TRUE
النتيجة := 0;
نهاية؛
WM_KEYUP: // حرر المفتاح
يبدأ
key[wParam] := False;
النتيجة := 0;
نهاية؛
WM_SIZE: // ضبط حجم نافذة OpenGL
يبدأ
glResizeWnd(LOWord(lParam), HIWORD(lParam)); //LoWord=Width,HiWord=Height
النتيجة := 0;
نهاية؛
WM_TIMER: // الموقتات
يبدأ
نهاية؛
آخر // دع Windows يتعامل مع الباقي.
النتيجة := DefWindowProc(hWnd, Msg, wParam, lParam); // تمرير كافة الرسائل غير المعالجة إلى DefWindowProc.
نهاية؛
نهاية؛
//================================================================================================ =============================================================
// يتم الاتصال به فقط قبل خروج البرنامج. تتمثل الوظيفة في تحرير جدول سياق التلوين وجدول سياق الجهاز ومقبض النافذة بالتسلسل.
// تمت إضافة الكثير من عمليات التحقق من الأخطاء. إذا كان البرنامج غير قادر على تدمير أي جزء من النافذة، فسوف تظهر رسالة خطأ مناسبة.
// نافذة الرسالة،
//================================================================================================ =============================================================
الإجراء glKillWnd(ملء الشاشة: Boolean);
يبدأ
// أول شيء يتم فعله في KillGLWindow() هو التحقق مما إذا كان في وضع ملء الشاشة.
// إذا كانت الإجابة بنعم، فارجع إلى سطح المكتب. كان من المفترض أن يتم تدمير النافذة قبل تعطيل وضع ملء الشاشة،
// لكن القيام بذلك على بعض بطاقات الرسومات قد يؤدي إلى تعطل سطح المكتب. لذا من الأفضل تعطيل وضع ملء الشاشة أولاً.
// سيمنع هذا تعطل سطح المكتب ويعمل بشكل رائع على كل من بطاقات الرسومات Nvidia و3dfx!
إذا كان ملء الشاشة ثم // في وضع ملء الشاشة؟
يبدأ
// استخدم ChangeDisplaySettings(NULL,0) للعودة إلى سطح المكتب الأصلي.
// خذ NULL كمعلمة أولى،
// تمرير 0 كمعلمة ثانية يفرض على Windows استخدام القيمة المخزنة حاليًا في السجل
// (الدقة الافتراضية، وعمق الألوان، ومعدل التحديث، وما إلى ذلك) لاستعادة سطح المكتب الأصلي بشكل فعال.
// بعد العودة إلى سطح المكتب، يجب أن يكون مؤشر الماوس مرئيًا مرة أخرى.
ChangeDisplaySettings(devmode(Nil^), 0); // إذا كانت الإجابة بنعم، فارجع مرة أخرى إلى سطح المكتب
ShowCursor(True); //إظهار الماوس
نهاية؛
// ما إذا كان يحتوي على جدول وصف التلوين (hRC).
إذا h_RC> 0 ثم
// معرفة ما إذا كان بإمكاننا تحريره (افصل hRC عن hDC).
إذا (ليس wglMakeCurrent(h_DC, 0)) إذن
messageBox(0, 'لا يمكن تحرير DC وRC!', 'خطأ', MB_OK أو
MB_ICONERROR)؛
// هل يمكن حذف جدول وصف التظليل؟
إذا (ليس wglDeleteContext(h_RC)) إذن
يبدأ
messageBox(0، "فشل في حذف جدول سياق التظليل!"، "خطأ"، MB_OK أو
MB_ICONERROR);
h_RC := 0;
نهاية؛
// ما إذا كان جدول سياق الجهاز موجودًا، وإذا كان الأمر كذلك، فحاول تحريره.
إذا ((h_DC > 0) و (ReleaseDC(h_Wnd, h_DC) = 0)) ثم
يبدأ
messageBox(0، "فشل في تحرير سياق الجهاز!"، "خطأ"، MB_OK أو
MB_ICONERROR);
h_DC := 0;
نهاية؛
// سواء كان هناك مقبض نافذة، اتصل بـ DestroyWindow(hWnd) لمحاولة تدمير النافذة
إذا ((h_Wnd <> 0) و (Not DestroyWindow(h_Wnd))) ثم
يبدأ
messageBox(0, 'لا يمكن تدمير النموذج!', 'خطأ', MB_OK أو
MB_ICONERROR);
h_Wnd := 0;
نهاية؛
// تسجيل الخروج من فئة النافذة
// هذا يسمح لنا بتدمير النافذة بشكل طبيعي ثم فتح النوافذ الأخرى،
// لن تتلقى رسائل خطأ مثل "فئة Windows مسجلة بالفعل" (فئة النافذة مسجلة بالفعل).
إذا (ليس UnRegisterClass('OpenGL', hInstance)) إذن
يبدأ
messageBox(0، 'غير قادر على تسجيل الخروج من فئة النافذة!'، 'خطأ'، MB_OK أو
MB_ICONERROR);
hInstance := 0;
نهاية؛
نهاية؛