Added support to load RG16F texture data. Added R_WriteEXR function

This commit is contained in:
Robert Beckebans 2020-04-18 19:16:24 +02:00
parent 9872734f62
commit c8250b184b
8 changed files with 22063 additions and 369 deletions

View file

@ -240,6 +240,23 @@ void idBinaryImage::Load2DFromMemory( int width, int height, const byte* pic_con
img.data[ i * 2 + 1 ] = color & 0xFF;
}
}
else if( textureFormat == FMT_RG16F )
{
// RB: copy it as it was a RGBA8 because of the same size
img.Alloc( scaledWidth * scaledHeight * 4 );
for( int i = 0; i < img.dataSize; i++ )
{
img.data[ i ] = pic[ i ];
}
}
else if( textureFormat == FMT_RGBA16F )
{
img.Alloc( scaledWidth * scaledHeight * 8 );
for( int i = 0; i < img.dataSize; i++ )
{
img.data[ i ] = pic[ i ];
}
}
else
{
fileData.format = textureFormat = FMT_RGBA8;

View file

@ -96,7 +96,7 @@ enum textureFormat_t
// RB: don't change above for legacy .bimage compatibility
FMT_ETC1_RGB8_OES, // 4 bpp
FMT_SHADOW_ARRAY, // 32 bpp * 6
//FMT_RG16F, // 32 bpp
FMT_RG16F, // 32 bpp
FMT_RGBA16F, // 64 bpp
FMT_RGBA32F, // 128 bpp
FMT_R32F, // 32 bpp
@ -222,6 +222,7 @@ typedef enum
TD_HIGHQUALITY_CUBE, // motorsep - Uncompressed cubemap texture (RGB colorspace)
TD_LOWQUALITY_CUBE, // motorsep - Compressed cubemap texture (RGB colorspace DXT5)
TD_SHADOW_ARRAY, // 2D depth buffer array for shadow mapping
TD_RG16F,
TD_RGBA16F,
TD_RGBA32F,
TD_R32F,
@ -479,6 +480,7 @@ void R_WriteTGA( const char* filename, const byte* data, int width, int height,
// RB begin
void R_WritePNG( const char* filename, const byte* data, int bytesPerPixel, int width, int height, bool flipVertical = false, const char* basePath = "fs_savepath" );
void R_WriteEXR( const char* filename, const void* data, int channelsPerPixel, int width, int height, const char* basePath = "fs_savepath" );
// RB end
class idImageManager

File diff suppressed because it is too large Load diff

View file

@ -851,6 +851,161 @@ void R_WritePNG( const char* filename, const byte* data, int bytesPerPixel, int
Mem_Free( buffer );
}
/*
================
R_WriteEXR
================
*/
// miniexr.cpp - v0.2 - public domain - 2013 Aras Pranckevicius / Unity Technologies
//
// Writes OpenEXR RGB files out of half-precision RGBA or RGB data.
//
// Only tested on Windows (VS2008) and Mac (clang 3.3), little endian.
// Testing status: "works for me".
//
// History:
// 0.2 Source data can be RGB or RGBA now.
// 0.1 Initial release.
void R_WriteEXR( const char* filename, const void* rgba16f, int channelsPerPixel, int width, int height, const char* basePath )
{
const unsigned ww = width - 1;
const unsigned hh = height - 1;
const unsigned char kHeader[] =
{
0x76, 0x2f, 0x31, 0x01, // magic
2, 0, 0, 0, // version, scanline
// channels
'c', 'h', 'a', 'n', 'n', 'e', 'l', 's', 0,
'c', 'h', 'l', 'i', 's', 't', 0,
55, 0, 0, 0,
'B', 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, // B, half
'G', 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, // G, half
'R', 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, // R, half
0,
// compression
'c', 'o', 'm', 'p', 'r', 'e', 's', 's', 'i', 'o', 'n', 0,
'c', 'o', 'm', 'p', 'r', 'e', 's', 's', 'i', 'o', 'n', 0,
1, 0, 0, 0,
0, // no compression
// dataWindow
'd', 'a', 't', 'a', 'W', 'i', 'n', 'd', 'o', 'w', 0,
'b', 'o', 'x', '2', 'i', 0,
16, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
ww & 0xFF, ( ww >> 8 ) & 0xFF, ( ww >> 16 ) & 0xFF, ( ww >> 24 ) & 0xFF,
hh & 0xFF, ( hh >> 8 ) & 0xFF, ( hh >> 16 ) & 0xFF, ( hh >> 24 ) & 0xFF,
// displayWindow
'd', 'i', 's', 'p', 'l', 'a', 'y', 'W', 'i', 'n', 'd', 'o', 'w', 0,
'b', 'o', 'x', '2', 'i', 0,
16, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
ww & 0xFF, ( ww >> 8 ) & 0xFF, ( ww >> 16 ) & 0xFF, ( ww >> 24 ) & 0xFF,
hh & 0xFF, ( hh >> 8 ) & 0xFF, ( hh >> 16 ) & 0xFF, ( hh >> 24 ) & 0xFF,
// lineOrder
'l', 'i', 'n', 'e', 'O', 'r', 'd', 'e', 'r', 0,
'l', 'i', 'n', 'e', 'O', 'r', 'd', 'e', 'r', 0,
1, 0, 0, 0,
0, // increasing Y
// pixelAspectRatio
'p', 'i', 'x', 'e', 'l', 'A', 's', 'p', 'e', 'c', 't', 'R', 'a', 't', 'i', 'o', 0,
'f', 'l', 'o', 'a', 't', 0,
4, 0, 0, 0,
0, 0, 0x80, 0x3f, // 1.0f
// screenWindowCenter
's', 'c', 'r', 'e', 'e', 'n', 'W', 'i', 'n', 'd', 'o', 'w', 'C', 'e', 'n', 't', 'e', 'r', 0,
'v', '2', 'f', 0,
8, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
// screenWindowWidth
's', 'c', 'r', 'e', 'e', 'n', 'W', 'i', 'n', 'd', 'o', 'w', 'W', 'i', 'd', 't', 'h', 0,
'f', 'l', 'o', 'a', 't', 0,
4, 0, 0, 0,
0, 0, 0x80, 0x3f, // 1.0f
// end of header
0,
};
const int kHeaderSize = sizeof( kHeader );
const int kScanlineTableSize = 8 * height;
const unsigned pixelRowSize = width * 3 * 2;
const unsigned fullRowSize = pixelRowSize + 8;
unsigned bufSize = kHeaderSize + kScanlineTableSize + height * fullRowSize;
unsigned char* buf = ( unsigned char* )Mem_Alloc( bufSize, TAG_TEMP );
if( !buf )
{
return;
}
// copy in header
memcpy( buf, kHeader, kHeaderSize );
// line offset table
unsigned ofs = kHeaderSize + kScanlineTableSize;
unsigned char* ptr = buf + kHeaderSize;
for( int y = 0; y < height; ++y )
{
*ptr++ = ofs & 0xFF;
*ptr++ = ( ofs >> 8 ) & 0xFF;
*ptr++ = ( ofs >> 16 ) & 0xFF;
*ptr++ = ( ofs >> 24 ) & 0xFF;
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
ofs += fullRowSize;
}
// scanline data
const unsigned char* src = ( const unsigned char* )rgba16f;
const int stride = channelsPerPixel * 2;
for( int y = 0; y < height; ++y )
{
// coordinate
*ptr++ = y & 0xFF;
*ptr++ = ( y >> 8 ) & 0xFF;
*ptr++ = ( y >> 16 ) & 0xFF;
*ptr++ = ( y >> 24 ) & 0xFF;
// data size
*ptr++ = pixelRowSize & 0xFF;
*ptr++ = ( pixelRowSize >> 8 ) & 0xFF;
*ptr++ = ( pixelRowSize >> 16 ) & 0xFF;
*ptr++ = ( pixelRowSize >> 24 ) & 0xFF;
// B, G, R
const unsigned char* chsrc;
chsrc = src + 4;
for( int x = 0; x < width; ++x )
{
*ptr++ = chsrc[0];
*ptr++ = chsrc[1];
chsrc += stride;
}
chsrc = src + 2;
for( int x = 0; x < width; ++x )
{
*ptr++ = chsrc[0];
*ptr++ = chsrc[1];
chsrc += stride;
}
chsrc = src + 0;
for( int x = 0; x < width; ++x )
{
*ptr++ = chsrc[0];
*ptr++ = chsrc[1];
chsrc += stride;
}
src += width * stride;
}
assert( ptr - buf == bufSize );
fileSystem->WriteFile( filename, buf, bufSize, basePath );
Mem_Free( buf );
}
// RB end
//===================================================================

View file

@ -861,7 +861,7 @@ static void R_CreateBrdfLutImage( idImage* image )
}
#endif
image->GenerateImage( ( byte* )brfLutTexBytes, BRDFLUT_TEX_WIDTH, BRDFLUT_TEX_HEIGHT, TF_LINEAR, TR_CLAMP, TD_LOOKUP_TABLE_RGBA );
image->GenerateImage( ( byte* )brfLutTexBytes, BRDFLUT_TEX_WIDTH, BRDFLUT_TEX_HEIGHT, TF_LINEAR, TR_CLAMP, TD_RG16F );
}
// RB end

