เนื่องจาก OpenGL.pas ของ Delphi คือเวอร์ชัน 1.0 และเวอร์ชันที่ใช้จริงตอนนี้คือเวอร์ชัน 1.1 เป็นอย่างน้อย และวิธีการจำลองซอฟต์แวร์ Windows ล้วนเป็นเวอร์ชัน 1.1 เช่นกัน ดังนั้นคุณจึงต้องนำเข้าฟังก์ชันที่จำเป็นบางอย่างด้วยตนเอง นอกจากนี้ยังมีโอเพ่นซอร์สฟรีบางยูนิตให้เลือกใช้ เช่น OpenGL12.pas ของ Mike Lischke แน่นอนว่าการเขียนด้วยตัวเองสามารถทำให้การออกแบบกระชับยิ่งขึ้น และคุณไม่จำเป็นต้องค้นหาข้อผิดพลาดในโค้ดขนาดใหญ่ที่สูงเกินไปและสมบูรณ์เกินไป
ขั้นแรกแนะนำหน่วยที่จำเป็น Windows, Messages, 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 (เป้าหมาย: GLEnum; พื้นผิว: GLuint); stdcall ภายนอก
ขั้นตอน glDeleteTextures (n: GLsizei; พื้นผิว: PGLuint); opengl32 ภายนอก;
ขั้นตอน glGenTextures (n: GLsizei; พื้นผิว: PGLuint); stdcall ภายนอก
ฟังก์ชั่น glIsTexture (พื้นผิว: GLuint): GLboolean; stdcall ภายนอก;
ขั้นตอน glPolygonOffset (ปัจจัย, หน่วย: GLfloat); opengl32 ภายนอก;
// คำสั่งนี้ใช้เพื่อแก้ไขข้อผิดพลาดใน OpenGL.pas
ฟังก์ชั่น gluBuild2DMipmaps (เป้าหมาย: GLEnum; ส่วนประกอบ, ความกว้าง, ความสูง: GLint; รูปแบบ, atype: GLEnum; ข้อมูล: ตัวชี้): GLint; stdcall ภายนอก;
ขณะนี้อินเทอร์เฟซได้รับการอัปเกรดเป็นเวอร์ชัน 1.1 แล้ว หากจำเป็นต้องใช้ส่วนขยายอื่นๆ คุณสามารถเพิ่มส่วนขยายเหล่านั้นได้ในลักษณะเดียวกัน
ถัดไป คุณต้องสร้าง RC บริบทการวาดภาพ OpenGL ซึ่งคุณต้องการ DC บริบทอุปกรณ์ของหน้าต่าง GDI คุณสมบัติ TForm.Handle หรือคุณสมบัติการจัดการอื่นๆ ของ TWinControl คือ DC คุณสามารถใช้ฟังก์ชันต่อไปนี้เพื่อสร้าง RC จาก DC และค่าที่ส่งกลับคือหมายเลขอ้างอิงของ RC จากนั้นคุณสามารถวาดโดยใช้ OpenGL โดยทั่วไปสามารถใช้ได้ภายในเหตุการณ์ OnCreate ของแบบฟอร์ม ตัวเลือกของฟังก์ชันนี้หมายถึงบัฟเฟอร์เชิงลึก บัฟเฟอร์เทมเพลต บัฟเฟอร์สะสม และสร้างค่าช่องอัลฟ่า
พิมพ์
TRCOptions = ชุดของ (roDepth, roStencil, roAccum, roAlpha);
ฟังก์ชั่น CreateRC (dc: HDC; เลือก: TRCOptions): HGLRC;
var
PFDescriptor: TPixelFormatDescriptor;
รูปแบบพิกเซล: จำนวนเต็ม;
เริ่ม
FillChar(PFDescriptor, SizeOf(PFDescriptor), 0);
ด้วย PFDescriptor ทำ
เริ่ม
nSize := SizeOf(PFDescriptor);
เวอร์ชัน := 1;
dwFlags := PFD_SUPPORT_OPENGL หรือ PFD_DRAW_TO_WINDOW หรือ PFD_DOUBLEBUFFER;
iPixelType := PFD_TYPE_RGBA;
cColorBits := GetDeviceCaps (DC, BITSPIXEL) * GetDeviceCaps (DC, เครื่องบิน);
ถ้า roDepth เลือกแล้ว cDepthBits := 24;
ถ้า roStencil เลือกแล้ว cStencilBits := 8;
ถ้า roAccum เลือกแล้ว cAccumBits := 64;
iLayerType := PFD_MAIN_PLANE;
จบ;
PixelFormat := ChoosePixelFormat(DC, @PFDescriptor);
ยืนยัน(รูปแบบพิกเซล <> 0);
ยืนยัน (SetPixelFormat (DC, PixelFormat, @PFDescriptor));
ผลลัพธ์ := wglCreateContext(DC);
ยืนยัน(ผลลัพธ์ <> 0);
wglMakeCurrent(dc ผลลัพธ์);
จบ;
วาดในกิจกรรม OnPaint ของแบบฟอร์ม โปรดจำไว้ว่า หลังจากการวาดเสร็จสมบูรณ์ คุณต้องใช้ SwapBuffers (dc: HDC) เพื่อแลกเปลี่ยนบัฟเฟอร์การวาดและบัฟเฟอร์การแสดงผล เพื่อให้รูปภาพปรากฏ อย่าลืมเรียก glViewport(0, 0, ClientWidth, ClientHeight); ในเหตุการณ์ OnResize ของแบบฟอร์มเพื่อให้สามารถซิงโครไนซ์ RC และ DC ได้
ทำลาย RC ในกิจกรรม OnDestroy ของแบบฟอร์ม
ขั้นตอน DestroyRC (rc: HGLRC);
เริ่ม
ถ้า rc = 0 ให้ออก;
wglMakeปัจจุบัน(0, 0);
wglDeleteContext(rc);
จบ;
ณ จุดนี้ กรอบการทำงานของโปรแกรม OpenGL เป็นรูปเป็นร่างขึ้นมาคร่าวๆ แต่ยังคงมีปัญหาที่ต้องแก้ไข
ขั้นแรก ป้องกันไม่ให้ Windows ลบพื้นหลังและส่งผลต่อความเร็ว เพิ่มฟังก์ชันสมาชิกลงในแบบฟอร์ม
ส่วนตัว
ขั้นตอน WMEraseBkgnd (ข้อความ var: TWmEraseBkgnd); ข้อความ WM_ERASEBKGND;
ขั้นตอน TGLWindow.WMEraseBkgnd (ข้อความ var: TWmEraseBkgnd);
เริ่ม
ข้อความผลลัพธ์ := 1;
จบ;
ประการที่สองเพื่อความปลอดภัยยิ่งขึ้น เพิ่มฟังก์ชันสมาชิกต่อไปนี้
ได้รับการคุ้มครอง
ขั้นตอน CreateParams (var Params: TCreateParams);
ขั้นตอน TGLWindow.CreateParams (var Params: TCreateParams);
เริ่ม
สืบทอด;
ด้วย Params ทำ
เริ่ม
สไตล์ := สไตล์หรือ WS_CLIPCHILDREN หรือ WS_CLIPSIBLINGS;
WindowClass.Style := CS_VREDRAW หรือ CS_HREDRAW หรือ CS_OWNDC;
จบ;
จบ;
เอาล่ะ ตอนนี้คุณสามารถลืมเรื่องยุ่งยากเหล่านี้ได้แล้วเขียนการแสดงผล 3D ที่ยอดเยี่ยมของคุณได้เลย :)
ฉันต้องพูดอะไรสักสองสามคำ อย่าสร้าง RC หลายอันในเธรดเดียว เนื่องจากจะส่งผลต่อประสิทธิภาพการทำงานอย่างรุนแรง การสาธิตการควบคุมหน้าต่าง OpenGL ส่วนตัวบางอย่างทำให้มีการควบคุมหลายรายการในแบบฟอร์ม ซึ่งจริงๆ แล้วไม่ใช่ความคิดที่ดี ควรแสดงหลายมุมมองด้วยหน้าต่าง OpenGL เดียว นอกจากนี้ อย่าเข้าถึงฟังก์ชัน OpenGL ข้ามเธรด
นอกจากนี้ เมื่อ Windows ติดตั้งไดรเวอร์การ์ดแสดงผลโดยอัตโนมัติ ระบบจะไม่ติดตั้งการเร่งด้วยฮาร์ดแวร์ OpenGL คุณต้องติดตั้งไดรเวอร์ของผู้ผลิตการ์ดแสดงผลด้วยตัวเอง!
นอกจากนี้ยังมีฟังก์ชันการแสดงผลแบบเต็มหน้าจอให้ฟรีอีกด้วย :)
ฟังก์ชั่นเต็มหน้าจอ (win: TWinControl; ความกว้าง, ความสูง, บิตความลึก: จำนวนเต็ม): บูลีน;
โหมดการแสดงผล var: DEVMODE;
เริ่ม
FillChar (โหมดการแสดงผล, ขนาดของ (โหมดการแสดงผล), 0);
ด้วยโหมดการแสดงผลทำ
เริ่ม
dmSize := ขนาดของ(โหมดการแสดงผล);
dmPelsWidth:= ความกว้าง;
dmPelsHeight := ความสูง;
dmBitsPerPel := ความลึกบิต;
dmFields := DM_BITSPERPEL หรือ DM_PELSWIDTH หรือ DM_PELSHEIGHT;
จบ;
ถ้า ChangeDisplaySettings (โหมดการแสดงผล, CDS_FULLSCREEN) = DISP_CHANGE_SUCCESSFUL
จากนั้นเริ่มต้น
ShowWindow(win.Handle, WS_MAXIMIZE);
ผลลัพธ์ := จริง;
จบ
ผลลัพธ์อื่น := false;
จบ;
ขั้นตอน RestoreDisplay (ชนะ: TWinControl);
เริ่ม
ChangeDisplaySettings (PDEVMODE (0) ^, 0);
ShowWindow(win.Handle, SW_RESTORE);
จบ;