void VertexBuffer::SetAttribPointers() { for (Uint8 i = 0; i < MAX_ATTRIBS; i++) { const auto& attr = m_desc.attrib[i]; const auto offset = reinterpret_cast<const GLvoid*>(m_desc.attrib[i].offset); switch (attr.semantic) { case ATTRIB_POSITION: glVertexPointer(get_num_components(attr.format), get_component_type(attr.format), m_desc.stride, offset); break; case ATTRIB_NORMAL: glNormalPointer(get_component_type(attr.format), m_desc.stride, offset); break; case ATTRIB_DIFFUSE: glColorPointer(get_num_components(attr.format), get_component_type(attr.format), m_desc.stride, offset); break; case ATTRIB_UV0: glTexCoordPointer(get_num_components(attr.format), get_component_type(attr.format), m_desc.stride, offset); break; case ATTRIB_NONE: default: return; } } }
VertexBuffer::VertexBuffer(const VertexBufferDesc &desc) : Graphics::VertexBuffer(desc) { //update offsets in desc for (Uint32 i = 0; i < MAX_ATTRIBS; i++) { if (m_desc.attrib[i].offset == 0) m_desc.attrib[i].offset = VertexBufferDesc::CalculateOffset(m_desc, m_desc.attrib[i].semantic); } //update stride in desc (respecting offsets) if (m_desc.stride == 0) { Uint32 lastAttrib = 0; while (lastAttrib < MAX_ATTRIBS) { if (m_desc.attrib[lastAttrib].semantic == ATTRIB_NONE) break; lastAttrib++; } m_desc.stride = m_desc.attrib[lastAttrib].offset + VertexBufferDesc::GetAttribSize(m_desc.attrib[lastAttrib].format); } assert(m_desc.stride > 0); assert(m_desc.numVertices > 0); SetVertexCount(m_desc.numVertices); glGenVertexArrays(1, &m_vao); glBindVertexArray(m_vao); glGenBuffers(1, &m_buffer); //Allocate initial data store //Using zeroed m_data is not mandatory, but otherwise contents are undefined glBindBuffer(GL_ARRAY_BUFFER, m_buffer); const Uint32 dataSize = m_desc.numVertices * m_desc.stride; m_data = new Uint8[dataSize]; memset(m_data, 0, dataSize); const GLenum usage = (m_desc.usage == BUFFER_USAGE_STATIC) ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW; glBufferData(GL_ARRAY_BUFFER, dataSize, m_data, usage); //Setup the VAO pointers for (Uint8 i = 0; i < MAX_ATTRIBS; i++) { const auto& attr = m_desc.attrib[i]; if (attr.semantic == ATTRIB_NONE) break; // Tell OpenGL what the array contains const auto offset = reinterpret_cast<const GLvoid*>(attr.offset); switch (attr.semantic) { case ATTRIB_POSITION: glEnableVertexAttribArray(0); // Enable the attribute at that location glVertexAttribPointer(0, get_num_components(attr.format), get_component_type(attr.format), GL_FALSE, m_desc.stride, offset); break; case ATTRIB_NORMAL: glEnableVertexAttribArray(1); // Enable the attribute at that location glVertexAttribPointer(1, get_num_components(attr.format), get_component_type(attr.format), GL_FALSE, m_desc.stride, offset); break; case ATTRIB_DIFFUSE: glEnableVertexAttribArray(2); // Enable the attribute at that location glVertexAttribPointer(2, get_num_components(attr.format), get_component_type(attr.format), GL_TRUE, m_desc.stride, offset); // only normalise the colours break; case ATTRIB_UV0: glEnableVertexAttribArray(3); // Enable the attribute at that location glVertexAttribPointer(3, get_num_components(attr.format), get_component_type(attr.format), GL_FALSE, m_desc.stride, offset); break; case ATTRIB_NONE: default: break; } } glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); //Don't keep client data around for static buffers if (GetDesc().usage == BUFFER_USAGE_STATIC) { delete[] m_data; m_data = nullptr; } }