From e9a9b8a2cfe8c9f3ff5ce21483820fb79faf02d5 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Mon, 30 Dec 2024 19:07:53 +0000 Subject: [PATCH] Use instanced arrays to draw the lights --- shaders/light_vert.glsl | 18 +++++++++++ src/main.cc | 69 +++++++++++++++++++++++++++++++++-------- 2 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 shaders/light_vert.glsl diff --git a/shaders/light_vert.glsl b/shaders/light_vert.glsl new file mode 100644 index 0000000..d0c0e58 --- /dev/null +++ b/shaders/light_vert.glsl @@ -0,0 +1,18 @@ +#version 330 core + +#define POINT_LIGHT_COUNT 4 + +layout(location=0) in vec3 position; +layout(location=1) in vec3 normal; +layout(location=2) in vec2 uv; +layout(location=3) in mat4 model; + +layout (std140) uniform Common { + mat4 projection; + mat4 view; + vec3 camera_position; +}; + +void main() { + gl_Position = projection * view * model * vec4(position, 1.0); +}; diff --git a/src/main.cc b/src/main.cc index 9eb9e07..4897da6 100644 --- a/src/main.cc +++ b/src/main.cc @@ -50,7 +50,7 @@ #define WIREFRAME 0 #define NORMALS 0 -#define POINT_LIGHTS 0 +#define POINT_LIGHTS 1 enum exit_codes : int { EXIT_CODE_SUCCESS, @@ -116,10 +116,14 @@ class Mesh { std::vector textures; Mesh(std::vector vertices, std::vector indices, std::vector textures); + void activate(); + void deactivate(); void draw(Shader &Shader); + void draw_instanced(Shader &Shader, unsigned int count = 1); private: GLuint vao, vbo, ebo; void setup_mesh(); + void set_mesh_textures_for_drawing(Shader &shader); }; class Model { @@ -282,7 +286,8 @@ int main() { #endif #if POINT_LIGHTS - Shader light_shader {"shaders/vert.glsl", "shaders/light_frag.glsl"}; + Shader light_shader {"shaders/light_vert.glsl", "shaders/light_frag.glsl"}; + std::vector light_shader_model_mats; #endif const float camera_speed = 25.0f; @@ -356,8 +361,36 @@ int main() { memset(constant, 0, sizeof(constant)); memset(linear, 0, sizeof(linear)); memset(quadratic, 0, sizeof(quadratic)); + +#if POINT_LIGHTS + glm::mat4 light_shader_model_mat = glm::translate(glm::mat4(1.0f), point_light_positions[i]); + light_shader_model_mat = glm::scale(light_shader_model_mat, glm::vec3(0.2f)); + light_shader_model_mats.push_back(light_shader_model_mat); +#endif } +#if POINT_LIGHTS + std::size_t vec4_size = sizeof(glm::vec4); + + light.activate(); + + GLuint instanceVBO; + glGenBuffers(1, &instanceVBO); + glBindBuffer(GL_ARRAY_BUFFER, instanceVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * light_shader_model_mats.size(), glm::value_ptr(light_shader_model_mats[0]), GL_STATIC_DRAW); + + // Set up attribute pointers for each column of the matrix + for (unsigned int i = 3; i < 7; ++i) { + glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 4 * vec4_size, (void *)((i - 3) * vec4_size)); + glEnableVertexAttribArray(i); + glVertexAttribDivisor(i, 1); + } + + light.deactivate(); + + glBindBuffer(GL_ARRAY_BUFFER, 0); +#endif + // Load cube map std::vector cube_map_textures = { "images/skybox/right.jpg", @@ -526,22 +559,14 @@ int main() { refractive_shader.set_mat4("model", model); refractive_shader.set_mat3("normal_mat", normal_mat); suzanne.draw(refractive_shader); - glEnable(GL_CULL_FACE); #if POINT_LIGHTS // Draw point lights - for (int i = 0; i < point_light_positions.size(); ++i) { - model = glm::translate(glm::mat4(1.0f), point_light_positions[i]); - model = glm::scale(model, glm::vec3(0.2f)); - light_shader.activate(); - light_shader.set_mat4("model", model); - light_shader.set_vec3("light_diffuse", light_diffuse); - light.draw(light_shader); - } + light_shader.set_vec3("light_diffuse", light_diffuse); + light.draw_instanced(light_shader, point_light_positions.size()); #endif // Draw skybox - glDisable(GL_CULL_FACE); skybox_shader.activate(); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); @@ -803,7 +828,7 @@ void Mesh::setup_mesh() { glEnableVertexAttribArray(2); } -void Mesh::draw(Shader &shader) { +void Mesh::set_mesh_textures_for_drawing(Shader &shader) { unsigned int diffuse = 1; unsigned int specular = 1; unsigned int index; @@ -814,9 +839,27 @@ void Mesh::draw(Shader &shader) { shader.set_int(texture.name(index).c_str(), texture.texture_unit - GL_TEXTURE0); texture.activate(); } +} +void Mesh::activate() { glBindVertexArray(vao); +} + +void Mesh::deactivate() { + glBindVertexArray(0); +} + +void Mesh::draw(Shader &shader) { + set_mesh_textures_for_drawing(shader); + activate(); glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void *)0); + deactivate(); +} + +void Mesh::draw_instanced(Shader &shader, unsigned int count) { + set_mesh_textures_for_drawing(shader); + glBindVertexArray(vao); + glDrawElementsInstanced(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, (void *)0, count); glBindVertexArray(0); }