Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Lập Trình Bash

Tích Hợp OpenGL Với Bash: Binding Cập Nhật Và Tài Liệu

Trong bài viết trước mô tả thiết kế Perl 5 và sự phù hợp như "ngôn ngữ keo" (glue language), tôi nhắc đến việc trước đây đã viết binding OpenGL cho Bash. Điều này có lẽ quá khó tin để nói không bằng chứng, nên tôi quay lại góc bụi ổ cứng, đào nó ra, làm mới một chút, cải thiện hỗ trợ font, viết tài liệu, và xuất bản trên trang web và GitHub. (Bạn cần hệ thống có cả Bash và hỗ trợ OpenGL để trải nghiệm trực tiếp, nhưng đây là video.)

Vậy là lời khai của tôi: Đồ họa Perl trong bảng điều khiển DeLorean tôi mô tả trong My DeLorean runs Perl chia sẻ lịch sử với dự án OpenGL cho Bash. Trong một sự ngẫu nhiên thú vị, tôi bắt đầu dự án 13 năm trước sau khi chứng kiến Frozen Bubble và cảm thấy xúc phạm về mặt kỹ thuật khi ai đó viết game video real-time bằng Perl. Lúc đó, ngôn ngữ chính của tôi là C++, và tôi học OpenGL cho mục đích game. Tôi tuyên bố với bạn bè rằng điều tệ hơn chỉ có nếu nó là 3D và viết bằng Bash. Nói ý tưởng đó lớn ra, nó cứ móc tôi, và cuối cùng tôi quyết định thử để "vượt mức tệ hại" của việc dùng Perl cho đồ họa real-time.

Mở Rộng Bash

Cách trực tiếp nhất thêm hỗ trợ OpenGL vào Bash là sửa mã nguồn và thêm mỗi hàm OpenGL như "builtin" shell; tuy nhiên, chỉ những người sẵn sàng cài bản Bash tùy chỉnh mới trải nghiệm được, và có lẽ không ai muốn. Nó cũng không theo tinh thần làm việc "the Bash way".

Tôi nghĩ ra ý tưởng client-server, nơi mỗi hàm OpenGL được cài trong PATH và gọi client kết nối đến server OpenGL để truyền thông điệp thực thi hàm đó. Đó sẽ là giải pháp "tệ hại" thú vị, nhưng không importa tối ưu hóa thế nào, vẫn quá chậm để tôi nói thành công mục tiêu tổng thể.

Cuối cùng, tôi chọn thiết kế có một tiến trình "OpenGL Interpreter" đọc lệnh OpenGL trên standard-in và ghi sự kiện đầu vào người dùng ra standard-out. Sau đó script Bash có thể khởi động interpreter này kết nối với pipe, và mỗi lệnh OpenGL có thể là hàm Bash ghi vào pipe. Trong lúc đó, tôi quyết định tung cả túi mẹo hiệu quả và viết interpreter bằng C thuần túy với bảng băm tĩnh và cây đỏ-đen (red-black trees).

Chế Độ Ngay Lập (Immediate Mode) OpenGL

Chi tiết OpenGL là nơi dự án bắt đầu giao với dự án bảng điều khiển DeLorean. Đầu tiên, tôi lùi lại và tóm tắt API OpenGL.

OpenGL về việc viết chương trình lên kế hoạch đồ họa dưới dạng tọa độ 3D và texture, sau đó chuyển dữ liệu đó sang card đồ họa để render ra màn hình 2D. Để đơn giản hóa, có tập toán học mô tả vùng màn hình đang vẽ, và tập toán học mô tả màu mỗi pixel trong vùng đó.

Hoạt động phổ biến nhất là mô tả ba góc tam giác trong không gian 3D ảo, để OpenGL tính vị trí trên màn hình 2D, rồi nói nó kéo giãn hình 2D qua khu vực đó, có thể kết hợp hình khác hoặc thay đổi bằng tính toán độ sáng. Vòng lặp chính của chương trình tạo một khung video bằng cách xóa buffer, vẽ mọi polygon thấy được, và gửi đến màn hình. Nếu kéo cả trò này trong 16 mili-giây hoặc ít hơn, bạn duy trì 60 FPS và có đồ họa mượt.

Tôi không nói được với thẩm quyền về nguồn gốc API OpenGL, nhưng rõ ràng nó xây quanh ý tưởng streaming, có thể để tương thích giao thức hiển thị X11, nhưng cũng chỉ vì ý tưởng tốt. Vì vậy, hầu hết hàm OpenGL không có giá trị trả về, khác với API khác nơi mỗi lời gọi hàm trả về trạng thái cho biết kết quả hoạt động. Nếu hình dung hàm OpenGL như glVertex3f(1,2,3) như câu lệnh in ghi ba số qua pipe, bạn có ý tưởng khá tốt cách nó hoạt động bên dưới. Thực tế, cho binding Bash, tôi thực sự ghi glVertex 1 2 3 qua pipe khi glVertex 1 2 3 thực thi. Script Bash chạy mù, không biết lệnh đồ họa có làm gì như ý định.

