mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-06-01 17:22:34 +00:00
Implemented GGX Split Sum approximation using a 2D atlas trick
This commit is contained in:
parent
779534626f
commit
2391ba1b43
14 changed files with 845 additions and 372 deletions
|
@ -1,11 +1,11 @@
|
||||||
astyle.exe -v --formatted --options=astyle-options.ini --exclude="libs" --exclude="extern" --recursive *.h
|
astyle.exe -v --formatted --options=astyle-options.ini --exclude="libs" --exclude="extern" --recursive *.h
|
||||||
astyle.exe -v --formatted --options=astyle-options.ini --exclude="libs" --exclude="extern" --exclude="d3xp/gamesys/SysCvar.cpp" --exclude="d3xp/gamesys/Callbacks.cpp" --exclude="sys/win32/win_cpu.cpp" --exclude="sys/win32/win_main.cpp" --recursive *.cpp
|
astyle.exe -v --formatted --options=astyle-options.ini --exclude="libs" --exclude="extern" --exclude="d3xp/gamesys/SysCvar.cpp" --exclude="d3xp/gamesys/Callbacks.cpp" --exclude="sys/win32/win_cpu.cpp" --exclude="sys/win32/win_main.cpp" --recursive *.cpp
|
||||||
|
|
||||||
REM astyle.exe -v --formatted --options=astyle-options.ini --recursive libs/imgui/*.h
|
astyle.exe -v --formatted --options=astyle-options.ini --recursive libs/imgui/*.h
|
||||||
REM astyle.exe -v --formatted --options=astyle-options.ini --recursive libs/imgui/*.cpp
|
astyle.exe -v --formatted --options=astyle-options.ini --recursive libs/imgui/*.cpp
|
||||||
|
|
||||||
REM astyle.exe -v --formatted --options=astyle-options.ini --recursive libs/stb/*.h
|
astyle.exe -v --formatted --options=astyle-options.ini --recursive libs/stb/*.h
|
||||||
REM astyle.exe -v --formatted --options=astyle-options.ini --recursive libs/tinyexr/*.h
|
astyle.exe -v --formatted --options=astyle-options.ini --recursive libs/tinyexr/*.h
|
||||||
|
|
||||||
astyle.exe -v -Q --options=astyle-options.ini --recursive ../base/renderprogs/*.hlsl
|
astyle.exe -v -Q --options=astyle-options.ini --recursive ../base/renderprogs/*.hlsl
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
Doom 3 BFG Edition GPL Source Code
|
Doom 3 BFG Edition GPL Source Code
|
||||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||||
Copyright (C) 2014-2016 Robert Beckebans
|
Copyright (C) 2014-2021 Robert Beckebans
|
||||||
Copyright (C) 2014-2016 Kot in Action Creative Artel
|
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").
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||||
|
@ -43,6 +43,8 @@ If you have questions concerning this license or the applicable additional terms
|
||||||
#include "DXT/DXTCodec.h"
|
#include "DXT/DXTCodec.h"
|
||||||
#include "Color/ColorSpace.h"
|
#include "Color/ColorSpace.h"
|
||||||
|
|
||||||
|
#include "../libs/mesa/format_r11g11b10f.h"
|
||||||
|
|
||||||
idCVar image_highQualityCompression( "image_highQualityCompression", "0", CVAR_BOOL, "Use high quality (slow) compression" );
|
idCVar image_highQualityCompression( "image_highQualityCompression", "0", CVAR_BOOL, "Use high quality (slow) compression" );
|
||||||
idCVar r_useHighQualitySky( "r_useHighQualitySky", "1", CVAR_BOOL | CVAR_ARCHIVE, "Use high quality skyboxes" );
|
idCVar r_useHighQualitySky( "r_useHighQualitySky", "1", CVAR_BOOL | CVAR_ARCHIVE, "Use high quality skyboxes" );
|
||||||
|
|
||||||
|
@ -303,6 +305,319 @@ void idBinaryImage::Load2DFromMemory( int width, int height, const byte* pic_con
|
||||||
Mem_Free( pic );
|
Mem_Free( pic );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
========================
|
||||||
|
RB idBinaryImage::Load2DAtlasMipchainFromMemory
|
||||||
|
========================
|
||||||
|
*/
|
||||||
|
void idBinaryImage::Load2DAtlasMipchainFromMemory( int width, int height, const byte* pic_const, int numLevels, textureFormat_t& textureFormat, textureColor_t& colorFormat )
|
||||||
|
{
|
||||||
|
int sourceWidth = width * ( 2.0f / 3.0f ); // RB
|
||||||
|
|
||||||
|
fileData.textureType = TT_2D;
|
||||||
|
fileData.format = textureFormat;
|
||||||
|
fileData.colorFormat = CFM_DEFAULT;
|
||||||
|
fileData.width = sourceWidth;
|
||||||
|
fileData.height = height;
|
||||||
|
fileData.numLevels = numLevels;
|
||||||
|
|
||||||
|
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d)", width, height ) );
|
||||||
|
|
||||||
|
byte* sourcePic = ( byte* )Mem_Alloc( width * height * 4, TAG_TEMP );
|
||||||
|
memcpy( sourcePic, pic_const, width * height * 4 );
|
||||||
|
|
||||||
|
if( colorFormat == CFM_YCOCG_DXT5 )
|
||||||
|
{
|
||||||
|
// convert the image data to YCoCg and use the YCoCgDXT5 compressor
|
||||||
|
idColorSpace::ConvertRGBToCoCg_Y( sourcePic, sourcePic, width, height );
|
||||||
|
}
|
||||||
|
else if( colorFormat == CFM_NORMAL_DXT5 )
|
||||||
|
{
|
||||||
|
// Blah, HQ swizzles automatically, Fast doesn't
|
||||||
|
if( !image_highQualityCompression.GetBool() )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < width * height; i++ )
|
||||||
|
{
|
||||||
|
sourcePic[i * 4 + 3] = sourcePic[i * 4 + 0];
|
||||||
|
sourcePic[i * 4 + 0] = 0;
|
||||||
|
sourcePic[i * 4 + 2] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( colorFormat == CFM_GREEN_ALPHA )
|
||||||
|
{
|
||||||
|
for( int i = 0; i < width * height; i++ )
|
||||||
|
{
|
||||||
|
sourcePic[i * 4 + 1] = sourcePic[i * 4 + 3];
|
||||||
|
sourcePic[i * 4 + 0] = 0;
|
||||||
|
sourcePic[i * 4 + 2] = 0;
|
||||||
|
sourcePic[i * 4 + 3] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
images.SetNum( numLevels );
|
||||||
|
|
||||||
|
const int numColors = 5;
|
||||||
|
static idVec4 colors[numColors] = { colorBlue, colorCyan, colorGreen, colorYellow, colorRed };
|
||||||
|
|
||||||
|
for( int level = 0; level < images.Num(); level++ )
|
||||||
|
{
|
||||||
|
idBinaryImageData& img = images[ level ];
|
||||||
|
|
||||||
|
// RB: create shrunk image which is a copy of the sub image in the atlas
|
||||||
|
idVec4 rect = R_CalculateMipRect( sourceWidth, level );
|
||||||
|
|
||||||
|
int scaledWidth = rect.z;
|
||||||
|
int scaledHeight = rect.w;
|
||||||
|
|
||||||
|
byte* pic = ( byte* )Mem_Alloc( scaledWidth * scaledHeight * 4, TAG_TEMP );
|
||||||
|
|
||||||
|
for( int x = rect.x; x < ( rect.x + rect.z ); x++ )
|
||||||
|
//for( int x = 0; x < rect.z; x++ )
|
||||||
|
{
|
||||||
|
for( int y = rect.y; y < ( rect.y + rect.w ); y++ )
|
||||||
|
//for( int y = 0; y < rect.w; y++ )
|
||||||
|
{
|
||||||
|
int sx = x - rect.x;
|
||||||
|
int sy = y - rect.y;
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
pic[( sy * scaledWidth + sx ) * 4 + 0] = sourcePic[( y * width + x ) * 4 + 0];
|
||||||
|
pic[( sy * scaledWidth + sx ) * 4 + 1] = sourcePic[( y * width + x ) * 4 + 1];
|
||||||
|
pic[( sy * scaledWidth + sx ) * 4 + 2] = sourcePic[( y * width + x ) * 4 + 2];
|
||||||
|
pic[( sy * scaledWidth + sx ) * 4 + 3] = sourcePic[( y * width + x ) * 4 + 3];
|
||||||
|
#else
|
||||||
|
int colorIdx = level % numColors;
|
||||||
|
float color[3];
|
||||||
|
color[0] = colors[ colorIdx ].x;
|
||||||
|
color[0] = colors[ colorIdx ].y;
|
||||||
|
color[0] = colors[ colorIdx ].z;
|
||||||
|
|
||||||
|
uint32_t value = float3_to_r11g11b10f( color );
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32 i;
|
||||||
|
byte b[4];
|
||||||
|
} tmp;
|
||||||
|
|
||||||
|
tmp.i = value;
|
||||||
|
|
||||||
|
//*( uint32_t* )pic[( sy * scaledWidth + sx ) * 3] = value;
|
||||||
|
|
||||||
|
pic[( sy * scaledWidth + sx ) * 4 + 0] = tmp.b[0];
|
||||||
|
pic[( sy * scaledWidth + sx ) * 4 + 1] = tmp.b[1];
|
||||||
|
pic[( sy * scaledWidth + sx ) * 4 + 2] = tmp.b[2];
|
||||||
|
pic[( sy * scaledWidth + sx ) * 4 + 3] = tmp.b[3];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// RB end
|
||||||
|
|
||||||
|
commonLocal.LoadPacifierBinarizeMiplevel( level + 1, numLevels );
|
||||||
|
|
||||||
|
// Images that are going to be DXT compressed and aren't multiples of 4 need to be
|
||||||
|
// padded out before compressing.
|
||||||
|
byte* dxtPic = pic;
|
||||||
|
int dxtWidth = 0;
|
||||||
|
int dxtHeight = 0;
|
||||||
|
if( textureFormat == FMT_DXT5 || textureFormat == FMT_DXT1 )
|
||||||
|
{
|
||||||
|
if( ( scaledWidth & 3 ) || ( scaledHeight & 3 ) )
|
||||||
|
{
|
||||||
|
dxtWidth = ( scaledWidth + 3 ) & ~3;
|
||||||
|
dxtHeight = ( scaledHeight + 3 ) & ~3;
|
||||||
|
dxtPic = ( byte* )Mem_ClearedAlloc( dxtWidth * 4 * dxtHeight, TAG_IMAGE );
|
||||||
|
for( int i = 0; i < scaledHeight; i++ )
|
||||||
|
{
|
||||||
|
memcpy( dxtPic + i * dxtWidth * 4, pic + i * scaledWidth * 4, scaledWidth * 4 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dxtPic = pic;
|
||||||
|
dxtWidth = scaledWidth;
|
||||||
|
dxtHeight = scaledHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
img.level = level;
|
||||||
|
img.destZ = 0;
|
||||||
|
img.width = scaledWidth;
|
||||||
|
img.height = scaledHeight;
|
||||||
|
|
||||||
|
// compress data or convert floats as necessary
|
||||||
|
if( textureFormat == FMT_DXT1 )
|
||||||
|
{
|
||||||
|
idDxtEncoder dxt;
|
||||||
|
img.Alloc( dxtWidth * dxtHeight / 2 );
|
||||||
|
if( image_highQualityCompression.GetBool() )
|
||||||
|
{
|
||||||
|
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - DXT1HQ", width, height ) );
|
||||||
|
|
||||||
|
dxt.CompressImageDXT1HQ( dxtPic, img.data, dxtWidth, dxtHeight );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - DXT1Fast", width, height ) );
|
||||||
|
|
||||||
|
dxt.CompressImageDXT1Fast( dxtPic, img.data, dxtWidth, dxtHeight );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( textureFormat == FMT_DXT5 )
|
||||||
|
{
|
||||||
|
idDxtEncoder dxt;
|
||||||
|
img.Alloc( dxtWidth * dxtHeight );
|
||||||
|
if( colorFormat == CFM_NORMAL_DXT5 )
|
||||||
|
{
|
||||||
|
if( image_highQualityCompression.GetBool() )
|
||||||
|
{
|
||||||
|
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - NormalMapDXT5HQ", width, height ) );
|
||||||
|
|
||||||
|
dxt.CompressNormalMapDXT5HQ( dxtPic, img.data, dxtWidth, dxtHeight );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - NormalMapDXT5Fast", width, height ) );
|
||||||
|
|
||||||
|
dxt.CompressNormalMapDXT5Fast( dxtPic, img.data, dxtWidth, dxtHeight );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( colorFormat == CFM_YCOCG_DXT5 )
|
||||||
|
{
|
||||||
|
if( image_highQualityCompression.GetBool() )
|
||||||
|
{
|
||||||
|
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - YCoCgDXT5HQ", width, height ) );
|
||||||
|
|
||||||
|
dxt.CompressYCoCgDXT5HQ( dxtPic, img.data, dxtWidth, dxtHeight );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - YCoCgDXT5Fast", width, height ) );
|
||||||
|
|
||||||
|
dxt.CompressYCoCgDXT5Fast( dxtPic, img.data, dxtWidth, dxtHeight );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fileData.colorFormat = colorFormat = CFM_DEFAULT;
|
||||||
|
if( image_highQualityCompression.GetBool() )
|
||||||
|
{
|
||||||
|
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - DXT5HQ", width, height ) );
|
||||||
|
|
||||||
|
dxt.CompressImageDXT5HQ( dxtPic, img.data, dxtWidth, dxtHeight );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
commonLocal.LoadPacifierBinarizeInfo( va( "(%d x %d) - DXT5Fast", width, height ) );
|
||||||
|
|
||||||
|
dxt.CompressImageDXT5Fast( dxtPic, img.data, dxtWidth, dxtHeight );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( textureFormat == FMT_LUM8 || textureFormat == FMT_INT8 )
|
||||||
|
{
|
||||||
|
// LUM8 and INT8 just read the red channel
|
||||||
|
img.Alloc( scaledWidth * scaledHeight );
|
||||||
|
for( int i = 0; i < img.dataSize; i++ )
|
||||||
|
{
|
||||||
|
img.data[ i ] = pic[ i * 4 ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( textureFormat == FMT_ALPHA )
|
||||||
|
{
|
||||||
|
// ALPHA reads the alpha channel
|
||||||
|
img.Alloc( scaledWidth * scaledHeight );
|
||||||
|
for( int i = 0; i < img.dataSize; i++ )
|
||||||
|
{
|
||||||
|
img.data[ i ] = pic[ i * 4 + 3 ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( textureFormat == FMT_L8A8 )
|
||||||
|
{
|
||||||
|
// L8A8 reads the alpha and red channels
|
||||||
|
img.Alloc( scaledWidth * scaledHeight * 2 );
|
||||||
|
for( int i = 0; i < img.dataSize / 2; i++ )
|
||||||
|
{
|
||||||
|
img.data[ i * 2 + 0 ] = pic[ i * 4 + 0 ];
|
||||||
|
img.data[ i * 2 + 1 ] = pic[ i * 4 + 3 ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( textureFormat == FMT_RGB565 )
|
||||||
|
{
|
||||||
|
img.Alloc( scaledWidth * scaledHeight * 2 );
|
||||||
|
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 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
|
||||||
|
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;
|
||||||
|
img.Alloc( scaledWidth * scaledHeight * 4 );
|
||||||
|
for( int i = 0; i < img.dataSize; i++ )
|
||||||
|
{
|
||||||
|
img.data[ i ] = pic[ i ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we had to pad to quads, free the padded version
|
||||||
|
if( pic != dxtPic )
|
||||||
|
{
|
||||||
|
Mem_Free( dxtPic );
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Mem_Free( sourcePic );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
========================
|
========================
|
||||||
PadImageTo4x4
|
PadImageTo4x4
|
||||||
|
|
|
@ -53,6 +53,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void Load2DFromMemory( int width, int height, const byte* pic_const, int numLevels, textureFormat_t& textureFormat, textureColor_t& colorFormat, bool gammaMips );
|
void Load2DFromMemory( int width, int height, const byte* pic_const, int numLevels, textureFormat_t& textureFormat, textureColor_t& colorFormat, bool gammaMips );
|
||||||
|
void Load2DAtlasMipchainFromMemory( int width, int height, const byte* pic_const, int numLevels, textureFormat_t& textureFormat, textureColor_t& colorFormat );
|
||||||
void LoadCubeFromMemory( int width, const byte* pics[6], int numLevels, textureFormat_t& textureFormat, bool gammaMips );
|
void LoadCubeFromMemory( int width, const byte* pics[6], int numLevels, textureFormat_t& textureFormat, bool gammaMips );
|
||||||
|
|
||||||
ID_TIME_T LoadFromGeneratedFile( ID_TIME_T sourceFileTime );
|
ID_TIME_T LoadFromGeneratedFile( ID_TIME_T sourceFileTime );
|
||||||
|
|
|
@ -35,7 +35,7 @@ static const int MAX_SSAO_BUFFERS = 2;
|
||||||
static const int MAX_HIERARCHICAL_ZBUFFERS = 6; // native resolution + 5 MIP LEVELS
|
static const int MAX_HIERARCHICAL_ZBUFFERS = 6; // native resolution + 5 MIP LEVELS
|
||||||
|
|
||||||
static const int RADIANCE_CUBEMAP_SIZE = 256;
|
static const int RADIANCE_CUBEMAP_SIZE = 256;
|
||||||
static const int IRRADIANCE_CUBEMAP_SIZE = 32;
|
static const int IRRADIANCE_CUBEMAP_SIZE = 128;
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 2048, 1024, 512, 512, 256 };
|
static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 2048, 1024, 512, 512, 256 };
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
Doom 3 BFG Edition GPL Source Code
|
Doom 3 BFG Edition GPL Source Code
|
||||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||||
Copyright (C) 2013-2017 Robert Beckebans
|
Copyright (C) 2013-2021 Robert Beckebans
|
||||||
Copyright (C) 2016-2017 Dustin Land
|
Copyright (C) 2016-2017 Dustin Land
|
||||||
|
|
||||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||||
|
@ -236,7 +236,9 @@ typedef enum
|
||||||
CF_2D, // not a cube map
|
CF_2D, // not a cube map
|
||||||
CF_NATIVE, // _px, _nx, _py, etc, directly sent to GL
|
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_CAMERA, // _forward, _back, etc, rotated and flipped as needed before sending to GL
|
||||||
CF_2D_ARRAY // not a cube map but not a single 2d texture either
|
CF_PANORAMA, // TODO 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
|
||||||
} cubeFiles_t;
|
} cubeFiles_t;
|
||||||
|
|
||||||
enum imageFileType_t
|
enum imageFileType_t
|
||||||
|
@ -643,6 +645,9 @@ void R_VerticalFlip( byte* data, int width, int height );
|
||||||
void R_RotatePic( byte* data, int width );
|
void R_RotatePic( byte* data, int width );
|
||||||
void R_ApplyCubeMapTransforms( int i, byte* data, int size );
|
void R_ApplyCubeMapTransforms( int i, byte* data, int size );
|
||||||
|
|
||||||
|
idVec4 R_CalculateMipRect( uint dimensions, uint mip );
|
||||||
|
int R_CalculateUsedAtlasPixels( int dimensions );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
====================================================================
|
====================================================================
|
||||||
|
|
||||||
|
|
|
@ -981,6 +981,9 @@ static void LoadEXR( const char* filename, unsigned char** pic, int* width, int*
|
||||||
free( rgba );
|
free( rgba );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RB: EXR needs to be flipped to match the .tga behavior
|
||||||
|
//R_VerticalFlip( *pic, *width, *height );
|
||||||
|
|
||||||
Mem_Free( ( void* )fbuffer );
|
Mem_Free( ( void* )fbuffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1056,8 +1056,8 @@ void idImageManager::CreateIntrinsicImages()
|
||||||
|
|
||||||
// RB begin
|
// RB begin
|
||||||
// FIXME change back to TF_DEFAULT
|
// FIXME change back to TF_DEFAULT
|
||||||
defaultUACIrradianceCube = ImageFromFile( "env/UAC3_amb", TF_NEAREST, TR_CLAMP, TD_R11G11B10F, CF_2D );
|
defaultUACIrradianceCube = ImageFromFile( "env/UAC5_amb", TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||||
defaultUACRadianceCube = ImageFromFile( "env/UAC3_spec", TF_NEAREST, TR_CLAMP, TD_R11G11B10F, CF_2D );
|
defaultUACRadianceCube = ImageFromFile( "env/UAC5_spec", TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||||
// RB end
|
// RB end
|
||||||
|
|
||||||
release_assert( loadingIconImage->referencedOutsideLevelLoad );
|
release_assert( loadingIconImage->referencedOutsideLevelLoad );
|
||||||
|
|
|
@ -319,7 +319,7 @@ void idImage::ActuallyLoadImage( bool fromBackEnd )
|
||||||
{
|
{
|
||||||
opts.textureType = TT_2D_ARRAY;
|
opts.textureType = TT_2D_ARRAY;
|
||||||
}
|
}
|
||||||
else if( cubeFiles != CF_2D )
|
else if( cubeFiles == CF_NATIVE || cubeFiles == CF_CAMERA )
|
||||||
{
|
{
|
||||||
opts.textureType = TT_CUBIC;
|
opts.textureType = TT_CUBIC;
|
||||||
repeat = TR_CLAMP;
|
repeat = TR_CLAMP;
|
||||||
|
@ -439,7 +439,7 @@ void idImage::ActuallyLoadImage( bool fromBackEnd )
|
||||||
//else if( toolUsage )
|
//else if( toolUsage )
|
||||||
// binarizeReason = va( "binarize: tool usage '%s'", generatedName.c_str() );
|
// binarizeReason = va( "binarize: tool usage '%s'", generatedName.c_str() );
|
||||||
|
|
||||||
if( cubeFiles != CF_2D )
|
if( cubeFiles == CF_NATIVE || cubeFiles == CF_CAMERA )
|
||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
byte* pics[6];
|
byte* pics[6];
|
||||||
|
@ -520,6 +520,13 @@ void idImage::ActuallyLoadImage( bool fromBackEnd )
|
||||||
opts.width = width;
|
opts.width = width;
|
||||||
opts.height = height;
|
opts.height = height;
|
||||||
opts.numLevels = 0;
|
opts.numLevels = 0;
|
||||||
|
|
||||||
|
// RB
|
||||||
|
if( cubeFiles == CF_2D_PACKED_MIPCHAIN )
|
||||||
|
{
|
||||||
|
opts.width = width * ( 2.0f / 3.0f );
|
||||||
|
}
|
||||||
|
|
||||||
DeriveOpts();
|
DeriveOpts();
|
||||||
|
|
||||||
// foresthale 2014-05-30: give a nice progress display when binarizing
|
// foresthale 2014-05-30: give a nice progress display when binarizing
|
||||||
|
@ -547,7 +554,14 @@ void idImage::ActuallyLoadImage( bool fromBackEnd )
|
||||||
}
|
}
|
||||||
|
|
||||||
// RB: convert to compressed DXT or whatever choosen target format
|
// RB: convert to compressed DXT or whatever choosen target format
|
||||||
im.Load2DFromMemory( opts.width, opts.height, pic, opts.numLevels, opts.format, opts.colorFormat, opts.gammaMips );
|
if( cubeFiles == CF_2D_PACKED_MIPCHAIN )
|
||||||
|
{
|
||||||
|
im.Load2DAtlasMipchainFromMemory( width, opts.height, pic, opts.numLevels, opts.format, opts.colorFormat );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
im.Load2DFromMemory( opts.width, opts.height, pic, opts.numLevels, opts.format, opts.colorFormat, opts.gammaMips );
|
||||||
|
}
|
||||||
commonLocal.LoadPacifierBinarizeEnd();
|
commonLocal.LoadPacifierBinarizeEnd();
|
||||||
|
|
||||||
Mem_Free( pic );
|
Mem_Free( pic );
|
||||||
|
@ -650,6 +664,7 @@ void idImage::Print() const
|
||||||
NAME_FORMAT( RGBA16F );
|
NAME_FORMAT( RGBA16F );
|
||||||
NAME_FORMAT( RGBA32F );
|
NAME_FORMAT( RGBA32F );
|
||||||
NAME_FORMAT( R32F );
|
NAME_FORMAT( R32F );
|
||||||
|
NAME_FORMAT( R11G11B10F );
|
||||||
// RB end
|
// RB end
|
||||||
NAME_FORMAT( DEPTH );
|
NAME_FORMAT( DEPTH );
|
||||||
NAME_FORMAT( X16 );
|
NAME_FORMAT( X16 );
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
Doom 3 BFG Edition GPL Source Code
|
Doom 3 BFG Edition GPL Source Code
|
||||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||||
|
Copyright (C) 2021 Robert Beckebans
|
||||||
|
|
||||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||||
|
|
||||||
|
@ -570,3 +571,35 @@ void R_ApplyCubeMapTransforms( int iter, byte* data, int size )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This is the most efficient way to atlas a mip chain to a 2d texture
|
||||||
|
// https://twitter.com/SebAaltonen/status/1327188239451611139
|
||||||
|
|
||||||
|
idVec4 R_CalculateMipRect( uint dimensions, uint mip )
|
||||||
|
{
|
||||||
|
uint pixels_mip = dimensions >> mip;
|
||||||
|
idVec4 uv_rect = idVec4( 0, 0, pixels_mip, pixels_mip );
|
||||||
|
|
||||||
|
if( mip > 0 )
|
||||||
|
{
|
||||||
|
uv_rect.x = dimensions;
|
||||||
|
uv_rect.y = dimensions - pixels_mip * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return uv_rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
int R_CalculateUsedAtlasPixels( int dimensions )
|
||||||
|
{
|
||||||
|
int numPixels = 0;
|
||||||
|
const int numMips = idMath::BitsForInteger( dimensions );
|
||||||
|
|
||||||
|
for( int mip = 0; mip < numMips; mip++ )
|
||||||
|
{
|
||||||
|
idVec4 dstRect = R_CalculateMipRect( dimensions, mip );
|
||||||
|
|
||||||
|
numPixels += ( dstRect.z * dstRect.w );
|
||||||
|
}
|
||||||
|
|
||||||
|
return numPixels;
|
||||||
|
}
|
||||||
|
|
|
@ -2096,6 +2096,11 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( viewDef->renderView.rdflags & RDF_NOAMBIENT )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined( USE_VULKAN )
|
#if defined( USE_VULKAN )
|
||||||
if( fillGbuffer )
|
if( fillGbuffer )
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
Doom 3 BFG Edition GPL Source Code
|
Doom 3 BFG Edition GPL Source Code
|
||||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||||
Copyright (C) 2012-2020 Robert Beckebans
|
Copyright (C) 2012-2021 Robert Beckebans
|
||||||
Copyright (C) 2014-2016 Kot in Action Creative Artel
|
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").
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||||
|
|
|
@ -838,6 +838,24 @@ void R_ReadTiledPixels( int width, int height, byte* buffer, renderView_t* ref =
|
||||||
glPixelStorei( GL_PACK_ROW_LENGTH, RADIANCE_CUBEMAP_SIZE );
|
glPixelStorei( GL_PACK_ROW_LENGTH, RADIANCE_CUBEMAP_SIZE );
|
||||||
glReadPixels( 0, 0, w, h, GL_RGB, GL_HALF_FLOAT, buffer );
|
glReadPixels( 0, 0, w, h, GL_RGB, GL_HALF_FLOAT, buffer );
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// TODO vertical flip with half floats
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
uint64 temp;
|
||||||
|
|
||||||
|
for( i = 0 ; i < width ; i++ )
|
||||||
|
{
|
||||||
|
for( j = 0 ; j < height / 2 ; j++ )
|
||||||
|
{
|
||||||
|
temp = *( ( uint64* )buffer + j * width + i );
|
||||||
|
*( ( uint64* )buffer + j * width + i ) = *( ( uint64* )buffer + ( height - 1 - j ) * width + i );
|
||||||
|
*( ( uint64* )buffer + ( height - 1 - j ) * width + i ) = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Framebuffer::Unbind();
|
Framebuffer::Unbind();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -769,10 +769,10 @@ void R_DeriveEnvprobeData( RenderEnvprobeLocal* probe )
|
||||||
|
|
||||||
// TODO get preconvolved cubemaps
|
// TODO get preconvolved cubemaps
|
||||||
fullname.Format( "env/%s/envprobe%i_amb", basename.c_str(), probeIndex );
|
fullname.Format( "env/%s/envprobe%i_amb", basename.c_str(), probeIndex );
|
||||||
probe->irradianceImage = globalImages->ImageFromFile( fullname, TF_NEAREST, TR_CLAMP, TD_R11G11B10F, CF_2D );
|
probe->irradianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||||
|
|
||||||
fullname.Format( "env/%s/envprobe%i_spec", basename.c_str(), probeIndex );
|
fullname.Format( "env/%s/envprobe%i_spec", basename.c_str(), probeIndex );
|
||||||
probe->radianceImage = globalImages->ImageFromFile( fullname, TF_NEAREST, TR_CLAMP, TD_R11G11B10F, CF_2D );
|
probe->radianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN );
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
// compute the light projection matrix
|
// compute the light projection matrix
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/*
|
/*
|
||||||
===========================================================================
|
===========================================================================
|
||||||
|
|
||||||
Doom 3 BFG Edition GPL Source Code
|
Doom 3 BFG Edition GPL Source Code
|
||||||
|
@ -496,6 +496,439 @@ idVec2 IntegrateBRDF( float NdotV, float roughness, int sampleCount )
|
||||||
return idVec2( A, B );
|
return idVec2( A, B );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Compute normalized oct coord, mapping top left of top left pixel to (-1,-1)
|
||||||
|
idVec2 NormalizedOctCoord( int x, int y, const int probeSideLength )
|
||||||
|
{
|
||||||
|
const int margin = 0;
|
||||||
|
|
||||||
|
int probeWithBorderSide = probeSideLength + margin;
|
||||||
|
|
||||||
|
idVec2 octFragCoord = idVec2( ( x - margin ) % probeWithBorderSide, ( y - margin ) % probeWithBorderSide );
|
||||||
|
|
||||||
|
// Add back the half pixel to get pixel center normalized coordinates
|
||||||
|
return ( idVec2( octFragCoord ) + idVec2( 0.5f, 0.5f ) ) * ( 2.0f / float( probeSideLength ) ) - idVec2( 1.0f, 1.0f );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
R_MakeAmbientMap_f
|
||||||
|
|
||||||
|
R_MakeAmbientMap_f <basename> [size]
|
||||||
|
|
||||||
|
Saves out env/<basename>_amb_ft.tga, etc
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void R_MakeAmbientMap( const char* baseName, const char* suffix, int outSize, bool specular )
|
||||||
|
{
|
||||||
|
idStr fullname;
|
||||||
|
renderView_t ref;
|
||||||
|
viewDef_t primary;
|
||||||
|
byte* buffers[6];
|
||||||
|
int width = 0, height = 0;
|
||||||
|
|
||||||
|
memset( &cubeAxis, 0, sizeof( cubeAxis ) );
|
||||||
|
cubeAxis[0][0][0] = 1;
|
||||||
|
cubeAxis[0][1][2] = 1;
|
||||||
|
cubeAxis[0][2][1] = 1;
|
||||||
|
|
||||||
|
cubeAxis[1][0][0] = -1;
|
||||||
|
cubeAxis[1][1][2] = -1;
|
||||||
|
cubeAxis[1][2][1] = 1;
|
||||||
|
|
||||||
|
cubeAxis[2][0][1] = 1;
|
||||||
|
cubeAxis[2][1][0] = -1;
|
||||||
|
cubeAxis[2][2][2] = -1;
|
||||||
|
|
||||||
|
cubeAxis[3][0][1] = -1;
|
||||||
|
cubeAxis[3][1][0] = -1;
|
||||||
|
cubeAxis[3][2][2] = 1;
|
||||||
|
|
||||||
|
cubeAxis[4][0][2] = 1;
|
||||||
|
cubeAxis[4][1][0] = -1;
|
||||||
|
cubeAxis[4][2][1] = 1;
|
||||||
|
|
||||||
|
cubeAxis[5][0][2] = -1;
|
||||||
|
cubeAxis[5][1][0] = 1;
|
||||||
|
cubeAxis[5][2][1] = 1;
|
||||||
|
|
||||||
|
// read all of the images
|
||||||
|
for( int i = 0 ; i < 6 ; i++ )
|
||||||
|
{
|
||||||
|
fullname.Format( "env/%s%s.exr", baseName, envDirection[i] );
|
||||||
|
|
||||||
|
const bool captureToImage = false;
|
||||||
|
common->UpdateScreen( captureToImage );
|
||||||
|
|
||||||
|
R_LoadImage( fullname, &buffers[i], &width, &height, NULL, true, NULL );
|
||||||
|
if( !buffers[i] )
|
||||||
|
{
|
||||||
|
common->Printf( "loading %s failed.\n", fullname.c_str() );
|
||||||
|
for( i-- ; i >= 0 ; i-- )
|
||||||
|
{
|
||||||
|
Mem_Free( buffers[i] );
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pacifier = true;
|
||||||
|
|
||||||
|
// resample with hemispherical blending
|
||||||
|
int samples = 1000;
|
||||||
|
|
||||||
|
int outWidth = int( outSize * 1.5f );
|
||||||
|
int outHeight = outSize;
|
||||||
|
|
||||||
|
//halfFloat_t* outBuffer = ( halfFloat_t* )_alloca( outSize * outSize * 3 * sizeof( halfFloat_t ) );
|
||||||
|
halfFloat_t* outBuffer = ( halfFloat_t* )R_StaticAlloc( idMath::Ceil( outSize * outSize * 3 * sizeof( halfFloat_t ) * 1.5f ), TAG_IMAGE );
|
||||||
|
|
||||||
|
{
|
||||||
|
// output an octahedron probe
|
||||||
|
|
||||||
|
CommandlineProgressBar progressBar( R_CalculateUsedAtlasPixels( outSize ) );
|
||||||
|
|
||||||
|
int start = Sys_Milliseconds();
|
||||||
|
|
||||||
|
const float invDstSize = 1.0f / float( outSize );
|
||||||
|
|
||||||
|
const int numMips = idMath::BitsForInteger( outSize );
|
||||||
|
|
||||||
|
// reset image to black
|
||||||
|
for( int x = 0; x < outWidth; x++ )
|
||||||
|
{
|
||||||
|
for( int y = 0; y < outHeight; y++ )
|
||||||
|
{
|
||||||
|
outBuffer[( y * outWidth + x ) * 3 + 0] = F32toF16( 0 );
|
||||||
|
outBuffer[( y * outWidth + x ) * 3 + 1] = F32toF16( 0 );
|
||||||
|
outBuffer[( y * outWidth + x ) * 3 + 2] = F32toF16( 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int mip = 0; mip < numMips; mip++ )
|
||||||
|
{
|
||||||
|
float roughness = ( float )mip / ( float )( numMips - 1 );
|
||||||
|
|
||||||
|
idVec4 dstRect = R_CalculateMipRect( outSize, mip );
|
||||||
|
|
||||||
|
for( int x = dstRect.x; x < ( dstRect.x + dstRect.z ); x++ )
|
||||||
|
{
|
||||||
|
for( int y = dstRect.y; y < ( dstRect.y + dstRect.w ); y++ )
|
||||||
|
{
|
||||||
|
idVec2 octCoord;
|
||||||
|
if( mip > 0 )
|
||||||
|
{
|
||||||
|
// move back to [0, 1] coords
|
||||||
|
octCoord = NormalizedOctCoord( x - dstRect.x, y - dstRect.y, dstRect.z );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
octCoord = NormalizedOctCoord( x, y, dstRect.z );
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert UV coord to 3D direction
|
||||||
|
idVec3 N;
|
||||||
|
|
||||||
|
N.FromOctahedral( octCoord );
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
// RB: Split Sum approximation explanation
|
||||||
|
|
||||||
|
// Epic Games makes a further approximation by assuming the view direction
|
||||||
|
// (and thus the specular reflection direction) to be equal to the output sample direction ωo.
|
||||||
|
// This translates itself to the following code:
|
||||||
|
const idVec3 R = N;
|
||||||
|
const idVec3 V = R;
|
||||||
|
|
||||||
|
idVec3 prefilteredColor( 0, 0, 0 );
|
||||||
|
|
||||||
|
if( specular )
|
||||||
|
{
|
||||||
|
float totalWeight = 0.0f;
|
||||||
|
|
||||||
|
for( int s = 0; s < samples; s++ )
|
||||||
|
{
|
||||||
|
idVec2 Xi = Hammersley2D( s, samples );
|
||||||
|
idVec3 H = ImportanceSampleGGX( Xi, N, roughness );
|
||||||
|
idVec3 L = ( 2.0 * ( H * ( V * H ) ) - V );
|
||||||
|
|
||||||
|
float NdotL = Max( ( N * L ), 0.0f );
|
||||||
|
if( NdotL > 0.0 )
|
||||||
|
{
|
||||||
|
float sample[3];
|
||||||
|
|
||||||
|
R_SampleCubeMapHDR( H, width, buffers, sample );
|
||||||
|
|
||||||
|
prefilteredColor[0] += sample[0] * NdotL;
|
||||||
|
prefilteredColor[1] += sample[1] * NdotL;
|
||||||
|
prefilteredColor[2] += sample[2] * NdotL;
|
||||||
|
|
||||||
|
totalWeight += NdotL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prefilteredColor[0] /= totalWeight;
|
||||||
|
prefilteredColor[1] /= totalWeight;
|
||||||
|
prefilteredColor[2] /= totalWeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for( int s = 0; s < samples; s++ )
|
||||||
|
{
|
||||||
|
idVec2 Xi = Hammersley2D( s, samples );
|
||||||
|
idVec3 H = ImportanceSampleGGX( Xi, N, 0.95f );
|
||||||
|
|
||||||
|
float sample[3];
|
||||||
|
|
||||||
|
R_SampleCubeMapHDR( H, width, buffers, sample );
|
||||||
|
|
||||||
|
prefilteredColor[0] += sample[0];
|
||||||
|
prefilteredColor[1] += sample[1];
|
||||||
|
prefilteredColor[2] += sample[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
prefilteredColor[0] /= samples;
|
||||||
|
prefilteredColor[1] /= samples;
|
||||||
|
prefilteredColor[2] /= samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
outBuffer[( y * outWidth + x ) * 3 + 0] = F32toF16( prefilteredColor[0] );
|
||||||
|
outBuffer[( y * outWidth + x ) * 3 + 1] = F32toF16( prefilteredColor[1] );
|
||||||
|
outBuffer[( y * outWidth + x ) * 3 + 2] = F32toF16( prefilteredColor[2] );
|
||||||
|
#else
|
||||||
|
outBuffer[( y * outWidth + x ) * 3 + 0] = F32toF16( ( N.x * 0.5f + 0.5f ) );
|
||||||
|
outBuffer[( y * outWidth + x ) * 3 + 1] = F32toF16( ( N.y * 0.5f + 0.5f ) );
|
||||||
|
outBuffer[( y * outWidth + x ) * 3 + 2] = F32toF16( ( N.z * 0.5f + 0.5f ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
progressBar.Increment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fullname.Format( "env/%s%s.exr", baseName, suffix );
|
||||||
|
//common->Printf( "writing %s\n", fullname.c_str() );
|
||||||
|
|
||||||
|
const bool captureToImage = false;
|
||||||
|
common->UpdateScreen( captureToImage );
|
||||||
|
|
||||||
|
//R_WriteTGA( fullname, outBuffer, outSize, outSize, false, "fs_basepath" );
|
||||||
|
//R_WritePNG( fullname, outBuffer, 4, outSize, outSize, true, "fs_basepath" );
|
||||||
|
R_WriteEXR( fullname, ( byte* )outBuffer, 3, outWidth, outHeight, "fs_basepath" );
|
||||||
|
|
||||||
|
int end = Sys_Milliseconds();
|
||||||
|
|
||||||
|
common->Printf( "env/%s convolved in %5.1f seconds\n\n", baseName, ( end - start ) * 0.001f );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int i = 0 ; i < 6 ; i++ )
|
||||||
|
{
|
||||||
|
if( buffers[i] )
|
||||||
|
{
|
||||||
|
Mem_Free( buffers[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Mem_Free( outBuffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
R_MakeAmbientMap_f
|
||||||
|
|
||||||
|
R_MakeAmbientMap_f <basename> [size]
|
||||||
|
|
||||||
|
Saves out env/<basename>_amb_ft.tga, etc
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
//void R_MakeAmbientMap_f( const idCmdArgs& args )
|
||||||
|
CONSOLE_COMMAND( makeAmbientMap, "Saves out env/<basename>_amb_ft.tga, etc", NULL )
|
||||||
|
{
|
||||||
|
const char* baseName;
|
||||||
|
int outSize;
|
||||||
|
float roughness;
|
||||||
|
|
||||||
|
if( args.Argc() != 2 && args.Argc() != 3 && args.Argc() != 4 )
|
||||||
|
{
|
||||||
|
common->Printf( "USAGE: makeAmbientMap <basename> [size]\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
baseName = args.Argv( 1 );
|
||||||
|
|
||||||
|
if( args.Argc() >= 3 )
|
||||||
|
{
|
||||||
|
outSize = atoi( args.Argv( 2 ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outSize = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( args.Argc() == 4 )
|
||||||
|
{
|
||||||
|
roughness = atof( args.Argv( 3 ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
roughness = 0.95f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( roughness > 0.8f )
|
||||||
|
{
|
||||||
|
R_MakeAmbientMap( baseName, "_amb", outSize, false );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
R_MakeAmbientMap( baseName, "_spec", outSize, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL )
|
||||||
|
{
|
||||||
|
idStr fullname;
|
||||||
|
idStr baseName;
|
||||||
|
idMat3 axis[6], oldAxis;
|
||||||
|
idVec3 oldPosition;
|
||||||
|
renderView_t ref;
|
||||||
|
int blends;
|
||||||
|
const char* extension;
|
||||||
|
int size;
|
||||||
|
int old_fov_x, old_fov_y;
|
||||||
|
|
||||||
|
static const char* envDirection[6] = { "_px", "_nx", "_py", "_ny", "_pz", "_nz" };
|
||||||
|
|
||||||
|
if( !tr.primaryWorld )
|
||||||
|
{
|
||||||
|
common->Printf( "No primary world loaded.\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
baseName = tr.primaryWorld->mapName;
|
||||||
|
baseName.StripFileExtension();
|
||||||
|
|
||||||
|
size = RADIANCE_CUBEMAP_SIZE;
|
||||||
|
blends = 1;
|
||||||
|
|
||||||
|
if( !tr.primaryView )
|
||||||
|
{
|
||||||
|
common->Printf( "No primary view.\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const viewDef_t primary = *tr.primaryView;
|
||||||
|
|
||||||
|
memset( &axis, 0, sizeof( axis ) );
|
||||||
|
|
||||||
|
// +X
|
||||||
|
axis[0][0][0] = 1;
|
||||||
|
axis[0][1][2] = 1;
|
||||||
|
axis[0][2][1] = 1;
|
||||||
|
|
||||||
|
// -X
|
||||||
|
axis[1][0][0] = -1;
|
||||||
|
axis[1][1][2] = -1;
|
||||||
|
axis[1][2][1] = 1;
|
||||||
|
|
||||||
|
// +Y
|
||||||
|
axis[2][0][1] = 1;
|
||||||
|
axis[2][1][0] = -1;
|
||||||
|
axis[2][2][2] = -1;
|
||||||
|
|
||||||
|
// -Y
|
||||||
|
axis[3][0][1] = -1;
|
||||||
|
axis[3][1][0] = -1;
|
||||||
|
axis[3][2][2] = 1;
|
||||||
|
|
||||||
|
// +Z
|
||||||
|
axis[4][0][2] = 1;
|
||||||
|
axis[4][1][0] = -1;
|
||||||
|
axis[4][2][1] = 1;
|
||||||
|
|
||||||
|
// -Z
|
||||||
|
axis[5][0][2] = -1;
|
||||||
|
axis[5][1][0] = 1;
|
||||||
|
axis[5][2][1] = 1;
|
||||||
|
|
||||||
|
//--------------------------------------------
|
||||||
|
// CAPTURE SCENE LIGHTING TO CUBEMAPS
|
||||||
|
//--------------------------------------------
|
||||||
|
|
||||||
|
// so we return to that axis and fov after the fact.
|
||||||
|
oldPosition = primary.renderView.vieworg;
|
||||||
|
oldAxis = primary.renderView.viewaxis;
|
||||||
|
old_fov_x = primary.renderView.fov_x;
|
||||||
|
old_fov_y = primary.renderView.fov_y;
|
||||||
|
|
||||||
|
for( int i = 0; i < tr.primaryWorld->envprobeDefs.Num(); i++ )
|
||||||
|
{
|
||||||
|
RenderEnvprobeLocal* def = tr.primaryWorld->envprobeDefs[i];
|
||||||
|
if( def == NULL )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int j = 0 ; j < 6 ; j++ )
|
||||||
|
{
|
||||||
|
ref = primary.renderView;
|
||||||
|
|
||||||
|
ref.rdflags = RDF_NOAMBIENT | RDF_IRRADIANCE;
|
||||||
|
ref.fov_x = ref.fov_y = 90;
|
||||||
|
|
||||||
|
ref.vieworg = def->parms.origin;
|
||||||
|
ref.viewaxis = axis[j];
|
||||||
|
|
||||||
|
extension = envDirection[ j ];
|
||||||
|
fullname.Format( "env/%s/envprobe%i%s", baseName.c_str(), i, extension );
|
||||||
|
|
||||||
|
tr.TakeScreenshot( size, size, fullname, blends, &ref, EXR );
|
||||||
|
//tr.CaptureRenderToFile( fullname, false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore the original axis and fov
|
||||||
|
/*
|
||||||
|
ref.vieworg = oldPosition;
|
||||||
|
ref.viewaxis = oldAxis;
|
||||||
|
ref.fov_x = old_fov_x;
|
||||||
|
ref.fov_y = old_fov_y;
|
||||||
|
cvarSystem->SetCVarInteger( "r_windowWidth", res_w );
|
||||||
|
cvarSystem->SetCVarInteger( "r_windowHeight", res_h );
|
||||||
|
R_SetNewMode( false ); // the same as "vid_restart"
|
||||||
|
*/
|
||||||
|
|
||||||
|
common->Printf( "Wrote a env set with the name %s\n", baseName.c_str() );
|
||||||
|
|
||||||
|
//--------------------------------------------
|
||||||
|
// CONVOLVE CUBEMAPS
|
||||||
|
//--------------------------------------------
|
||||||
|
|
||||||
|
int start = Sys_Milliseconds();
|
||||||
|
|
||||||
|
for( int i = 0; i < tr.primaryWorld->envprobeDefs.Num(); i++ )
|
||||||
|
{
|
||||||
|
RenderEnvprobeLocal* def = tr.primaryWorld->envprobeDefs[i];
|
||||||
|
if( def == NULL )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fullname.Format( "%s/envprobe%i", baseName.c_str(), i );
|
||||||
|
|
||||||
|
R_MakeAmbientMap( fullname.c_str(), "_amb", IRRADIANCE_CUBEMAP_SIZE, false );
|
||||||
|
R_MakeAmbientMap( fullname.c_str(), "_spec", RADIANCE_CUBEMAP_SIZE, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
int end = Sys_Milliseconds();
|
||||||
|
|
||||||
|
common->Printf( "convolved probes in %5.1f seconds\n\n", ( end - start ) * 0.001f );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//void R_MakeBrdfLut_f( const idCmdArgs& args )
|
//void R_MakeBrdfLut_f( const idCmdArgs& args )
|
||||||
CONSOLE_COMMAND( makeBrdfLUT, "make a GGX BRDF lookup table", NULL )
|
CONSOLE_COMMAND( makeBrdfLUT, "make a GGX BRDF lookup table", NULL )
|
||||||
{
|
{
|
||||||
|
@ -608,358 +1041,3 @@ static const unsigned char brfLutTexBytes[] =
|
||||||
Mem_Free( ldrBuffer );
|
Mem_Free( ldrBuffer );
|
||||||
Mem_Free( hdrBuffer );
|
Mem_Free( hdrBuffer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Compute normalized oct coord, mapping top left of top left pixel to (-1,-1)
|
|
||||||
idVec2 NormalizedOctCoord( int x, int y, const int probeSideLength )
|
|
||||||
{
|
|
||||||
const int margin = 0;
|
|
||||||
|
|
||||||
int probeWithBorderSide = probeSideLength + margin;
|
|
||||||
|
|
||||||
idVec2 octFragCoord = idVec2( ( x - margin ) % probeWithBorderSide, ( y - margin ) % probeWithBorderSide );
|
|
||||||
|
|
||||||
// Add back the half pixel to get pixel center normalized coordinates
|
|
||||||
return ( idVec2( octFragCoord ) + idVec2( 0.5f, 0.5f ) ) * ( 2.0f / float( probeSideLength ) ) - idVec2( 1.0f, 1.0f );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
==================
|
|
||||||
R_MakeAmbientMap_f
|
|
||||||
|
|
||||||
R_MakeAmbientMap_f <basename> [size]
|
|
||||||
|
|
||||||
Saves out env/<basename>_amb_ft.tga, etc
|
|
||||||
==================
|
|
||||||
*/
|
|
||||||
void R_MakeAmbientMap( const char* baseName, const char* suffix, int outSize, float roughness )
|
|
||||||
{
|
|
||||||
idStr fullname;
|
|
||||||
renderView_t ref;
|
|
||||||
viewDef_t primary;
|
|
||||||
byte* buffers[6];
|
|
||||||
int width = 0, height = 0;
|
|
||||||
|
|
||||||
memset( &cubeAxis, 0, sizeof( cubeAxis ) );
|
|
||||||
cubeAxis[0][0][0] = 1;
|
|
||||||
cubeAxis[0][1][2] = 1;
|
|
||||||
cubeAxis[0][2][1] = 1;
|
|
||||||
|
|
||||||
cubeAxis[1][0][0] = -1;
|
|
||||||
cubeAxis[1][1][2] = -1;
|
|
||||||
cubeAxis[1][2][1] = 1;
|
|
||||||
|
|
||||||
cubeAxis[2][0][1] = 1;
|
|
||||||
cubeAxis[2][1][0] = -1;
|
|
||||||
cubeAxis[2][2][2] = -1;
|
|
||||||
|
|
||||||
cubeAxis[3][0][1] = -1;
|
|
||||||
cubeAxis[3][1][0] = -1;
|
|
||||||
cubeAxis[3][2][2] = 1;
|
|
||||||
|
|
||||||
cubeAxis[4][0][2] = 1;
|
|
||||||
cubeAxis[4][1][0] = -1;
|
|
||||||
cubeAxis[4][2][1] = 1;
|
|
||||||
|
|
||||||
cubeAxis[5][0][2] = -1;
|
|
||||||
cubeAxis[5][1][0] = 1;
|
|
||||||
cubeAxis[5][2][1] = 1;
|
|
||||||
|
|
||||||
// read all of the images
|
|
||||||
for( int i = 0 ; i < 6 ; i++ )
|
|
||||||
{
|
|
||||||
fullname.Format( "env/%s%s.exr", baseName, envDirection[i] );
|
|
||||||
|
|
||||||
const bool captureToImage = false;
|
|
||||||
common->UpdateScreen( captureToImage );
|
|
||||||
|
|
||||||
R_LoadImage( fullname, &buffers[i], &width, &height, NULL, true, NULL );
|
|
||||||
if( !buffers[i] )
|
|
||||||
{
|
|
||||||
common->Printf( "loading %s failed.\n", fullname.c_str() );
|
|
||||||
for( i-- ; i >= 0 ; i-- )
|
|
||||||
{
|
|
||||||
Mem_Free( buffers[i] );
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pacifier = true;
|
|
||||||
|
|
||||||
// resample with hemispherical blending
|
|
||||||
int samples = 1000;
|
|
||||||
|
|
||||||
//halfFloat_t* outBuffer = ( halfFloat_t* )_alloca( outSize * outSize * 3 * sizeof( halfFloat_t ) );
|
|
||||||
halfFloat_t* outBuffer = ( halfFloat_t* )R_StaticAlloc( outSize * outSize * 3 * sizeof( halfFloat_t ) , TAG_IMAGE );
|
|
||||||
|
|
||||||
{
|
|
||||||
// output an octahedron probe
|
|
||||||
|
|
||||||
CommandlineProgressBar progressBar( outSize * outSize );
|
|
||||||
|
|
||||||
int start = Sys_Milliseconds();
|
|
||||||
|
|
||||||
const float invDstSize = 1.0f / float( outSize );
|
|
||||||
|
|
||||||
for( int x = 0 ; x < outSize ; x++ )
|
|
||||||
{
|
|
||||||
for( int y = 0 ; y < outSize ; y++ )
|
|
||||||
{
|
|
||||||
idVec3 dir;
|
|
||||||
float total[3];
|
|
||||||
|
|
||||||
// convert UV coord from [0, 1] to [-1, 1] space
|
|
||||||
const float u = 2.0f * x * invDstSize - 1.0f;
|
|
||||||
const float v = 2.0f * y * invDstSize - 1.0f;
|
|
||||||
|
|
||||||
idVec2 octCoord = NormalizedOctCoord( x, y, outSize );
|
|
||||||
|
|
||||||
// convert UV coord to 3D direction
|
|
||||||
dir.FromOctahedral( octCoord );
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
total[0] = total[1] = total[2] = 0;
|
|
||||||
|
|
||||||
//float roughness = map ? 0.1 : 0.95; // small for specular, almost hemisphere for ambient
|
|
||||||
|
|
||||||
for( int s = 0 ; s < samples ; s++ )
|
|
||||||
{
|
|
||||||
idVec2 Xi = Hammersley2D( s, samples );
|
|
||||||
idVec3 test = ImportanceSampleGGX( Xi, dir, roughness );
|
|
||||||
|
|
||||||
float result[3];
|
|
||||||
//test = dir;
|
|
||||||
|
|
||||||
R_SampleCubeMapHDR( test, width, buffers, result );
|
|
||||||
|
|
||||||
total[0] += result[0];
|
|
||||||
total[1] += result[1];
|
|
||||||
total[2] += result[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
outBuffer[( y * outSize + x ) * 3 + 0] = F32toF16( total[0] / samples );
|
|
||||||
outBuffer[( y * outSize + x ) * 3 + 1] = F32toF16( total[1] / samples );
|
|
||||||
outBuffer[( y * outSize + x ) * 3 + 2] = F32toF16( total[2] / samples );
|
|
||||||
#else
|
|
||||||
outBuffer[( y * outSize + x ) * 3 + 0] = F32toF16( ( dir.x * 0.5f + 0.5f ) );
|
|
||||||
outBuffer[( y * outSize + x ) * 3 + 1] = F32toF16( ( dir.y * 0.5f + 0.5f ) );
|
|
||||||
outBuffer[( y * outSize + x ) * 3 + 2] = F32toF16( ( dir.z * 0.5f + 0.5f ) );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
progressBar.Increment();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fullname.Format( "env/%s%s.exr", baseName, suffix );
|
|
||||||
//common->Printf( "writing %s\n", fullname.c_str() );
|
|
||||||
|
|
||||||
const bool captureToImage = false;
|
|
||||||
common->UpdateScreen( captureToImage );
|
|
||||||
|
|
||||||
//R_WriteTGA( fullname, outBuffer, outSize, outSize, false, "fs_basepath" );
|
|
||||||
//R_WritePNG( fullname, outBuffer, 4, outSize, outSize, true, "fs_basepath" );
|
|
||||||
R_WriteEXR( fullname, (byte*)outBuffer, 3, outSize, outSize, "fs_basepath" );
|
|
||||||
|
|
||||||
int end = Sys_Milliseconds();
|
|
||||||
|
|
||||||
common->Printf( "env/%s convolved in %5.1f seconds\n\n", baseName, ( end - start ) * 0.001f );
|
|
||||||
}
|
|
||||||
|
|
||||||
for( int i = 0 ; i < 6 ; i++ )
|
|
||||||
{
|
|
||||||
if( buffers[i] )
|
|
||||||
{
|
|
||||||
Mem_Free( buffers[i] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Mem_Free( outBuffer );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
==================
|
|
||||||
R_MakeAmbientMap_f
|
|
||||||
|
|
||||||
R_MakeAmbientMap_f <basename> [size]
|
|
||||||
|
|
||||||
Saves out env/<basename>_amb_ft.tga, etc
|
|
||||||
==================
|
|
||||||
*/
|
|
||||||
//void R_MakeAmbientMap_f( const idCmdArgs& args )
|
|
||||||
CONSOLE_COMMAND( makeAmbientMap, "Saves out env/<basename>_amb_ft.tga, etc", NULL )
|
|
||||||
{
|
|
||||||
const char* baseName;
|
|
||||||
int outSize;
|
|
||||||
float roughness;
|
|
||||||
|
|
||||||
if( args.Argc() != 2 && args.Argc() != 3 && args.Argc() != 4 )
|
|
||||||
{
|
|
||||||
common->Printf( "USAGE: makeAmbientMap <basename> [size]\n" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
baseName = args.Argv( 1 );
|
|
||||||
|
|
||||||
if( args.Argc() >= 3 )
|
|
||||||
{
|
|
||||||
outSize = atoi( args.Argv( 2 ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
outSize = 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( args.Argc() == 4 )
|
|
||||||
{
|
|
||||||
roughness = atof( args.Argv( 3 ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
roughness = 0.95f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( roughness > 0.8f )
|
|
||||||
{
|
|
||||||
R_MakeAmbientMap( baseName, "_amb", outSize, roughness );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
R_MakeAmbientMap( baseName, "_spec", outSize, roughness );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL )
|
|
||||||
{
|
|
||||||
idStr fullname;
|
|
||||||
idStr baseName;
|
|
||||||
idMat3 axis[6], oldAxis;
|
|
||||||
idVec3 oldPosition;
|
|
||||||
renderView_t ref;
|
|
||||||
int blends;
|
|
||||||
const char* extension;
|
|
||||||
int size;
|
|
||||||
int old_fov_x, old_fov_y;
|
|
||||||
|
|
||||||
static const char* envDirection[6] = { "_px", "_nx", "_py", "_ny", "_pz", "_nz" };
|
|
||||||
|
|
||||||
baseName = tr.primaryWorld->mapName;
|
|
||||||
baseName.StripFileExtension();
|
|
||||||
|
|
||||||
size = RADIANCE_CUBEMAP_SIZE;
|
|
||||||
blends = 1;
|
|
||||||
|
|
||||||
if( !tr.primaryView )
|
|
||||||
{
|
|
||||||
common->Printf( "No primary view.\n" );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const viewDef_t primary = *tr.primaryView;
|
|
||||||
|
|
||||||
memset( &axis, 0, sizeof( axis ) );
|
|
||||||
|
|
||||||
// +X
|
|
||||||
axis[0][0][0] = 1;
|
|
||||||
axis[0][1][2] = 1;
|
|
||||||
axis[0][2][1] = 1;
|
|
||||||
|
|
||||||
// -X
|
|
||||||
axis[1][0][0] = -1;
|
|
||||||
axis[1][1][2] = -1;
|
|
||||||
axis[1][2][1] = 1;
|
|
||||||
|
|
||||||
// +Y
|
|
||||||
axis[2][0][1] = 1;
|
|
||||||
axis[2][1][0] = -1;
|
|
||||||
axis[2][2][2] = -1;
|
|
||||||
|
|
||||||
// -Y
|
|
||||||
axis[3][0][1] = -1;
|
|
||||||
axis[3][1][0] = -1;
|
|
||||||
axis[3][2][2] = 1;
|
|
||||||
|
|
||||||
// +Z
|
|
||||||
axis[4][0][2] = 1;
|
|
||||||
axis[4][1][0] = -1;
|
|
||||||
axis[4][2][1] = 1;
|
|
||||||
|
|
||||||
// -Z
|
|
||||||
axis[5][0][2] = -1;
|
|
||||||
axis[5][1][0] = 1;
|
|
||||||
axis[5][2][1] = 1;
|
|
||||||
|
|
||||||
//--------------------------------------------
|
|
||||||
// CAPTURE SCENE LIGHTING TO CUBEMAPS
|
|
||||||
//--------------------------------------------
|
|
||||||
|
|
||||||
// so we return to that axis and fov after the fact.
|
|
||||||
oldPosition = primary.renderView.vieworg;
|
|
||||||
oldAxis = primary.renderView.viewaxis;
|
|
||||||
old_fov_x = primary.renderView.fov_x;
|
|
||||||
old_fov_y = primary.renderView.fov_y;
|
|
||||||
|
|
||||||
for( int i = 0; i < tr.primaryWorld->envprobeDefs.Num(); i++ )
|
|
||||||
{
|
|
||||||
RenderEnvprobeLocal* def = tr.primaryWorld->envprobeDefs[i];
|
|
||||||
if( def == NULL )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for( int j = 0 ; j < 6 ; j++ )
|
|
||||||
{
|
|
||||||
ref = primary.renderView;
|
|
||||||
|
|
||||||
ref.rdflags = RDF_NOAMBIENT | RDF_IRRADIANCE;
|
|
||||||
ref.fov_x = ref.fov_y = 90;
|
|
||||||
|
|
||||||
ref.vieworg = def->parms.origin;
|
|
||||||
ref.viewaxis = axis[j];
|
|
||||||
|
|
||||||
extension = envDirection[ j ];
|
|
||||||
fullname.Format( "env/%s/envprobe%i%s", baseName.c_str(), i, extension );
|
|
||||||
|
|
||||||
tr.TakeScreenshot( size, size, fullname, blends, &ref, EXR );
|
|
||||||
//tr.CaptureRenderToFile( fullname, false );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// restore the original axis and fov
|
|
||||||
/*
|
|
||||||
ref.vieworg = oldPosition;
|
|
||||||
ref.viewaxis = oldAxis;
|
|
||||||
ref.fov_x = old_fov_x;
|
|
||||||
ref.fov_y = old_fov_y;
|
|
||||||
cvarSystem->SetCVarInteger( "r_windowWidth", res_w );
|
|
||||||
cvarSystem->SetCVarInteger( "r_windowHeight", res_h );
|
|
||||||
R_SetNewMode( false ); // the same as "vid_restart"
|
|
||||||
*/
|
|
||||||
|
|
||||||
common->Printf( "Wrote a env set with the name %s\n", baseName.c_str() );
|
|
||||||
|
|
||||||
//--------------------------------------------
|
|
||||||
// CONVOLVE CUBEMAPS
|
|
||||||
//--------------------------------------------
|
|
||||||
|
|
||||||
int start = Sys_Milliseconds();
|
|
||||||
|
|
||||||
for( int i = 0; i < tr.primaryWorld->envprobeDefs.Num(); i++ )
|
|
||||||
{
|
|
||||||
RenderEnvprobeLocal* def = tr.primaryWorld->envprobeDefs[i];
|
|
||||||
if( def == NULL )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
fullname.Format( "%s/envprobe%i", baseName.c_str(), i );
|
|
||||||
|
|
||||||
R_MakeAmbientMap( fullname.c_str(), "_amb", IRRADIANCE_CUBEMAP_SIZE, 0.95f );
|
|
||||||
R_MakeAmbientMap( fullname.c_str(), "_spec", RADIANCE_CUBEMAP_SIZE, 0.1f );
|
|
||||||
}
|
|
||||||
|
|
||||||
int end = Sys_Milliseconds();
|
|
||||||
|
|
||||||
common->Printf( "convolved probes in %5.1f seconds\n\n", ( end - start ) * 0.001f );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue