mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-09-08 14:17:06 +03:00
0031478: Visualization, TKOpenGl - allow uploading Cubemap in compressed DDS format when supported by GPU
Graphic3d_TextureRoot::GetCompressedImage() - added new interface for fetching compressed texture image. Default implementation detects DDS image files using Image_DDSParser parser. Graphic3d_TextureRoot::GetImage() has been extended with new parameter - the list of image formats supported by OpenGL driver. Graphic3d_TextureRoot::convertToCompatible() implicitly converts BGRA image to RGBA on OpenGL ES, which normally does not support BGR formats. OpenGl_Caps::isTopDownTextureUV - new property defines how application defines UV texture coordinates in primitive arrays. OpenGl_Context::SetTextureMatrix() compares this flag with OpenGl_Texture::IsTopDown() and automatically flips V coordinate in case of mismatch. OpenGl_Texture now holds exact number of mipmap levels instead of Boolean flag indicating that they are defined. This allows loading DDS files with incomplete mipmap level set by setting GL_TEXTURE_MAX_LEVEL to appropriate value instead of default 1000 (causing black textures in case if mipmap levels are not defined till 1x1). Fixed order of texture coordinates transformation within GLSL program to match FFP matrix: Rotate -> Translate -> Scale (previously Rotation was applied afterwards).
This commit is contained in:
@@ -21,10 +21,15 @@
|
||||
#include <Graphic3d_TextureParams.hxx>
|
||||
#include <TCollection_ExtendedString.hxx>
|
||||
#include <Standard_Assert.hxx>
|
||||
#include <Image_CompressedPixMap.hxx>
|
||||
#include <Image_PixMap.hxx>
|
||||
#include <Image_SupportedFormats.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Texture, OpenGl_NamedResource)
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
//! Simple class to reset unpack alignment settings
|
||||
struct OpenGl_UnpackAlignmentSentry
|
||||
{
|
||||
@@ -47,6 +52,43 @@ struct OpenGl_UnpackAlignmentSentry
|
||||
|
||||
};
|
||||
|
||||
//! Compute the upper mipmap level for complete mipmap set (e.g. till the 1x1 level).
|
||||
static Standard_Integer computeUpperMipMapLevel (Standard_Integer theSize)
|
||||
{
|
||||
for (Standard_Integer aMipIter = 0;; ++aMipIter, theSize /= 2)
|
||||
{
|
||||
if (theSize <= 1)
|
||||
{
|
||||
return aMipIter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Compute the upper mipmap level for complete mipmap set (e.g. till the 1x1 level).
|
||||
static Standard_Integer computeUpperMipMapLevel (Standard_Integer theSizeX, Standard_Integer theSizeY)
|
||||
{
|
||||
return computeUpperMipMapLevel (Max (theSizeX, theSizeY));
|
||||
}
|
||||
|
||||
//! Compute size of the smallest defined mipmap level (for verbose messages).
|
||||
static Graphic3d_Vec2i computeSmallestMipMapSize (const Graphic3d_Vec2i& theBaseSize, Standard_Integer theMaxLevel)
|
||||
{
|
||||
Graphic3d_Vec2i aMipSizeXY = theBaseSize;
|
||||
for (Standard_Integer aMipIter = 0;; ++aMipIter)
|
||||
{
|
||||
if (aMipIter > theMaxLevel)
|
||||
{
|
||||
return aMipSizeXY;
|
||||
}
|
||||
|
||||
aMipSizeXY /= 2;
|
||||
if (aMipSizeXY.x() == 0) { aMipSizeXY.x() = 1; }
|
||||
if (aMipSizeXY.y() == 0) { aMipSizeXY.y() = 1; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : OpenGl_Texture
|
||||
// purpose :
|
||||
@@ -64,8 +106,9 @@ OpenGl_Texture::OpenGl_Texture (const TCollection_AsciiString& theResourceId,
|
||||
myTextFormat (GL_RGBA),
|
||||
mySizedFormat(GL_RGBA8),
|
||||
myNbSamples (1),
|
||||
myHasMipmaps (Standard_False),
|
||||
myIsAlpha (false)
|
||||
myMaxMipLevel(0),
|
||||
myIsAlpha (false),
|
||||
myIsTopDown (true)
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -130,10 +173,10 @@ void OpenGl_Texture::Release (OpenGl_Context* theGlCtx)
|
||||
// =======================================================================
|
||||
void OpenGl_Texture::applyDefaultSamplerParams (const Handle(OpenGl_Context)& theCtx)
|
||||
{
|
||||
OpenGl_Sampler::applySamplerParams (theCtx, mySampler->Parameters(), NULL, myTarget, myHasMipmaps);
|
||||
OpenGl_Sampler::applySamplerParams (theCtx, mySampler->Parameters(), NULL, myTarget, myMaxMipLevel);
|
||||
if (mySampler->IsValid() && !mySampler->IsImmutable())
|
||||
{
|
||||
OpenGl_Sampler::applySamplerParams (theCtx, mySampler->Parameters(), mySampler.get(), myTarget, myHasMipmaps);
|
||||
OpenGl_Sampler::applySamplerParams (theCtx, mySampler->Parameters(), mySampler.get(), myTarget, myMaxMipLevel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,11 +246,10 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
|
||||
#else
|
||||
const GLenum aTarget = GL_TEXTURE_2D;
|
||||
#endif
|
||||
const Standard_Boolean toCreateMipMaps = (theType == Graphic3d_TOT_2D_MIPMAP);
|
||||
const bool toPatchExisting = IsValid()
|
||||
&& myTextFormat == theFormat.PixelFormat()
|
||||
&& myTarget == aTarget
|
||||
&& myHasMipmaps == toCreateMipMaps
|
||||
&& HasMipmaps() == (theType == Graphic3d_TOT_2D_MIPMAP)
|
||||
&& mySizeX == theSizeXY.x()
|
||||
&& (mySizeY == theSizeXY.y() || theType == Graphic3d_TOT_1D);
|
||||
if (!Create (theCtx))
|
||||
@@ -220,16 +262,19 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
|
||||
{
|
||||
myIsAlpha = theImage->Format() == Image_Format_Alpha
|
||||
|| theImage->Format() == Image_Format_AlphaF;
|
||||
myIsTopDown = theImage->IsTopDown();
|
||||
}
|
||||
else
|
||||
{
|
||||
myIsAlpha = theFormat.PixelFormat() == GL_ALPHA;
|
||||
}
|
||||
|
||||
myHasMipmaps = toCreateMipMaps;
|
||||
myTextFormat = theFormat.PixelFormat();
|
||||
mySizedFormat = theFormat.InternalFormat();
|
||||
myNbSamples = 1;
|
||||
myMaxMipLevel = theType == Graphic3d_TOT_2D_MIPMAP && theCtx->arbFBO != NULL
|
||||
? computeUpperMipMapLevel (theSizeXY.x(), theSizeXY.y())
|
||||
: 0;
|
||||
myTextFormat = theFormat.PixelFormat();
|
||||
mySizedFormat = theFormat.InternalFormat();
|
||||
myNbSamples = 1;
|
||||
#if !defined(GL_ES_VERSION_2_0)
|
||||
const GLint anIntFormat = theFormat.InternalFormat();
|
||||
#else
|
||||
@@ -294,8 +339,7 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
|
||||
#endif
|
||||
|
||||
#if !defined(GL_ES_VERSION_2_0)
|
||||
GLint aTestWidth = 0;
|
||||
GLint aTestHeight = 0;
|
||||
GLint aTestWidth = 0, aTestHeight = 0;
|
||||
#endif
|
||||
GLvoid* aDataPtr = (theImage != NULL) ? (GLvoid* )theImage->Data() : NULL;
|
||||
|
||||
@@ -369,58 +413,6 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
|
||||
#endif
|
||||
}
|
||||
case Graphic3d_TOT_2D:
|
||||
{
|
||||
Bind (theCtx);
|
||||
applyDefaultSamplerParams (theCtx);
|
||||
if (toPatchExisting)
|
||||
{
|
||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||
0, 0,
|
||||
theSizeXY.x(), theSizeXY.y(),
|
||||
theFormat.PixelFormat(), theFormat.DataType(), aDataPtr);
|
||||
Unbind (theCtx);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !defined(GL_ES_VERSION_2_0)
|
||||
// use proxy to check texture could be created or not
|
||||
glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat,
|
||||
theSizeXY.x(), theSizeXY.y(), 0,
|
||||
theFormat.PixelFormat(), theFormat.DataType(), NULL);
|
||||
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
|
||||
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
|
||||
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
|
||||
if (aTestWidth == 0 || aTestHeight == 0)
|
||||
{
|
||||
// no memory or broken input parameters
|
||||
Unbind (theCtx);
|
||||
Release (theCtx.get());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
|
||||
theSizeXY.x(), theSizeXY.y(), 0,
|
||||
theFormat.PixelFormat(), theFormat.DataType(), aDataPtr);
|
||||
const GLenum anErr = glGetError();
|
||||
if (anErr != GL_NO_ERROR)
|
||||
{
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
|
||||
TCollection_AsciiString ("Error: 2D texture ") + theSizeXY.x() + "x" + theSizeXY.y()
|
||||
+ " IF: " + int(anIntFormat) + " PF: " + int(theFormat.PixelFormat())
|
||||
+ " DT: " + int(theFormat.DataType())
|
||||
+ " can not be created with error " + int(anErr) + ".");
|
||||
Unbind (theCtx);
|
||||
Release (theCtx.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
mySizeX = theSizeXY.x();
|
||||
mySizeY = theSizeXY.y();
|
||||
|
||||
Unbind (theCtx);
|
||||
return true;
|
||||
}
|
||||
case Graphic3d_TOT_2D_MIPMAP:
|
||||
{
|
||||
Bind (theCtx);
|
||||
@@ -431,15 +423,14 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
|
||||
0, 0,
|
||||
theSizeXY.x(), theSizeXY.y(),
|
||||
theFormat.PixelFormat(), theFormat.DataType(), aDataPtr);
|
||||
if (theCtx->arbFBO != NULL)
|
||||
|
||||
if (myMaxMipLevel > 0)
|
||||
{
|
||||
// generate mipmaps
|
||||
theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
|
||||
if (glGetError() != GL_NO_ERROR)
|
||||
{
|
||||
Unbind (theCtx);
|
||||
Release (theCtx.get());
|
||||
return false;
|
||||
myMaxMipLevel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,18 +455,17 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
|
||||
}
|
||||
#endif
|
||||
|
||||
// upload main picture
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat,
|
||||
theSizeXY.x(), theSizeXY.y(), 0,
|
||||
theFormat.PixelFormat(), theFormat.DataType(), theImage->Data());
|
||||
const GLenum aTexImgErr = glGetError();
|
||||
if (aTexImgErr != GL_NO_ERROR)
|
||||
theFormat.PixelFormat(), theFormat.DataType(), aDataPtr);
|
||||
GLenum anErr = glGetError();
|
||||
if (anErr != GL_NO_ERROR)
|
||||
{
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
|
||||
TCollection_AsciiString ("Error: 2D texture ") + theSizeXY.x() + "x" + theSizeXY.y()
|
||||
+ " IF: " + int(anIntFormat) + " PF: " + int(theFormat.PixelFormat())
|
||||
+ " DT: " + int(theFormat.DataType())
|
||||
+ " can not be created with error " + int(aTexImgErr) + ".");
|
||||
+ " IF: " + int(anIntFormat) + " PF: " + int(theFormat.PixelFormat())
|
||||
+ " DT: " + int(theFormat.DataType())
|
||||
+ " can not be created with error " + int(anErr) + ".");
|
||||
Unbind (theCtx);
|
||||
Release (theCtx.get());
|
||||
return false;
|
||||
@@ -484,27 +474,19 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
|
||||
mySizeX = theSizeXY.x();
|
||||
mySizeY = theSizeXY.y();
|
||||
|
||||
if (theCtx->arbFBO != NULL)
|
||||
if (myMaxMipLevel > 0)
|
||||
{
|
||||
// generate mipmaps
|
||||
//glHint (GL_GENERATE_MIPMAP_HINT, GL_NICEST);
|
||||
theCtx->arbFBO->glGenerateMipmap (GL_TEXTURE_2D);
|
||||
|
||||
if (glGetError() != GL_NO_ERROR)
|
||||
anErr = glGetError();
|
||||
if (anErr != GL_NO_ERROR)
|
||||
{
|
||||
Unbind (theCtx);
|
||||
Release (theCtx.get());
|
||||
return false;
|
||||
myMaxMipLevel = 0;
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
|
||||
"Warning: generating mipmaps requires GL_ARB_framebuffer_object extension which is missing.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
|
||||
"Warning: generating mipmaps requires GL_ARB_framebuffer_object extension which is missing.");
|
||||
Unbind (theCtx);
|
||||
Release (theCtx.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
Unbind (theCtx);
|
||||
return true;
|
||||
@@ -568,7 +550,16 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
|
||||
}
|
||||
default:
|
||||
{
|
||||
Handle(Image_PixMap) anImage = theTextureMap->GetImage();
|
||||
if (theCtx->SupportedTextureFormats()->HasCompressed()
|
||||
&& !theCtx->caps->compressedTexturesDisable)
|
||||
{
|
||||
if (Handle(Image_CompressedPixMap) aCompressed = theTextureMap->GetCompressedImage (theCtx->SupportedTextureFormats()))
|
||||
{
|
||||
return InitCompressed (theCtx, *aCompressed, theTextureMap->IsColorMap());
|
||||
}
|
||||
}
|
||||
|
||||
Handle(Image_PixMap) anImage = theTextureMap->GetImage (theCtx->SupportedTextureFormats());
|
||||
if (anImage.IsNull())
|
||||
{
|
||||
return false;
|
||||
@@ -578,6 +569,106 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx,
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : InitCompressed
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool OpenGl_Texture::InitCompressed (const Handle(OpenGl_Context)& theCtx,
|
||||
const Image_CompressedPixMap& theImage,
|
||||
const Standard_Boolean theIsColorMap)
|
||||
{
|
||||
if (theImage.SizeX() < 1
|
||||
|| theImage.SizeY() < 1
|
||||
|| theImage.FaceData().IsNull())
|
||||
{
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
|
||||
"Error: texture of 0 size cannot be created.");
|
||||
Release (theCtx.get());
|
||||
return false;
|
||||
}
|
||||
if (theImage.SizeX() > theCtx->MaxTextureSize()
|
||||
|| theImage.SizeY() > theCtx->MaxTextureSize())
|
||||
{
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
|
||||
TCollection_AsciiString ("Error: Texture dimension - ") + theImage.SizeX() + "x" + theImage.SizeY()
|
||||
+ " exceeds hardware limits (" + theCtx->MaxTextureSize() + "x" + theCtx->MaxTextureSize() + ")");
|
||||
Release (theCtx.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
const OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindCompressedFormat (theCtx, theImage.CompressedFormat(), theIsColorMap);
|
||||
if (!aFormat.IsValid())
|
||||
{
|
||||
Release (theCtx.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Create (theCtx))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
myTarget = GL_TEXTURE_2D;
|
||||
myNbSamples = 1;
|
||||
myTextFormat = aFormat.Format();
|
||||
mySizedFormat = aFormat.Internal();
|
||||
myIsTopDown = theImage.IsTopDown();
|
||||
mySizeX = theImage.SizeX();
|
||||
mySizeY = theImage.SizeY();
|
||||
myMaxMipLevel = Max (theImage.MipMaps().Size() - 1, 0);
|
||||
if (myMaxMipLevel > 0
|
||||
&& !theImage.IsCompleteMipMapSet())
|
||||
{
|
||||
const Graphic3d_Vec2i aMipSize = computeSmallestMipMapSize (Graphic3d_Vec2i (mySizeX, mySizeY), myMaxMipLevel);
|
||||
if (!theCtx->HasTextureBaseLevel())
|
||||
{
|
||||
myMaxMipLevel = 0;
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_MEDIUM,
|
||||
TCollection_AsciiString ("Warning: compressed 2D texture ") + myResourceId + " " + mySizeX + "x" + mySizeY
|
||||
+ " has smallest mipmap " + aMipSize.x() + "x" + aMipSize.y() + "; mipmaps will be ignored");
|
||||
}
|
||||
else
|
||||
{
|
||||
Message::SendTrace (TCollection_AsciiString ("Warning: compressed 2D texture ") + myResourceId + " " + mySizeX + "x" + mySizeY
|
||||
+ " has smallest mipmap " + aMipSize.x() + "x" + aMipSize.y());
|
||||
}
|
||||
}
|
||||
|
||||
Bind (theCtx);
|
||||
applyDefaultSamplerParams (theCtx);
|
||||
|
||||
// setup the alignment
|
||||
OpenGl_UnpackAlignmentSentry::Reset();
|
||||
|
||||
Graphic3d_Vec2i aMipSizeXY (theImage.SizeX(), theImage.SizeY());
|
||||
const Standard_Byte* aData = theImage.FaceData()->Data();
|
||||
for (Standard_Integer aMipIter = 0; aMipIter <= myMaxMipLevel; ++aMipIter)
|
||||
{
|
||||
const Standard_Integer aMipLength = theImage.MipMaps().Value (aMipIter);
|
||||
theCtx->Functions()->glCompressedTexImage2D (GL_TEXTURE_2D, aMipIter, mySizedFormat, aMipSizeXY.x(), aMipSizeXY.y(), 0, aMipLength, aData);
|
||||
const GLenum aTexImgErr = glGetError();
|
||||
if (aTexImgErr != GL_NO_ERROR)
|
||||
{
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
|
||||
TCollection_AsciiString ("Error: 2D compressed texture ") + aMipSizeXY.x() + "x" + aMipSizeXY.y()
|
||||
+ " IF: " + int(aFormat.Internal()) + " PF: " + int(aFormat.PixelFormat())
|
||||
+ " DT: " + int(aFormat.DataType())
|
||||
+ " can not be created with error " + int(aTexImgErr) + ".");
|
||||
Unbind (theCtx);
|
||||
Release (theCtx.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
aData += aMipLength;
|
||||
aMipSizeXY /= 2;
|
||||
if (aMipSizeXY.x() == 0) { aMipSizeXY.x() = 1; }
|
||||
if (aMipSizeXY.y() == 0) { aMipSizeXY.y() = 1; }
|
||||
}
|
||||
|
||||
Unbind (theCtx);
|
||||
return true;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Init2DMultisample
|
||||
// purpose :
|
||||
@@ -597,7 +688,7 @@ bool OpenGl_Texture::Init2DMultisample (const Handle(OpenGl_Context)& theCtx,
|
||||
|
||||
myNbSamples = OpenGl_Context::GetPowerOfTwo (theNbSamples, theCtx->MaxMsaaSamples());
|
||||
myTarget = GL_TEXTURE_2D_MULTISAMPLE;
|
||||
myHasMipmaps = false;
|
||||
myMaxMipLevel = 0;
|
||||
if(theSizeX > theCtx->MaxTextureSize()
|
||||
|| theSizeY > theCtx->MaxTextureSize())
|
||||
{
|
||||
@@ -649,7 +740,7 @@ bool OpenGl_Texture::InitRectangle (const Handle(OpenGl_Context)& theCtx,
|
||||
#if !defined(GL_ES_VERSION_2_0)
|
||||
myTarget = GL_TEXTURE_RECTANGLE;
|
||||
myNbSamples = 1;
|
||||
myHasMipmaps = false;
|
||||
myMaxMipLevel = 0;
|
||||
|
||||
const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX);
|
||||
const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY);
|
||||
@@ -726,7 +817,7 @@ bool OpenGl_Texture::Init3D (const Handle(OpenGl_Context)& theCtx,
|
||||
|
||||
myTarget = GL_TEXTURE_3D;
|
||||
myNbSamples = 1;
|
||||
myHasMipmaps = false;
|
||||
myMaxMipLevel = 0;
|
||||
|
||||
const Graphic3d_Vec3i aSizeXYZ = theSizeXYZ.cwiseMin (Graphic3d_Vec3i (theCtx->MaxTextureSize()));
|
||||
if (aSizeXYZ != theSizeXYZ)
|
||||
@@ -809,24 +900,80 @@ bool OpenGl_Texture::InitCubeMap (const Handle(OpenGl_Context)& theCtx,
|
||||
return false;
|
||||
}
|
||||
|
||||
Handle(Image_PixMap) anImage;
|
||||
Handle(Image_CompressedPixMap) aCompImage;
|
||||
OpenGl_TextureFormat aFormat;
|
||||
if (!theCubeMap.IsNull())
|
||||
{
|
||||
theToGenMipmap = theCubeMap->HasMipmaps();
|
||||
if (Handle(Image_PixMap) anImage = theCubeMap->Reset().Value())
|
||||
theCubeMap->Reset();
|
||||
if (theCtx->SupportedTextureFormats()->HasCompressed()
|
||||
&& !theCtx->caps->compressedTexturesDisable)
|
||||
{
|
||||
aCompImage = theCubeMap->CompressedValue (theCtx->SupportedTextureFormats());
|
||||
}
|
||||
if (!aCompImage.IsNull())
|
||||
{
|
||||
aFormat = OpenGl_TextureFormat::FindCompressedFormat (theCtx, aCompImage->CompressedFormat(), theIsColorMap);
|
||||
if (aFormat.IsValid())
|
||||
{
|
||||
theToGenMipmap = false;
|
||||
theSize = aCompImage->SizeX();
|
||||
theFormat = aCompImage->BaseFormat();
|
||||
myMaxMipLevel = Max (aCompImage->MipMaps().Size() - 1, 0);
|
||||
if (myMaxMipLevel > 0
|
||||
&& !aCompImage->IsCompleteMipMapSet())
|
||||
{
|
||||
const Graphic3d_Vec2i aMipSize = computeSmallestMipMapSize (Graphic3d_Vec2i (aCompImage->SizeX(), aCompImage->SizeY()), myMaxMipLevel);
|
||||
if (!theCtx->HasTextureBaseLevel())
|
||||
{
|
||||
myMaxMipLevel = 0;
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_MEDIUM,
|
||||
TCollection_AsciiString ("Warning: Cubemap compressed texture ") + theCubeMap->GetId() + " " + aCompImage->SizeX() + "x" + aCompImage->SizeX()
|
||||
+ " has smallest mipmap " + aMipSize.x() + "x" + aMipSize.y() + "; mipmaps will be ignored");
|
||||
}
|
||||
else
|
||||
{
|
||||
Message::SendTrace (TCollection_AsciiString ("Warning: Cubemap compressed texture ") + theCubeMap->GetId() + " " + aCompImage->SizeX() + "x" + aCompImage->SizeX()
|
||||
+ " has smallest mipmap " + aMipSize.x() + "x" + aMipSize.y());
|
||||
}
|
||||
}
|
||||
|
||||
OpenGl_UnpackAlignmentSentry::Reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
aCompImage.Nullify();
|
||||
}
|
||||
}
|
||||
|
||||
if (!aFormat.IsValid())
|
||||
{
|
||||
anImage = theCubeMap->Reset().Value (theCtx->SupportedTextureFormats());
|
||||
if (anImage.IsNull())
|
||||
{
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
|
||||
"Unable to get the first side of cubemap");
|
||||
Release(theCtx.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
theSize = anImage->SizeX();
|
||||
theFormat = anImage->Format();
|
||||
theToGenMipmap = theCubeMap->HasMipmaps();
|
||||
myMaxMipLevel = theToGenMipmap ? computeUpperMipMapLevel ((Standard_Integer )theSize) : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
|
||||
"Unable to get the first side of cubemap");
|
||||
Release(theCtx.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
myIsTopDown = theCubeMap->IsTopDown();
|
||||
}
|
||||
else
|
||||
{
|
||||
myMaxMipLevel = theToGenMipmap ? computeUpperMipMapLevel ((Standard_Integer )theSize) : 0;
|
||||
}
|
||||
|
||||
OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindFormat (theCtx, theFormat, theIsColorMap);
|
||||
if (!aFormat.IsValid())
|
||||
{
|
||||
aFormat = OpenGl_TextureFormat::FindFormat (theCtx, theFormat, theIsColorMap);
|
||||
}
|
||||
if (!aFormat.IsValid())
|
||||
{
|
||||
Unbind(theCtx);
|
||||
@@ -835,21 +982,62 @@ bool OpenGl_Texture::InitCubeMap (const Handle(OpenGl_Context)& theCtx,
|
||||
}
|
||||
|
||||
myTarget = GL_TEXTURE_CUBE_MAP;
|
||||
myHasMipmaps = theToGenMipmap;
|
||||
myNbSamples = 1;
|
||||
mySizeX = (GLsizei )theSize;
|
||||
mySizeY = (GLsizei )theSize;
|
||||
myTextFormat = aFormat.Format();
|
||||
mySizedFormat = aFormat.Internal();
|
||||
Bind (theCtx);
|
||||
applyDefaultSamplerParams (theCtx);
|
||||
|
||||
for (Standard_Integer i = 0; i < 6; ++i)
|
||||
{
|
||||
const void* aData = NULL;
|
||||
Handle(Image_PixMap) anImage;
|
||||
const Standard_Byte* aData = NULL;
|
||||
|
||||
if (!theCubeMap.IsNull())
|
||||
{
|
||||
anImage = theCubeMap->Value();
|
||||
if (i != 0)
|
||||
{
|
||||
if (!aCompImage.IsNull())
|
||||
{
|
||||
aCompImage = theCubeMap->CompressedValue (theCtx->SupportedTextureFormats());
|
||||
}
|
||||
else
|
||||
{
|
||||
anImage = theCubeMap->Value (theCtx->SupportedTextureFormats());
|
||||
}
|
||||
}
|
||||
if (!aCompImage.IsNull())
|
||||
{
|
||||
Graphic3d_Vec2i aMipSizeXY (mySizeX, mySizeY);
|
||||
aData = aCompImage->FaceData()->Data();
|
||||
for (Standard_Integer aMipIter = 0; aMipIter <= myMaxMipLevel; ++aMipIter)
|
||||
{
|
||||
const Standard_Integer aMipLength = aCompImage->MipMaps().Value (aMipIter);
|
||||
theCtx->Functions()->glCompressedTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, aMipIter, mySizedFormat, aMipSizeXY.x(), aMipSizeXY.y(), 0, aMipLength, aData);
|
||||
const GLenum aTexImgErr = glGetError();
|
||||
if (aTexImgErr != GL_NO_ERROR)
|
||||
{
|
||||
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
|
||||
TCollection_AsciiString ("Error: cubemap compressed texture ") + aMipSizeXY.x() + "x" + aMipSizeXY.y()
|
||||
+ " IF: " + int(aFormat.Internal()) + " PF: " + int(aFormat.PixelFormat())
|
||||
+ " DT: " + int(aFormat.DataType())
|
||||
+ " can not be created with error " + int(aTexImgErr) + ".");
|
||||
Unbind (theCtx);
|
||||
Release (theCtx.get());
|
||||
return false;
|
||||
}
|
||||
|
||||
aData += aMipLength;
|
||||
aMipSizeXY /= 2;
|
||||
if (aMipSizeXY.x() == 0) { aMipSizeXY.x() = 1; }
|
||||
if (aMipSizeXY.y() == 0) { aMipSizeXY.y() = 1; }
|
||||
}
|
||||
|
||||
theCubeMap->Next();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!anImage.IsNull())
|
||||
{
|
||||
#if !defined(GL_ES_VERSION_2_0)
|
||||
@@ -970,8 +1158,18 @@ Standard_Size OpenGl_Texture::PixelSizeOfPixelFormat (Standard_Integer theIntern
|
||||
case GL_DEPTH_COMPONENT16: return 2;
|
||||
case GL_DEPTH_COMPONENT24: return 3;
|
||||
case GL_DEPTH_COMPONENT32F: return 4;
|
||||
// compressed
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // DXT1 uses circa half a byte per pixel (64 bits per 4x4 block)
|
||||
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: // DXT3/5 uses circa 1 byte per pixel (128 bits per 4x4 block)
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
@@ -998,7 +1196,7 @@ Standard_Size OpenGl_Texture::EstimatedDataSize() const
|
||||
{
|
||||
aSize *= 6; // cube sides
|
||||
}
|
||||
if (myHasMipmaps)
|
||||
if (myMaxMipLevel > 0)
|
||||
{
|
||||
aSize = aSize + aSize / 3;
|
||||
}
|
||||
|
Reference in New Issue
Block a user