#include "material.h" #include "../lib/glm/glm.hpp" #include "../lib/glm/gtc/matrix_transform.hpp" #include "light.h" #include "shader.h" #include "state.h" #include "texture.h" Material::Material(const std::shared_ptr& tex, const std::shared_ptr& shader) : shader_(shader) , texture_(tex) , color_(1.0f, 1.0f, 1.0f, 1.0f) , shininess_(0) { } const std::shared_ptr& Material::shader() const { return shader_ ? shader_ : state::default_shader; } std::shared_ptr& Material::shader() { return shader_ ? shader_ : state::default_shader; } void Material::set_shader(const std::shared_ptr& shader) { shader_ = shader; } void Material::prepare() { // Activate shader std::shared_ptr active_shader = shader(); if (!active_shader) return; active_shader->use(); // Set uniform variables const glm::mat4 mvp = state::projection_matrix * state::view_matrix * state::model_matrix; const int mvp_loc = active_shader->uniform_location("mvp"); Shader::set_mat4(mvp_loc, mvp); // Set ModelView matrix const glm::mat4 model_view = state::view_matrix * state::model_matrix; const int model_view_loc = active_shader->uniform_location("modelView"); Shader::set_mat4(model_view_loc, model_view); // Set Normal matrix (transpose of inverse of ModelView) const glm::mat4 normal_matrix = glm::transpose(glm::inverse(model_view)); const int normal_matrix_loc = active_shader->uniform_location("normalMatrix"); Shader::set_mat4(normal_matrix_loc, normal_matrix); // Set material properties const int material_color_loc = active_shader->uniform_location("materialColor"); Shader::set_vec4(material_color_loc, color_); const int shininess_loc = active_shader->uniform_location("shininess"); Shader::set_float(shininess_loc, static_cast(shininess_)); // Set ambient light const int ambient_loc = active_shader->uniform_location("ambientLight"); Shader::set_vec3(ambient_loc, state::ambient); // Set number of lights const int num_lights_loc = active_shader->uniform_location("numLights"); Shader::set_int(num_lights_loc, static_cast(state::lights.size())); // Prepare each light for (size_t i = 0; i < state::lights.size(); ++i) { state::lights[i]->prepare(static_cast(i), active_shader); } // Set texture-related uniforms const int use_texture_loc = active_shader->uniform_location("useTexture"); if (texture_) { Shader::set_int(use_texture_loc, 1); const int sampler_loc = active_shader->uniform_location("texSampler"); Shader::set_int(sampler_loc, 0); // Texture unit 0 } else { Shader::set_int(use_texture_loc, 0); } // Bind texture if available if (texture_) { texture_->bind(); } }