perlin-shadows/src/point_light.cpp

127 lines
4.4 KiB
C++

#include "point_light.h"
#include <array>
#include <glm/ext/matrix_clip_space.hpp>
#include <glm/ext/matrix_transform.hpp>
#include <iostream>
#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<Renderable *> &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<float>() / 2, 1.0f, kNearPlane, kFarPlane);
auto shadowTransforms = array<glm::mat4, 6>();
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);
}