#pragma once #include #include #include #include #include #include #include "dbc.hpp" struct Material { glm::vec3 ambient{0.1f,0.1f,0.1f}; float shininess{32.0f}; unsigned int diffuseMap = 0; unsigned int specularMap = 0; }; struct Light { glm::vec3 position{0.0f, 0.0f, 0.0f}; glm::vec3 direction{0.0f, 0.0f, 0.0f}; glm::vec3 ambient{0.0f, 0.0f, 0.0f}; glm::vec3 diffuse{0.0f, 0.0f, 0.0f}; glm::vec3 specular{0.0f, 0.0f, 0.0f}; float constant=0.0f; float linear=0.0f; float quadratic=0.0f; float cutOff=0.0f; float outerCutOff=0.0f; void adjust(float amount) { ambient += amount; diffuse += amount; specular += amount; } }; #define NR_POINT_LIGHTS 4 struct Lighting { Light directional; std::vector positioned; Light spot; }; class Shader { public: unsigned int ID = UINT_MAX; Shader(const char* vertexPath, const char* fragmentPath); unsigned int load_shader(const std::string& filename, GLenum shader_type); void use() const; void setBool(const std::string &name, bool value) const; void setInt(const std::string &name, int value) const; void setFloat(const std::string &name, float value) const; void setVec4(const std::string &name, float v1, float v2, float v3, float v4) const; void setVec4(const std::string &name, const glm::vec4& value) const; void setVec3(const std::string &name, float v1, float v2, float v3) const; void setVec3(const std::string &name, const glm::vec3& value) const; void setMat4(const std::string &name, const glm::mat4& what) const; void cleanup(); void applyMaterial(const Material& material) { setVec3("material.ambient", material.ambient); setFloat("material.shininess", material.shininess); } void applyLighting(const Lighting& lighting) { applyDirLight(lighting.directional); setInt("pointLightCount", lighting.positioned.size()); for(size_t i = 0; i < lighting.positioned.size(); i++) { applyPointLight(lighting.positioned[i], i); } applySpotLight(lighting.spot); } void applyDirLight(const Light& light) { setVec3("dirLight.direction", light.direction); setVec3("dirLight.ambient", light.ambient); setVec3("dirLight.diffuse", light.diffuse); setVec3("dirLight.specular", light.specular); } void applyPointLight(const Light& light, size_t index) { dbc::check(index < NR_POINT_LIGHTS, "too many positioned lights"); setVec3(std::format("pointLights[{}].position", index), light.position); setVec3(std::format("pointLights[{}].ambient", index), light.ambient); setVec3(std::format("pointLights[{}].diffuse", index), light.diffuse); setVec3(std::format("pointLights[{}].specular", index), light.specular); setFloat(std::format("pointLights[{}].constant", index), light.constant); setFloat(std::format("pointLights[{}].linear", index), light.linear); setFloat(std::format("pointLights[{}].quadratic", index), light.quadratic); } void applySpotLight(const Light& light) { setVec3("spotLight.position", light.position); setVec3("spotLight.direction", light.direction); setVec3("spotLight.ambient", light.ambient); setVec3("spotLight.diffuse", light.diffuse); setVec3("spotLight.specular", light.specular); setFloat("spotLight.constant", light.constant); setFloat("spotLight.linear", light.linear); setFloat("spotLight.quadratic", light.quadratic); setFloat("spotLight.cutOff", glm::cos(glm::radians(light.cutOff))); setFloat("spotLight.outerCutOff", glm::cos(glm::radians(light.outerCutOff))); } };