added possibility to save a cubemap's face as a file, added specifications for TexturePack

This commit is contained in:
Anselme 2016-07-26 17:36:24 +02:00
parent 7ca0d3d003
commit 1a515f92ec
7 changed files with 128 additions and 25 deletions

View File

@ -3,6 +3,9 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <unordered_map>
class Texture;
struct Image struct Image
{ {
@ -31,14 +34,81 @@ struct Image
bool save(std::vector<unsigned char> &out); bool save(std::vector<unsigned char> &out);
}; };
struct TexturePack class TexturePack
{ {
private:
struct TexImage
{
std::string name;
Texture* tex;
Image* img;
};
std::string m_name; std::string m_name;
std::vector<Image> m_images; std::unordered_map<std::string, Image> m_images;
bool allocatedImg;
bool allocatedTex;
TexturePack(std::string name) : m_name(name) {} public:
TexturePack(const std::string &filename); /**
bool save(const std::string &filename); * @brief creates a new empty texture pack
* the name must be a valid string for a filename :
* (no symbols except underscore, avoid spaces, avoid special characters)
*/
TexturePack(std::string name = "texture_pack") :
m_name(name), allocatedImg(false), allocatedTex(false) {}
/**
* @brief rename renames the texture pack
* the name must be a valid string for a filename :
* (no symbols except underscore, avoid spaces, avoid special characters)
*/
void rename(const std::string &name) { m_name = name; }
/**
* @brief addImage adds an image to the pack, if an image of this name already exists in the pack, it will be replaced.
*/
void addImage(Image* img);
/**
* @brief addImage adds an image from an OpenGL texture and names it with the provided name.
* @param downloadFromGL if this is false, the Image will not be downloaded from the texture, only the texture will be added.
*/
void addImage(Texture* tex, const std::string &name, bool downloadFromGL = true);
/**
* @brief initGL creates an OpenGL texture for every Image in the pack.
*/
void initGL();
/**
* @brief initDestroyImages creates an OpenGL texture for every Image in the pack, and then deletes all Images.
*/
void initDestroyImages();
/**
* @brief getImagesFromGL downloads the images from the opengl texture memory for all available textures
*/
void getImagesFromGL();
/**
* @brief destroyGL destroys all the OpenGL textures of the pack.
*/
void destroyGL();
/**
* @brief loads a texture pack from a folder
* the texture pack name will be the folder name
* every png file in the folder will be loaded in the pack
* and named from the file name minus its extension
*/
TexturePack(const std::string &folderPath);
/**
* @brief saves the texture pack as png images in the specified existing folder
* @return true if serialisation succeeded
*/
bool save(const std::string &folderPath);
}; };
#endif // IMAGE #endif // IMAGE

View File

