Thuộc tính OpenGL Vertex - Chuẩn hóa


8

Than ôi, tôi đã tìm kiếm, và không tìm thấy câu trả lời dứt khoát.

Khi nào bạn sẽ bình thường hóa dữ liệu đỉnh trong OpenGL bằng lệnh sau:

glVertexAttribPointer(index, size, type, normalize, stride, pointer);

Tức là khi nào sẽ normalize == GL_TRUE; tình huống nào và tại sao bạn lại chọn để GPU thực hiện các phép tính thay vì tiền xử lý nó? Tất cả các ví dụ tôi đã từng thấy, có bộ này thành GL_FALSE; và cá nhân tôi không thể thấy việc sử dụng nó. Nhưng Khronos không ngu ngốc, vì vậy nó phải ở đó cho một cái gì đó hữu ích (và có thể phổ biến).

Câu trả lời:


9

Tham số "chuẩn hóa" ảnh hưởng đến việc sử dụng các giá trị điểm cố định.

Tài liệu này cho biết tham số "Chỉ định liệu các giá trị dữ liệu điểm cố định sẽ được chuẩn hóa (GL_TRUE) hoặc được chuyển đổi trực tiếp dưới dạng giá trị điểm cố định (GL_FALSE) khi chúng được truy cập."

Hơn nữa, điều này nói "Đối với glVertexAttribPulum, nếu chuẩn hóa được đặt thành GL_TRUE, nó chỉ ra rằng các giá trị được lưu trữ ở định dạng số nguyên sẽ được ánh xạ tới phạm vi [-1,1] (đối với các giá trị đã ký) hoặc [0,1] ( đối với các giá trị không dấu) khi chúng được truy cập và chuyển đổi thành dấu phẩy động. Nếu không, các giá trị sẽ được chuyển đổi thành float trực tiếp mà không cần chuẩn hóa. "

Tóm lại, nếu bạn không sử dụng các giá trị điểm cố định, bạn không cần phải quan tâm. Nếu bạn làm như vậy, cờ này sẽ kiểm soát xem (ví dụ) giá trị byte 128 nên là 0,5 hay 128.0.


3
Điều này không thực sự trả lời câu hỏi, tôi đã hiểu những gì nó làm, nhưng tôi muốn biết khi nào nó thực sự sẽ được áp dụng để thực hiện 'chung'.
giảm tốc

2
Tôi khá chắc chắn rằng nó có liên quan trở lại khi nhiều ứng dụng di động sử dụng toán học điểm cố định chủ yếu và không muốn chạm vào toán học dấu phẩy động. Một khả năng khác là đôi khi bạn có thể muốn lưu trữ dữ liệu theo cách gọn hơn, tính bằng byte, nếu độ chính xác là đủ và để OpenGL chuyển đổi các byte thành phạm vi 0..1.
Jari Komppa

Nó vẫn có liên quan. Hãy nghĩ về coords UV chẳng hạn. Bạn có thể không muốn lãng phí dung lượng và lưu trữ dưới dạng float2, vì vậy bạn lưu trữ dưới dạng 2 uint8 thay vào đó để tối ưu hóa và đặt cờ chuẩn hóa để bạn sẽ nhận được phạm vi [0, 1] thay vì [0, 256] trong chương trình.
khoảng trống

Là 128 sẽ trở thành 0,5 hoặc 128/255 = cao hơn một chút?
RIV

11

Đây là một câu hỏi cũ, nhưng câu trả lời hiện tại không thực sự giải thích bạn sẽ sử dụng chúng để làm gì.

Đó là tất cả về tiết kiệm không gian. Và với các thuộc tính đỉnh, ít không gian hơn có thể có nghĩa là hiệu suất cao hơn (nếu bạn bị ràng buộc chuyển giao đỉnh).

Màu sắc thường không cần nhiều hơn 8 bit cho mỗi thành phần. Đôi khi bạn cần 16 bit, nếu đó là giá trị ánh sáng HDR hoặc thứ gì đó. Nhưng đối với các đặc điểm bề mặt (đó là những gì hầu hết các thuộc tính đỉnh), 8 bit là tốt. Vì vậy, byte chuẩn hóa không dấu là một định dạng đỉnh tốt.

