GLTexture.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <GLEXT/GLTexture.h>
00022 #include <GLEXT/GLStateExtension.h>
00023 #include <common/Defines.h>
00024 #include <set>
00025 
00026 //static std::set<GLuint> usedNumbers_;
00027 unsigned int GLTexture::textureSpace_ = 0;
00028 unsigned int GLTexture::textureSets_ = 0;
00029 
00030 GLTexture::GLTexture() : 
00031         texNum_(0), texType_(GL_TEXTURE_2D), 
00032         usedSpace_(0),
00033         width_(0), height_(0)
00034 {
00035 
00036 }
00037 
00038 GLTexture::~GLTexture()
00039 {
00040         textureSpace_ -= usedSpace_;
00041         if (texNum_)
00042         {
00043                 glDeleteTextures(1, &texNum_);
00044                 //usedNumbers_.erase(texNum_);
00045                 texNum_ = 0;
00046         }
00047 }
00048 
00049 void GLTexture::draw(bool force)
00050 {
00051         if ((this != lastBind_) || force)
00052         {
00053                 glBindTexture(texType_, texNum_);
00054                 lastBind_ = this;
00055                 textureSets_++;
00056         }
00057 }
00058 
00059 bool GLTexture::replace(Image &bitmap, bool mipMap)
00060 {
00061         GLenum format = 
00062                 (bitmap.getComponents()==1)?GL_LUMINANCE:
00063                 ((bitmap.getComponents() == 3)?GL_RGB:GL_RGBA);
00064 
00065         if (textureValid())
00066         { 
00067                 if(GLStateExtension::getNoTexSubImage() ||
00068                         (bitmap.getWidth() != width_) ||
00069                         (bitmap.getHeight() != height_))
00070                 {
00071                         glDeleteTextures(1, &texNum_);
00072                         //usedNumbers_.erase(texNum_);
00073                         texNum_ = 0;
00074                 }
00075         }
00076 
00077         if (textureValid())
00078         {
00079                 draw(); // Bind texture
00080                 {
00081                         glPixelStorei(GL_UNPACK_ROW_LENGTH, bitmap.getWidth());
00082                         glTexSubImage2D(texType_, 0, 
00083                                 0, 0, 
00084                                 bitmap.getWidth(), bitmap.getHeight(), 
00085                                 format, GL_UNSIGNED_BYTE, 
00086                                 bitmap.getBits());
00087                         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
00088                 }
00089         }
00090         else
00091         {
00092                 return create(bitmap, mipMap);
00093         }
00094         return true;
00095 }
00096 
00097 bool GLTexture::create(Image &bitmap, bool mipMap)
00098 {
00099         GLenum format = 
00100                 (bitmap.getComponents()==1)?GL_LUMINANCE:
00101                 ((bitmap.getComponents() == 3)?GL_RGB:GL_RGBA);
00102         
00103         bool success = create(bitmap.getBits(),
00104                         bitmap.getWidth(), 
00105                         bitmap.getHeight(), 
00106                         bitmap.getComponents(), 
00107                         bitmap.getAlignment(),
00108                         format,
00109                         mipMap);
00110 
00111         return success;
00112 }
00113 
00114 bool GLTexture::createObject()
00115 {
00116         if (!textureValid())
00117         {
00118                 GLfloat priority = 1.0f;
00119                 glGenTextures(1, &texNum_);
00120                 //if (usedNumbers_.find(texNum_) != usedNumbers_.end())
00121                 //{
00122                 //      DIALOG_ASSERT("Texture Reuse" == 0);
00123                 //}
00124                 //usedNumbers_.insert(texNum_);
00125 
00126                 glPrioritizeTextures(1, &texNum_, &priority);
00127         }
00128 
00129         return true;
00130 }
00131 
00132 bool GLTexture::create(const void * data, 
00133                                            GLint width, 
00134                                            GLint height, 
00135                                            GLint components, 
00136                                            GLint alignment,
00137                                            GLenum format, 
00138                                            bool mipMap)
00139 {
00140         bool success = false;
00141         if (data)
00142         {
00143                 if (height == 1 || width == 1) texType_ = GL_TEXTURE_1D;
00144                 else texType_ = GL_TEXTURE_2D;
00145 
00146                 if (!validateSize(width) ||     !validateSize(height))
00147                 {
00148                         S3D::dialogExit("Scorched3D",
00149                                 S3D::formatStringBuffer("Invalid OpenGL texture size %ix%i specified",
00150                                 width, height));
00151                 }
00152 
00153                 if (!createObject()) return false;
00154                 glBindTexture(texType_, texNum_);
00155 
00156                 success = createTexture(data, width, height, components, alignment, format, mipMap);
00157         }
00158 
00159         return success;
00160 }
00161 
00162 bool GLTexture::createTexture(const void * data, 
00163                                                           GLint width, 
00164                                                           GLint height, 
00165                                                           GLint components, 
00166                                                           GLint alignment,
00167                                                           GLenum format, 
00168                                                           bool mipMap)
00169 {
00170         textureSpace_ -= usedSpace_;
00171         usedSpace_ = width * height * components;
00172         textureSpace_ += usedSpace_;
00173         width_ = width;
00174         height_ = height;
00175 
00176         texFormat_ = format;
00177         glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
00178         glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
00179         glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
00180         glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
00181 
00182         if (height == 1)
00183         {
00184                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00185                 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00186 
00187                 gluBuild1DMipmaps(GL_TEXTURE_1D, components, width, 
00188                                 format, GL_UNSIGNED_BYTE, data);
00189         }
00190         else if (width == 1)
00191         {
00192                 if (mipMap)
00193                 {
00194                         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00195                         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00196 
00197                         gluBuild1DMipmaps(GL_TEXTURE_1D, components, height, 
00198                                         format, GL_UNSIGNED_BYTE, data);
00199                 }
00200                 else
00201                 {
00202                         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00203                         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00204 
00205                         glTexImage1D(GL_TEXTURE_1D, 0, components, height, 
00206                                 0, format, GL_UNSIGNED_BYTE, data);
00207                 }
00208         }
00209         else
00210         {
00211                 if (mipMap)
00212                 {
00213                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00214                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00215 
00216                         if (GLStateExtension::hasHardwareMipmaps()) // Use hardware mipmaps
00217                         {
00218                                 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
00219 
00220                                 glTexImage2D(GL_TEXTURE_2D, 0, components, width, 
00221                                         height, 0, format, GL_UNSIGNED_BYTE, data);
00222                         }
00223                         else
00224                         {
00225                                 gluBuild2DMipmaps(GL_TEXTURE_2D, components, width, 
00226                                         height, format, GL_UNSIGNED_BYTE, data);
00227                         }
00228                 }
00229                 else
00230                 {
00231                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
00232                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
00233 
00234                         glTexImage2D(GL_TEXTURE_2D, 0, components, width, 
00235                                 height, 0, format, GL_UNSIGNED_BYTE, data);
00236                 }
00237         };
00238 
00239         return true;
00240 }
00241 
00242 bool GLTexture::create(GLint width, GLint height, GLenum format)
00243 {
00244         // Init internals
00245         texType_ = GL_TEXTURE_2D;
00246         width_ = width;
00247         height_ = height;
00248         texFormat_ = format;
00249 
00250         // Create texture
00251         if (!createObject()) return false;
00252 
00253         glBindTexture(texType_, texNum_);
00254 
00255         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
00256         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
00257     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00258     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00259 
00260         glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0,
00261                 GL_RGBA, GL_UNSIGNED_BYTE,NULL);
00262 
00263         return true;
00264 }
00265 
00266 bool GLTexture::createBufferTexture(GLint width, GLint height, bool depthTex)
00267 {
00268         // Init internals
00269         texType_ = GL_TEXTURE_2D;
00270         width_ = width;
00271         height_ = height;
00272 
00273         // Create texture
00274         if (!createObject()) return false;
00275 
00276         glBindTexture(texType_, texNum_);
00277 
00278         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
00279         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
00280     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
00281     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
00282 
00283         if (!depthTex)
00284         {
00285                 texFormat_ = GL_RGB;
00286 
00287                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
00288                         GL_RGB, GL_UNSIGNED_BYTE, NULL);
00289         }
00290         else
00291         {
00292                 texFormat_ = GL_DEPTH_COMPONENT;
00293 
00294                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
00295                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
00296 
00297                 // Find current depth buffer and use the same depth
00298                 GLint depth_bits;
00299                 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
00300                 GLenum depth_format;
00301                 if(depth_bits == 16)  depth_format = GL_DEPTH_COMPONENT16_ARB;
00302                 else                  depth_format = GL_DEPTH_COMPONENT24_ARB;
00303 
00304                 glTexImage2D(GL_TEXTURE_2D, 0, depth_format, width, height, 0, 
00305                         GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);                
00306         }
00307 
00308         return true;
00309 }
00310 
00311 bool GLTexture::textureValid()
00312 {
00313         return (glIsTexture(texNum_) == GL_TRUE);
00314 }
00315 
00316 bool GLTexture::validateSize(int size)
00317 {
00318         return (!(size != 1 &&
00319                 size != 2 &&
00320                 size != 4 &&
00321                 size != 8 && 
00322                 size != 16 &&
00323                 size != 32 &&
00324                 size != 64 &&
00325                 size != 128 &&
00326                 size != 256 &&
00327                 size != 512 &&
00328                 size != 1024 &&
00329                 size != 2048));
00330 }

Generated on Mon Feb 16 15:14:45 2009 for Scorched3D by  doxygen 1.5.3