Direct3D sử dụng surface cho rất nhiều thứ. Màn hình sẽ hiển thị những thứ mà card đồ họa gửi đến nó và card đồ họa sẽ lấy dữ liệu vùng nhớ đệm (frame buffer) và gửi tới màn hình.
Một số khái niệm
Frame buffer / Front buffer (bề mặt chính): là một vùng trên bộ nhớ được bộ xử lý hiển thị trực tiếp lên màn hình. Trong Direct3D, các chương trình sẽ không được thao tác trực tiếp lên Front buffer. Frame buffer được back buffer sao chép lên trong mỗi vòng lặp.
Back buffer: là một vùng trên bộ nhớ, các chương trình có thể thao tác trực tiếp lên đây hoặc sao chép từ surface khác. Back buffer sẽ không hiển thị trực tiếp lên màn hình.
Surface (off-screen surface) là một bề mặt thứ cấp được lưu trữ trong bộ nhớ của card đồ họa hoặc có thể trong bộ nhớ của hệ thống. Chúng ta có thể thực hiện nhiều thao tác như vẽ bitmap, load ảnh. Surface có thể ra tạo bao nhiêu cũng được miễn là còn đủ RAM và VRAM để chứa tất cả.
Cách hoạt động:
Card đồ họa sẽ chứa thông tin mà chúng ta muốn hiển thị lên màn hình. Khi bạn muốn hiển thị thứ gì đó, card đồ họa sẽ lấy dữ liệu cần hiển thị tại vùng nhớ đệm được gọi là Front buffer (Frame buffer) sau đó sẽ gửi những thông tin đã lấy được đến màn hình để hiển thị. Màn hình sẽ cập nhật những phần mới và vẽ lại từ trên xuống dưới.
Front buffer nằm ở bộ nhớ đồ họa và biểu thị hình ảnh lên màn hình. Do đó, để thay đổi hiển thị trên màn hình theo ý muốn, cách đơn giản nhất là thay đổi trực tiếp dữ liệu trên Front buffer. Tuy nhiên, chúng ta sẽ không muốn vẽ trực tiếp lên Front buffer vì màn hình sẽ bị giật lag khi ta vẽ. Hiện tượng xảy ra là do một chương trình nào đó cập nhật trên Front buffer trong khi màn hình đang trong quá trình refresh. Cách giải quyết là ta sẽ vẽ mọi thứ lên một vùng nhớ ngoài màn hình chính là back buffer (double buffer) và chuyển nó lên màn hình rất nhanh. Kỹ thuật này người ta gọi là “double buffering”.
Dưới đây là hình minh họa cho khái niệm “double buffering”
Tạo surface
Vẽ lên surface
Để vẽ một surface lên một surface ta dùng hàm StretchRect.
Hai surface đó phải cùng kích thước. Nếu surface nguồn nhỏ hơn surface đích thì nó sẽ được vẽ tại phía trên - bên trái của surface đích.
Rect nguồn có thể nhỏ hơn rect đích và bạn có thể vẽ surface nguồn lên bất kỳ nơi nào trên surface đích. Ví dụ:
Để lấy con trỏ đến backbuffer ta dùng hàm GetBackBuffer.
Chương trình Create_Surface
Đây là ví dụ minh họa cách dùng ColorFill, StretchRect, GetBackBuffer, cách sử dụng surface, cách kết hợp các hàm trên với nhau. Kết quả chương trình như hình dưới đây:
Tạo một project tên “Create_Surface” và thêm các file vào project “winmain.cpp”. Nhớ thêm thư viện “d3d9.lib”.
Load Bitmap
Cuối cùng là cách tải ảnh bitmap lên surface từ ổ cứng và vẽ nó lên màn hình thông qua backbuffer. Yêu cầu:
Thêm thư viện “d3dx9.lib” (tương tự như thêm d3d9.lib) và thêm “#include .
Hàm cần dùng:
Chương trình Load_Bitmap
Hãy viết một chương trình đơn giản nạp một ảnh bitmap vào surface và vẽ nó lên màn hình. Ta sẽ chỉ thay đổi vãi chỗ so với chương trình Create_Surface, nên chỉ cần thay đổi chỗ cần thay đổi, không cần viết lại toàn bộ code. Nhớ thêm thư viện “d3d9.lib” và “d3dx9.lib”
Đầu tiên ta thêm “#include vào đoạn code như sau:
Đi đến hàm Game_Init và thay đổi để được nội dung sau, phần còn lại không thay đổi:
Thay đổi một chút ở hàm Game_Run:
Kết quả chương trình sẽ hiển thị ảnh theo đường dẫn bạn truyền vào.
Tổng kết
Chúng ta đã cùng nhau tìm hiểu về surface và bitmap, đặc biệt là 2 chương trình Create_Surface và Load_Bitmap…Các bạn hãy luyện tập code lại 2 chương trình này trong bài để nắm và hiểu rõ hơn về cách hoạt động của nó nhé, hơn thế các đoạn code này về sau sẽ sử dụng rất nhiều đến lúc đó các bạn chỉ cần coppy sử dụng lại thôi.😉 Hãy truy cập vào Series Make Game - TuiTuCode để học tiếp những bài thú vị khác nữa. Nếu có thắc mắc các bạn cứ bình luận bên dưới hoặc gửi thắc mắc về page TuiTuCode để các ad giải đáp. Pie~