Пример #1
0
//-----------------------------------------------------------------------------
// innerCreateTexture
//-----------------------------------------------------------------------------
// This just creates the texture, no info is actually loaded to it.  We do that later.
void GFXGLTextureManager::innerCreateTexture( GFXGLTextureObject *retTex,
        U32 height,
        U32 width,
        U32 depth,
        GFXFormat format,
        GFXTextureProfile *profile,
        U32 numMipLevels,
        bool forceMips)
{
    // No 24 bit formats.  They trigger various oddities because hardware (and Apple's drivers apparently...) don't natively support them.
    if(format == GFXFormatR8G8B8)
        format = GFXFormatR8G8B8A8;

    retTex->mFormat = format;
    retTex->mIsZombie = false;
    retTex->mIsNPoT2 = false;

    GLenum binding = ( (height == 1 || width == 1) && ( height != width ) ) ? GL_TEXTURE_1D : ( (depth == 0) ? GL_TEXTURE_2D : GL_TEXTURE_3D );
    if((profile->testFlag(GFXTextureProfile::RenderTarget) || profile->testFlag(GFXTextureProfile::ZTarget)) && (!isPow2(width) || !isPow2(height)) && !depth)
        retTex->mIsNPoT2 = true;
    retTex->mBinding = binding;

    // Bind it
    PRESERVE_TEXTURE(binding);
    glBindTexture(retTex->getBinding(), retTex->getHandle());

    // Create it
    // TODO: Reenable mipmaps on render targets when Apple fixes their drivers
    if(forceMips && !retTex->mIsNPoT2)
    {
        retTex->mMipLevels = numMipLevels > 1 ? numMipLevels : 0;
    }
    else if(profile->testFlag(GFXTextureProfile::NoMipmap) || profile->testFlag(GFXTextureProfile::RenderTarget) || numMipLevels == 1 || retTex->mIsNPoT2)
    {
        retTex->mMipLevels = 1;
    }
    else
    {
        retTex->mMipLevels = numMipLevels;
    }

    if(!retTex->mIsNPoT2)
    {
        if(!isPow2(width))
            width = getNextPow2(width);
        if(!isPow2(height))
            height = getNextPow2(height);
        if(depth && !isPow2(depth))
            depth = getNextPow2(depth);
    }

    AssertFatal(GFXGLTextureInternalFormat[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid internal format");
    AssertFatal(GFXGLTextureFormat[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid format");
    AssertFatal(GFXGLTextureType[format] != GL_ZERO, "GFXGLTextureManager::innerCreateTexture - invalid type");

    //calculate num mipmaps
    if(retTex->mMipLevels == 0)
        retTex->mMipLevels = getMaxMipmaps(width, height, 1);

    glTexParameteri(binding, GL_TEXTURE_MAX_LEVEL, retTex->mMipLevels-1 );

    //If it wasn't for problems on amd drivers this next part could be really simplified and we wouldn't need to go through manually creating our
    //mipmap pyramid and instead just use glGenerateMipmap
    if(isCompressedFormat(format))
    {
        AssertFatal(binding == GL_TEXTURE_2D,
                    "GFXGLTextureManager::innerCreateTexture - Only compressed 2D textures are supported");

        U32 tempWidth = width;
        U32 tempHeight = height;
        U32 size = getCompressedSurfaceSize(format,height,width);
        //Fill compressed images with 0's
        U8 *pTemp = (U8*)dMalloc(sizeof(U8)*size);
        dMemset(pTemp,0,size);

        for(U32 i=0; i< retTex->mMipLevels; i++)
        {
            tempWidth = getMax( U32(1), width >> i );
            tempHeight = getMax( U32(1), height >> i );
            size = getCompressedSurfaceSize(format,width,height,i);
            glCompressedTexImage2D(binding,i,GFXGLTextureInternalFormat[format],tempWidth,tempHeight,0,size,pTemp);
        }

        dFree(pTemp);
    }
    else
    {
        if(binding == GL_TEXTURE_2D)
Пример #2
0
    // Creation / loading methods
    void GL3PlusTexture::createInternalResourcesImpl(void)
    {
        // set HardwareBuffer::Usage for TU_RENDERTARGET if nothing else specified
        if((mUsage & TU_RENDERTARGET) && (mUsage & ~TU_RENDERTARGET) == 0)
            mUsage |= HardwareBuffer::HBU_DYNAMIC;

        // Adjust format if required.
        mFormat = TextureManager::getSingleton().getNativeFormat(mTextureType, mFormat, mUsage);

        // Check requested number of mipmaps.
        uint32 maxMips = getMaxMipmaps();

        if (PixelUtil::isCompressed(mFormat) && (mNumMipmaps == 0))
            mNumRequestedMipmaps = 0;

        mNumMipmaps = mNumRequestedMipmaps;
        if (mNumMipmaps > maxMips)
            mNumMipmaps = maxMips;

        // Create a texture object and identify its GL type.
        OGRE_CHECK_GL_ERROR(glGenTextures(1, &mTextureID));
        GLenum texTarget = getGL3PlusTextureTarget();

        // Calculate size for all mip levels of the texture.
        uint32 width, height, depth;

        if ((mWidth * PixelUtil::getNumElemBytes(mFormat)) & 3) {
            // Standard alignment of 4 is not right for some formats.
            OGRE_CHECK_GL_ERROR(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
        }

        // Bind texture object to its type, making it the active texture object
        // for that type.
        mRenderSystem->_getStateCacheManager()->bindGLTexture( texTarget, mTextureID );

        mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_BASE_LEVEL, 0);
        mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_MAX_LEVEL, mNumMipmaps);

        // Set some misc default parameters, these can of course be changed later.
        mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget,
                                            GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget,
                                            GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget,
                                            GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget,
                                            GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        // Set up texture swizzling.
        mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_R, GL_RED);
        mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_G, GL_GREEN);
        mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_B, GL_BLUE);
        mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_A, GL_ALPHA);
	
        if (PixelUtil::isLuminance(mFormat) && (mRenderSystem->hasMinGLVersion(3, 3) || mRenderSystem->checkExtension("GL_ARB_texture_swizzle")))
        {
            if (PixelUtil::getComponentCount(mFormat) == 2)
            {
                mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_R, GL_RED);
                mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_G, GL_RED);
                mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_B, GL_RED);
                mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_A, GL_GREEN);
            }
            else
            {
                mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_R, GL_RED);
                mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_G, GL_RED);
                mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_B, GL_RED);
                mRenderSystem->_getStateCacheManager()->setTexParameteri(texTarget, GL_TEXTURE_SWIZZLE_A, GL_ONE);
            }
        }

        GLenum format = GL3PlusPixelUtil::getGLInternalFormat(mFormat, mHwGamma);
        GLenum datatype = GL3PlusPixelUtil::getGLOriginDataType(mFormat);
        width = mWidth;
        height = mHeight;
        depth = mDepth;

        // Allocate texture storage so that glTexSubImageXD can be
        // used to upload the texture.
        if (PixelUtil::isCompressed(mFormat))
        {
            // Compressed formats
            GLsizei size;

            for (uint32 mip = 0; mip <= mNumMipmaps; mip++)
            {
                size = static_cast<GLsizei>(PixelUtil::getMemorySize(width, height, depth, mFormat));
                // std::stringstream str;
                // str << "GL3PlusTexture::create - " << StringConverter::toString(mTextureID)
                // << " bytes: " << StringConverter::toString(PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat))
                // << " Mip: " + StringConverter::toString(mip)
                // << " Width: " << StringConverter::toString(width)
                // << " Height: " << StringConverter::toString(height)
                // << " Format " << PixelUtil::getFormatName(mFormat)
                // << " Internal Format: 0x" << std::hex << format
                // << " Origin Format: 0x" << std::hex << GL3PlusPixelUtil::getGLOriginFormat(mFormat)
                // << " Data type: 0x" << std::hex << datatype;
                // LogManager::getSingleton().logMessage(LML_NORMAL, str.str());

                switch(mTextureType)
                {
                case TEX_TYPE_1D:
                    OGRE_CHECK_GL_ERROR(glCompressedTexImage1D(GL_TEXTURE_1D, mip, format,
                                                               width, 0,
                                                               size, NULL));
                    break;
                case TEX_TYPE_2D:
                    OGRE_CHECK_GL_ERROR(glCompressedTexImage2D(GL_TEXTURE_2D,
                                                               mip,
                                                               format,
                                                               width, height,
                                                               0,
                                                               size,
                                                               NULL));
                    break;
                case TEX_TYPE_2D_RECT:
                    OGRE_CHECK_GL_ERROR(glCompressedTexImage2D(GL_TEXTURE_RECTANGLE,
                                                               mip,
                                                               format,
                                                               width, height,
                                                               0,
                                                               size,
                                                               NULL));
                    break;
                case TEX_TYPE_2D_ARRAY:
                case TEX_TYPE_3D:
                    OGRE_CHECK_GL_ERROR(glCompressedTexImage3D(texTarget, mip, format,
                                                               width, height, depth, 0,
                                                               size, NULL));
                    break;
                case TEX_TYPE_CUBE_MAP:
                    for(int face = 0; face < 6; face++) {
                        OGRE_CHECK_GL_ERROR(glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, format,
                                                                   width, height, 0,
                                                                   size, NULL));
                    }
                    break;
                default:
                    break;
                };

                if (width > 1)
                {
                    width = width / 2;
                }
                if (height > 1)
                {
                    height = height / 2;
                }
                if (depth > 1 && mTextureType != TEX_TYPE_2D_ARRAY)
                {
                    depth = depth / 2;
                }
            }
        }
        else
        {
            if (mRenderSystem->hasMinGLVersion(4, 2) || mRenderSystem->checkExtension("GL_ARB_texture_storage"))
            {
                switch(mTextureType)
                {
                case TEX_TYPE_1D:
                    OGRE_CHECK_GL_ERROR(glTexStorage1D(GL_TEXTURE_1D, GLsizei(mNumMipmaps+1), format, GLsizei(width)));
                    break;
                case TEX_TYPE_2D:
                case TEX_TYPE_2D_RECT:
                    OGRE_CHECK_GL_ERROR(glTexStorage2D(GL_TEXTURE_2D, GLsizei(mNumMipmaps+1), format, GLsizei(width), GLsizei(height)));
                    break;
                case TEX_TYPE_CUBE_MAP:
                    OGRE_CHECK_GL_ERROR(glTexStorage2D(GL_TEXTURE_CUBE_MAP, GLsizei(mNumMipmaps+1), format, GLsizei(width), GLsizei(height)));
                    break;
                case TEX_TYPE_2D_ARRAY:
                    OGRE_CHECK_GL_ERROR(glTexStorage3D(GL_TEXTURE_2D_ARRAY, GLsizei(mNumMipmaps+1), format, GLsizei(width), GLsizei(height), GLsizei(depth)));
                    break;
                case TEX_TYPE_3D:
                    OGRE_CHECK_GL_ERROR(glTexStorage3D(GL_TEXTURE_3D, GLsizei(mNumMipmaps+1), format, GLsizei(width), GLsizei(height), GLsizei(depth)));
                    break;
                }
            }
            else
            {
                GLenum originFormat = GL3PlusPixelUtil::getGLOriginFormat(mFormat);

                // Run through this process to pregenerate mipmap pyramid
                for(uint32 mip = 0; mip <= mNumMipmaps; mip++)
                {
                    //                    std::stringstream str;
                    //                    str << "GL3PlusTexture::create - " << StringConverter::toString(mTextureID)
                    //                    << " bytes: " << StringConverter::toString(PixelUtil::getMemorySize(width, height, depth, mFormat))
                    //                    << " Mip: " + StringConverter::toString(mip)
                    //                    << " Width: " << StringConverter::toString(width)
                    //                    << " Height: " << StringConverter::toString(height)
                    //                    << " Format " << PixelUtil::getFormatName(mFormat)
                    //                    << " Internal Format: 0x" << std::hex << format
                    //                    << " Origin Format: 0x" << std::hex << GL3PlusPixelUtil::getGLOriginFormat(mFormat)
                    //                    << " Data type: 0x" << std::hex << datatype;
                    //                    LogManager::getSingleton().logMessage(LML_NORMAL, str.str());

                    // Normal formats
                    switch(mTextureType)
                    {
                    case TEX_TYPE_1D:
                        OGRE_CHECK_GL_ERROR(glTexImage1D(GL_TEXTURE_1D, mip, format,
                                                         width, 0,
                                                         originFormat, datatype, NULL));
                        break;
                    case TEX_TYPE_2D:
                        OGRE_CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_2D,
                                                         mip,
                                                         format,
                                                         width, height,
                                                         0,
                                                         originFormat,
                                                         datatype, NULL));
                        break;
                    case TEX_TYPE_2D_RECT:
                        OGRE_CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_RECTANGLE,
                                                         mip,
                                                         format,
                                                         width, height,
                                                         0,
                                                         originFormat,
                                                         datatype, NULL));
                        break;
                    case TEX_TYPE_3D:
                    case TEX_TYPE_2D_ARRAY:
                        OGRE_CHECK_GL_ERROR(glTexImage3D(texTarget, mip, format,
                                                         width, height, depth, 0,
                                                         originFormat, datatype, NULL));
                        break;
                    case TEX_TYPE_CUBE_MAP:
                        for(int face = 0; face < 6; face++) {
                            OGRE_CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, format,
                                                             width, height, 0,
                                                             originFormat, datatype, NULL));
                        }
                        break;
                    default:
                        break;
                    };

                    if (width > 1)
                    {
                        width = width / 2;
                    }
                    if (height > 1)
                    {
                        height = height / 2;
                    }
                    if (depth > 1 && mTextureType != TEX_TYPE_2D_ARRAY)
                    {
                        depth = depth / 2;
                    }
                }
            }
        }

        // Reset unpack alignment to defaults
        OGRE_CHECK_GL_ERROR(glPixelStorei(GL_UNPACK_ALIGNMENT, 4));

        _createSurfaceList();

        // Generate mipmaps after all texture levels have been loaded
        // This is required for compressed formats such as DXT
        if (PixelUtil::isCompressed(mFormat) && mUsage & TU_AUTOMIPMAP)
        {
            OGRE_CHECK_GL_ERROR(glGenerateMipmap(getGL3PlusTextureTarget()));
        }

        // Get final internal format.
        mFormat = getBuffer(0,0)->getFormat();
    }
