News:

One Minute Game Review by The Happy Friar: https://ugetube.com/@OneMinteGameReviews
Also on Rumble: https://rumble.com/c/c-1115371

idTech 4 (aka Doom 3 tech) Discord Server! https://discord.gg/9wtCGHa

Main Menu

Sgt.Kelly BFG Textures

Started by oneofthe8devilz, April 21, 2015, 10:45:39 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

oneofthe8devilz

Was someone able to extract ALL textures (diffuse, normal, bump, specular) for Sgt.Kelly's Head and Body from the BFG edition ?

I like the new "younger" looking version and would like to add it to my pool of selectable player models/skins...



I got six little friends and they all run faster than you ;)


Check out our mods at
moddb or the SPS Homepage

BielBdeLuna

I'm afraid that if you want that you'll be forced to look into the source code on how to the engine does it and replicate the process. :(

oneofthe8devilz

#2
I am quite sure there are ways to "grab" engine render calls that would allow you to take/grab shots of the textures used during rendering...
I got six little friends and they all run faster than you ;)


Check out our mods at
moddb or the SPS Homepage

TeaMonster

Can't you extract the level assets and find them that way?

oneofthe8devilz

As far as I know for D3 BFG most textures are in binary format...
I got six little friends and they all run faster than you ;)


Check out our mods at
moddb or the SPS Homepage

motorsep

not only, they are also compressed with different methods.

BielBdeLuna

I guess the best bet is to look in the code, the decoding should be there, and replicate that code in a small app to extract textures.

motorsep

But you can't - just like you can't recreated TGA from JPG, you can't recreate lossless original TGA from DXT compressed image. Perhaps you could turn .bimage into DXT image (.dds), but it's also unlikely and will still leave you with unusable image. Note that all diffuse is encoded with YCoCg DXT5, which isn't supported by Doom 3 anyway.

trebor

You can extract all images back to .png in void idImage::ActuallyLoadImage( bool fromBackEnd )
by adding

if( image_exportPNG.GetBool() && binaryFileTime != FILE_NOT_FOUND_TIMESTAMP )
   {
      const bimageImage_t& img = im.GetImageHeader( 0 );
      
      const byte* data = im.GetImageData( 0 );
      
      //( img.level, 0, 0, img.destZ, img.width, img.height, data );
      
      idTempArray<byte> rgba( img.width * img.height * 4 );
      memset( rgba.Ptr(), 255, rgba.Size() );
      
      if( header.format == FMT_DXT1 )
      {
         idDxtDecoder dxt;
         dxt.DecompressImageDXT1( data, rgba.Ptr(), img.width, img.height );
         
         if( header.colorFormat == CFM_GREEN_ALPHA )
         {
            byte* pic = rgba.Ptr();
            for( int i = 0; i < img.width * img.height; i++ )
            {
               pic[i * 4 + 3] = pic[i * 4 + 1];
               pic[i * 4 + 0] = 255;
               pic[i * 4 + 1] = 255;
               pic[i * 4 + 2] = 255;
            }
         }
      }
      else if( header.format == FMT_DXT5 )
      {
         idDxtDecoder dxt;
         
         if( header.colorFormat == CFM_NORMAL_DXT5 )
         {
            dxt.DecompressNormalMapDXT5( data, rgba.Ptr(), img.width, img.height );
         }
         else if( header.colorFormat == CFM_YCOCG_DXT5 )
         {
            dxt.DecompressYCoCgDXT5( data, rgba.Ptr(), img.width, img.height );
         }
         else
         {
         
            dxt.DecompressImageDXT5( data, rgba.Ptr(), img.width, img.height );
         }
      }
      else if( header.format == FMT_LUM8 || header.format == FMT_INT8 )
      {
         // LUM8 and INT8 just read the red channel
         byte* pic = rgba.Ptr();
         for( int i = 0; i < img.dataSize; i++ )
         {
            pic[ i * 4 ] = data[ i ];
         }
      }
      else if( header.format == FMT_ALPHA )
      {
         // ALPHA reads the alpha channel
         byte* pic = rgba.Ptr();
         for( int i = 0; i < img.dataSize; i++ )
         {
            pic[ i * 4 + 3 ] = data[ i ];
         }
      }
      else if( header.format == FMT_L8A8 )
      {
         // L8A8 reads the alpha and red channels
         byte* pic = rgba.Ptr();
         for( int i = 0; i < img.dataSize / 2; i++ )
         {
            pic[ i * 4 + 0 ] = data[ i * 2 + 0 ];
            pic[ i * 4 + 3 ] = data[ i * 2 + 1 ];
         }
      }
      else if( header.format == FMT_RGB565 )
      {
         // FIXME
         /*
         byte* pic = rgba.Ptr();
         for( int i = 0; i < img.dataSize / 2; i++ )
         {
            unsigned short color = ( ( pic[ i * 4 + 0 ] >> 3 ) << 11 ) | ( ( pic[ i * 4 + 1 ] >> 2 ) << 5 ) | ( pic[ i * 4 + 2 ] >> 3 );
            img.data[ i * 2 + 0 ] = ( color >> 8 ) & 0xFF;
            img.data[ i * 2 + 1 ] = color & 0xFF;
         }
         */
      }
      else
      {
         byte* pic = rgba.Ptr();
         for( int i = 0; i < img.dataSize; i++ )
         {
            pic[ i ] = data[ i ];
         }
      }
      
      idStr pngFileNameExport = generatedName;
      pngFileNameExport.SetFileExtension( ".png" );
      
      R_WritePNG( pngFileNameExport, rgba.Ptr(), 4, img.width, img.height, true, "fs_basepath" );
   }

