mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-13 22:22:05 +00:00
Fixed several bugs in the .bimage lookup logic
This commit is contained in:
parent
f9ca463d50
commit
67987ab715
7 changed files with 207 additions and 60 deletions
|
@ -3,7 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2014-2024 Robert Beckebans
|
||||
Copyright (C) 2014-2025 Robert Beckebans
|
||||
Copyright (C) 2014-2016 Kot in Action Creative Artel
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
@ -260,14 +260,6 @@ void idBinaryImage::Load2DFromMemory( int width, int height, const byte* pic_con
|
|||
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;
|
||||
|
@ -287,7 +279,11 @@ void idBinaryImage::Load2DFromMemory( int width, int height, const byte* pic_con
|
|||
|
||||
// downsample for the next level
|
||||
byte* shrunk = NULL;
|
||||
if( gammaMips )
|
||||
if( textureFormat == FMT_R11G11B10F )
|
||||
{
|
||||
shrunk = R_MipMapR11G11B10F( pic, scaledWidth, scaledHeight );
|
||||
}
|
||||
else if( gammaMips )
|
||||
{
|
||||
shrunk = R_MipMapWithGamma( pic, scaledWidth, scaledHeight );
|
||||
}
|
||||
|
@ -556,15 +552,6 @@ void idBinaryImage::Load2DAtlasMipchainFromMemory( int width, int height, const
|
|||
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_R11G11B10F )
|
||||
{
|
||||
// RB: copy it as it was a RGBA8 because of the same size
|
||||
|
@ -574,14 +561,6 @@ void idBinaryImage::Load2DAtlasMipchainFromMemory( int width, int height, const
|
|||
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;
|
||||
|
@ -599,21 +578,6 @@ void idBinaryImage::Load2DAtlasMipchainFromMemory( int width, int height, const
|
|||
dxtPic = NULL;
|
||||
}
|
||||
|
||||
// downsample for the next level
|
||||
/*
|
||||
byte* shrunk = NULL;
|
||||
if( gammaMips )
|
||||
{
|
||||
shrunk = R_MipMapWithGamma( pic, scaledWidth, scaledHeight );
|
||||
}
|
||||
else
|
||||
{
|
||||
shrunk = R_MipMap( pic, scaledWidth, scaledHeight );
|
||||
}
|
||||
Mem_Free( pic );
|
||||
pic = shrunk;
|
||||
*/
|
||||
|
||||
Mem_Free( pic );
|
||||
}
|
||||
|
||||
|
@ -753,7 +717,11 @@ void idBinaryImage::LoadCubeFromMemory( int width, const byte* pics[6], int numL
|
|||
|
||||
// downsample for the next level
|
||||
byte* shrunk = NULL;
|
||||
if( gammaMips )
|
||||
if( textureFormat == FMT_R11G11B10F )
|
||||
{
|
||||
shrunk = R_MipMapR11G11B10F( pic, scaledWidth, scaledWidth );
|
||||
}
|
||||
else if( gammaMips )
|
||||
{
|
||||
shrunk = R_MipMapWithGamma( pic, scaledWidth, scaledWidth );
|
||||
}
|
||||
|
|
|
@ -207,6 +207,8 @@ No texture is ever used that does not have a corresponding idImage.
|
|||
static const int MAX_TEXTURE_LEVELS = 14;
|
||||
|
||||
// How is this texture used? Determines the storage and color format
|
||||
// NOTE: be very careful when editing these because it might break older .bimage files or the lookup name
|
||||
// Only add new entries at the bottom
|
||||
typedef enum
|
||||
{
|
||||
TD_SPECULAR, // may be compressed, and always zeros the alpha channel
|
||||
|
@ -227,28 +229,33 @@ 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_RGBA16S,
|
||||
TD_RGBA32F,
|
||||
TD_R32F,
|
||||
TD_RG16F, // BRDF lookup table
|
||||
TD_RGBA16F, // RT = render target format only, not written to disk
|
||||
TD_RGBA16S, // RT only
|
||||
TD_RGBA32F, // RT only
|
||||
TD_R11G11B10F, // memory efficient HDR RGB format with only 32bpp
|
||||
// ^-- used up until RBDOOM-3-BFG 1.3
|
||||
TD_HDRI, // RB: R11G11B10F or BC6
|
||||
// RB end
|
||||
TD_R8F, // Stephen: Added for ambient occlusion render target.
|
||||
TD_LDR, // Stephen: Added for SRGB render target when tonemapping.
|
||||
TD_DEPTH_STENCIL, // depth buffer and stencil buffer
|
||||
TD_R32F, // RT only
|
||||
TD_R8F, // SP: RT only, added for ambient occlusion
|
||||
TD_LDR, // SP: RT only, added for SRGB render target when tonemapping
|
||||
TD_DEPTH_STENCIL, // SP: RT only, depth buffer and stencil buffer
|
||||
} textureUsage_t;
|
||||
|
||||
// NOTE: be very careful when editing these because it might break older .bimage files or the lookup name
|
||||
// Only add new entries at the bottom
|
||||
typedef enum
|
||||
{
|
||||
CF_2D, // not a cube map
|
||||
CF_NATIVE, // _px, _nx, _py, etc, directly sent to GL
|
||||
CF_CAMERA, // _forward, _back, etc, rotated and flipped as needed before sending to GL
|
||||
CF_QUAKE1, // _ft, _bk, etc, rotated and flipped as needed before sending to GL
|
||||
CF_PANORAMA, // TODO latlong encoded HDRI panorama typically used by Substance or Blender
|
||||
CF_PANORAMA, // RB: latlong encoded HDRI panorama typically used by Substance or Blender
|
||||
CF_2D_ARRAY, // not a cube map but not a single 2d texture either
|
||||
CF_2D_PACKED_MIPCHAIN, // usually 2d but can be an octahedron, packed mipmaps into single 2d texture atlas and limited to dim^2
|
||||
// ^-- used up until RBDOOM-3-BFG 1.3
|
||||
CF_SINGLE, // SP: A single texture cubemap. All six sides in one image.
|
||||
CF_QUAKE1, // RB: _ft, _bk, etc, rotated and flipped as needed before sending to GL
|
||||
} cubeFiles_t;
|
||||
|
||||
typedef void ( *ImageGeneratorFunction )( idImage* image, nvrhi::ICommandList* commandList );
|
||||
|
@ -663,6 +670,7 @@ byte* R_ResampleTexture( const byte* in, int inwidth, int inheight, int outwidth
|
|||
byte* R_MipMapWithAlphaSpecularity( const byte* in, int width, int height );
|
||||
byte* R_MipMapWithGamma( const byte* in, int width, int height );
|
||||
byte* R_MipMap( const byte* in, int width, int height );
|
||||
byte* R_MipMapR11G11B10F( const byte* in, int width, int height );
|
||||
|
||||
// these operate in-place on the provided pixels
|
||||
void R_BlendOverTexture( byte* data, int pixelCount, const byte blend[4] );
|
||||
|
|
|
@ -156,11 +156,11 @@ ID_INLINE void idImage::DeriveOpts()
|
|||
opts.format = FMT_DEPTH;
|
||||
break;
|
||||
|
||||
// sp begin
|
||||
// SP begin
|
||||
case TD_DEPTH_STENCIL:
|
||||
opts.format = FMT_DEPTH_STENCIL;
|
||||
break;
|
||||
// sp end
|
||||
// SP end
|
||||
|
||||
case TD_SHADOW_ARRAY:
|
||||
opts.format = FMT_SHADOW_ARRAY;
|
||||
|
@ -200,6 +200,7 @@ ID_INLINE void idImage::DeriveOpts()
|
|||
opts.format = FMT_DXT5;
|
||||
opts.colorFormat = CFM_YCOCG_DXT5;
|
||||
break;
|
||||
|
||||
case TD_SPECULAR:
|
||||
opts.gammaMips = true;
|
||||
opts.format = FMT_DXT1;
|
||||
|
@ -223,16 +224,19 @@ ID_INLINE void idImage::DeriveOpts()
|
|||
opts.format = FMT_DXT5;
|
||||
opts.colorFormat = CFM_DEFAULT;
|
||||
break;
|
||||
|
||||
case TD_BUMP:
|
||||
opts.format = FMT_DXT5;
|
||||
opts.colorFormat = CFM_NORMAL_DXT5;
|
||||
break;
|
||||
|
||||
case TD_FONT:
|
||||
opts.format = FMT_DXT1;
|
||||
opts.colorFormat = CFM_GREEN_ALPHA;
|
||||
opts.numLevels = 4; // We only support 4 levels because we align to 16 in the exporter
|
||||
opts.gammaMips = true;
|
||||
break;
|
||||
|
||||
case TD_LIGHT:
|
||||
// RB: TODO check binary format version
|
||||
// D3 BFG assets require RGB565 but it introduces color banding
|
||||
|
@ -240,16 +244,20 @@ ID_INLINE void idImage::DeriveOpts()
|
|||
opts.format = FMT_RGB565; //FMT_RGBA8;
|
||||
opts.gammaMips = true;
|
||||
break;
|
||||
|
||||
case TD_LOOKUP_TABLE_MONO:
|
||||
opts.format = FMT_INT8;
|
||||
break;
|
||||
|
||||
case TD_LOOKUP_TABLE_ALPHA:
|
||||
opts.format = FMT_ALPHA;
|
||||
break;
|
||||
|
||||
case TD_LOOKUP_TABLE_RGB1:
|
||||
case TD_LOOKUP_TABLE_RGBA:
|
||||
opts.format = FMT_RGBA8;
|
||||
break;
|
||||
|
||||
// motorsep 05-17-2015; added this for uncompressed cubemap/skybox textures
|
||||
case TD_HIGHQUALITY_CUBE:
|
||||
opts.colorFormat = CFM_DEFAULT;
|
||||
|
@ -261,6 +269,13 @@ ID_INLINE void idImage::DeriveOpts()
|
|||
opts.format = FMT_DXT5;
|
||||
opts.gammaMips = true;
|
||||
break;
|
||||
// motorsep end
|
||||
|
||||
case TD_HDRI:
|
||||
opts.format = FMT_R11G11B10F;
|
||||
//opts.numLevels = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( false );
|
||||
opts.format = FMT_RGBA8;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2021 Robert Beckebans
|
||||
Copyright (C) 2021-2025 Robert Beckebans
|
||||
Copyright (C) 2021 Stephen Pridham
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
@ -33,6 +33,8 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "RenderCommon.h"
|
||||
|
||||
#include "../libs/mesa/format_r11g11b10f.h"
|
||||
|
||||
/*
|
||||
================
|
||||
R_ResampleTexture
|
||||
|
@ -463,6 +465,152 @@ byte* R_MipMap( const byte* in, int width, int height )
|
|||
return out;
|
||||
}
|
||||
|
||||
// RB begin
|
||||
byte* R_MipMapR11G11B10F( const byte* in, int width, int height )
|
||||
{
|
||||
int i, j;
|
||||
const byte* in_p;
|
||||
byte* out, *out_p;
|
||||
int row;
|
||||
int newWidth, newHeight;
|
||||
|
||||
if( width < 1 || height < 1 || ( width + height == 2 ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
row = width * 4;
|
||||
|
||||
newWidth = width >> 1;
|
||||
newHeight = height >> 1;
|
||||
if( !newWidth )
|
||||
{
|
||||
newWidth = 1;
|
||||
}
|
||||
if( !newHeight )
|
||||
{
|
||||
newHeight = 1;
|
||||
}
|
||||
out = ( byte* )R_StaticAlloc( newWidth * newHeight * 4, TAG_IMAGE );
|
||||
out_p = out;
|
||||
|
||||
in_p = in;
|
||||
|
||||
width >>= 1;
|
||||
height >>= 1;
|
||||
|
||||
typedef union
|
||||
{
|
||||
uint32 i;
|
||||
byte b[4];
|
||||
} convert_t;
|
||||
|
||||
if( width == 0 || height == 0 )
|
||||
{
|
||||
width += height; // get largest
|
||||
for( i = 0 ; i < width ; i++, out_p += 4, in_p += 8 )
|
||||
{
|
||||
convert_t p1;
|
||||
p1.b[0] = in_p[0];
|
||||
p1.b[1] = in_p[1];
|
||||
p1.b[2] = in_p[2];
|
||||
p1.b[3] = in_p[3];
|
||||
|
||||
convert_t p2;
|
||||
p2.b[0] = in_p[4];
|
||||
p2.b[1] = in_p[5];
|
||||
p2.b[2] = in_p[6];
|
||||
p2.b[3] = in_p[7];
|
||||
|
||||
float c1[3];
|
||||
r11g11b10f_to_float3( p1.i, c1 );
|
||||
|
||||
float c2[3];
|
||||
r11g11b10f_to_float3( p2.i, c2 );
|
||||
|
||||
float rgb[3];
|
||||
rgb[0] = ( c1[0] + c2[0] ) * 0.5f;
|
||||
rgb[1] = ( c1[1] + c2[1] ) * 0.5f;
|
||||
rgb[2] = ( c1[2] + c2[2] ) * 0.5f;
|
||||
|
||||
p1.i = float3_to_r11g11b10f( rgb );
|
||||
|
||||
out_p[0] = p1.b[0];
|
||||
out_p[1] = p1.b[1];
|
||||
out_p[2] = p1.b[2];
|
||||
out_p[3] = p1.b[3];
|
||||
|
||||
//out_p[0] = ( in_p[0] + in_p[4] ) >> 1;
|
||||
//out_p[1] = ( in_p[1] + in_p[5] ) >> 1;
|
||||
//out_p[2] = ( in_p[2] + in_p[6] ) >> 1;
|
||||
//out_p[3] = ( in_p[3] + in_p[7] ) >> 1;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
for( i = 0 ; i < height ; i++, in_p += row )
|
||||
{
|
||||
for( j = 0 ; j < width ; j++, out_p += 4, in_p += 8 )
|
||||
{
|
||||
convert_t p1;
|
||||
p1.b[0] = in_p[0];
|
||||
p1.b[1] = in_p[1];
|
||||
p1.b[2] = in_p[2];
|
||||
p1.b[3] = in_p[3];
|
||||
|
||||
convert_t p2;
|
||||
p2.b[0] = in_p[4];
|
||||
p2.b[1] = in_p[5];
|
||||
p2.b[2] = in_p[6];
|
||||
p2.b[3] = in_p[7];
|
||||
|
||||
convert_t p3;
|
||||
p3.b[0] = in_p[row + 0];
|
||||
p3.b[1] = in_p[row + 1];
|
||||
p3.b[2] = in_p[row + 2];
|
||||
p3.b[3] = in_p[row + 3];
|
||||
|
||||
convert_t p4;
|
||||
p4.b[0] = in_p[row + 4];
|
||||
p4.b[1] = in_p[row + 5];
|
||||
p4.b[2] = in_p[row + 6];
|
||||
p4.b[3] = in_p[row + 7];
|
||||
|
||||
float c1[3];
|
||||
r11g11b10f_to_float3( p1.i, c1 );
|
||||
|
||||
float c2[3];
|
||||
r11g11b10f_to_float3( p2.i, c2 );
|
||||
|
||||
float c3[3];
|
||||
r11g11b10f_to_float3( p3.i, c3 );
|
||||
|
||||
float c4[3];
|
||||
r11g11b10f_to_float3( p4.i, c4 );
|
||||
|
||||
float rgb[3];
|
||||
rgb[0] = ( c1[0] + c2[0] + c3[0] + c4[0] ) * 0.25f;
|
||||
rgb[1] = ( c1[1] + c2[1] + c3[1] + c4[1] ) * 0.25f;
|
||||
rgb[2] = ( c1[2] + c2[2] + c3[2] + c4[2] ) * 0.25f;
|
||||
|
||||
p1.i = float3_to_r11g11b10f( rgb );
|
||||
|
||||
out_p[0] = p1.b[0];
|
||||
out_p[1] = p1.b[1];
|
||||
out_p[2] = p1.b[2];
|
||||
out_p[3] = p1.b[3];
|
||||
|
||||
//out_p[0] = ( in_p[0] + in_p[4] + in_p[row + 0] + in_p[row + 4] ) >> 2;
|
||||
//out_p[1] = ( in_p[1] + in_p[5] + in_p[row + 1] + in_p[row + 5] ) >> 2;
|
||||
//out_p[2] = ( in_p[2] + in_p[6] + in_p[row + 2] + in_p[row + 6] ) >> 2;
|
||||
//out_p[3] = ( in_p[3] + in_p[7] + in_p[row + 3] + in_p[row + 7] ) >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
// RB end
|
||||
|
||||
/*
|
||||
==================
|
||||
R_BlendOverTexture
|
||||
|
|
|
@ -1293,7 +1293,7 @@ void idMaterial::ParseFragmentMap( idLexer& src, newShaderStage_t* newStage )
|
|||
if( !token.Icmp( "hdriMap" ) )
|
||||
{
|
||||
cubeMap = CF_PANORAMA;
|
||||
td = TD_R11G11B10F;
|
||||
td = TD_HDRI;
|
||||
continue;
|
||||
}
|
||||
if( !token.Icmp( "nearest" ) )
|
||||
|
@ -1832,7 +1832,7 @@ void idMaterial::ParseStage( idLexer& src, const textureRepeat_t trpDefault )
|
|||
str = R_ParsePastImageProgram( src );
|
||||
idStr::Copynz( imageName, str, sizeof( imageName ) );
|
||||
cubeMap = CF_PANORAMA;
|
||||
td = TD_R11G11B10F;
|
||||
td = TD_HDRI;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1133,7 +1133,14 @@ CONSOLE_COMMAND_SHIP( bakeEnvironmentProbes, "Bake environment probes", NULL )
|
|||
}
|
||||
|
||||
// generate .bimage file
|
||||
globalImages->ImageFromFile( job->filename, TF_LINEAR, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||
if( job->outHeight == RADIANCE_OCTAHEDRON_SIZE )
|
||||
{
|
||||
globalImages->ImageFromFile( job->filename, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||
}
|
||||
else
|
||||
{
|
||||
globalImages->ImageFromFile( job->filename, TF_LINEAR, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||
}
|
||||
|
||||
Mem_Free( job->outBuffer );
|
||||
|
||||
|
|
|
@ -497,7 +497,8 @@ void idRenderWorldLocal::WriteLightGrid( idFile* fp, const LightGrid& lightGrid
|
|||
{
|
||||
const lightGridPoint_t* gridPoint = &lightGrid.lightGridPoints[i];
|
||||
|
||||
fp->WriteFloatString( "/* lgp %i */ %d ( %f %f %f )", i, ( int )gridPoint->valid, gridPoint->origin[0], gridPoint->origin[1], gridPoint->origin[2] );
|
||||
//fp->WriteFloatString( "/* lgp %i */ %d ( %f %f %f )", i, ( int )gridPoint->valid, gridPoint->origin[0], gridPoint->origin[1], gridPoint->origin[2] );
|
||||
fp->WriteFloatString( " %d ( %f %f %f )", ( int )gridPoint->valid, gridPoint->origin[0], gridPoint->origin[1], gridPoint->origin[2] );
|
||||
|
||||
#if STORE_LIGHTGRID_SHDATA
|
||||
// spherical harmonic
|
||||
|
|
Loading…
Reference in a new issue