bool TEXTURE::Load(const std::string & path, const TEXTUREINFO & info, std::ostream & error) { if (id) { error << "Tried to double load texture " << path << std::endl; return false; } if (path.empty() && !info.data) { error << "Tried to load a texture with an empty name" << std::endl; return false; } id = 0; cube = info.cube; if (info.cube && info.verticalcross) { return LoadCubeVerticalCross(path, info, error); } else if (info.cube) { return LoadCube(path, info, error); } SDL_Surface * orig_surface = 0; if (info.data) { Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif orig_surface = SDL_CreateRGBSurfaceFrom( info.data, info.width, info.height, info.bytespp * 8, info.width * info.bytespp, rmask, gmask, bmask, amask); } if (!orig_surface) { orig_surface = IMG_Load(path.c_str()); if (!orig_surface) { error << "Error loading texture file: " << path << std::endl; return false; } } SDL_Surface * texture_surface = orig_surface; if (orig_surface) { origw = texture_surface->w; origh = texture_surface->h; //scale to power of two if necessary bool norescale = (IsPowerOfTwo(orig_surface->w) && IsPowerOfTwo(orig_surface->h)) || (info.npot && (GLEW_VERSION_2_0 || GLEW_ARB_texture_non_power_of_two)); if (!norescale) { int maxsize = 2048; int newx = GetPowerOfTwo(orig_surface->w, maxsize); int newy = GetPowerOfTwo(orig_surface->h, maxsize); float scalew = ((float)newx+0.5) / orig_surface->w; float scaleh = ((float)newy+0.5) / orig_surface->h; SDL_Surface * pot_surface = zoomSurface(orig_surface, scalew, scaleh, SMOOTHING_ON); assert(IsPowerOfTwo(pot_surface->w)); assert(IsPowerOfTwo(pot_surface->h)); SDL_FreeSurface(orig_surface); orig_surface = pot_surface; texture_surface = orig_surface; } //scale texture down if necessary scale = Scale(info.maxsize, orig_surface->w, orig_surface->h); if (scale < 1.0) { texture_surface = zoomSurface(orig_surface, scale, scale, SMOOTHING_ON); } //store dimensions w = texture_surface->w; h = texture_surface->h; GenTexture(texture_surface, info, id, alpha, error); } //free the texture surface separately if it's a scaled copy of the original if (texture_surface != orig_surface && texture_surface) { SDL_FreeSurface(texture_surface); } //free the original surface if it's not a custom surface (used for the track map) if (!info.data && orig_surface) { SDL_FreeSurface(orig_surface); } return true; }
bool Texture::LoadCube(const std::string & path, const TextureInfo & info, std::ostream & error) { if (info.verticalcross) { return LoadCubeVerticalCross(path, info, error); } std::string cubefiles[6]; cubefiles[0] = path+"-xp.png"; cubefiles[1] = path+"-xn.png"; cubefiles[2] = path+"-yn.png"; cubefiles[3] = path+"-yp.png"; cubefiles[4] = path+"-zn.png"; cubefiles[5] = path+"-zp.png"; unsigned id = 0; glGenTextures(1, &id); CheckForOpenGLErrors("Cubemap texture ID generation", error); glBindTexture(GL_TEXTURE_CUBE_MAP, id); m_id = id; for (int i = 0; i < 6; ++i) { SDL_Surface * surface = IMG_Load(cubefiles[i].c_str()); if (!surface) { error << "Error loading texture file: " + path + " (" + cubefiles[i] + ")" << std::endl; error << IMG_GetError() << std::endl; return false; } // store dimensions if (i != 0 && ((m_w != (unsigned)surface->w) || (m_h != (unsigned)surface->h))) { error << "Cube map sides aren't equal sizes" << std::endl; return false; } m_w = surface->w; m_h = surface->h; // detect channels int format = GL_RGB; switch (surface->format->BytesPerPixel) { case 1: format = GL_LUMINANCE; break; case 2: format = GL_LUMINANCE_ALPHA; break; case 3: format = GL_RGB; break; case 4: format = GL_RGBA; break; default: error << "Texture has unknown format: " + path + " (" + cubefiles[i] + ")" << std::endl; return false; break; } // Create MipMapped Texture GLenum targetparam; if (i == 0) targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; else if (i == 1) targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_X; else if (i == 2) targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; else if (i == 3) targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_Y; else if (i == 4) targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; else if (i == 5) targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_Z; else { error << "Iterated too far: " + path + " (" + cubefiles[i] + ")" << std::endl; assert(0); } glTexImage2D(targetparam, 0, format, surface->w, surface->h, 0, format, GL_UNSIGNED_BYTE, surface->pixels ); SDL_FreeSurface(surface); } 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); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glDisable(GL_TEXTURE_CUBE_MAP); CheckForOpenGLErrors("Cubemap creation", error); return true; }
bool TEXTURE::LoadCube(const std::string & path, const TEXTUREINFO & info, std::ostream & error) { if (info.verticalcross) { return LoadCubeVerticalCross(path, info, error); } std::string cubefiles[6]; cubefiles[0] = path+"-xp.png"; cubefiles[1] = path+"-xn.png"; cubefiles[2] = path+"-yn.png"; cubefiles[3] = path+"-yp.png"; cubefiles[4] = path+"-zn.png"; cubefiles[5] = path+"-zp.png"; GLuint new_handle = 0; glGenTextures(1, &new_handle); OPENGL_UTILITY::CheckForOpenGLErrors("Cubemap texture ID generation", error); id = new_handle; glBindTexture(GL_TEXTURE_CUBE_MAP, new_handle); for (unsigned int i = 0; i < 6; ++i) { SDL_Surface * texture_surface = IMG_Load(cubefiles[i].c_str()); if (texture_surface) { //store dimensions if (i != 0 && (w != (unsigned int) texture_surface->w || h != (unsigned int) texture_surface->h)) { error << "Cube map sides aren't equal sizes" << std::endl; return false; } w = texture_surface->w; h = texture_surface->h; //detect channels int format = GL_RGB; switch (texture_surface->format->BytesPerPixel) { case 1: format = GL_LUMINANCE; break; case 2: format = GL_LUMINANCE_ALPHA; break; case 3: format = GL_RGB; break; case 4: format = GL_RGBA; break; default: error << "Texture has unknown format: " + path + " (" + cubefiles[i] + ")" << std::endl; return false; break; } if (format != GL_RGB) { error << "Cube map texture format isn't GL_RGB (this causes problems for some reason): " + path + " (" + cubefiles[i] + ")" << std::endl; return false; } // Create MipMapped Texture GLenum targetparam; if (i == 0) targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; else if (i == 1) targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_X; else if (i == 2) targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_Y; else if (i == 3) targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_Y; else if (i == 4) targetparam = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; else if (i == 5) targetparam = GL_TEXTURE_CUBE_MAP_POSITIVE_Z; else { error << "Iterated too far: " + path + " (" + cubefiles[i] + ")" << std::endl; assert(0); } glTexImage2D( targetparam, 0, format,texture_surface->w, texture_surface->h, 0, format, GL_UNSIGNED_BYTE, texture_surface->pixels ); } else { error << "Error loading texture file: " + path + " (" + cubefiles[i] + ")" << std::endl; return false; } if (texture_surface) { // Free up any memory we may have used SDL_FreeSurface( texture_surface ); texture_surface = NULL; } } 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); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glDisable(GL_TEXTURE_CUBE_MAP); OPENGL_UTILITY::CheckForOpenGLErrors("Cubemap creation", error); return true; }