BielBdeLuna

Quote from: motorsep on April 23, 2015, 07:46:05 PM
But you can't - just like you can't recreated TGA from JPG, you can't recreate lossless original TGA from DXT compressed image. Perhaps you could turn .bimage into DXT image (.dds), but it's also unlikely and will still leave you with unusable image. Note that all diffuse is encoded with YCoCg DXT5, which isn't supported by Doom 3 anyway.
nobody said anything on getting the original assets fof which d3bfg distributed compressed textures where made of, but to extract those compressed images d3bfg uses and convert them to a format usable to vanilla d3, which should be doable with the help of the source code

you can create a TGA from a JPG but you won't get any benefit quality-wise, you will only get a non lossy file form that version of the data, which is the point of TGA

motorsep

Sure, I understand that. Just don't see a point in having bad quality assets :/

BielBdeLuna

it should be the most high quality given the BFG compressed content, if you want to use this content you have to put up with it's compression artefacts isn't it? the thing is to don't add more artefacts to the equation.

The Happy Friar

Even if the extracted textures are converted to TGA to use in original Doom 3, unless you run on Ultra (or change whatever cvar it needed) it will re-compress for you.

From a technical standpoint, I'd be interested to see the extracted textures compared to the TGA's & DDS included with Doom 3.  I wonder if reducing TGA dimension would give the same benefits as using the compressed D3 textures.


vurt

Quote from: trebor on April 24, 2015, 05:57:32 AM
You can extract all images back to .png in void idImage::ActuallyLoadImage( bool fromBackEnd )
by adding

if( image_exportPNG.GetBool() && binaryFileTime != FILE_NOT_FOUND_TIMESTAMP )
   {
      const bimageImage_t& img = im.GetImageHeader( 0 );
      
      const byte* data = im.GetImageData( 0 );
      
      //( img.level, 0, 0, img.destZ, img.width, img.height, data );
      
      idTempArray<byte> rgba( img.width * img.height * 4 );
      memset( rgba.Ptr(), 255, rgba.Size() );
      
      if( header.format == FMT_DXT1 )
      {
         idDxtDecoder dxt;
         dxt.DecompressImageDXT1( data, rgba.Ptr(), img.width, img.height );
         
         if( header.colorFormat == CFM_GREEN_ALPHA )
         {
            byte* pic = rgba.Ptr();
            for( int i = 0; i < img.width * img.height; i++ )
            {
               pic[i * 4 + 3] = pic[i * 4 + 1];
               pic[i * 4 + 0] = 255;
               pic[i * 4 + 1] = 255;
               pic[i * 4 + 2] = 255;
            }
         }
      }
      else if( header.format == FMT_DXT5 )
      {
         idDxtDecoder dxt;
         
         if( header.colorFormat == CFM_NORMAL_DXT5 )
         {
            dxt.DecompressNormalMapDXT5( data, rgba.Ptr(), img.width, img.height );
         }
         else if( header.colorFormat == CFM_YCOCG_DXT5 )
         {
            dxt.DecompressYCoCgDXT5( data, rgba.Ptr(), img.width, img.height );
         }
         else
         {
         
            dxt.DecompressImageDXT5( data, rgba.Ptr(), img.width, img.height );
         }
      }
      else if( header.format == FMT_LUM8 || header.format == FMT_INT8 )
      {
         // LUM8 and INT8 just read the red channel
         byte* pic = rgba.Ptr();
         for( int i = 0; i < img.dataSize; i++ )
         {
            pic[ i * 4 ] = data[ i ];
         }
      }
      else if( header.format == FMT_ALPHA )
      {
         // ALPHA reads the alpha channel
         byte* pic = rgba.Ptr();
         for( int i = 0; i < img.dataSize; i++ )
         {
            pic[ i * 4 + 3 ] = data[ i ];
         }
      }
      else if( header.format == FMT_L8A8 )
      {
         // L8A8 reads the alpha and red channels
         byte* pic = rgba.Ptr();
         for( int i = 0; i < img.dataSize / 2; i++ )
         {
            pic[ i * 4 + 0 ] = data[ i * 2 + 0 ];
            pic[ i * 4 + 3 ] = data[ i * 2 + 1 ];
         }
      }
      else if( header.format == FMT_RGB565 )
      {
         // FIXME
         /*
         byte* pic = rgba.Ptr();
         for( int i = 0; i < img.dataSize / 2; i++ )
         {
            unsigned short color = ( ( pic[ i * 4 + 0 ] >> 3 ) << 11 ) | ( ( pic[ i * 4 + 1 ] >> 2 ) << 5 ) | ( pic[ i * 4 + 2 ] >> 3 );
            img.data[ i * 2 + 0 ] = ( color >> 8 ) & 0xFF;
            img.data[ i * 2 + 1 ] = color & 0xFF;
         }
         */
      }
      else
      {
         byte* pic = rgba.Ptr();
         for( int i = 0; i < img.dataSize; i++ )
         {
            pic[ i ] = data[ i ];
         }
      }
      
      idStr pngFileNameExport = generatedName;
      pngFileNameExport.SetFileExtension( ".png" );
      
      R_WritePNG( pngFileNameExport, rgba.Ptr(), 4, img.width, img.height, true, "fs_basepath" );
   }

Sorry for resurrecting this old post.. Does anyone know how / where I would i apply this script?

I'd like to make a texture pack for Doom 3 BFG, being able to see and open the generated .bimage files is vital. Haven't found any converters.

Thanks


argoon

That is not a script that is source c++ code, not knowing much about the engine source i would assume this should be used on the render part of the engine where idImage is implemented, search for it on the code base.