View file

@ -69,6 +69,8 @@ int BitsForFormat( textureFormat_t format )
return 4;
case FMT_SHADOW_ARRAY:
return ( 32 * 6 );
case FMT_RG16F:
return 32;
case FMT_RGBA16F:
return 64;
case FMT_RGBA32F:
@ -114,6 +116,10 @@ ID_INLINE void idImage::DeriveOpts()
opts.format = FMT_SHADOW_ARRAY;
break;
case TD_RG16F:
opts.format = FMT_RG16F;
break;
case TD_RGBA16F:
opts.format = FMT_RGBA16F;
break;
@ -630,6 +636,7 @@ void idImage::Print() const
// RB begin
NAME_FORMAT( ETC1_RGB8_OES );
NAME_FORMAT( SHADOW_ARRAY );
NAME_FORMAT( RG16F );
NAME_FORMAT( RGBA16F );
NAME_FORMAT( RGBA32F );
NAME_FORMAT( R32F );

View file

@ -472,7 +472,7 @@ void idImage::SetTexParameters()
glTexParameteri( target, GL_TEXTURE_SWIZZLE_B, GL_RED );
glTexParameteri( target, GL_TEXTURE_SWIZZLE_A, GL_ONE );
}
else if( opts.format == FMT_L8A8 )
else if( opts.format == FMT_L8A8 )//|| opts.format == FMT_RG16F )
{
glTexParameteri( target, GL_TEXTURE_SWIZZLE_R, GL_RED );
glTexParameteri( target, GL_TEXTURE_SWIZZLE_G, GL_RED );
@ -690,10 +690,16 @@ void idImage::AllocImage()
dataType = GL_UNSIGNED_BYTE;
break;
case FMT_RG16F:
internalFormat = GL_RG16F;
dataFormat = GL_RG;
dataType = GL_HALF_FLOAT;
break;
case FMT_RGBA16F:
internalFormat = GL_RGBA16F;
dataFormat = GL_RGBA;
dataType = GL_UNSIGNED_BYTE;
dataType = GL_HALF_FLOAT;
break;
case FMT_RGBA32F:

View file

@ -1497,7 +1497,7 @@ idVec2 IntegrateBRDF( float NdotV, float roughness, int sampleCount )
void R_MakeBrdfLut_f( const idCmdArgs& args )
{
int outSize = 32;
int outSize = 256;
int width = 0, height = 0;
//if( args.Argc() != 2 )
@ -1519,6 +1519,9 @@ void R_MakeBrdfLut_f( const idCmdArgs& args )
int ldrBufferSize = outSize * outSize * 4;
byte* ldrBuffer = ( byte* )Mem_Alloc( ldrBufferSize, TAG_TEMP );
int hdrBufferSize = outSize * outSize * 2 * sizeof( halfFloat_t );
halfFloat_t* hdrBuffer = ( halfFloat_t* )Mem_Alloc( hdrBufferSize, TAG_TEMP );
CommandlineProgressBar progressBar( outSize * outSize );
int start = Sys_Milliseconds();
@ -1538,18 +1541,23 @@ void R_MakeBrdfLut_f( const idCmdArgs& args )
ldrBuffer[( y * outSize + x ) * 4 + 2] = 0;
ldrBuffer[( y * outSize + x ) * 4 + 3] = 255;
halfFloat_t half1 = F32toF16( output.x );
halfFloat_t half2 = F32toF16( output.y );
hdrBuffer[( y * outSize + x ) * 2 + 0] = half1;
hdrBuffer[( y * outSize + x ) * 2 + 1] = half2;
//hdrBuffer[( y * outSize + x ) * 4 + 2] = 0;
//hdrBuffer[( y * outSize + x ) * 4 + 3] = 1;
progressBar.Increment();
}
//const bool captureToImage = false;
//common->UpdateScreen( captureToImage );
}
idStr fullname = "env/_brdfLut.png";
idLib::Printf( "writing %s\n", fullname.c_str() );
//R_WriteTGA( fullname, outBuffer, outSize, outSize, false, "fs_basepath" );
R_WritePNG( fullname, ldrBuffer, 4, outSize, outSize, true, "fs_basepath" );
//R_WriteEXR( "env/_brdfLut.exr", hdrBuffer, 4, outSize, outSize, "fs_basepath" );
idFileLocal headerFile( fileSystem->OpenFileWrite( "env/Image_brdfLut.h", "fs_basepath" ) );
@ -1558,27 +1566,24 @@ void R_MakeBrdfLut_f( const idCmdArgs& args )
#ifndef BRDFLUT_TEX_H
#define BRDFLUT_TEX_H
#define BRDFLUT_TEX_WIDTH 512
#define BRDFLUT_TEX_HEIGHT 512
#define BRDFLUT_TEX_WIDTH 256
#define BRDFLUT_TEX_HEIGHT 256
#define BRDFLUT_TEX_PITCH (BRDFLUT_TEX_WIDTH * 2)
#define BRDFLUT_TEX_SIZE (BRDFLUT_TEX_WIDTH * BRDFLUT_TEX_PITCH)
/**
* Stored in R8G8 format. Load it in the following format:
* - DX9: D3DFMT_A8L8
* - DX10: DXGI_FORMAT_R8G8_UNORM
*/
// Stored in R16G16F format
static const unsigned char brfLutTexBytes[] =
{
)";
headerFile->Printf( "%s\n", intro );
for( int i = 0; i < ldrBufferSize; i++ )
const byte* hdrBytes = (const byte* ) hdrBuffer;
for( int i = 0; i < hdrBufferSize; i++ )
{
byte b = ldrBuffer[i];
byte b = hdrBytes[i];
if( i < ( ldrBufferSize - 1 ) )
if( i < ( hdrBufferSize - 1 ) )
{
headerFile->Printf( "0x%02hhx, ", b );
}
@ -1599,6 +1604,7 @@ static const unsigned char brfLutTexBytes[] =
common->Printf( "%s integrated in %5.1f seconds\n\n", fullname.c_str(), ( end - start ) * 0.001f );
Mem_Free( ldrBuffer );
Mem_Free( hdrBuffer );
}
/*