Làm cách nào để phát hiện định dạng kết cấu OpenGL nào được hỗ trợ nguyên bản?


10

Ví dụ: cách phát hiện nếu videocard của tôi không hỗ trợ "bgr8" và chuyển đổi nó sang định dạng khác, chẳng hạn như "rgba8" trong chế độ phần mềm.

CẬP NHẬT: Xin lỗi vì sự nhầm lẫn. Câu hỏi này nói thêm về tình huống khi tôi đặt InternalFormat trong glTexImage2D thành một cái gì đó như "bgra8" nhưng videodriver nội bộ chuyển đổi dữ liệu sang định dạng khác, như "rgba8".

Câu trả lời:


11

Câu hỏi của bạn dường như gây nhầm lẫn các khái niệm nhất định, vì vậy hãy lấy những thứ từ đầu. Đây là định nghĩa của hàm glTexImage2D:

void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, void *data );

Có hai điều mà bạn có thể gọi là "định dạng kết cấu". Đầu tiên là internalformattham số. Đây là định dạng thực của hình ảnh khi OpenGL lưu trữ nó. Các formattham số mô tả một phần của định dạng của dữ liệu pixel bạn đang cung cấp với các datatham số.

Nói cách khác, formattypexác định dữ liệu của bạn trông như thế nào. internalformatlà cách bạn nói với OpenGL để lưu trữ dữ liệu của bạn. Hãy để chúng tôi gọi formattype"định dạng chuyển pixel", trong khi đó internalformatsẽ là "định dạng hình ảnh".

Định dạng hình ảnh của một kết cấu không bao giờ có thể là "bgr8". Không có liệt kê định dạng hình ảnh GL_BGR8. Có một enum GL_BGR, nhưng đó là dành cho các định dạng chuyển pixel, không phải là định dạng hình ảnh.

Hoặc nói cách khác, dữ liệu pixel mà bạn cung cấp cho OpenGL có thể được lưu trữ theo thứ tự BGR. Nhưng việc triển khai OpenGL tự quyết định cách lưu trữ dữ liệu pixel đó. Có lẽ nó lưu trữ nó theo thứ tự endian nhỏ. Có lẽ nó lưu trữ nó cuối lớn. Có lẽ nó chỉ tùy ý sắp xếp lại các byte. Bạn không biết và OpenGL không cung cấp cách để tìm hiểu.

Không có cách nào để biết liệu một tập hợp các tham số định dạng chuyển pixel cụ thể có khớp với cách triển khai OpenGL sẽ lưu trữ chúng theo định dạng hình ảnh hay không.

một cách để nói bây giờ. Và theo "bây giờ", ý tôi là trong OpenGL 4.3 và / hoặc ARB_iternalformat_query2. Đến với một card đồ họa gần bạn:

GLenum format, type;
glGetInternalformativ(texture_target, GL_RGBA8, GL_TEXTURE_IMAGE_FORMAT, 1, &format);
glGetInternalformativ(texture_target, GL_RGBA8, GL_TEXTURE_IMAGE_TYPE, 1, &type);

formattypebây giờ có ưu tiên thực hiện formattypesử dụng glTex(Sub)Imagecác cuộc gọi đến GL_RGBA8hình ảnh. Có riêng biệt formattypetruy vấn để glReadPixelstải về.

những truy vấn khác bạn có thể thực hiện .

Nếu bạn không có quyền truy cập vào các mục này, bạn có thể sử dụng một số quy tắc chung mà hầu hết phần cứng sẽ tuân thủ:

  • sẽ lưu trữ dữ liệu pixel cho dữ liệu 8 bit trên mỗi kênh theo thứ tự BGRA. Vì vậy, nếu bạn muốn khớp định dạng với dữ liệu pixel của mình, để nhanh chóng tải lên dữ liệu kết cấu, bạn muốn sử dụng GL_BGRAcho formatGL_UNSIGNED_INT_8888hoặc GL_UNSIGNED_BYTEcho type.
  • sẽ không thực sự lưu trữ màu 24 bit dưới dạng 24 bit. Nó sẽ luôn đệm chúng ra 32 bit; alpha sẽ chỉ bị bỏ qua khi nó đọc dữ liệu. Vì vậy, nếu bạn muốn khớp các định dạng, luôn luôn sử dụng GL_BGRA formatvới GL_RGB8các định dạng hình ảnh, ngay cả khi bạn phải đặt dữ liệu giả trong thành phần alpha.

