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