Các tọa độ kết cấu không cần độ chính xác của dấu phẩy động 32 bit. Giá trị 16 bit từ [0, 1] là đủ. Vì vậy, quần short không dấu bình thường là một định dạng đỉnh hợp lý.

Định mức không bao giờ cần 32 bit chính xác. Họ chỉ đường. Các byte được chuẩn hóa 8 bit có xu hướng hơi nhỏ, nhưng hầu hết các giá trị chuẩn hóa 10 bit là đủ tốt trong hầu hết thời gian. OpenGL (3.3+) thậm chí cho phép bạn sử dụng các định mức 10 bit thông qua định dạng đóng gói 10/10/10/2 bit, được lưu trữ trong một số nguyên không dấu 32 bit.

Bạn thậm chí có thể chơi các trò chơi với các vị trí đỉnh, nếu bạn thấy mình cần nhiều bộ nhớ hơn.

Nếu không chuẩn hóa, bạn sẽ phải lãng phí các chu kỳ quý giá trong shader chia các thuộc tính byte cho 255.0. Tại sao làm điều này, khi phần cứng có thể làm điều đó miễn phí?


Một câu trả lời tốt đẹp. Nhưng liệu chi phí của phép toán dấu phẩy động phân chia có thể so sánh với mức giảm kích thước bình thường là 50%? (Tức là 32 bit để nói 16 bit); trên phần cứng HIỆN ĐẠI. Đặc biệt là, chúng tôi thực sự không cần phải lo lắng về quá nhiều bộ nhớ (ít nhất là trong trường hợp của tôi).
giảm tốc

1
@Daniel: Chà, hãy nghĩ về nó. Trên "phần cứng HIỆN ĐẠI", chi phí chuyển các giá trị chuẩn hóa là ... không. Chi phí hoạt động của bộ phận trong shader là ... khác không. Cho dù nó nhỏ đến mức nào, nó vẫn lớn hơn không. Chưa kể đến việc tiết kiệm băng thông khi gửi một khối dữ liệu đỉnh 32 byte thay vì khối 64 + -byte. Ồ, và shader không cần phải được lập trình đặc biệt; bạn có thể sử dụng cùng một shader để lấy các giá trị chuẩn hóa hoặc float. Nếu bạn đặt phân chia trong trình đổ bóng, bây giờ bạn cần các trình tạo bóng mới cho các kích thước khác nhau của dữ liệu đỉnh.
Nicol Bolas

Cảm ơn câu trả lời tốt đẹp. Tôi chắc chắn sẽ ghi nhớ nó, hiện tại không cần thiết vì tôi đang gửi dữ liệu đỉnh được căn chỉnh, nhưng khi tôi thêm thông tin thì nó có thể không giống nhau, và điều này có thể là một lợi ích tuyệt vời, cả trong bộ nhớ đệm và thông lượng.
giảm tốc

Bất kỳ chiến lược nào về cách chuyển đổi bình thường (được lưu trữ trong một chuỗi (3x) 32 bit nổi) thành int 32 bit (10/10/10/2)?
giảm tốc

@Daniel: Nếu bạn đang hỏi cách sử dụng tiện ích mở rộng ARB_vertex_type_2_10_10_10_Vv , thì tôi khuyên bạn nên đọc thông số tiện ích mở rộng mà tôi vừa liên kết. Nếu bạn đang hỏi cách cá nhân thực hiện thao tác bit, tôi sẽ đề xuất cấu trúc kiểu C có chứa các trường bit .
Nicol Bolas

0

Hãy tưởng tượng bạn có một lưới với các thông số chính xác cao và một lưới khác với mức thấp. Với chuẩn hóa thuộc tính, bạn có thể sử dụng cùng một shader nhưng đóng gói các quy tắc của lưới thứ hai theo byte.

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.