Tôi đang sử dụng OpenGL ES 2.0 trên Android, nhưng tôi cho rằng câu hỏi này là một câu hỏi chung về OpenGL.Phạm vi của glVertexAttribPointer và glEnableVertexAttribArray là gì?
Tôi đang tìm hiểu OpenGL và đang cố gắng hiểu chính xác API nào phải được gọi cho mỗi khung hình, so với chỉ một lần. Ban đầu tôi gọi glVertexAttribPointer
và glEnableVertexAttribArray
mỗi khung hình, nhưng khi tôi thay đổi chương trình thử nghiệm của mình để chỉ gọi chúng một lần cho mỗi chương trình Shader, tôi nhận được hành vi không phải là những gì tôi mong đợi.
Có vẻ như glVertexAttribPointer
và glEnableVertexAttribArray
chỉ nên được gọi một lần, thay vì mọi khung hình, vì chúng chỉ có ý nghĩa trong ngữ cảnh của một chương trình Shader cụ thể. Tôi nói điều này vì glVertexAttribPointer
lấy làm tham số đầu tiên là GLuint index
được trả về từ glGetAttribLocation
chỉ định một chuỗi tương ứng với tên biến trong chương trình đổ bóng. Vì vậy, có vẻ như dữ liệu được gắn với một biến "thuộc tính" cụ thể trong một chương trình đổ bóng cụ thể.
Chương trình thử nghiệm của tôi hiển thị hai hình dạng rời nhau (hình tam giác), sử dụng hai chương trình hoàn toàn khác nhau - nguồn đổ bóng phân đoạn khác nhau, nguồn đổ bóng khác nhau, gọi riêng đến glLinkProgram
. như mong đợi - tôi thấy cả hai hình dạng được hiển thị chính xác.
m_glhook.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// Shape/Program 1
m_glhook.glUseProgram(m_iGlProgramId);
int iPositionLocation = m_glhook.glGetAttribLocation(m_iGlProgramId, "a_Position");
m_bfVertices.rewind();
m_glhook.glVertexAttribPointer(iPositionLocation, 4, GLES20.GL_FLOAT, false, STRIDE, m_bfVertices);
m_glhook.glEnableVertexAttribArray(iPositionLocation);
gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
// Shape/Program 2
m_glhook.glUseProgram(m_iGlProgramId2);
int iPositionLocation2 = m_glhook.glGetAttribLocation(m_iGlProgramId2, "a_Position");
m_bfVertices2.rewind();
m_glhook.glVertexAttribPointer(iPositionLocation2, 4, GLES20.GL_FLOAT, false, STRIDE, m_bfVertices2);
m_glhook.glEnableVertexAttribArray(iPositionLocation2);
gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
Sau đó, tôi đã sửa đổi các cuộc gọi được thực hiện cho mỗi khung như được hiển thị bên dưới. m_bFirstDraw
là đúng cho khung đầu tiên và giả cho khung hình liên tiếp.
m_glhook.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// Shape/Program 1
m_glhook.glUseProgram(m_iGlProgramId);
if (m_bFirstDraw)
{
int iPositionLocation = m_glhook.glGetAttribLocation(m_iGlProgramId, "a_Position");
m_bfVertices.rewind();
m_glhook.glVertexAttribPointer(iPositionLocation, 4, GLES20.GL_FLOAT, false, STRIDE, m_bfVertices);
m_glhook.glEnableVertexAttribArray(iPositionLocation);
}
gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
// Shape/Program 2
m_glhook.glUseProgram(m_iGlProgramId2);
if (m_bFirstDraw)
{
int iPositionLocation2 = m_glhook.glGetAttribLocation(m_iGlProgramId2, "a_Position");
m_bfVertices2.rewind();
m_glhook.glVertexAttribPointer(iPositionLocation2, 4, GLES20.GL_FLOAT, false, STRIDE, m_bfVertices2);
m_glhook.glEnableVertexAttribArray(iPositionLocation2);
}
gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
m_bFirstDraw = false;
Hành vi tôi thấy với mã trên là cho khung đầu tiên mọi thứ vẫn ổn (điều này có ý nghĩa vì khung đầu tiên chuỗi cuộc gọi giống hệt nhau). Nhưng đối với các khung hình liên tiếp, Shape1 được vẽ bằng các đỉnh của Shape2. Vì vậy, tôi chỉ thấy Shape2 vì nó được vẽ chính xác trên đỉnh của Shape1.
Hãy giúp tôi hiểu điều này ... tại sao việc đặt dữ liệu (hình dạng đỉnh) cho một chương trình ảnh hưởng đến dữ liệu được chương trình khác sử dụng trong khung liên tiếp? Tôi đang thiếu một cái gì đó ...
Cảm ơn rất nhiều vì câu trả lời Andon. Nhìn vào spec, VAOs không có sẵn trong OpenGL ES 2.0 vì vậy tôi sẽ không thể sử dụng chúng. Vì vậy, chỉ để xác nhận, mà không có VAOs nó là cần thiết để gọi 'glVertexAttribPointer' và' glEnableVertexAttribArray' mỗi khi tôi chuyển đổi chương trình.Nếu tôi có nhiều chương trình chạy với mọi khung hình (theo thứ tự như nhau), điều này có nghĩa là tôi phải gọi những hàm đó cho mọi Chương trình, cho từng khung hình. Đúng không? –
@DavidStone: Không nhất thiết, bạn chỉ phải làm điều này nếu bạn muốn vẽ với một bộ đệm đỉnh khác hoặc nếu bạn cần các con trỏ thuộc tính ánh xạ tới các vị trí khác nhau để cung cấp cho trình đổ bóng với đúng dữ liệu ở vị trí gắn kết phù hợp . –
OK Tôi nghĩ bây giờ tôi đã hiểu. Hai shaders của tôi cần phải hoạt động trên các đỉnh khác nhau và cả hai đều chạy trong mọi frame, theo thứ tự như nhau. Vì vậy, trong trường hợp đó nó là cần thiết để gọi 'glVertexAttribPointer' ** hai lần ** cho mỗi khung hình. Vì lý do gì, khi tôi gọi 'glGetAttribLocation' và để OpenGL chọn chỉ mục thuộc tính đỉnh cho tôi, nó luôn chọn 0 vì vậy tôi đang sử dụng cùng một chỉ mục cho cả hai thuộc tính đỉnh. Tuy nhiên tôi thấy rằng 'glBindAttribLocation' ** là ** có sẵn trong OpenGL ES 2.0 và nó cho phép tôi chỉ định các chỉ số khác nhau cho hai chương trình, tránh vấn đề này. –