Added ImageProcessor interface class and plugin mechnanism for ImageProcessor implementations to osgDB::Registry.
Add NVidiaTextureTools based plugin that provides an ImageProcessor implementation within an nvtt plugin.
This commit is contained in:
parent
f61a6aa4e7
commit
1b67e3ad1f
@ -423,6 +423,7 @@ FIND_PACKAGE(Poppler-glib)
|
||||
FIND_PACKAGE(RSVG)
|
||||
FIND_PACKAGE(GtkGl)
|
||||
FIND_PACKAGE(DirectInput)
|
||||
FIND_PACKAGE(NVTT)
|
||||
|
||||
# Include macro utilities here
|
||||
INCLUDE(OsgMacroUtils)
|
||||
|
61
CMakeModules/FindNVTT.cmake
Normal file
61
CMakeModules/FindNVTT.cmake
Normal file
@ -0,0 +1,61 @@
|
||||
# Locate nvidia-texture-tools
|
||||
# This module defines
|
||||
# NVTT_LIBRARY
|
||||
# NVTT_FOUND, if false, do not try to link to nvtt
|
||||
# NVTT_INCLUDE_DIR, where to find the headers
|
||||
#
|
||||
|
||||
|
||||
FIND_PATH(NVTT_INCLUDE_DIR nvtt/nvtt.h
|
||||
PATHS
|
||||
/usr/local
|
||||
/usr
|
||||
$ENV{NVTT_DIR}
|
||||
${3rdPartyRoot}
|
||||
PATH_SUFFIXES include
|
||||
)
|
||||
|
||||
FIND_LIBRARY(NVTT_LIBRARY
|
||||
NAMES nvtt
|
||||
PATHS
|
||||
/usr/local
|
||||
/usr
|
||||
$ENV{NVTT_DIR}
|
||||
${3rdPartyRoot}
|
||||
PATH_SUFFIXES lib64 lib lib/shared lib/static lib64/static
|
||||
)
|
||||
|
||||
FIND_LIBRARY(NVIMAGE_LIBRARY
|
||||
NAMES nvimage
|
||||
PATHS
|
||||
/usr/local
|
||||
/usr
|
||||
$ENV{NVTT_DIR}
|
||||
${3rdPartyRoot}
|
||||
PATH_SUFFIXES lib64 lib lib/shared lib/static lib64/static
|
||||
)
|
||||
|
||||
FIND_LIBRARY(NVMATH_LIBRARY
|
||||
NAMES nvmath
|
||||
PATHS
|
||||
/usr/local
|
||||
/usr
|
||||
$ENV{NVTT_DIR}
|
||||
${3rdPartyRoot}
|
||||
PATH_SUFFIXES lib64 lib lib/shared lib/static lib64/static
|
||||
)
|
||||
|
||||
FIND_LIBRARY(NVCORE_LIBRARY
|
||||
NAMES nvcore
|
||||
PATHS
|
||||
/usr/local
|
||||
/usr
|
||||
$ENV{NVTT_DIR}
|
||||
${3rdPartyRoot}
|
||||
PATH_SUFFIXES lib64 lib lib/shared lib/static lib64/static
|
||||
)
|
||||
|
||||
SET(NVTT_FOUND "NO")
|
||||
IF(NVTT_LIBRARY AND NVTT_INCLUDE_DIR)
|
||||
SET(NVTT_FOUND "YES")
|
||||
ENDIF(NVTT_LIBRARY AND NVTT_INCLUDE_DIR)
|
54
include/osgDB/ImageProcessor
Normal file
54
include/osgDB/ImageProcessor
Normal file
@ -0,0 +1,54 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
||||
*
|
||||
* This library is open source and may be redistributed and/or modified under
|
||||
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||
* (at your option) any later version. The full license is in LICENSE file
|
||||
* included with this distribution, and on the openscenegraph.org website.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* OpenSceneGraph Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef OSGDB_IMAGEPROCESSOR
|
||||
#define OSGDB_IMAGEPROCESSOR 1
|
||||
|
||||
#include <osg/Object>
|
||||
|
||||
namespace osgDB {
|
||||
|
||||
class ImageProcessor : public osg::Object
|
||||
{
|
||||
public:
|
||||
|
||||
ImageProcessor():
|
||||
osg::Object(true) {}
|
||||
|
||||
ImageProcessor(const ImageProcessor& rw,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):
|
||||
osg::Object(rw,copyop) {}
|
||||
|
||||
virtual ~ImageProcessor() {}
|
||||
|
||||
META_Object(osgDB,ImageProcessor);
|
||||
|
||||
enum CompressionMethod
|
||||
{
|
||||
USE_CPU, /// Use CPU for compression even when GPU compression is available
|
||||
USE_GPU /// Use GPU for compression when available (i.e CUDA), otherwise fallback to CPU
|
||||
};
|
||||
|
||||
enum CompressionQuality
|
||||
{
|
||||
FASTEST,
|
||||
NORMAL,
|
||||
PRODUCTION,
|
||||
HIGHEST
|
||||
};
|
||||
|
||||
virtual void compress(osg::Image& image, osg::Texture::InternalFormatMode compressedFormat, bool generateMipMap, bool resizeToPowerOfTwo, CompressionMethod method, CompressionQuality quality) {}
|
||||
virtual void generateMipMap(osg::Image& image, bool resizeToPowerOfTwo, CompressionMethod method) {}
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
@ -27,6 +27,7 @@
|
||||
#include <osgDB/ObjectWrapper>
|
||||
#include <osgDB/FileCache>
|
||||
#include <osgDB/SharedStateManager>
|
||||
#include <osgDB/ImageProcessor>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@ -59,7 +60,6 @@ struct type_wrapper: basic_type_wrapper {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Registry is a singleton factory which stores
|
||||
the reader/writers which are linked in
|
||||
@ -101,6 +101,9 @@ class OSGDB_EXPORT Registry : public osg::Referenced
|
||||
void addReaderWriter(ReaderWriter* rw);
|
||||
void removeReaderWriter(ReaderWriter* rw);
|
||||
|
||||
void addImageProcessor(ImageProcessor* ip);
|
||||
void removeImageProcessor(ImageProcessor* ip);
|
||||
|
||||
/** create the platform specific library name associated with file.*/
|
||||
std::string createLibraryNameForFile(const std::string& fileName);
|
||||
|
||||
@ -142,6 +145,21 @@ class OSGDB_EXPORT Registry : public osg::Referenced
|
||||
const ReaderWriterList& getReaderWriterList() const { return _rwList; }
|
||||
|
||||
|
||||
typedef std::vector< osg::ref_ptr<ImageProcessor> > ImageProcessorList;
|
||||
|
||||
/** get a image processor if available.*/
|
||||
ImageProcessor* getImageProcessor();
|
||||
|
||||
/** get a image processor which is associated specified extension.*/
|
||||
ImageProcessor* getImageProcessorForExtension(const std::string& ext);
|
||||
|
||||
/** get list of all registered ImageProcessors.*/
|
||||
ImageProcessorList& getImageProcessorList() { return _ipList; }
|
||||
|
||||
/** get const list of all registered ImageProcessors.*/
|
||||
const ImageProcessorList& getImageProcessorList() const { return _ipList; }
|
||||
|
||||
|
||||
typedef class osgDB::FindFileCallback FindFileCallback;
|
||||
typedef class osgDB::ReadFileCallback ReadFileCallback;
|
||||
typedef class osgDB::WriteFileCallback WriteFileCallback;
|
||||
@ -555,6 +573,7 @@ class OSGDB_EXPORT Registry : public osg::Referenced
|
||||
|
||||
OpenThreads::ReentrantMutex _pluginMutex;
|
||||
ReaderWriterList _rwList;
|
||||
ImageProcessorList _ipList;
|
||||
DynamicLibraryList _dlList;
|
||||
|
||||
bool _openingLibrary;
|
||||
@ -624,6 +643,34 @@ class RegisterReaderWriterProxy
|
||||
};
|
||||
|
||||
|
||||
/** Proxy class for automatic registration of reader/writers with the Registry.*/
|
||||
template<class T>
|
||||
class RegisterImageProcessorProxy
|
||||
{
|
||||
public:
|
||||
RegisterImageProcessorProxy()
|
||||
{
|
||||
if (Registry::instance())
|
||||
{
|
||||
_rw = new T;
|
||||
Registry::instance()->addImageProcessor(_rw.get());
|
||||
}
|
||||
}
|
||||
|
||||
~RegisterImageProcessorProxy()
|
||||
{
|
||||
if (Registry::instance())
|
||||
{
|
||||
Registry::instance()->removeImageProcessor(_rw.get());
|
||||
}
|
||||
}
|
||||
|
||||
T* get() { return _rw.get(); }
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<T> _rw;
|
||||
};
|
||||
|
||||
struct PluginFunctionProxy
|
||||
{
|
||||
PluginFunctionProxy(CPluginFunction function) { (function)(); }
|
||||
@ -657,6 +704,9 @@ struct PluginFunctionProxy
|
||||
extern "C" void osgdb_##ext(void) {} \
|
||||
static osgDB::RegisterReaderWriterProxy<classname> g_proxy_##classname;
|
||||
|
||||
#define REGISTER_OSGIMAGEPROCESSOR(ext, classname) \
|
||||
extern "C" void osgdb_##ext(void) {} \
|
||||
static osgDB::RegisterImageProcessorProxy<classname> g_proxy_##classname;
|
||||
|
||||
}
|
||||
|
||||
|
@ -550,6 +550,71 @@ void Registry::removeReaderWriter(ReaderWriter* rw)
|
||||
|
||||
}
|
||||
|
||||
ImageProcessor* Registry::getImageProcessor()
|
||||
{
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
|
||||
if (!_ipList.empty())
|
||||
{
|
||||
return _ipList.front().get();
|
||||
}
|
||||
}
|
||||
return getImageProcessorForExtension("nvtt");
|
||||
}
|
||||
|
||||
ImageProcessor* Registry::getImageProcessorForExtension(const std::string& ext)
|
||||
{
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
|
||||
if (!_ipList.empty())
|
||||
{
|
||||
return _ipList.front().get();
|
||||
}
|
||||
}
|
||||
|
||||
std::string libraryName = createLibraryNameForExtension(ext);
|
||||
OSG_NOTICE << "Now checking for plug-in "<<libraryName<< std::endl;
|
||||
if (loadLibrary(libraryName)==LOADED)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
|
||||
if (!_ipList.empty())
|
||||
{
|
||||
OSG_NOTICE << "Loaded plug-in "<<libraryName<<" and located ImageProcessor"<< std::endl;
|
||||
return _ipList.front().get();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Registry::addImageProcessor(ImageProcessor* ip)
|
||||
{
|
||||
if (ip==0L) return;
|
||||
|
||||
OSG_NOTIFY(NOTICE) << "osg::Registry::addImageProcessor("<<ip->className()<<")"<< std::endl;
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
|
||||
|
||||
_ipList.push_back(ip);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Registry::removeImageProcessor(ImageProcessor* ip)
|
||||
{
|
||||
if (ip==0L) return;
|
||||
|
||||
OSG_NOTIFY(NOTICE) << "osg::Registry::removeImageProcessor();"<< std::endl;
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::ReentrantMutex> lock(_pluginMutex);
|
||||
|
||||
ImageProcessorList::iterator ipitr = std::find(_ipList.begin(),_ipList.end(),ip);
|
||||
if (ipitr!=_ipList.end())
|
||||
{
|
||||
_ipList.erase(ipitr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Registry::addFileExtensionAlias(const std::string mapExt, const std::string toExt)
|
||||
{
|
||||
|
@ -215,6 +215,9 @@ IF(QTKIT_FOUND)
|
||||
ADD_SUBDIRECTORY(QTKit)
|
||||
ENDIF()
|
||||
|
||||
IF(NVTT_FOUND)
|
||||
ADD_SUBDIRECTORY(nvtt)
|
||||
ENDIF()
|
||||
|
||||
|
||||
IF(FREETYPE_FOUND)
|
||||
|
11
src/osgPlugins/nvtt/CMakeLists.txt
Normal file
11
src/osgPlugins/nvtt/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
INCLUDE_DIRECTORIES( ${NVTT_INCLUDE_DIR} )
|
||||
|
||||
|
||||
SET(TARGET_SRC
|
||||
NVTTImageProcessor.cpp
|
||||
)
|
||||
|
||||
SET(TARGET_LIBRARIES_VARS NVTT_LIBRARY)
|
||||
|
||||
#### end var setup ###
|
||||
SETUP_PLUGIN(nvtt)
|
329
src/osgPlugins/nvtt/NVTTImageProcessor.cpp
Normal file
329
src/osgPlugins/nvtt/NVTTImageProcessor.cpp
Normal file
@ -0,0 +1,329 @@
|
||||
|
||||
#include <osg/Texture>
|
||||
#include <osgDB/Registry>
|
||||
|
||||
#include <nvtt/nvtt.h>
|
||||
#include <string.h>
|
||||
|
||||
class NVTTProcessor : public osgDB::ImageProcessor
|
||||
{
|
||||
public:
|
||||
virtual void compress(osg::Image& image, osg::Texture::InternalFormatMode compressedFormat, bool generateMipMap, bool resizeToPowerOfTwo, CompressionMethod method, CompressionQuality quality);
|
||||
virtual void generateMipMap(osg::Image& image, bool resizeToPowerOfTwo, CompressionMethod method);
|
||||
|
||||
protected:
|
||||
|
||||
void process( osg::Image& texture, nvtt::Format format, bool generateMipMap, bool resizeToPowerOfTwo, CompressionMethod method, CompressionQuality quality);
|
||||
|
||||
struct VPBErrorHandler : public nvtt::ErrorHandler
|
||||
{
|
||||
virtual void error(nvtt::Error e);
|
||||
};
|
||||
|
||||
struct OSGImageOutputHandler : public nvtt::OutputHandler
|
||||
{
|
||||
typedef std::vector<unsigned char> MipMapData;
|
||||
|
||||
std::vector<MipMapData*> _mipmaps;
|
||||
int _width;
|
||||
int _height;
|
||||
int _currentMipLevel;
|
||||
int _currentNumberOfWritenBytes;
|
||||
nvtt::Format _format;
|
||||
bool _discardAlpha;
|
||||
|
||||
OSGImageOutputHandler(nvtt::Format format, bool discardAlpha);
|
||||
virtual ~OSGImageOutputHandler();
|
||||
|
||||
// create the osg image from the given format
|
||||
bool assignImage(osg::Image& image);
|
||||
|
||||
/// Indicate the start of a new compressed image that's part of the final texture.
|
||||
virtual void beginImage(int size, int width, int height, int depth, int face, int miplevel);
|
||||
|
||||
/// Output data. Compressed data is output as soon as it's generated to minimize memory allocations.
|
||||
virtual bool writeData(const void * data, int size);
|
||||
};
|
||||
|
||||
// Convert RGBA to BGRA : nvtt only accepts BGRA pixel format
|
||||
void convertRGBAToBGRA( std::vector<unsigned char>& outputData, const unsigned char* inputData );
|
||||
|
||||
// Convert RGB to BGRA : nvtt only accepts BGRA pixel format
|
||||
void convertRGBToBGRA( std::vector<unsigned char>& outputData, const unsigned char* inputData );
|
||||
|
||||
};
|
||||
|
||||
/// Error handler.
|
||||
void NVTTProcessor::VPBErrorHandler::error(nvtt::Error e)
|
||||
{
|
||||
switch (e)
|
||||
{
|
||||
case nvtt::Error_Unknown:
|
||||
OSG_WARN<<" NVTT : unknown error"<<std::endl;
|
||||
break;
|
||||
case nvtt::Error_InvalidInput:
|
||||
OSG_WARN<<" NVTT : invalid input"<<std::endl;
|
||||
break;
|
||||
case nvtt::Error_UnsupportedFeature:
|
||||
OSG_WARN<<" NVTT : unsupported feature"<<std::endl;
|
||||
break;
|
||||
case nvtt::Error_CudaError:
|
||||
OSG_WARN<<" NVTT : cuda error"<<std::endl;
|
||||
break;
|
||||
case nvtt::Error_FileOpen:
|
||||
OSG_WARN<<" NVTT : file open error"<<std::endl;
|
||||
break;
|
||||
case nvtt::Error_FileWrite:
|
||||
OSG_WARN<<" NVTT : file write error"<<std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Output handler.
|
||||
NVTTProcessor::OSGImageOutputHandler::OSGImageOutputHandler(nvtt::Format format, bool discardAlpha)
|
||||
: _format(format), _discardAlpha(discardAlpha)
|
||||
{
|
||||
}
|
||||
|
||||
NVTTProcessor::OSGImageOutputHandler::~OSGImageOutputHandler()
|
||||
{
|
||||
for (unsigned int n=0; n<_mipmaps.size(); n++)
|
||||
{
|
||||
delete _mipmaps[n];
|
||||
}
|
||||
_mipmaps.clear();
|
||||
}
|
||||
|
||||
// create the osg image from the given format
|
||||
bool NVTTProcessor::OSGImageOutputHandler::assignImage(osg::Image& image)
|
||||
{
|
||||
// convert nvtt format to OpenGL pixel format
|
||||
GLint pixelFormat;
|
||||
switch (_format)
|
||||
{
|
||||
case nvtt::Format_RGBA:
|
||||
pixelFormat = _discardAlpha ? GL_RGB : GL_RGBA;
|
||||
break;
|
||||
case nvtt::Format_DXT1:
|
||||
pixelFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
|
||||
break;
|
||||
case nvtt::Format_DXT1a:
|
||||
pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||
break;
|
||||
case nvtt::Format_DXT3:
|
||||
pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||
break;
|
||||
case nvtt::Format_DXT5:
|
||||
pixelFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
break;
|
||||
default:
|
||||
OSG_WARN<<" Invalid or not supported format"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute the total size and the mipmap offsets
|
||||
osg::Image::MipmapDataType mipmapOffsets(_mipmaps.size()-1);
|
||||
unsigned int totalSize = _mipmaps[0]->size();
|
||||
for (unsigned int n=1; n<_mipmaps.size(); n++)
|
||||
{
|
||||
mipmapOffsets[n-1] = totalSize;
|
||||
totalSize += _mipmaps[n]->size();
|
||||
}
|
||||
|
||||
// Allocate data and copy it
|
||||
unsigned char* data = new unsigned char[ totalSize ];
|
||||
unsigned char* ptr = data;
|
||||
for (unsigned int n=0; n<_mipmaps.size(); n++)
|
||||
{
|
||||
memcpy( ptr, &(*_mipmaps[n])[0], _mipmaps[n]->size() );
|
||||
ptr += _mipmaps[n]->size();
|
||||
}
|
||||
|
||||
image.setImage(_width,_height,1,pixelFormat,pixelFormat,GL_UNSIGNED_BYTE,data,osg::Image::USE_NEW_DELETE);
|
||||
image.setMipmapLevels(mipmapOffsets);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Indicate the start of a new compressed image that's part of the final texture.
|
||||
void NVTTProcessor::OSGImageOutputHandler::beginImage(int size, int width, int height, int depth, int face, int miplevel)
|
||||
{
|
||||
// store the new width/height of the texture
|
||||
if (miplevel == 0)
|
||||
{
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
// prepare to receive mipmap data
|
||||
if (miplevel >= static_cast<int>(_mipmaps.size()))
|
||||
{
|
||||
_mipmaps.resize(miplevel+1);
|
||||
}
|
||||
_mipmaps[miplevel] = new MipMapData(size);
|
||||
_currentMipLevel = miplevel;
|
||||
_currentNumberOfWritenBytes = 0;
|
||||
}
|
||||
|
||||
/// Output data. Compressed data is output as soon as it's generated to minimize memory allocations.
|
||||
bool NVTTProcessor::OSGImageOutputHandler::writeData(const void * data, int size)
|
||||
{
|
||||
// Copy mipmap data
|
||||
std::vector<unsigned char>& dstData = *_mipmaps[_currentMipLevel];
|
||||
memcpy( &dstData[_currentNumberOfWritenBytes], data, size );
|
||||
_currentNumberOfWritenBytes += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Convert RGBA to BGRA : nvtt only accepts BGRA pixel format
|
||||
void NVTTProcessor::convertRGBAToBGRA( std::vector<unsigned char>& outputData, const unsigned char* inputData )
|
||||
{
|
||||
for (unsigned n=0; n<outputData.size(); n += 4)
|
||||
{
|
||||
outputData[n] = inputData[n+2];
|
||||
outputData[n+1] = inputData[n+1];
|
||||
outputData[n+2] = inputData[n];
|
||||
outputData[n+3] = inputData[n+3];
|
||||
}
|
||||
}
|
||||
|
||||
// Convert RGB to BGRA : nvtt only accepts BGRA pixel format
|
||||
void NVTTProcessor::convertRGBToBGRA( std::vector<unsigned char>& outputData, const unsigned char* inputData )
|
||||
{
|
||||
unsigned int numberOfPixels = outputData.size()/4;
|
||||
for (unsigned n=0; n<numberOfPixels; n++)
|
||||
{
|
||||
outputData[4*n] = inputData[3*n+2];
|
||||
outputData[4*n+1] = inputData[3*n+1];
|
||||
outputData[4*n+2] = inputData[3*n];
|
||||
outputData[4*n+3] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
// Main interface with NVTT
|
||||
void NVTTProcessor::process( osg::Image& image, nvtt::Format format, bool generateMipMap, bool resizeToPowerOfTwo, CompressionMethod method, CompressionQuality quality)
|
||||
{
|
||||
// Fill input options
|
||||
nvtt::InputOptions inputOptions;
|
||||
inputOptions.setTextureLayout(nvtt::TextureType_2D, image.s(), image.t() );
|
||||
inputOptions.setNormalMap(false);
|
||||
inputOptions.setConvertToNormalMap(false);
|
||||
inputOptions.setGamma(2.2f, 2.2f);
|
||||
inputOptions.setNormalizeMipmaps(false);
|
||||
inputOptions.setWrapMode(nvtt::WrapMode_Clamp);
|
||||
if (resizeToPowerOfTwo)
|
||||
{
|
||||
inputOptions.setRoundMode(nvtt::RoundMode_ToNearestPowerOfTwo);
|
||||
}
|
||||
inputOptions.setMipmapGeneration(generateMipMap);
|
||||
|
||||
if (image.getPixelFormat() == GL_RGBA)
|
||||
{
|
||||
inputOptions.setAlphaMode( nvtt::AlphaMode_Transparency );
|
||||
}
|
||||
else
|
||||
{
|
||||
inputOptions.setAlphaMode( nvtt::AlphaMode_None );
|
||||
}
|
||||
std::vector<unsigned char> imageData( image.s() * image.t() * 4 );
|
||||
if (image.getPixelFormat() == GL_RGB)
|
||||
{
|
||||
convertRGBToBGRA( imageData, image.data() );
|
||||
}
|
||||
else
|
||||
{
|
||||
convertRGBAToBGRA( imageData, image.data() );
|
||||
}
|
||||
inputOptions.setMipmapData(&imageData[0],image.s(),image.t());
|
||||
|
||||
// Fill compression options
|
||||
nvtt::CompressionOptions compressionOptions;
|
||||
switch(quality)
|
||||
{
|
||||
case FASTEST:
|
||||
compressionOptions.setQuality( nvtt::Quality_Fastest );
|
||||
break;
|
||||
case NORMAL:
|
||||
compressionOptions.setQuality( nvtt::Quality_Normal );
|
||||
break;
|
||||
case PRODUCTION:
|
||||
compressionOptions.setQuality( nvtt::Quality_Production);
|
||||
break;
|
||||
case HIGHEST:
|
||||
compressionOptions.setQuality( nvtt::Quality_Highest);
|
||||
break;
|
||||
}
|
||||
compressionOptions.setFormat( format );
|
||||
//compressionOptions.setQuantization(false,false,false);
|
||||
if (format == nvtt::Format_RGBA)
|
||||
{
|
||||
if (image.getPixelFormat() == GL_RGB)
|
||||
{
|
||||
compressionOptions.setPixelFormat(24,0xff,0xff00,0xff0000,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
compressionOptions.setPixelFormat(32,0xff,0xff00,0xff0000,0xff000000);
|
||||
}
|
||||
}
|
||||
|
||||
// Handler
|
||||
OSGImageOutputHandler outputHandler(format,image.getPixelFormat() == GL_RGB);
|
||||
VPBErrorHandler errorHandler;
|
||||
|
||||
// Fill output options
|
||||
nvtt::OutputOptions outputOptions;
|
||||
outputOptions.setOutputHandler(&outputHandler);
|
||||
outputOptions.setErrorHandler(&errorHandler);
|
||||
outputOptions.setOutputHeader(false);
|
||||
|
||||
// Process the compression now
|
||||
nvtt::Compressor compressor;
|
||||
if(method == USE_GPU)
|
||||
{
|
||||
compressor.enableCudaAcceleration(true);
|
||||
if(!compressor.isCudaAccelerationEnabled())
|
||||
{
|
||||
OSG_WARN<< "CUDA acceleration was enabled but it is not available. CPU will be used."<<std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
compressor.enableCudaAcceleration(false);
|
||||
}
|
||||
|
||||
compressor.process(inputOptions,compressionOptions,outputOptions);
|
||||
|
||||
outputHandler.assignImage(image);
|
||||
}
|
||||
|
||||
void NVTTProcessor::compress(osg::Image& image, osg::Texture::InternalFormatMode compressedFormat, bool generateMipMap, bool resizeToPowerOfTwo, CompressionMethod method, CompressionQuality quality)
|
||||
{
|
||||
nvtt::Format format;
|
||||
switch (compressedFormat)
|
||||
{
|
||||
case osg::Texture::USE_S3TC_DXT1_COMPRESSION:
|
||||
if (image.getPixelFormat() == GL_RGBA)
|
||||
format = nvtt::Format_DXT1a;
|
||||
else
|
||||
format = nvtt::Format_DXT1;
|
||||
break;
|
||||
case osg::Texture::USE_S3TC_DXT3_COMPRESSION:
|
||||
format = nvtt::Format_DXT3;
|
||||
break;
|
||||
case osg::Texture::USE_S3TC_DXT5_COMPRESSION:
|
||||
format = nvtt::Format_DXT5;
|
||||
break;
|
||||
default:
|
||||
OSG_WARN<<" Invalid or not supported compress format"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
process( image, format, generateMipMap, resizeToPowerOfTwo, method, quality );
|
||||
}
|
||||
|
||||
void NVTTProcessor::generateMipMap(osg::Image& image, bool resizeToPowerOfTwo, CompressionMethod method)
|
||||
{
|
||||
process( image, nvtt::Format_RGBA, true, resizeToPowerOfTwo, method, NORMAL);
|
||||
}
|
||||
|
||||
REGISTER_OSGIMAGEPROCESSOR(nvtt, NVTTProcessor)
|
Loading…
Reference in New Issue
Block a user