mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-15 07:00:58 +00:00
Added command makeBrdfLut for testing
This commit is contained in:
parent
31df292288
commit
28ad01ab80
3 changed files with 217 additions and 12 deletions
|
@ -96,6 +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_RGBA16F, // 64 bpp
|
||||
FMT_RGBA32F, // 128 bpp
|
||||
FMT_R32F, // 32 bpp
|
||||
|
@ -574,6 +575,7 @@ public:
|
|||
idImage* hierarchicalZbufferImage; // zbuffer with mip maps to accelerate screen space ray tracing
|
||||
idImage* imguiFontImage;
|
||||
|
||||
idImage* brdfLutImage;
|
||||
idImage* defaultUACIrradianceCube;
|
||||
idImage* defaultUACRadianceCube;
|
||||
// RB end
|
||||
|
|
|
@ -35,6 +35,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#include "RenderCommon.h"
|
||||
#include "SMAA/AreaTex.h"
|
||||
#include "SMAA/SearchTex.h"
|
||||
#include "Image_brdfLut.h"
|
||||
|
||||
#define DEFAULT_SIZE 16
|
||||
|
||||
|
@ -764,8 +765,6 @@ static void R_CreateSMAAAreaImage( idImage* image )
|
|||
{
|
||||
static byte data[AREATEX_HEIGHT][AREATEX_WIDTH][4];
|
||||
|
||||
idRandom2 random( Sys_Milliseconds() );
|
||||
|
||||
for( int x = 0; x < AREATEX_WIDTH; x++ )
|
||||
{
|
||||
for( int y = 0; y < AREATEX_HEIGHT; y++ )
|
||||
|
@ -791,8 +790,6 @@ static void R_CreateSMAASearchImage( idImage* image )
|
|||
{
|
||||
static byte data[SEARCHTEX_HEIGHT][SEARCHTEX_WIDTH][4];
|
||||
|
||||
idRandom2 random( Sys_Milliseconds() );
|
||||
|
||||
for( int x = 0; x < SEARCHTEX_WIDTH; x++ )
|
||||
{
|
||||
for( int y = 0; y < SEARCHTEX_HEIGHT; y++ )
|
||||
|
@ -840,6 +837,33 @@ static void R_CreateImGuiFontImage( idImage* image )
|
|||
//io.Fonts->ClearTexData();
|
||||
}
|
||||
|
||||
static void R_CreateBrdfLutImage( idImage* image )
|
||||
{
|
||||
#if 0
|
||||
static byte data[BRDFLUT_TEX_HEIGHT][BRDFLUT_TEX_WIDTH][4];
|
||||
|
||||
for( int x = 0; x < BRDFLUT_TEX_WIDTH; x++ )
|
||||
{
|
||||
for( int y = 0; y < BRDFLUT_TEX_HEIGHT; y++ )
|
||||
{
|
||||
#if 0
|
||||
data[AREATEX_HEIGHT - y][x][0] = areaTexBytes[ y * AREATEX_PITCH + x * 2 + 0 ];
|
||||
data[AREATEX_HEIGHT - y][x][1] = areaTexBytes[ y * AREATEX_PITCH + x * 2 + 1 ];
|
||||
data[AREATEX_HEIGHT - y][x][2] = 0;
|
||||
data[AREATEX_HEIGHT - y][x][3] = 1;
|
||||
#else
|
||||
data[y][x][0] = brfLutTexBytes[ y * BRDFLUT_TEX_PITCH + x * 2 + 0 ];
|
||||
data[y][x][1] = brfLutTexBytes[ y * BRDFLUT_TEX_PITCH + x * 2 + 1 ];
|
||||
data[y][x][2] = 0;
|
||||
data[y][x][3] = 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
image->GenerateImage( ( byte* )brfLutTexBytes, BRDFLUT_TEX_WIDTH, BRDFLUT_TEX_HEIGHT, TF_LINEAR, TR_CLAMP, TD_LOOKUP_TABLE_RGBA );
|
||||
}
|
||||
|
||||
// RB end
|
||||
|
||||
/*
|
||||
|
@ -904,6 +928,8 @@ void idImageManager::CreateIntrinsicImages()
|
|||
hierarchicalZbufferImage = ImageFromFunction( "_cszBuffer", R_HierarchicalZBufferImage_ResNative );
|
||||
|
||||
imguiFontImage = ImageFromFunction( "_imguiFont", R_CreateImGuiFontImage );
|
||||
|
||||
brdfLutImage = globalImages->ImageFromFunction( "_brdfLut", R_CreateBrdfLutImage );
|
||||
// RB end
|
||||
|
||||
// scratchImage is used for screen wipes/doublevision etc..
|
||||
|
@ -920,8 +946,10 @@ void idImageManager::CreateIntrinsicImages()
|
|||
loadingIconImage = ImageFromFile( "textures/loadingicon2", TF_DEFAULT, TR_CLAMP, TD_DEFAULT, CF_2D );
|
||||
hellLoadingIconImage = ImageFromFile( "textures/loadingicon3", TF_DEFAULT, TR_CLAMP, TD_DEFAULT, CF_2D );
|
||||
|
||||
// RB begin
|
||||
defaultUACIrradianceCube = ImageFromFile( "env/testmap_1_amb", TF_DEFAULT, TR_CLAMP, TD_HIGHQUALITY_CUBE, CF_NATIVE );
|
||||
defaultUACRadianceCube = ImageFromFile( "env/testmap_1_spec", TF_DEFAULT, TR_CLAMP, TD_HIGHQUALITY_CUBE, CF_NATIVE );
|
||||
// RB end
|
||||
|
||||
release_assert( loadingIconImage->referencedOutsideLevelLoad );
|
||||
release_assert( hellLoadingIconImage->referencedOutsideLevelLoad );
|
||||
|
|
|
@ -1404,18 +1404,18 @@ inline idVec2 Hammersley2D( uint i, uint N )
|
|||
return idVec2( float( i ) / float( N ), RadicalInverse_VdC( i ) );
|
||||
}
|
||||
|
||||
idVec3 ImportanceSampleGGX( const idVec2& Xi, float roughness, const idVec3& N )
|
||||
idVec3 ImportanceSampleGGX( const idVec2& Xi, const idVec3& N, float roughness )
|
||||
{
|
||||
float a = roughness * roughness;
|
||||
|
||||
// cosinus distributed direction (Z-up or tangent space) from the hammersley point xi
|
||||
float Phi = 2 * idMath::PI * Xi.x;
|
||||
float cosTheta = sqrt( ( 1 - Xi.y ) / ( 1 + ( a * a - 1 ) * Xi.y ) );
|
||||
float sinTheta = sqrt( 1 - cosTheta * cosTheta );
|
||||
float cosTheta = idMath::Sqrt( ( 1 - Xi.y ) / ( 1 + ( a * a - 1 ) * Xi.y ) );
|
||||
float sinTheta = idMath::Sqrt( 1 - cosTheta * cosTheta );
|
||||
|
||||
idVec3 H;
|
||||
H.x = sinTheta * cos( Phi );
|
||||
H.y = sinTheta * sin( Phi );
|
||||
H.x = sinTheta * idMath::Cos( Phi );
|
||||
H.y = sinTheta * idMath::Sin( Phi );
|
||||
H.z = cosTheta;
|
||||
|
||||
// rotate from tangent space to world space along N
|
||||
|
@ -1424,7 +1424,181 @@ idVec3 ImportanceSampleGGX( const idVec2& Xi, float roughness, const idVec3& N )
|
|||
tangentX.Normalize();
|
||||
idVec3 tangentY = N.Cross( tangentX );
|
||||
|
||||
return tangentX * H.x + tangentY * H.y + N * H.z;
|
||||
idVec3 sampleVec = tangentX * H.x + tangentY * H.y + N * H.z;
|
||||
sampleVec.Normalize();
|
||||
|
||||
return sampleVec;
|
||||
}
|
||||
|
||||
float Geometry_SchlickGGX( float NdotV, float roughness )
|
||||
{
|
||||
// note that we use a different k for IBL
|
||||
float a = roughness;
|
||||
float k = ( a * a ) / 2.0;
|
||||
|
||||
float nom = NdotV;
|
||||
float denom = NdotV * ( 1.0 - k ) + k;
|
||||
|
||||
return nom / denom;
|
||||
}
|
||||
|
||||
float Geometry_Smith( idVec3 N, idVec3 V, idVec3 L, float roughness )
|
||||
{
|
||||
float NdotV = Max( ( N * V ), 0.0f );
|
||||
float NdotL = Max( ( N * L ), 0.0f );
|
||||
|
||||
float ggx2 = Geometry_SchlickGGX( NdotV, roughness );
|
||||
float ggx1 = Geometry_SchlickGGX( NdotL, roughness );
|
||||
|
||||
return ggx1 * ggx2;
|
||||
}
|
||||
|
||||
idVec2 IntegrateBRDF( float NdotV, float roughness, int sampleCount )
|
||||
{
|
||||
idVec3 V;
|
||||
V.x = sqrt( 1.0 - NdotV * NdotV );
|
||||
V.y = 0.0;
|
||||
V.z = NdotV;
|
||||
|
||||
float A = 0.0;
|
||||
float B = 0.0;
|
||||
|
||||
idVec3 N( 0.0f, 0.0f, 1.0f );
|
||||
for( int i = 0; i < sampleCount; ++i )
|
||||
{
|
||||
// generates a sample vector that's biased towards the
|
||||
// preferred alignment direction (importance sampling).
|
||||
idVec2 Xi = Hammersley2D( i, sampleCount );
|
||||
|
||||
idVec3 H = ImportanceSampleGGX( Xi, N, roughness );
|
||||
idVec3 L = ( 2.0 * ( V * H ) * H - V );
|
||||
L.Normalize();
|
||||
|
||||
float NdotL = Max( L.z, 0.0f );
|
||||
float NdotH = Max( H.z, 0.0f );
|
||||
float VdotH = Max( ( V * H ), 0.0f );
|
||||
|
||||
if( NdotL > 0.0 )
|
||||
{
|
||||
float G = Geometry_Smith( N, V, L, roughness );
|
||||
float G_Vis = ( G * VdotH ) / ( NdotH * NdotV );
|
||||
float Fc = idMath::Pow( 1.0 - VdotH, 5.0 );
|
||||
|
||||
A += ( 1.0 - Fc ) * G_Vis;
|
||||
B += Fc * G_Vis;
|
||||
}
|
||||
}
|
||||
|
||||
A /= float( sampleCount );
|
||||
B /= float( sampleCount );
|
||||
|
||||
return idVec2( A, B );
|
||||
}
|
||||
|
||||
void R_MakeBrdfLut_f( const idCmdArgs& args )
|
||||
{
|
||||
int outSize = 32;
|
||||
int width = 0, height = 0;
|
||||
|
||||
//if( args.Argc() != 2 )
|
||||
//{
|
||||
// common->Printf( "USAGE: makeBrdfLut [size]\n" );
|
||||
// return;
|
||||
//}
|
||||
|
||||
//if( args.Argc() == 2 )
|
||||
//{
|
||||
// outSize = atoi( args.Argv( 1 ) );
|
||||
//}
|
||||
|
||||
bool pacifier = true;
|
||||
|
||||
// resample with hemispherical blending
|
||||
int samples = 1024;
|
||||
|
||||
int ldrBufferSize = outSize * outSize * 4;
|
||||
byte* ldrBuffer = ( byte* )Mem_Alloc( ldrBufferSize, TAG_TEMP );
|
||||
|
||||
CommandlineProgressBar progressBar( outSize * outSize );
|
||||
|
||||
int start = Sys_Milliseconds();
|
||||
|
||||
for( int x = 0 ; x < outSize ; x++ )
|
||||
{
|
||||
float NdotV = ( x + 0.5f ) / outSize;
|
||||
|
||||
for( int y = 0 ; y < outSize ; y++ )
|
||||
{
|
||||
float roughness = ( y + 0.5f ) / outSize;
|
||||
|
||||
idVec2 output = IntegrateBRDF( NdotV, roughness, samples );
|
||||
|
||||
ldrBuffer[( y * outSize + x ) * 4 + 0] = byte( output.x * 255 );
|
||||
ldrBuffer[( y * outSize + x ) * 4 + 1] = byte( output.y * 255 );
|
||||
ldrBuffer[( y * outSize + x ) * 4 + 2] = 0;
|
||||
ldrBuffer[( y * outSize + x ) * 4 + 3] = 255;
|
||||
|
||||
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" );
|
||||
|
||||
|
||||
idFileLocal headerFile( fileSystem->OpenFileWrite( "env/Image_brdfLut.h", "fs_basepath" ) );
|
||||
|
||||
static const char* intro = R"(
|
||||
#ifndef BRDFLUT_TEX_H
|
||||
#define BRDFLUT_TEX_H
|
||||
|
||||
#define BRDFLUT_TEX_WIDTH 512
|
||||
#define BRDFLUT_TEX_HEIGHT 512
|
||||
#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
|
||||
*/
|
||||
static const unsigned char brfLutTexBytes[] =
|
||||
{
|
||||
)";
|
||||
|
||||
headerFile->Printf( "%s\n", intro );
|
||||
|
||||
for( int i = 0; i < ldrBufferSize; i++ )
|
||||
{
|
||||
byte b = ldrBuffer[i];
|
||||
|
||||
if( i < ( ldrBufferSize - 1 ) )
|
||||
{
|
||||
headerFile->Printf( "0x%02hhx, ", b );
|
||||
}
|
||||
else
|
||||
{
|
||||
headerFile->Printf( "0x%02hhx", b );
|
||||
}
|
||||
|
||||
if( i % 12 == 0 )
|
||||
{
|
||||
headerFile->Printf( "\n" );
|
||||
}
|
||||
}
|
||||
headerFile->Printf( "\n};\n#endif\n" );
|
||||
|
||||
int end = Sys_Milliseconds();
|
||||
|
||||
common->Printf( "%s integrated in %5.1f seconds\n\n", fullname.c_str(), ( end - start ) * 0.001f );
|
||||
|
||||
Mem_Free( ldrBuffer );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1450,7 +1624,7 @@ void R_MakeAmbientMap_f( const idCmdArgs& args )
|
|||
|
||||
if( args.Argc() != 2 && args.Argc() != 3 )
|
||||
{
|
||||
common->Printf( "USAGE: ambientshot <basename> [size]\n" );
|
||||
common->Printf( "USAGE: makeAmbientMap <basename> [size]\n" );
|
||||
return;
|
||||
}
|
||||
baseName = args.Argv( 1 );
|
||||
|
@ -1540,7 +1714,7 @@ void R_MakeAmbientMap_f( const idCmdArgs& args )
|
|||
for( int s = 0 ; s < samples ; s++ )
|
||||
{
|
||||
idVec2 Xi = Hammersley2D( s, samples );
|
||||
idVec3 test = ImportanceSampleGGX( Xi, roughness, dir );
|
||||
idVec3 test = ImportanceSampleGGX( Xi, dir, roughness );
|
||||
|
||||
byte result[4];
|
||||
//test = dir;
|
||||
|
@ -1968,6 +2142,7 @@ void R_InitCommands()
|
|||
cmdSystem->AddCommand( "touchGui", R_TouchGui_f, CMD_FL_RENDERER, "touches a gui" );
|
||||
cmdSystem->AddCommand( "screenshot", R_ScreenShot_f, CMD_FL_RENDERER, "takes a screenshot" );
|
||||
cmdSystem->AddCommand( "envshot", R_EnvShot_f, CMD_FL_RENDERER, "takes an environment shot" );
|
||||
cmdSystem->AddCommand( "makeBrfdLut", R_MakeBrdfLut_f, CMD_FL_RENDERER | CMD_FL_CHEAT, "make a GGX BRDF lookup table" ); // RB
|
||||
cmdSystem->AddCommand( "makeAmbientMap", R_MakeAmbientMap_f, CMD_FL_RENDERER | CMD_FL_CHEAT, "makes an ambient map" );
|
||||
cmdSystem->AddCommand( "envToSky", R_TransformEnvToSkybox_f, CMD_FL_RENDERER | CMD_FL_CHEAT, "transforms environment textures to sky box textures" );
|
||||
cmdSystem->AddCommand( "skyToEnv", R_TransformSkyboxToEnv_f, CMD_FL_RENDERER | CMD_FL_CHEAT, "transforms sky box textures to environment textures" );
|
||||
|
|
Loading…
Reference in a new issue