Пример #3
0
    //* Creation / loading methods ********************************************
    void GLTexture::createInternalResourcesImpl(void)
    {
        if (!GLEW_VERSION_1_2 && mTextureType == TEX_TYPE_3D)
            OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, 
                "3D Textures not supported before OpenGL 1.2", 
                "GLTexture::createInternalResourcesImpl");

        if (!GLEW_VERSION_2_0 && mTextureType == TEX_TYPE_2D_ARRAY)
            OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED, 
                "2D texture arrays not supported before OpenGL 2.0", 
                "GLTexture::createInternalResourcesImpl");

        if (mTextureType == TEX_TYPE_EXTERNAL_OES) {
            OGRE_EXCEPT(
                Exception::ERR_RENDERINGAPI_ERROR,
                "TEX_TYPE_EXTERNAL_OES is not available for openGL",
                "GLTexture::createInternalResourcesImpl"
            );
        }

        // Convert to nearest power-of-two size if required
        mWidth = GLPixelUtil::optionalPO2(mWidth);      
        mHeight = GLPixelUtil::optionalPO2(mHeight);
        mDepth = GLPixelUtil::optionalPO2(mDepth);
        

        // Adjust format if required
        mFormat = TextureManager::getSingleton().getNativeFormat(mTextureType, mFormat, mUsage);
        
        // Check requested number of mipmaps
        uint32 maxMips = getMaxMipmaps();
        mNumMipmaps = mNumRequestedMipmaps;
        if(mNumMipmaps>maxMips)
            mNumMipmaps = maxMips;

        // Check if we can do HW mipmap generation
        mMipmapsHardwareGenerated = true;
        
        // Generate texture name
        glGenTextures( 1, &mTextureID );
        
        // Set texture type
        mRenderSystem->_getStateCacheManager()->bindGLTexture( getGLTextureTarget(), mTextureID );
        
        // This needs to be set otherwise the texture doesn't get rendered
        if (GLEW_VERSION_1_2)
            mRenderSystem->_getStateCacheManager()->setTexParameteri(getGLTextureTarget(),
                GL_TEXTURE_MAX_LEVEL, mNumMipmaps);
        
        // Set some misc default parameters so NVidia won't complain, these can of course be changed later
        mRenderSystem->_getStateCacheManager()->setTexParameteri(getGLTextureTarget(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        mRenderSystem->_getStateCacheManager()->setTexParameteri(getGLTextureTarget(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        if (GLEW_VERSION_1_2)
        {
            mRenderSystem->_getStateCacheManager()->setTexParameteri(getGLTextureTarget(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            mRenderSystem->_getStateCacheManager()->setTexParameteri(getGLTextureTarget(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        }

        if ((mUsage & TU_AUTOMIPMAP) && mNumRequestedMipmaps)
        {
            mRenderSystem->_getStateCacheManager()->setTexParameteri( getGLTextureTarget(), GL_GENERATE_MIPMAP, GL_TRUE );
        }
        
        // Allocate internal buffer so that glTexSubImageXD can be used
        // Internal format
        GLenum internalformat = GLPixelUtil::getGLInternalFormat(mFormat, mHwGamma);
        uint32 width = mWidth;
        uint32 height = mHeight;
        uint32 depth = mDepth;

        GLenum format = GLPixelUtil::getGLOriginFormat(mFormat);
        GLenum datatype = GLPixelUtil::getGLOriginDataType(mFormat);

        if(PixelUtil::isCompressed(mFormat))
        {
            // Compressed formats
            GLsizei size = static_cast<GLsizei>(PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat));
            // Provide temporary buffer filled with zeroes as glCompressedTexImageXD does not
            // accept a 0 pointer like normal glTexImageXD
            // Run through this process for every mipmap to pregenerate mipmap piramid
            std::vector<uint8> tmpdata(size);
            
            for(uint32 mip=0; mip<=mNumMipmaps; mip++)
            {
                size = static_cast<GLsizei>(PixelUtil::getMemorySize(width, height, depth, mFormat));
                switch(mTextureType)
                {
                    case TEX_TYPE_1D:
                        glCompressedTexImage1DARB(GL_TEXTURE_1D, mip, internalformat, 
                            width, 0, 
                            size, &tmpdata[0]);
                        break;
                    case TEX_TYPE_2D:
                        glCompressedTexImage2DARB(GL_TEXTURE_2D, mip, internalformat,
                            width, height, 0, 
                            size, &tmpdata[0]);
                        break;
                    case TEX_TYPE_2D_ARRAY:
                    case TEX_TYPE_3D:
                        glCompressedTexImage3DARB(getGLTextureTarget(), mip, internalformat,
                            width, height, depth, 0, 
                            size, &tmpdata[0]);
                        break;
                    case TEX_TYPE_CUBE_MAP:
                        for(int face=0; face<6; face++) {
                            glCompressedTexImage2DARB(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, internalformat,
                                width, height, 0, 
                                size, &tmpdata[0]);
                        }
                        break;
                    case TEX_TYPE_2D_RECT:
                        break;
                    case TEX_TYPE_EXTERNAL_OES:
                        OGRE_EXCEPT(
                            Exception::ERR_RENDERINGAPI_ERROR,
                            "Attempt to create mipmaps for unsupported TEX_TYPE_EXTERNAL_OES, should never happen",
                            "GLTexture::createInternalResourcesImpl"
                        );
                        break;
                };
                if(width>1)
                    width = width/2;
                if(height>1)
                    height = height/2;
                if(depth>1 && mTextureType != TEX_TYPE_2D_ARRAY)
                    depth = depth/2;
            }
        }
        else
        {
            // Run through this process to pregenerate mipmap pyramid
            for(uint32 mip=0; mip<=mNumMipmaps; mip++)
            {
                // Normal formats
                switch(mTextureType)
                {
                    case TEX_TYPE_1D:
                        glTexImage1D(GL_TEXTURE_1D, mip, internalformat,
                            width, 0, 
                            format, datatype, 0);
    
                        break;
                    case TEX_TYPE_2D:
                        glTexImage2D(GL_TEXTURE_2D, mip, internalformat,
                            width, height, 0, 
                            format, datatype, 0);
                        break;
                    case TEX_TYPE_2D_ARRAY:
                    case TEX_TYPE_3D:
                        glTexImage3D(getGLTextureTarget(), mip, internalformat,
                            width, height, depth, 0, 
                            format, datatype, 0);
                        break;
                    case TEX_TYPE_CUBE_MAP:
                        for(int face=0; face<6; face++) {
                            glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, mip, internalformat,
                                width, height, 0, 
                                format, datatype, 0);
                        }
                        break;
                    case TEX_TYPE_2D_RECT:
                        break;
                    case TEX_TYPE_EXTERNAL_OES:
                        OGRE_EXCEPT(
                            Exception::ERR_RENDERINGAPI_ERROR,
                            "Attempt to create mipmaps for unsupported TEX_TYPE_EXTERNAL_OES, should never happen",
                            "GLTexture::createInternalResourcesImpl"
                        );
                        break;
                };
                if(width>1)
                    width = width/2;
                if(height>1)
                    height = height/2;
                if(depth>1 && mTextureType != TEX_TYPE_2D_ARRAY)
                    depth = depth/2;
            }
        }
        _createSurfaceList();
        // Get final internal format
        mFormat = getBuffer(0,0)->getFormat();
    }