2012-09-19 15:15:01 +00:00
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
# include "gfx/gl/gfxGLDevice.h"
# include "gfx/gl/gfxGLTextureObject.h"
# include "gfx/gl/gfxGLEnumTranslate.h"
# include "gfx/gl/gfxGLUtils.h"
# include "gfx/gl/gfxGLCubemap.h"
# include "gfx/gfxTextureManager.h"
# include "gfx/gfxCardProfile.h"
2014-11-08 16:41:17 +00:00
# include "gfx/bitmap/ddsFile.h"
2017-06-23 16:36:20 +00:00
# include "gfx/bitmap/imageUtils.h"
2012-09-19 15:15:01 +00:00
GFXGLCubemap : : GFXGLCubemap ( ) :
mCubemap ( 0 ) ,
mDynamicTexSize ( 0 ) ,
2020-05-11 20:00:25 +00:00
mWidth ( 0 ) ,
mHeight ( 0 ) ,
2012-09-19 15:15:01 +00:00
mFaceFormat ( GFXFormatR8G8B8A8 )
{
for ( U32 i = 0 ; i < 6 ; i + + )
mTextures [ i ] = NULL ;
GFXTextureManager : : addEventDelegate ( this , & GFXGLCubemap : : _onTextureEvent ) ;
}
GFXGLCubemap : : ~ GFXGLCubemap ( )
{
glDeleteTextures ( 1 , & mCubemap ) ;
GFXTextureManager : : removeEventDelegate ( this , & GFXGLCubemap : : _onTextureEvent ) ;
}
2019-04-16 04:11:18 +00:00
GLenum GFXGLCubemap : : getEnumForFaceNumber ( U32 face )
{
2020-07-04 03:56:44 +00:00
return GFXGLFaceType [ face ] ;
2019-04-16 04:11:18 +00:00
}
2012-09-19 15:15:01 +00:00
void GFXGLCubemap : : fillCubeTextures ( GFXTexHandle * faces )
{
2014-12-26 19:58:22 +00:00
AssertFatal ( faces , " " ) ;
AssertFatal ( faces [ 0 ] - > mMipLevels > 0 , " " ) ;
2014-11-08 16:41:17 +00:00
PRESERVE_CUBEMAP_TEXTURE ( ) ;
2012-09-19 15:15:01 +00:00
glBindTexture ( GL_TEXTURE_CUBE_MAP , mCubemap ) ;
2014-12-26 19:58:22 +00:00
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_MAX_LEVEL , faces [ 0 ] - > mMipLevels - 1 ) ;
2012-09-19 15:15:01 +00:00
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 ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_WRAP_R , GL_CLAMP_TO_EDGE ) ;
U32 reqWidth = faces [ 0 ] - > getWidth ( ) ;
U32 reqHeight = faces [ 0 ] - > getHeight ( ) ;
GFXFormat regFaceFormat = faces [ 0 ] - > getFormat ( ) ;
2017-06-23 16:36:20 +00:00
const bool isCompressed = ImageUtil : : isCompressedFormat ( regFaceFormat ) ;
2012-09-19 15:15:01 +00:00
mWidth = reqWidth ;
mHeight = reqHeight ;
mFaceFormat = regFaceFormat ;
2017-06-23 16:36:20 +00:00
mMipMapLevels = getMax ( ( U32 ) 1 , faces [ 0 ] - > mMipLevels ) ;
2012-09-19 15:15:01 +00:00
AssertFatal ( reqWidth = = reqHeight , " GFXGLCubemap::fillCubeTextures - Width and height must be equal! " ) ;
for ( U32 i = 0 ; i < 6 ; i + + )
{
AssertFatal ( faces [ i ] , avar ( " GFXGLCubemap::fillCubeFaces - texture %i is NULL! " , i ) ) ;
AssertFatal ( ( faces [ i ] - > getWidth ( ) = = reqWidth ) & & ( faces [ i ] - > getHeight ( ) = = reqHeight ) , " GFXGLCubemap::fillCubeFaces - All textures must have identical dimensions! " ) ;
AssertFatal ( faces [ i ] - > getFormat ( ) = = regFaceFormat , " GFXGLCubemap::fillCubeFaces - All textures must have identical formats! " ) ;
mTextures [ i ] = faces [ i ] ;
GFXFormat faceFormat = faces [ i ] - > getFormat ( ) ;
2014-12-26 19:58:22 +00:00
GFXGLTextureObject * glTex = static_cast < GFXGLTextureObject * > ( faces [ i ] . getPointer ( ) ) ;
2014-12-26 23:01:21 +00:00
if ( isCompressed )
2014-12-26 19:58:22 +00:00
{
2017-06-23 16:36:20 +00:00
for ( U32 mip = 0 ; mip < mMipMapLevels ; + + mip )
2014-12-26 23:01:21 +00:00
{
const U32 mipWidth = getMax ( U32 ( 1 ) , faces [ i ] - > getWidth ( ) > > mip ) ;
const U32 mipHeight = getMax ( U32 ( 1 ) , faces [ i ] - > getHeight ( ) > > mip ) ;
const U32 mipDataSize = getCompressedSurfaceSize ( mFaceFormat , mWidth , mHeight , mip ) ;
U8 * buf = glTex - > getTextureData ( mip ) ;
2020-07-04 03:56:44 +00:00
glCompressedTexImage2D ( GFXGLFaceType [ i ] , mip , GFXGLTextureInternalFormat [ mFaceFormat ] , mipWidth , mipHeight , 0 , mipDataSize , buf ) ;
2014-12-26 23:01:21 +00:00
delete [ ] buf ;
}
}
else
{
U8 * buf = glTex - > getTextureData ( ) ;
2020-07-04 03:56:44 +00:00
glTexImage2D ( GFXGLFaceType [ i ] , 0 , GFXGLTextureInternalFormat [ faceFormat ] , mWidth , mHeight ,
2014-12-26 19:58:22 +00:00
0 , GFXGLTextureFormat [ faceFormat ] , GFXGLTextureType [ faceFormat ] , buf ) ;
delete [ ] buf ;
}
2012-09-19 15:15:01 +00:00
}
2014-12-16 14:14:30 +00:00
2014-12-26 19:58:22 +00:00
if ( ! isCompressed )
glGenerateMipmap ( GL_TEXTURE_CUBE_MAP ) ;
2012-09-19 15:15:01 +00:00
}
void GFXGLCubemap : : initStatic ( GFXTexHandle * faces )
{
if ( mCubemap )
return ;
if ( faces )
{
AssertFatal ( faces [ 0 ] , " GFXGLCubemap::initStatic - empty texture passed " ) ;
glGenTextures ( 1 , & mCubemap ) ;
fillCubeTextures ( faces ) ;
}
2019-01-22 08:03:14 +00:00
mInitialized = true ;
2012-09-19 15:15:01 +00:00
}
void GFXGLCubemap : : initStatic ( DDSFile * dds )
{
if ( mCubemap )
return ;
AssertFatal ( dds , " GFXGLCubemap::initStatic - Got null DDS file! " ) ;
AssertFatal ( dds - > isCubemap ( ) , " GFXGLCubemap::initStatic - Got non-cubemap DDS file! " ) ;
AssertFatal ( dds - > mSurfaces . size ( ) = = 6 , " GFXGLCubemap::initStatic - DDS has less than 6 surfaces! " ) ;
2014-12-15 17:59:42 +00:00
mWidth = dds - > getWidth ( ) ;
mHeight = dds - > getHeight ( ) ;
mFaceFormat = dds - > getFormat ( ) ;
2017-06-23 16:36:20 +00:00
mMipMapLevels = dds - > getMipLevels ( ) ;
const bool isCompressed = ImageUtil : : isCompressedFormat ( mFaceFormat ) ;
2012-09-19 15:15:01 +00:00
glGenTextures ( 1 , & mCubemap ) ;
2014-11-08 16:41:17 +00:00
PRESERVE_CUBEMAP_TEXTURE ( ) ;
2012-09-19 15:15:01 +00:00
glBindTexture ( GL_TEXTURE_CUBE_MAP , mCubemap ) ;
2017-06-23 16:36:20 +00:00
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_MAX_LEVEL , mMipMapLevels - 1 ) ;
2012-09-19 15:15:01 +00:00
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 ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_WRAP_R , GL_CLAMP_TO_EDGE ) ;
AssertFatal ( mWidth = = mHeight , " GFXGLCubemap::initStatic - Width and height must be equal! " ) ;
for ( U32 i = 0 ; i < 6 ; i + + )
{
if ( ! dds - > mSurfaces [ i ] )
{
// TODO: The DDS can skip surfaces, but i'm unsure what i should
// do here when creating the cubemap. Ignore it for now.
continue ;
2014-12-26 19:58:22 +00:00
}
2012-09-19 15:15:01 +00:00
2017-06-23 16:36:20 +00:00
// convert to Z up
2018-11-28 07:51:52 +00:00
const U32 faceIndex = zUpFaceIndex ( i ) ;
2017-06-23 16:36:20 +00:00
2014-12-26 19:58:22 +00:00
// Now loop thru the mip levels!
2017-06-23 16:36:20 +00:00
for ( U32 mip = 0 ; mip < mMipMapLevels ; + + mip )
2014-12-26 20:24:14 +00:00
{
const U32 mipWidth = getMax ( U32 ( 1 ) , mWidth > > mip ) ;
const U32 mipHeight = getMax ( U32 ( 1 ) , mHeight > > mip ) ;
2017-06-23 16:36:20 +00:00
if ( isCompressed )
2020-07-04 03:56:44 +00:00
glCompressedTexImage2D ( GFXGLFaceType [ faceIndex ] , mip , GFXGLTextureInternalFormat [ mFaceFormat ] , mipWidth , mipHeight , 0 , dds - > getSurfaceSize ( mip ) , dds - > mSurfaces [ i ] - > mMips [ mip ] ) ;
2017-06-23 16:36:20 +00:00
else
2020-07-04 03:56:44 +00:00
glTexImage2D ( GFXGLFaceType [ faceIndex ] , mip , GFXGLTextureInternalFormat [ mFaceFormat ] , mipWidth , mipHeight , 0 ,
2017-06-23 16:36:20 +00:00
GFXGLTextureFormat [ mFaceFormat ] , GFXGLTextureType [ mFaceFormat ] , dds - > mSurfaces [ i ] - > mMips [ mip ] ) ;
2014-12-26 20:24:14 +00:00
}
2012-09-19 15:15:01 +00:00
}
2019-01-22 08:03:14 +00:00
mInitialized = true ;
2012-09-19 15:15:01 +00:00
}
2018-09-16 23:19:04 +00:00
void GFXGLCubemap : : initDynamic ( U32 texSize , GFXFormat faceFormat , U32 mipLevels )
2012-09-19 15:15:01 +00:00
{
mDynamicTexSize = texSize ;
mFaceFormat = faceFormat ;
2017-06-23 16:36:20 +00:00
const bool isCompressed = ImageUtil : : isCompressedFormat ( faceFormat ) ;
2020-07-04 03:56:44 +00:00
mMipMapLevels = ImageUtil : : getMaxMipCount ( texSize , texSize ) ;
2012-09-19 15:15:01 +00:00
glGenTextures ( 1 , & mCubemap ) ;
2014-11-08 16:41:17 +00:00
PRESERVE_CUBEMAP_TEXTURE ( ) ;
2012-09-19 15:15:01 +00:00
glBindTexture ( GL_TEXTURE_CUBE_MAP , mCubemap ) ;
2017-06-23 16:36:20 +00:00
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_MAX_LEVEL , mMipMapLevels - 1 ) ;
2012-09-19 15:15:01 +00:00
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 ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_WRAP_R , GL_CLAMP_TO_EDGE ) ;
mWidth = texSize ;
mHeight = texSize ;
2014-12-26 19:58:22 +00:00
2014-12-26 23:01:21 +00:00
for ( U32 i = 0 ; i < 6 ; i + + )
{
2017-06-23 16:36:20 +00:00
if ( ImageUtil : : isCompressedFormat ( faceFormat ) )
2014-12-26 23:01:21 +00:00
{
2017-06-23 16:36:20 +00:00
for ( U32 mip = 0 ; mip < mMipMapLevels ; + + mip )
2014-12-26 23:01:21 +00:00
{
const U32 mipSize = getMax ( U32 ( 1 ) , texSize > > mip ) ;
const U32 mipDataSize = getCompressedSurfaceSize ( mFaceFormat , texSize , texSize , mip ) ;
2020-07-04 03:56:44 +00:00
glCompressedTexImage2D ( GFXGLFaceType [ i ] , mip , GFXGLTextureInternalFormat [ mFaceFormat ] , mipSize , mipSize , 0 , mipDataSize , NULL ) ;
2014-12-26 23:01:21 +00:00
}
}
else
2014-12-26 19:58:22 +00:00
{
2020-07-04 03:56:44 +00:00
glTexImage2D ( GFXGLFaceType [ i ] , 0 , GFXGLTextureInternalFormat [ faceFormat ] , texSize , texSize ,
2014-12-26 19:58:22 +00:00
0 , GFXGLTextureFormat [ faceFormat ] , GFXGLTextureType [ faceFormat ] , NULL ) ;
}
2014-12-26 23:01:21 +00:00
}
2014-12-26 19:58:22 +00:00
2020-06-25 22:34:48 +00:00
if ( ! isCompressed & & ! mipLevels )
2014-12-26 19:58:22 +00:00
glGenerateMipmap ( GL_TEXTURE_CUBE_MAP ) ;
2019-01-22 08:03:14 +00:00
mInitialized = true ;
2012-09-19 15:15:01 +00:00
}
void GFXGLCubemap : : zombify ( )
{
glDeleteTextures ( 1 , & mCubemap ) ;
mCubemap = 0 ;
}
void GFXGLCubemap : : resurrect ( )
{
// Handled in tmResurrect
}
void GFXGLCubemap : : tmResurrect ( )
{
if ( mDynamicTexSize )
initDynamic ( mDynamicTexSize , mFaceFormat ) ;
else
{
if ( mDDSFile )
initStatic ( mDDSFile ) ;
else
initStatic ( mTextures ) ;
}
}
void GFXGLCubemap : : setToTexUnit ( U32 tuNum )
{
static_cast < GFXGLDevice * > ( getOwningDevice ( ) ) - > setCubemapInternal ( tuNum , this ) ;
}
void GFXGLCubemap : : bind ( U32 textureUnit ) const
{
glActiveTexture ( GL_TEXTURE0 + textureUnit ) ;
glBindTexture ( GL_TEXTURE_CUBE_MAP , mCubemap ) ;
2014-11-08 16:41:17 +00:00
static_cast < GFXGLDevice * > ( getOwningDevice ( ) ) - > getOpenglCache ( ) - > setCacheBindedTex ( textureUnit , GL_TEXTURE_CUBE_MAP , mCubemap ) ;
2012-09-19 15:15:01 +00:00
GFXGLStateBlockRef sb = static_cast < GFXGLDevice * > ( GFX ) - > getCurrentStateBlock ( ) ;
AssertFatal ( sb , " GFXGLCubemap::bind - No active stateblock! " ) ;
if ( ! sb )
return ;
const GFXSamplerStateDesc & ssd = sb - > getDesc ( ) . samplers [ textureUnit ] ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_MIN_FILTER , minificationFilter ( ssd . minFilter , ssd . mipFilter , 0 ) ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_MAG_FILTER , GFXGLTextureFilter [ ssd . magFilter ] ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_WRAP_S , GFXGLTextureAddress [ ssd . addressModeU ] ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_WRAP_T , GFXGLTextureAddress [ ssd . addressModeV ] ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP , GL_TEXTURE_WRAP_R , GFXGLTextureAddress [ ssd . addressModeW ] ) ;
}
void GFXGLCubemap : : _onTextureEvent ( GFXTexCallbackCode code )
{
if ( code = = GFXZombify )
zombify ( ) ;
else
tmResurrect ( ) ;
}
2019-04-16 04:11:18 +00:00
U8 * GFXGLCubemap : : getTextureData ( U32 face , U32 mip )
{
AssertFatal ( mMipMapLevels , " " ) ;
mip = ( mip < mMipMapLevels ) ? mip : 0 ;
2019-04-26 18:32:23 +00:00
const U32 bytesPerTexel = 8 ; //TODO make work with more formats!!!!!
2019-04-16 04:11:18 +00:00
const U32 dataSize = ImageUtil : : isCompressedFormat ( mFaceFormat )
? getCompressedSurfaceSize ( mFaceFormat , mWidth , mHeight , mip )
: ( mWidth > > mip ) * ( mHeight > > mip ) * bytesPerTexel ;
U8 * data = new U8 [ dataSize ] ;
2019-04-26 18:32:23 +00:00
PRESERVE_TEXTURE ( GL_TEXTURE_CUBE_MAP ) ;
2019-04-16 04:11:18 +00:00
glBindTexture ( GL_TEXTURE_CUBE_MAP , mCubemap ) ;
if ( ImageUtil : : isCompressedFormat ( mFaceFormat ) )
2020-07-04 03:56:44 +00:00
glGetCompressedTexImage ( GFXGLFaceType [ face ] , mip , data ) ;
2019-04-16 04:11:18 +00:00
else
2020-07-04 03:56:44 +00:00
glGetTexImage ( GFXGLFaceType [ face ] , mip , GFXGLTextureFormat [ mFaceFormat ] , GFXGLTextureType [ mFaceFormat ] , data ) ;
2019-04-16 04:11:18 +00:00
return data ;
}
//-----------------------------------------------------------------------------
// Cubemap Array
//-----------------------------------------------------------------------------
GFXGLCubemapArray : : GFXGLCubemapArray ( )
{
2020-05-11 20:00:25 +00:00
mCubemap = NULL ;
2019-04-16 04:11:18 +00:00
}
GFXGLCubemapArray : : ~ GFXGLCubemapArray ( )
{
glDeleteTextures ( 1 , & mCubemap ) ;
}
//TODO: really need a common private 'init' function to avoid code double up with these init* functions
void GFXGLCubemapArray : : init ( GFXCubemapHandle * cubemaps , const U32 cubemapCount )
{
AssertFatal ( cubemaps , " GFXGLCubemapArray- Got null GFXCubemapHandle! " ) ;
AssertFatal ( * cubemaps , " GFXGLCubemapArray - Got empty cubemap! " ) ;
2019-09-29 12:51:43 +00:00
U32 downscalePower = GFXTextureManager : : smTextureReductionLevel ;
U32 scaledSize = cubemaps [ 0 ] - > getSize ( ) ;
if ( downscalePower ! = 0 )
{
// Otherwise apply the appropriate scale...
scaledSize > > = downscalePower ;
}
2019-04-16 04:11:18 +00:00
//all cubemaps must be the same size,format and number of mipmaps. Grab the details from the first cubemap
2019-09-29 12:51:43 +00:00
mSize = scaledSize ;
2019-04-16 04:11:18 +00:00
mFormat = cubemaps [ 0 ] - > getFormat ( ) ;
2019-09-29 12:51:43 +00:00
mMipMapLevels = cubemaps [ 0 ] - > getMipMapLevels ( ) - downscalePower ;
2019-04-16 04:11:18 +00:00
mNumCubemaps = cubemapCount ;
const bool isCompressed = ImageUtil : : isCompressedFormat ( mFormat ) ;
glGenTextures ( 1 , & mCubemap ) ;
PRESERVE_CUBEMAP_ARRAY_TEXTURE ( ) ;
glBindTexture ( GL_TEXTURE_CUBE_MAP_ARRAY , mCubemap ) ;
2019-09-29 12:51:43 +00:00
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_MAX_LEVEL , mMin ( mMipMapLevels - 1 , 1 ) ) ;
2019-04-16 04:11:18 +00:00
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_WRAP_R , GL_CLAMP_TO_EDGE ) ;
for ( U32 i = 0 ; i < cubemapCount ; i + + )
{
GFXGLCubemap * glTex = static_cast < GFXGLCubemap * > ( cubemaps [ i ] . getPointer ( ) ) ;
for ( U32 face = 0 ; face < 6 ; face + + )
{
for ( U32 currentMip = 0 ; currentMip < mMipMapLevels ; currentMip + + )
{
U8 * pixelData = glTex - > getTextureData ( face , currentMip ) ;
2019-04-27 08:09:01 +00:00
glBindTexture ( GL_TEXTURE_CUBE_MAP_ARRAY , mCubemap ) ;
2019-04-16 04:11:18 +00:00
const U32 mipSize = getMax ( U32 ( 1 ) , mSize > > currentMip ) ;
2019-04-28 23:32:23 +00:00
if ( isCompressed )
2019-04-16 04:11:18 +00:00
{
const U32 mipDataSize = getCompressedSurfaceSize ( mFormat , mSize , mSize , currentMip ) ;
2019-04-29 05:07:38 +00:00
glCompressedTexSubImage3D ( GL_TEXTURE_CUBE_MAP_ARRAY , currentMip , 0 , 0 , i * 6 + face , mipSize , mipSize , 1 , GFXGLTextureFormat [ mFormat ] , GFXGLTextureType [ mFormat ] , pixelData ) ;
2019-04-16 04:11:18 +00:00
}
else
2019-04-28 23:32:23 +00:00
{
glTexSubImage3D ( GL_TEXTURE_CUBE_MAP_ARRAY , currentMip , 0 , 0 , i * 6 + face , mipSize , mipSize , 1 , GFXGLTextureFormat [ mFormat ] , GFXGLTextureType [ mFormat ] , pixelData ) ;
}
2019-04-27 08:09:01 +00:00
glBindTexture ( GL_TEXTURE_CUBE_MAP_ARRAY , 0 ) ;
2019-04-16 04:11:18 +00:00
delete [ ] pixelData ;
}
}
}
}
//Just allocate the cubemap array but we don't upload any data
void GFXGLCubemapArray : : init ( const U32 cubemapCount , const U32 cubemapFaceSize , const GFXFormat format )
{
2019-09-29 12:51:43 +00:00
U32 downscalePower = GFXTextureManager : : smTextureReductionLevel ;
U32 scaledSize = cubemapFaceSize ;
if ( downscalePower ! = 0 )
{
// Otherwise apply the appropriate scale...
scaledSize > > = downscalePower ;
}
2019-04-16 04:11:18 +00:00
//all cubemaps must be the same size,format and number of mipmaps. Grab the details from the first cubemap
2019-09-29 12:51:43 +00:00
mSize = scaledSize ;
2019-04-16 04:11:18 +00:00
mFormat = format ;
2019-09-29 12:51:43 +00:00
mMipMapLevels = ImageUtil : : getMaxMipCount ( scaledSize , scaledSize ) ;
2019-04-16 04:11:18 +00:00
mNumCubemaps = cubemapCount ;
const bool isCompressed = ImageUtil : : isCompressedFormat ( mFormat ) ;
glGenTextures ( 1 , & mCubemap ) ;
PRESERVE_CUBEMAP_ARRAY_TEXTURE ( ) ;
glBindTexture ( GL_TEXTURE_CUBE_MAP_ARRAY , mCubemap ) ;
2019-04-26 06:57:07 +00:00
for ( U32 i = 0 ; i < mMipMapLevels ; i + + )
{
const U32 mipSize = getMax ( U32 ( 1 ) , mSize > > i ) ;
glTexImage3D ( GL_TEXTURE_CUBE_MAP_ARRAY , i , GFXGLTextureInternalFormat [ mFormat ] , mipSize , mipSize , cubemapCount * 6 , 0 , GFXGLTextureFormat [ mFormat ] , GFXGLTextureType [ mFormat ] , NULL ) ;
}
2019-04-16 04:11:18 +00:00
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_MAX_LEVEL , mMipMapLevels - 1 ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_WRAP_R , GL_CLAMP_TO_EDGE ) ;
}
void GFXGLCubemapArray : : updateTexture ( const GFXCubemapHandle & cubemap , const U32 slot )
{
AssertFatal ( slot < = mNumCubemaps , " GFXD3D11CubemapArray::updateTexture - trying to update a cubemap texture that is out of bounds! " ) ;
2019-04-26 18:32:23 +00:00
if ( ! cubemap - > isInitialized ( ) )
return ;
2019-04-16 04:11:18 +00:00
const bool isCompressed = ImageUtil : : isCompressedFormat ( mFormat ) ;
2019-04-27 08:09:01 +00:00
GFXGLCubemap * glTex = static_cast < GFXGLCubemap * > ( cubemap . getPointer ( ) ) ;
2019-04-16 04:11:18 +00:00
for ( U32 face = 0 ; face < 6 ; face + + )
{
for ( U32 currentMip = 0 ; currentMip < mMipMapLevels ; currentMip + + )
{
U8 * pixelData = glTex - > getTextureData ( face , currentMip ) ;
2019-04-27 08:09:01 +00:00
glBindTexture ( GL_TEXTURE_CUBE_MAP_ARRAY , mCubemap ) ;
2019-04-16 04:11:18 +00:00
const U32 mipSize = getMax ( U32 ( 1 ) , mSize > > currentMip ) ;
2019-04-28 23:32:23 +00:00
if ( isCompressed )
2019-04-16 04:11:18 +00:00
{
const U32 mipDataSize = getCompressedSurfaceSize ( mFormat , mSize , mSize , currentMip ) ;
2019-04-29 05:07:38 +00:00
glCompressedTexSubImage3D ( GL_TEXTURE_CUBE_MAP_ARRAY , currentMip , 0 , 0 , slot * 6 + face , mipSize , mipSize , 1 , GFXGLTextureFormat [ mFormat ] , GFXGLTextureType [ mFormat ] , pixelData ) ;
2019-04-16 04:11:18 +00:00
}
else
2019-04-28 23:32:23 +00:00
{
2019-04-27 08:09:01 +00:00
glTexSubImage3D ( GL_TEXTURE_CUBE_MAP_ARRAY , currentMip , 0 , 0 , slot * 6 + face , mipSize , mipSize , 1 , GFXGLTextureFormat [ mFormat ] , GFXGLTextureType [ mFormat ] , pixelData ) ;
2019-04-28 23:32:23 +00:00
}
2019-04-27 08:09:01 +00:00
glBindTexture ( GL_TEXTURE_CUBE_MAP_ARRAY , 0 ) ;
2019-04-16 04:11:18 +00:00
delete [ ] pixelData ;
}
}
}
void GFXGLCubemapArray : : copyTo ( GFXCubemapArray * pDstCubemap )
{
AssertFatal ( pDstCubemap , " GFXGLCubemapArray::copyTo - Got null GFXCubemapArray " ) ;
const U32 dstCount = pDstCubemap - > getNumCubemaps ( ) ;
const GFXFormat dstFmt = pDstCubemap - > getFormat ( ) ;
const U32 dstSize = pDstCubemap - > getSize ( ) ;
const U32 dstMips = pDstCubemap - > getMipMapLevels ( ) ;
AssertFatal ( dstCount > mNumCubemaps , " GFXGLCubemapArray::copyTo - Destination too small " ) ;
AssertFatal ( dstFmt = = mFormat , " GFXGLCubemapArray::copyTo - Destination format doesn't match " ) ;
AssertFatal ( dstSize = = mSize , " GFXGLCubemapArray::copyTo - Destination size doesn't match " ) ;
AssertFatal ( dstMips = = mMipMapLevels , " GFXGLCubemapArray::copyTo - Destination mip levels doesn't match " ) ;
GFXGLCubemapArray * pDstCube = static_cast < GFXGLCubemapArray * > ( pDstCubemap ) ;
for ( U32 cubeMap = 0 ; cubeMap < mNumCubemaps ; cubeMap + + )
{
for ( U32 face = 0 ; face < CubeFaces ; face + + )
{
for ( U32 currentMip = 0 ; currentMip < mMipMapLevels ; currentMip + + )
//U32 currentMip = 0;
{
//U8 *pixelData = pDstCube->get->getTextureData(face, currentMip);
const U32 mipSize = getMax ( U32 ( 1 ) , mSize > > currentMip ) ;
/*if (isCompressed)
{
const U32 mipDataSize = getCompressedSurfaceSize ( mFormat , mSize , mSize , currentMip ) ;
2020-07-04 03:56:44 +00:00
glCompressedTexImage2D ( GFXGLFaceType [ face ] , currentMip , GFXGLTextureInternalFormat [ mFormat ] , mipSize , mipSize , 0 , mipDataSize , pixelData ) ;
2019-04-16 04:11:18 +00:00
}
else
{ */ //TODO figure out xyzOffsets
2019-04-26 06:57:07 +00:00
glCopyImageSubData ( mCubemap , GL_TEXTURE_CUBE_MAP_ARRAY , currentMip , 0 , 0 , cubeMap * face , pDstCube - > mCubemap , GL_TEXTURE_CUBE_MAP_ARRAY , currentMip , 0 , 0 , cubeMap * face , mipSize , mipSize , 6 ) ;
2019-04-16 04:11:18 +00:00
//glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, mCubemap);
//glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, currentMip, 0, 0, 0, mipSize, mipSize, CubeFaces, GFXGLTextureFormat[mFormat], GFXGLTextureType[mFormat], pixelData);
//}
//delete[] pixelData;
}
}
}
}
void GFXGLCubemapArray : : setToTexUnit ( U32 tuNum )
{
static_cast < GFXGLDevice * > ( getOwningDevice ( ) ) - > setCubemapArrayInternal ( tuNum , this ) ;
}
void GFXGLCubemapArray : : bind ( U32 textureUnit ) const
{
glActiveTexture ( GL_TEXTURE0 + textureUnit ) ;
glBindTexture ( GL_TEXTURE_CUBE_MAP_ARRAY , mCubemap ) ;
static_cast < GFXGLDevice * > ( getOwningDevice ( ) ) - > getOpenglCache ( ) - > setCacheBindedTex ( textureUnit , GL_TEXTURE_CUBE_MAP_ARRAY , mCubemap ) ;
GFXGLStateBlockRef sb = static_cast < GFXGLDevice * > ( GFX ) - > getCurrentStateBlock ( ) ;
AssertFatal ( sb , " GFXGLCubemap::bind - No active stateblock! " ) ;
if ( ! sb )
return ;
const GFXSamplerStateDesc & ssd = sb - > getDesc ( ) . samplers [ textureUnit ] ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_MIN_FILTER , minificationFilter ( ssd . minFilter , ssd . mipFilter , 0 ) ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_MAG_FILTER , GFXGLTextureFilter [ ssd . magFilter ] ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_WRAP_S , GFXGLTextureAddress [ ssd . addressModeU ] ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_WRAP_T , GFXGLTextureAddress [ ssd . addressModeV ] ) ;
glTexParameteri ( GL_TEXTURE_CUBE_MAP_ARRAY , GL_TEXTURE_WRAP_R , GFXGLTextureAddress [ ssd . addressModeW ] ) ;
}