4
Tôi cũng thấy sử dụng định dạng GL_BGRA tốt hơn với InternalFormat GL_RGBA http.doad.nvidia.com/developer/Papers/2005/ trên
KindDragon

Tôi sẽ không đặt lại thương hiệu cho tham số InternalFormat là "định dạng hình ảnh", vì nó khó hiểu như nhau. Có lẽ sẽ hợp lý khi nghĩ "InternalFormat" là "định dạng pixel kết cấu". Kết hợp tham số "định dạng" và "loại" là "định dạng pixel nguồn" (thường là hình ảnh, do đó là nhận xét của tôi). Và dĩ nhiên, có định dạng GPU, đó là BGRA cho các định dạng kiểu số nguyên.
StarShine

6

Nói chung, hầu hết các phần cứng không hỗ trợ các định dạng kết cấu 3 thành phần, vì vậy trong ví dụ cụ thể này, bạn có thể đưa ra một giả định hợp lý an toàn rằng nó được chuyển đổi. Kết cấu OpenGL 3 thành phần thực sự là 4 thành phần trong phần cứng nhưng với thành phần alpha bị bỏ qua / đặt thành 255 / bất cứ thứ gì.

https://www.khronos.org/opengl/wiki/Common_Mistakes#Texture_upload_and_pixel_reads (Trang "lỗi phổ biến" đó là một goldmine - đánh dấu nó ngay bây giờ!)

Đối với trường hợp tổng quát hơn, hiệu suất glTexSubImage2D có thể cho bạn một dấu hiệu tốt về việc liệu việc tải lên có phải đi qua một đường dẫn chuyển đổi phần mềm hay không. Bạn sẽ giải quyết vấn đề này trong quá trình khởi động chương trình - chỉ cần tạo một kết cấu trống (thông qua glTexImage2D với dữ liệu NULL), sau đó đưa ra một loạt các cuộc gọi glTexSubImage2D, mỗi lần theo sau là glFinish để đảm bảo hoàn thành. Bỏ qua cái đầu tiên bởi vì bộ nhớ cache / trạng thái / vv đang được thiết lập cho nó và thời gian còn lại của chúng. Lặp lại điều này cho một vài định dạng khác nhau và chọn nhanh nhất.

Một cách khác - xem như bạn đã gắn thẻ câu hỏi này "Windows" - là tạo một thiết bị D3D khi khởi động (ngay sau khi bạn đã tạo cửa sổ của mình nhưng trước khi bạn khởi tạo OpenGL), sau đó sử dụng D3D để kiểm tra hỗ trợ định dạng. Mặc dù OpenGL cho phép chuyển đổi phần mềm sang định dạng bên trong hợp lệ, D3D không - nếu nó không được phần cứng hỗ trợ, bạn không thể làm điều đó. Sau đó phá hủy D3D và mở OpenGL. (Kỹ thuật này cũng có thể được sử dụng để truy vấn các nội dung khác mà OpenGL không cho phép bạn truy vấn trực tiếp).

Đây thực sự là một quy tắc hữu ích để kiểm tra chéo những gì bạn đang làm trong OpenGL với tài liệu D3D. Nếu D3D không thể làm điều gì đó thì đó có thể là một dấu hiệu tốt cho thấy điều gì đó trong câu hỏi không được hỗ trợ trong phần cứng. Không phải lúc nào cũng đúng, nhưng một nơi bắt đầu hữu ích.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.