#include "point_light.h" #include #include #include #include #include "constants.h" #include "shader.h" using namespace std; PointLight::PointLight(const glm::vec3 &pos) : Renderable(false), pos_(pos) { // Much of this code retrieved and modified 2024/03/31 from // https://learnopengl.com/Advanced-Lighting/Shadows/Point-Shadows // By Joey de Vries (https://twitter.com/JoeyDeVriez) // Licensed CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/legalcode) glGenTextures(1, &depth_); glBindTexture(GL_TEXTURE_CUBE_MAP, depth_); for (auto i = 0; i < 6; ++i) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, kShadowMapSize, kShadowMapSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); } glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); glGenFramebuffers(1, &fbo_); glBindFramebuffer(GL_FRAMEBUFFER, fbo_); glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_, 0); glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); glBindFramebuffer(GL_FRAMEBUFFER, 0); } PointLight::~PointLight() { CleanUp(); glDeleteTextures(1, &depth_); glDeleteFramebuffers(1, &fbo_); } void PointLight::LoadData(const Shader *shader) const { if (!shader->CopyDataToUniform(ambient_, "pointLight.ambient")) { cerr << "Point light ambient not loaded to shader" << endl; } if (!shader->CopyDataToUniform(diffuse_, "pointLight.diffuse")) { cerr << "Point light diffuse not loaded to shader" << endl; } if (!shader->CopyDataToUniform(specularPower_, "pointLight.specularPower")) { cerr << "Point light specular power not loaded to shader" << endl; } if (!shader->CopyDataToUniform(specular_, "pointLight.specular")) { cerr << "Point light specular not loaded to shader" << endl; } if (!shader->CopyDataToUniform(pos_, "pointLight.position")) { cerr << "Point light position not loaded to shader" << endl; } } void PointLight::GenerateCubeMaps( const vector &renderables) const { // Much of this code retrieved and modified 2024/03/31 from // https://learnopengl.com/Advanced-Lighting/Shadows/Point-Shadows // By Joey de Vries (https://twitter.com/JoeyDeVriez) // CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/legalcode) const auto shadowProj = glm::perspective(glm::pi() / 2, 1.0f, kNearPlane, kFarPlane); auto shadowTransforms = array(); shadowTransforms[0] = shadowProj * lookAt(pos_, pos_ + glm::vec3(1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)); shadowTransforms[1] = shadowProj * lookAt(pos_, pos_ + glm::vec3(-1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)); shadowTransforms[2] = shadowProj * lookAt(pos_, pos_ + glm::vec3(0.0, 1.0, 0.0), glm::vec3(0.0, 0.0, 1.0)); shadowTransforms[3] = shadowProj * lookAt(pos_, pos_ + glm::vec3(0.0, -1.0, 0.0), glm::vec3(0.0, 0.0, -1.0)); shadowTransforms[4] = shadowProj * lookAt(pos_, pos_ + glm::vec3(0.0, 0.0, 1.0), glm::vec3(0.0, -1.0, 0.0)); shadowTransforms[5] = shadowProj * lookAt(pos_, pos_ + glm::vec3(0.0, 0.0, -1.0), glm::vec3(0.0, -1.0, 0.0)); glViewport(0, 0, kShadowMapSize, kShadowMapSize); glBindFramebuffer(GL_FRAMEBUFFER, fbo_); glClear(GL_DEPTH_BUFFER_BIT); glUseProgram(shadow_.id()); if (!shadow_.CopyDataToUniform(6, shadowTransforms.data(), "shadowMatrices")) { cerr << "Shadow matrix not in shader" << endl; } if (!shadow_.CopyDataToUniform(pos_, "lightPos")) { cerr << "Light position not in shader" << endl; } if (!shadow_.CopyDataToUniform(kFarPlane, "farPlane")) { cerr << "Far plane not in shader" << endl; } for (const auto renderable : renderables) { renderable->Render(&shadow_); } glBindFramebuffer(GL_FRAMEBUFFER, 0); } void PointLight::SetData() { vertexCount_ = 1; vertices_ = new Vertex({pos_, glm::vec3(0, 0, 1)}); indexCount_ = 1; indices_ = new unsigned int(0); }