diff --git a/Engine/source/gfx/gl/gfxGLCubemap.cpp b/Engine/source/gfx/gl/gfxGLCubemap.cpp index b20f27bf1..381df9114 100644 --- a/Engine/source/gfx/gl/gfxGLCubemap.cpp +++ b/Engine/source/gfx/gl/gfxGLCubemap.cpp @@ -56,9 +56,12 @@ GFXGLCubemap::~GFXGLCubemap() void GFXGLCubemap::fillCubeTextures(GFXTexHandle* faces) { + AssertFatal( faces, ""); + AssertFatal( faces[0]->mMipLevels > 0, ""); + PRESERVE_CUBEMAP_TEXTURE(); glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0 ); // TODO OPENGL GFXGLCubemap mipmaps + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, faces[0]->mMipLevels - 1 ); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -68,10 +71,11 @@ void GFXGLCubemap::fillCubeTextures(GFXTexHandle* faces) U32 reqWidth = faces[0]->getWidth(); U32 reqHeight = faces[0]->getHeight(); GFXFormat regFaceFormat = faces[0]->getFormat(); + const bool isCompressed = isCompressedFormat(regFaceFormat); mWidth = reqWidth; mHeight = reqHeight; mFaceFormat = regFaceFormat; - mMipLevels = 1; // Lie for now + mMipLevels = getMax( (U32)1, faces[0]->mMipLevels); AssertFatal(reqWidth == reqHeight, "GFXGLCubemap::fillCubeTextures - Width and height must be equal!"); for(U32 i = 0; i < 6; i++) @@ -83,14 +87,19 @@ void GFXGLCubemap::fillCubeTextures(GFXTexHandle* faces) mTextures[i] = faces[i]; GFXFormat faceFormat = faces[i]->getFormat(); - GFXGLTextureObject* glTex = static_cast(faces[i].getPointer()); - U8* buf = glTex->getTextureData(); - glTexImage2D(faceList[i], 0, GFXGLTextureInternalFormat[faceFormat], faces[i]->getWidth(), faces[i]->getHeight(), - 0, GFXGLTextureFormat[faceFormat], GFXGLTextureType[faceFormat], buf); - delete[] buf; + GFXGLTextureObject* glTex = static_cast(faces[i].getPointer()); + const U32 mipCount = isCompressed ? mMipLevels : 1; + for( U32 mip = 0; mip < mipCount; ++mip ) + { + U8* buf = glTex->getTextureData( mip ); + glTexImage2D(faceList[i], mip, GFXGLTextureInternalFormat[faceFormat], faces[i]->getWidth(), faces[i]->getHeight(), + 0, GFXGLTextureFormat[faceFormat], GFXGLTextureType[faceFormat], buf); + delete[] buf; + } } - glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + if( !isCompressed ) + glGenerateMipmap(GL_TEXTURE_CUBE_MAP); } void GFXGLCubemap::initStatic(GFXTexHandle* faces) @@ -150,11 +159,11 @@ void GFXGLCubemap::initStatic( DDSFile *dds ) // TODO: The DDS can skip surfaces, but i'm unsure what i should // do here when creating the cubemap. Ignore it for now. continue; - } + } - // Now loop thru the mip levels! - for (U32 j = 0; j < mMipLevels; j++) - glCompressedTexImage2D(faceList[i], j, GFXGLTextureInternalFormat[mFaceFormat], mWidth, mHeight, 0, dds->getSurfaceSize(j), dds->mSurfaces[i]->mMips[j]); + // Now loop thru the mip levels! + for (U32 j = 0; j < mMipLevels; j++) + glCompressedTexImage2D(faceList[i], j, GFXGLTextureInternalFormat[mFaceFormat], mWidth, mHeight, 0, dds->getSurfaceSize(j), dds->mSurfaces[i]->mMips[j]); } } @@ -162,10 +171,13 @@ void GFXGLCubemap::initDynamic(U32 texSize, GFXFormat faceFormat) { mDynamicTexSize = texSize; mFaceFormat = faceFormat; + const bool isCompressed = isCompressedFormat(faceFormat); + mMipLevels = getMax( (U32)1, getMaxMipmaps( texSize, texSize, 1 ) ); glGenTextures(1, &mCubemap); PRESERVE_CUBEMAP_TEXTURE(); glBindTexture(GL_TEXTURE_CUBE_MAP, mCubemap); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, mMipLevels - 1); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -173,12 +185,19 @@ void GFXGLCubemap::initDynamic(U32 texSize, GFXFormat faceFormat) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); mWidth = texSize; mHeight = texSize; - mMipLevels = 1; + for(U32 i = 0; i < 6; i++) { - glTexImage2D( faceList[i], 0, GFXGLTextureInternalFormat[faceFormat], texSize, texSize, - 0, GFXGLTextureFormat[faceFormat], GFXGLTextureType[faceFormat], NULL); + const U32 mipCount = isCompressed ? mMipLevels : 1; + for( U32 mip = 0; mip < mipCount; ++mip ) + { + glTexImage2D( faceList[i], mip, GFXGLTextureInternalFormat[faceFormat], texSize, texSize, + 0, GFXGLTextureFormat[faceFormat], GFXGLTextureType[faceFormat], NULL); + } } + + if( !isCompressed ) + glGenerateMipmap(GL_TEXTURE_CUBE_MAP); } void GFXGLCubemap::zombify() diff --git a/Engine/source/gfx/gl/gfxGLTextureObject.cpp b/Engine/source/gfx/gl/gfxGLTextureObject.cpp index 423899f70..8e2627a79 100644 --- a/Engine/source/gfx/gl/gfxGLTextureObject.cpp +++ b/Engine/source/gfx/gl/gfxGLTextureObject.cpp @@ -243,12 +243,19 @@ void GFXGLTextureObject::bind(U32 textureUnit) mSampler = ssd; } -U8* GFXGLTextureObject::getTextureData() +U8* GFXGLTextureObject::getTextureData( U32 mip ) { - U8* data = new U8[mTextureSize.x * mTextureSize.y * mBytesPerTexel]; + AssertFatal( mMipLevels, ""); + mip = (mip < mMipLevels) ? mip : 0; + + const U32 dataSize = isCompressedFormat(mFormat) + ? getCompressedSurfaceSize( mFormat, mTextureSize.x, mTextureSize.y, mip ) + : (mTextureSize.x >> mip) * (mTextureSize.y >> mip) * mBytesPerTexel; + + U8* data = new U8[dataSize]; PRESERVE_TEXTURE(mBinding); glBindTexture(mBinding, mHandle); - glGetTexImage(mBinding, 0, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], data); + glGetTexImage(mBinding, mip, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], data); return data; } diff --git a/Engine/source/gfx/gl/gfxGLTextureObject.h b/Engine/source/gfx/gl/gfxGLTextureObject.h index c3ebe9e23..90d748bab 100644 --- a/Engine/source/gfx/gl/gfxGLTextureObject.h +++ b/Engine/source/gfx/gl/gfxGLTextureObject.h @@ -51,7 +51,7 @@ public: /// @return An array containing the texture data /// @note You are responsible for deleting the returned data! (Use delete[]) - U8* getTextureData(); + U8* getTextureData( U32 mip = 0); virtual F32 getMaxUCoord() const; virtual F32 getMaxVCoord() const;