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/Makefile.am | 2 - src/render/draw.cc | 122 +++++++++++++++++++++++----- src/render/gl.cc | 5 ++ src/render/gl.h | 3 + src/render/image.cc | 61 +++++++++++++- src/render/image.h | 14 +++- src/render/render.cc | 7 -- src/render/screenshot.cc | 4 +- src/render/sky.cc | 158 ------------------------------------- src/render/sky.h | 35 --------- src/render/textures.cc | 201 +++++++++++++++++++++++++++++++++++++++-------- src/render/textures.h | 3 + src/render/tgafile.cc | 8 +- 13 files changed, 358 insertions(+), 265 deletions(-) delete mode 100644 src/render/sky.cc delete mode 100644 src/render/sky.h (limited to 'src/render') diff --git a/src/render/Makefile.am b/src/render/Makefile.am index 2e97501..31ba73d 100644 --- a/src/render/Makefile.am +++ b/src/render/Makefile.am @@ -20,7 +20,6 @@ noinst_HEADERS = \ render.h \ renderext.h \ screenshot.h \ - sky.h \ state.h \ text.h \ textures.h \ @@ -40,7 +39,6 @@ librender_la_SOURCES = \ render.cc \ renderext.cc \ screenshot.cc \ - sky.cc \ state.cc \ text.cc \ textures.cc \ diff --git a/src/render/draw.cc b/src/render/draw.cc index 1e166b3..7511598 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -19,7 +19,6 @@ #include "render/draw.h" #include "render/dust.h" #include "render/gl.h" -#include "render/sky.h" #include "math/functions.h" namespace render @@ -157,7 +156,13 @@ void pass_prepare(float seconds) } /* ----- Skybox ---------------------------------------------------- */ - +/* +* To use quake3 skyboxes: +* switch left and right images +* rotate top image 90 degrees clockwise +* rotate bottom image 90 degrees counter-clockwise +* +*/ void draw_pass_sky() { if (!(r_sky && r_sky->value())) @@ -169,7 +174,59 @@ void draw_pass_sky() if (!core::localplayer()->zone()->sky().size()) return; - Sky::draw(core::localplayer()->zone()->sky(), (r_wireframe && r_wireframe->value())); + Textures::load_cubemap("textures/sky/" + core::localplayer()->zone()->sky()); + + gl::push(); + gl::translate(Camera::eye()); + + gl::color(1.0f, 1.0f, 1.0f, 1.0f); + gl::enable(GL_TEXTURE_CUBE_MAP); + + gl::begin((r_wireframe && r_wireframe->value()) ? gl::LineLoop : gl::Quads); + + // front + gl::texcoord(1, 1, 1); gl::vertex(1, 1, 1); + gl::texcoord(1, -1, 1); gl::vertex(1, -1, 1); + gl::texcoord(1, -1, -1); gl::vertex(1, -1, -1); + gl::texcoord(1, 1, -1); gl::vertex(1, 1, -1); + + // right + gl::texcoord(1, -1, 1); gl::vertex(1, -1, 1); + gl::texcoord(-1, -1, 1); gl::vertex(-1, -1, 1); + gl::texcoord(-1, -1, -1); gl::vertex(-1, -1, -1); + gl::texcoord(1, -1, -1); gl::vertex(1, -1, -1); + + // back + gl::texcoord(-1, -1, 1); gl::vertex(-1, -1, 1); + gl::texcoord(-1, 1, 1); gl::vertex(-1, 1, 1); + gl::texcoord(-1, 1, -1); gl::vertex(-1, 1, -1); + gl::texcoord(-1, -1, -1); gl::vertex(-1, -1, -1); + + // left + gl::texcoord(-1, 1, 1); gl::vertex(-1, 1, 1); + gl::texcoord(1, 1, 1); gl::vertex(1, 1, 1); + gl::texcoord(1, 1, -1); gl::vertex(1, 1, -1); + gl::texcoord(-1, 1, -1); gl::vertex(-1, 1, -1); + + // up + gl::texcoord(-1, 1, 1); gl::vertex(-1, 1, 1); + gl::texcoord(-1, -1, 1); gl::vertex(-1, -1, 1); + gl::texcoord(1, -1, 1); gl::vertex(1, -1, 1); + gl::texcoord(1, 1, 1); gl::vertex(1, 1, 1); + + // down + gl::texcoord(1, 1, -1); gl::vertex(1, 1, -1); + gl::texcoord(1, -1, -1); gl::vertex(1, -1, -1); + gl::texcoord(-1, -1, -1); gl::vertex(-1, -1, -1); + gl::texcoord(-1, 1, -1); gl::vertex(-1, 1, -1); + + gl::end(); + + gl::disable(GL_TEXTURE_CUBE_MAP); + + gl::pop(); + + Stats::quads += 6; } @@ -595,7 +652,13 @@ void draw_model_fragments(model::Model *model, // TODO this should probably be initialized somewhere else gl::texgeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); gl::texgeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - + + /* + gl::texgeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + gl::texgeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + gl::texgeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + */ + for (model::Model::Groups::const_iterator git = model->groups().begin(); git != model->groups().end(); git++) { const model::FragmentGroup *group = (*git); @@ -688,34 +751,47 @@ void draw_model_fragments(model::Model *model, if (material->flags() & model::Material::Environment) { if (!(material->flags() & model::Material::Texture)) { - /* - // use sky as envmap if the material defines no texture - // FIXME broken since skybox - if (core::localplayer()->zone()->sky_texture()) { - Textures::bind(core::localplayer()->zone()->sky_texture()); - gl::enable(GL_TEXTURE_2D); - use_texture = true; - } else - */ + if (use_texture) { gl::disable(GL_TEXTURE_2D); use_texture = false; } - } - - if (!use_env) { - // enable env mapping + + // use sky as envmap if the material doesn't define a texture + if (core::localplayer()->zone()->sky().size()) { + gl::enable(GL_TEXTURE_CUBE_MAP); + + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + + gl::enable(GL_TEXTURE_GEN_S); + gl::enable(GL_TEXTURE_GEN_T); + gl::enable(GL_TEXTURE_GEN_R); + use_env = true; + } + + } else { + + gl::texgeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + gl::texgeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + gl::enable(GL_TEXTURE_GEN_S); gl::enable(GL_TEXTURE_GEN_T); use_env = true; + + if (!use_texture) { + gl::enable(GL_TEXTURE_2D); + use_texture = true; + } } - } else { - if (use_env) { // disable env mapping gl::disable(GL_TEXTURE_GEN_S); gl::disable(GL_TEXTURE_GEN_T); + gl::disable(GL_TEXTURE_GEN_R); + gl::disable(GL_TEXTURE_CUBE_MAP); use_env = false; } } @@ -739,6 +815,8 @@ void draw_model_fragments(model::Model *model, // disable env mapping gl::disable(GL_TEXTURE_GEN_S); gl::disable(GL_TEXTURE_GEN_T); + gl::disable(GL_TEXTURE_GEN_R); + gl::disable(GL_TEXTURE_CUBE_MAP); use_env = false; } @@ -767,6 +845,8 @@ void draw_model_fragments(model::Model *model, // disable env mapping gl::disable(GL_TEXTURE_GEN_S); gl::disable(GL_TEXTURE_GEN_T); + gl::disable(GL_TEXTURE_GEN_R); + gl::disable(GL_TEXTURE_CUBE_MAP); use_env = false; } @@ -793,12 +873,12 @@ void draw_model_fragments(model::Model *model, // disable env mapping gl::disable(GL_TEXTURE_GEN_S); gl::disable(GL_TEXTURE_GEN_T); - use_env = false; + gl::disable(GL_TEXTURE_GEN_R); + gl::disable(GL_TEXTURE_CUBE_MAP); } if (use_texture) { gl::disable(GL_TEXTURE_2D); - use_texture = false; } } diff --git a/src/render/gl.cc b/src/render/gl.cc index fa7c092..ebba733 100644 --- a/src/render/gl.cc +++ b/src/render/gl.cc @@ -178,6 +178,11 @@ void texcoord(const math::Vector2f& vector) glTexCoord2fv(vector.ptr()); } +void texcoord(const float x, const float y, const float z) +{ + glTexCoord3f(x, y, z); +} + void push() { glPushMatrix(); diff --git a/src/render/gl.h b/src/render/gl.h index fc2237e..c230547 100644 --- a/src/render/gl.h +++ b/src/render/gl.h @@ -146,6 +146,9 @@ void texcoord(const float x, const float y); /// glTexCoord void texcoord(const math::Vector2f& vector); +/// glTexCoord +void texcoord(const float x, const float y, const float z); + /// glNormal void normal(const math::Vector3f & vector); diff --git a/src/render/image.cc b/src/render/image.cc index 98898ef..9019daf 100644 --- a/src/render/image.cc +++ b/src/render/image.cc @@ -4,10 +4,17 @@ the terms of the GNU General Public License version 2 */ -#include -#include +#include + +#include +#include + +#include "sys/sys.h" #include "render/image.h" +#include "render/tgafile.h" +#include "render/pngfile.h" +#include "render/jpgfile.h" namespace render { @@ -69,7 +76,7 @@ void Image::pad() image_data = image_new; } -void Image::flip() +void Image::flip_vertical() { unsigned char line[image_width*image_channels]; for (size_t y = 0; y < image_height / 2; y++) { @@ -85,5 +92,53 @@ void Image::flip() } } +void Image::flip_horizontal() +{ + unsigned char pixel_data[image_channels]; + for (size_t y = 0; y < image_height; y++) { + for (size_t x = 0; x < image_width / 2; x++) { + void *src = pixel(x,y); // &image_data[(y * image_width + x) * image_channels]; + void *dst = pixel(image_width - x - 1, y); // (&image_data[((y+1) * image_width - x - 1) * image_channels]; + memcpy(pixel_data, dst, image_channels); + memcpy(dst, src, image_channels); + memcpy(src, pixel_data, image_channels); + } + } +} + +Image *Image::load(const std::string & name) +{ + 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()); + } + + if (!image) { + con_warn << "Could not open image " << name << std::endl; + return 0; + } + + return image; +} + } diff --git a/src/render/image.h b/src/render/image.h index 244948e..3182fc8 100644 --- a/src/render/image.h +++ b/src/render/image.h @@ -20,7 +20,7 @@ public: ~Image(); /// pointer to the raw image data - inline unsigned char *data() { + inline unsigned char *ptr() { return image_data; } @@ -28,6 +28,10 @@ public: inline unsigned char *operator[](size_t index) { return &image_data[index]; } + + inline unsigned char *pixel(size_t x, size_t y) { + return &image_data[(y * image_width + x) * image_channels]; + } /// width of the image in pixels inline unsigned int width() const { @@ -61,10 +65,16 @@ public: void swap_channels(); /// flip upside-down - void flip(); + void flip_vertical(); + + /// flip left-right + void flip_horizontal(); /// pad width and height up to 8 bytes void pad(); + + /// load an image + static Image *load(const std::string & name); private: unsigned char *image_data; diff --git a/src/render/render.cc b/src/render/render.cc index 33dcb0c..f24eb83 100644 --- a/src/render/render.cc +++ b/src/render/render.cc @@ -22,7 +22,6 @@ #include "render/particles.h" #include "render/render.h" #include "render/screenshot.h" -#include "render/sky.h" #include "render/textures.h" #include "sys/sys.h" @@ -164,9 +163,6 @@ void init(int width, int height) // unload game assets (zone change) void unload() { - // unload skybox - Sky::unload(); - for (core::Entity::Registry::iterator it = core::Entity::registry().begin(); it != core::Entity::registry().end(); it++) { core:: Entity *entity = (*it).second; @@ -192,9 +188,6 @@ void unload() // clear all assets void clear() { - // unload skybox - Sky::unload(); - // clear entity models, and globe textures, this will force a reload for (core::Entity::Registry::iterator it = core::Entity::registry().begin(); it != core::Entity::registry().end(); it++) { core::Entity *entity = (*it).second; diff --git a/src/render/screenshot.cc b/src/render/screenshot.cc index ea2659b..7b40156 100644 --- a/src/render/screenshot.cc +++ b/src/render/screenshot.cc @@ -106,9 +106,9 @@ void Screenshot::save() render::Image image(State::width(), State::height(), 3); glReadPixels(0, 0, (GLsizei) State::width(), (GLsizei) State::height(), - GL_RGB, GL_UNSIGNED_BYTE, (void *) image.data()); + GL_RGB, GL_UNSIGNED_BYTE, (void *) image.ptr()); - image.flip(); + image.flip_vertical(); if (filetype == TYPEPNG) { render::PNG::save(filename.c_str(), image); diff --git a/src/render/sky.cc b/src/render/sky.cc deleted file mode 100644 index 1b914a6..0000000 --- a/src/render/sky.cc +++ /dev/null @@ -1,158 +0,0 @@ -/* - render/sky.cc - This file is part of the Osirion project and is distributed under - the terms of the GNU General Public License version 2 -*/ - -#include "render/render.h" -#include "render/camera.h" -#include "render/sky.h" -#include "render/textures.h" - -namespace render -{ - -size_t Sky::sky_texture_up = 0; -size_t Sky::sky_texture_down = 0; -size_t Sky::sky_texture_left = 0; -size_t Sky::sky_texture_right = 0; -size_t Sky::sky_texture_front = 0; -size_t Sky::sky_texture_back = 0; - -std::string Sky::sky_name; - -void Sky::draw(const std::string & name, const float wireframe) -{ - if (sky_name.compare(name) != 0) { - unload(); - } - - if (!sky_name.size()) { - - if (name.size()) { - const std::string basename("textures/sky/" + name); - - sky_texture_up = Textures::load(basename + "_up", false); - sky_texture_down = Textures::load(basename + "_down", false); - sky_texture_left = Textures::load(basename + "_left", false); - sky_texture_right = Textures::load(basename + "_right", false); - sky_texture_front = Textures::load(basename + "_front", false); - sky_texture_back = Textures::load(basename + "_back", false); - } - sky_name.assign(name); - } - - /* - * NOTE: - * to use quake3 skyboxes: - * switch left and right images - * rotate top image 90 degrees clockwise - * rotate bottom image 90 degrees counter-clockwise - * - */ - - const gl::Primitive primitive = (wireframe ? gl::LineLoop : gl::Quads); - - gl::push(); - gl::translate(Camera::eye()); - - gl::enable(GL_TEXTURE_2D); - gl::color(1.0f, 1.0f, 1.0f, 1.0f); - - // front - Textures::bind(sky_texture_front); - gl::begin(primitive); - gl::texcoord(0, 0); gl::vertex(1, 1, 1); - gl::texcoord(1, 0); gl::vertex(1, -1, 1); - gl::texcoord(1, 1); gl::vertex(1, -1, -1); - gl::texcoord(0, 1); gl::vertex(1, 1, -1); - gl::end(); - - // right - Textures::bind(sky_texture_right); - gl::begin(primitive); - gl::texcoord(0, 0); gl::vertex(1, -1, 1); - gl::texcoord(1, 0); gl::vertex(-1, -1, 1); - gl::texcoord(1, 1); gl::vertex(-1, -1, -1); - gl::texcoord(0, 1); gl::vertex(1, -1, -1); - gl::end(); - - // back - Textures::bind(sky_texture_back); - gl::begin(primitive); - gl::texcoord(0, 0); gl::vertex(-1, -1, 1); - gl::texcoord(1, 0); gl::vertex(-1, 1, 1); - gl::texcoord(1, 1); gl::vertex(-1, 1, -1); - gl::texcoord(0, 1); gl::vertex(-1, -1, -1); - gl::end(); - - // left - Textures::bind(sky_texture_left); - gl::begin(primitive); - gl::texcoord(0, 0); gl::vertex(-1, 1, 1); - gl::texcoord(1, 0); gl::vertex(1, 1, 1); - gl::texcoord(1, 1); gl::vertex(1, 1, -1); - gl::texcoord(0, 1); gl::vertex(-1, 1, -1); - gl::end(); - - // up - Textures::bind(sky_texture_up); - gl::begin(primitive); - gl::texcoord(0, 0); gl::vertex(-1, 1, 1); - gl::texcoord(1, 0); gl::vertex(-1, -1, 1); - gl::texcoord(1, 1); gl::vertex(1, -1, 1); - gl::texcoord(0, 1); gl::vertex(1, 1, 1); - gl::end(); - - // down - Textures::bind(sky_texture_down); - gl::begin(primitive); - gl::texcoord(0, 0); gl::vertex(1, 1, -1); - gl::texcoord(1, 0); gl::vertex(1, -1, -1); - gl::texcoord(1, 1); gl::vertex(-1, -1, -1); - gl::texcoord(0, 1); gl::vertex(-1, 1, -1); - gl::end(); - - gl::pop(); - - gl::disable(GL_TEXTURE_2D); - - Stats::quads += 6; -} - -void Sky::unload() -{ - if (sky_texture_up) { - Textures::unload(sky_texture_up); - sky_texture_up = 0; - } - - if (sky_texture_down) { - Textures::unload(sky_texture_down); - sky_texture_down = 0; - } - - if (sky_texture_left) { - Textures::unload(sky_texture_left); - sky_texture_left = 0; - } - - if (sky_texture_right) { - Textures::unload(sky_texture_right); - sky_texture_right = 0; - } - - if (sky_texture_front) { - Textures::unload(sky_texture_front); - sky_texture_front = 0; - } - - if (sky_texture_back) { - Textures::unload(sky_texture_back); - sky_texture_back = 0; - } - - sky_name.clear(); -} - -} // namespace render diff --git a/src/render/sky.h b/src/render/sky.h deleted file mode 100644 index 9c41ee0..0000000 --- a/src/render/sky.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - render/sky.h - This file is part of the Osirion project and is distributed under - the terms of the GNU General Public License version 2 -*/ - -#ifndef __INCLUDED_RENDER_SKY_H__ -#define __INCLUDED_RENDER_SKY_H__ - -#include - -namespace render -{ - -class Sky { -public: - - static void unload(); - - static void draw(const std::string & name, const float wireframe = false); - -private: - - static size_t sky_texture_up; - static size_t sky_texture_down; - static size_t sky_texture_left; - static size_t sky_texture_right; - static size_t sky_texture_front; - static size_t sky_texture_back; - - static std::string sky_name; -}; - -} // namespace render -#endif // __INCLUDED_RENDER_SKY_H__ \ No newline at end of file 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 diff --git a/src/render/textures.h b/src/render/textures.h index c1ccabe..90b26b1 100644 --- a/src/render/textures.h +++ b/src/render/textures.h @@ -28,6 +28,9 @@ public: /// Shutdown the textures registry static void shutdown(); + /// load the environment cubemap + static void load_cubemap(const std::string & name); + /// Load a texture /** Returns 0 on failure, and the texture index on success */ diff --git a/src/render/tgafile.cc b/src/render/tgafile.cc index 10082e6..0f5833e 100644 --- a/src/render/tgafile.cc +++ b/src/render/tgafile.cc @@ -149,9 +149,9 @@ Image *TGA::load(const char *filename) unsigned int r = ((unpacked >> 10) & 0x1f) << 3; // store it - image->data()[i * channels] = (unsigned char) b; - image->data()[i * channels+1] = (unsigned char) g; - image->data()[i * channels+2] = (unsigned char) r; + image->ptr()[i * channels] = (unsigned char) b; + image->ptr()[i * channels+1] = (unsigned char) g; + image->ptr()[i * channels+2] = (unsigned char) r; } } else { con_warn << "Error reading " << filename @@ -205,7 +205,7 @@ Image *TGA::load(const char *filename) if ((tga_descriptor & 0x20) == 0x0) { // origin at bottom left - image->flip(); + image->flip_vertical(); } if ((tga_descriptor & 0x10) == 0x10) { -- cgit v1.2.3