From 77e44c5424bd5e6e7c6a706151fa786a56270e12 Mon Sep 17 00:00:00 2001 From: Eleni Maria Stea Date: Thu, 27 Jul 2017 11:32:24 +0300 Subject: [PATCH] srgb textures, cubemap support --- src/gfxapi.cc | 2 +- src/image.cc | 82 ++++++++++++++++++++++++++++++++++++++++++++++ src/image.h | 26 +++++++++++++++ src/opengl/texture-gl.cc | 36 +++++++++++++------- src/opengl/texture-gl.h | 1 + src/renderer.cc | 13 ++++++++ src/renderer.h | 4 +++ src/texture.cc | 55 ++++++++++++++++++++++++++----- src/texture.h | 11 +++++-- 9 files changed, 206 insertions(+), 24 deletions(-) create mode 100644 src/image.cc create mode 100644 src/image.h diff --git a/src/gfxapi.cc b/src/gfxapi.cc index 58692a3..3bda079 100644 --- a/src/gfxapi.cc +++ b/src/gfxapi.cc @@ -100,5 +100,5 @@ char *gfx_get_shader_path() case GFX_VK: return (char *)"vk_shaders"; } - return (char*)""; + return (char *)""; } \ No newline at end of file diff --git a/src/image.cc b/src/image.cc new file mode 100644 index 0000000..2bfdbd8 --- /dev/null +++ b/src/image.cc @@ -0,0 +1,82 @@ +#include + +#include "imago2.h" +#include "image.h" + +Image::Image() +{ + w = h = 0; + pixels = 0; +} + +Image::~Image() +{ + delete [] pixels; +} + +Image::Image(const Image &image) +{ + w = image.w; + h = image.h; + + pixels = new unsigned char[w * h * 4]; + memcpy(pixels, image.pixels, w * h * 4); +} + +Image &Image::operator =(const Image &image) +{ + if(&image == this) + return *this; + + delete [] pixels; + + w = image.w; + h = image.h; + + pixels = new unsigned char[w * h * 4]; + memcpy(pixels, image.pixels, w * h * 4); + + return *this; +} + +Image::Image(Image &&image) +{ + w = image.w; + h = image.h; + + pixels = image.pixels; + image.pixels = 0; +} + +Image &Image::operator =(Image &&image) +{ + if(&image == this) + return *this; + + delete [] pixels; + + w = image.w; + h = image.h; + + pixels = image.pixels; + image.pixels = 0; + + return *this; +} + +bool Image::load(const char *fname) +{ + unsigned char *imago_pixels; + if(!(imago_pixels = (unsigned char *)img_load_pixels(fname, &w, &h))) { + fprintf(stderr, "Failed to load pixels from file: %s.\n", fname); + return false; + } + + delete [] pixels; + pixels = new unsigned char[w * h * 4]; + memcpy(pixels, imago_pixels, w * h * 4); + + img_free_pixels(imago_pixels); + + return true; +} \ No newline at end of file diff --git a/src/image.h b/src/image.h new file mode 100644 index 0000000..d39e750 --- /dev/null +++ b/src/image.h @@ -0,0 +1,26 @@ +#ifndef IMAGE_H_ +#define IMAGE_H_ + +class Image { +public: + int w; + int h; + unsigned char *pixels; + + Image(); + ~Image(); + + Image(const Image &image); + Image &operator =(const Image &image); + + /* + move constructor: called when you assign + an rvalue reference + */ + Image(Image &&image); // rvalue reference + Image &operator =(Image &&image); + + bool load(const char *fname); +}; + +#endif // IMAGE_H_ \ No newline at end of file diff --git a/src/opengl/texture-gl.cc b/src/opengl/texture-gl.cc index 17ea926..607d014 100644 --- a/src/opengl/texture-gl.cc +++ b/src/opengl/texture-gl.cc @@ -5,11 +5,8 @@ TextureGL::TextureGL() { - w = 0; - h = 0; - - pixels = 0; tex = 0; + target = GL_TEXTURE_2D; } TextureGL::~TextureGL() @@ -19,20 +16,37 @@ TextureGL::~TextureGL() void TextureGL::update() { + if(images.empty()) + return; + if(!tex) { + target = is_cubemap() ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; + glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(target, tex); + glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } else { - glBindTexture(GL_TEXTURE_2D, tex); + glBindTexture(target, tex); } - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - glGenerateMipmap(GL_TEXTURE_2D); -} + static const unsigned int faces[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + }; + for(size_t i=0; imesh->update_vertex_data(); object->mesh->draw(); +} + +void Renderer::set_sky_tex(Texture *stex) +{ + skytex = stex; +} + +void Renderer::set_diffuse_sky_tex(Texture *dstex) +{ + dskytex = dstex; } \ No newline at end of file diff --git a/src/renderer.h b/src/renderer.h index 8f19243..efbab80 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -14,6 +14,7 @@ protected: int mmviewproj_loc; int mview_loc; + Texture *skytex, *dskytex; ShaderProgram *sprog; virtual void draw_object(Object *object) const; @@ -26,6 +27,9 @@ public: virtual bool create(); virtual void draw() const; + + virtual void set_sky_tex(Texture *stex); + virtual void set_diffuse_sky_tex(Texture *dstex); }; #endif // RENDERER_H_ \ No newline at end of file diff --git a/src/texture.cc b/src/texture.cc index 624edc2..bbebd7f 100644 --- a/src/texture.cc +++ b/src/texture.cc @@ -1,25 +1,62 @@ -#include "imago2.h" +#include #include "texture.h" Texture::Texture() { - w = 0; - h = 0; - - pixels = 0; } Texture::~Texture() { - img_free_pixels(pixels); } bool Texture::load(const char *fname) { - if(!(pixels = (unsigned char *)img_load_pixels(fname, &w, &h))) { - fprintf(stderr, "Failed to load pixels from file: %s.\n", fname); - return false; + Image img; + + if(img.load(fname)) { + images.clear(); + images.push_back(img); + + update(); + return true; } + + /* check if it is a cubemap */ + return load_cubemap(fname); +} + +bool Texture::load_cubemap(const char *fname) +{ + const char *suffixes[] = { + "_px", "_py", "_pz", + "_nx", "_ny", "_nz" + }; + + for(int i=0; i<6; i++) { + char *buf = new char[strlen(fname) + 3 + 1]; + strcpy(buf, fname); + char *suffix = strrchr(buf, '.'); + + if(suffix) { + memmove(suffix + 3, suffix, strlen(suffix) + 1); + memcpy(suffix, suffixes[i], 3); + } else { + strcat(buf, suffixes[i]); + } + + Image img; + if(!img.load(buf)) { + images.clear(); + return false; + } + images.push_back(img); + } + update(); return true; +} + +bool Texture::is_cubemap() const +{ + return images.size() > 1; } \ No newline at end of file diff --git a/src/texture.h b/src/texture.h index bcf9a92..4fcdbf5 100644 --- a/src/texture.h +++ b/src/texture.h @@ -2,15 +2,16 @@ #define TEXTURE_H_ #include +#include + +#include "image.h" class Texture { private: virtual void update() = 0; protected: - int w; - int h; - unsigned char *pixels; + std::vector images; public: std::string name; @@ -19,6 +20,10 @@ public: virtual ~Texture(); virtual bool load(const char *fname); + virtual bool load_cubemap(const char *fname); + + virtual bool is_cubemap() const; + virtual void bind() = 0; }; -- 1.7.10.4