diff --git a/src/light.cpp b/src/light.cpp index 848cb2e..0c46fcb 100644 --- a/src/light.cpp +++ b/src/light.cpp @@ -27,11 +27,23 @@ const glm::mat4 Light::biasMatrix( 0.0, 0.0, 0.5, 0.0, 0.5, 0.5, 0.5, 1.0); +const glm::mat4 PointLight::m_viewMatrices[6] = +{ + glm::lookAt(glm::vec3(0), glm::vec3(1, 0, 0 ), glm::vec3(0,-1, 0 )), + glm::lookAt(glm::vec3(0), glm::vec3(-1,0, 0 ), glm::vec3(0,-1, 0 )), + glm::lookAt(glm::vec3(0), glm::vec3(0, 1, 0 ), glm::vec3(0, 0, 1 )), + glm::lookAt(glm::vec3(0), glm::vec3(0, -1,0 ), glm::vec3(0, 0, -1)), + glm::lookAt(glm::vec3(0), glm::vec3(0, 0, 1 ), glm::vec3(0,-1, 0 )), + glm::lookAt(glm::vec3(0), glm::vec3(0, 0, -1), glm::vec3(0,-1, 0 )) +}; + void AmbientLight::bindAttributes(Shader *shader, Camera *camera) { shader->bindVec3(shader->getLocation("lightColor"), m_color); } +// DIRECTIONNAL LIGHT + int DirectionnalLight::m_shaderRefCounter = 0; Shader* DirectionnalLight::m_shaders[4] = {NULL}; @@ -218,6 +230,119 @@ void DirectionnalLight::updateShadowMap(Scene* scene) } } } + +// POINT LIGHT + +int PointLight::m_shaderRefCounter = 0; +Shader* PointLight::m_shaders[2] = {NULL}; + +PointLight::PointLight(glm::vec3 pos, float attenuation, glm::vec3 lightColor) : + m_position(pos), + m_attenuation(attenuation), + m_shadowCaster(false) + +{ + m_color = lightColor; + m_shadowMap = NULL; +} + +void PointLight::bindAttributes(Shader *shader, Camera *camera) +{ + glm::vec4 posInView = camera->getViewMatrix() * glm::vec4(m_position.x, m_position.y, m_position.z, 1.f); + shader->bindVec3(shader->getLocation("lightColor"), m_color); + shader->bindVec3(shader->getLocation("pointLight"), glm::vec3(posInView)); + shader->bindFloat(shader->getLocation("attenuation"), m_attenuation); + if(m_shadowCaster) + { + m_shadowMap->getTexture(0)->bind(7); // TODO use something else than 7 + shader->bindInteger(shader->getLocation("shadowMap"), 7); + } +} + +unsigned int PointLight::getFlags() +{ + unsigned int flag = 1 << POINT_FLAG; + if(m_shadowCaster) + flag |= 1 << SHADOWMAP_FLAG; + return flag; +} + +void PointLight::initShadowMap(int resolution) +{ + m_shadowMapResolution = resolution; + + // shader compilation + if(m_shaderRefCounter == 0) + { + ShaderSource source; + Resource::ResourceMap shaderMap; + Resource::getResourcePack_shaders(shaderMap); + source.setSource(shaderMap["shaders/shadow.vert.glsl"], ShaderSource::VERTEX); + source.setSource(shaderMap["shaders/shadow.geom.glsl"], ShaderSource::GEOMETRY); + source.setSource(shaderMap["shaders/shadow.frag.glsl"], ShaderSource::FRAGMENT); + unsigned int flag = 1 << POINT_FLAG; + m_shaders[0] = source.compile(Mesh::MESH_3D, flag); + m_shaders[1] = source.compile(Mesh::MESH_3D & Mesh::MATERIAL_ALPHA_MASK, flag); + } + if(!m_shadowCaster) + ++m_shaderRefCounter; + m_shadowCaster = true; + + // Depth buffer + Texture *tex = new Texture(GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, resolution, resolution, GL_FLOAT, GL_TEXTURE_CUBE_MAP); + tex->setParameter(GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + tex->setParameter(GL_TEXTURE_COMPARE_FUNC, GL_LESS); + + // framebuffer + m_shadowCaster = true; + m_shadowMap = new FrameBuffer(); + m_shadowMap->addTexture(tex, GL_DEPTH_ATTACHMENT); + m_shadowMap->initColorAttachments(); +} + +void PointLight::destroyShadowMap() +{ + if(m_shadowCaster) + { + m_shadowCaster = false; + --m_shaderRefCounter; + if(m_shaderRefCounter == 0) + { + for(int i=0; i<2; ++i) + delete m_shaders[i]; + } + if(m_shadowMap != NULL) + delete m_shadowMap; + } + m_shadowMap = NULL; +} + +void PointLight::updateShadowMap(Scene* scene) +{ + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glViewport(0, 0, m_shadowMapResolution, m_shadowMapResolution); + m_shadowMap->bindFBO(); + glClearDepth(1.0); + glClear(GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + for(SceneIterator* geometryIt = scene->getGeometry(); + geometryIt->isValid(); geometryIt->next()) + { + GeometryNode* node = geometryIt->getItem(); + if(node->mesh->getFlags() & (1 << Mesh::MESH_SHADOWED)) + { + int shaderId = (node->mesh->getFlags() & (1 << Mesh::MATERIAL_ALPHA_MASK)) != 0; + + m_shaders[shaderId]->bind(); + m_shaders[shaderId]->bindMat4(m_shaders[shaderId]->getLocation("modelMatrix"), node->modelMatrix); + m_shaders[shaderId]->bindMat4(m_shaders[shaderId]->getLocation("projectionMatrix"), m_projectionMatrix); + m_shaders[shaderId]->bindMat4Array(m_shaders[shaderId]->getLocation("viewMatrices"), m_viewMatrices, 6); + m_shaders[shaderId]->bindVec3(m_shaders[shaderId]->getLocation("pointLight"), m_position); + node->mesh->draw(m_shaders[shaderId], false, shaderId, false); + } + } +} // OLD IMPLEMENTATION diff --git a/src/light.h b/src/light.h index ffd5ed7..bf6fc6e 100644 --- a/src/light.h +++ b/src/light.h @@ -89,4 +89,37 @@ private: static Shader* m_shaders[4]; }; +class PointLight : public Light +{ +public: + PointLight(glm::vec3 pos = glm::vec3(0), float attenuation = 1, glm::vec3 lightColor = glm::vec3(1)); + + glm::vec3 getPos() { return m_position; } + float getAttenuation() { return m_attenuation; } + + void setPos(glm::vec3 pos) { m_position = pos; /* TODO : update projection matrix */ } + void setAttenuation(float attenuation) { m_attenuation = attenuation; } + + virtual LightType getType() { return POINT; } + virtual void bindAttributes(Shader *shader, Camera *camera); + virtual unsigned int getFlags(); + + void initShadowMap(int resolution); + void destroyShadowMap(); + void updateShadowMap(Scene* scene); + +private: + glm::vec3 m_position; + float m_attenuation; + + bool m_shadowCaster; + int m_shadowMapResolution; + FrameBuffer* m_shadowMap; + static const glm::mat4 m_viewMatrices[6]; + glm::mat4 m_projectionMatrix; + + static int m_shaderRefCounter; + static Shader* m_shaders[2]; +}; + #endif // LIGHT_H diff --git a/src/mesh.cpp b/src/mesh.cpp index 2c61529..061c6dd 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -32,7 +32,8 @@ const char* const Mesh::flagStr[Mesh::NB_FLAGS] = "BUMP_MAP" }; -Mesh::Mesh() : +Mesh::Mesh(const std::string &name) : + m_name(name), material(NULL), isDoubleSided(false), isBillboard(false), diff --git a/src/mesh.h b/src/mesh.h index 53e071a..a9a0069 100644 --- a/src/mesh.h +++ b/src/mesh.h @@ -3,6 +3,7 @@ #include "opengl.h" #include +#include #include #include @@ -86,9 +87,12 @@ public: /** * @brief Mesh builds an empty mesh, to be renderable, a mesh must have vertices and a material. */ - Mesh(); + Mesh(const std::string &name = "mesh"); ~Mesh(); - + + void setName(const std::string &name) { m_name = name; } + std::string getName() { return m_name; } + /** * OpenGL methods : * - initGL allocates the GPU buffers and sends the mesh data to the GPU @@ -206,7 +210,8 @@ public: void setPrimitiveType(GLenum type) {primitive_type = type;} protected: - + std::string m_name; + Material* material; bool isDoubleSided; bool isBillboard; diff --git a/src/parametricmesh.cpp b/src/parametricmesh.cpp index d9a2094..29479b0 100644 --- a/src/parametricmesh.cpp +++ b/src/parametricmesh.cpp @@ -8,7 +8,7 @@ Mesh* MeshGenerator::generateParametricMesh(Material* mat, int width, int height, float size, bool alternate) { m_size = size; - m_mesh = new Mesh(); + m_mesh = new Mesh("parametric_mesh"); m_mesh->setMaterial(mat); for(int i=0; i<=width; ++i) @@ -46,7 +46,7 @@ Mesh* MeshGenerator::generateParametricMesh(Material* mat, int width, int height Mesh* MeshGenerator::generateGeodesicMesh(Material* mat, int n, float size) { m_size = size; - m_mesh = new Mesh(); + m_mesh = new Mesh("geodesic_mesh"); m_mesh->setMaterial(mat); // icosahedron : diff --git a/src/serializers.cpp b/src/serializers.cpp index 7680c4c..a727123 100644 --- a/src/serializers.cpp +++ b/src/serializers.cpp @@ -19,6 +19,7 @@ struct MeshHeader int depth; int nbInstances_offsets; int nbIndices; + int nameLength; }; struct MaterialHeader @@ -85,6 +86,7 @@ bool saveMesh(const std::string &filename, Mesh *mesh) } header.nbIndices = mesh->indices.size(); header.nbInstances_offsets = mesh->instances_offsets.size(); + header.nameLength = mesh->getName().size(); // serializing bool ok = false; @@ -99,9 +101,18 @@ bool saveMesh(const std::string &filename, Mesh *mesh) bool serializeMesh(Mesh* mesh, const MeshHeader &header, FILE *file) { // writing header - size_t nbWritten = std::fwrite(&header, sizeof(MeshHeader), 1, file); + size_t nbWritten; + + nbWritten = std::fwrite(&header, sizeof(MeshHeader), 1, file); if(nbWritten != 1) return false; + + if(header.nameLength != 0) + { + nbWritten = std::fwrite(mesh->getName().data(), header.nameLength, 1, file); + if(nbWritten != 1) + return false; + } // writing buffers if(header.flags & (1 << Mesh::MESH_3D)) @@ -206,6 +217,15 @@ Mesh* loadMesh(const std::string &filename) bool deserializeMesh(Mesh* mesh, const MeshHeader &header, FILE *file) { + std::string name = "mesh"; + if(header.nameLength != 0) + { + name.resize(header.nameLength); + if(!fread(&(name[0]), header.nameLength, 1, file)) + return false; + } + mesh->setName(name); + if(header.flags & (1 << Mesh::MESH_3D)) { mesh->positions3D.reserve(header.nbPositions); diff --git a/src/shader.cpp b/src/shader.cpp index 6528500..343a9c4 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -162,32 +162,37 @@ void Shader::bindFloat(GLuint location, float val) glUniform1f(location, val); } -void Shader::bindMat3(GLuint location, glm::mat3 mat) +void Shader::bindMat3(GLuint location, const glm::mat3 &mat) { glUniformMatrix3fv(location, 1, GL_FALSE, glm::value_ptr(mat)); } -void Shader::bindMat4(GLuint location, glm::mat4 mat) +void Shader::bindMat4(GLuint location, const glm::mat4 &mat) { glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(mat)); } -void Shader::bindVec2(GLuint location, glm::vec2 vec) +void Shader::bindMat4Array(GLuint location, const glm::mat4 *matrices, int nbMat) +{ + glUniformMatrix4fv(location, nbMat, GL_FALSE, (GLfloat*)matrices); +} + +void Shader::bindVec2(GLuint location, const glm::vec2 &vec) { glUniform2fv(location, 1, glm::value_ptr(vec)); } -void Shader::bindVec3(GLuint location, glm::vec3 vec) +void Shader::bindVec3(GLuint location, const glm::vec3 &vec) { glUniform3fv(location, 1, glm::value_ptr(vec)); } -void Shader::bindVec4(GLuint location, glm::vec4 vec) +void Shader::bindVec4(GLuint location, const glm::vec4 &vec) { glUniform4fv(location, 1, glm::value_ptr(vec)); } -void Shader::bindVec3Array(GLuint location, glm::vec3* vec, int nb_elements) +void Shader::bindVec3Array(GLuint location, const glm::vec3* vec, int nb_elements) { glUniform3fv(location, nb_elements, (GLfloat*)vec); } diff --git a/src/shader.h b/src/shader.h index 3f70d2b..47055cf 100644 --- a/src/shader.h +++ b/src/shader.h @@ -21,12 +21,13 @@ public: void bind(); void unbind(); void bindFloat(GLuint location, float val); - void bindMat3(GLuint location, glm::mat3 mat); - void bindMat4(GLuint location, glm::mat4 mat); - void bindVec2(GLuint location, glm::vec2 vec); - void bindVec3(GLuint location, glm::vec3 vec); - void bindVec4(GLuint location, glm::vec4 vec); - void bindVec3Array(GLuint location, glm::vec3* vec, int nb_elements); + void bindMat3(GLuint location, const glm::mat3 &mat); + void bindMat4(GLuint location, const glm::mat4 &mat); + void bindMat4Array(GLuint location, const glm::mat4 *matrices, int nbMat); + void bindVec2(GLuint location, const glm::vec2 &vec); + void bindVec3(GLuint location, const glm::vec3 &vec); + void bindVec4(GLuint location, const glm::vec4 &vec); + void bindVec3Array(GLuint location, const glm::vec3* vec, int nb_elements); void bindUnsignedInteger(GLuint location, GLuint unsigned_integer); void bindInteger(GLuint location, GLint integer); };