void afSetVertexAttributes(const InputElement elements[], int numElements, int numBuffers, GLuint const vertexBufferIds[], const int strides[]) { for (int i = 0; i < numElements; i++) { const InputElement& d = elements[i]; glBindBuffer(GL_ARRAY_BUFFER, vertexBufferIds[d.inputSlot]); GLenum r = glGetError(); if (r != GL_NO_ERROR) { aflog("glBindBuffer error! i=%d inputSlot=%d vbo=%d\n", i, d.inputSlot, vertexBufferIds[d.inputSlot].x); } afHandleGLError(glEnableVertexAttribArray(i)); switch (d.format) { case SF_R32_FLOAT: case SF_R32G32_FLOAT: case SF_R32G32B32_FLOAT: case SF_R32G32B32A32_FLOAT: glVertexAttribPointer(i, d.format - SF_R32_FLOAT + 1, GL_FLOAT, GL_FALSE, strides[d.inputSlot], (void*)d.offset); break; case SF_R8_UNORM: case SF_R8G8_UNORM: case SF_R8G8B8_UNORM: case SF_R8G8B8A8_UNORM: glVertexAttribPointer(i, d.format - SF_R8_UNORM + 1, GL_UNSIGNED_BYTE, GL_TRUE, strides[d.inputSlot], (void*)d.offset); break; case SF_R8_UINT_TO_FLOAT: case SF_R8G8_UINT_TO_FLOAT: case SF_R8G8B8_UINT_TO_FLOAT: case SF_R8G8B8A8_UINT_TO_FLOAT: glVertexAttribPointer(i, d.format - SF_R8_UINT_TO_FLOAT + 1, GL_UNSIGNED_BYTE, GL_FALSE, strides[d.inputSlot], (void*)d.offset); break; case SF_R8_UINT: case SF_R8G8_UINT: case SF_R8G8B8_UINT: case SF_R8G8B8A8_UINT: #ifdef AF_GLES31 glVertexAttribIPointer(i, d.format - SF_R8_UINT + 1, GL_UNSIGNED_BYTE, strides[d.inputSlot], (void*)d.offset); #endif break; case SF_R16_UINT_TO_FLOAT: case SF_R16G16_UINT_TO_FLOAT: case SF_R16G16B16_UINT_TO_FLOAT: case SF_R16G16B16A16_UINT_TO_FLOAT: glVertexAttribPointer(i, d.format - SF_R16_UINT_TO_FLOAT + 1, GL_UNSIGNED_SHORT, GL_FALSE, strides[d.inputSlot], (void*)d.offset); break; case SF_R16_UINT: case SF_R16G16_UINT: case SF_R16G16B16_UINT: case SF_R16G16B16A16_UINT: #ifdef AF_GLES31 glVertexAttribIPointer(i, d.format - SF_R16_UINT + 1, GL_UNSIGNED_SHORT, strides[d.inputSlot], (void*)d.offset); #endif break; case SF_R32_UINT: case SF_R32G32_UINT: case SF_R32G32B32_UINT: case SF_R32G32B32A32_UINT: #ifdef AF_GLES31 glVertexAttribIPointer(i, d.format - SF_R32_UINT + 1, GL_UNSIGNED_INT, strides[d.inputSlot], (void*)d.offset); #endif break; default: assert(0); break; } #ifdef AF_GLES31 if (d.perInstance) { glVertexAttribDivisor(i, 1); } #endif } glBindBuffer(GL_ARRAY_BUFFER, 0); } GLuint afCreateVAO(const InputElement elements[], int numElements, int numBuffers, GLuint const vertexBufferIds[], const int strides[], GLuint ibo) { VAOID vao; glGenVertexArrays(1, &vao.x); glBindVertexArray(vao); afSetVertexAttributes(elements, numElements, numBuffers, vertexBufferIds, strides); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); glBindVertexArray(0); return vao; }