static void faceTwiddling(int face, TextureHostSharedPtr const& texImage) { if ( face == 0 || face == 1 || face == 4 || face == 5 ) // px, nx, pz, nz { texImage->mirrorY(face); } else { texImage->mirrorX(face); } }
bool ILTexSaver::save( const TextureHostSharedPtr & image, const string & fileName ) { DP_ASSERT(image); // set locale temporarily to standard "C" locale dp::util::Locale tl("C"); bool isCube; unsigned int imageID; ilGenImages( 1, (ILuint *) &imageID ); ilBindImage( imageID ); string ext = dp::util::getFileExtension( fileName ); bool isDDS = !_stricmp(".DDS", ext.c_str()); // .dds needs special handling if ( isDDS ) { // DirectDraw Surfaces have their origin at upper left ilEnable( IL_ORIGIN_SET ); ilOriginFunc( IL_ORIGIN_UPPER_LEFT ); } else { ilDisable( IL_ORIGIN_SET ); } // DevIL does not know how to handle .jps and .pns. Since those formats are just renamed .jpgs and .pngs // pass over filename.(jps|pns).(jpg|png) and rename the file after saving it. // FIXME Sent bug report to DevIL. Remove this once jps/pns is added to DevIL. bool isStereoFormat = false; std::string devilFilename = fileName; if (!_stricmp(".JPS", ext.c_str())) { isStereoFormat = true; devilFilename += ".JPG"; } else if (!_stricmp(".PNS", ext.c_str())) { isStereoFormat = true; devilFilename += ".PNG"; } unsigned int numImages = image->getNumberOfImages(); isCube = image->isCubeMap(); unsigned char * pixels = NULL; // we only handle these cases properly DP_ASSERT(isCube == (numImages==6)); DP_ASSERT(!isCube == (numImages==1)); for ( unsigned int i = 0; i < numImages; ++i ) { // for DDS cube maps we need to juggle with the faces // to get them into the right order for DDS formats int face = determineImage( i, isDDS, isCube ); ilBindImage(imageID); ilActiveImage(0); ilActiveFace(face); DP_ASSERT(IL_NO_ERROR == ilGetError()); // TODO: Do not know how to handle paletted! This information is already destroyed // // pixel format // unsigned int format = ilGetInteger(IL_IMAGE_FORMAT); // if ( IL_COLOR_INDEX == format ) // { // // convert color index to whatever the base type of the palette is // if ( !ilConvertImage(ilGetInteger(IL_PALETTE_BASE_TYPE), IL_UNSIGNED_BYTE) ) // { // DP_TRACE_OUT("ERROR: conversion from color index format failed!\n"); // INVOKE_CALLBACK(onInvalidFile(fileName, "DevIL Loadable Color-Indexed Image")); // goto ERROREXIT; // } // // now query format of the converted image // format = ilGetInteger(IL_IMAGE_FORMAT); // } // // Determine the Pixel Format and type ILenum ilFormat = determineILFormat(image->getFormat()); ILenum ilType = determineILType(image->getType()); // Retrieve the image dimensions unsigned int width = image->getWidth(i); unsigned int height = image->getHeight(i); unsigned int depth = image->getDepth(i); // If assertion fires, something is wrong DP_ASSERT( (width > 0) && (height > 0) && (depth > 0) ); // again some twiddling for DDS format necessary prior to // specify the IL image if ( isDDS && isCube ) { faceTwiddling( face, image ); } // temporary cache to retrieve SceniX' TextureHost pixels pixels = new unsigned char[image->getNumberOfBytes()]; // specify the IL image image->getSubImagePixels(i, 0, 0, 0, 0, width, height, depth, pixels); ilTexImage( width, height, depth, dp::sg::core::numberOfComponents( image->getFormat() ), ilFormat, ilType, NULL ); void* destpixels = ilGetData(); memcpy(destpixels, pixels, image->getNumberOfBytes()); // done with the temporary pixel cache delete[] pixels; DP_ASSERT(IL_NO_ERROR == ilGetError()); // undo the face twiddling from before if ( isDDS && isCube ) { faceTwiddling( face, image ); } } // By default, always overwrite ilEnable(IL_FILE_OVERWRITE); if ( ilSaveImage( (const ILstring)devilFilename.c_str() ) ) { // For stereo formats rename the file to the original filename if (isStereoFormat) { // Windows will not rename a file if the destination filename already does exist. remove( fileName.c_str() ); rename( devilFilename.c_str(), fileName.c_str() ); } ilDeleteImages(1, &imageID); DP_ASSERT(IL_NO_ERROR == ilGetError()); return true; } else { #if 0 DP_TRACE_OUT("ERROR: save image failed!\n"); #endif // clean up errors while( ilGetError() != IL_NO_ERROR ) {} // report that an error has occured INVOKE_CALLBACK( onInvalidFile( fileName, "saving image file failed!") ); } // free all resources associated with the DevIL image ilDeleteImages(1, &imageID); return false; }
const ParameterGroupDataSharedPtr & StackedAtlasManager::submitTexture( const std::string & file , const std::string & attrString , int & layer ) { // // see if we have seen this texture before // std::map< std::string, std::pair<std::string,int> >::iterator fiter = m_cachedFiles.find( file ); if ( fiter != m_cachedFiles.end() ) { // it is in the list, return the right atlas std::map< std::string, StackedAtlas * >::iterator saiter = m_atlases.find( (*fiter).second.first ); layer = (*fiter).second.second; return (*saiter).second->getTexture(); } // we have not seen this one before, go looking for the file static ParameterGroupDataSharedPtr nullTexture; TextureHostSharedPtr tex = dp::sg::io::loadTextureHost( file, m_searchPaths ); if( tex ) { std::stringstream ss; bool forceMipmaps = false; if( m_rescale ) { // rescale to width, height if( m_width != tex->getWidth() || m_height != tex->getHeight() ) { tex->scale( 0, m_width, m_height, 1 ); forceMipmaps = true; } } // we create mipmaps if there were none if( m_createMipmaps || forceMipmaps ) { if( forceMipmaps || tex->getNumberOfMipmaps() < 1 ) { tex->createMipmaps(); } } // convert everything to bgra - more efficient for the hardware // anyway. tex->convertPixelFormat( Image::IMG_BGRA ); // concatenate width, height and attribute string ss << tex->getWidth() << "x" << tex->getHeight() << attrString << "-" << numberOfComponents( tex->getFormat() ); // see if we already have a stack like this std::map< std::string, StackedAtlas * >::iterator saiter = m_atlases.find( ss.str() ); StackedAtlas * atlas = 0; if( saiter != m_atlases.end() && (*saiter).second->getCount() < m_maxSlices ) { atlas = (*saiter).second; } else { // we either don't have one like this, or it is full, make a new one atlas = new StackedAtlas( tex->getWidth(), tex->getHeight() ); // add to list m_atlases[ ss.str() ] = atlas; } const ParameterGroupDataSharedPtr & texture = atlas->addTexture( tex, layer ); if ( texture ) { // mark it as being cached m_cachedFiles[ file ] = std::make_pair(ss.str(),layer); return( texture ); } else { return( nullTexture ); } } else { // unable to find file... return( nullTexture ); } }
void ParameterGroupData::initData( const dp::fx::ParameterGroupDataSharedPtr & data ) { // fill the data area with the defaults from the spec for ( ParameterGroupSpec::iterator it = m_parameterGroupSpec->beginParameterSpecs() ; it != m_parameterGroupSpec->endParameterSpecs() ; ++it ) { // If the parameter is a sampler it needs to be initialized. // For GLSL to silence the OpenGL driver debug output warning that a sampler is not assigned. // Both the undefined and the default filename initialization should be done via some scene graph global texture cache. if ( ( it->first.getType() & PT_POINTER_TYPE_MASK ) == PT_SAMPLER_PTR ) { if ( it->first.getDefaultValue() ) { // If a sampler has a default value it must be a texture image filename. const char * name = static_cast<const char *>( data->getParameter( it ) ); TextureFileSharedPtr texture = TextureFile::create( name, textureTypeToTarget( it->first.getType() ) ); DP_ASSERT( texture ); if ( texture ) { texture->incrementMipmapUseCount(); SamplerSharedPtr sampler = Sampler::create( texture ); std::string extension = dp::util::getFileExtension( name ); boost::algorithm::to_lower(extension); if ( extension == ".mbsdf" ) { sampler->setName( it->first.getName() ); sampler->setMagFilterMode( TFM_MAG_NEAREST ); sampler->setMinFilterMode( TFM_MIN_NEAREST ); sampler->setWrapModes( TWM_CLAMP_TO_EDGE, TWM_CLAMP_TO_EDGE, TWM_CLAMP_TO_EDGE ); } else { sampler->setName( it->first.getName() ); sampler->setMagFilterMode( TFM_MAG_LINEAR ); sampler->setMinFilterMode( TFM_MIN_LINEAR_MIPMAP_LINEAR ); } setParameter( it, sampler ); } } else { // If the sampler has no default initialization, find out their type and assign a matching default texture. // DAR FIXME Support for "sampler" in standardMaterialEffect standardTextureParameters for now. // 2x2 RGBA8 red, green, blue, yellow default texture. static const unsigned char texel[] = { 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF }; TextureHostSharedPtr textureHost = TextureHost::create(); DP_ASSERT( textureHost ); textureHost->setCreationFlags( TextureHost::F_PRESERVE_IMAGE_DATA_AFTER_UPLOAD ); unsigned int index = textureHost->addImage( 2, 2, 1, Image::IMG_RGBA, Image::IMG_UNSIGNED_BYTE ); DP_ASSERT( index != -1 ); textureHost->setImageData( index, (const void *) &texel[0] ); textureHost->setTextureTarget( TT_TEXTURE_2D ); SamplerSharedPtr sampler = Sampler::create( textureHost ); DP_ASSERT( sampler ); sampler->setName( "default_sampler2D" ); sampler->setMagFilterMode( TFM_MAG_NEAREST ); sampler->setMinFilterMode( TFM_MIN_NEAREST ); setParameter( it, sampler ); } } else { // No other pointer types than samplers are supported inside the EffectLibrary so far. DP_ASSERT( ( it->first.getType() & PT_POINTER_TYPE_MASK ) == 0 ); if ( it->first.getDefaultValue() ) { setParameter( it, data->getParameter( it ) ); } } } }