CefRefPtr<CefResourceHandler> VTFSchemeHandlerFactory::Create(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& scheme_name, CefRefPtr<CefRequest> request) { CefRefPtr<CefResourceHandler> pResourceHandler = NULL; CefURLParts parts; CefParseURL(request->GetURL(), parts); std::string strVtfPath = CefString(&parts.path); char vtfPath[MAX_PATH]; V_snprintf( vtfPath, sizeof( vtfPath ), "materials/%s", strVtfPath.c_str() ); V_FixupPathName( vtfPath, sizeof( vtfPath ), vtfPath ); if (!filesystem->FileExists(vtfPath)) { Warning( "VTFSchemeHandlerFactory: invalid vtf %s\n", vtfPath ); return NULL; } CUtlBuffer imageDataBuffer( 0, filesystem->Size(vtfPath), 0 ); if( !filesystem->ReadFile( vtfPath, NULL, imageDataBuffer ) ) { Warning( "VTFSchemeHandlerFactory: failed to read vtf %s\n", vtfPath ); return NULL; } IVTFTexture *pVTFTexture = CreateVTFTexture(); if( pVTFTexture->Unserialize( imageDataBuffer ) ) { pVTFTexture->ConvertImageFormat( IMAGE_FORMAT_RGB888, false, false ); if( pVTFTexture->Format() == IMAGE_FORMAT_RGB888 ) { uint8 *pImageData = pVTFTexture->ImageData(); CUtlBuffer buf; VTFHandler_ConvertImageToJPG( buf, pImageData, pVTFTexture->Width(), pVTFTexture->Height() ); if( buf.Size() > 0 ) { CefRefPtr<CefStreamReader> stream = CefStreamReader::CreateForData(static_cast<void*>(buf.Base()), buf.Size()); pResourceHandler = new CefStreamResourceHandler("image/jpeg", stream); } } else { Warning( "VTFSchemeHandlerFactory: unable to convert vtf %s to rgb format\n", vtfPath ); } } DestroyVTFTexture( pVTFTexture ); return pResourceHandler; }
CMacroTextureData* LoadMacroTextureFile( const char *pFilename ) { FileHandle_t hFile = g_pFileSystem->Open( pFilename, "rb" ); if ( hFile == FILESYSTEM_INVALID_HANDLE ) return NULL; // Read the file in. CUtlVector<char> tempData; tempData.SetSize( g_pFileSystem->Size( hFile ) ); g_pFileSystem->Read( tempData.Base(), tempData.Count(), hFile ); g_pFileSystem->Close( hFile ); // Now feed the data into a CUtlBuffer (great...) CUtlBuffer buf; buf.Put( tempData.Base(), tempData.Count() ); // Now make a texture out of it. IVTFTexture *pTex = CreateVTFTexture(); if ( !pTex->Unserialize( buf ) ) Error( "IVTFTexture::Unserialize( %s ) failed.", pFilename ); pTex->ConvertImageFormat( IMAGE_FORMAT_RGBA8888, false ); // Get it in a format we like. // Now convert to a CMacroTextureData. CMacroTextureData *pData = new CMacroTextureData; pData->m_Width = pTex->Width(); pData->m_Height = pTex->Height(); pData->m_ImageData.EnsureCapacity( pData->m_Width * pData->m_Height * 4 ); memcpy( pData->m_ImageData.Base(), pTex->ImageData(), pData->m_Width * pData->m_Height * 4 ); DestroyVTFTexture( pTex ); Msg( "-- LoadMacroTextureFile: %s\n", pFilename ); return pData; }
void CViewRender::WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height, bool bCreatePowerOf2Padded/*=false*/, bool bWriteVTF/*=false*/ ) { #ifndef _X360 CMatRenderContextPtr pRenderContext( materials ); pRenderContext->MatrixMode( MATERIAL_PROJECTION ); pRenderContext->PushMatrix(); pRenderContext->MatrixMode( MATERIAL_VIEW ); pRenderContext->PushMatrix(); g_bRenderingScreenshot = true; // Push back buffer on the stack with small viewport pRenderContext->PushRenderTargetAndViewport( NULL, 0, 0, width, height ); // render out to the backbuffer CViewSetup viewSetup = GetView ( STEREO_EYE_MONO ); viewSetup.x = 0; viewSetup.y = 0; viewSetup.width = width; viewSetup.height = height; viewSetup.fov = ScaleFOVByWidthRatio( viewSetup.fov, ( (float)width / (float)height ) / ( 4.0f / 3.0f ) ); viewSetup.m_bRenderToSubrectOfLargerScreen = true; // draw out the scene // Don't draw the HUD or the viewmodel RenderView( viewSetup, VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR, 0 ); // get the data from the backbuffer and save to disk // bitmap bits unsigned char *pImage = ( unsigned char * )malloc( width * height * 3 ); // Get Bits from the material system pRenderContext->ReadPixels( 0, 0, width, height, pImage, IMAGE_FORMAT_RGB888 ); // Some stuff to be setup dependent on padded vs. not padded int nSrcWidth, nSrcHeight; unsigned char *pSrcImage; // Create a padded version if necessary unsigned char *pPaddedImage = NULL; if ( bCreatePowerOf2Padded ) { // Setup dimensions as needed int nPaddedWidth = SmallestPowerOfTwoGreaterOrEqual( width ); int nPaddedHeight = SmallestPowerOfTwoGreaterOrEqual( height ); // Allocate int nPaddedImageSize = nPaddedWidth * nPaddedHeight * 3; pPaddedImage = ( unsigned char * )malloc( nPaddedImageSize ); // Zero out the entire thing V_memset( pPaddedImage, 255, nPaddedImageSize ); // Copy over each row individually for ( int nRow = 0; nRow < height; ++nRow ) { unsigned char *pDst = pPaddedImage + 3 * ( nRow * nPaddedWidth ); const unsigned char *pSrc = pImage + 3 * ( nRow * width ); V_memcpy( pDst, pSrc, 3 * width ); } // Setup source data nSrcWidth = nPaddedWidth; nSrcHeight = nPaddedHeight; pSrcImage = pPaddedImage; } else { // Use non-padded info nSrcWidth = width; nSrcHeight = height; pSrcImage = pImage; } // allocate a buffer to write the tga into CUtlBuffer buffer; bool bWriteResult; if ( bWriteVTF ) { // Create and initialize a VTF texture IVTFTexture *pVTFTexture = CreateVTFTexture(); const int nFlags = TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_SRGB; if ( pVTFTexture->Init( nSrcWidth, nSrcHeight, 1, IMAGE_FORMAT_RGB888, nFlags, 1, 1 ) ) { // Copy the image data over to the VTF unsigned char *pDestBits = pVTFTexture->ImageData(); int nDstSize = nSrcWidth * nSrcHeight * 3; V_memcpy( pDestBits, pSrcImage, nDstSize ); // Allocate output buffer int iMaxVTFSize = 1024 + ( nSrcWidth * nSrcHeight * 3 ); void *pVTF = malloc( iMaxVTFSize ); buffer.SetExternalBuffer( pVTF, iMaxVTFSize, 0 ); // Serialize to the buffer bWriteResult = pVTFTexture->Serialize( buffer ); // Free the VTF texture DestroyVTFTexture( pVTFTexture ); } else { bWriteResult = false; } } else { // Write TGA format to buffer int iMaxTGASize = 1024 + ( nSrcWidth * nSrcHeight * 4 ); void *pTGA = malloc( iMaxTGASize ); buffer.SetExternalBuffer( pTGA, iMaxTGASize, 0 ); bWriteResult = TGAWriter::WriteToBuffer( pSrcImage, buffer, nSrcWidth, nSrcHeight, IMAGE_FORMAT_RGB888, IMAGE_FORMAT_RGB888 ); } if ( !bWriteResult ) { Error( "Couldn't write bitmap data snapshot.\n" ); } free( pImage ); free( pPaddedImage ); // async write to disk (this will take ownership of the memory) char szPathedFileName[_MAX_PATH]; Q_snprintf( szPathedFileName, sizeof(szPathedFileName), "//MOD/%s", pFilename ); filesystem->AsyncWrite( szPathedFileName, buffer.Base(), buffer.TellPut(), true ); // restore our previous state pRenderContext->PopRenderTargetAndViewport(); pRenderContext->MatrixMode( MATERIAL_PROJECTION ); pRenderContext->PopMatrix(); pRenderContext->MatrixMode( MATERIAL_VIEW ); pRenderContext->PopMatrix(); g_bRenderingScreenshot = false; #endif }
void CreateDefaultCubemaps( bool bHDR ) { memset( g_IsCubemapTexData, 0, sizeof(g_IsCubemapTexData) ); // NOTE: This implementation depends on the fact that all VTF files contain // all mipmap levels const char *pSkyboxBaseName = FindSkyboxMaterialName(); char skyboxMaterialName[MAX_PATH]; Q_snprintf( skyboxMaterialName, MAX_PATH, "skybox/%s", pSkyboxBaseName ); IVTFTexture *pSrcVTFTextures[6]; if( !skyboxMaterialName ) { if( s_DefaultCubemapNames.Count() ) { Warning( "This map uses env_cubemap, and you don't have a skybox, so no default env_cubemaps will be generated.\n" ); } return; } int unionTextureFlags = 0; if( !LoadSrcVTFFiles( pSrcVTFTextures, skyboxMaterialName, &unionTextureFlags, bHDR ) ) { Warning( "Can't load skybox file %s to build the default cubemap!\n", skyboxMaterialName ); return; } Msg( "Creating default %scubemaps for env_cubemap using skybox materials:\n%s*.vmt\n" "Run buildcubemaps in the engine to get the correct cube maps.\n\n", bHDR ? "HDR " : "", skyboxMaterialName ); // Figure out the mip differences between the two textures int iMipLevelOffset = 0; int tmp = pSrcVTFTextures[0]->Width(); while( tmp > DEFAULT_CUBEMAP_SIZE ) { iMipLevelOffset++; tmp >>= 1; } // Create the destination cubemap IVTFTexture *pDstCubemap = CreateVTFTexture(); pDstCubemap->Init( DEFAULT_CUBEMAP_SIZE, DEFAULT_CUBEMAP_SIZE, 1, pSrcVTFTextures[0]->Format(), unionTextureFlags | TEXTUREFLAGS_ENVMAP, pSrcVTFTextures[0]->FrameCount() ); // First iterate over all frames for (int iFrame = 0; iFrame < pDstCubemap->FrameCount(); ++iFrame) { // Next iterate over all normal cube faces (we know there's 6 cause it's an envmap) for (int iFace = 0; iFace < 6; ++iFace ) { // Finally, iterate over all mip levels in the *destination* for (int iMip = 0; iMip < pDstCubemap->MipCount(); ++iMip ) { // Copy the bits from the source images into the cube faces unsigned char *pSrcBits = pSrcVTFTextures[iFace]->ImageData( iFrame, 0, iMip + iMipLevelOffset ); unsigned char *pDstBits = pDstCubemap->ImageData( iFrame, iFace, iMip ); int iSize = pDstCubemap->ComputeMipSize( iMip ); memcpy( pDstBits, pSrcBits, iSize ); } } } ImageFormat originalFormat = pDstCubemap->Format(); if( !bHDR ) { // Convert the cube to format that we can apply tools to it... pDstCubemap->ConvertImageFormat( IMAGE_FORMAT_DEFAULT, false ); } // Fixup the cubemap facing pDstCubemap->FixCubemapFaceOrientation(); // Now that the bits are in place, compute the spheremaps... pDstCubemap->GenerateSpheremap(); if( !bHDR ) { // Convert the cubemap to the final format pDstCubemap->ConvertImageFormat( originalFormat, false ); } // Write the puppy out! char dstVTFFileName[1024]; if( bHDR ) { sprintf( dstVTFFileName, "materials/maps/%s/cubemapdefault.hdr.vtf", mapbase ); } else { sprintf( dstVTFFileName, "materials/maps/%s/cubemapdefault.vtf", mapbase ); } CUtlBuffer outputBuf; if (!pDstCubemap->Serialize( outputBuf )) { Warning( "Error serializing default cubemap %s\n", dstVTFFileName ); return; } // spit out the default one. AddBufferToPack( dstVTFFileName, outputBuf.Base(), outputBuf.TellPut(), false ); // spit out all of the ones that are attached to world geometry. int i; for( i = 0; i < s_DefaultCubemapNames.Count(); i++ ) { char vtfName[MAX_PATH]; VTFNameToHDRVTFName( s_DefaultCubemapNames[i], vtfName, MAX_PATH, bHDR ); if( FileExistsInPack( vtfName ) ) { continue; } AddBufferToPack( vtfName, outputBuf.Base(),outputBuf.TellPut(), false ); } // Clean up the textures for( i = 0; i < 6; i++ ) { DestroyVTFTexture( pSrcVTFTextures[i] ); } DestroyVTFTexture( pDstCubemap ); }
int main( int argc, char **argv ) { SpewOutputFunc( VTF2TGAOutputFunc ); CommandLine()->CreateCmdLine( argc, argv ); MathLib_Init( 2.2f, 2.2f, 0.0f, 1.0f, false, false, false, false ); InitDefaultFileSystem(); const char *pVTFFileName = CommandLine()->ParmValue( "-i" ); const char *pTGAFileName = CommandLine()->ParmValue( "-o" ); bool bGenerateMipLevels = CommandLine()->CheckParm( "-mip" ) != NULL; if ( !pVTFFileName ) { Usage(); } if ( !pTGAFileName ) { pTGAFileName = pVTFFileName; } char pCurrentDirectory[MAX_PATH]; if ( _getcwd( pCurrentDirectory, sizeof(pCurrentDirectory) ) == NULL ) { fprintf( stderr, "Unable to get the current directory\n" ); return -1; } Q_StripTrailingSlash( pCurrentDirectory ); char pBuf[MAX_PATH]; if ( !Q_IsAbsolutePath( pTGAFileName ) ) { Q_snprintf( pBuf, sizeof(pBuf), "%s\\%s", pCurrentDirectory, pTGAFileName ); } else { Q_strncpy( pBuf, pTGAFileName, sizeof(pBuf) ); } Q_FixSlashes( pBuf ); char pOutFileNameBase[MAX_PATH]; Q_StripExtension( pBuf, pOutFileNameBase, MAX_PATH ); char pActualVTFFileName[MAX_PATH]; Q_strncpy( pActualVTFFileName, pVTFFileName, MAX_PATH ); if ( !Q_strstr( pActualVTFFileName, ".vtf" ) ) { Q_strcat( pActualVTFFileName, ".vtf", MAX_PATH ); } FILE *vtfFp = fopen( pActualVTFFileName, "rb" ); if( !vtfFp ) { Error( "Can't open %s\n", pActualVTFFileName ); exit( -1 ); } fseek( vtfFp, 0, SEEK_END ); int srcVTFLength = ftell( vtfFp ); fseek( vtfFp, 0, SEEK_SET ); CUtlBuffer buf; buf.EnsureCapacity( srcVTFLength ); int nBytesRead = fread( buf.Base(), 1, srcVTFLength, vtfFp ); fclose( vtfFp ); buf.SeekPut( CUtlBuffer::SEEK_HEAD, nBytesRead ); IVTFTexture *pTex = CreateVTFTexture(); if (!pTex->Unserialize( buf )) { Error( "*** Error reading in .VTF file %s\n", pActualVTFFileName ); exit(-1); } Msg( "vtf width: %d\n", pTex->Width() ); Msg( "vtf height: %d\n", pTex->Height() ); Msg( "vtf numFrames: %d\n", pTex->FrameCount() ); Msg( "TEXTUREFLAGS_POINTSAMPLE=%s\n", ( pTex->Flags() & TEXTUREFLAGS_POINTSAMPLE ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_TRILINEAR=%s\n", ( pTex->Flags() & TEXTUREFLAGS_TRILINEAR ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_CLAMPS=%s\n", ( pTex->Flags() & TEXTUREFLAGS_CLAMPS ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_CLAMPT=%s\n", ( pTex->Flags() & TEXTUREFLAGS_CLAMPT ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_CLAMPU=%s\n", ( pTex->Flags() & TEXTUREFLAGS_CLAMPU ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_BORDER=%s\n", ( pTex->Flags() & TEXTUREFLAGS_BORDER ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_ANISOTROPIC=%s\n", ( pTex->Flags() & TEXTUREFLAGS_ANISOTROPIC ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_HINT_DXT5=%s\n", ( pTex->Flags() & TEXTUREFLAGS_HINT_DXT5 ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_SRGB=%s\n", ( pTex->Flags() & TEXTUREFLAGS_SRGB ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_NORMAL=%s\n", ( pTex->Flags() & TEXTUREFLAGS_NORMAL ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_NOMIP=%s\n", ( pTex->Flags() & TEXTUREFLAGS_NOMIP ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_NOLOD=%s\n", ( pTex->Flags() & TEXTUREFLAGS_NOLOD ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_ALL_MIPS=%s\n", ( pTex->Flags() & TEXTUREFLAGS_ALL_MIPS ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_PROCEDURAL=%s\n", ( pTex->Flags() & TEXTUREFLAGS_PROCEDURAL ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_ONEBITALPHA=%s\n", ( pTex->Flags() & TEXTUREFLAGS_ONEBITALPHA ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_EIGHTBITALPHA=%s\n", ( pTex->Flags() & TEXTUREFLAGS_EIGHTBITALPHA ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_ENVMAP=%s\n", ( pTex->Flags() & TEXTUREFLAGS_ENVMAP ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_RENDERTARGET=%s\n", ( pTex->Flags() & TEXTUREFLAGS_RENDERTARGET ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_DEPTHRENDERTARGET=%s\n", ( pTex->Flags() & TEXTUREFLAGS_DEPTHRENDERTARGET ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_NODEBUGOVERRIDE=%s\n", ( pTex->Flags() & TEXTUREFLAGS_NODEBUGOVERRIDE ) ? "true" : "false" ); Msg( "TEXTUREFLAGS_SINGLECOPY=%s\n", ( pTex->Flags() & TEXTUREFLAGS_SINGLECOPY ) ? "true" : "false" ); Vector vecReflectivity = pTex->Reflectivity(); Msg( "vtf reflectivity: %f %f %f\n", vecReflectivity[0], vecReflectivity[1], vecReflectivity[2] ); Msg( "transparency: " ); if( pTex->Flags() & TEXTUREFLAGS_EIGHTBITALPHA ) { Msg( "eightbitalpha\n" ); } else if( pTex->Flags() & TEXTUREFLAGS_ONEBITALPHA ) { Msg( "onebitalpha\n" ); } else { Msg( "noalpha\n" ); } ImageFormat srcFormat = pTex->Format(); Msg( "vtf format: %s\n", ImageLoader::GetName( srcFormat ) ); int iTGANameLen = Q_strlen( pOutFileNameBase ); int iFaceCount = pTex->FaceCount(); int nFrameCount = pTex->FrameCount(); bool bIsCubeMap = pTex->IsCubeMap(); int iLastMipLevel = bGenerateMipLevels ? pTex->MipCount() - 1 : 0; for( int iFrame = 0; iFrame < nFrameCount; ++iFrame ) { for ( int iMipLevel = 0; iMipLevel <= iLastMipLevel; ++iMipLevel ) { int iWidth, iHeight, iDepth; pTex->ComputeMipLevelDimensions( iMipLevel, &iWidth, &iHeight, &iDepth ); for (int iCubeFace = 0; iCubeFace < iFaceCount; ++iCubeFace) { for ( int z = 0; z < iDepth; ++z ) { // Construct output filename char *pTempNameBuf = (char *)stackalloc( iTGANameLen + 13 ); Q_strncpy( pTempNameBuf, pOutFileNameBase, iTGANameLen + 1 ); char *pExt = Q_strrchr( pTempNameBuf, '.' ); if ( pExt ) { pExt = 0; } if ( bIsCubeMap ) { Assert( pTex->Depth() == 1 ); // shouldn't this be 1 instead of 0? static const char *pCubeFaceName[7] = { "rt", "lf", "bk", "ft", "up", "dn", "sph" }; Q_strcat( pTempNameBuf, pCubeFaceName[iCubeFace], iTGANameLen + 13 ); } if ( nFrameCount > 1 ) { char pTemp[4]; Q_snprintf( pTemp, 4, "%03d", iFrame ); Q_strcat( pTempNameBuf, pTemp, iTGANameLen + 13 ); } if ( iLastMipLevel != 0 ) { char pTemp[8]; Q_snprintf( pTemp, 8, "_mip%d", iMipLevel ); Q_strcat( pTempNameBuf, pTemp, iTGANameLen + 13 ); } if ( pTex->Depth() > 1 ) { char pTemp[6]; Q_snprintf( pTemp, 6, "_z%03d", z ); Q_strcat( pTempNameBuf, pTemp, iTGANameLen + 13 ); } if( srcFormat == IMAGE_FORMAT_RGBA16161616F ) { Q_strcat( pTempNameBuf, ".pfm", iTGANameLen + 13 ); } else { Q_strcat( pTempNameBuf, ".tga", iTGANameLen + 13 ); } unsigned char *pSrcImage = pTex->ImageData( iFrame, iCubeFace, iMipLevel, 0, 0, z ); ImageFormat dstFormat; if( srcFormat == IMAGE_FORMAT_RGBA16161616F ) { dstFormat = IMAGE_FORMAT_RGB323232F; } else { if( ImageLoader::IsTransparent( srcFormat ) || (srcFormat == IMAGE_FORMAT_ATI1N ) || (srcFormat == IMAGE_FORMAT_ATI2N )) { dstFormat = IMAGE_FORMAT_BGRA8888; } else { dstFormat = IMAGE_FORMAT_BGR888; } } // dstFormat = IMAGE_FORMAT_RGBA8888; // dstFormat = IMAGE_FORMAT_RGB888; // dstFormat = IMAGE_FORMAT_BGRA8888; // dstFormat = IMAGE_FORMAT_BGR888; // dstFormat = IMAGE_FORMAT_BGRA5551; // dstFormat = IMAGE_FORMAT_BGR565; // dstFormat = IMAGE_FORMAT_BGRA4444; // printf( "dstFormat: %s\n", ImageLoader::GetName( dstFormat ) ); unsigned char *pDstImage = new unsigned char[ImageLoader::GetMemRequired( iWidth, iHeight, 1, dstFormat, false )]; if( !ImageLoader::ConvertImageFormat( pSrcImage, srcFormat, pDstImage, dstFormat, iWidth, iHeight, 0, 0 ) ) { Error( "Error converting from %s to %s\n", ImageLoader::GetName( srcFormat ), ImageLoader::GetName( dstFormat ) ); exit( -1 ); } if( dstFormat != IMAGE_FORMAT_RGB323232F ) { if( ImageLoader::IsTransparent( dstFormat ) && ( dstFormat != IMAGE_FORMAT_RGBA8888 ) ) { unsigned char *tmpImage = pDstImage; pDstImage = new unsigned char[ImageLoader::GetMemRequired( iWidth, iHeight, 1, IMAGE_FORMAT_RGBA8888, false )]; if( !ImageLoader::ConvertImageFormat( tmpImage, dstFormat, pDstImage, IMAGE_FORMAT_RGBA8888, iWidth, iHeight, 0, 0 ) ) { Error( "Error converting from %s to %s\n", ImageLoader::GetName( dstFormat ), ImageLoader::GetName( IMAGE_FORMAT_RGBA8888 ) ); } dstFormat = IMAGE_FORMAT_RGBA8888; } else if( !ImageLoader::IsTransparent( dstFormat ) && ( dstFormat != IMAGE_FORMAT_RGB888 ) ) { unsigned char *tmpImage = pDstImage; pDstImage = new unsigned char[ImageLoader::GetMemRequired( iWidth, iHeight, 1, IMAGE_FORMAT_RGB888, false )]; if( !ImageLoader::ConvertImageFormat( tmpImage, dstFormat, pDstImage, IMAGE_FORMAT_RGB888, iWidth, iHeight, 0, 0 ) ) { Error( "Error converting from %s to %s\n", ImageLoader::GetName( dstFormat ), ImageLoader::GetName( IMAGE_FORMAT_RGB888 ) ); } dstFormat = IMAGE_FORMAT_RGB888; } CUtlBuffer outBuffer; TGAWriter::WriteToBuffer( pDstImage, outBuffer, iWidth, iHeight, dstFormat, dstFormat ); if ( !g_pFullFileSystem->WriteFile( pTempNameBuf, NULL, outBuffer ) ) { fprintf( stderr, "unable to write %s\n", pTempNameBuf ); } } else { PFMWrite( ( float * )pDstImage, pTempNameBuf, iWidth, iHeight ); } } } } } // leak leak leak leak leak, leak leak, leak leak (Blue Danube) return 0; }
void CreateDefaultCubemaps( bool bHDR ) { memset( g_IsCubemapTexData, 0, sizeof(g_IsCubemapTexData) ); // NOTE: This implementation depends on the fact that all VTF files contain // all mipmap levels const char *pSkyboxBaseName = FindSkyboxMaterialName(); char skyboxMaterialName[MAX_PATH]; Q_snprintf( skyboxMaterialName, MAX_PATH, "skybox/%s", pSkyboxBaseName ); IVTFTexture *pSrcVTFTextures[6]; if( !skyboxMaterialName ) { if( s_DefaultCubemapNames.Count() ) { Warning( "This map uses env_cubemap, and you don't have a skybox, so no default env_cubemaps will be generated.\n" ); } return; } int unionTextureFlags = 0; if( !LoadSrcVTFFiles( pSrcVTFTextures, skyboxMaterialName, &unionTextureFlags, bHDR ) ) { Warning( "Can't load skybox file %s to build the default cubemap!\n", skyboxMaterialName ); return; } Msg( "Creating default %scubemaps for env_cubemap using skybox materials:\n %s*.vmt\n" " ! Run buildcubemaps in the engine to get the correct cube maps.\n", bHDR ? "HDR " : "LDR ", skyboxMaterialName ); // Figure out the mip differences between the two textures int iMipLevelOffset = 0; int tmp = pSrcVTFTextures[0]->Width(); while( tmp > DEFAULT_CUBEMAP_SIZE ) { iMipLevelOffset++; tmp >>= 1; } // Create the destination cubemap IVTFTexture *pDstCubemap = CreateVTFTexture(); pDstCubemap->Init( DEFAULT_CUBEMAP_SIZE, DEFAULT_CUBEMAP_SIZE, 1, pSrcVTFTextures[0]->Format(), unionTextureFlags | TEXTUREFLAGS_ENVMAP, pSrcVTFTextures[0]->FrameCount() ); // First iterate over all frames for (int iFrame = 0; iFrame < pDstCubemap->FrameCount(); ++iFrame) { // Next iterate over all normal cube faces (we know there's 6 cause it's an envmap) for (int iFace = 0; iFace < 6; ++iFace ) { // Finally, iterate over all mip levels in the *destination* for (int iMip = 0; iMip < pDstCubemap->MipCount(); ++iMip ) { // Copy the bits from the source images into the cube faces unsigned char *pSrcBits = pSrcVTFTextures[iFace]->ImageData( iFrame, 0, iMip + iMipLevelOffset ); unsigned char *pDstBits = pDstCubemap->ImageData( iFrame, iFace, iMip ); int iSize = pDstCubemap->ComputeMipSize( iMip ); int iSrcMipSize = pSrcVTFTextures[iFace]->ComputeMipSize( iMip + iMipLevelOffset ); // !!! FIXME: Set this to black until HDR cubemaps are built properly! memset( pDstBits, 0, iSize ); continue; if ( ( pSrcVTFTextures[iFace]->Width() == 4 ) && ( pSrcVTFTextures[iFace]->Height() == 4 ) ) // If texture is 4x4 square { // Force mip level 2 to get the 1x1 face unsigned char *pSrcBits = pSrcVTFTextures[iFace]->ImageData( iFrame, 0, 2 ); int iSrcMipSize = pSrcVTFTextures[iFace]->ComputeMipSize( 2 ); // Replicate 1x1 mip level across entire face //memset( pDstBits, 0, iSize ); for ( int i = 0; i < ( iSize / iSrcMipSize ); i++ ) { memcpy( pDstBits + ( i * iSrcMipSize ), pSrcBits, iSrcMipSize ); } } else if ( pSrcVTFTextures[iFace]->Width() == pSrcVTFTextures[iFace]->Height() ) // If texture is square { if ( iSrcMipSize != iSize ) { Warning( "%s - ERROR! Cannot copy square face for default cubemap! iSrcMipSize(%d) != iSize(%d)\n", skyboxMaterialName, iSrcMipSize, iSize ); memset( pDstBits, 0, iSize ); } else { // Just copy the mip level memcpy( pDstBits, pSrcBits, iSize ); } } else if ( pSrcVTFTextures[iFace]->Width() == pSrcVTFTextures[iFace]->Height()*2 ) // If texture is rectangle 2x wide { int iMipWidth, iMipHeight, iMipDepth; pDstCubemap->ComputeMipLevelDimensions( iMip, &iMipWidth, &iMipHeight, &iMipDepth ); if ( ( iMipHeight > 1 ) && ( iSrcMipSize*2 != iSize ) ) { Warning( "%s - ERROR building default cube map! %d*2 != %d\n", skyboxMaterialName, iSrcMipSize, iSize ); memset( pDstBits, 0, iSize ); } else { // Copy row at a time and repeat last row memcpy( pDstBits, pSrcBits, iSize/2 ); //memcpy( pDstBits + iSize/2, pSrcBits, iSize/2 ); int nSrcRowSize = pSrcVTFTextures[iFace]->RowSizeInBytes( iMip + iMipLevelOffset ); int nDstRowSize = pDstCubemap->RowSizeInBytes( iMip ); if ( nSrcRowSize != nDstRowSize ) { Warning( "%s - ERROR building default cube map! nSrcRowSize(%d) != nDstRowSize(%d)!\n", skyboxMaterialName, nSrcRowSize, nDstRowSize ); memset( pDstBits, 0, iSize ); } else { for ( int i = 0; i < ( iSize/2 / nSrcRowSize ); i++ ) { memcpy( pDstBits + iSize/2 + i*nSrcRowSize, pSrcBits + iSrcMipSize - nSrcRowSize, nSrcRowSize ); } } } } else { // ERROR! This code only supports square and rectangluar 2x wide Warning( "%s - Couldn't create default cubemap because texture res is %dx%d\n", skyboxMaterialName, pSrcVTFTextures[iFace]->Width(), pSrcVTFTextures[iFace]->Height() ); memset( pDstBits, 0, iSize ); return; } } } } ImageFormat originalFormat = pDstCubemap->Format(); if( !bHDR ) { // Convert the cube to format that we can apply tools to it... pDstCubemap->ConvertImageFormat( IMAGE_FORMAT_DEFAULT, false ); } // Fixup the cubemap facing pDstCubemap->FixCubemapFaceOrientation(); // Now that the bits are in place, compute the spheremaps... pDstCubemap->GenerateSpheremap(); if( !bHDR ) { // Convert the cubemap to the final format pDstCubemap->ConvertImageFormat( originalFormat, false ); } // Write the puppy out! char dstVTFFileName[1024]; if( bHDR ) { sprintf( dstVTFFileName, "materials/maps/%s/cubemapdefault.hdr.vtf", mapbase ); } else { sprintf( dstVTFFileName, "materials/maps/%s/cubemapdefault.vtf", mapbase ); } CUtlBuffer outputBuf; if (!pDstCubemap->Serialize( outputBuf )) { Warning( "Error serializing default cubemap %s\n", dstVTFFileName ); return; } IZip *pak = GetPakFile(); // spit out the default one. AddBufferToPak( pak, dstVTFFileName, outputBuf.Base(), outputBuf.TellPut(), false ); // spit out all of the ones that are attached to world geometry. int i; for( i = 0; i < s_DefaultCubemapNames.Count(); i++ ) { char vtfName[MAX_PATH]; VTFNameToHDRVTFName( s_DefaultCubemapNames[i], vtfName, MAX_PATH, bHDR ); if( FileExistsInPak( pak, vtfName ) ) { continue; } AddBufferToPak( pak, vtfName, outputBuf.Base(),outputBuf.TellPut(), false ); } // Clean up the textures for( i = 0; i < 6; i++ ) { DestroyVTFTexture( pSrcVTFTextures[i] ); } DestroyVTFTexture( pDstCubemap ); }