2014-07-21 15 views
5

Tôi là một newbie tại Open GL và đã đến đây để xóa một sự nhầm lẫn mà tôi có. Tôi đánh giá cao sự giúp đỡ nào!hiểu glVertexAttribPointer?

private int vbo; 
private int ibo; 

vbo = glGenBuffers(); 
ibo = glGenBuffers(); 

glBindBuffer(GL_ARRAY_BUFFER, vbo); 
glBufferData(GL_ARRAY_BUFFER, Util.createFlippedBuffer(vertices), GL_STATIC_DRAW); 

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, Util.createFlippedBuffer(indices), GL_STATIC_DRAW); 




glEnableVertexAttribArray(0); 
glEnableVertexAttribArray(1); 
//glEnableVertexAttribArray(2); 

//glBindBuffer(GL_ARRAY_BUFFER, vbo); 
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0); 
glVertexAttribPointer(1, 2, GL_FLOAT, false, Vertex.SIZE * 4, 12); 
//glVertexAttribPointer(2, 3, GL_FLOAT, false, Vertex.SIZE * 4, 20); 

//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0); 

glDisableVertexAttribArray(0); 
glDisableVertexAttribArray(1); 
//glDisableVertexAttribArray(2); 

Mã vertex shader trông giống như

#version 330 

layout (location = 0) in vec3 position; 
layout (location = 1) in vec2 texCoord; 

out vec2 texCoord0; 

uniform mat4 transform; 

void main() 
{ 
    gl_Position = transform * vec4(position, 1.0); 
    texCoord0 = texCoord; 
} 

Vì vậy, đây là sự hiểu biết của tôi. Mục đích của glVertexAttribPointer là định nghĩa định dạng dữ liệu trong đối tượng vertex buffer. Vì vậy, trong VBO nó lưu trữ dữ liệu như sau

buffer.put(vertices[i].getPos().getX()); 
buffer.put(vertices[i].getPos().getY()); 
buffer.put(vertices[i].getPos().getZ()); 
buffer.put(vertices[i].getTexCoord().getX()); 
buffer.put(vertices[i].getTexCoord().getY()); 
buffer.put(vertices[i].getNormal().getX()); 
buffer.put(vertices[i].getNormal().getY()); 
buffer.put(vertices[i].getNormal().getZ()); 

Vì vậy, chúng tôi có hai dòng glVertexAttribPointer vì chúng ta có hai biến định nghĩa trong vertex shader. Vì vậy, về cơ bản chúng tôi đang xác định những gì hai biến này trỏ đến. Vì vậy, glVertexAttribPointer đầu tiên xác định rằng biến đầu tiên "position" là một đỉnh với ba tọa độ mỗi float. Các glVertexAttribPointer thứ hai định nghĩa biến thứ hai "texCoord" là một cặp tọa độ kết cấu mỗi float. Vì vậy, nếu sự hiểu biết của tôi là chính xác cho đến nay thì tôi đã giả định trước tiên chúng ta cần phải ràng buộc đối tượng bộ đệm đỉnh đầu tiên nhưng ngay cả sau khi nhận xét ra dòng này

glBindBuffer (GL_ARRAY_BUFFER, vbo);

nó vẫn hoạt động. Tôi bị bối rối. Làm cách nào để biết đối tượng đệm nào chúng ta đang nói đến vì có hai vbos?

Tôi đánh giá cao bất kỳ trợ giúp nào. Cảm ơn rất nhiều!

+1

Không có hai VBO. Có một VBO và một IBO. Cả hai đều có thể (và phải) vẫn bị ràng buộc cùng một lúc. – fintelia

+0

vậy điều đó có nghĩa là nếu có hai VBO thì chúng ta cần ràng buộc nó một cách rõ ràng nhưng vì chỉ có một VBO thì nó bị ràng buộc theo mặc định? – user3256520

+2

@fintelia: Thực tế là không. Bạn có thể hủy liên kết một cách an toàn VBO sau khi thực hiện cuộc gọi đến 'gl… Pointer', liên kết với VBO bị ràng buộc tại thời điểm cuộc gọi của hàm' gl… Pointer' không bị mất. – datenwolf

Trả lời

14

@datenwolf đã đề cập đến khía cạnh quan trọng trong nhận xét ở trên. Để xây dựng thêm một số chi tiết:

Bạn làm không phải liên kết GL_ARRAY_BUFFER lần nữa trước cuộc gọi glDrawElements(). Điều quan trọng là bộ đệm bạn muốn nguồn một thuộc tính đã cho từ bị ràng buộc khi bạn thực hiện cuộc gọi glVertexAttribPointer() cho thuộc tính đó.

Cách tốt nhất để hình dung ra điều này là khi bạn thực hiện cuộc gọi này:

glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0); 

bạn đang xác định tất cả các trạng thái cần thiết để nói với OpenGL nơi để lấy dữ liệu cho thuộc tính 0 (số đầu tiên) từ, và cách đọc nó. Hầu hết các trạng thái đó được đưa ra trực tiếp bởi các đối số:

  • nó có 3 thành phần
  • các thành phần là float giá trị
  • đỉnh được đọc với một sải chân của 20 byte ...
  • ... và bắt đầu từ byte 0 của bộ đệm

Nhưng có một mảnh ngụ ý bổ sung của nhà nước mà còn được cất giữ cho thuộc tính 0 khi bạn thực hiện cuộc gọi:

  • dữ liệu được đọc từ bộ đệm hiện ràng buộc để GL_ARRAY_BUFFER

Nói cách khác, trạng thái kết hợp với mỗi thuộc tính bao gồm các id của bộ đệm dữ liệu thuộc tính có nguồn gốc từ đâu. Đây có thể là cùng một bộ đệm cho nhiều/tất cả các thuộc tính, hoặc nó có thể là một bộ đệm khác nhau cho mỗi thuộc tính.

Lưu ý rằng điều này cũng không đúng cho GL_ELEMENT_ARRAY_BUFFER. Người đó cần phải bị ràng buộc tại thời điểm cuộc gọi glDrawElements(). Trong khi nó có vẻ hơi không nhất quán, điều này là cần thiết vì không có tương đương với glVertexAttribPointer() cho mảng chỉ mục. API có thể đã được định nghĩa để có loại cuộc gọi này, nhưng ... nó không phải. Lý do rất có thể là nó chỉ đơn giản là không cần thiết, vì chỉ có một mảng chỉ mục có thể được sử dụng cho một cuộc gọi vẽ, trong khi nhiều bộ đệm đỉnh có thể được sử dụng.

+0

trong ngắn hạn tôi đã ràng buộc hai bộ đệm này .. glBindBuffer (GL_ARRAY_BUFFER, vbo); glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, ibo); do đó tôi không cần phải rebind..correct? – user3256520

+0

Chắc chắn, bạn không cần phải rebind bộ đệm đã bị ràng buộc. Những gì tôi đã cố gắng để trang trải trong câu trả lời của tôi là bộ đệm phải được ràng buộc cho các cuộc gọi. –