Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreGLTexture.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://ogre.sourceforge.net/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 
00026 #include "OgreGLTexture.h"
00027 #include "OgreGLSupport.h"
00028 #include "OgreTextureManager.h"
00029 #include "OgreDataChunk.h"
00030 #include "OgreImage.h"
00031 #include "OgreLogManager.h"
00032 #include "OgreCamera.h"
00033 #include "OgreException.h"
00034 #include "OgreRoot.h"
00035 #include "OgreCodec.h"
00036 #include "OgreSDDataChunk.h"
00037 
00038 #if OGRE_PLATFORM == PLATFORM_WIN32
00039 #   include <windows.h>
00040 #   include <wingdi.h>
00041 #endif
00042 
00043 namespace Ogre {
00044 
00045     unsigned int mostSignificantBitSet(unsigned int value)
00046     {
00047         unsigned int result = 0;
00048         while (value != 0) {
00049             ++result;
00050             value >>= 1;
00051         }
00052         return result-1;
00053     }
00054 
00055     GLTexture::GLTexture(const String& name, GLSupport& support, TextureType texType) :
00056         mGLSupport(support)
00057     {
00058         mName = name;
00059         mTextureType = texType;
00060 
00061         mUsage = TU_DEFAULT;
00062         enable32Bit(false);
00063     }
00064 
00065     GLTexture::GLTexture(const String& name, GLSupport& support, TextureType texType, 
00066         uint width, uint height, uint num_mips, PixelFormat format, 
00067         TextureUsage usage) : 
00068             Texture(name, texType, width, height, 1, num_mips, format, usage),
00069             mGLSupport(support),
00070             mTextureID(0)
00071     {
00072     }
00073 
00074     GLTexture::~GLTexture()
00075     {
00076         unload();
00077     }
00078 
00079     GLenum GLTexture::getGLTextureType(void) const
00080     {
00081         switch(mTextureType)
00082         {
00083             case TEX_TYPE_1D:
00084                 return GL_TEXTURE_1D;
00085             case TEX_TYPE_2D:
00086                 return GL_TEXTURE_2D;
00087             case TEX_TYPE_3D:
00088                 return GL_TEXTURE_3D;
00089             case TEX_TYPE_CUBE_MAP:
00090                 return GL_TEXTURE_CUBE_MAP;
00091             default:
00092                 return 0;
00093         };
00094     }
00095 
00096     GLenum GLTexture::getGLTextureFormat(void) const
00097     {
00098         switch(mFormat)
00099         {
00100             case PF_L8:
00101                 return GL_LUMINANCE;
00102             case PF_R8G8B8:
00103                 return GL_RGB;
00104             case PF_B8G8R8:
00105                 return GL_BGR;
00106             case PF_B8G8R8A8:
00107                 return GL_BGRA;
00108             case PF_A8R8G8B8:
00109                 return GL_RGBA;
00110             case PF_DXT1:
00111                 return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
00112             case PF_DXT3:
00113                  return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
00114             case PF_DXT5:
00115                  return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
00116             default:
00117                 return 0;
00118         }
00119     }
00120 
00121     void GLTexture::blitToTexture( 
00122         const Image& src, 
00123         unsigned uStartX, unsigned uStartY )
00124     {
00125         if (this->getTextureType() != TEX_TYPE_2D)
00126           Except( Exception::UNIMPLEMENTED_FEATURE, "**** Blit to texture implemented only for 2D textures!!! ****", "GLTexture::blitToTexture" );
00127 
00128         mGLSupport.begin_context();
00129         glBindTexture( GL_TEXTURE_2D, mTextureID );
00130         glTexSubImage2D( 
00131             GL_TEXTURE_2D, 0, 
00132             uStartX, uStartY,
00133             src.getWidth(), src.getHeight(),
00134             getGLTextureFormat(),
00135             GL_UNSIGNED_BYTE, src.getData() );
00136         mGLSupport.end_context();
00137     }
00138 
00139     uchar* GLTexture::rescaleNPower2( const Image& src ) 
00140     {
00141         // Scale image to n^2 dimensions
00142         unsigned int newWidth = (1 << mostSignificantBitSet(mSrcWidth));
00143         if (newWidth != mSrcWidth)
00144             newWidth <<= 1;
00145 
00146         unsigned int newHeight = (1 << mostSignificantBitSet(mSrcHeight));
00147         if (newHeight != mSrcHeight)
00148             newHeight <<= 1;
00149 
00150         uchar *pTempData;
00151         if(newWidth != mSrcWidth || newHeight != mSrcHeight)
00152         {
00153           unsigned int newImageSize = newWidth * newHeight * 
00154             (mHasAlpha ? 4 : 3);
00155 
00156           pTempData = new uchar[ newImageSize ];
00157           mGLSupport.begin_context();
00158           if(gluScaleImage(getGLTextureFormat(), mSrcWidth, mSrcHeight,
00159                 GL_UNSIGNED_BYTE, src.getData(), newWidth, newHeight, 
00160                 GL_UNSIGNED_BYTE, pTempData) != 0)
00161           {
00162             Except(Exception::ERR_INTERNAL_ERROR, 
00163                 "Error while rescaling image!", "GLTexture::rescaleNPower2");
00164           }
00165           mGLSupport.end_context();
00166 
00167           Image::applyGamma( pTempData, mGamma, newImageSize, mSrcBpp );
00168 
00169           mSrcWidth = mWidth = newWidth; 
00170           mSrcHeight = mHeight = newHeight;
00171         }
00172         else
00173         {
00174           pTempData = new uchar[ src.getSize() ];
00175           memcpy( pTempData, src.getData(), src.getSize() );
00176           Image::applyGamma( pTempData, mGamma, src.getSize(), mSrcBpp );
00177         }
00178 
00179         return pTempData;
00180     }
00181 
00182     void GLTexture::loadImage( const Image& img )
00183     {
00184         std::vector<Image> images;
00185         
00186         images.push_back(img);
00187         loadImages(images);
00188         images.clear();
00189     }
00190 
00191     void GLTexture::loadImages( const std::vector<Image>& images )
00192     {
00193         bool useSoftwareMipmaps = true;
00194 
00195         if( mIsLoaded )
00196         {
00197             std::cout << "Unloading image" << std::endl;
00198             unload();
00199         }
00200 
00201         // Create the GL texture
00202         mGLSupport.begin_context();
00203         glGenTextures( 1, &mTextureID );
00204         glBindTexture( getGLTextureType(), mTextureID );
00205 
00206         if(mNumMipMaps && Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_AUTOMIPMAP))
00207         {
00208             glTexParameteri( getGLTextureType(), GL_GENERATE_MIPMAP, GL_TRUE );
00209             useSoftwareMipmaps = false;
00210         }
00211 
00212         for(size_t i = 0; i < images.size(); i++)
00213         {
00214             const Image& img = images[i];
00215 
00216             LogManager::getSingleton().logMessage( 
00217                 LML_NORMAL,
00218                 "GLTexture: Loading %s with %d mipmaps from Image.", 
00219                 mName.c_str(), mNumMipMaps );        
00220 
00221             mFormat = img.getFormat();
00222 
00223             mSrcBpp = Image::PF2BPP(mFormat);
00224             mHasAlpha = img.getHasAlpha();
00225 
00226             mSrcWidth = img.getWidth();
00227             mSrcHeight = img.getHeight();
00228             // Same dest dimensions for GL
00229             mWidth = mSrcWidth;
00230             mHeight = mSrcHeight;
00231 
00232             mDepth = img.getDepth();
00233 
00234             unsigned short imageMipmaps = img.getNumMipmaps();
00235             if(imageMipmaps)
00236                 mNumMipMaps = imageMipmaps;
00237 
00238             glTexParameteri(getGLTextureType(), GL_TEXTURE_MAX_LEVEL, mNumMipMaps);
00239 
00240             uchar *pTempData = rescaleNPower2(img);
00241 
00242             generateMipMaps( pTempData, useSoftwareMipmaps, img.hasFlag(IF_COMPRESSED), i );
00243             delete [] pTempData;
00244         }
00245         mGLSupport.end_context();
00246 
00247         // Update size (the final size, not including temp space)
00248         unsigned short bytesPerPixel = mFinalBpp >> 3;
00249         if( !mHasAlpha && mFinalBpp == 32 )
00250         {
00251             bytesPerPixel--;
00252         }
00253         mSize = mWidth * mHeight * bytesPerPixel;
00254 
00255         mIsLoaded = true;     
00256     }
00257     
00258     void GLTexture::createRenderTexture(void)
00259     {
00260         if (this->getTextureType() != TEX_TYPE_2D)
00261             Except( Exception::UNIMPLEMENTED_FEATURE, "**** Create render texture implemented only for 2D textures!!! ****", "GLTexture::createRenderTexture" );
00262 
00263         // Create the GL texture
00264         mGLSupport.begin_context();
00265         glGenTextures( 1, &mTextureID );
00266         glBindTexture( GL_TEXTURE_2D, mTextureID );
00267 
00268         glTexImage2D( GL_TEXTURE_2D, 0, getGLTextureFormat(),
00269             mWidth, mHeight, 0, getGLTextureFormat(), GL_UNSIGNED_BYTE, 0 );
00270 
00271         // This needs to be set otherwise the texture doesn't get rendered
00272         glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mNumMipMaps );
00273         mGLSupport.end_context();
00274     }
00275 
00276     void GLTexture::load()
00277     {
00278         if( mUsage == TU_RENDERTARGET )
00279         {
00280             createRenderTexture();
00281             mIsLoaded = true;     
00282         }
00283         else
00284         {
00285             if(mTextureType == TEX_TYPE_1D || mTextureType == TEX_TYPE_2D || 
00286                 mTextureType == TEX_TYPE_3D)
00287             {
00288                 Image img;
00289                 img.load( mName );
00290 
00291                 if (StringUtil::endsWith(getName(), "dds") && img.hasFlag(IF_CUBEMAP))
00292                 {
00293                     Image newImage;
00294                     std::vector<Image> images;
00295                     uint imageSize = img.getSize() / 6;
00296 
00297                     mTextureType = TEX_TYPE_CUBE_MAP;
00298 
00299                     uint offset = 0;
00300                     for(int i = 0; i < 6; i++)
00301                     {
00302                         DataChunk chunk(img.getData() + offset, imageSize);
00303                         newImage.loadRawData(chunk, img.getWidth(), 
00304                             img.getHeight(), img.getFormat());
00305                         offset += imageSize;
00306                         images.push_back(newImage);
00307                     }
00308 
00309                     loadImages( images );
00310                     images.clear();
00311                 }
00312                 else
00313                 {
00314                     // If this is a dds volumetric texture set the texture type flag accordingly.
00315                     if(StringUtil::endsWith(getName(), ".dds") && img.getDepth() > 1)
00316                         mTextureType = TEX_TYPE_3D;
00317 
00318                     loadImage( img );
00319                 }
00320             }
00321             else if (mTextureType == TEX_TYPE_CUBE_MAP)
00322             {
00323                 Image img;
00324                 String baseName, ext;
00325                 std::vector<Image> images;
00326                 static const String suffixes[6] = {"_rt", "_lf", "_up", "_dn", "_fr", "_bk"};
00327 
00328                 for(size_t i = 0; i < 6; i++)
00329                 {
00330                     size_t pos = mName.find_last_of(".");
00331                     baseName = mName.substr(0, pos);
00332                     ext = mName.substr(pos);
00333                     String fullName = baseName + suffixes[i] + ext;
00334 
00335                     img.load( fullName );
00336                     images.push_back(img);
00337                 }
00338 
00339                 loadImages( images );
00340                 images.clear();
00341             }
00342             else
00343                 Except( Exception::UNIMPLEMENTED_FEATURE, "**** Unknown texture type ****", "GLTexture::load" );
00344         }
00345     }
00346     
00347     void GLTexture::unload()
00348     {
00349         if( mIsLoaded )
00350         {
00351             glDeleteTextures( 1, &mTextureID );
00352             mIsLoaded = false;
00353         }
00354     }
00355 
00356     void GLTexture::generateMipMaps( const uchar *data, bool useSoftware, 
00357         bool isCompressed, size_t faceNumber )
00358     {
00359         mGLSupport.begin_context();
00360         if(useSoftware && mNumMipMaps)
00361         {
00362             if(mTextureType == TEX_TYPE_1D)
00363             {
00364                 gluBuild1DMipmaps(
00365                     getGLTextureType(), mHasAlpha ? GL_RGBA8 : GL_RGB8, 
00366                     mSrcWidth, getGLTextureFormat(), GL_UNSIGNED_BYTE, data);
00367             }
00368             else if (mTextureType == TEX_TYPE_3D)
00369             {
00370                 /* Requires GLU 1.3 which is harder to come by
00371                    Most 3D textures don't need mipmaps?
00372                 gluBuild3DMipmaps(
00373                     getGLTextureType(), mHasAlpha ? GL_RGBA8 : GL_RGB8, 
00374                     mSrcWidth, mSrcHeight, mDepth, getGLTextureFormat(), 
00375                     GL_UNSIGNED_BYTE, data);
00376                 */
00377                 glTexImage3D(
00378                     getGLTextureType(), 0, mHasAlpha ? GL_RGBA8 : GL_RGB8, 
00379                     mSrcWidth, mSrcHeight, mDepth, 0, getGLTextureFormat(), 
00380                     GL_UNSIGNED_BYTE, data );
00381             }
00382             else
00383             {
00384                 gluBuild2DMipmaps(
00385                     mTextureType == TEX_TYPE_CUBE_MAP ? 
00386                         GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceNumber : 
00387                         getGLTextureType(), 
00388                     mHasAlpha ? GL_RGBA8 : GL_RGB8, mSrcWidth, mSrcHeight, 
00389                     getGLTextureFormat(), GL_UNSIGNED_BYTE, data);
00390             }
00391         }
00392         else
00393         {
00394             if(mTextureType == TEX_TYPE_1D)
00395             {
00396                 glTexImage1D(
00397                     getGLTextureType(), 0, mHasAlpha ? GL_RGBA8 : GL_RGB8, 
00398                     mSrcWidth, 0, getGLTextureFormat(), GL_UNSIGNED_BYTE, data);
00399             }
00400             else if (mTextureType == TEX_TYPE_3D)
00401             {
00402                 glTexImage3D(
00403                     getGLTextureType(), 0, mHasAlpha ? GL_RGBA8 : GL_RGB8, 
00404                     mSrcWidth, mSrcHeight, mDepth, 0, getGLTextureFormat(), 
00405                     GL_UNSIGNED_BYTE, data );
00406             }
00407             else
00408             {
00409                 if(isCompressed && Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability( RSC_TEXTURE_COMPRESSION_DXT ))
00410                 {    
00411                     unsigned short blockSize = (mFormat == PF_DXT1) ? 8 : 16;
00412                     int size = ((mWidth+3)/4)*((mHeight+3)/4)*blockSize; 
00413 
00414                     glCompressedTexImage2DARB_ptr(
00415                         mTextureType == TEX_TYPE_CUBE_MAP ?
00416                             GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceNumber :
00417                             getGLTextureType(), 0,
00418                          getGLTextureFormat(), mSrcWidth, mSrcHeight, 0, 
00419                          size, data);
00420                 }
00421                 else
00422                 {
00423                     glTexImage2D(
00424                         mTextureType == TEX_TYPE_CUBE_MAP ? 
00425                             GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceNumber : 
00426                             getGLTextureType(), 0, 
00427                         mHasAlpha ? GL_RGBA8 : GL_RGB8, mSrcWidth, mSrcHeight, 
00428                         0, getGLTextureFormat(), GL_UNSIGNED_BYTE, data );
00429                 }
00430             }
00431         }
00432 
00433         mGLSupport.end_context();
00434     }
00435 
00436     void GLRenderTexture::_copyToTexture(void)
00437     {
00438         
00439         glBindTexture(GL_TEXTURE_2D,
00440             static_cast<GLTexture*>(mTexture)->getGLID());
00441             
00442         glCopyTexSubImage2D(GL_TEXTURE_2D, mTexture->getNumMipMaps(), 0, 0,
00443             0, 0, mWidth, mHeight);
00444 
00445     }
00446 }
00447 

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:26 2004