Use instanced arrays to draw the lights

This commit is contained in:
Abdelrahman Said 2024-12-30 19:07:53 +00:00
parent ce561fc44d
commit e9a9b8a2cf
2 changed files with 74 additions and 13 deletions

18
shaders/light_vert.glsl Normal file
View File

@ -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);
};

View File

@ -50,7 +50,7 @@
#define WIREFRAME 0 #define WIREFRAME 0
#define NORMALS 0 #define NORMALS 0
#define POINT_LIGHTS 0 #define POINT_LIGHTS 1
enum exit_codes : int { enum exit_codes : int {
EXIT_CODE_SUCCESS, EXIT_CODE_SUCCESS,
@ -116,10 +116,14 @@ class Mesh {
std::vector<Texture2D> textures; std::vector<Texture2D> textures;
Mesh(std::vector<Vertex> vertices, std::vector<GLuint> indices, std::vector<Texture2D> textures); Mesh(std::vector<Vertex> vertices, std::vector<GLuint> indices, std::vector<Texture2D> textures);
void activate();
void deactivate();
void draw(Shader &Shader); void draw(Shader &Shader);
void draw_instanced(Shader &Shader, unsigned int count = 1);
private: private:
GLuint vao, vbo, ebo; GLuint vao, vbo, ebo;
void setup_mesh(); void setup_mesh();
void set_mesh_textures_for_drawing(Shader &shader);
}; };
class Model { class Model {
@ -282,7 +286,8 @@ int main() {
#endif #endif
#if POINT_LIGHTS #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<glm::mat4> light_shader_model_mats;
#endif #endif
const float camera_speed = 25.0f; const float camera_speed = 25.0f;
@ -356,8 +361,36 @@ int main() {
memset(constant, 0, sizeof(constant)); memset(constant, 0, sizeof(constant));
memset(linear, 0, sizeof(linear)); memset(linear, 0, sizeof(linear));
memset(quadratic, 0, sizeof(quadratic)); 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 // Load cube map
std::vector<std::string> cube_map_textures = { std::vector<std::string> cube_map_textures = {
"images/skybox/right.jpg", "images/skybox/right.jpg",
@ -526,22 +559,14 @@ int main() {
refractive_shader.set_mat4("model", model); refractive_shader.set_mat4("model", model);
refractive_shader.set_mat3("normal_mat", normal_mat); refractive_shader.set_mat3("normal_mat", normal_mat);
suzanne.draw(refractive_shader); suzanne.draw(refractive_shader);
glEnable(GL_CULL_FACE);
#if POINT_LIGHTS #if POINT_LIGHTS
// Draw point lights // Draw point lights
for (int i = 0; i < point_light_positions.size(); ++i) { light_shader.set_vec3("light_diffuse", light_diffuse);
model = glm::translate(glm::mat4(1.0f), point_light_positions[i]); light.draw_instanced(light_shader, point_light_positions.size());
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);
}
#endif #endif
// Draw skybox // Draw skybox
glDisable(GL_CULL_FACE);
skybox_shader.activate(); skybox_shader.activate();
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap); glBindTexture(GL_TEXTURE_CUBE_MAP, cubemap);
@ -803,7 +828,7 @@ void Mesh::setup_mesh() {
glEnableVertexAttribArray(2); glEnableVertexAttribArray(2);
} }
void Mesh::draw(Shader &shader) { void Mesh::set_mesh_textures_for_drawing(Shader &shader) {
unsigned int diffuse = 1; unsigned int diffuse = 1;
unsigned int specular = 1; unsigned int specular = 1;
unsigned int index; 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); shader.set_int(texture.name(index).c_str(), texture.texture_unit - GL_TEXTURE0);
texture.activate(); texture.activate();
} }
}
void Mesh::activate() {
glBindVertexArray(vao); 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); 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); glBindVertexArray(0);
} }