I want to create a class which is a "Renderable class". Basically, world objects will use this as a Base class to create objects that can be drawn into an OpenGL window. This is what i 've got so far:
typedef struct {
GLfloat pos_x_, pos_y_, pos_z_;
std::string object_path_;
std::string texture_path_;
} OpenGLObjectParams_t;
class OpenGLObject {
public:
OpenGLObject(OpenGLObjectParams_t params);
int Init(OpenGLContext * context_);
int Destroy();
int Draw();
void SetPosition(GLfloat pos_x, GLfloat pos_y, GLfloat pos_z);
private:
bool is_inited_;
glm::mat4 model_;
OpenGLObjectParams_t params_;
OpenGLShaderVariables_t shader_vars_;
GLuint VAO, vertex_buffer_, color_buffer_;
};
And the implementation (Right now the object/texture are not used, and a rectangle is painted instead). The OpenGLContext is just used to take the shader variables:
OpenGLObject::OpenGLObject(OpenGLObjectParams_t params) {
params_ = params;
is_inited_ = false;
}
int OpenGLObject::Init(OpenGLContext * context)
{
if (is_inited_) return -1;
SetPosition(params_.pos_x_, params_.pos_y_, params_.pos_z_);
shader_vars_ = context->GetShaderVariables();
static const GLfloat vertex_buffer_data[] = {
-1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
};
glGenBuffers(1, &vertex_buffer_);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_buffer_data), vertex_buffer_data, GL_STATIC_DRAW);
static const GLfloat color_buffer_data[] = {
1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f,
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f,
};
glGenBuffers(1, &color_buffer_);
glBindBuffer(GL_ARRAY_BUFFER, color_buffer_);
glBufferData(GL_ARRAY_BUFFER, sizeof(color_buffer_data), color_buffer_data, GL_STATIC_DRAW);
/* Configure a VAO */
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
/* Attribute number 0 is the model vertices */
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
glVertexAttribPointer(shader_vars_.attr_vertex_position_, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(0);
/* Attribute number 1 is the colors */
glBindBuffer(GL_ARRAY_BUFFER, color_buffer_);
glVertexAttribPointer(shader_vars_.attr_vertex_color_, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(1);
is_inited_ = true;
return 0;
}
int OpenGLObject::Destroy() {
if (!is_inited_) return -1;
glDeleteBuffers(1, &vertex_buffer_);
glDeleteBuffers(1, &color_buffer_);
glDeleteVertexArrays(1, &VAO);
is_inited_ = false;
return 0;
}
int OpenGLObject::Draw(double delta_time) {
if (!is_inited_) return -1;
glBindVertexArray(VAO);
glUniformMatrix4fv(shader_vars_.uni_Model_, 1, GL_FALSE, &model_[0][0]);
glDrawArrays(GL_TRIANGLES, 0, 2 * 3);
return 0;
}
void OpenGLObject::SetPosition(GLfloat pos_x, GLfloat pos_y, GLfloat pos_z) {
params_.pos_x_ = pos_x;
params_.pos_y_ = pos_y;
params_.pos_z_ = pos_z;
model_ = GetTranslateMatrix(glm::vec3(pos_x, pos_y, pos_z));
}
And the main loop will call the Draw function on the objects that use the above as a Base class.
Is this the way to implement such a mechanism?
Because if the world has thousands of objects, then there will be a loop on a data structure to call thousands of Draw calls. I assume that the Draw() above cannot be called from multiple threads?
What's the best architecture for such a feature? Is it possible to call a Draw() from different threads?
Edit: I don't ask about the drawing method itself, since it's better to use glDrawElements() but the whole architecture.