2012-01-01 3 views
6
đang

mẫu:Tại sao có nhiều cách để chuyển VAO sang chương trình GLSL?

1. glGenBuffers(1, &VboId); 
2. glBindBuffer(GL_ARRAY_BUFFER, VboId); 
3. glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); 
4. glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); 
5. glEnableVertexAttribArray(0); 

Vì vậy, các "0" trên dòng 4 (số đầu tiên) và 5 đề cập đến một định danh/vị trí tùy ý mà chúng tôi đã chọn. Trong GLSL, nếu chúng ta muốn đề cập đến dữ liệu này, chúng ta chỉ cần phải đề cập đến cùng một ID:

layout(location=0) in vec4 in_Position; 

Tuy nhiên, trong một chương trình ví dụ khác nhau, tôi đã nhìn thấy nó thực hiện khác nhau, không có tham chiếu đến " vị trí bố trí ". Thay vào đó, chúng tôi làm điều gì đó giống như vậy:

1. glGenBuffers(1, &VboId); 
2. glBindBuffer(GL_ARRAY_BUFFER, VboId); 
3. glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW); 
4. glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); 
5. glBindAttribLocation(shaderProgramHandle, 0, "in_position"); 
6. glEnableVertexAttribArray(0); 

Chúng tôi đã thêm thêm một bước (5), nơi chúng tôi dường như để ràng buộc con trỏ thuộc tính này cho một biến cụ thể trong một chương trình cụ thể. Và sau đó trong GLSL của chúng tôi, chúng tôi chỉ viết thay thế này:

in vec3 in_position; 

Không có tham chiếu đến một vị trí.

Nếu tôi không nhầm, hai chương trình này về cơ bản cũng làm điều tương tự ... vậy tại sao lại khác biệt? Những ưu và nhược điểm của từng phương pháp là gì?

(Tôi vừa mới bắt đầu học OpenGL 3.x)

Trả lời

15

Không có thứ gì như chuyển VAO đến trình đổ bóng. Một VAO chỉ đơn giản là thiết lập các thuộc tính vertex được kéo từ các đối tượng đệm để render.

Ví dụ thứ hai không làm bất cứ điều gì, trừ khi shaderProgramHandle chưa được liên kết. glBindAttribLocation vị trí chỉ hoạt động trước khi liên kết chương trình. Khi chương trình đã được liên kết, bạn không thể thay đổi vị trí của chương trình.

Trong mọi trường hợp, câu hỏi thực sự của bạn là lý do tại sao một số người sử dụng glBindAttribLocation(..., 0) thay vì đặt layout(location = X) trong trình đổ bóng của họ. Lý do rất đơn giản: cú pháp layout(location) là (tương đối) mới. glBindAttribLocation ngày trở lại phiên bản đầu tiên của giao diện OpenGL của GLSL, quay trở lại phần mở rộng ARB_vertex_shader vào năm 2003 hoặc lâu hơn. layout(location) xuất phát từ ARB_explicit_attrib_location gần đây hơn, chỉ là lõi trong GL 3.3 trở lên. 3.3 chỉ xuất hiện vào năm 2010. Vì vậy, nhiều tài liệu tự nhiên hơn sẽ nói về cách cũ.

"Ưu và nhược điểm" của mỗi loại khá rõ ràng. Từ quan điểm thuần túy thực tế, layout(location), là mới, yêu cầu trình điều khiển mới hơn (mặc dù nó không yêu cầu GL 3.3. Phần cứng 6xxx + của NVIDIA hỗ trợ ARB_explicit_attrib_location mặc dù chỉ là 2.1). glBindAttribLocation hoạt động trong mã nguồn, trong khi layout(location) được tích hợp vào trình tạo bóng của GLSL. Vì vậy, nếu bạn cần phải quyết định các thuộc tính nào sử dụng các chỉ số nào trong thời gian chạy, thì sẽ khó khăn hơn nếu thực hiện nó với layout(location) hơn là không có nó. Nhưng nếu, giống như hầu hết mọi người, bạn muốn kiểm soát chúng từ trình đổ bóng, thì layout(location) là những gì bạn cần.

+0

Thật kỳ lạ ... bởi vì tôi có một chương trình đang chạy thực hiện chính xác điều đó. Nó không * chính xác * như trên (nó là một wrapper C#) nhưng nó chắc chắn liên kết chương trình trước khi gọi glBindAttribLocation. Nếu 'bố cục (vị trí) 'là cách làm mới, tôi đoán tôi sẽ tiếp tục với điều đó cho đến khi tôi đánh một khối đường để thuyết phục tôi. Cảm ơn. – mpen

+1

@Mark: Chỉ vì chức năng không có nghĩa là bạn không thể may mắn. Nếu bạn không sử dụng 'layout (location)' hoặc 'glBindAttribLocation', thì OpenGL sẽ tự động gán các chỉ mục thuộc tính khi nó thấy phù hợp. –

+2

Hahaha ... bạn là một thiên tài!Tôi vừa thực hiện các cuộc gọi đến glBindAttribLocation và nó chạy chính xác như nhau. Có lẽ tôi nên liên lạc với mọi người ở OpenTK vì đây là ví dụ đi kèm với thư viện của họ! – mpen