نظرًا لأن OpenGL.pas الخاص بشركة Delphi هو الإصدار 1.0، وما يتم استخدامه فعليًا الآن هو الإصدار 1.1 على الأقل، وطريقة محاكاة برامج Windows النقية هي أيضًا الإصدار 1.1، لذلك يتعين عليك استيراد بعض الوظائف الضرورية بنفسك. تتوفر أيضًا بعض الوحدات المجانية مفتوحة المصدر، مثل OpenGL12.pas الخاص بـ Mike Lischke. بالطبع، كتابتها بنفسك يمكن أن تجعل التصميم أكثر إيجازًا، ولن تضطر إلى العثور على أخطاء في كود ضخم متقدم جدًا ومكتمل.
قم أولاً بتقديم الوحدات الضرورية لنظام التشغيل Windows، والرسائل، وOpenGL
لإضافة بعض الإضافات الضرورية.
ثابت
//GL_EXT_bgra
GL_BGR_EXT = 80E0 دولارًا أمريكيًا؛
GL_BGRA_EXT = 80E1 دولارًا أمريكيًا؛
// إزاحة المضلع
GL_POLYGON_OFFSET_UNITS = 2A00 دولار؛
GL_POLYGON_OFFSET_POINT = $2A01;
GL_POLYGON_OFFSET_LINE = 2A02 دولار؛
GL_POLYGON_OFFSET_FILL = 8037 دولارًا أمريكيًا؛
GL_POLYGON_OFFSET_FACTOR = 8038 دولارًا أمريكيًا؛
PROcedure glBindTexture(target: GLEnum;texture: GLuint stdcall);
الإجراء glDeleteTextures(n: GLsizei; contexts: PGLuint stdcall); opengl32 الخارجي;
الإجراء glGenTextures(n: GLsizei; contexts: PGLuint stdcall); opengl32 الخارجي;
دالة glIsTexture(texture: GLuint): GLboolean stdcall opengl32 الخارجي;
الإجراء glPolygonOffset(factor,Units: GLfloat stdcall); opengl32 الخارجي;
// يُستخدم هذا البيان لتصحيح خطأ في OpenGL.pas
وظيفة gluBuild2DMipmaps (الهدف: GLEnum؛ المكونات، العرض، الارتفاع: GLint؛ التنسيق، atype: GLEnum؛ البيانات: المؤشر): GLint stdcall الخارجي؛
الآن تمت ترقية الواجهة بشكل أساسي إلى الإصدار 1.1. إذا كانت هناك حاجة إلى ملحقات أخرى، فيمكن إضافتها بالمثل.
بعد ذلك، تحتاج إلى إنشاء سياق رسم OpenGL RC، والذي تحتاج إلى سياق الجهاز DC الخاص بنافذة GDI. الخاصية TForm.Handle أو خصائص المؤشر الأخرى الخاصة بـ TWinControl هي DC. يمكنك استخدام الدالة التالية لإنشاء RC من DC، وتكون قيمة الإرجاع هي مقبض RC. يمكنك بعد ذلك الرسم باستخدام OpenGL. بشكل عام يمكن استخدامه ضمن حدث OnCreate للنموذج. تعني خيارات هذه الوظيفة المخزن المؤقت للعمق، والمخزن المؤقت للقالب، والمخزن المؤقت للتراكم، وإنشاء قيمة قناة ألفا.
يكتب
TRCOptions = مجموعة من (roDepth، roStencil، roAccum، roAlpha)؛
وظيفة CreateRC(dc: HDC; opt: TRCOptions): HGLRC;
فار
PFDescriptor: TPixelFormatDescriptor;
تنسيق البكسل: عدد صحيح؛
يبدأ
fillChar(PFDescriptor, SizeOf(PFDescriptor), 0);
مع PFDescriptor تفعل
يبدأ
nSize := SizeOf(PFDescriptor);
nVersion := 1;
dwFlags := PFD_SUPPORT_OPENGL أو PFD_DRAW_TO_WINDOW أو PFD_DOUBLEBUFFER;
iPixelType := PFD_TYPE_RGBA;
cColorBits := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES);
إذا تم اختيار roDepth، فعندئذٍ cDepthBits := 24;
إذا تم اختيار roStencil، فعندئذٍ cStencilBits := 8;
إذا تم اختيار roAccum، فعندئذٍ cAccumBits := 64;
iLayerType := PFD_MAIN_PLANE;
نهاية؛
PixelFormat := ChoosePixelFormat(DC, @PFDescriptor);
تأكيد(PixelFormat <> 0);
Assert(SetPixelFormat(DC, PixelFormat, @PFDescriptor));
النتيجة := wglCreateContext(DC);
تأكيد(النتيجة <> 0);
wglMakeCurrent(dc, Result);
نهاية؛
الرسم في الحدث OnPaint الخاص بالنموذج. تذكر أنه بعد اكتمال الرسم، تحتاج إلى استخدام SwapBuffers (dc: HDC) لتبادل المخزن المؤقت للرسم والمخزن المؤقت للعرض حتى يتم عرض الصورة. تذكر أيضًا استدعاء glViewport(0, 0, ClientWidth, ClientHeight); في حدث OnResize الخاص بالنموذج بحيث يمكن مزامنة RC وDC.
تدمير RC في حدث OnDestroy الخاص بالنموذج.
الإجراء DestroyRC(rc: HGLRC);
يبدأ
إذا RC = 0 ثم خروج؛
wglMakeCurrent(0, 0);
wglDeleteContext(rc);
نهاية؛
في هذه المرحلة، يكون إطار عمل برنامج OpenGL قد تبلور تقريبًا. ولكن لا تزال هناك مشاكل يتعين حلها.
أولاً، منع Windows من مسح الخلفية والتأثير على السرعة. إضافة وظائف الأعضاء إلى النموذج
خاص
الإجراء WMEraseBkgnd (رسالة var: TWmEraseBkgnd)؛
الإجراء TGLWindow.WMEraseBkgnd(var الرسالة: TWmEraseBkgnd);
يبدأ
الرسالة. النتيجة := 1;
نهاية؛
ثانيا، أن تكون أكثر أمانا. أضف وظائف الأعضاء التالية.
محمي
الإجراء CreateParams(var Params: TCreateParams);
الإجراء TGLWindow.CreateParams(var Params: TCreateParams);
يبدأ
موروث؛
مع بارامز تفعل
يبدأ
النمط := النمط أو WS_CLIPCHILDREN أو WS_CLIPSIBLINGS؛
WindowClass.Style := CS_VREDRAW أو CS_HREDRAW أو CS_OWNDC؛
نهاية؛
نهاية؛
حسنًا، الآن يمكنك نسيان هذه الأشياء المزعجة وكتابة عرضك الرائع ثلاثي الأبعاد :)
يجب أن أقول بضع كلمات، لا تقم بإنشاء عدة RCs في موضوع واحد، لأن هذا سيؤثر بشكل خطير على الأداء. تضع بعض العروض التوضيحية الشخصية للتحكم في نافذة OpenGL عناصر تحكم متعددة في النموذج، وهي في الواقع ليست فكرة جيدة. يجب أن يتم عرض طرق عرض متعددة في نافذة OpenGL واحدة. أيضًا، لا تصل إلى وظائف OpenGL عبر سلاسل الرسائل.
وأيضًا، عندما يقوم Windows بتثبيت برنامج تشغيل بطاقة الرسومات تلقائيًا، فلن يقوم بتثبيت تسريع أجهزة OpenGL، ويجب عليك تثبيت برنامج تشغيل الشركة المصنعة لبطاقة الرسومات بنفسك!
بالإضافة إلى ذلك، يتم توفير وظيفة عرض ملء الشاشة مجانًا :)
وظيفة ملء الشاشة (الفوز: TWinControl؛ العرض، الارتفاع، عمق البت: عدد صحيح): منطقي؛
فار عرض الوضع: DEVMODE؛
يبدأ
fillChar(displaymode, sizeof(displaymode), 0);
مع وضع العرض تفعل ذلك
يبدأ
dmSize := sizeof(displaymode);
dmPelsWidth:= width;
dmPelsHeight := height;
dmBitsPerPel := عمق البت;
dmFields := DM_BITSPERPEL أو DM_PELSWIDTH أو DM_PELSHEIGHT؛
نهاية؛
إذا ChangeDisplaySettings(displaymode, CDS_FULLSCREEN) = DISP_CHANGE_SUCCESSFUL
ثم ابدأ
ShowWindow(win.Handle, WS_MAXIMIZE);
النتيجة :=صحيح؛
نهاية
نتيجة أخرى:= خطأ؛
نهاية؛
الإجراء RestoreDisplay(win: TWinControl);
يبدأ
ChangeDisplaySettings(PDEVMODE(0)^, 0);
ShowWindow(win.Handle, SW_RESTORE);
نهاية؛