2013-03-13 34 views
8

Tôi đang đọc hướng dẫn về OpenGL và OpenGLES và tôi hơi bối rối về việc sử dụng hàm glVertexAttribPointer trong hai API này.glVertexAttribPointer trong OpenGL và OpenGLES

Trong hướng dẫn OpenGL, hàm này sử dụng làm tham số cuối cùng một số bù (với phép đúc thành const GLVoid *) và tôi cho rằng các đỉnh được lấy trực tiếp từ Bộ đệm mảng hiện tại.

glVertexAttribPointer(vs_position, 2, GL_FLOAT, GL_TRUE, 5 * sizeof(GLfloat), (const GLvoid*) (3*sizeof(GLfloat))); 

Trong OpenGLES hướng dẫn những điểm số cuối cùng trực tiếp đến một cấu trúc đại diện cho đỉnh:

GLFloat vertices[] = {...definition}; 
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices); 

Tôi không thể hiểu tại sao những 2 chức năng làm việc. Chúng có hoàn toàn khác nhau không?

Trả lời

25

Chúng là cùng một chức năng đang được sử dụng theo hai cách khác nhau. Tôi giải thích lý do tại sao nó hoạt động theo cách này, nhưng bạn sẽ không quan tâm, và nó cho những lý do rất ngu ngốc và không liên quan.

Điều quan trọng là những gì họ đang làm. Và những gì họ đang làm phụ thuộc vào một cái gì đó mà bạn không hiển thị: những gì được ràng buộc để GL_ARRAY_BUFFER.

Xem, hành vi của glVertexAttribPointerthay đổi tùy thuộc vào điều đó. Nếu không có đối tượng đệm nào bị ràng buộc với GL_ARRAY_BUFFER khi bạn gọi glVertexAttribPointer, thì hàm sẽ giả định rằng giá trị cuối cùng là một con trỏ (giống như tên của hàm cho biết: glVertexAttrib Pointer). Cụ thể, nó là một con trỏ vào bộ nhớ thuộc sở hữu của khách hàng.

Khi đến lúc hiển thị, dữ liệu thuộc tính đỉnh sẽ đến từ con trỏ được cung cấp trước đó. Do đó, ví dụ thứ hai chỉ là sử dụng một mảng dữ liệu khách hàng, được khai báo theo kiểu C chuẩn, làm dữ liệu nguồn. Không có đối tượng đệm nào có liên quan.

Lưu ý: cấu hình cốt lõi của OpenGL 3.1+ đã loại bỏ khả năng sử dụng bộ nhớ máy khách; ở đó, bạn phải sử dụng các đối tượng đệm, như được giải thích bên dưới.

Nếu đối tượng đệm bị ràng buộc ở GL_ARRAY_BUFFER khi gọi glVertexAttribPointer thì có điều gì đó đặc biệt xảy ra. OpenGL sẽ giả vờ rằng con trỏ (đó là những gì tham số cuối cùng là như xa như C/C + + là có liên quan) thực sự là một bù đắp byte vào bộ đệm bị ràng buộc để GL_ARRAY_BUFFER. Nó sẽ chuyển đổi con trỏ thành một số nguyên và sau đó lưu trữ số nguyên đó bù đắp và đối tượng bộ đệm hiện đang bị ràng buộc để GL_ARRAY_BUFFER.

Vì vậy, mã trên mất 3*sizeof(GLfloat), độ lệch byte và chuyển đổi thành con trỏ. OpenGL sẽ lấy con trỏ và chuyển đổi nó trở lại thành một offset, mang lại 3*sizeof(GLfloat) một lần nữa.

Khi đến lúc hiển thị, OpenGL sau đó sẽ đọc từ đối tượng đệm đã cho trước đó, sử dụng bù trừ đã cho trước đó.

Ví dụ đầu tiên đặt dữ liệu đỉnh vào đối tượng đệm trong bộ nhớ GPU. Ví dụ thứ hai đặt dữ liệu đỉnh trong một mảng C/C++ thông thường, trong bộ nhớ CPU.

+0

Giải thích hoàn hảo! Cảm ơn bạn. - Bạn lấy thông tin này ở đâu? Tôi không thể tìm thấy tài liệu về điều đó. - những gì bạn nói về OpenGL3.1 và không sử dụng ứng dụng bộ nhớ cũng hợp lệ cho OpenGLEs 2.0? – MatterGoal

+0

@MatterGoal: Nói chung, các ứng dụng luôn sử dụng bộ nhớ phía máy khách hoặc các đối tượng đệm. Vì vậy, không ai cần phải nói về sự khác biệt giữa chúng. Và phần lớn tài liệu OpenGL trên máy tính để bàn đã chuyển sang hành vi hồ sơ cốt lõi, vì vậy nó cũng không nói về nó. Nhưng nó ở ngay trong [trang hướng dẫn cho GL ES] (http://www.khronos.org/opengles/sdk/docs/man/xhtml/glVertexAttribPointer.xml). Chỉ cần đọc đoạn thứ hai của mô tả. –

+0

@MatterGoal: Nó cũng được giải thích trong câu trả lời này (http://stackoverflow.com/a/5402762/734069) trong một câu hỏi liên quan. –

1

GL spec rõ ràng đề cập đến điều này:

trường hợp 1: Nếu một số không không tên đối tượng đệm được ràng buộc với mục tiêu GL_ARRAY_BUFFER trong khi một mảng thuộc tính đỉnh chung được chỉ định, con trỏ được coi là một byte bù đắp vào bộ đệm của đối tượng kho dữ liệu.

trường hợp 2: Chỉ định con trỏ tới thành phần đầu tiên của thuộc tính đỉnh chung đầu tiên trong mảng.

Các vấn đề liên quan