@ -9,6 +9,7 @@
#include "camera.h" #include "camera.h"
#include <resource.h> #include <resource.h>
#include <glm/ext.hpp> #include <glm/ext.hpp>
#include "image.h"
RESOURCE_PACK(shaders) RESOURCE_PACK(shaders)
@ -335,10 +336,11 @@ void PointLight::updateShadowMap(Scene* scene)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
m_shadowMap->bindFBO(); m_shadowMap->bindFBO();
glViewport(0, 0, m_shadowMapResolution, m_shadowMapResolution); glViewport(0, 0, m_shadowMapResolution, m_shadowMapResolution);
glClearDepth(1.0); glDisable(GL_BLEND);
glClear(GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glClearDepth(0.2);
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
glClear(GL_DEPTH_BUFFER_BIT);
for(SceneIterator<GeometryNode*>* geometryIt = scene->getGeometry(); for(SceneIterator<GeometryNode*>* geometryIt = scene->getGeometry();
geometryIt->isValid(); geometryIt->next()) geometryIt->isValid(); geometryIt->next())
{ {
@ -354,9 +356,20 @@ void PointLight::updateShadowMap(Scene* scene)
node->mesh->draw(m_shaders[shaderId], false, shaderId, false); node->mesh->draw(m_shaders[shaderId], false, shaderId, false);
} }
} }
tempGetShadowMap();
FrameBuffer::screen->bindFBO(); FrameBuffer::screen->bindFBO();
} }
void PointLight::tempGetShadowMap()
{
m_shadowMap->getTexture(0)->getData(0)->save("cubemapFace0.png");
m_shadowMap->getTexture(0)->getData(1)->save("cubemapFace1.png");
m_shadowMap->getTexture(0)->getData(2)->save("cubemapFace2.png");
m_shadowMap->getTexture(0)->getData(3)->save("cubemapFace3.png");
m_shadowMap->getTexture(0)->getData(4)->save("cubemapFace4.png");
m_shadowMap->getTexture(0)->getData(5)->save("cubemapFace5.png");
}
// OLD IMPLEMENTATION // OLD IMPLEMENTATION
/* /*

View File

@ -108,6 +108,8 @@ public:
void destroyShadowMap(); void destroyShadowMap();
void updateShadowMap(Scene* scene); void updateShadowMap(Scene* scene);
void tempGetShadowMap();
private: private:
void updateTransform(); void updateTransform();

View File

@ -4,6 +4,8 @@
#include "texture.h" #include "texture.h"
#include "phongmaterial.h" #include "phongmaterial.h"
Model::Model() : m_texPack(NULL) {}
Model::~Model() Model::~Model()
{ {
destroy(); destroy();
@ -11,7 +13,7 @@ Model::~Model()
for(Mesh *m : m_meshes) for(Mesh *m : m_meshes)
delete m; delete m;
} }
/*
Image* Model::getImage(const std::string &name) Image* Model::getImage(const std::string &name)
{ {
for(TextureImg &tex : m_textures) for(TextureImg &tex : m_textures)
@ -30,7 +32,7 @@ Texture* Model::getTexture(const std::string &name)
return tex.tex; return tex.tex;
} }
return NULL; return NULL;
} }*/
void Model::destroy() void Model::destroy()
{ {
@ -78,7 +80,8 @@ bool Model::save(const std::string &filename, const std::string &texturesPath)
bool ok = false; bool ok = false;
int size = m_meshes.size(); int size = m_meshes.size();
if(std::fwrite(&size, sizeof(int), 1, file)) if(std::fwrite(&size, sizeof(int), 1, file))
{ {
// write meshes and materials, there is no material sharing (1 mesh = 1 material)
ok = true; ok = true;
for(Mesh* m : m_meshes) for(Mesh* m : m_meshes)
{ {
@ -86,14 +89,16 @@ bool Model::save(const std::string &filename, const std::string &texturesPath)
PhongMaterial* mat = (PhongMaterial*)m->getMaterial(); PhongMaterial* mat = (PhongMaterial*)m->getMaterial();
ok = ok && mat->serialize(file); ok = ok && mat->serialize(file);
} }
for(Model::TextureImg &texImg : m_textures) // write texture pack
/*for(Model::TextureImg &texImg : m_textures)
{ {
std::string texFilename = texturesPath + texImg.name + ".png"; std::string texFilename = texturesPath + texImg.name + ".png";
if(texImg.img == NULL && texImg.tex != NULL) if(texImg.img == NULL && texImg.tex != NULL)
texImg.img = texImg.tex->getData(); texImg.img = texImg.tex->getData();
if(texImg.img != NULL) if(texImg.img != NULL)
ok = ok && texImg.img->save(texFilename); ok = ok && texImg.img->save(texFilename);
} }*/
std::fclose(file); std::fclose(file);
} }

View File

@ -6,12 +6,12 @@
class Mesh; class Mesh;
class Image; class Image;
class Texture; class TexturePack;
class Model class Model
{ {
protected: protected:
struct TextureImg /*struct TextureImg
{ {
std::string name; std::string name;
Texture* tex; Texture* tex;
@ -19,12 +19,16 @@ protected:
TextureImg(const std::string n, Image* i) : TextureImg(const std::string n, Image* i) :
name(n), tex(NULL), img(i) {} name(n), tex(NULL), img(i) {}
}; };*/
TexturePack *m_texPack;
std::vector<Mesh*> m_meshes; std::vector<Mesh*> m_meshes;
std::vector<TextureImg> m_textures;
//std::vector<TextureImg> m_textures;
public: public:
Model();
~Model(); ~Model();
/** /**
@ -35,10 +39,10 @@ public:
/** /**
* @brief addImage adds an image to the texture pack * @brief addImage adds an image to the texture pack
*/ */
void addImage(const std::string &name, Image* img) /*void addImage(const std::string &name, Image* img)
{ {
m_textures.push_back(TextureImg(name, img)); m_textures.push_back(TextureImg(name, img));
} }*/
/** /**
* @brief getMeshes returns the mesh array * @brief getMeshes returns the mesh array
@ -48,15 +52,16 @@ public:
/** /**
* @brief getImage returns the image which has the specified name, or NULL if there are no images of this name. * @brief getImage returns the image which has the specified name, or NULL if there are no images of this name.
*/ */
Image* getImage(const std::string &name); //Image* getImage(const std::string &name);
/** /**
* @brief getTexture returns the texture which has the specified name, or NULL if there are no images of this name. * @brief getTexture returns the texture which has the specified name, or NULL if there are no images of this name.
*/ */
Texture* getTexture(const std::string &name); //Texture* getTexture(const std::string &name);
/** /**
* @brief destroy frees Mesh and Image memory in the RAM, but it stays allocated in GPU memory. * @brief destroy frees Mesh and Image memory in the RAM, but it stays allocated in GPU memory.
* (not supported yet when rendering because of flags)
*/ */
void destroy(); void destroy();

View File

@ -162,7 +162,7 @@ void Texture::unbind()
glBindTexture(m_target, 0); glBindTexture(m_target, 0);
} }
Image* Texture::getData() Image* Texture::getData(int faceId)
{ {
bind(); bind();
int nbVal; int nbVal;
@ -172,11 +172,11 @@ Image* Texture::getData()
case GL_RGBA: nbVal = 4; break; case GL_RGBA: nbVal = 4; break;
case GL_RGB: nbVal = 3; break; case GL_RGB: nbVal = 3; break;
case GL_RED: nbVal = 1; break; case GL_RED: nbVal = 1; break;
case GL_DEPTH_COMPONENT: nbVal = 1; break;
default: return NULL; default: return NULL;
} }
switch(m_target) switch(m_target)
{ {
case GL_TEXTURE_CUBE_MAP: nbImages = 6; break;
case GL_TEXTURE_2D_ARRAY: nbImages = 3; break; // TODO : add a member specifying how many layers has the texture case GL_TEXTURE_2D_ARRAY: nbImages = 3; break; // TODO : add a member specifying how many layers has the texture
default: nbImages = 1; break; default: nbImages = 1; break;
} }
@ -188,6 +188,9 @@ Image* Texture::getData()
img->height = m_height; img->height = m_height;
img->width = m_width; img->width = m_width;
img->allocate(size); img->allocate(size);
glGetTexImage(m_target, 0, m_format, GL_UNSIGNED_BYTE, img->pixels.data()); if(m_target == GL_TEXTURE_CUBE_MAP)
glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X+faceId, 0, m_format, GL_UNSIGNED_BYTE, img->pixels.data());
else
glGetTexImage(m_target, 0, m_format, GL_UNSIGNED_BYTE, img->pixels.data());
return img; return img;
} }

View File

@ -53,7 +53,12 @@ public:
int getWidth() {return m_width;} int getWidth() {return m_width;}
int getHeight() {return m_height;} int getHeight() {return m_height;}
Image* getData(); /**
* @brief getData downloads the texture data as an Image from GPU memory,
* it is particulary useful to take a screenshot or debugging a framebuffer.
* @param faceId is the id of the face if the texture is a cubemap, must be between 0 and 5
*/
Image* getData(int faceId = 0);
}; };
#endif // TEXTURE_H #endif // TEXTURE_H