Переглянути джерело

OpenGL: Mipmaps for GFXGLCubemap.

LuisAntonRebollo 10 роки тому
батько
коміт
9150c7f5ab

+ 34 - 15
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<GFXGLTextureObject*>(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<GFXGLTextureObject*>(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()

+ 10 - 3
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;
 }
 

+ 1 - 1
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;