From c50095cab023e91ba2a4fec8dcb290e6d817124b Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Mon, 6 Dec 2010 21:33:34 +0000 Subject: Re-enabled environment mapping with the skybox as cubemap. --- src/render/textures.cc | 201 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 170 insertions(+), 31 deletions(-) (limited to 'src/render/textures.cc') diff --git a/src/render/textures.cc b/src/render/textures.cc index e252f2d..ad1d8d1 100644 --- a/src/render/textures.cc +++ b/src/render/textures.cc @@ -10,9 +10,6 @@ #include "render/gl.h" #include "render/image.h" #include "render/textures.h" -#include "render/tgafile.h" -#include "render/pngfile.h" -#include "render/jpgfile.h" #include "render/state.h" #include "sys/sys.h" @@ -24,6 +21,7 @@ namespace render std::map Textures::registry; GLuint Textures::textures[MAXTEXTURES]; math::Vector2f Textures::texture_size[MAXTEXTURES]; +std::string textures_cubemapname; void material_loader_func(model::Material *material) { @@ -84,6 +82,8 @@ void Textures::clear() registry.clear(); memset(textures, 0, sizeof(textures)); + + textures_cubemapname.clear(); } void Textures::unload(const std::string &name) @@ -118,6 +118,169 @@ void Textures::unload(const size_t id) } } +void Textures::load_cubemap(const std::string & name) +{ + if (textures_cubemapname.compare(name) == 0) { + // cubemap is already loaded + return; + } + + textures_cubemapname.assign(name); + +const GLenum cube_map[6] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z + + }; + + Image *cube_texture[6] = { + Image::load(name + "_front"), + Image::load(name + "_back"), + Image::load(name + "_left"), + Image::load(name + "_right"), + Image::load(name + "_up"), + Image::load(name + "_down") + + }; + + if (cube_texture[0]) { + Image *image = cube_texture[0]; + + if (image->width() != image->height()) { + con_warn << " " << name << "_front: non-square sky texture!" << std::endl; + } else { + unsigned char pixel_data[image->channels()]; + + for (size_t y = 0; y < image->height(); y++) { + for (size_t x = y +1; x < image->width(); x++) { + void *src = image->pixel(x, y); + void *dst = image->pixel(y, x); + memcpy(pixel_data, dst, image->channels()); + memcpy(dst, src, image->channels()); + memcpy(src, pixel_data, image->channels()); + } + + } + } + } + + if (cube_texture[1]) { + Image *image = cube_texture[1]; + + if (image->width() != image->height()) { + con_warn << " " << name << "_back: non-square sky texture!" << std::endl; + } else { + unsigned char pixel_data[image->channels()]; + + for (size_t y = 0; y < image->height(); y++) { + for (size_t x = y +1; x < image->width(); x++) { + void *src = image->pixel(image->width() - x - 1, y); + void *dst = image->pixel(image->height() - y - 1, x); + memcpy(pixel_data, dst, image->channels()); + memcpy(dst, src, image->channels()); + memcpy(src, pixel_data, image->channels()); + } + + } + } + } + + if (cube_texture[2]) { + cube_texture[2]->flip_vertical(); + } + + if (cube_texture[3]) { + cube_texture[3]->flip_horizontal(); + } + + if (cube_texture[4]) { + Image *image = cube_texture[4]; + + if (image->width() != image->height()) { + con_warn << " " << name << "_back: non-square sky texture!" << std::endl; + } else { + unsigned char pixel_data[image->channels()]; + + for (size_t y = 0; y < image->height(); y++) { + for (size_t x = y +1; x < image->width(); x++) { + void *src = image->pixel(x, y); + void *dst = image->pixel(y, x); + memcpy(pixel_data, dst, image->channels()); + memcpy(dst, src, image->channels()); + memcpy(src, pixel_data, image->channels()); + } + + } + } + } + + if (cube_texture[5]) { + Image *image = cube_texture[5]; + + if (image->width() != image->height()) { + con_warn << " " << name << "_down: non-square sky texture!" << std::endl; + } else { + unsigned char pixel_data[image->channels()]; + + for (size_t y = 0; y < image->height(); y++) { + for (size_t x = y +1; x < image->width(); x++) { + void *src = image->pixel(x, y); + void *dst = image->pixel(y, x); + memcpy(pixel_data, dst, image->channels()); + memcpy(dst, src, image->channels()); + memcpy(src, pixel_data, image->channels()); + } + + } + } + } + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + 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); + + // 4 levels of mipmaps + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 4); + + if (r_mipmap->value()) { + // hardware generated mipmaps (requires OpenGL 1.4) + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE); + } + + for (size_t i = 0; i < 6; i++) { + if (cube_texture[i]) { + int texture_format; + int texture_internalformat; + + if (cube_texture[i]->channels() == 4) { + texture_format = GL_RGBA; + texture_internalformat = GL_RGBA8; + } else { + texture_format = GL_RGB; + texture_internalformat = GL_RGB8; + } + + if (r_mipmap->value() <= 0) { + gluBuild2DMipmaps(cube_map[i], + texture_internalformat, cube_texture[i]->width(), cube_texture[i]->height(), + texture_format, GL_UNSIGNED_BYTE, cube_texture[i]->ptr()); + } else { + glTexImage2D(cube_map[i], 0, + texture_internalformat, cube_texture[i]->width(), cube_texture[i]->height(), 0, + texture_format, GL_UNSIGNED_BYTE, cube_texture[i]->ptr()); + } + + delete cube_texture[i]; + } + } +} + size_t Textures::load(const char *name, const bool filter) { if (name) @@ -144,33 +307,9 @@ size_t Textures::load(const std::string &name, const bool filter) return 0; } - std::string filename; - Image *image = 0; - - if (!image) { - // try the png version - filename.assign(name); - filename.append(".png"); - image = PNG::load(filename.c_str()); - } - - if (!image) { - // try the tga version - filename.assign(name); - filename.append(".tga"); - image = TGA::load(filename.c_str()); - } - - if (!image) { - // try the jpg version - filename.assign(name); - filename.append(".jpg"); - image = JPG::load(filename.c_str()); - } - + Image *image = Image::load(name); if (!image) { // add to the registry with id 0 (texture not found) - con_warn << "Could not open texture " << name << std::endl; registry[name] = 0; return 0; } @@ -183,7 +322,7 @@ size_t Textures::load(const std::string &name, const bool filter) if (filter) { // scaling functions - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 4 levels of mipmaps glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 4); @@ -219,11 +358,11 @@ size_t Textures::load(const std::string &name, const bool filter) if (filter && (r_mipmap->value() <= 0)) { gluBuild2DMipmaps(GL_TEXTURE_2D, texture_internalformat, image->width(), image->height(), - texture_format, GL_UNSIGNED_BYTE, image->data()); + texture_format, GL_UNSIGNED_BYTE, image->ptr()); } else { glTexImage2D(GL_TEXTURE_2D, 0, texture_internalformat, image->width(), image->height(), 0, - texture_format, GL_UNSIGNED_BYTE, image->data()); + texture_format, GL_UNSIGNED_BYTE, image->ptr()); } // add to the registry -- cgit v1.2.3