Bộ xử lý trung tâm (CPU) và Bộ xử lý đồ họa (GPU) của máy tính tương tác với nhau mọi khoảnh khắc bạn đang sử dụng máy tính của mình để mang đến cho bạn giao diện hình ảnh sắc nét và nhanh nhạy. Đọc tiếp để hiểu rõ hơn về cách chúng hoạt động cùng nhau.
ảnh chụp bởi sskennel .
Phiên Hỏi & Đáp hôm nay đến với chúng tôi với sự hỗ trợ của SuperUser — một phân nhánh của Stack Exchange, một nhóm các trang web Hỏi & Đáp do cộng đồng thúc đẩy.
Câu hỏi
Độc giả của SuperUser Sathya đặt câu hỏi:
Ở đây bạn có thể thấy ảnh chụp màn hình của một chương trình C ++ nhỏ có tên là Triangle.exe với một hình tam giác xoay dựa trên API OpenGL.
Phải thừa nhận là một ví dụ rất cơ bản nhưng tôi nghĩ nó có thể áp dụng cho các hoạt động của thẻ đồ họa khác.
Tôi chỉ tò mò và muốn biết toàn bộ quá trình từ việc nhấp đúp vào Triangle.exe trong Windows XP cho đến khi tôi có thể thấy hình tam giác xoay trên màn hình. Điều gì xảy ra, CPU (cái đầu tiên xử lý .exe) và GPU (cái cuối cùng xuất ra hình tam giác trên màn hình) tương tác như thế nào?
Tôi đoán liên quan đến việc hiển thị tam giác xoay này chủ yếu là phần cứng / phần mềm sau đây trong số những thứ khác:
Phần cứng
- HDD
- Bộ nhớ hệ thống (RAM)
- CPU
- Bộ nhớ video
- GPU
- Màn hình LCD
Phần mềm
- Hệ điều hành
- API DirectX / OpenGL
- Nvidia Driver
Bất cứ ai có thể giải thích quá trình, có thể với một số loại lưu đồ để minh họa?
Nó không phải là một lời giải thích phức tạp bao hàm từng bước đơn lẻ (đoán rằng sẽ vượt ra ngoài phạm vi), nhưng một lời giải thích mà một anh chàng IT trung cấp có thể làm theo.
Tôi khá chắc rằng nhiều người thậm chí tự gọi mình là chuyên gia CNTT không thể mô tả chính xác quá trình này.
Câu trả lời
Mặc dù nhiều thành viên cộng đồng đã trả lời câu hỏi, Oliver Salzburg đã đi xa hơn và trả lời câu hỏi đó không chỉ bằng một câu trả lời chi tiết mà còn cả đồ họa đi kèm tuyệt vời.
Hình ảnh của JasonC, có sẵn làm hình nền ở đây .
Anh ấy viết:
Tôi quyết định viết một chút về khía cạnh lập trình và cách các thành phần nói chuyện với nhau. Có thể nó sẽ làm sáng tỏ một số lĩnh vực nhất định.
Sự trình bày
Điều gì cần làm để thậm chí có một hình ảnh duy nhất mà bạn đã đăng trong câu hỏi của mình, được vẽ trên màn hình?
Có nhiều cách để vẽ hình tam giác trên màn hình. Để đơn giản, giả sử không có bộ đệm đỉnh nào được sử dụng. (A bộ đệm đỉnh là một vùng bộ nhớ nơi bạn lưu trữ tọa độ.) Giả sử chương trình chỉ đơn giản nói với đường ống xử lý đồ họa về mọi đỉnh đơn lẻ (một đỉnh chỉ là một tọa độ trong không gian) liên tiếp.
Nhưng , trước khi chúng ta có thể vẽ bất cứ thứ gì, trước tiên chúng ta phải chạy một số giàn giáo. Chúng ta sẽ thấy tại sao một lát sau:
// Xóa màn hình và bộ đệm độ sâu glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Đặt lại Ma trận Chế độ xem Mô hình Hiện tại glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Vẽ bằng hình tam giác glBegin (GL_TRIANGLES); // Đỏ glColor3f (1,0f, 0,0f, 0,0f); // Đỉnh Tam giác (Mặt trước) glVertex3f (0,0f, 1,0f, 0,0f); // Màu xanh lá glColor3f (0,0f, 1,0f, 0,0f); // Left Of Triangle (Mặt trước) glVertex3f (-1.0f, -1.0f, 1.0f); // Màu xanh da trời glColor3f (0.0f, 0.0f, 1.0f); // Right Of Triangle (Mặt trước) glVertex3f (1.0f, -1.0f, 1.0f); // Vẽ xong glEnd ();
Vậy điều đó đã làm được gì?
Khi bạn viết một chương trình muốn sử dụng cạc đồ họa, bạn thường sẽ chọn một số loại giao diện cho trình điều khiển. Một số giao diện nổi tiếng cho trình điều khiển là:
- OpenGL
- Direct3D
- MIRACLES
Đối với ví dụ này, chúng tôi sẽ gắn bó với OpenGL. Bây giờ, của bạn giao diện với trình điều khiển là thứ cung cấp cho bạn tất cả các công cụ bạn cần để tạo chương trình của mình nói chuyện vào cạc đồ họa (hoặc trình điều khiển, sau đó cuộc nói chuyện vào thẻ).
Giao diện này chắc chắn cung cấp cho bạn công cụ . Những công cụ này có hình dạng NGỌN LỬA mà bạn có thể gọi từ chương trình của mình.
API đó là những gì chúng ta thấy đang được sử dụng trong ví dụ trên. Chúng ta hãy xem xét kỹ hơn.
Giàn giáo
Trước khi bạn thực sự có thể thực hiện bất kỳ bản vẽ thực tế nào, bạn sẽ phải thực hiện thiết lập . Bạn phải xác định khung nhìn của mình (khu vực thực sự sẽ được hiển thị), phối cảnh của bạn ( camera vào thế giới của bạn), bạn sẽ sử dụng tính năng khử răng cưa nào (để làm mịn các cạnh của tam giác)…
Nhưng chúng tôi sẽ không xem xét bất kỳ điều gì trong số đó. Chúng tôi sẽ chỉ xem qua những việc bạn sẽ phải làm mọi khung hình . Giống:
Xóa màn hình
Đường ống đồ họa sẽ không xóa màn hình cho bạn mọi khung hình. Bạn sẽ phải nói điều đó. Tại sao? Đây là lý do tại sao:
Nếu bạn không xóa màn hình, bạn sẽ đơn giản
vẽ qua
nó mọi khung hình. Đó là lý do tại sao chúng tôi gọi
glClear
với
GL_COLOR_BUFFER_BIT
bộ. Các bit khác (
GL_DEPTH_BUFFER_BIT
) yêu cầu OpenGL xóa
chiều sâu
đệm. Bộ đệm này được sử dụng để xác định pixel nào ở phía trước (hoặc phía sau) các pixel khác.
Chuyển đổi
Chuyển đổi là phần mà chúng ta lấy tất cả các tọa độ đầu vào (các đỉnh của tam giác) và áp dụng ma trận ModelView của chúng ta. Đây là ma trận mà giải thích của chúng tôi như thế nào mô hình (các đỉnh) được xoay, chia tỷ lệ và dịch (di chuyển).
Tiếp theo, chúng tôi áp dụng ma trận chiếu của chúng tôi. Thao tác này di chuyển tất cả các tọa độ để chúng đối mặt với máy ảnh của chúng tôi một cách chính xác.
Bây giờ chúng ta biến đổi một lần nữa, với ma trận Viewport của chúng ta. Chúng tôi làm điều này để mở rộng quy mô mô hình với kích thước của màn hình của chúng tôi. Bây giờ chúng ta có một tập hợp các đỉnh đã sẵn sàng để được hiển thị!
Chúng ta sẽ quay lại chuyển đổi một chút sau.
Đang vẽ
Để vẽ một hình tam giác, chúng ta có thể chỉ cần yêu cầu OpenGL bắt đầu một
danh sách các hình tam giác
bằng cách gọi
glBegin
với
GL_TRIANGLES
không thay đổi.
Ngoài ra còn có các hình thức khác bạn có thể vẽ. Giống một
dải tam giác
hoặc một
quạt tam giác
. Đây chủ yếu là tối ưu hóa, vì chúng yêu cầu ít giao tiếp hơn giữa CPU và GPU để vẽ cùng một lượng hình tam giác.
Sau đó, chúng ta có thể cung cấp một danh sách các bộ 3 đỉnh tạo nên mỗi tam giác. Mọi tam giác đều sử dụng 3 tọa độ (khi chúng ta đang ở trong không gian 3D). Ngoài ra, tôi cũng cung cấp một
màu sắc
cho mỗi đỉnh, bằng cách gọi
glColor3f
trước
kêu gọi
glVertex3f
.
Bóng giữa 3 đỉnh (3 góc của tam giác) được tính bằng OpenGL tự động . Nó sẽ nội suy màu trên toàn bộ mặt của đa giác.
Sự tương tác
Bây giờ, khi bạn nhấp vào cửa sổ. Ứng dụng chỉ phải nắm bắt tin nhắn cửa sổ báo hiệu lần nhấp. Sau đó, bạn có thể chạy bất kỳ hành động nào trong chương trình của mình mà bạn muốn.
Điều này được một nhiều khó hơn khi bạn muốn bắt đầu tương tác với cảnh 3D của mình.
Trước tiên, bạn phải biết rõ người dùng đã nhấp vào cửa sổ ở pixel nào. Sau đó, lấy của bạn Góc nhìn cá nhân đặc biệt, bạn có thể tính toán hướng của một tia, từ điểm nhấp chuột vào cảnh của bạn. Sau đó, bạn có thể tính toán xem có đối tượng nào trong cảnh của bạn giao nhau với tia đó . Bây giờ bạn biết nếu người dùng nhấp vào một đối tượng.
Vì vậy, làm thế nào để bạn làm cho nó xoay?
Chuyển đổi
Tôi biết hai loại biến đổi thường được áp dụng:
- Chuyển đổi dựa trên ma trận
- Biến đổi dựa trên xương
Sự khác biệt là xương ảnh hưởng đến độc thân đỉnh . Ma trận luôn ảnh hưởng đến tất cả các đỉnh được vẽ theo cùng một cách. Hãy xem một ví dụ.
Thí dụ
Trước đó, chúng tôi đã tải ma trận đơn vị trước khi vẽ tam giác của chúng tôi. Ma trận nhận dạng là một ma trận đơn giản cung cấp không biến đổi ở tất cả. Vì vậy, bất cứ điều gì tôi vẽ, chỉ bị ảnh hưởng bởi góc nhìn của tôi. Vì vậy, tam giác sẽ không được xoay ở tất cả.
Nếu tôi muốn xoay nó ngay bây giờ, tôi có thể tự mình làm phép toán (trên CPU) và chỉ cần gọi
glVertex3f
với
khác
tọa độ (được xoay). Hoặc tôi có thể để GPU thực hiện tất cả công việc, bằng cách gọi
glRotatef
trước khi vẽ:
// Xoay Tam giác Trên trục Y glRotatef (amount, 0.0f, 1.0f, 0.0f);
số tiền
tất nhiên, chỉ là một giá trị cố định. Nếu bạn muốn
hoạt hình
, bạn sẽ phải theo dõi
số tiền
và tăng nó lên mỗi khung hình.
Vì vậy, chờ đợi, điều gì đã xảy ra với tất cả các cuộc nói chuyện ma trận trước đó?
Trong ví dụ đơn giản này, chúng ta không cần quan tâm đến ma trận. Chúng tôi chỉ đơn giản gọi
glRotatef
và nó sẽ chăm sóc tất cả những điều đó cho chúng tôi.
glRotatetạo ra một vòng quay củagócđộ xung quanh vectơ x y z. Ma trận hiện tại (xem glMatrixMode ) được nhân với ma trận xoay với tích thay thế ma trận hiện tại, như thể glMultMatrix được gọi với ma trận sau làm đối số của nó:x 2 1 - c + cx y 1 - c - z sx z 1 - c + y s 0 y x 1 - c + z sy 2 1 - c + cy z 1 - c - x s 0 x z 1 - c - y sy z 1 - c + x sz 2 1 - c + c 0 0 0 0 1
Vâng, cảm ơn vì điều đó!
Phần kết luận
Điều trở nên hiển nhiên là, có rất nhiều lời bàn tán đến OpenGL. Nhưng nó không nói chúng ta bất cứ thứ gì. Giao tiếp ở đâu?
Điều duy nhất mà OpenGL nói với chúng ta trong ví dụ này là khi nào nó hoàn thành . Mọi thao tác sẽ mất một khoảng thời gian nhất định. Một số thao tác mất rất nhiều thời gian, những thao tác khác thì cực kỳ nhanh chóng.
Gửi một đỉnh đối với GPU sẽ rất nhanh, tôi thậm chí không biết làm thế nào để diễn đạt nó. Gửi hàng nghìn đỉnh từ CPU đến GPU, mỗi khung hình đơn lẻ, rất có thể không có vấn đề gì.
Xóa màn hình có thể mất một phần nghìn giây hoặc tệ hơn (hãy nhớ rằng bạn thường chỉ có khoảng 16 phần nghìn giây thời gian để vẽ mỗi khung hình), tùy thuộc vào độ lớn của khung nhìn. Để xóa nó, OpenGL phải vẽ từng pixel bằng màu bạn muốn xóa, đó có thể là hàng triệu pixel.
Ngoài ra, chúng tôi chỉ có thể hỏi OpenGL về khả năng của bộ điều hợp đồ họa của chúng tôi (độ phân giải tối đa, khử răng cưa tối đa, độ sâu màu tối đa,…).
Nhưng chúng ta cũng có thể lấp đầy kết cấu bằng các pixel mà mỗi pixel có một màu cụ thể. Do đó, mỗi pixel chứa một giá trị và kết cấu là một “tệp” khổng lồ chứa đầy dữ liệu. Chúng tôi có thể tải nó vào card đồ họa (bằng cách tạo một bộ đệm kết cấu), sau đó tải một shader , yêu cầu trình đổ bóng đó sử dụng kết cấu của chúng tôi làm đầu vào và chạy một số tính toán cực kỳ nặng trên “tệp” của chúng tôi.
Sau đó, chúng tôi có thể "kết xuất" kết quả tính toán của chúng tôi (dưới dạng các màu mới) thành một kết cấu mới.
Đó là cách bạn có thể làm cho GPU hoạt động cho mình theo những cách khác. Tôi cho rằng CUDA hoạt động tương tự như khía cạnh đó, nhưng tôi chưa bao giờ có cơ hội làm việc với nó.
Chúng tôi thực sự chỉ chạm nhẹ vào toàn bộ chủ đề. Lập trình đồ họa 3D là một con quái vật.
Có điều gì đó để thêm vào lời giải thích? Tắt âm thanh trong các bình luận. Bạn muốn đọc thêm câu trả lời từ những người dùng Stack Exchange am hiểu công nghệ khác? Kiểm tra toàn bộ chuỗi thảo luận tại đây .