Liên kết vị trí thuộc tính rõ ràng so với tự động cho trình tạo bóng OpenGL


82

Khi thiết lập vị trí thuộc tính cho chương trình đổ bóng OpenGL, bạn phải đối mặt với hai tùy chọn:

glBindAttribLocation () trước khi liên kết để xác định rõ ràng một vị trí thuộc tính.

hoặc là

glGetAttribLocation () sau khi liên kết để lấy vị trí thuộc tính được gán tự động.

Tiện ích khi sử dụng cái này hơn cái kia là gì?

Và cái nào, nếu có, được ưa thích hơn trong thực tế?


6
Tôi không bận tâm đến việc sử dụng glBindAttribLocationcông cụ đồ họa của mình, công cụ này hoạt động tốt trên linux. Khi tôi chuyển đến cửa sổ, nó đã được sử dụng normals của tôi như là đỉnh - Tôi phải dứt khoát nói với nó thứ tự của các biến trong shader của tôi qua glBindAttribLocationđể làm cho nó làm việc ...
Jarrett

Câu trả lời:


93

Tôi biết một lý do chính đáng để thích xác định vị trí rõ ràng .

Cân nhắc rằng bạn giữ dữ liệu hình học của mình trong Đối tượng Mảng Vertex. Đối với một đối tượng nhất định, bạn tạo một VAO theo cách mà các chỉ số tương ứng với, ví dụ:

  • chỉ số 0 : vị trí,
  • chỉ số 1 : tiêu chuẩn,
  • chỉ mục 2 : texcoords

Bây giờ hãy xem xét rằng bạn muốn vẽ một đối tượng với hai bóng đổ khác nhau . Một bộ đổ bóng yêu cầu vị trí và dữ liệu bình thường làm đầu vào, bộ còn lại - vị trí và các cuộn kết cấu .

Nếu bạn biên dịch các bộ đổ bóng đó, bạn sẽ nhận thấy rằng bộ đổ bóng đầu tiên sẽ mong đợi các vị trí ở chỉ số thuộc tính 0 và chuẩn ở mức 1. Cái còn lại sẽ mong đợi các vị trí ở 0 nhưng kết cấu ở 1.

Trích dẫn https://www.opengl.org/wiki/Vertex_Shader :

Tuyển tự động

Nếu cả hai phương thức trước đều không gán đầu vào cho chỉ mục thuộc tính thì chỉ mục đó sẽ được OpenGL tự động gán khi chương trình được liên kết. Chỉ mục được gán là hoàn toàn tùy ý và có thể khác đối với các chương trình khác nhau được liên kết, ngay cả khi chúng sử dụng cùng một mã bộ tạo bóng đỉnh.

Điều này có nghĩa là bạn sẽ không thể sử dụng VAO của mình với cả hai trình tạo bóng. Thay vì có một VAO cho mỗi đối tượng, giả sử, bạn cần - trong trường hợp xấu nhất - một VAO riêng biệt cho mỗi đối tượng trên mỗi bộ đổ bóng .

Việc buộc các trình tạo bóng sử dụng quy ước đánh số thuộc tính của riêng bạn thông qua glBindAttribLocationcó thể giải quyết vấn đề này một cách dễ dàng - tất cả những gì bạn cần làm là giữ mối quan hệ nhất quán giữa các thuộc tính và ID đã thiết lập của chúng và buộc các trình tạo bóng sử dụng quy ước đó khi liên kết.

(Đó không thực sự là một vấn đề lớn nếu bạn không sử dụng các VAO riêng biệt, nhưng vẫn có thể làm cho mã của bạn rõ ràng hơn.)


BTW:

Khi thiết lập vị trí thuộc tính cho chương trình đổ bóng OpenGL, bạn phải đối mặt với hai tùy chọn

Có một tùy chọn thứ ba trong OpenGL / GLSL 3.3: Chỉ định vị trí trực tiếp trong mã đổ bóng . Nó trông như thế này:

layout(location=0) in vec4 position;

Nhưng điều này không có trong GLSL ES shader ngôn ngữ.


1
Tôi không thấy vấn đề. VAO thực sự nhẹ và bạn thường sẽ tạo lại chúng cho mỗi khung hình. Trong trường hợp của bạn, bạn sẽ chỉ tạo các VAO khác nhau trước khi gọi mỗi shader, phải không?
PierreBdR

1
Có, bạn có thể làm điều đó tất nhiên. Nó sẽ hoạt động tốt, chúng tôi chỉ thảo luận về các quy ước ở đây. :)
Kos

4
Tùy chọn thứ ba thực sự có sẵn trong GLES2.0 nhưng định dạng hơi khác một chút: bố cục (vị trí = 0) thuộc tính vị trí vec4; Lưu ý rằng bạn cũng sẽ cần cái này ở đầu tệp GLSL của mình: #extension GL_EXT_separate_shader_objects: enable
Gavin Maclean

35
"VAO thực sự rất nhẹ và bạn thường sẽ tạo lại chúng cho mỗi khung hình. Trong trường hợp của bạn, bạn sẽ chỉ tạo các VAO khác nhau trước khi gọi mỗi bộ đổ bóng, phải không?" - Không, bạn thường sẽ không làm điều này, vì điều này cuối cùng hoàn toàn vô hiệu toàn bộ mục đích của VAO. Tại sao lại sử dụng VAO?
Christian Rau

2
Chỉ là một ghi chú. Bạn sẽ không giữ dữ liệu hình học của mình trong VAO. Đó sẽ là một VBO. VAO không có bộ nhớ dữ liệu.
trung bình joe

20

Một câu trả lời khác ở đây là glGetAttribLocation trả về dữ liệu cho người gọi, có nghĩa là nó hoàn toàn yêu cầu xả đường ống. Nếu bạn gọi nó ngay sau khi biên dịch chương trình của mình, về cơ bản bạn đang buộc quá trình biên dịch không đồng bộ diễn ra đồng bộ.



Cảm ơn, đây là một cân nhắc rất quan trọng.
Jing

1
Tôi hiểu rằng trong hầu hết các tình huống, bạn vẫn phải gọi glGetUniformLocation; xem xét cụ thể này có còn phù hợp không?
Mike Weir

@MikeWeir kể từ GL 4.3, bạn có thể đặt vị trí thống nhất rõ ràng .
Ruslan

1
@Ruslan Họ đang sử dụng OpenGL ES.
Mike Weir

9

Tùy chọn thứ ba, tức là layout(location=0) in vec4 position;trong mã đổ bóng, hiện có sẵn trong OpenGL ES 3.0 / GLSL 300 es. Tuy nhiên, chỉ dành cho các biến đầu vào của trình đổ bóng đỉnh.


7
Khi họ gợi ý, thẻ Intel có thể không hỗ trợ điều này (trong khi được một cách hoàn hảo 3.0+ comformant cách khác, khi tôi nhận được nó), mà là kinh tởm :)
mlvljr
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.