srgb textures, cubemap support
authorEleni Maria Stea <elene.mst@gmail.com>
Thu, 27 Jul 2017 08:32:24 +0000 (11:32 +0300)
committerEleni Maria Stea <elene.mst@gmail.com>
Thu, 27 Jul 2017 08:32:24 +0000 (11:32 +0300)
src/gfxapi.cc
src/image.cc [new file with mode: 0644]
src/image.h [new file with mode: 0644]
src/opengl/texture-gl.cc
src/opengl/texture-gl.h
src/renderer.cc
src/renderer.h
src/texture.cc
src/texture.h

index 58692a3..3bda079 100644 (file)
@@ -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 (file)
index 0000000..2bfdbd8
--- /dev/null
@@ -0,0 +1,82 @@
+#include <string.h>
+
+#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 (file)
index 0000000..d39e750
--- /dev/null
@@ -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
index 17ea926..607d014 100644 (file)
@@ -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; i<images.size(); i++) {
+               int w = images[i].w;
+               int h = images[i].h;
+
+               unsigned char *pixels = images[i].pixels;
+               unsigned int t = is_cubemap() ? faces[i] : GL_TEXTURE_2D;
+               glTexImage2D(t, 0, GL_SRGB_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+       }
+
+       glGenerateMipmap(target);
+}
 
 void TextureGL::bind()
 {
index b443f09..11c48a3 100644 (file)
@@ -6,6 +6,7 @@
 class TextureGL : public Texture {
 private:
        unsigned int tex;
+       unsigned int target;
        
        virtual void update() override;
 public:
index 06efbee..260c3cf 100644 (file)
@@ -16,6 +16,9 @@ Renderer::Renderer()
        scene = 0;
        camera = 0;
        sprog = 0;
+
+       skytex = 0;
+       dskytex = 0;
 }
 
 Renderer::~Renderer()
@@ -104,4 +107,14 @@ void Renderer::draw_object(Object *object) const
 
        object->mesh->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
index 8f19243..efbab80 100644 (file)
@@ -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
index 624edc2..bbebd7f 100644 (file)
@@ -1,25 +1,62 @@
-#include "imago2.h"
+#include <string.h>
 #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
index bcf9a92..4fcdbf5 100644 (file)
@@ -2,15 +2,16 @@
 #define TEXTURE_H_
 
 #include <string>
+#include <vector>
+
+#include "image.h"
 
 class Texture {
 private:
        virtual void update() = 0;
 
 protected:
-       int w;
-       int h;
-       unsigned char *pixels;
+       std::vector<Image> 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;
 };