Có vài bản sửa đổi lớn API OpenGL qua các năm, và người ta viết cả chương trong sách về chế độ "retained" vs "immediate", nhưng tất cả归结为 hai khái niệm:

  • Chậm để gửi lại tất cả dữ liệu qua pipe mỗi khung, nên cache một phần ở đầu kia.
  • Không bao giờ thỏa mãn nhu cầu mọi người với toán học tích hợp, nên cho người ta ngôn ngữ mô tả toán học tùy chỉnh.

Điều đó nói, dù caching và toán học tùy chỉnh của API OpenGL mới hiệu quả hơn nhiều và chắc chắn cần cho game top-tier, chúng cũng nỗ lực hơn để thiết lập và làm việc (và học) và có thể hại hơn tốt cho người chơi. Chúng cũng không cần trừ khi làm hiệu ứng đồ họa nâng cao hoặc mô hình chi tiết cao.

Vì vậy, mặc dù binding Bash OpenGL chỉ xử lý API "deprecated" (lỗi thời), tôi vẫn khuyến khích mọi người xem xét nó cho mục đích giáo dục và thử nghiệm.

Display Lists (Danh Sách Hiển Thị)

May mắn thay, API OpenGL gốc có cơ chế caching, và chúng dễ dùng. Chúng hoạt động đại khái theo trình tự:

"Này OpenGL, tôi muốn bạn tạo đối tượng 37 ở đầu kia"

"Đây là dữ liệu mô tả đối tượng 37"

"Dùng đối tượng 37 trong các bước render tiếp theo"

Để dễ hơn, binding Bash cho phép dùng tên thay vì số.

Loại đối tượng chính đầu tiên là texture (kết cấu), nơi bạn nạp hình 2D vào card đồ họa và sau đó "sơn" polygon với nó. Loại thứ hai là "display list", nơi bạn ghi chuỗi lệnh OpenGL, sau đó phát lại như thể chúng là một lệnh OpenGL đơn.

Display lists rất tốt cho prototyping ad-hoc. Bạn có thể vẽ một số điểm mô hình 3D (hoặc 2D) dùng lệnh vertex đơn giản, sau đó ghi chuỗi điểm đó làm display list, và bây giờ bạn có thể render mô hình đó với một lệnh đơn.

Ví dụ về sức mạnh này, xem Robot.sh trong thư mục Examples. Nó tạo một display list cho mỗi đoạn cơ thể robot khi khởi động, và khi chạy, nó chỉ phát 58 dòng văn bản mỗi khung để render robot. Bash dễ dàng tạo 58 dòng văn bản trong 16 mili-giây (cả 12 năm trước cũng được), nên demo chạy toàn tốc trên phần cứng phổ biến.

Display lists là thủ thuật chính tôi mang sang đồ họa Perl dùng trong phần mềm bảng điều khiển DeLorean. Lời gọi hàm Perl hơi đắt so với C, đặc biệt cho API nhiều hàm như OpenGL 1.4, nhưng bằng cách gộp vào display lists, Perl không có nhiều việc mỗi khung video. Nếu không học thủ thuật này cho dự án Bash, dự án Perl không thành công như vậy.

Tại Sao Tôi Không Xuất Bản 12 Năm Trước?

Mặc dù tạo được demo hoạt hình chốc lẹ trong Bash, mục tiêu thực sự là tạo game hoàn chỉnh. Tôi nhắm đến clone game mô phỏng bay cũ Terminal Velocity, và tiến xa đến tàu vũ trụ bay qua trường lập phương (xem Flight.sh trong Examples), nhưng vấn đề tiếp theo là phát hiện va chạm. Các nguyên ngữ trong Bash là "mảng liên kết" toàn cục tên biến và biến mảng (mặc dù phiên bản 4 có associative-array variables), và mọi toán học là số nguyên. Mặc dù tôi làm được xoay ma trận 3D bằng toán học điểm cố định số nguyên, cài đặt phát hiện va chạm trông như chướng ngại vật quá lớn. Tôi cũng không hài lòng với API font. Trong khi suy nghĩ giải pháp, dự án dần rơi khỏi danh sách.

Đây là nơi tôi kết luận (như viết), "Bash là ngôn ngữ keo tồi tệ." Dự án này bắt đầu và kết thúc như đùa (hoặc công cụ giáo dục, có lẽ), nhưng cùng phong cách chương trình trong Perl hóa ra khá hữu ích cho ứng dụng thực. Nếu tôi xem xét Frozen Bubble nghiêm túc hơn 13 năm trước, tôi có thể bắt đầu sớm với Perl, ngôn ngữ yêu thích nay.

Tôi không có kế hoạch nâng cấp dự án này ngoài sửa lỗi, nhưng tôi nghĩ nó ít nhất hữu ích cho người muốn học khái niệm OpenGL hoặc ai đó có nhiều thời gian rảnh và khát khao viết bản clone Doom trong M4.

Thưởng thức! Và vui vẻ chuyển tiếp link này, nếu không không ai tin bạn đâu.