Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2010-12-06 21:33:34 +0000
committerStijn Buys <ingar@osirion.org>2010-12-06 21:33:34 +0000
commitc50095cab023e91ba2a4fec8dcb290e6d817124b (patch)
treee9511df876d45faffb428ee7ae342a8aabab4194
parent8c7fa7dd3258e8d3e112fb9780249dd0d0ef008a (diff)
Re-enabled environment mapping with the skybox as cubemap.
-rw-r--r--src/render/Makefile.am2
-rw-r--r--src/render/draw.cc122
-rw-r--r--src/render/gl.cc5
-rw-r--r--src/render/gl.h3
-rw-r--r--src/render/image.cc61
-rw-r--r--src/render/image.h14
-rw-r--r--src/render/render.cc7
-rw-r--r--src/render/screenshot.cc4
-rw-r--r--src/render/sky.cc158
-rw-r--r--src/render/sky.h35
-rw-r--r--src/render/textures.cc201
-rw-r--r--src/render/textures.h3
-rw-r--r--src/render/tgafile.cc8
13 files changed, 358 insertions, 265 deletions
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 <stdlib.h>
-#include <string.h>
+#include <string>
+
+#include <cstdlib>
+#include <cstring>
+
+#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 <string>
-
-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<std::string, size_t> 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) {