แปลงเฟรมเวิร์ก VC OPENGL ของ NeHe ที่แปลโดย CKER เป็นเวอร์ชัน Delphi
ฉันหวังว่ามันจะเป็นประโยชน์กับพี่น้องที่ใช้ Delphi เพื่อเรียนรู้ OPENGL
ฉันไม่รู้ว่าทำไม แต่มันไม่สามารถทำงานได้โดยตรงในสภาพแวดล้อม Delphi ของฉัน แต่ดูเหมือนว่าจะทำงานได้ดีบนเครื่องอื่น
เครื่องของฉันสามารถคอมไพล์และรันไฟล์ EXE เท่านั้น
ขอบคุณ NeHe ที่ให้บริการเฟรมเวิร์กที่ดีเช่นนี้ และขอบคุณ CKER สำหรับการแปลข้อมูล VC
โปรแกรม โครงการ1;
การใช้งาน
โอเพ่นเกิล,
หน้าต่าง,
ข้อความ;
คอนสตรัคชั่น
WND_TITLE = 'OPenGl กรอบงานพื้นฐาน'; //Title
วาร์
//================================================ ===========================
// แต่ละ OpenGL เชื่อมต่อกับบริบทการแรเงา ตารางบริบทแรเงาเชื่อมต่อการเรียก OpenGL ทั้งหมด
// รับบริบทอุปกรณ์ (ตารางคำอธิบายอุปกรณ์) และกำหนดตารางคำอธิบายการแรเงา OpenGL เป็น hRC เพื่อให้โปรแกรมสามารถ
// หากวาดหน้าต่างได้เพียงพอแล้ว คุณต้องสร้างตารางคำอธิบายอุปกรณ์ด้วย ตารางคำอธิบายอุปกรณ์ Windows ถูกกำหนดเป็น hDC
// DC เชื่อมต่อหน้าต่างกับ GDI (Graphics Device Interface) และ RC เชื่อมต่อ OpenGL
// ถึงดีซี
//================================================ ===========================
h_RC: HGLRC; // บริบทการแสดงผล (ตารางคำอธิบายการแรเงา)
h_DC: HDC; // บริบทอุปกรณ์ (ตารางคำอธิบายอุปกรณ์)
h_Wnd: HWND; // ที่จับหน้าต่าง
h_Instance: HINST; // อินสแตนซ์ของโปรแกรม (อินสแตนซ์)
ปุ่ม : Array[0..255] ของ Boolean; // Array สำหรับรูทีนของคีย์บอร์ด
{$R *.เรส}
//================================================ ==============================
//รีเซ็ตขนาดของฉาก OpenGL ไม่ว่าขนาดหน้าต่างจะเปลี่ยนไปหรือไม่ (สมมติว่าไม่ได้ใช้โหมดเต็มหน้าจอ)
//แม้ว่าหน้าต่างจะไม่สามารถปรับขนาดได้ (เช่น ในโหมดเต็มหน้าจอ) หน้าต่างก็ยังคงทำงานอย่างน้อยหนึ่งครั้ง————————
//กำหนดเปอร์สเปคทีฟเมื่อเริ่มต้นโปรแกรม ขนาดของฉาก OpenGL จะถูกกำหนดเป็นขนาดของหน้าต่างที่จะแสดง
//================================================ ==============================
ขั้นตอน glResizeWnd(Width, Height: Integer); //รีเซ็ตและเริ่มต้นขนาดหน้าต่าง GL
เริ่ม
ถ้า (ความสูง = 0) จากนั้น // ป้องกันความสูงไม่ให้เป็น 0 และทำให้เกิดข้อยกเว้นการหารด้วย 0
ส่วนสูง := 1;
glViewport(0, 0, ความกว้าง, ความสูง); // รีเซ็ตวิวพอร์ตปัจจุบัน (วิวพอร์ต)
//บรรทัดต่อไปนี้ตั้งค่าหน้าจอเปอร์สเปคทีฟ ซึ่งหมายความว่าสิ่งที่อยู่ไกลออกไปจะดูเล็กลง การทำเช่นนั้นจะสร้างความเป็นจริง
//ฉากการปรากฏตัว. เปอร์สเปคทีฟที่นี่คำนวณเป็นมุมมอง 45 องศา โดยพิจารณาจากความกว้างและความสูงของหน้าต่าง 0.1f, 100.0f คือ
//จุดเริ่มต้นและจุดสิ้นสุดของความลึกที่เราวาดได้ในฉาก
//glMatrixMode(GL_PROJECTION) ระบุว่าโค้ดสองบรรทัดถัดไปจะส่งผลต่อเมทริกซ์การฉายภาพ
//เมทริกซ์การฉายภาพมีหน้าที่ในการเพิ่มมุมมองให้กับฉากของเรา
//glLoadIdentity() คล้ายกับการรีเซ็ต จะคืนค่าสถานะเมทริกซ์ที่เลือกไปเป็นสถานะดั้งเดิม
//หลังจากเรียก glLoadIdentity() เราก็กำหนดมุมมองของฉาก
glMatrixMode(GL_PROJECTION); //เลือกเมทริกซ์การฉายภาพ
glLoadIdentity(); // รีเซ็ตเมทริกซ์การฉายภาพ
gluPerspective(45.0, ความกว้าง / ความสูง, 0.1, 100.0); // คำนวณสัดส่วนลักษณะของหน้าต่าง
//glMatrixMode(GL_MODELVIEW) ระบุว่าการเปลี่ยนแปลงใหม่ใดๆ จะส่งผลต่อเมทริกซ์ modelview (เมทริกซ์การสังเกตแบบจำลอง)
//ข้อมูลวัตถุของเราถูกเก็บไว้ในเมทริกซ์การสังเกตแบบจำลอง
glMatrixMode(GL_MODELVIEW); //เลือกเมทริกซ์การสังเกตแบบจำลอง
glLoadIdentity(); //รีเซ็ตเมทริกซ์การสังเกตโมเดล
//หากคุณยังไม่เข้าใจว่าคำเหล่านี้หมายถึงอะไร ไม่ต้องกังวล
//รู้แค่ว่าต้องทำแบบนี้ถ้าอยากได้ฉากเปอร์สเป็คทีฟที่ยอดเยี่ยม
จบ;
//================================================ ==============================
// ทำการตั้งค่าทั้งหมดสำหรับ OpenGL ตั้งค่าสีเพื่อล้างหน้าจอ, เปิดแคชความลึก,
// เปิดใช้งานการแรเงาที่ราบรื่น (การปรับเงาให้เรียบ) ฯลฯ รูทีนนี้จะไม่ถูกเรียกจนกว่าจะสร้างหน้าต่าง OpenGL
// กระบวนการนี้จะมีการคืนค่า แต่การเริ่มต้นที่นี่ไม่ได้ซับซ้อนขนาดนั้น และยังไม่จำเป็นต้องกังวลเกี่ยวกับค่าที่ส่งคืน
//================================================ ==============================
ขั้นตอน glInit();
เริ่ม
//ตั้งค่าสีที่ใช้เมื่อล้างหน้าจอ หากคุณไม่แน่ใจว่าสีทำงานอย่างไร ต่อไปนี้เป็นคำอธิบายสั้นๆ
//ค่าสีอยู่ในช่วงตั้งแต่ 0.0f ถึง 1.0f 0.0f หมายถึงสถานการณ์ที่มืดมนที่สุด และ 1.0f คือสถานการณ์ที่สว่างที่สุด
//พารามิเตอร์ตัวแรกหลังจาก glClearColor คือ Red Intensity (ส่วนประกอบสีแดง) พารามิเตอร์ตัวที่สองคือสีเขียว และพารามิเตอร์ตัวที่สามคือสีน้ำเงิน
//ค่าสูงสุดคือ 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 เกือบทั้งหมดที่แสดงฉาก 3 มิติบนหน้าจอใช้บัฟเฟอร์เชิงลึก การเรียงลำดับจะกำหนดว่าวัตถุใดจะถูกวาดก่อน
//วิธีนี้จะทำให้คุณไม่ต้องวาดรูปสี่เหลี่ยมหลังวงกลมลงบนวงกลม บัฟเฟอร์ความลึกเป็นส่วนสำคัญของ 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 หรือ GL_DEPTH_BUFFER_BIT); // ล้างหน้าจอและบัฟเฟอร์ความลึก
glLoadIdentity(); //รีเซ็ตเมทริกซ์การสังเกตโมเดลปัจจุบัน
จบ;
ฟังก์ชั่น WndProc(hWnd: HWND; // หมายเลขอ้างอิงของหน้าต่าง
ข่าวสารเกี่ยวกับ: UINT; // ข้อความหน้าต่าง
wParam: WPARAM; // เนื้อหาข้อความเพิ่มเติม
lParam: LPARAM // เนื้อหาข้อความเพิ่มเติม
): LRESULT; stdcall;
เริ่ม
ผลลัพธ์ := 0;
Case (Msg) Of // ตรวจสอบข้อความ Windows
WM_ACTIVATE: // ตรวจสอบข้อความการเปิดใช้งานหน้าต่าง
เริ่ม
จบ;
WM_CREATE: // สร้าง
เริ่ม
จบ;
WM_CLOSE: // ปิด
เริ่ม
PostQuitMessage(0); //ส่งข้อความออก
ผลลัพธ์ := 0
จบ;
WM_KEYDOWN: // กดปุ่ม
เริ่ม
ปุ่ม [wParam] := True; // ถ้าใช่ ให้ตั้งค่าเป็น TRUE
ผลลัพธ์ := 0;
จบ;
WM_KEYUP: // ปล่อยกุญแจ
เริ่ม
คีย์[wParam] := False; // ถ้าใช่ ให้ตั้งค่าเป็น FALSE
ผลลัพธ์ := 0;
จบ;
WM_SIZE: //ปรับขนาดหน้าต่าง OpenGL
เริ่ม
glResizeWnd(LOWord(lParam), HIWORD(lParam)); //LoWord=ความกว้าง,HiWord=ความสูง
ผลลัพธ์ := 0;
จบ;
WM_TIMER: //ตัวจับเวลา
เริ่ม
จบ;
อื่น //ให้ Windows จัดการส่วนที่เหลือ
ผลลัพธ์ := DefWindowProc(hWnd, Msg, wParam, lParam); // ส่งข้อความที่ยังไม่ได้ประมวลผลทั้งหมดไปยัง DefWindowProc
จบ;
จบ;
//================================================ ==============================
// เรียกก่อนที่โปรแกรมจะออกเท่านั้น ฟังก์ชันนี้คือการปล่อยตารางบริบทการระบายสี ตารางบริบทของอุปกรณ์ และตัวจัดการหน้าต่างตามลำดับ
// เพิ่มการตรวจสอบข้อผิดพลาดมากมาย หากโปรแกรมไม่สามารถทำลายส่วนใดส่วนหนึ่งของหน้าต่างได้ ข้อความแสดงข้อผิดพลาดที่เหมาะสมจะปรากฏขึ้น
// หน้าต่างข้อความ
//================================================ ==============================
ขั้นตอน glKillWnd (เต็มหน้าจอ: บูลีน);
เริ่ม
//สิ่งแรกที่ทำใน KillGLWindow() คือการตรวจสอบว่าอยู่ในโหมดเต็มหน้าจอหรือไม่
//ถ้าใช่ ให้สลับกลับไปที่เดสก์ท็อป หน้าต่างควรถูกทำลายก่อนที่จะปิดใช้งานโหมดเต็มหน้าจอ
//แต่การทำเช่นนี้กับการ์ดกราฟิกบางรุ่นอาจทำให้เดสก์ท็อปเสียหายได้ ดังนั้นจึงควรปิดการใช้งานโหมดเต็มหน้าจอก่อน
//ซึ่งจะป้องกันการล่มของเดสก์ท็อปและใช้งานได้ดีกับทั้งการ์ดกราฟิก Nvidia และ 3dfx!
ถ้าเต็มหน้าจอแล้ว // ในโหมดเต็มหน้าจอ?
เริ่ม
// ใช้ ChangeDisplaySettings(NULL,0) เพื่อกลับสู่เดสก์ท็อปเดิม
// ใช้ NULL เป็นพารามิเตอร์แรก
// การส่งผ่าน 0 เป็นพารามิเตอร์ตัวที่สองบังคับให้ Windows ใช้ค่าที่เก็บไว้ในรีจิสทรีในปัจจุบัน
// (ความละเอียดเริ่มต้น ความลึกของสี อัตรารีเฟรช ฯลฯ) เพื่อคืนค่าเดสก์ท็อปดั้งเดิมของฉันอย่างมีประสิทธิภาพ
// หลังจากเปลี่ยนกลับไปเป็นเดสก์ท็อปแล้ว ต้องทำให้ตัวชี้เมาส์มองเห็นได้อีกครั้ง
ChangeDisplaySettings(devmode(Nil^), 0); // ถ้าใช่ ให้เปลี่ยนกลับไปใช้เดสก์ท็อป
ShowCursor(จริง); //แสดงเมาส์
จบ;
//ไม่ว่าจะมีตารางคำอธิบายการระบายสี (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) และ (ไม่ DestroyWindow(h_Wnd))) แล้ว
เริ่ม
MessageBox(0, 'ไม่สามารถทำลายแบบฟอร์มได้!', 'ข้อผิดพลาด', MB_OK Or
MB_ICONERROR);
h_Wnd := 0;
จบ;
//ออกจากระบบคลาสหน้าต่าง
//สิ่งนี้ทำให้เราสามารถทำลายหน้าต่างได้ตามปกติแล้วเปิดหน้าต่างอื่น ๆ
// คุณจะไม่ได้รับข้อความแสดงข้อผิดพลาดเช่น "ลงทะเบียนคลาส Windows แล้ว" (ลงทะเบียนคลาสหน้าต่างแล้ว)
ถ้า (ไม่ใช่ UnRegisterClass ('OpenGL', hInstance)) จากนั้น
เริ่ม
MessageBox(0, 'ไม่สามารถออกจากระบบคลาสหน้าต่างได้!', 'ข้อผิดพลาด', MB_OK หรือ
MB_ICONERROR);
อินสแตนซ์ := 0;
จบ;
จบ;