I want to draw a selected number of instances using glDrawElements...
but I don't know which function to use and how to set the parameters.
I set the gl_InstanceID
in shader and set the shader data through SSBO:
glGenBuffers(1, &SSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, data_vector.size() * sizeof(data_type), data_vector.data(), GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding_index, SSBO);
I have an array drawable_vector
contains bool
to check if the vertex is drawn or not.
for(auto index = 0; index < drawable_vector.size(); index ++){
glDrawElements...(???)
}
I want to draw instance with ID gl_instanceID
only when the drawable_vector[index]
is true
. The size of drawable_vector, data_vector and number of instances are the same.
Edit: Setup & render code
Setup:
//VAO
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
//VBO1 - Position
glGenBuffers(1, &VBO1);
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
glBufferData(GL_ARRAY_BUFFER, 3*sizeof(glm::vec4), vertices.data(), GL_DYNAMIC_DRAW);
//VBO2 - color
glGenBuffers(1, &VBO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(GL_ARRAY_BUFFER, 3*sizeof(glm::vec4), colors.data(), GL_DYNAMIC_DRAW);
//EBO
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);
//SSBO - models in shader
glGenBuffers(1, &SSBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);
glBufferData(GL_SHADER_STORAGE_BUFFER, models.size() * sizeof(glm::vec4), models.data(), GL_DYNAMIC_DRAW);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, SSBO);
//Set data of shader
//in_pos
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (void *) 0);
glEnableVertexAttribArray(0);
//in_color
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void *) 0);
glEnableVertexAttribArray(1);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, 0);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
glBindVertexArray(0);
Shader:
#version 450 core
out vec4 frag_color;
in vec4 out_color;
void main()
{
frag_color = out_color;
}
#version 430 core
layout (location = 0) in vec4 in_pos;
layout (location = 1) in vec4 in_color;
layout(std430, binding = 2) buffer DataBuffer
{
mat4 in_models[];
} buffer_data;
uniform mat4 view;
uniform mat4 projection;
out vec4 out_color;
void main()
{
out_color = in_color;
gl_Position = projection * view * buffer_data.in_models[gl_InstanceID] * in_pos;
}
Render:
use_shader();
shader_set_view("view", view);
shader_set_projection("projection", projection);
update_models();
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBindBuffer(GL_ARRAY_BUFFER, EBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, SSBO);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, SSBO[0]);
glDrawArraysInstanced(GL_TRIANGLES, 0, 3, n_instances);
glfwSwapBuffers(window);
glBindVertexArray(0);
I figured it out.
Hav to use the command @Yakov Galka mentioned and added gl_BaseInstance to the shader
void main()
{
out_color = in_color;
gl_Position = projection * view * buffer_data.in_models[gl_BaseInstance+gl_InstanceID] * in_pos;
}
and set baseinstance
in glDrawElementsInstancedBaseInstance
to instance numbers to draw.
for(int r_index = 0; r_index < instance_id_list; r_index++) {
glDrawElementsInstancedBaseInstance(
GL_TRIANGLES, // type of primitive to render
3, // vertex count
GL_UNSIGNED_INT, // type of each index in the GL_ELEMENT_ARRAY_BUFFER
(void*)0, // element array buffer offset
1, // Number of copies to render
instance_id_list[r_index] // Number to start from for InstanceId
);
}