From 6decaa229395591b4a83b61889b3db041a7f53b5 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Tue, 13 Apr 2021 15:50:46 +0200 Subject: [PATCH 01/26] Started to bring back the Quake 3 lightgrid as irradiance cache --- neo/idlib/math/SphericalHarmonics.h | 4 + neo/renderer/OpenGL/RenderDebug_GL.cpp | 82 +++ neo/renderer/RenderBackend.h | 1 + neo/renderer/RenderCommon.h | 93 ++- neo/renderer/RenderSystem_init.cpp | 42 +- neo/renderer/RenderWorld_envprobes.cpp | 96 +-- neo/renderer/RenderWorld_lightgrid.cpp | 828 +++++++++++++++++++++++++ neo/renderer/RenderWorld_load.cpp | 2 + neo/renderer/RenderWorld_local.h | 50 +- 9 files changed, 1099 insertions(+), 99 deletions(-) create mode 100644 neo/renderer/RenderWorld_lightgrid.cpp diff --git a/neo/idlib/math/SphericalHarmonics.h b/neo/idlib/math/SphericalHarmonics.h index a8937261..5a33bfa8 100644 --- a/neo/idlib/math/SphericalHarmonics.h +++ b/neo/idlib/math/SphericalHarmonics.h @@ -26,6 +26,10 @@ SOFTWARE. #ifndef __MATH_SPHERICAL_HARMONICS_H__ #define __MATH_SPHERICAL_HARMONICS_H__ +// RB: there is a very good talk by Yuriy O'Donnell that explains the the functions used in this library +// Precomputed Global Illumination in Frostbite (GDC 2018) +// https://www.gdcvault.com/play/1025214/Precomputed-Global-Illumination-in + // https://graphics.stanford.edu/papers/envmap/envmap.pdf template diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index d893e379..a610faf8 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1787,6 +1787,82 @@ void idRenderBackend::DBG_ShowViewEnvprobes() } } +void idRenderBackend::DBG_ShowLightGrid() +{ + if( r_showLightGrid.GetInteger() <= 0 || !tr.primaryWorld ) + { + return; + } + + // all volumes are expressed in world coordinates + renderProgManager.BindShader_Color(); + + GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_DEPTHMASK ); + GL_Color( 1.0f, 1.0f, 1.0f ); + + idMat3 axis; + axis.Identity(); + + for( int i = 0; i < tr.primaryWorld->lightGrid.lightGridPoints.Num(); i++ ) + { + lightGridPoint_t* gridPoint = &tr.primaryWorld->lightGrid.lightGridPoints[i]; + + idVec3 distanceToCam = gridPoint->origin - viewDef->renderView.vieworg; + if( distanceToCam.LengthSqr() > ( 1024 * 1024 ) ) + { + continue; + } + + /* + idVec4 c; + c[0] = idMath::ClampFloat( 0, 1, gridPoint->directed[0] * ( 1.0f / 255.0f ) ); + c[1] = idMath::ClampFloat( 0, 1, gridPoint->directed[1] * ( 1.0f / 255.0f ) ); + c[2] = idMath::ClampFloat( 0, 1, gridPoint->directed[2] * ( 1.0f / 255.0f ) ); + + glColor4f( c[0], c[1], c[2], 1 ); + + float lattitude = DEG2RAD( gridPoint->latLong[1] * ( 360.0f / 255.0f ) ); + float longitude = DEG2RAD( gridPoint->latLong[0] * ( 360.0f / 255.0f ) ); + + idVec3 dir; + dir[0] = idMath::Cos( lattitude ) * idMath::Sin( longitude ); + dir[1] = idMath::Sin( lattitude ) * idMath::Sin( longitude ); + dir[2] = idMath::Cos( longitude ); + + idVec3 pos2 = gridPoint->origin - dir * r_showLightGrid.GetFloat(); + + glBegin( GL_LINES ); + + glColor4f( c[0], c[1], c[2], 1 ); + //glColor4f( 1, 1, 1, 1 ); + glVertex3fv( gridPoint->origin.ToFloatPtr() ); + + glColor4f( 0, 0, 0, 1 ); + glVertex3fv( pos2.ToFloatPtr() ); + glEnd(); + */ + + idVec3 color = tr.primaryWorld->lightGrid.GetProbeIndexDebugColor( i ); + GL_Color( color ); + + idRenderMatrix modelRenderMatrix; + idRenderMatrix::CreateFromOriginAxis( gridPoint->origin, axis, modelRenderMatrix ); + + // calculate the matrix that transforms the unit cube to exactly cover the model in world space + const float size = 3.0f; + idBounds debugBounds( idVec3( -size ), idVec3( size ) ); + + idRenderMatrix inverseBaseModelProject; + idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject ); + + idRenderMatrix invProjectMVPMatrix; + idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix ); + RB_SetMVP( invProjectMVPMatrix ); + + DrawElementsWithCounters( &zeroOneSphereSurface ); + } +} + void idRenderBackend::DBG_ShowShadowMapLODs() { if( !r_showShadowMapLODs.GetInteger() ) @@ -3125,6 +3201,11 @@ idRenderBackend::DBG_RenderDebugTools */ void idRenderBackend::DBG_RenderDebugTools( drawSurf_t** drawSurfs, int numDrawSurfs ) { + if( viewDef->renderView.rdflags & RDF_IRRADIANCE ) + { + return; + } + // don't do much if this was a 2D rendering if( !viewDef->viewEntitys ) { @@ -3158,6 +3239,7 @@ void idRenderBackend::DBG_RenderDebugTools( drawSurf_t** drawSurfs, int numDrawS DBG_ShowViewEntitys( viewDef->viewEntitys ); DBG_ShowLights(); // RB begin + DBG_ShowLightGrid(); DBG_ShowViewEnvprobes(); DBG_ShowShadowMapLODs(); DBG_ShowShadowMaps(); diff --git a/neo/renderer/RenderBackend.h b/neo/renderer/RenderBackend.h index 097c0a98..e0701330 100644 --- a/neo/renderer/RenderBackend.h +++ b/neo/renderer/RenderBackend.h @@ -425,6 +425,7 @@ private: void DBG_ShowDominantTris( drawSurf_t** drawSurfs, int numDrawSurfs ); void DBG_ShowEdges( drawSurf_t** drawSurfs, int numDrawSurfs ); void DBG_ShowLights(); + void DBG_ShowLightGrid(); // RB void DBG_ShowViewEnvprobes(); // RB void DBG_ShowShadowMapLODs(); // RB void DBG_ShowPortals(); diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index 31974653..b8f6d8f2 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -501,6 +501,24 @@ struct calcEnvprobeParms_t halfFloat_t* outBuffer; // HDR R11G11B11F packed atlas int time; // execution time in milliseconds }; + +struct calcLightGridPointParms_t +{ + // input + byte* buffers[6]; // HDR R11G11B11F standard OpenGL cubemap sides + int samples; + + int outWidth; + int outHeight; + + bool printProgress; + + idStr filename; + + // output + halfFloat_t* outBuffer; // HDR R11G11B11F packed atlas + int time; // execution time in milliseconds +}; // RB end const int MAX_CLIP_PLANES = 1; // we may expand this to six for some subview issues @@ -940,6 +958,8 @@ public: unsigned short gammaTable[256]; // brightness / gamma modify this + idMat3 cubeAxis[6]; // RB + srfTriangles_t* unitSquareTriangles; srfTriangles_t* zeroOneCubeTriangles; srfTriangles_t* zeroOneSphereTriangles; @@ -956,8 +976,9 @@ public: idParallelJobList* frontEndJobList; // RB irradiance and GGX background jobs - idParallelJobList* envprobeJobList; - idList irradianceJobs; + idParallelJobList* envprobeJobList; + idList envprobeJobs; + idList lightGridJobs; idRenderBackend backend; @@ -1172,6 +1193,7 @@ extern idCVar r_useHierarchicalDepthBuffer; extern idCVar r_usePBR; extern idCVar r_pbrDebug; extern idCVar r_showViewEnvprobes; +extern idCVar r_showLightGrid; // show Quake 3 style light grid points extern idCVar r_exposure; // RB end @@ -1349,6 +1371,69 @@ RENDERWORLD_PORTALS viewEntity_t* R_SetEntityDefViewEntity( idRenderEntityLocal* def ); viewLight_t* R_SetLightDefViewLight( idRenderLightLocal* def ); +/* +============================================================ + +RENDERWORLD_ENVPROBES + +============================================================ +*/ + +void R_SampleCubeMapHDR( const idVec3& dir, int size, byte* buffers[6], float result[3], float& u, float& v ); + +idVec2 NormalizedOctCoord( int x, int y, const int probeSideLength ); + +class CommandlineProgressBar +{ +private: + size_t tics = 0; + size_t nextTicCount = 0; + int count = 0; + int expectedCount = 0; + +public: + CommandlineProgressBar( int _expectedCount ) + { + expectedCount = _expectedCount; + } + + void Start() + { + common->Printf( "0%% 10 20 30 40 50 60 70 80 90 100%%\n" ); + common->Printf( "|----|----|----|----|----|----|----|----|----|----|\n" ); + + common->UpdateScreen( false ); + } + + void Increment() + { + if( ( count + 1 ) >= nextTicCount ) + { + size_t ticsNeeded = ( size_t )( ( ( double )( count + 1 ) / expectedCount ) * 50.0 ); + + do + { + common->Printf( "*" ); + } + while( ++tics < ticsNeeded ); + + nextTicCount = ( size_t )( ( tics / 50.0 ) * expectedCount ); + if( count == ( expectedCount - 1 ) ) + { + if( tics < 51 ) + { + common->Printf( "*" ); + } + common->Printf( "\n" ); + } + + common->UpdateScreen( false ); + } + + count++; + } +}; + /* ==================================================================== @@ -1555,7 +1640,6 @@ struct localTrace_t localTrace_t R_LocalTrace( const idVec3& start, const idVec3& end, const float radius, const srfTriangles_t* tri ); - /* ============================================================ @@ -1586,6 +1670,9 @@ void RB_DrawBounds( const idBounds& bounds ); void RB_ShutdownDebugTools(); void RB_SetVertexColorParms( stageVertexColor_t svc ); + + + //============================================= #include "ResolutionScale.h" diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index a2124dee..fc9d236e 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -300,6 +300,7 @@ idCVar r_useHierarchicalDepthBuffer( "r_useHierarchicalDepthBuffer", "1", CVAR_R idCVar r_usePBR( "r_usePBR", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "use PBR and Image Based Lighting instead of old Quake 4 style ambient lighting" ); idCVar r_pbrDebug( "r_pbrDebug", "0", CVAR_RENDERER | CVAR_INTEGER, "show which materials have PBR support (green = PBR, red = oldschool D3)" ); idCVar r_showViewEnvprobes( "r_showViewEnvprobes", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = displays the bounding boxes of all view environment probes, 2 = show irradiance" ); +idCVar r_showLightGrid( "r_showLightGrid", "0", CVAR_RENDERER | CVAR_INTEGER, "show Quake 3 style light grid points" ); idCVar r_exposure( "r_exposure", "0.5", CVAR_ARCHIVE | CVAR_RENDERER | CVAR_FLOAT, "HDR exposure or LDR brightness [0.0 .. 1.0]", 0.0f, 1.0f ); // RB end @@ -1268,11 +1269,6 @@ void R_EnvShot_f( const idCmdArgs& args ) //============================================================================ -static idMat3 cubeAxis[6]; - - - - void R_TransformCubemap( const char* orgDirection[6], const char* orgDir, const char* destDirection[6], const char* destDir, const char* baseName ) { idStr fullname; @@ -1691,6 +1687,7 @@ void idRenderSystemLocal::Clear() guiRecursionLevel = 0; guiModel = NULL; memset( gammaTable, 0, sizeof( gammaTable ) ); + memset( &cubeAxis, 0, sizeof( cubeAxis ) ); // RB takingScreenshot = false; if( unitSquareTriangles != NULL ) @@ -1721,7 +1718,8 @@ void idRenderSystemLocal::Clear() // RB envprobeJobList = NULL; - irradianceJobs.Clear(); + envprobeJobs.Clear(); + lightGridJobs.Clear(); } /* @@ -2037,6 +2035,38 @@ void idRenderSystemLocal::Init() identitySpace.modelMatrix[1 * 4 + 1] = 1.0f; identitySpace.modelMatrix[2 * 4 + 2] = 1.0f; + // set cubemap axis for cubemap sampling tools + + // +X + cubeAxis[0][0][0] = 1; + cubeAxis[0][1][2] = 1; + cubeAxis[0][2][1] = 1; + + // -X + cubeAxis[1][0][0] = -1; + cubeAxis[1][1][2] = -1; + cubeAxis[1][2][1] = 1; + + // +Y + cubeAxis[2][0][1] = 1; + cubeAxis[2][1][0] = -1; + cubeAxis[2][2][2] = -1; + + // -Y + cubeAxis[3][0][1] = -1; + cubeAxis[3][1][0] = -1; + cubeAxis[3][2][2] = 1; + + // +Z + cubeAxis[4][0][2] = 1; + cubeAxis[4][1][0] = -1; + cubeAxis[4][2][1] = 1; + + // -Z + cubeAxis[5][0][2] = -1; + cubeAxis[5][1][0] = 1; + cubeAxis[5][2][1] = 1; + // make sure the tr.unitSquareTriangles data is current in the vertex / index cache if( unitSquareTriangles == NULL ) { diff --git a/neo/renderer/RenderWorld_envprobes.cpp b/neo/renderer/RenderWorld_envprobes.cpp index e3c53460..1dc45be9 100644 --- a/neo/renderer/RenderWorld_envprobes.cpp +++ b/neo/renderer/RenderWorld_envprobes.cpp @@ -171,7 +171,6 @@ void idRenderWorldLocal::AddAreaViewEnvprobes( int areaNum, const portalStack_t* R_SampleCubeMapHDR ================== */ -static idMat3 cubeAxis[6]; static const char* envDirection[6] = { "_px", "_nx", "_py", "_ny", "_pz", "_nz" }; void R_SampleCubeMapHDR( const idVec3& dir, int size, byte* buffers[6], float result[3], float& u, float& v ) @@ -208,8 +207,8 @@ void R_SampleCubeMapHDR( const idVec3& dir, int size, byte* buffers[6], float re axis = 5; } - float fx = ( dir * cubeAxis[axis][1] ) / ( dir * cubeAxis[axis][0] ); - float fy = ( dir * cubeAxis[axis][2] ) / ( dir * cubeAxis[axis][0] ); + float fx = ( dir * tr.cubeAxis[axis][1] ) / ( dir * tr.cubeAxis[axis][0] ); + float fy = ( dir * tr.cubeAxis[axis][2] ) / ( dir * tr.cubeAxis[axis][0] ); fx = -fx; fy = -fy; @@ -252,56 +251,7 @@ void R_SampleCubeMapHDR( const idVec3& dir, int size, byte* buffers[6], float re r11g11b10f_to_float3( tmp.i, result ); } -class CommandlineProgressBar -{ -private: - size_t tics = 0; - size_t nextTicCount = 0; - int count = 0; - int expectedCount = 0; -public: - CommandlineProgressBar( int _expectedCount ) - { - expectedCount = _expectedCount; - } - - void Start() - { - common->Printf( "0%% 10 20 30 40 50 60 70 80 90 100%%\n" ); - common->Printf( "|----|----|----|----|----|----|----|----|----|----|\n" ); - - common->UpdateScreen( false ); - } - - void Increment() - { - if( ( count + 1 ) >= nextTicCount ) - { - size_t ticsNeeded = ( size_t )( ( ( double )( count + 1 ) / expectedCount ) * 50.0 ); - - do - { - common->Printf( "*" ); - } - while( ++tics < ticsNeeded ); - - nextTicCount = ( size_t )( ( tics / 50.0 ) * expectedCount ); - if( count == ( expectedCount - 1 ) ) - { - if( tics < 51 ) - { - common->Printf( "*" ); - } - common->Printf( "\n" ); - } - - common->UpdateScreen( false ); - } - - count++; - } -}; // http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html @@ -921,7 +871,7 @@ void R_MakeAmbientMap( const char* baseName, const char* suffix, int outSize, bo jobParms->outHeight = outSize; jobParms->outBuffer = ( halfFloat_t* )R_StaticAlloc( idMath::Ceil( outSize * outSize * 3 * sizeof( halfFloat_t ) * 1.5f ), TAG_IMAGE ); - tr.irradianceJobs.Append( jobParms ); + tr.envprobeJobs.Append( jobParms ); if( useThreads ) { @@ -990,38 +940,6 @@ CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL const viewDef_t primary = *tr.primaryView; - memset( &cubeAxis, 0, sizeof( cubeAxis ) ); - - // +X - cubeAxis[0][0][0] = 1; - cubeAxis[0][1][2] = 1; - cubeAxis[0][2][1] = 1; - - // -X - cubeAxis[1][0][0] = -1; - cubeAxis[1][1][2] = -1; - cubeAxis[1][2][1] = 1; - - // +Y - cubeAxis[2][0][1] = 1; - cubeAxis[2][1][0] = -1; - cubeAxis[2][2][2] = -1; - - // -Y - cubeAxis[3][0][1] = -1; - cubeAxis[3][1][0] = -1; - cubeAxis[3][2][2] = 1; - - // +Z - cubeAxis[4][0][2] = 1; - cubeAxis[4][1][0] = -1; - cubeAxis[4][2][1] = 1; - - // -Z - cubeAxis[5][0][2] = -1; - cubeAxis[5][1][0] = 1; - cubeAxis[5][2][1] = 1; - //-------------------------------------------- // CAPTURE SCENE LIGHTING TO CUBEMAPS //-------------------------------------------- @@ -1042,7 +960,7 @@ CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL ref.fov_x = ref.fov_y = 90; ref.vieworg = def->parms.origin; - ref.viewaxis = cubeAxis[j]; + ref.viewaxis = tr.cubeAxis[j]; extension = envDirection[ j ]; fullname.Format( "env/%s/envprobe%i%s", baseName.c_str(), i, extension ); @@ -1082,9 +1000,9 @@ CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL tr.envprobeJobList->Wait(); } - for( int j = 0; j < tr.irradianceJobs.Num(); j++ ) + for( int j = 0; j < tr.envprobeJobs.Num(); j++ ) { - calcEnvprobeParms_t* job = tr.irradianceJobs[ j ]; + calcEnvprobeParms_t* job = tr.envprobeJobs[ j ]; R_WriteEXR( job->filename, ( byte* )job->outBuffer, 3, job->outWidth, job->outHeight, "fs_basepath" ); @@ -1103,7 +1021,7 @@ CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL delete job; } - tr.irradianceJobs.Clear(); + tr.envprobeJobs.Clear(); int end = Sys_Milliseconds(); diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp new file mode 100644 index 00000000..970500a0 --- /dev/null +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -0,0 +1,828 @@ +/* +=========================================================================== + +Doom 3 GPL Source Code +Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. +Copyright (C) 2013-2021 Robert Beckebans + +This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?). + +Doom 3 Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 Source Code. If not, see . + +In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ + +#include "precompiled.h" +#pragma hdrstop + +#include "RenderCommon.h" + +// RB: old constant from q3map2 +#define MAX_MAP_LIGHTGRID_POINTS 0x100000 + +void LightGrid::SetupLightGrid( const idBounds& bounds ) +{ + //idLib::Printf( "----- SetupLightGrid -----\n" ); + + lightGridSize.Set( 64, 64, 128 ); + lightGridPoints.Clear(); + + idVec3 maxs; + int j = 0; + int numGridPoints = MAX_MAP_LIGHTGRID_POINTS + 1; + while( numGridPoints > MAX_MAP_LIGHTGRID_POINTS ) + { + for( int i = 0; i < 3; i++ ) + { + lightGridOrigin[i] = lightGridSize[i] * ceil( bounds[0][i] / lightGridSize[i] ); + maxs[i] = lightGridSize[i] * floor( bounds[1][i] / lightGridSize[i] ); + lightGridBounds[i] = ( maxs[i] - lightGridOrigin[i] ) / lightGridSize[i] + 1; + } + + numGridPoints = lightGridBounds[0] * lightGridBounds[1] * lightGridBounds[2]; + + if( numGridPoints > MAX_MAP_LIGHTGRID_POINTS ) + { + lightGridSize[ j++ % 3 ] += 16.0f; + } + } + + idLib::Printf( "grid size (%i %i %i)\n", ( int )lightGridSize[0], ( int )lightGridSize[1], ( int )lightGridSize[2] ); + idLib::Printf( "grid bounds (%i %i %i)\n", ( int )lightGridBounds[0], ( int )lightGridBounds[1], ( int )lightGridBounds[2] ); + + idLib::Printf( "%i x %i x %i = %i grid points \n", lightGridBounds[0], lightGridBounds[1], lightGridBounds[2], numGridPoints ); + + lightGridPoints.SetNum( numGridPoints ); + + idLib::Printf( "%9u x %" PRIuSIZE " = lightGridSize = (%.2fMB)\n", numGridPoints, sizeof( lightGridPoint_t ), ( float )( lightGridPoints.MemoryUsed() ) / ( 1024.0f * 1024.0f ) ); + + CalculateLightGridPointPositions(); +} + +void LightGrid::ProbeIndexToGridIndex( const int probeIndex, int gridIndex[3] ) +{ + // slow brute force method only for debugging + int gridStep[3]; + + gridStep[0] = 1; + gridStep[1] = lightGridBounds[0]; + gridStep[2] = lightGridBounds[0] * lightGridBounds[1]; + + gridIndex[0] = 0; + gridIndex[1] = 0; + gridIndex[2] = 0; + + int p = 0; + for( int i = 0; i < lightGridBounds[0]; i += 1 ) + { + for( int j = 0; j < lightGridBounds[1]; j += 1 ) + { + for( int k = 0; k < lightGridBounds[2]; k += 1 ) + { + if( probeIndex == p ) + { + gridIndex[0] = i; + gridIndex[1] = j; + gridIndex[2] = k; + + return; + } + + p++; + } + } + } +} + +idVec3 LightGrid::GetProbeIndexDebugColor( const int probeIndex ) +{ + idVec3 color( colorGold.x, colorGold.y, colorGold.z ); + + int gridIndex[3]; + ProbeIndexToGridIndex( probeIndex, gridIndex ); + + color.x = float( gridIndex[0] & 1 ); + color.y = float( gridIndex[1] & 1 ); + color.z = float( gridIndex[2] & 1 ); + + color *= ( 1.0f / Max( color.x + color.y + color.z, 0.01f ) ); + color = color * 0.6f + idVec3( 0.2f ); + + return color; +} + +void LightGrid::CalculateLightGridPointPositions() +{ + // calculate grid point positions + int gridStep[3]; + int pos[3]; + idVec3 posFloat; + + gridStep[0] = 1; + gridStep[1] = lightGridBounds[0]; + gridStep[2] = lightGridBounds[0] * lightGridBounds[1]; + + int p = 0; + for( int i = 0; i < lightGridBounds[0]; i += 1 ) + { + for( int j = 0; j < lightGridBounds[1]; j += 1 ) + { + for( int k = 0; k < lightGridBounds[2]; k += 1 ) + { + pos[0] = i; + pos[1] = j; + pos[2] = k; + + posFloat[0] = i * lightGridSize[0]; + posFloat[1] = j * lightGridSize[1]; + posFloat[2] = k * lightGridSize[2]; + + lightGridPoint_t* gridPoint = &lightGridPoints[ pos[0] * gridStep[0] + pos[1] * gridStep[1] + pos[2] * gridStep[2] ]; + + gridPoint->origin = lightGridOrigin + posFloat; + + p++; + } + } + } +} + +void idRenderWorldLocal::SetupLightGrid() +{ + idLib::Printf( "----- SetupLightGrid -----\n" ); + + idBounds bounds; + bounds.Clear(); + + for( int i = 0; i < numPortalAreas; i++ ) + { + portalArea_t* area = &portalAreas[i]; + + bounds.AddBounds( area->globalBounds ); + } + + lightGrid.SetupLightGrid( bounds ); +} + + +static const char* envDirection[6] = { "_px", "_nx", "_py", "_ny", "_pz", "_nz" }; + +/// http://www.mpia-hd.mpg.de/~mathar/public/mathar20051002.pdf +/// http://www.rorydriscoll.com/2012/01/15/cubemap-texel-solid-angle/ +static inline float AreaElement( float _x, float _y ) +{ + return atan2f( _x * _y, sqrtf( _x * _x + _y * _y + 1.0f ) ); +} + +/// u and v should be center adressing and in [-1.0 + invSize.. 1.0 - invSize] range. +static inline float CubemapTexelSolidAngle( float u, float v, float _invFaceSize ) +{ + // Specify texel area. + const float x0 = u - _invFaceSize; + const float x1 = u + _invFaceSize; + const float y0 = v - _invFaceSize; + const float y1 = v + _invFaceSize; + + // Compute solid angle of texel area. + const float solidAngle = AreaElement( x1, y1 ) + - AreaElement( x0, y1 ) + - AreaElement( x1, y0 ) + + AreaElement( x0, y0 ) + ; + + return solidAngle; +} + +static inline idVec3 MapXYSToDirection( uint64 x, uint64 y, uint64 s, uint64 width, uint64 height ) +{ + float u = ( ( x + 0.5f ) / float( width ) ) * 2.0f - 1.0f; + float v = ( ( y + 0.5f ) / float( height ) ) * 2.0f - 1.0f; + v *= -1.0f; + + idVec3 dir( 0, 0, 0 ); + + // +x, -x, +y, -y, +z, -z + switch( s ) + { + case 0: + dir = idVec3( 1.0f, v, -u ); + break; + case 1: + dir = idVec3( -1.0f, v, u ); + break; + case 2: + dir = idVec3( u, 1.0f, -v ); + break; + case 3: + dir = idVec3( u, -1.0f, v ); + break; + case 4: + dir = idVec3( u, v, 1.0f ); + break; + case 5: + dir = idVec3( -u, v, -1.0f ); + break; + } + + dir.Normalize(); + + return dir; +} + +void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) +{ + byte* buffers[6]; + + int start = Sys_Milliseconds(); + + for( int i = 0; i < 6; i++ ) + { + buffers[ i ] = parms->buffers[ i ]; + } + + const float invDstSize = 1.0f / float( parms->outHeight ); + + const int numMips = idMath::BitsForInteger( parms->outHeight ); + + const idVec2i sourceImageSize( parms->outHeight, parms->outHeight ); + + // build L4 Spherical Harmonics from source image + SphericalHarmonicsT shRadiance; + + for( int i = 0; i < shSize( 4 ); i++ ) + { + shRadiance[i].Zero(); + } + +#if 0 + + // build SH by only iterating over the octahedron + // RB: not used because I don't know the texel area of an octahedron pixel and the cubemap texel area is too small + // however it would be nice to use this because it would be 6 times faster + + idVec4 dstRect = R_CalculateMipRect( parms->outHeight, 0 ); + + for( int x = dstRect.x; x < ( dstRect.x + dstRect.z ); x++ ) + { + for( int y = dstRect.y; y < ( dstRect.y + dstRect.w ); y++ ) + { + idVec2 octCoord = NormalizedOctCoord( x, y, dstRect.z ); + + // convert UV coord to 3D direction + idVec3 dir; + + dir.FromOctahedral( octCoord ); + + float u, v; + idVec3 radiance; + R_SampleCubeMapHDR( dir, parms->outHeight, buffers, &radiance[0], u, v ); + + //radiance = dir * 0.5 + idVec3( 0.5f, 0.5f, 0.5f ); + + // convert from [0 .. size-1] to [-1.0 + invSize .. 1.0 - invSize] + const float uu = 2.0f * ( u * invDstSize ) - 1.0f; + const float vv = 2.0f * ( v * invDstSize ) - 1.0f; + + float texelArea = CubemapTexelSolidAngle( uu, vv, invDstSize ); + + const SphericalHarmonicsT& sh = shEvaluate<4>( dir ); + + bool shValid = true; + for( int i = 0; i < 25; i++ ) + { + if( IsNAN( sh[i] ) ) + { + shValid = false; + break; + } + } + + if( shValid ) + { + shAddWeighted( shRadiance, sh, radiance * texelArea ); + } + } + } + +#else + + // build SH by iterating over all cubemap pixels + + idVec4 dstRect = R_CalculateMipRect( parms->outHeight, 0 ); + + for( int side = 0; side < 6; side++ ) + { + for( int x = 0; x < sourceImageSize.x; x++ ) + { + for( int y = 0; y < sourceImageSize.y; y++ ) + { + // convert UV coord to 3D direction + idVec3 dir = MapXYSToDirection( x, y, side, sourceImageSize.x, sourceImageSize.y ); + + float u, v; + idVec3 radiance; + R_SampleCubeMapHDR( dir, parms->outHeight, buffers, &radiance[0], u, v ); + + //radiance = dir * 0.5 + idVec3( 0.5f, 0.5f, 0.5f ); + + // convert from [0 .. size-1] to [-1.0 + invSize .. 1.0 - invSize] + const float uu = 2.0f * ( u * invDstSize ) - 1.0f; + const float vv = 2.0f * ( v * invDstSize ) - 1.0f; + + float texelArea = CubemapTexelSolidAngle( uu, vv, invDstSize ); + + const SphericalHarmonicsT& sh = shEvaluate<4>( dir ); + + bool shValid = true; + for( int i = 0; i < 25; i++ ) + { + if( IsNAN( sh[i] ) ) + { + shValid = false; + break; + } + } + + if( shValid ) + { + shAddWeighted( shRadiance, sh, radiance * texelArea ); + } + } + } + } + +#endif + + // reset image to black + for( int x = 0; x < parms->outWidth; x++ ) + { + for( int y = 0; y < parms->outHeight; y++ ) + { + parms->outBuffer[( y * parms->outWidth + x ) * 3 + 0] = F32toF16( 0 ); + parms->outBuffer[( y * parms->outWidth + x ) * 3 + 1] = F32toF16( 0 ); + parms->outBuffer[( y * parms->outWidth + x ) * 3 + 2] = F32toF16( 0 ); + } + } + + for( int mip = 0; mip < numMips; mip++ ) + { + float roughness = ( float )mip / ( float )( numMips - 1 ); + + idVec4 dstRect = R_CalculateMipRect( parms->outHeight, 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 dir; + + dir.FromOctahedral( octCoord ); + + idVec3 outColor( 0, 0, 0 ); + +#if 1 + // generate ambient colors by evaluating the L4 Spherical Harmonics + SphericalHarmonicsT shDirection = shEvaluate<4>( dir ); + + idVec3 sampleIrradianceSh = shEvaluateDiffuse( shRadiance, dir ) / idMath::PI; + + outColor[0] = Max( 0.0f, sampleIrradianceSh.x ); + outColor[1] = Max( 0.0f, sampleIrradianceSh.y ); + outColor[2] = Max( 0.0f, sampleIrradianceSh.z ); +#else + // generate ambient colors using Monte Carlo method + for( int s = 0; s < parms->samples; s++ ) + { + idVec2 Xi = Hammersley2D( s, parms->samples ); + idVec3 H = ImportanceSampleGGX( Xi, dir, 0.95f ); + + float u, v; + idVec3 radiance; + R_SampleCubeMapHDR( H, parms->outHeight, buffers, &radiance[0], u, v ); + + outColor[0] += radiance[0]; + outColor[1] += radiance[1]; + outColor[2] += radiance[2]; + } + + outColor[0] /= parms->samples; + outColor[1] /= parms->samples; + outColor[2] /= parms->samples; +#endif + + //outColor = dir * 0.5 + idVec3( 0.5f, 0.5f, 0.5f ); + + parms->outBuffer[( y * parms->outWidth + x ) * 3 + 0] = F32toF16( outColor[0] ); + parms->outBuffer[( y * parms->outWidth + x ) * 3 + 1] = F32toF16( outColor[1] ); + parms->outBuffer[( y * parms->outWidth + x ) * 3 + 2] = F32toF16( outColor[2] ); + } + } + } + + int end = Sys_Milliseconds(); + + parms->time = end - start; +} + +REGISTER_PARALLEL_JOB( CalculateLightGridPointJob, "CalculateLightGridPointJob" ); + +void R_MakeAmbientGridPoint( const char* baseName, const char* suffix, int outSize, bool deleteTempFiles, bool useThreads ) +{ + idStr fullname; + renderView_t ref; + viewDef_t primary; + byte* buffers[6]; + int width = 0, height = 0; + + // 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; + } + } + + // set up the job + calcLightGridPointParms_t* jobParms = new calcLightGridPointParms_t; + + for( int i = 0; i < 6; i++ ) + { + jobParms->buffers[ i ] = buffers[ i ]; + } + + jobParms->samples = 1000; + jobParms->filename.Format( "env/%s%s.exr", baseName, suffix ); + + jobParms->printProgress = !useThreads; + + jobParms->outWidth = int( outSize * 1.5f ); + jobParms->outHeight = outSize; + jobParms->outBuffer = ( halfFloat_t* )R_StaticAlloc( idMath::Ceil( outSize * outSize * 3 * sizeof( halfFloat_t ) * 1.5f ), TAG_IMAGE ); + + tr.lightGridJobs.Append( jobParms ); + + if( useThreads ) + { + tr.envprobeJobList->AddJob( ( jobRun_t )CalculateLightGridPointJob, jobParms ); + } + else + { + CalculateLightGridPointJob( jobParms ); + } + + if( deleteTempFiles ) + { + for( int i = 0 ; i < 6 ; i++ ) + { + fullname.Format( "env/%s%s.exr", baseName, envDirection[i] ); + + fileSystem->RemoveFile( fullname ); + } + } +} + +CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) +{ + idStr fullname; + idStr baseName; + renderView_t ref; + int blends; + const char* extension; + int size; + + static const char* envDirection[6] = { "_px", "_nx", "_py", "_ny", "_pz", "_nz" }; + + if( !tr.primaryWorld ) + { + common->Printf( "No primary world loaded.\n" ); + return; + } + + bool useThreads = false; + + 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; + + //-------------------------------------------- + // CAPTURE SCENE LIGHTING TO CUBEMAPS + //-------------------------------------------- + + for( int i = 0; i < tr.primaryWorld->lightGrid.lightGridPoints.Num(); i++ ) + { + lightGridPoint_t* gridPoint = &tr.primaryWorld->lightGrid.lightGridPoints[i]; + + 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 = gridPoint->origin; + ref.viewaxis = tr.cubeAxis[j]; + + extension = envDirection[ j ]; + fullname.Format( "env/%s/lightgridpoint%i%s", baseName.c_str(), i, extension ); + + tr.TakeScreenshot( size, size, fullname, blends, &ref, EXR ); + //tr.CaptureRenderToFile( fullname, false ); + } + } + + + common->Printf( "Wrote a env set with the name %s\n", baseName.c_str() ); + + //-------------------------------------------- + // GENERATE IRRADIANCE + //-------------------------------------------- + + CommandlineProgressBar progressBar( tr.primaryWorld->lightGrid.lightGridPoints.Num() ); + if( !useThreads ) + { + progressBar.Start(); + } + + int start = Sys_Milliseconds(); + + for( int i = 0; i < tr.primaryWorld->lightGrid.lightGridPoints.Num(); i++ ) + { + lightGridPoint_t* gridPoint = &tr.primaryWorld->lightGrid.lightGridPoints[i]; + + fullname.Format( "%s/lightgridpoint%i", baseName.c_str(), i ); + + R_MakeAmbientGridPoint( fullname.c_str(), "_amb", IRRADIANCE_CUBEMAP_SIZE, true, useThreads ); + + if( !useThreads ) + { + progressBar.Increment(); + } + } + + if( useThreads ) + { + //tr.envprobeJobList->Submit(); + tr.envprobeJobList->Submit( NULL, JOBLIST_PARALLELISM_MAX_CORES ); + tr.envprobeJobList->Wait(); + } + + for( int j = 0; j < tr.lightGridJobs.Num(); j++ ) + { + calcLightGridPointParms_t* job = tr.lightGridJobs[ j ]; + + R_WriteEXR( job->filename, ( byte* )job->outBuffer, 3, job->outWidth, job->outHeight, "fs_basepath" ); + + common->Printf( "%s convolved in %5.1f seconds\n\n", job->filename.c_str(), job->time * 0.001f ); + + for( int i = 0; i < 6; i++ ) + { + if( job->buffers[i] ) + { + Mem_Free( job->buffers[i] ); + } + } + + Mem_Free( job->outBuffer ); + + delete job; + } + + tr.lightGridJobs.Clear(); + + int end = Sys_Milliseconds(); + + common->Printf( "convolved probes in %5.1f seconds\n\n", ( end - start ) * 0.001f ); +} + +#if 0 +// straight port of Quake 3 +void idRenderWorldLocal::SetupEntityGridLighting( idRenderEntityLocal* def ) +{ + // lighting calculations +#if 0 + if( def->lightgridCalculated ) + { + return; + } + + def->lightgridCalculated = true; +#endif + + if( lightGridPoints.Num() > 0 ) + { + idVec3 lightOrigin; + int pos[3]; + int i, j; + int gridPointIndex; + lightGridPoint_t* gridPoint; + lightGridPoint_t* gridPoint2; + float frac[3]; + int gridStep[3]; + idVec3 direction; + idVec3 direction2; + float lattitude; + float longitude; + float totalFactor; + +#if 0 + if( forcedOrigin ) + { + VectorCopy( forcedOrigin, lightOrigin ); + } + else + { + if( ent->e.renderfx & RF_LIGHTING_ORIGIN ) + { + // seperate lightOrigins are needed so an object that is + // sinking into the ground can still be lit, and so + // multi-part models can be lit identically + VectorCopy( ent->e.lightingOrigin, lightOrigin ); + } + else + { + VectorCopy( ent->e.origin, lightOrigin ); + } + } +#else + // some models, like empty particles have no volume +#if 1 + lightOrigin = def->parms.origin; +#else + if( def->referenceBounds.IsCleared() ) + { + lightOrigin = def->parms.origin; + } + else + { + lightOrigin = def->volumeMidPoint; + } +#endif + +#endif + + lightOrigin -= lightGridOrigin; + for( i = 0; i < 3; i++ ) + { + float v; + + v = lightOrigin[i] * ( 1.0f / lightGridSize[i] ); + pos[i] = floor( v ); + frac[i] = v - pos[i]; + if( pos[i] < 0 ) + { + pos[i] = 0; + } + else if( pos[i] >= lightGridBounds[i] - 1 ) + { + pos[i] = lightGridBounds[i] - 1; + } + } + + def->ambientLight.Zero(); + def->directedLight.Zero(); + direction.Zero(); + + // trilerp the light value + gridStep[0] = 1; + gridStep[1] = lightGridBounds[0]; + gridStep[2] = lightGridBounds[0] * lightGridBounds[1]; + + gridPointIndex = pos[0] * gridStep[0] + pos[1] * gridStep[1] + pos[2] * gridStep[2]; + gridPoint = &lightGridPoints[ gridPointIndex ]; + + totalFactor = 0; + for( i = 0; i < 8; i++ ) + { + float factor; + + factor = 1.0; + gridPoint2 = gridPoint; + for( j = 0; j < 3; j++ ) + { + if( i & ( 1 << j ) ) + { + int gridPointIndex2 = gridPointIndex + gridStep[j]; + + if( gridPointIndex2 < 0 || gridPointIndex2 >= lightGridPoints.Num() ) + { + continue; + } + + factor *= frac[j]; + + gridPoint2 = &lightGridPoints[ gridPointIndex + gridStep[j] ]; + } + else + { + factor *= ( 1.0f - frac[j] ); + } + } + + if( !( gridPoint2->ambient[0] + gridPoint2->ambient[1] + gridPoint2->ambient[2] ) ) + { + continue; // ignore samples in walls + } + + totalFactor += factor; + + def->ambientLight[0] += factor * gridPoint2->ambient[0] * ( 1.0f / 255.0f ); + def->ambientLight[1] += factor * gridPoint2->ambient[1] * ( 1.0f / 255.0f ); + def->ambientLight[2] += factor * gridPoint2->ambient[2] * ( 1.0f / 255.0f ); + + def->directedLight[0] += factor * gridPoint2->directed[0] * ( 1.0f / 255.0f ); + def->directedLight[1] += factor * gridPoint2->directed[1] * ( 1.0f / 255.0f ); + def->directedLight[2] += factor * gridPoint2->directed[2] * ( 1.0f / 255.0f ); + + lattitude = DEG2RAD( gridPoint2->latLong[1] * ( 360.0f / 255.0f ) ); + longitude = DEG2RAD( gridPoint2->latLong[0] * ( 360.0f / 255.0f ) ); + + direction2[0] = idMath::Cos( lattitude ) * idMath::Sin( longitude ); + direction2[1] = idMath::Sin( lattitude ) * idMath::Sin( longitude ); + direction2[2] = idMath::Cos( longitude ); + + direction += ( direction2 * factor ); + + //direction += ( gridPoint2->dir * factor ); + } + +#if 1 + if( totalFactor > 0 && totalFactor < 0.99 ) + { + totalFactor = 1.0f / totalFactor; + def->ambientLight *= totalFactor; + def->directedLight *= totalFactor; + } +#endif + + def->ambientLight[0] = idMath::ClampFloat( 0, 1, def->ambientLight[0] ); + def->ambientLight[1] = idMath::ClampFloat( 0, 1, def->ambientLight[1] ); + def->ambientLight[2] = idMath::ClampFloat( 0, 1, def->ambientLight[2] ); + + def->directedLight[0] = idMath::ClampFloat( 0, 1, def->directedLight[0] ); + def->directedLight[1] = idMath::ClampFloat( 0, 1, def->directedLight[1] ); + def->directedLight[2] = idMath::ClampFloat( 0, 1, def->directedLight[2] ); + + def->lightDir = direction; + def->lightDir.Normalize(); + +#if 0 + if( VectorLength( ent->ambientLight ) < r_forceAmbient->value ) + { + ent->ambientLight[0] = r_forceAmbient->value; + ent->ambientLight[1] = r_forceAmbient->value; + ent->ambientLight[2] = r_forceAmbient->value; + } +#endif + } +} + +#endif \ No newline at end of file diff --git a/neo/renderer/RenderWorld_load.cpp b/neo/renderer/RenderWorld_load.cpp index 8fd2de60..214cda72 100644 --- a/neo/renderer/RenderWorld_load.cpp +++ b/neo/renderer/RenderWorld_load.cpp @@ -858,6 +858,7 @@ bool idRenderWorldLocal::InitFromMap( const char* name ) TouchWorldModels(); AddWorldModelEntities(); ClearPortalStates(); + SetupLightGrid(); return true; } common->Printf( "idRenderWorldLocal::InitFromMap: timestamp has changed, reloading.\n" ); @@ -1047,6 +1048,7 @@ bool idRenderWorldLocal::InitFromMap( const char* name ) AddWorldModelEntities(); ClearPortalStates(); + SetupLightGrid(); // done! return true; diff --git a/neo/renderer/RenderWorld_local.h b/neo/renderer/RenderWorld_local.h index 7881eb8f..07022908 100644 --- a/neo/renderer/RenderWorld_local.h +++ b/neo/renderer/RenderWorld_local.h @@ -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-2016 Robert Beckebans +Copyright (C) 2014-2021 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"). @@ -59,6 +59,42 @@ typedef struct doublePortal_s struct doublePortal_s* nextFoggedPortal; } doublePortal_t; +// RB: added Quake 3 style light grid +struct lightGridPoint_t +{ + idVec3 origin; // not saved to .proc + + byte ambient[3]; + byte directed[3]; + byte latLong[2]; +}; + +class LightGrid +{ +private: + idVec3 lightGridOrigin; + idVec3 lightGridSize; + int lightGridBounds[3]; + +public: + idList lightGridPoints; + + //LightGrid(); + + // setup light grid for given world bounds + void SetupLightGrid( const idBounds& bounds ); + + void ProbeIndexToGridIndex( const int probeIndex, int gridIndex[3] ); + + idVec3 GetProbeIndexDebugColor( const int probeIndex ); + + // fetch grid lighting on a per object basis + void SetupEntityGridLighting( idRenderEntityLocal* def ); + +private: + void CalculateLightGridPointPositions(); +}; +// RB end typedef struct portalArea_s { @@ -187,6 +223,9 @@ public: doublePortal_t* doublePortals; int numInterAreaPortals; + // RB: added Quake 3 style light grid + LightGrid lightGrid; + idList localModels; idList entityDefs; @@ -337,6 +376,15 @@ public: //------------------------------- // tr_light.c void CreateLightDefInteractions( idRenderLightLocal* const ldef, const int renderViewID ); + +// RB begin + + //-------------------------- + // RenderWorld_lightgrid.cpp + +private: + void SetupLightGrid(); +// RB end }; // if an entity / light combination has been evaluated and found to not genrate any surfaces or shadows, From 99c7d58dc606d46837a83dc830c08a84e7a2232d Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Tue, 13 Apr 2021 17:51:16 +0200 Subject: [PATCH 02/26] Compute irradiance for each light grid point --- neo/renderer/OpenGL/RenderDebug_GL.cpp | 28 ++++- neo/renderer/RenderCommon.h | 14 ++- neo/renderer/RenderSystem.h | 3 + neo/renderer/RenderSystem_init.cpp | 44 +++++++- neo/renderer/RenderWorld_envprobes.cpp | 69 +++++++++++- neo/renderer/RenderWorld_lightgrid.cpp | 147 +++++++++++++++++-------- neo/renderer/RenderWorld_local.h | 5 +- 7 files changed, 247 insertions(+), 63 deletions(-) diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index a610faf8..14c32a04 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1724,11 +1724,10 @@ void idRenderBackend::DBG_ShowViewEnvprobes() GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_DEPTHMASK ); GL_Color( 1.0f, 1.0f, 1.0f ); - float modelMatrix[16]; - idMat3 axis; axis.Identity(); + float modelMatrix[16]; R_AxisToModelMatrix( axis, vProbe->globalOrigin, modelMatrix ); idRenderMatrix modelRenderMatrix; @@ -1795,7 +1794,8 @@ void idRenderBackend::DBG_ShowLightGrid() } // all volumes are expressed in world coordinates - renderProgManager.BindShader_Color(); + //renderProgManager.BindShader_Color(); + renderProgManager.BindShader_Octahedron(); GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_DEPTHMASK ); GL_Color( 1.0f, 1.0f, 1.0f ); @@ -1842,8 +1842,30 @@ void idRenderBackend::DBG_ShowLightGrid() glEnd(); */ +#if 1 + idVec4 localViewOrigin( 1.0f ); + idVec4 globalViewOrigin; + globalViewOrigin.x = viewDef->renderView.vieworg.x; + globalViewOrigin.y = viewDef->renderView.vieworg.y; + globalViewOrigin.z = viewDef->renderView.vieworg.z; + globalViewOrigin.w = 1.0f; + + float modelMatrix[16]; + R_AxisToModelMatrix( axis, gridPoint->origin, modelMatrix ); + + R_GlobalPointToLocal( modelMatrix, viewDef->renderView.vieworg, localViewOrigin.ToVec3() ); + + renderProgManager.SetUniformValue( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); // rpLocalViewOrigin +#endif + + +#if 0 idVec3 color = tr.primaryWorld->lightGrid.GetProbeIndexDebugColor( i ); GL_Color( color ); +#else + GL_SelectTexture( 0 ); + gridPoint->irradianceImage->Bind(); +#endif idRenderMatrix modelRenderMatrix; idRenderMatrix::CreateFromOriginAxis( gridPoint->origin, axis, modelRenderMatrix ); diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index b8f6d8f2..d766e3ed 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -505,16 +505,11 @@ struct calcEnvprobeParms_t struct calcLightGridPointParms_t { // input - byte* buffers[6]; // HDR R11G11B11F standard OpenGL cubemap sides - int samples; + byte* buffers[6]; // HDR RGB16F standard OpenGL cubemap sides int outWidth; int outHeight; - bool printProgress; - - idStr filename; - // output halfFloat_t* outBuffer; // HDR R11G11B11F packed atlas int time; // execution time in milliseconds @@ -876,6 +871,7 @@ public: virtual void RenderCommandBuffers( const emptyCommand_t* commandBuffers ); virtual void TakeScreenshot( int width, int height, const char* fileName, int downSample, renderView_t* ref, int exten ); + virtual byte* CaptureRenderToBuffer( int width, int height, renderView_t* ref ); virtual void CropRenderSize( int width, int height ); virtual void CaptureRenderToImage( const char* imageName, bool clearColorAfterCopy = false ); virtual void CaptureRenderToFile( const char* fileName, bool fixAlpha ); @@ -1380,6 +1376,7 @@ RENDERWORLD_ENVPROBES */ void R_SampleCubeMapHDR( const idVec3& dir, int size, byte* buffers[6], float result[3], float& u, float& v ); +void R_SampleCubeMapHDR16F( const idVec3& dir, int size, halfFloat_t* buffers[6], float result[3], float& u, float& v ); idVec2 NormalizedOctCoord( int x, int y, const int probeSideLength ); @@ -1432,6 +1429,11 @@ public: count++; } + + void Reset() + { + count = 0; + } }; /* diff --git a/neo/renderer/RenderSystem.h b/neo/renderer/RenderSystem.h index d37ed5e6..4db32ab6 100644 --- a/neo/renderer/RenderSystem.h +++ b/neo/renderer/RenderSystem.h @@ -405,6 +405,9 @@ public: // markers. Use WriteRender() instead. virtual void TakeScreenshot( int width, int height, const char* fileName, int samples, struct renderView_s* ref, int exten ) = 0; + // RB + virtual byte* CaptureRenderToBuffer( int width, int height, renderView_t* ref ) = 0; + // the render output can be cropped down to a subset of the real screen, as // for save-game reviews and split-screen multiplayer. Users of the renderer // will not know the actual pixel size of the area they are rendering to diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index fc9d236e..019f2bb4 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -737,7 +737,7 @@ void R_ReadTiledPixels( int width, int height, byte* buffer, renderView_t* ref = if( ref && ref->rdflags & RDF_IRRADIANCE ) { // * 2 = sizeof( half float ) - temp = ( byte* )R_StaticAlloc( RADIANCE_CUBEMAP_SIZE * RADIANCE_CUBEMAP_SIZE * 3 * 2 ); + //temp = ( byte* )R_StaticAlloc( RADIANCE_CUBEMAP_SIZE * RADIANCE_CUBEMAP_SIZE * 3 * 2 ); } else { @@ -764,8 +764,12 @@ void R_ReadTiledPixels( int width, int height, byte* buffer, renderView_t* ref = int originalNativeWidth = glConfig.nativeScreenWidth; int originalNativeHeight = glConfig.nativeScreenHeight; - glConfig.nativeScreenWidth = sysWidth; - glConfig.nativeScreenHeight = sysHeight; + + //if( !ref || ( ref && !( ref->rdflags & RDF_IRRADIANCE ) ) ) + { + glConfig.nativeScreenWidth = sysWidth; + glConfig.nativeScreenHeight = sysHeight; + } #endif // disable scissor, so we don't need to adjust all those rects @@ -864,8 +868,11 @@ void R_ReadTiledPixels( int width, int height, byte* buffer, renderView_t* ref = // discard anything currently on the list tr.SwapCommandBuffers( NULL, NULL, NULL, NULL, NULL, NULL ); - glConfig.nativeScreenWidth = originalNativeWidth; - glConfig.nativeScreenHeight = originalNativeHeight; + if( !ref || ( ref && !( ref->rdflags & RDF_IRRADIANCE ) ) ) + { + glConfig.nativeScreenWidth = originalNativeWidth; + glConfig.nativeScreenHeight = originalNativeHeight; + } #endif r_useScissor.SetBool( true ); @@ -1010,6 +1017,33 @@ void idRenderSystemLocal::TakeScreenshot( int width, int height, const char* fil takingScreenshot = false; } +// RB begin +byte* idRenderSystemLocal::CaptureRenderToBuffer( int width, int height, renderView_t* ref ) +{ + byte* buffer; + + takingScreenshot = true; + + int pix = width * height; + const int bufferSize = pix * 3 + 18; + + // HDR only for now + //if( exten == EXR ) + { + buffer = ( byte* )R_StaticAlloc( pix * 3 * 2 ); + } + //else if( exten == PNG ) + //{ + // buffer = ( byte* )R_StaticAlloc( pix * 3 ); + //} + + R_ReadTiledPixels( width, height, buffer, ref ); + + takingScreenshot = false; + + return buffer; +} + /* ================== R_ScreenshotFilename diff --git a/neo/renderer/RenderWorld_envprobes.cpp b/neo/renderer/RenderWorld_envprobes.cpp index 1dc45be9..2e3f629b 100644 --- a/neo/renderer/RenderWorld_envprobes.cpp +++ b/neo/renderer/RenderWorld_envprobes.cpp @@ -251,6 +251,73 @@ void R_SampleCubeMapHDR( const idVec3& dir, int size, byte* buffers[6], float re r11g11b10f_to_float3( tmp.i, result ); } +void R_SampleCubeMapHDR16F( const idVec3& dir, int size, halfFloat_t* buffers[6], float result[3], float& u, float& v ) +{ + float adir[3]; + int axis, x, y; + + adir[0] = fabs( dir[0] ); + adir[1] = fabs( dir[1] ); + adir[2] = fabs( dir[2] ); + + if( dir[0] >= adir[1] && dir[0] >= adir[2] ) + { + axis = 0; + } + else if( -dir[0] >= adir[1] && -dir[0] >= adir[2] ) + { + axis = 1; + } + else if( dir[1] >= adir[0] && dir[1] >= adir[2] ) + { + axis = 2; + } + else if( -dir[1] >= adir[0] && -dir[1] >= adir[2] ) + { + axis = 3; + } + else if( dir[2] >= adir[1] && dir[2] >= adir[2] ) + { + axis = 4; + } + else + { + axis = 5; + } + + float fx = ( dir * tr.cubeAxis[axis][1] ) / ( dir * tr.cubeAxis[axis][0] ); + float fy = ( dir * tr.cubeAxis[axis][2] ) / ( dir * tr.cubeAxis[axis][0] ); + + fx = -fx; + fy = -fy; + x = size * 0.5 * ( fx + 1 ); + y = size * 0.5 * ( fy + 1 ); + if( x < 0 ) + { + x = 0; + } + else if( x >= size ) + { + x = size - 1; + } + if( y < 0 ) + { + y = 0; + } + else if( y >= size ) + { + y = size - 1; + } + + u = x; + v = y; + + // unpack RGB16F to 3 floats + result[0] = F16toF32( buffers[axis][( y * size + x ) * 3 + 0] ); + result[1] = F16toF32( buffers[axis][( y * size + x ) * 3 + 1] ); + result[2] = F16toF32( buffers[axis][( y * size + x ) * 3 + 2] ); +} + @@ -990,7 +1057,7 @@ CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL fullname.Format( "%s/envprobe%i", baseName.c_str(), i ); R_MakeAmbientMap( fullname.c_str(), "_amb", IRRADIANCE_CUBEMAP_SIZE, false, false, useThreads ); - R_MakeAmbientMap( fullname.c_str(), "_spec", RADIANCE_CUBEMAP_SIZE, true, true, useThreads ); + R_MakeAmbientMap( fullname.c_str(), "_spec", RADIANCE_CUBEMAP_SIZE, true, false, useThreads ); } if( useThreads ) diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 970500a0..9e92a0b1 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -33,9 +33,11 @@ If you have questions concerning this license or the applicable additional terms #include "RenderCommon.h" // RB: old constant from q3map2 -#define MAX_MAP_LIGHTGRID_POINTS 0x100000 +static const int MAX_MAP_LIGHTGRID_POINTS = 0x100000; -void LightGrid::SetupLightGrid( const idBounds& bounds ) +static const int LIGHTGRID_IRRADIANCE_SIZE = 32; + +void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName ) { //idLib::Printf( "----- SetupLightGrid -----\n" ); @@ -72,6 +74,20 @@ void LightGrid::SetupLightGrid( const idBounds& bounds ) idLib::Printf( "%9u x %" PRIuSIZE " = lightGridSize = (%.2fMB)\n", numGridPoints, sizeof( lightGridPoint_t ), ( float )( lightGridPoints.MemoryUsed() ) / ( 1024.0f * 1024.0f ) ); CalculateLightGridPointPositions(); + + // try to load existing lightgrid data + idStr basename = mapName; + basename.StripFileExtension(); + + idStr fullname; + + for( int i = 0; i < lightGridPoints.Num(); i++ ) + { + lightGridPoint_t* gridPoint = &lightGridPoints[i]; + + fullname.Format( "env/%s/lightgridpoint%i_amb", basename.c_str(), i ); + gridPoint->irradianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); + } } void LightGrid::ProbeIndexToGridIndex( const int probeIndex, int gridIndex[3] ) @@ -176,7 +192,7 @@ void idRenderWorldLocal::SetupLightGrid() bounds.AddBounds( area->globalBounds ); } - lightGrid.SetupLightGrid( bounds ); + lightGrid.SetupLightGrid( bounds, mapName ); } @@ -246,13 +262,13 @@ static inline idVec3 MapXYSToDirection( uint64 x, uint64 y, uint64 s, uint64 wid void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) { - byte* buffers[6]; + halfFloat_t* buffers[6]; int start = Sys_Milliseconds(); for( int i = 0; i < 6; i++ ) { - buffers[ i ] = parms->buffers[ i ]; + buffers[ i ] = ( halfFloat_t* ) parms->buffers[ i ]; } const float invDstSize = 1.0f / float( parms->outHeight ); @@ -336,7 +352,7 @@ void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) float u, v; idVec3 radiance; - R_SampleCubeMapHDR( dir, parms->outHeight, buffers, &radiance[0], u, v ); + R_SampleCubeMapHDR16F( dir, parms->outHeight, buffers, &radiance[0], u, v ); //radiance = dir * 0.5 + idVec3( 0.5f, 0.5f, 0.5f ); @@ -453,6 +469,7 @@ void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) REGISTER_PARALLEL_JOB( CalculateLightGridPointJob, "CalculateLightGridPointJob" ); +#if 0 void R_MakeAmbientGridPoint( const char* baseName, const char* suffix, int outSize, bool deleteTempFiles, bool useThreads ) { idStr fullname; @@ -489,10 +506,10 @@ void R_MakeAmbientGridPoint( const char* baseName, const char* suffix, int outSi jobParms->buffers[ i ] = buffers[ i ]; } - jobParms->samples = 1000; - jobParms->filename.Format( "env/%s%s.exr", baseName, suffix ); +// jobParms->samples = 1000; +// jobParms->filename.Format( "env/%s%s.exr", baseName, suffix ); - jobParms->printProgress = !useThreads; +// jobParms->printProgress = !useThreads; jobParms->outWidth = int( outSize * 1.5f ); jobParms->outHeight = outSize; @@ -519,11 +536,12 @@ void R_MakeAmbientGridPoint( const char* baseName, const char* suffix, int outSi } } } +#endif CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) { - idStr fullname; idStr baseName; + idStr filename; renderView_t ref; int blends; const char* extension; @@ -557,35 +575,6 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) // CAPTURE SCENE LIGHTING TO CUBEMAPS //-------------------------------------------- - for( int i = 0; i < tr.primaryWorld->lightGrid.lightGridPoints.Num(); i++ ) - { - lightGridPoint_t* gridPoint = &tr.primaryWorld->lightGrid.lightGridPoints[i]; - - 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 = gridPoint->origin; - ref.viewaxis = tr.cubeAxis[j]; - - extension = envDirection[ j ]; - fullname.Format( "env/%s/lightgridpoint%i%s", baseName.c_str(), i, extension ); - - tr.TakeScreenshot( size, size, fullname, blends, &ref, EXR ); - //tr.CaptureRenderToFile( fullname, false ); - } - } - - - common->Printf( "Wrote a env set with the name %s\n", baseName.c_str() ); - - //-------------------------------------------- - // GENERATE IRRADIANCE - //-------------------------------------------- - CommandlineProgressBar progressBar( tr.primaryWorld->lightGrid.lightGridPoints.Num() ); if( !useThreads ) { @@ -598,12 +587,72 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) { lightGridPoint_t* gridPoint = &tr.primaryWorld->lightGrid.lightGridPoints[i]; - fullname.Format( "%s/lightgridpoint%i", baseName.c_str(), i ); + calcLightGridPointParms_t* jobParms = new calcLightGridPointParms_t; - R_MakeAmbientGridPoint( fullname.c_str(), "_amb", IRRADIANCE_CUBEMAP_SIZE, true, useThreads ); - - if( !useThreads ) + 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 = gridPoint->origin; + ref.viewaxis = tr.cubeAxis[j]; + + extension = envDirection[ j ]; + + //tr.TakeScreenshot( size, size, fullname, blends, &ref, EXR ); + byte* float16FRGB = tr.CaptureRenderToBuffer( size, size, &ref ); + + jobParms->buffers[ j ] = float16FRGB; + +#if 0 + if( i < 3 ) + { + filename.Format( "env/%s/lightgridpoint%i%s.exr", baseName.c_str(), i, extension ); + R_WriteEXR( filename, float16FRGB, 3, size, size, "fs_basepath" ); + } +#endif + } + + tr.lightGridJobs.Append( jobParms ); + + progressBar.Increment(); + } + + int end = Sys_Milliseconds(); + + common->Printf( "captured light grid radiance in %5.1f seconds\n\n", ( end - start ) * 0.001f ); + + //common->Printf( "Wrote a env set with the name %s\n", baseName.c_str() ); + + //-------------------------------------------- + // GENERATE IRRADIANCE + //-------------------------------------------- + + if( !useThreads ) + { + progressBar.Reset(); + progressBar.Start(); + } + + start = Sys_Milliseconds(); + + for( int j = 0; j < tr.lightGridJobs.Num(); j++ ) + { + calcLightGridPointParms_t* jobParms = tr.lightGridJobs[ j ]; + + jobParms->outWidth = int( IRRADIANCE_CUBEMAP_SIZE * 1.5f ); + jobParms->outHeight = IRRADIANCE_CUBEMAP_SIZE; + jobParms->outBuffer = ( halfFloat_t* )R_StaticAlloc( idMath::Ceil( IRRADIANCE_CUBEMAP_SIZE * IRRADIANCE_CUBEMAP_SIZE * 3 * sizeof( halfFloat_t ) * 1.5f ), TAG_IMAGE ); + + if( useThreads ) + { + tr.envprobeJobList->AddJob( ( jobRun_t )CalculateLightGridPointJob, jobParms ); + } + else + { + CalculateLightGridPointJob( jobParms ); progressBar.Increment(); } } @@ -615,13 +664,17 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) tr.envprobeJobList->Wait(); } + + for( int j = 0; j < tr.lightGridJobs.Num(); j++ ) { calcLightGridPointParms_t* job = tr.lightGridJobs[ j ]; - R_WriteEXR( job->filename, ( byte* )job->outBuffer, 3, job->outWidth, job->outHeight, "fs_basepath" ); + filename.Format( "env/%s/lightgridpoint%i_amb.exr", baseName.c_str(), j ); - common->Printf( "%s convolved in %5.1f seconds\n\n", job->filename.c_str(), job->time * 0.001f ); + R_WriteEXR( filename.c_str(), ( byte* )job->outBuffer, 3, job->outWidth, job->outHeight, "fs_basepath" ); + + //common->Printf( "%s convolved in %5.1f seconds\n\n", filename.c_str(), job->time * 0.001f ); for( int i = 0; i < 6; i++ ) { @@ -638,9 +691,9 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) tr.lightGridJobs.Clear(); - int end = Sys_Milliseconds(); + end = Sys_Milliseconds(); - common->Printf( "convolved probes in %5.1f seconds\n\n", ( end - start ) * 0.001f ); + common->Printf( "computed light grid irradiance in %5.1f seconds\n\n", ( end - start ) * 0.001f ); } #if 0 diff --git a/neo/renderer/RenderWorld_local.h b/neo/renderer/RenderWorld_local.h index 07022908..e939f2f0 100644 --- a/neo/renderer/RenderWorld_local.h +++ b/neo/renderer/RenderWorld_local.h @@ -67,6 +67,9 @@ struct lightGridPoint_t byte ambient[3]; byte directed[3]; byte latLong[2]; + + // TODO REMOVE just for testing + idImage* irradianceImage; }; class LightGrid @@ -82,7 +85,7 @@ public: //LightGrid(); // setup light grid for given world bounds - void SetupLightGrid( const idBounds& bounds ); + void SetupLightGrid( const idBounds& bounds, const char* baseName ); void ProbeIndexToGridIndex( const int probeIndex, int gridIndex[3] ); From f1e54f249b473696511cfa6bb0ca7019bc27a246 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Tue, 13 Apr 2021 19:53:02 +0200 Subject: [PATCH 03/26] Splitted light grid up into multiple for each BSP area --- neo/renderer/OpenGL/RenderDebug_GL.cpp | 127 ++++++++++++++----------- neo/renderer/RenderCommon.h | 1 + neo/renderer/RenderWorld_lightgrid.cpp | 116 ++++++++++++++-------- neo/renderer/RenderWorld_local.h | 12 ++- 4 files changed, 158 insertions(+), 98 deletions(-) diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index 14c32a04..cf58cca2 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1794,8 +1794,8 @@ void idRenderBackend::DBG_ShowLightGrid() } // all volumes are expressed in world coordinates - //renderProgManager.BindShader_Color(); - renderProgManager.BindShader_Octahedron(); + renderProgManager.BindShader_Color(); + //renderProgManager.BindShader_Octahedron(); GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_DEPTHMASK ); GL_Color( 1.0f, 1.0f, 1.0f ); @@ -1803,85 +1803,102 @@ void idRenderBackend::DBG_ShowLightGrid() idMat3 axis; axis.Identity(); - for( int i = 0; i < tr.primaryWorld->lightGrid.lightGridPoints.Num(); i++ ) + //for( int a = 0; a < tr.primaryWorld->NumAreas(); a++ ) + + // only show current area + int a = tr.primaryWorld->PointInArea( viewDef->renderView.vieworg ); + if( a == -1 ) { - lightGridPoint_t* gridPoint = &tr.primaryWorld->lightGrid.lightGridPoints[i]; + return; + } - idVec3 distanceToCam = gridPoint->origin - viewDef->renderView.vieworg; - if( distanceToCam.LengthSqr() > ( 1024 * 1024 ) ) + { + portalArea_t* area = &tr.primaryWorld->portalAreas[a]; + + for( int i = 0; i < area->lightGrid.lightGridPoints.Num(); i++ ) { - continue; - } + lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i]; + if( !gridPoint->valid ) + { + continue; + } - /* - idVec4 c; - c[0] = idMath::ClampFloat( 0, 1, gridPoint->directed[0] * ( 1.0f / 255.0f ) ); - c[1] = idMath::ClampFloat( 0, 1, gridPoint->directed[1] * ( 1.0f / 255.0f ) ); - c[2] = idMath::ClampFloat( 0, 1, gridPoint->directed[2] * ( 1.0f / 255.0f ) ); + idVec3 distanceToCam = gridPoint->origin - viewDef->renderView.vieworg; + if( distanceToCam.LengthSqr() > ( 1024 * 1024 ) ) + { + continue; + } - glColor4f( c[0], c[1], c[2], 1 ); + /* + idVec4 c; + c[0] = idMath::ClampFloat( 0, 1, gridPoint->directed[0] * ( 1.0f / 255.0f ) ); + c[1] = idMath::ClampFloat( 0, 1, gridPoint->directed[1] * ( 1.0f / 255.0f ) ); + c[2] = idMath::ClampFloat( 0, 1, gridPoint->directed[2] * ( 1.0f / 255.0f ) ); - float lattitude = DEG2RAD( gridPoint->latLong[1] * ( 360.0f / 255.0f ) ); - float longitude = DEG2RAD( gridPoint->latLong[0] * ( 360.0f / 255.0f ) ); + glColor4f( c[0], c[1], c[2], 1 ); - idVec3 dir; - dir[0] = idMath::Cos( lattitude ) * idMath::Sin( longitude ); - dir[1] = idMath::Sin( lattitude ) * idMath::Sin( longitude ); - dir[2] = idMath::Cos( longitude ); + float lattitude = DEG2RAD( gridPoint->latLong[1] * ( 360.0f / 255.0f ) ); + float longitude = DEG2RAD( gridPoint->latLong[0] * ( 360.0f / 255.0f ) ); - idVec3 pos2 = gridPoint->origin - dir * r_showLightGrid.GetFloat(); + idVec3 dir; + dir[0] = idMath::Cos( lattitude ) * idMath::Sin( longitude ); + dir[1] = idMath::Sin( lattitude ) * idMath::Sin( longitude ); + dir[2] = idMath::Cos( longitude ); - glBegin( GL_LINES ); + idVec3 pos2 = gridPoint->origin - dir * r_showLightGrid.GetFloat(); - glColor4f( c[0], c[1], c[2], 1 ); - //glColor4f( 1, 1, 1, 1 ); - glVertex3fv( gridPoint->origin.ToFloatPtr() ); + glBegin( GL_LINES ); - glColor4f( 0, 0, 0, 1 ); - glVertex3fv( pos2.ToFloatPtr() ); - glEnd(); - */ + glColor4f( c[0], c[1], c[2], 1 ); + //glColor4f( 1, 1, 1, 1 ); + glVertex3fv( gridPoint->origin.ToFloatPtr() ); + + glColor4f( 0, 0, 0, 1 ); + glVertex3fv( pos2.ToFloatPtr() ); + glEnd(); + */ #if 1 - idVec4 localViewOrigin( 1.0f ); - idVec4 globalViewOrigin; - globalViewOrigin.x = viewDef->renderView.vieworg.x; - globalViewOrigin.y = viewDef->renderView.vieworg.y; - globalViewOrigin.z = viewDef->renderView.vieworg.z; - globalViewOrigin.w = 1.0f; + idVec4 localViewOrigin( 1.0f ); + idVec4 globalViewOrigin; + globalViewOrigin.x = viewDef->renderView.vieworg.x; + globalViewOrigin.y = viewDef->renderView.vieworg.y; + globalViewOrigin.z = viewDef->renderView.vieworg.z; + globalViewOrigin.w = 1.0f; - float modelMatrix[16]; - R_AxisToModelMatrix( axis, gridPoint->origin, modelMatrix ); + float modelMatrix[16]; + R_AxisToModelMatrix( axis, gridPoint->origin, modelMatrix ); - R_GlobalPointToLocal( modelMatrix, viewDef->renderView.vieworg, localViewOrigin.ToVec3() ); + R_GlobalPointToLocal( modelMatrix, viewDef->renderView.vieworg, localViewOrigin.ToVec3() ); - renderProgManager.SetUniformValue( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); // rpLocalViewOrigin + renderProgManager.SetUniformValue( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); // rpLocalViewOrigin #endif -#if 0 - idVec3 color = tr.primaryWorld->lightGrid.GetProbeIndexDebugColor( i ); - GL_Color( color ); +#if 1 + idVec3 color = area->lightGrid.GetProbeIndexDebugColor( i ); + GL_Color( color ); #else - GL_SelectTexture( 0 ); - gridPoint->irradianceImage->Bind(); + GL_SelectTexture( 0 ); + gridPoint->irradianceImage->Bind(); #endif - idRenderMatrix modelRenderMatrix; - idRenderMatrix::CreateFromOriginAxis( gridPoint->origin, axis, modelRenderMatrix ); + idRenderMatrix modelRenderMatrix; + idRenderMatrix::CreateFromOriginAxis( gridPoint->origin, axis, modelRenderMatrix ); - // calculate the matrix that transforms the unit cube to exactly cover the model in world space - const float size = 3.0f; - idBounds debugBounds( idVec3( -size ), idVec3( size ) ); + // calculate the matrix that transforms the unit cube to exactly cover the model in world space + const float size = 3.0f; + idBounds debugBounds( idVec3( -size ), idVec3( size ) ); - idRenderMatrix inverseBaseModelProject; - idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject ); + idRenderMatrix inverseBaseModelProject; + idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject ); - idRenderMatrix invProjectMVPMatrix; - idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix ); - RB_SetMVP( invProjectMVPMatrix ); + idRenderMatrix invProjectMVPMatrix; + idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix ); + RB_SetMVP( invProjectMVPMatrix ); - DrawElementsWithCounters( &zeroOneSphereSurface ); + DrawElementsWithCounters( &zeroOneSphereSurface ); + } } } diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index d766e3ed..5a664c26 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -506,6 +506,7 @@ struct calcLightGridPointParms_t { // input byte* buffers[6]; // HDR RGB16F standard OpenGL cubemap sides + int area; int outWidth; int outHeight; diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 9e92a0b1..8e2f6264 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -37,13 +37,15 @@ static const int MAX_MAP_LIGHTGRID_POINTS = 0x100000; static const int LIGHTGRID_IRRADIANCE_SIZE = 32; -void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName ) +void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, const idRenderWorld* world, int area ) { //idLib::Printf( "----- SetupLightGrid -----\n" ); lightGridSize.Set( 64, 64, 128 ); lightGridPoints.Clear(); + validGridPoints = 0; + idVec3 maxs; int j = 0; int numGridPoints = MAX_MAP_LIGHTGRID_POINTS + 1; @@ -64,18 +66,22 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName ) } } - idLib::Printf( "grid size (%i %i %i)\n", ( int )lightGridSize[0], ( int )lightGridSize[1], ( int )lightGridSize[2] ); - idLib::Printf( "grid bounds (%i %i %i)\n", ( int )lightGridBounds[0], ( int )lightGridBounds[1], ( int )lightGridBounds[2] ); + if( numGridPoints > 0 ) + { + lightGridPoints.SetNum( numGridPoints ); - idLib::Printf( "%i x %i x %i = %i grid points \n", lightGridBounds[0], lightGridBounds[1], lightGridBounds[2], numGridPoints ); + idLib::Printf( "area %i grid size (%i %i %i)\n", area, ( int )lightGridSize[0], ( int )lightGridSize[1], ( int )lightGridSize[2] ); + idLib::Printf( "area %i grid bounds (%i %i %i)\n", area, ( int )lightGridBounds[0], ( int )lightGridBounds[1], ( int )lightGridBounds[2] ); - lightGridPoints.SetNum( numGridPoints ); + idLib::Printf( "area %i (%i x %i x %i) = %i grid points \n", area, lightGridBounds[0], lightGridBounds[1], lightGridBounds[2], numGridPoints ); - idLib::Printf( "%9u x %" PRIuSIZE " = lightGridSize = (%.2fMB)\n", numGridPoints, sizeof( lightGridPoint_t ), ( float )( lightGridPoints.MemoryUsed() ) / ( 1024.0f * 1024.0f ) ); + idLib::Printf( "area %i %9u x %" PRIuSIZE " = lightGridSize = (%.2fMB)\n", area, numGridPoints, sizeof( lightGridPoint_t ), ( float )( lightGridPoints.MemoryUsed() ) / ( 1024.0f * 1024.0f ) ); - CalculateLightGridPointPositions(); + CalculateLightGridPointPositions( world, area ); + } // try to load existing lightgrid data +#if 0 idStr basename = mapName; basename.StripFileExtension(); @@ -88,6 +94,7 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName ) fullname.Format( "env/%s/lightgridpoint%i_amb", basename.c_str(), i ); gridPoint->irradianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); } +#endif } void LightGrid::ProbeIndexToGridIndex( const int probeIndex, int gridIndex[3] ) @@ -142,7 +149,7 @@ idVec3 LightGrid::GetProbeIndexDebugColor( const int probeIndex ) return color; } -void LightGrid::CalculateLightGridPointPositions() +void LightGrid::CalculateLightGridPointPositions( const idRenderWorld* world, int area ) { // calculate grid point positions int gridStep[3]; @@ -153,7 +160,9 @@ void LightGrid::CalculateLightGridPointPositions() gridStep[1] = lightGridBounds[0]; gridStep[2] = lightGridBounds[0] * lightGridBounds[1]; + int invalidCount = 0; int p = 0; + for( int i = 0; i < lightGridBounds[0]; i += 1 ) { for( int j = 0; j < lightGridBounds[1]; j += 1 ) @@ -172,27 +181,39 @@ void LightGrid::CalculateLightGridPointPositions() gridPoint->origin = lightGridOrigin + posFloat; + gridPoint->valid = ( world->PointInArea( gridPoint->origin ) != -1 ); + if( !gridPoint->valid ) + { + invalidCount++; + } + + gridPoint->irradianceImage = NULL; + p++; } } } + + validGridPoints = p - invalidCount; + + idLib::Printf( "area %i: %i of %i grid points in empty space (%.2f%%)\n", area, invalidCount, lightGridPoints.Num(), ( ( float ) invalidCount / lightGridPoints.Num() ) * 100 ); } void idRenderWorldLocal::SetupLightGrid() { idLib::Printf( "----- SetupLightGrid -----\n" ); - idBounds bounds; - bounds.Clear(); - + int totalGridPoints = 0; for( int i = 0; i < numPortalAreas; i++ ) { portalArea_t* area = &portalAreas[i]; - bounds.AddBounds( area->globalBounds ); + area->lightGrid.SetupLightGrid( area->globalBounds, mapName, this, i ); + + totalGridPoints += area->lightGrid.validGridPoints; } - lightGrid.SetupLightGrid( bounds, mapName ); + idLib::Printf( "total valid light grid points %i\n", totalGridPoints ); } @@ -575,7 +596,15 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) // CAPTURE SCENE LIGHTING TO CUBEMAPS //-------------------------------------------- - CommandlineProgressBar progressBar( tr.primaryWorld->lightGrid.lightGridPoints.Num() ); + int totalGridPoints = 0; + for( int a = 0; a < tr.primaryWorld->NumAreas(); a++ ) + { + portalArea_t* area = &tr.primaryWorld->portalAreas[a]; + + totalGridPoints += area->lightGrid.lightGridPoints.Num(); + } + + CommandlineProgressBar progressBar( totalGridPoints ); if( !useThreads ) { progressBar.Start(); @@ -583,41 +612,52 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) int start = Sys_Milliseconds(); - for( int i = 0; i < tr.primaryWorld->lightGrid.lightGridPoints.Num(); i++ ) + for( int a = 0; a < tr.primaryWorld->NumAreas(); a++ ) { - lightGridPoint_t* gridPoint = &tr.primaryWorld->lightGrid.lightGridPoints[i]; + portalArea_t* area = &tr.primaryWorld->portalAreas[a]; - calcLightGridPointParms_t* jobParms = new calcLightGridPointParms_t; - - for( int j = 0 ; j < 6 ; j++ ) + for( int i = 0; i < area->lightGrid.lightGridPoints.Num(); i++ ) { - ref = primary.renderView; + lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i]; + if( !gridPoint->valid ) + { + progressBar.Increment(); + continue; + } - ref.rdflags = RDF_NOAMBIENT | RDF_IRRADIANCE; - ref.fov_x = ref.fov_y = 90; + calcLightGridPointParms_t* jobParms = new calcLightGridPointParms_t; + jobParms->area = a; - ref.vieworg = gridPoint->origin; - ref.viewaxis = tr.cubeAxis[j]; + for( int j = 0 ; j < 6 ; j++ ) + { + ref = primary.renderView; - extension = envDirection[ j ]; + ref.rdflags = RDF_NOAMBIENT | RDF_IRRADIANCE; + ref.fov_x = ref.fov_y = 90; - //tr.TakeScreenshot( size, size, fullname, blends, &ref, EXR ); - byte* float16FRGB = tr.CaptureRenderToBuffer( size, size, &ref ); + ref.vieworg = gridPoint->origin; + ref.viewaxis = tr.cubeAxis[j]; - jobParms->buffers[ j ] = float16FRGB; + extension = envDirection[ j ]; + + //tr.TakeScreenshot( size, size, fullname, blends, &ref, EXR ); + byte* float16FRGB = tr.CaptureRenderToBuffer( size, size, &ref ); + + jobParms->buffers[ j ] = float16FRGB; #if 0 - if( i < 3 ) - { - filename.Format( "env/%s/lightgridpoint%i%s.exr", baseName.c_str(), i, extension ); - R_WriteEXR( filename, float16FRGB, 3, size, size, "fs_basepath" ); - } + if( i < 3 ) + { + filename.Format( "env/%s/area%i_lightgridpoint%i%s.exr", baseName.c_str(), a, i, extension ); + R_WriteEXR( filename, float16FRGB, 3, size, size, "fs_basepath" ); + } #endif + } + + tr.lightGridJobs.Append( jobParms ); + + progressBar.Increment(); } - - tr.lightGridJobs.Append( jobParms ); - - progressBar.Increment(); } int end = Sys_Milliseconds(); @@ -670,7 +710,7 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) { calcLightGridPointParms_t* job = tr.lightGridJobs[ j ]; - filename.Format( "env/%s/lightgridpoint%i_amb.exr", baseName.c_str(), j ); + filename.Format( "env/%s/area%i_lightgridpoint%i_amb.exr", baseName.c_str(), job->area, j ); R_WriteEXR( filename.c_str(), ( byte* )job->outBuffer, 3, job->outWidth, job->outHeight, "fs_basepath" ); diff --git a/neo/renderer/RenderWorld_local.h b/neo/renderer/RenderWorld_local.h index e939f2f0..d5a51855 100644 --- a/neo/renderer/RenderWorld_local.h +++ b/neo/renderer/RenderWorld_local.h @@ -70,6 +70,8 @@ struct lightGridPoint_t // TODO REMOVE just for testing idImage* irradianceImage; + + bool valid; // is not in solid area }; class LightGrid @@ -81,11 +83,12 @@ private: public: idList lightGridPoints; + int validGridPoints; //LightGrid(); // setup light grid for given world bounds - void SetupLightGrid( const idBounds& bounds, const char* baseName ); + void SetupLightGrid( const idBounds& bounds, const char* baseName, const idRenderWorld* world, int area ); void ProbeIndexToGridIndex( const int probeIndex, int gridIndex[3] ); @@ -95,7 +98,7 @@ public: void SetupEntityGridLighting( idRenderEntityLocal* def ); private: - void CalculateLightGridPointPositions(); + void CalculateLightGridPointPositions( const idRenderWorld* world, int area ); }; // RB end @@ -107,6 +110,8 @@ typedef struct portalArea_s idBounds globalBounds; // RB: AABB of the BSP area used for light grid density + LightGrid lightGrid; + int viewCount; // set by R_FindViewLightsAndEntities portal_t* portals; // never changes after load areaReference_t entityRefs; // head/tail of doubly linked list, may change @@ -226,9 +231,6 @@ public: doublePortal_t* doublePortals; int numInterAreaPortals; - // RB: added Quake 3 style light grid - LightGrid lightGrid; - idList localModels; idList entityDefs; From 26faa5797aba8773dcb1f0eba4fa5d68dbfee898 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Wed, 14 Apr 2021 12:55:46 +0200 Subject: [PATCH 04/26] r_showLightGrid 2 shows how light grid interpolation works --- neo/renderer/OpenGL/RenderDebug_GL.cpp | 261 ++++++++++++++++++++----- neo/renderer/RenderWorld_envprobes.cpp | 2 +- neo/renderer/RenderWorld_lightgrid.cpp | 29 ++- neo/renderer/RenderWorld_local.h | 7 +- 4 files changed, 233 insertions(+), 66 deletions(-) diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index cf58cca2..277da397 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1794,8 +1794,6 @@ void idRenderBackend::DBG_ShowLightGrid() } // all volumes are expressed in world coordinates - renderProgManager.BindShader_Color(); - //renderProgManager.BindShader_Octahedron(); GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_DEPTHMASK ); GL_Color( 1.0f, 1.0f, 1.0f ); @@ -1812,82 +1810,126 @@ void idRenderBackend::DBG_ShowLightGrid() return; } + portalArea_t* area = &tr.primaryWorld->portalAreas[a]; + + for( int i = 0; i < area->lightGrid.lightGridPoints.Num(); i++ ) { - portalArea_t* area = &tr.primaryWorld->portalAreas[a]; - - for( int i = 0; i < area->lightGrid.lightGridPoints.Num(); i++ ) + lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i]; + if( !gridPoint->valid ) { - lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i]; - if( !gridPoint->valid ) - { - continue; - } + continue; + } - idVec3 distanceToCam = gridPoint->origin - viewDef->renderView.vieworg; - if( distanceToCam.LengthSqr() > ( 1024 * 1024 ) ) - { - continue; - } + idVec3 distanceToCam = gridPoint->origin - viewDef->renderView.vieworg; + if( distanceToCam.LengthSqr() > ( 1024 * 1024 ) ) + { + continue; + } - /* - idVec4 c; - c[0] = idMath::ClampFloat( 0, 1, gridPoint->directed[0] * ( 1.0f / 255.0f ) ); - c[1] = idMath::ClampFloat( 0, 1, gridPoint->directed[1] * ( 1.0f / 255.0f ) ); - c[2] = idMath::ClampFloat( 0, 1, gridPoint->directed[2] * ( 1.0f / 255.0f ) ); + /* + idVec4 c; + c[0] = idMath::ClampFloat( 0, 1, gridPoint->directed[0] * ( 1.0f / 255.0f ) ); + c[1] = idMath::ClampFloat( 0, 1, gridPoint->directed[1] * ( 1.0f / 255.0f ) ); + c[2] = idMath::ClampFloat( 0, 1, gridPoint->directed[2] * ( 1.0f / 255.0f ) ); - glColor4f( c[0], c[1], c[2], 1 ); + glColor4f( c[0], c[1], c[2], 1 ); - float lattitude = DEG2RAD( gridPoint->latLong[1] * ( 360.0f / 255.0f ) ); - float longitude = DEG2RAD( gridPoint->latLong[0] * ( 360.0f / 255.0f ) ); + float lattitude = DEG2RAD( gridPoint->latLong[1] * ( 360.0f / 255.0f ) ); + float longitude = DEG2RAD( gridPoint->latLong[0] * ( 360.0f / 255.0f ) ); - idVec3 dir; - dir[0] = idMath::Cos( lattitude ) * idMath::Sin( longitude ); - dir[1] = idMath::Sin( lattitude ) * idMath::Sin( longitude ); - dir[2] = idMath::Cos( longitude ); + idVec3 dir; + dir[0] = idMath::Cos( lattitude ) * idMath::Sin( longitude ); + dir[1] = idMath::Sin( lattitude ) * idMath::Sin( longitude ); + dir[2] = idMath::Cos( longitude ); - idVec3 pos2 = gridPoint->origin - dir * r_showLightGrid.GetFloat(); + idVec3 pos2 = gridPoint->origin - dir * r_showLightGrid.GetFloat(); - glBegin( GL_LINES ); + glBegin( GL_LINES ); - glColor4f( c[0], c[1], c[2], 1 ); - //glColor4f( 1, 1, 1, 1 ); - glVertex3fv( gridPoint->origin.ToFloatPtr() ); + glColor4f( c[0], c[1], c[2], 1 ); + //glColor4f( 1, 1, 1, 1 ); + glVertex3fv( gridPoint->origin.ToFloatPtr() ); - glColor4f( 0, 0, 0, 1 ); - glVertex3fv( pos2.ToFloatPtr() ); - glEnd(); - */ + glColor4f( 0, 0, 0, 1 ); + glVertex3fv( pos2.ToFloatPtr() ); + glEnd(); + */ #if 1 - idVec4 localViewOrigin( 1.0f ); - idVec4 globalViewOrigin; - globalViewOrigin.x = viewDef->renderView.vieworg.x; - globalViewOrigin.y = viewDef->renderView.vieworg.y; - globalViewOrigin.z = viewDef->renderView.vieworg.z; - globalViewOrigin.w = 1.0f; + idVec4 localViewOrigin( 1.0f ); + idVec4 globalViewOrigin; + globalViewOrigin.x = viewDef->renderView.vieworg.x; + globalViewOrigin.y = viewDef->renderView.vieworg.y; + globalViewOrigin.z = viewDef->renderView.vieworg.z; + globalViewOrigin.w = 1.0f; - float modelMatrix[16]; - R_AxisToModelMatrix( axis, gridPoint->origin, modelMatrix ); + float modelMatrix[16]; + R_AxisToModelMatrix( axis, gridPoint->origin, modelMatrix ); - R_GlobalPointToLocal( modelMatrix, viewDef->renderView.vieworg, localViewOrigin.ToVec3() ); + R_GlobalPointToLocal( modelMatrix, viewDef->renderView.vieworg, localViewOrigin.ToVec3() ); - renderProgManager.SetUniformValue( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); // rpLocalViewOrigin + renderProgManager.SetUniformValue( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); // rpLocalViewOrigin #endif -#if 1 - idVec3 color = area->lightGrid.GetProbeIndexDebugColor( i ); - GL_Color( color ); +#if 0 + renderProgManager.BindShader_Color(); + + idVec3 color = area->lightGrid.GetProbeIndexDebugColor( i ); + GL_Color( color ); #else - GL_SelectTexture( 0 ); - gridPoint->irradianceImage->Bind(); + renderProgManager.BindShader_Octahedron(); + + GL_SelectTexture( 0 ); + gridPoint->irradianceImage->Bind(); #endif + idRenderMatrix modelRenderMatrix; + idRenderMatrix::CreateFromOriginAxis( gridPoint->origin, axis, modelRenderMatrix ); + + // calculate the matrix that transforms the unit cube to exactly cover the model in world space + const float size = 3.0f; + idBounds debugBounds( idVec3( -size ), idVec3( size ) ); + + idRenderMatrix inverseBaseModelProject; + idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject ); + + idRenderMatrix invProjectMVPMatrix; + idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix ); + RB_SetMVP( invProjectMVPMatrix ); + + DrawElementsWithCounters( &zeroOneSphereSurface ); + } + + if( r_showLightGrid.GetInteger() == 2 ) + { + // show 8 nearest grid points around the camera and illustrate how the trilerping works + + idVec3 lightOrigin; + int pos[3]; + int gridPointIndex; + int gridPointIndex2; + lightGridPoint_t* gridPoint; + lightGridPoint_t* gridPoint2; + float frac[3]; + int gridStep[3]; + float totalFactor; + + renderProgManager.BindShader_Color(); + + lightOrigin = viewDef->renderView.vieworg; + lightOrigin += viewDef->renderView.viewaxis[0] * 100.0f; + lightOrigin -= viewDef->renderView.viewaxis[2] * 16.0f; + + // draw sample origin we want to test the grid with + { + GL_Color( colorYellow ); + idRenderMatrix modelRenderMatrix; - idRenderMatrix::CreateFromOriginAxis( gridPoint->origin, axis, modelRenderMatrix ); + idRenderMatrix::CreateFromOriginAxis( lightOrigin, axis, modelRenderMatrix ); // calculate the matrix that transforms the unit cube to exactly cover the model in world space - const float size = 3.0f; + const float size = 2.0f; idBounds debugBounds( idVec3( -size ), idVec3( size ) ); idRenderMatrix inverseBaseModelProject; @@ -1899,6 +1941,119 @@ void idRenderBackend::DBG_ShowLightGrid() DrawElementsWithCounters( &zeroOneSphereSurface ); } + + // find base grid point + lightOrigin -= area->lightGrid.lightGridOrigin; + for( int i = 0; i < 3; i++ ) + { + float v; + + v = lightOrigin[i] * ( 1.0f / area->lightGrid.lightGridSize[i] ); + pos[i] = floor( v ); + frac[i] = v - pos[i]; + if( pos[i] < 0 ) + { + pos[i] = 0; + } + else if( pos[i] >= area->lightGrid.lightGridBounds[i] - 1 ) + { + pos[i] = area->lightGrid.lightGridBounds[i] - 1; + } + } + + // trilerp the light value + gridStep[0] = 1; + gridStep[1] = area->lightGrid.lightGridBounds[0]; + gridStep[2] = area->lightGrid.lightGridBounds[0] * area->lightGrid.lightGridBounds[1]; + + gridPointIndex = pos[0] * gridStep[0] + pos[1] * gridStep[1] + pos[2] * gridStep[2]; + gridPoint = &area->lightGrid.lightGridPoints[ gridPointIndex ]; + + totalFactor = 0; + for( int i = 0; i < 8; i++ ) + { + float factor = 1.0; + + gridPoint2 = gridPoint; + gridPointIndex2 = gridPointIndex; + + for( int j = 0; j < 3; j++ ) + { + if( i & ( 1 << j ) ) + { + factor *= frac[j]; + +#if 1 + gridPointIndex2 += gridStep[j]; + if( gridPointIndex2 < 0 || gridPointIndex2 >= area->lightGrid.lightGridPoints.Num() ) + { + // ignore values outside lightgrid + continue; + } + + gridPoint2 = &area->lightGrid.lightGridPoints[ gridPointIndex2 ]; +#else + if( pos[j] + 1 > area->lightGrid.lightGridBounds[j] - 1 ) + { + // ignore values outside lightgrid + break; + } + + gridPoint2 += gridStep[j]; +#endif + } + else + { + factor *= ( 1.0f - frac[j] ); + } + } + + if( !gridPoint2->valid ) + { + // ignore samples in walls + continue; + } + + totalFactor += factor; + + idVec4 color = Lerp( colorBlack, colorGreen, factor ); + GL_Color( color ); + + idRenderMatrix modelRenderMatrix; + idRenderMatrix::CreateFromOriginAxis( gridPoint2->origin, axis, modelRenderMatrix ); + + // calculate the matrix that transforms the unit cube to exactly cover the model in world space + const float size = 4.0f; + idBounds debugBounds( idVec3( -size ), idVec3( size ) ); + + idRenderMatrix inverseBaseModelProject; + idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject ); + + idRenderMatrix invProjectMVPMatrix; + idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix ); + RB_SetMVP( invProjectMVPMatrix ); + + DrawElementsWithCounters( &zeroOneSphereSurface ); + } + + // draw main grid point where camera position snapped to + GL_Color( colorRed ); + + idRenderMatrix modelRenderMatrix; + idRenderMatrix::CreateFromOriginAxis( gridPoint->origin, axis, modelRenderMatrix ); + + // calculate the matrix that transforms the unit cube to exactly cover the model in world space + const float size = 5.0f; + idBounds debugBounds( idVec3( -size ), idVec3( size ) ); + + idRenderMatrix inverseBaseModelProject; + idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject ); + + idRenderMatrix invProjectMVPMatrix; + idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix ); + RB_SetMVP( invProjectMVPMatrix ); + + DrawElementsWithCounters( &zeroOneSphereSurface ); } } diff --git a/neo/renderer/RenderWorld_envprobes.cpp b/neo/renderer/RenderWorld_envprobes.cpp index 2e3f629b..a4e034bd 100644 --- a/neo/renderer/RenderWorld_envprobes.cpp +++ b/neo/renderer/RenderWorld_envprobes.cpp @@ -1057,7 +1057,7 @@ CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL fullname.Format( "%s/envprobe%i", baseName.c_str(), i ); R_MakeAmbientMap( fullname.c_str(), "_amb", IRRADIANCE_CUBEMAP_SIZE, false, false, useThreads ); - R_MakeAmbientMap( fullname.c_str(), "_spec", RADIANCE_CUBEMAP_SIZE, true, false, useThreads ); + R_MakeAmbientMap( fullname.c_str(), "_spec", RADIANCE_CUBEMAP_SIZE, true, true, useThreads ); } if( useThreads ) diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 8e2f6264..b31fd416 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -37,13 +37,14 @@ static const int MAX_MAP_LIGHTGRID_POINTS = 0x100000; static const int LIGHTGRID_IRRADIANCE_SIZE = 32; -void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, const idRenderWorld* world, int area ) +void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, const idRenderWorld* world, int _area ) { //idLib::Printf( "----- SetupLightGrid -----\n" ); lightGridSize.Set( 64, 64, 128 ); lightGridPoints.Clear(); + area = _area; validGridPoints = 0; idVec3 maxs; @@ -81,7 +82,7 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con } // try to load existing lightgrid data -#if 0 +#if 1 idStr basename = mapName; basename.StripFileExtension(); @@ -91,7 +92,7 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con { lightGridPoint_t* gridPoint = &lightGridPoints[i]; - fullname.Format( "env/%s/lightgridpoint%i_amb", basename.c_str(), i ); + fullname.Format( "env/%s/area%i_lightgridpoint%i_amb", basename.c_str(), area, i ); gridPoint->irradianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); } #endif @@ -737,7 +738,7 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) } #if 0 -// straight port of Quake 3 +// straight port of Quake 3 / XreaL void idRenderWorldLocal::SetupEntityGridLighting( idRenderEntityLocal* def ) { // lighting calculations @@ -839,20 +840,30 @@ void idRenderWorldLocal::SetupEntityGridLighting( idRenderEntityLocal* def ) factor = 1.0; gridPoint2 = gridPoint; - for( j = 0; j < 3; j++ ) + for( int j = 0; j < 3; j++ ) { if( i & ( 1 << j ) ) { - int gridPointIndex2 = gridPointIndex + gridStep[j]; + factor *= frac[j]; - if( gridPointIndex2 < 0 || gridPointIndex2 >= lightGridPoints.Num() ) +#if 1 + gridPointIndex2 += gridStep[j]; + if( gridPointIndex2 < 0 || gridPointIndex2 >= area->lightGrid.lightGridPoints.Num() ) { + // ignore values outside lightgrid continue; } - factor *= frac[j]; + gridPoint2 = &area->lightGrid.lightGridPoints[ gridPointIndex2 ]; +#else + if( pos[j] + 1 > area->lightGrid.lightGridBounds[j] - 1 ) + { + // ignore values outside lightgrid + break; + } - gridPoint2 = &lightGridPoints[ gridPointIndex + gridStep[j] ]; + gridPoint2 += gridStep[j]; +#endif } else { diff --git a/neo/renderer/RenderWorld_local.h b/neo/renderer/RenderWorld_local.h index d5a51855..ac0b2cc0 100644 --- a/neo/renderer/RenderWorld_local.h +++ b/neo/renderer/RenderWorld_local.h @@ -76,19 +76,20 @@ struct lightGridPoint_t class LightGrid { -private: +public: idVec3 lightGridOrigin; idVec3 lightGridSize; int lightGridBounds[3]; + int area; -public: +//public: idList lightGridPoints; int validGridPoints; //LightGrid(); // setup light grid for given world bounds - void SetupLightGrid( const idBounds& bounds, const char* baseName, const idRenderWorld* world, int area ); + void SetupLightGrid( const idBounds& bounds, const char* baseName, const idRenderWorld* world, int _area ); void ProbeIndexToGridIndex( const int probeIndex, int gridIndex[3] ); From 7e16444fcc560a6d4856afd9419f20ae56742265 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Wed, 14 Apr 2021 18:17:28 +0200 Subject: [PATCH 05/26] More light grid debug code --- neo/renderer/OpenGL/RenderDebug_GL.cpp | 51 ++++------- neo/renderer/RenderCommon.h | 6 ++ neo/renderer/RenderWorld_lightgrid.cpp | 122 +++++++++++++++++++------ neo/renderer/RenderWorld_local.h | 16 ++-- 4 files changed, 128 insertions(+), 67 deletions(-) diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index 277da397..0dd53d6b 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1812,6 +1812,9 @@ void idRenderBackend::DBG_ShowLightGrid() portalArea_t* area = &tr.primaryWorld->portalAreas[a]; + const int numColors = 7; + static idVec4 colors[numColors] = { colorBlack, colorBlue, colorCyan, colorGreen, colorYellow, colorRed, colorWhite }; + for( int i = 0; i < area->lightGrid.lightGridPoints.Num(); i++ ) { lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i]; @@ -1826,36 +1829,13 @@ void idRenderBackend::DBG_ShowLightGrid() continue; } - /* - idVec4 c; - c[0] = idMath::ClampFloat( 0, 1, gridPoint->directed[0] * ( 1.0f / 255.0f ) ); - c[1] = idMath::ClampFloat( 0, 1, gridPoint->directed[1] * ( 1.0f / 255.0f ) ); - c[2] = idMath::ClampFloat( 0, 1, gridPoint->directed[2] * ( 1.0f / 255.0f ) ); - - glColor4f( c[0], c[1], c[2], 1 ); - - float lattitude = DEG2RAD( gridPoint->latLong[1] * ( 360.0f / 255.0f ) ); - float longitude = DEG2RAD( gridPoint->latLong[0] * ( 360.0f / 255.0f ) ); - - idVec3 dir; - dir[0] = idMath::Cos( lattitude ) * idMath::Sin( longitude ); - dir[1] = idMath::Sin( lattitude ) * idMath::Sin( longitude ); - dir[2] = idMath::Cos( longitude ); - - idVec3 pos2 = gridPoint->origin - dir * r_showLightGrid.GetFloat(); - - glBegin( GL_LINES ); - - glColor4f( c[0], c[1], c[2], 1 ); - //glColor4f( 1, 1, 1, 1 ); - glVertex3fv( gridPoint->origin.ToFloatPtr() ); - - glColor4f( 0, 0, 0, 1 ); - glVertex3fv( pos2.ToFloatPtr() ); - glEnd(); - */ - #if 1 + if( i > 53 ) + { + break; + } +#endif + idVec4 localViewOrigin( 1.0f ); idVec4 globalViewOrigin; globalViewOrigin.x = viewDef->renderView.vieworg.x; @@ -1869,13 +1849,17 @@ void idRenderBackend::DBG_ShowLightGrid() R_GlobalPointToLocal( modelMatrix, viewDef->renderView.vieworg, localViewOrigin.ToVec3() ); renderProgManager.SetUniformValue( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); // rpLocalViewOrigin -#endif -#if 0 +#if 1 renderProgManager.BindShader_Color(); - idVec3 color = area->lightGrid.GetProbeIndexDebugColor( i ); + int gridCoord[3]; + area->lightGrid.GetBaseGridCoord( gridPoint->origin, gridCoord ); + + idVec3 color = area->lightGrid.GetGridCoordDebugColor( gridCoord ); + //idVec3 color = area->lightGrid.GetProbeIndexDebugColor( i ); + //idVec4 color = colors[ i % numColors ]; GL_Color( color ); #else renderProgManager.BindShader_Octahedron(); @@ -1918,7 +1902,7 @@ void idRenderBackend::DBG_ShowLightGrid() renderProgManager.BindShader_Color(); lightOrigin = viewDef->renderView.vieworg; - lightOrigin += viewDef->renderView.viewaxis[0] * 100.0f; + lightOrigin += viewDef->renderView.viewaxis[0] * 150.0f; lightOrigin -= viewDef->renderView.viewaxis[2] * 16.0f; // draw sample origin we want to test the grid with @@ -1951,6 +1935,7 @@ void idRenderBackend::DBG_ShowLightGrid() v = lightOrigin[i] * ( 1.0f / area->lightGrid.lightGridSize[i] ); pos[i] = floor( v ); frac[i] = v - pos[i]; + if( pos[i] < 0 ) { pos[i] = 0; diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index 5a664c26..f7895ae8 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -502,6 +502,10 @@ struct calcEnvprobeParms_t int time; // execution time in milliseconds }; + + +static const int LIGHTGRID_IRRADIANCE_SIZE = 8; + struct calcLightGridPointParms_t { // input @@ -512,6 +516,8 @@ struct calcLightGridPointParms_t int outHeight; // output + SphericalHarmonicsT SH4; + halfFloat_t* outBuffer; // HDR R11G11B11F packed atlas int time; // execution time in milliseconds }; diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index b31fd416..69cf1195 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -32,10 +32,8 @@ If you have questions concerning this license or the applicable additional terms #include "RenderCommon.h" -// RB: old constant from q3map2 -static const int MAX_MAP_LIGHTGRID_POINTS = 0x100000; - -static const int LIGHTGRID_IRRADIANCE_SIZE = 32; +static const int MAX_LIGHTGRID_ATLAS_SIZE = 4096; +static const int MAX_AREA_LIGHTGRID_POINTS = ( MAX_LIGHTGRID_ATLAS_SIZE / LIGHTGRID_IRRADIANCE_SIZE ) * ( MAX_LIGHTGRID_ATLAS_SIZE / LIGHTGRID_IRRADIANCE_SIZE ); void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, const idRenderWorld* world, int _area ) { @@ -49,8 +47,8 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con idVec3 maxs; int j = 0; - int numGridPoints = MAX_MAP_LIGHTGRID_POINTS + 1; - while( numGridPoints > MAX_MAP_LIGHTGRID_POINTS ) + int numGridPoints = MAX_AREA_LIGHTGRID_POINTS + 1; + while( numGridPoints > MAX_AREA_LIGHTGRID_POINTS ) { for( int i = 0; i < 3; i++ ) { @@ -61,7 +59,7 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con numGridPoints = lightGridBounds[0] * lightGridBounds[1] * lightGridBounds[2]; - if( numGridPoints > MAX_MAP_LIGHTGRID_POINTS ) + if( numGridPoints > MAX_AREA_LIGHTGRID_POINTS ) { lightGridSize[ j++ % 3 ] += 16.0f; } @@ -82,7 +80,7 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con } // try to load existing lightgrid data -#if 1 +#if 0 idStr basename = mapName; basename.StripFileExtension(); @@ -92,13 +90,60 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con { lightGridPoint_t* gridPoint = &lightGridPoints[i]; + gridPoint->irradianceImage = NULL; + fullname.Format( "env/%s/area%i_lightgridpoint%i_amb", basename.c_str(), area, i ); gridPoint->irradianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); } +#else + for( int i = 0; i < lightGridPoints.Num(); i++ ) + { + lightGridPoint_t* gridPoint = &lightGridPoints[i]; + + //gridPoint->irradianceImage = NULL; + } #endif } -void LightGrid::ProbeIndexToGridIndex( const int probeIndex, int gridIndex[3] ) +void LightGrid::GetBaseGridCoord( const idVec3& origin, int gridCoord[3] ) +{ + int pos[3]; + + idVec3 lightOrigin = origin - lightGridOrigin; + for( int i = 0; i < 3; i++ ) + { + float v; + + v = lightOrigin[i] * ( 1.0f / lightGridSize[i] ); + pos[i] = floor( v ); + + if( pos[i] < 0 ) + { + pos[i] = 0; + } + else if( pos[i] >= lightGridBounds[i] - 1 ) + { + pos[i] = lightGridBounds[i] - 1; + } + + gridCoord[i] = pos[i]; + } +} + +int LightGrid::GridCoordToProbeIndex( int gridCoord[3] ) +{ + int gridStep[3]; + + gridStep[0] = 1; + gridStep[1] = lightGridBounds[0]; + gridStep[2] = lightGridBounds[0] * lightGridBounds[1]; + + int gridPointIndex = gridCoord[0] * gridStep[0] + gridCoord[1] * gridStep[1] + gridCoord[2] * gridStep[2]; + + return gridPointIndex; +} + +void LightGrid::ProbeIndexToGridCoord( const int probeIndex, int gridCoord[3] ) { // slow brute force method only for debugging int gridStep[3]; @@ -107,9 +152,9 @@ void LightGrid::ProbeIndexToGridIndex( const int probeIndex, int gridIndex[3] ) gridStep[1] = lightGridBounds[0]; gridStep[2] = lightGridBounds[0] * lightGridBounds[1]; - gridIndex[0] = 0; - gridIndex[1] = 0; - gridIndex[2] = 0; + gridCoord[0] = 0; + gridCoord[1] = 0; + gridCoord[2] = 0; int p = 0; for( int i = 0; i < lightGridBounds[0]; i += 1 ) @@ -120,9 +165,9 @@ void LightGrid::ProbeIndexToGridIndex( const int probeIndex, int gridIndex[3] ) { if( probeIndex == p ) { - gridIndex[0] = i; - gridIndex[1] = j; - gridIndex[2] = k; + gridCoord[0] = i; + gridCoord[1] = j; + gridCoord[2] = k; return; } @@ -133,21 +178,46 @@ void LightGrid::ProbeIndexToGridIndex( const int probeIndex, int gridIndex[3] ) } } +idVec3 LightGrid::GetGridCoordDebugColor( int gridCoord[3] ) +{ + idVec3 color( colorGold.x, colorGold.y, colorGold.z ); + +#if 0 + color.x = float( gridCoord[0] & 1 ); + color.y = float( gridCoord[1] & 1 ); + color.z = float( gridCoord[2] & 1 ); + + //color *= ( 1.0f / Max( color.x + color.y + color.z, 0.01f ) ); + //color = color * 0.6f + idVec3( 0.2f ); + +#else + int gridStep[3]; + + gridStep[0] = 1; + gridStep[1] = lightGridBounds[0]; + gridStep[2] = lightGridBounds[0] * lightGridBounds[1]; + + int gridPointIndex = gridCoord[0] * gridStep[0] + gridCoord[1] * gridStep[1] + gridCoord[2] * gridStep[2]; + + const int numColors = 7; + static idVec4 colors[numColors] = { colorBlack, colorBlue, colorCyan, colorGreen, colorYellow, colorRed, colorWhite }; + + color.x = colors[ gridPointIndex % numColors ].x; + color.y = colors[ gridPointIndex % numColors ].y; + color.z = colors[ gridPointIndex % numColors ].z; +#endif + + return color; +} + idVec3 LightGrid::GetProbeIndexDebugColor( const int probeIndex ) { idVec3 color( colorGold.x, colorGold.y, colorGold.z ); - int gridIndex[3]; - ProbeIndexToGridIndex( probeIndex, gridIndex ); + int gridCoord[3]; + ProbeIndexToGridCoord( probeIndex, gridCoord ); - color.x = float( gridIndex[0] & 1 ); - color.y = float( gridIndex[1] & 1 ); - color.z = float( gridIndex[2] & 1 ); - - color *= ( 1.0f / Max( color.x + color.y + color.z, 0.01f ) ); - color = color * 0.6f + idVec3( 0.2f ); - - return color; + return GetGridCoordDebugColor( gridCoord ); } void LightGrid::CalculateLightGridPointPositions( const idRenderWorld* world, int area ) @@ -188,8 +258,6 @@ void LightGrid::CalculateLightGridPointPositions( const idRenderWorld* world, in invalidCount++; } - gridPoint->irradianceImage = NULL; - p++; } } diff --git a/neo/renderer/RenderWorld_local.h b/neo/renderer/RenderWorld_local.h index ac0b2cc0..1026f210 100644 --- a/neo/renderer/RenderWorld_local.h +++ b/neo/renderer/RenderWorld_local.h @@ -60,18 +60,16 @@ typedef struct doublePortal_s } doublePortal_t; // RB: added Quake 3 style light grid +// however this 2021 version features Spherical Harmonics instead of ambient + directed color struct lightGridPoint_t { idVec3 origin; // not saved to .proc + bool valid; // is not in solid area - byte ambient[3]; - byte directed[3]; - byte latLong[2]; + SphericalHarmonicsT SH4; // TODO REMOVE just for testing - idImage* irradianceImage; - - bool valid; // is not in solid area + //idImage* irradianceImage; }; class LightGrid @@ -91,8 +89,12 @@ public: // setup light grid for given world bounds void SetupLightGrid( const idBounds& bounds, const char* baseName, const idRenderWorld* world, int _area ); - void ProbeIndexToGridIndex( const int probeIndex, int gridIndex[3] ); + void GetBaseGridCoord( const idVec3& origin, int gridCoord[3] ); + int GridCoordToProbeIndex( int gridCoord[3] ); + void ProbeIndexToGridCoord( const int probeIndex, int gridCoord[3] ); + + idVec3 GetGridCoordDebugColor( int gridCoord[3] ); idVec3 GetProbeIndexDebugColor( const int probeIndex ); // fetch grid lighting on a per object basis From 6ad03afca6a80f990ed5812bd7ac6eab50fc8f22 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Wed, 14 Apr 2021 22:17:09 +0200 Subject: [PATCH 06/26] Write an irradiance atlas for each area --- neo/renderer/OpenGL/RenderDebug_GL.cpp | 2 +- neo/renderer/RenderCommon.h | 11 +- neo/renderer/RenderWorld_lightgrid.cpp | 328 ++++++++++++++----------- neo/renderer/RenderWorld_local.h | 2 +- 4 files changed, 191 insertions(+), 152 deletions(-) diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index 0dd53d6b..955b786c 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1851,7 +1851,7 @@ void idRenderBackend::DBG_ShowLightGrid() renderProgManager.SetUniformValue( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); // rpLocalViewOrigin -#if 1 +#if 0 renderProgManager.BindShader_Color(); int gridCoord[3]; diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index f7895ae8..9e45b250 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -498,27 +498,26 @@ struct calcEnvprobeParms_t idStr filename; // output - halfFloat_t* outBuffer; // HDR R11G11B11F packed atlas + halfFloat_t* outBuffer; // HDR R11G11B11F packed octahedron atlas int time; // execution time in milliseconds }; -static const int LIGHTGRID_IRRADIANCE_SIZE = 8; +static const int LIGHTGRID_IRRADIANCE_SIZE = 32; struct calcLightGridPointParms_t { // input byte* buffers[6]; // HDR RGB16F standard OpenGL cubemap sides - int area; + int gridCoord[3]; - int outWidth; + int outWidth; // LIGHTGRID_IRRADIANCE_SIZE int outHeight; // output SphericalHarmonicsT SH4; - - halfFloat_t* outBuffer; // HDR R11G11B11F packed atlas + halfFloat_t* outBuffer; // HDR R11G11B11F octahedron LIGHTGRID_IRRADIANCE_SIZE^2 int time; // execution time in milliseconds }; // RB end diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 69cf1195..2666c221 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -80,7 +80,7 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con } // try to load existing lightgrid data -#if 0 +#if 1 idStr basename = mapName; basename.StripFileExtension(); @@ -93,14 +93,14 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con gridPoint->irradianceImage = NULL; fullname.Format( "env/%s/area%i_lightgridpoint%i_amb", basename.c_str(), area, i ); - gridPoint->irradianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); + gridPoint->irradianceImage = globalImages->ImageFromFile( fullname, TF_LINEAR, TR_CLAMP, TD_R11G11B10F, CF_2D ); } #else for( int i = 0; i < lightGridPoints.Num(); i++ ) { lightGridPoint_t* gridPoint = &lightGridPoints[i]; - //gridPoint->irradianceImage = NULL; + gridPoint->irradianceImage = NULL; } #endif } @@ -145,6 +145,7 @@ int LightGrid::GridCoordToProbeIndex( int gridCoord[3] ) void LightGrid::ProbeIndexToGridCoord( const int probeIndex, int gridCoord[3] ) { +#if 1 // slow brute force method only for debugging int gridStep[3]; @@ -176,6 +177,12 @@ void LightGrid::ProbeIndexToGridCoord( const int probeIndex, int gridCoord[3] ) } } } +#else + + gridPoints + + GetBaseGridCoord() +#endif } idVec3 LightGrid::GetGridCoordDebugColor( int gridCoord[3] ) @@ -429,7 +436,7 @@ void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) // build SH by iterating over all cubemap pixels - idVec4 dstRect = R_CalculateMipRect( parms->outHeight, 0 ); + //idVec4 dstRect = R_CalculateMipRect( parms->outHeight, 0 ); for( int side = 0; side < 6; side++ ) { @@ -485,70 +492,54 @@ void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) } } - for( int mip = 0; mip < numMips; mip++ ) + for( int x = 0; x < parms->outWidth; x++ ) { - float roughness = ( float )mip / ( float )( numMips - 1 ); - - idVec4 dstRect = R_CalculateMipRect( parms->outHeight, mip ); - - for( int x = dstRect.x; x < ( dstRect.x + dstRect.z ); x++ ) + for( int y = 0; y < parms->outHeight; y++ ) { - 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 ); - } + idVec2 octCoord = NormalizedOctCoord( x, y, parms->outWidth ); - // convert UV coord to 3D direction - idVec3 dir; + // convert UV coord to 3D direction + idVec3 dir; - dir.FromOctahedral( octCoord ); + dir.FromOctahedral( octCoord ); - idVec3 outColor( 0, 0, 0 ); + idVec3 outColor( 0, 0, 0 ); #if 1 - // generate ambient colors by evaluating the L4 Spherical Harmonics - SphericalHarmonicsT shDirection = shEvaluate<4>( dir ); + // generate ambient colors by evaluating the L4 Spherical Harmonics + SphericalHarmonicsT shDirection = shEvaluate<4>( dir ); - idVec3 sampleIrradianceSh = shEvaluateDiffuse( shRadiance, dir ) / idMath::PI; + idVec3 sampleIrradianceSh = shEvaluateDiffuse( shRadiance, dir ) / idMath::PI; - outColor[0] = Max( 0.0f, sampleIrradianceSh.x ); - outColor[1] = Max( 0.0f, sampleIrradianceSh.y ); - outColor[2] = Max( 0.0f, sampleIrradianceSh.z ); + outColor[0] = Max( 0.0f, sampleIrradianceSh.x ); + outColor[1] = Max( 0.0f, sampleIrradianceSh.y ); + outColor[2] = Max( 0.0f, sampleIrradianceSh.z ); #else - // generate ambient colors using Monte Carlo method - for( int s = 0; s < parms->samples; s++ ) - { - idVec2 Xi = Hammersley2D( s, parms->samples ); - idVec3 H = ImportanceSampleGGX( Xi, dir, 0.95f ); + // generate ambient colors using Monte Carlo method + for( int s = 0; s < parms->samples; s++ ) + { + idVec2 Xi = Hammersley2D( s, parms->samples ); + idVec3 H = ImportanceSampleGGX( Xi, dir, 0.95f ); - float u, v; - idVec3 radiance; - R_SampleCubeMapHDR( H, parms->outHeight, buffers, &radiance[0], u, v ); + float u, v; + idVec3 radiance; + R_SampleCubeMapHDR( H, parms->outHeight, buffers, &radiance[0], u, v ); - outColor[0] += radiance[0]; - outColor[1] += radiance[1]; - outColor[2] += radiance[2]; - } + outColor[0] += radiance[0]; + outColor[1] += radiance[1]; + outColor[2] += radiance[2]; + } - outColor[0] /= parms->samples; - outColor[1] /= parms->samples; - outColor[2] /= parms->samples; + outColor[0] /= parms->samples; + outColor[1] /= parms->samples; + outColor[2] /= parms->samples; #endif - //outColor = dir * 0.5 + idVec3( 0.5f, 0.5f, 0.5f ); + //outColor = dir * 0.5 + idVec3( 0.5f, 0.5f, 0.5f ); - parms->outBuffer[( y * parms->outWidth + x ) * 3 + 0] = F32toF16( outColor[0] ); - parms->outBuffer[( y * parms->outWidth + x ) * 3 + 1] = F32toF16( outColor[1] ); - parms->outBuffer[( y * parms->outWidth + x ) * 3 + 2] = F32toF16( outColor[2] ); - } + parms->outBuffer[( y * parms->outWidth + x ) * 3 + 0] = F32toF16( outColor[0] ); + parms->outBuffer[( y * parms->outWidth + x ) * 3 + 1] = F32toF16( outColor[1] ); + parms->outBuffer[( y * parms->outWidth + x ) * 3 + 2] = F32toF16( outColor[2] ); } } @@ -635,7 +626,7 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) renderView_t ref; int blends; const char* extension; - int size; + int captureSize; static const char* envDirection[6] = { "_px", "_nx", "_py", "_ny", "_pz", "_nz" }; @@ -650,7 +641,7 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) baseName = tr.primaryWorld->mapName; baseName.StripFileExtension(); - size = RADIANCE_CUBEMAP_SIZE; + captureSize = RADIANCE_CUBEMAP_SIZE; blends = 1; if( !tr.primaryView ) @@ -665,6 +656,7 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) // CAPTURE SCENE LIGHTING TO CUBEMAPS //-------------------------------------------- + /* int totalGridPoints = 0; for( int a = 0; a < tr.primaryWorld->NumAreas(); a++ ) { @@ -672,137 +664,185 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) totalGridPoints += area->lightGrid.lightGridPoints.Num(); } - - CommandlineProgressBar progressBar( totalGridPoints ); - if( !useThreads ) - { - progressBar.Start(); - } - - int start = Sys_Milliseconds(); + */ for( int a = 0; a < tr.primaryWorld->NumAreas(); a++ ) { portalArea_t* area = &tr.primaryWorld->portalAreas[a]; - for( int i = 0; i < area->lightGrid.lightGridPoints.Num(); i++ ) + CommandlineProgressBar progressBar( area->lightGrid.lightGridPoints.Num() ); + if( !useThreads ) { - lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i]; - if( !gridPoint->valid ) + progressBar.Start(); + } + + int start = Sys_Milliseconds(); + + int gridStep[3]; + + gridStep[0] = 1; + gridStep[1] = area->lightGrid.lightGridBounds[0]; + gridStep[2] = area->lightGrid.lightGridBounds[0] * area->lightGrid.lightGridBounds[1]; + + int gridCoord[3]; + + for( int i = 0; i < area->lightGrid.lightGridBounds[0]; i += 1 ) + { + for( int j = 0; j < area->lightGrid.lightGridBounds[1]; j += 1 ) { - progressBar.Increment(); - continue; - } + for( int k = 0; k < area->lightGrid.lightGridBounds[2]; k += 1 ) + { + gridCoord[0] = i; + gridCoord[1] = j; + gridCoord[2] = k; - calcLightGridPointParms_t* jobParms = new calcLightGridPointParms_t; - jobParms->area = a; + lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[ gridCoord[0] * gridStep[0] + gridCoord[1] * gridStep[1] + gridCoord[2] * gridStep[2] ]; + if( !gridPoint->valid ) + { + progressBar.Increment(); + continue; + } - for( int j = 0 ; j < 6 ; j++ ) - { - ref = primary.renderView; + calcLightGridPointParms_t* jobParms = new calcLightGridPointParms_t; + jobParms->gridCoord[0] = i; + jobParms->gridCoord[1] = j; + jobParms->gridCoord[2] = k; - ref.rdflags = RDF_NOAMBIENT | RDF_IRRADIANCE; - ref.fov_x = ref.fov_y = 90; + for( int side = 0; side < 6; side++ ) + { + ref = primary.renderView; - ref.vieworg = gridPoint->origin; - ref.viewaxis = tr.cubeAxis[j]; + ref.rdflags = RDF_NOAMBIENT | RDF_IRRADIANCE; + ref.fov_x = ref.fov_y = 90; - extension = envDirection[ j ]; + ref.vieworg = gridPoint->origin; + ref.viewaxis = tr.cubeAxis[ side ]; - //tr.TakeScreenshot( size, size, fullname, blends, &ref, EXR ); - byte* float16FRGB = tr.CaptureRenderToBuffer( size, size, &ref ); + extension = envDirection[ side ]; - jobParms->buffers[ j ] = float16FRGB; + //tr.TakeScreenshot( size, size, fullname, blends, &ref, EXR ); + byte* float16FRGB = tr.CaptureRenderToBuffer( captureSize, captureSize, &ref ); + + jobParms->buffers[ side ] = float16FRGB; #if 0 - if( i < 3 ) - { - filename.Format( "env/%s/area%i_lightgridpoint%i%s.exr", baseName.c_str(), a, i, extension ); - R_WriteEXR( filename, float16FRGB, 3, size, size, "fs_basepath" ); - } + if( i < 3 ) + { + filename.Format( "env/%s/area%i_lightgridpoint%i%s.exr", baseName.c_str(), a, i, extension ); + R_WriteEXR( filename, float16FRGB, 3, size, size, "fs_basepath" ); + } #endif + } + + tr.lightGridJobs.Append( jobParms ); + + progressBar.Increment(); + } } - - tr.lightGridJobs.Append( jobParms ); - - progressBar.Increment(); } - } - int end = Sys_Milliseconds(); + int end = Sys_Milliseconds(); - common->Printf( "captured light grid radiance in %5.1f seconds\n\n", ( end - start ) * 0.001f ); + common->Printf( "captured light grid radiance for area %i in %5.1f seconds\n\n", a, ( end - start ) * 0.001f ); - //common->Printf( "Wrote a env set with the name %s\n", baseName.c_str() ); + //-------------------------------------------- + // GENERATE IRRADIANCE + //-------------------------------------------- - //-------------------------------------------- - // GENERATE IRRADIANCE - //-------------------------------------------- + if( !useThreads ) + { + progressBar.Reset(); + progressBar.Start(); + } - if( !useThreads ) - { - progressBar.Reset(); - progressBar.Start(); - } + start = Sys_Milliseconds(); - start = Sys_Milliseconds(); + for( int j = 0; j < tr.lightGridJobs.Num(); j++ ) + { + calcLightGridPointParms_t* jobParms = tr.lightGridJobs[ j ]; - for( int j = 0; j < tr.lightGridJobs.Num(); j++ ) - { - calcLightGridPointParms_t* jobParms = tr.lightGridJobs[ j ]; + jobParms->outWidth = LIGHTGRID_IRRADIANCE_SIZE; + jobParms->outHeight = LIGHTGRID_IRRADIANCE_SIZE; + jobParms->outBuffer = ( halfFloat_t* )R_StaticAlloc( idMath::Ceil( LIGHTGRID_IRRADIANCE_SIZE * LIGHTGRID_IRRADIANCE_SIZE * 3 * sizeof( halfFloat_t ) * 1.5f ), TAG_IMAGE ); - jobParms->outWidth = int( IRRADIANCE_CUBEMAP_SIZE * 1.5f ); - jobParms->outHeight = IRRADIANCE_CUBEMAP_SIZE; - jobParms->outBuffer = ( halfFloat_t* )R_StaticAlloc( idMath::Ceil( IRRADIANCE_CUBEMAP_SIZE * IRRADIANCE_CUBEMAP_SIZE * 3 * sizeof( halfFloat_t ) * 1.5f ), TAG_IMAGE ); + if( useThreads ) + { + tr.envprobeJobList->AddJob( ( jobRun_t )CalculateLightGridPointJob, jobParms ); + } + else + { + CalculateLightGridPointJob( jobParms ); + progressBar.Increment(); + } + } if( useThreads ) { - tr.envprobeJobList->AddJob( ( jobRun_t )CalculateLightGridPointJob, jobParms ); + //tr.envprobeJobList->Submit(); + tr.envprobeJobList->Submit( NULL, JOBLIST_PARALLELISM_MAX_CORES ); + tr.envprobeJobList->Wait(); } - else + + + + int atlasWidth = area->lightGrid.lightGridBounds[0] * area->lightGrid.lightGridBounds[1] * LIGHTGRID_IRRADIANCE_SIZE; + int atlasHeight = area->lightGrid.lightGridBounds[2] * LIGHTGRID_IRRADIANCE_SIZE; + + idTempArray irradianceAtlas( atlasWidth * atlasHeight * 3 ); + + // fill everything with solid red + for( int i = 0; i < ( atlasWidth * atlasHeight ); i++ ) { - CalculateLightGridPointJob( jobParms ); - progressBar.Increment(); + irradianceAtlas[i * 3 + 0] = F32toF16( 1.0f ); + irradianceAtlas[i * 3 + 1] = F32toF16( 0.0f ); + irradianceAtlas[i * 3 + 2] = F32toF16( 0.0f ); } - } - if( useThreads ) - { - //tr.envprobeJobList->Submit(); - tr.envprobeJobList->Submit( NULL, JOBLIST_PARALLELISM_MAX_CORES ); - tr.envprobeJobList->Wait(); - } - - - - for( int j = 0; j < tr.lightGridJobs.Num(); j++ ) - { - calcLightGridPointParms_t* job = tr.lightGridJobs[ j ]; - - filename.Format( "env/%s/area%i_lightgridpoint%i_amb.exr", baseName.c_str(), job->area, j ); - - R_WriteEXR( filename.c_str(), ( byte* )job->outBuffer, 3, job->outWidth, job->outHeight, "fs_basepath" ); - - //common->Printf( "%s convolved in %5.1f seconds\n\n", filename.c_str(), job->time * 0.001f ); - - for( int i = 0; i < 6; i++ ) + for( int j = 0; j < tr.lightGridJobs.Num(); j++ ) { - if( job->buffers[i] ) + calcLightGridPointParms_t* job = tr.lightGridJobs[ j ]; + + //filename.Format( "env/%s/area%i_lightgridpoint%i_amb.exr", baseName.c_str(), a, j ); + //R_WriteEXR( filename.c_str(), ( byte* )job->outBuffer, 3, job->outWidth, job->outHeight, "fs_basepath" ); + + for( int x = 0; x < LIGHTGRID_IRRADIANCE_SIZE; x++ ) { - Mem_Free( job->buffers[i] ); + for( int y = 0; y < LIGHTGRID_IRRADIANCE_SIZE; y++ ) + { + // gridPoint = lightGridPoints[ gridCoord[0] * gridStep[0] + gridCoord[1] * gridStep[1] + gridCoord[2] * gridStep[2] ]; + + int xx = x + ( job->gridCoord[0] * gridStep[0] + job->gridCoord[1] * gridStep[1] ) * LIGHTGRID_IRRADIANCE_SIZE; + int yy = y + job->gridCoord[2] * LIGHTGRID_IRRADIANCE_SIZE; + + irradianceAtlas[( yy * atlasWidth + xx ) * 3 + 0] = job->outBuffer[( y * LIGHTGRID_IRRADIANCE_SIZE + x ) * 3 + 0]; + irradianceAtlas[( yy * atlasWidth + xx ) * 3 + 1] = job->outBuffer[( y * LIGHTGRID_IRRADIANCE_SIZE + x ) * 3 + 1]; + irradianceAtlas[( yy * atlasWidth + xx ) * 3 + 2] = job->outBuffer[( y * LIGHTGRID_IRRADIANCE_SIZE + x ) * 3 + 2]; + } } + + for( int i = 0; i < 6; i++ ) + { + if( job->buffers[i] ) + { + Mem_Free( job->buffers[i] ); + } + } + + Mem_Free( job->outBuffer ); + + delete job; } - Mem_Free( job->outBuffer ); + filename.Format( "env/%s/area%i_lightgrid_amb.exr", baseName.c_str(), a ); - delete job; + R_WriteEXR( filename.c_str(), irradianceAtlas.Ptr(), 3, atlasWidth, atlasHeight, "fs_basepath" ); + + tr.lightGridJobs.Clear(); + + end = Sys_Milliseconds(); + + common->Printf( "computed light grid irradiance for area %i in %5.1f seconds\n\n", a, ( end - start ) * 0.001f ); } - - tr.lightGridJobs.Clear(); - - end = Sys_Milliseconds(); - - common->Printf( "computed light grid irradiance in %5.1f seconds\n\n", ( end - start ) * 0.001f ); } #if 0 diff --git a/neo/renderer/RenderWorld_local.h b/neo/renderer/RenderWorld_local.h index 1026f210..cfe4de05 100644 --- a/neo/renderer/RenderWorld_local.h +++ b/neo/renderer/RenderWorld_local.h @@ -69,7 +69,7 @@ struct lightGridPoint_t SphericalHarmonicsT SH4; // TODO REMOVE just for testing - //idImage* irradianceImage; + idImage* irradianceImage; }; class LightGrid From 884658d6dd3dfc5edade821a1d6f090c490d581e Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Thu, 15 Apr 2021 13:11:27 +0200 Subject: [PATCH 07/26] Added lightgrid debug shader --- base/renderprogs/_manifest.lua | 2 + .../builtin/debug/lightgrid.ps.hlsl | 110 ++++++++ .../builtin/debug/lightgrid.vs.hlsl | 126 +++++++++ neo/renderer/OpenGL/RenderDebug_GL.cpp | 27 +- neo/renderer/RenderProgs.cpp | 11 +- neo/renderer/RenderProgs.h | 25 +- neo/renderer/RenderProgs_embedded.h | 248 ++++++++++++++++++ neo/renderer/RenderSystem_init.cpp | 2 +- neo/renderer/RenderWorld_lightgrid.cpp | 22 +- neo/renderer/RenderWorld_local.h | 7 +- 10 files changed, 552 insertions(+), 28 deletions(-) create mode 100644 base/renderprogs/builtin/debug/lightgrid.ps.hlsl create mode 100644 base/renderprogs/builtin/debug/lightgrid.vs.hlsl diff --git a/base/renderprogs/_manifest.lua b/base/renderprogs/_manifest.lua index f7b7c19e..7878a186 100644 --- a/base/renderprogs/_manifest.lua +++ b/base/renderprogs/_manifest.lua @@ -15,6 +15,8 @@ return "builtin/debug/shadowDebug_skinned.vs.hlsl", "builtin/debug/octahedron.ps.hlsl", "builtin/debug/octahedron.vs.hlsl", + "builtin/debug/lightgrid.ps.hlsl", + "builtin/debug/lightgrid.vs.hlsl", "builtin/fog/blendLight.ps.hlsl", "builtin/fog/blendLight.vs.hlsl", diff --git a/base/renderprogs/builtin/debug/lightgrid.ps.hlsl b/base/renderprogs/builtin/debug/lightgrid.ps.hlsl new file mode 100644 index 00000000..14f564d2 --- /dev/null +++ b/base/renderprogs/builtin/debug/lightgrid.ps.hlsl @@ -0,0 +1,110 @@ +/* +=========================================================================== + +Doom 3 BFG Edition GPL Source Code +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"). + +Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 BFG Edition Source Code. If not, see . + +In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ + +#include "renderprogs/global.inc.hlsl" + + +// *INDENT-OFF* +uniform sampler2D samp0 : register(s0); // texture 0 is octahedron cube map atlas + +struct PS_IN { + float4 position : VPOS; + float3 texcoord0 : TEXCOORD0_centroid; + float3 texcoord1 : TEXCOORD1_centroid; + float4 color : COLOR0; +}; + +struct PS_OUT { + float4 color : COLOR; +}; +// *INDENT-ON* + + +float3 lightGridOrigin = float3( -192.0, -128.0, 0 ); +float3 lightGridSize = float3( 64.0, 64.0, 128.0 ); +int3 lightGridBounds = int3( 7, 7, 3 ); + +int3 GetBaseGridCoord( float3 origin ) +{ + int3 pos; + + float3 lightOrigin = origin - lightGridOrigin; + for( int i = 0; i < 3; i++ ) + { + float v; + + v = lightOrigin[i] * ( 1.0f / lightGridSize[i] ); + pos[i] = int( floor( v ) ); + + if( pos[i] < 0 ) + { + pos[i] = 0; + } + else if( pos[i] >= lightGridBounds[i] - 1 ) + { + pos[i] = lightGridBounds[i] - 1; + } + } + + return pos; +} + + + +void main( PS_IN fragment, out PS_OUT result ) +{ + const int LIGHTGRID_IRRADIANCE_SIZE = 32; + + float3 globalPosition = fragment.texcoord0.xyz; + float3 globalNormal = normalize( fragment.texcoord1 ); + + float2 normalizedOctCoord = octEncode( globalNormal ); + float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5; + + float invXY = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[1] ) ); + float invZ = ( 1.0 / lightGridBounds[2] ); + + normalizedOctCoordZeroOne.x *= invXY; + normalizedOctCoordZeroOne.y *= invZ; + + int3 gridStep; + + gridStep[0] = 1; + gridStep[1] = lightGridBounds[0]; + gridStep[2] = lightGridBounds[0] * lightGridBounds[1]; + + int3 gridCoord = GetBaseGridCoord( globalPosition ); + + normalizedOctCoordZeroOne.x += ( gridCoord[0] * gridStep[0] + gridCoord[1] * gridStep[1] ) * invXY; + normalizedOctCoordZeroOne.y += ( gridCoord[2] * invZ ); + + float4 envMap = tex2D( samp0, normalizedOctCoordZeroOne ); + + result.color = float4( envMap.xyz, 1.0f ) * 1.0 * fragment.color; +} diff --git a/base/renderprogs/builtin/debug/lightgrid.vs.hlsl b/base/renderprogs/builtin/debug/lightgrid.vs.hlsl new file mode 100644 index 00000000..07a117c7 --- /dev/null +++ b/base/renderprogs/builtin/debug/lightgrid.vs.hlsl @@ -0,0 +1,126 @@ +/* +=========================================================================== + +Doom 3 BFG Edition GPL Source Code +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"). + +Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 BFG Edition Source Code. If not, see . + +In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ + +#include "renderprogs/global.inc.hlsl" + + +uniform matrices_ubo { float4 matrices[408]; }; + +// *INDENT-OFF* +struct VS_IN { + float4 position : POSITION; + float2 texcoord : TEXCOORD0; + float4 normal : NORMAL; + float4 tangent : TANGENT; + float4 color : COLOR0; + float4 color2 : COLOR1; +}; + +struct VS_OUT { + float4 position : POSITION; + float3 texcoord0 : TEXCOORD0; + float3 texcoord1 : TEXCOORD1; + float4 color : COLOR0; +}; +// *INDENT-ON* + +void main( VS_IN vertex, out VS_OUT result ) +{ + float4 vNormal = vertex.normal * 2.0 - 1.0; + +#if defined( USE_GPU_SKINNING ) + + //-------------------------------------------------------------- + // GPU transformation of the normal / binormal / bitangent + // + // multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 ) + //-------------------------------------------------------------- + const float w0 = vertex.color2.x; + const float w1 = vertex.color2.y; + const float w2 = vertex.color2.z; + const float w3 = vertex.color2.w; + + float4 matX, matY, matZ; // must be float4 for vec4 + int joint = int( vertex.color.x * 255.1 * 3.0 ); + matX = matrices[int( joint + 0 )] * w0; + matY = matrices[int( joint + 1 )] * w0; + matZ = matrices[int( joint + 2 )] * w0; + + joint = int( vertex.color.y * 255.1 * 3.0 ); + matX += matrices[int( joint + 0 )] * w1; + matY += matrices[int( joint + 1 )] * w1; + matZ += matrices[int( joint + 2 )] * w1; + + joint = int( vertex.color.z * 255.1 * 3.0 ); + matX += matrices[int( joint + 0 )] * w2; + matY += matrices[int( joint + 1 )] * w2; + matZ += matrices[int( joint + 2 )] * w2; + + joint = int( vertex.color.w * 255.1 * 3.0 ); + matX += matrices[int( joint + 0 )] * w3; + matY += matrices[int( joint + 1 )] * w3; + matZ += matrices[int( joint + 2 )] * w3; + + float3 normal; + normal.x = dot3( matX, vNormal ); + normal.y = dot3( matY, vNormal ); + normal.z = dot3( matZ, vNormal ); + normal = normalize( normal ); + + float4 modelPosition; + modelPosition.x = dot4( matX, vertex.position ); + modelPosition.y = dot4( matY, vertex.position ); + modelPosition.z = dot4( matZ, vertex.position ); + modelPosition.w = 1.0; + +#else + + float4 modelPosition = vertex.position; + float4 normal = vNormal; + +#endif + + result.position.x = dot4( modelPosition, rpMVPmatrixX ); + result.position.y = dot4( modelPosition, rpMVPmatrixY ); + result.position.z = dot4( modelPosition, rpMVPmatrixZ ); + result.position.w = dot4( modelPosition, rpMVPmatrixW ); + + result.texcoord1.x = dot3( normal, rpModelMatrixX ); + result.texcoord1.y = dot3( normal, rpModelMatrixY ); + result.texcoord1.z = dot3( normal, rpModelMatrixZ ); + + float4 worldPosition; + worldPosition.x = dot4( modelPosition, rpModelMatrixX ); + worldPosition.y = dot4( modelPosition, rpModelMatrixY ); + worldPosition.z = dot4( modelPosition, rpModelMatrixZ ); + worldPosition.w = dot4( modelPosition, rpModelMatrixW ); + result.texcoord0 = worldPosition.xyz; + + result.color = sRGBAToLinearRGBA( rpColor ); +} diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index 955b786c..f8684580 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1719,7 +1719,7 @@ void idRenderBackend::DBG_ShowViewEnvprobes() { count++; - renderProgManager.BindShader_Octahedron(); + renderProgManager.BindShader_DebugOctahedron(); GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_DEPTHMASK ); GL_Color( 1.0f, 1.0f, 1.0f ); @@ -1815,6 +1815,10 @@ void idRenderBackend::DBG_ShowLightGrid() const int numColors = 7; static idVec4 colors[numColors] = { colorBlack, colorBlue, colorCyan, colorGreen, colorYellow, colorRed, colorWhite }; + // use rpGlobalLightOrigin for camera center + idVec4 globalViewOrigin( viewDef->renderView.vieworg.x, viewDef->renderView.vieworg.y, viewDef->renderView.vieworg.z, 1.0f ); + renderProgManager.SetUniformValue( RENDERPARM_GLOBALLIGHTORIGIN, globalViewOrigin.ToFloatPtr() ); + for( int i = 0; i < area->lightGrid.lightGridPoints.Num(); i++ ) { lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i]; @@ -1829,13 +1833,16 @@ void idRenderBackend::DBG_ShowLightGrid() continue; } -#if 1 +#if 0 if( i > 53 ) { break; } #endif + // move center into the cube so we can void using negative results with GetBaseGridCoord + idVec3 gridPointOrigin = gridPoint->origin + idVec3( 4, 4, 4 ); + idVec4 localViewOrigin( 1.0f ); idVec4 globalViewOrigin; globalViewOrigin.x = viewDef->renderView.vieworg.x; @@ -1844,12 +1851,21 @@ void idRenderBackend::DBG_ShowLightGrid() globalViewOrigin.w = 1.0f; float modelMatrix[16]; - R_AxisToModelMatrix( axis, gridPoint->origin, modelMatrix ); + R_AxisToModelMatrix( axis, gridPointOrigin, modelMatrix ); R_GlobalPointToLocal( modelMatrix, viewDef->renderView.vieworg, localViewOrigin.ToVec3() ); renderProgManager.SetUniformValue( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); // rpLocalViewOrigin + // RB: if we want to get the normals in world space so we need the model -> world matrix + idRenderMatrix modelMatrix2; + idRenderMatrix::Transpose( *( idRenderMatrix* )modelMatrix, modelMatrix2 ); + + renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_X, &modelMatrix2[0][0] ); + renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_Y, &modelMatrix2[1][0] ); + renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_Z, &modelMatrix2[2][0] ); + renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_W, &modelMatrix2[3][0] ); + #if 0 renderProgManager.BindShader_Color(); @@ -1862,10 +1878,10 @@ void idRenderBackend::DBG_ShowLightGrid() //idVec4 color = colors[ i % numColors ]; GL_Color( color ); #else - renderProgManager.BindShader_Octahedron(); + renderProgManager.BindShader_DebugLightGrid(); GL_SelectTexture( 0 ); - gridPoint->irradianceImage->Bind(); + area->lightGrid.irradianceImage->Bind(); #endif idRenderMatrix modelRenderMatrix; @@ -1883,6 +1899,7 @@ void idRenderBackend::DBG_ShowLightGrid() RB_SetMVP( invProjectMVPMatrix ); DrawElementsWithCounters( &zeroOneSphereSurface ); + //DrawElementsWithCounters( &zeroOneCubeSurface ); } if( r_showLightGrid.GetInteger() == 2 ) diff --git a/neo/renderer/RenderProgs.cpp b/neo/renderer/RenderProgs.cpp index d3aadac4..cfb9c982 100644 --- a/neo/renderer/RenderProgs.cpp +++ b/neo/renderer/RenderProgs.cpp @@ -154,8 +154,12 @@ void idRenderProgManager::Init() { BUILTIN_PBR_INTERACTION_SHADOW_MAPPING_PARALLEL, "builtin/lighting/interactionSM", "_parallel_PBR", BIT( LIGHT_PARALLEL ) | BIT( USE_PBR ), false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, { BUILTIN_PBR_INTERACTION_SHADOW_MAPPING_PARALLEL_SKINNED, "builtin/lighting/interactionSM", "_parallel_skinned_PBR", BIT( USE_GPU_SKINNING ) | BIT( LIGHT_PARALLEL ) | BIT( USE_PBR ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, - { BUILTIN_OCTAHEDRON, "builtin/debug/octahedron", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, - { BUILTIN_OCTAHEDRON_SKINNED, "builtin/debug/octahedron", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, + // debug stuff + { BUILTIN_DEBUG_LIGHTGRID, "builtin/debug/lightgrid", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, + { BUILTIN_DEBUG_LIGHTGRID_SKINNED, "builtin/debug/lightgrid", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, + + { BUILTIN_DEBUG_OCTAHEDRON, "builtin/debug/octahedron", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, + { BUILTIN_DEBUG_OCTAHEDRON_SKINNED, "builtin/debug/octahedron", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, // RB end { BUILTIN_ENVIRONMENT, "builtin/legacy/environment", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, @@ -272,7 +276,8 @@ void idRenderProgManager::Init() renderProgs[builtinShaders[BUILTIN_SHADOW_DEBUG_SKINNED]].usesJoints = true; renderProgs[builtinShaders[BUILTIN_FOG_SKINNED]].usesJoints = true; // RB begin - renderProgs[builtinShaders[BUILTIN_OCTAHEDRON_SKINNED]].usesJoints = true; + renderProgs[builtinShaders[BUILTIN_DEBUG_LIGHTGRID_SKINNED]].usesJoints = true; + renderProgs[builtinShaders[BUILTIN_DEBUG_OCTAHEDRON_SKINNED]].usesJoints = true; renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTING_SKINNED]].usesJoints = true; renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED]].usesJoints = true; renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTING_IBL_PBR_SKINNED]].usesJoints = true; diff --git a/neo/renderer/RenderProgs.h b/neo/renderer/RenderProgs.h index e2f1076e..76114f8b 100644 --- a/neo/renderer/RenderProgs.h +++ b/neo/renderer/RenderProgs.h @@ -451,14 +451,24 @@ public: BindShader_Builtin( BUILTIN_PBR_INTERACTION_SHADOW_MAPPING_PARALLEL_SKINNED ); } - void BindShader_Octahedron() + void BindShader_DebugLightGrid() { - BindShader_Builtin( BUILTIN_OCTAHEDRON ); + BindShader_Builtin( BUILTIN_DEBUG_LIGHTGRID ); } - void BindShader_OctahedronSkinned() + void BindShader_DebugLightGridSkinned() { - BindShader_Builtin( BUILTIN_OCTAHEDRON_SKINNED ); + BindShader_Builtin( BUILTIN_DEBUG_LIGHTGRID_SKINNED ); + } + + void BindShader_DebugOctahedron() + { + BindShader_Builtin( BUILTIN_DEBUG_OCTAHEDRON ); + } + + void BindShader_DebugOctahedronSkinned() + { + BindShader_Builtin( BUILTIN_DEBUG_OCTAHEDRON_SKINNED ); } // RB end @@ -767,8 +777,11 @@ private: BUILTIN_PBR_INTERACTION_SHADOW_MAPPING_PARALLEL, BUILTIN_PBR_INTERACTION_SHADOW_MAPPING_PARALLEL_SKINNED, - BUILTIN_OCTAHEDRON, - BUILTIN_OCTAHEDRON_SKINNED, + BUILTIN_DEBUG_LIGHTGRID, + BUILTIN_DEBUG_LIGHTGRID_SKINNED, + + BUILTIN_DEBUG_OCTAHEDRON, + BUILTIN_DEBUG_OCTAHEDRON_SKINNED, // RB end BUILTIN_ENVIRONMENT, BUILTIN_ENVIRONMENT_SKINNED, diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index bdd1c269..2d797e87 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -2761,6 +2761,254 @@ static const cgShaderDef_t cg_renderprogs[] = }, + { + "renderprogs/builtin/debug/lightgrid.ps.hlsl", + "/*\n" + "===========================================================================\n" + "\n" + "Doom 3 BFG Edition GPL Source Code\n" + "Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.\n" + "Copyright (C) 2021 Robert Beckebans\n" + "\n" + "This file is part of the Doom 3 BFG Edition GPL Source Code (\"Doom 3 BFG Edition Source Code\").\n" + "\n" + "Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation, either version 3 of the License, or\n" + "(at your option) any later version.\n" + "\n" + "Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License\n" + "along with Doom 3 BFG Edition Source Code. If not, see .\n" + "\n" + "In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.\n" + "\n" + "If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.\n" + "\n" + "===========================================================================\n" + "*/\n" + "\n" + "#include \"renderprogs/global.inc.hlsl\"\n" + "\n" + "\n" + "// *INDENT-OFF*\n" + "uniform sampler2D samp0 : register(s0); // texture 0 is octahedron cube map atlas\n" + "\n" + "struct PS_IN {\n" + " float4 position : VPOS;\n" + " float3 texcoord0 : TEXCOORD0_centroid;\n" + " float3 texcoord1 : TEXCOORD1_centroid;\n" + " float4 color : COLOR0;\n" + "};\n" + "\n" + "struct PS_OUT {\n" + " float4 color : COLOR;\n" + "};\n" + "// *INDENT-ON*\n" + "\n" + "\n" + "float3 lightGridOrigin = float3( -192.0, -128.0, 0 );\n" + "float3 lightGridSize = float3( 64.0, 64.0, 128.0 );\n" + "int3 lightGridBounds = int3( 7, 7, 3 );\n" + "\n" + "int3 GetBaseGridCoord( float3 origin )\n" + "{\n" + " int3 pos;\n" + "\n" + " float3 lightOrigin = origin - lightGridOrigin;\n" + " for( int i = 0; i < 3; i++ )\n" + " {\n" + " float v;\n" + "\n" + " v = lightOrigin[i] * ( 1.0f / lightGridSize[i] );\n" + " pos[i] = int( floor( v ) );\n" + "\n" + " if( pos[i] < 0 )\n" + " {\n" + " pos[i] = 0;\n" + " }\n" + " else if( pos[i] >= lightGridBounds[i] - 1 )\n" + " {\n" + " pos[i] = lightGridBounds[i] - 1;\n" + " }\n" + " }\n" + "\n" + " return pos;\n" + "}\n" + "\n" + "\n" + "\n" + "void main( PS_IN fragment, out PS_OUT result )\n" + "{\n" + " const int LIGHTGRID_IRRADIANCE_SIZE = 32;\n" + "\n" + " float3 globalPosition = fragment.texcoord0.xyz;\n" + " float3 globalNormal = normalize( fragment.texcoord1 );\n" + "\n" + " float2 normalizedOctCoord = octEncode( globalNormal );\n" + " float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n" + "\n" + " float invXY = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[1] ) );\n" + " float invZ = ( 1.0 / lightGridBounds[2] );\n" + "\n" + " normalizedOctCoordZeroOne.x *= invXY;\n" + " normalizedOctCoordZeroOne.y *= invZ;\n" + "\n" + " int3 gridStep;\n" + "\n" + " gridStep[0] = 1;\n" + " gridStep[1] = lightGridBounds[0];\n" + " gridStep[2] = lightGridBounds[0] * lightGridBounds[1];\n" + "\n" + " int3 gridCoord = GetBaseGridCoord( globalPosition );\n" + "\n" + " normalizedOctCoordZeroOne.x += ( gridCoord[0] * gridStep[0] + gridCoord[1] * gridStep[1] ) * invXY;\n" + " normalizedOctCoordZeroOne.y += ( gridCoord[2] * invZ );\n" + "\n" + " float4 envMap = tex2D( samp0, normalizedOctCoordZeroOne );\n" + "\n" + " result.color = float4( envMap.xyz, 1.0f ) * 1.0 * fragment.color;\n" + "}\n" + "\n" + + }, + + { + "renderprogs/builtin/debug/lightgrid.vs.hlsl", + "/*\n" + "===========================================================================\n" + "\n" + "Doom 3 BFG Edition GPL Source Code\n" + "Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.\n" + "Copyright (C) 2021 Robert Beckebans\n" + "\n" + "This file is part of the Doom 3 BFG Edition GPL Source Code (\"Doom 3 BFG Edition Source Code\").\n" + "\n" + "Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation, either version 3 of the License, or\n" + "(at your option) any later version.\n" + "\n" + "Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License\n" + "along with Doom 3 BFG Edition Source Code. If not, see .\n" + "\n" + "In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.\n" + "\n" + "If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.\n" + "\n" + "===========================================================================\n" + "*/\n" + "\n" + "#include \"renderprogs/global.inc.hlsl\"\n" + "\n" + "\n" + "uniform matrices_ubo { float4 matrices[408]; };\n" + "\n" + "// *INDENT-OFF*\n" + "struct VS_IN {\n" + " float4 position : POSITION;\n" + " float2 texcoord : TEXCOORD0;\n" + " float4 normal : NORMAL;\n" + " float4 tangent : TANGENT;\n" + " float4 color : COLOR0;\n" + " float4 color2 : COLOR1;\n" + "};\n" + "\n" + "struct VS_OUT {\n" + " float4 position : POSITION;\n" + " float3 texcoord0 : TEXCOORD0;\n" + " float3 texcoord1 : TEXCOORD1;\n" + " float4 color : COLOR0;\n" + "};\n" + "// *INDENT-ON*\n" + "\n" + "void main( VS_IN vertex, out VS_OUT result )\n" + "{\n" + " float4 vNormal = vertex.normal * 2.0 - 1.0;\n" + "\n" + "#if defined( USE_GPU_SKINNING )\n" + "\n" + " //--------------------------------------------------------------\n" + " // GPU transformation of the normal / binormal / bitangent\n" + " //\n" + " // multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )\n" + " //--------------------------------------------------------------\n" + " const float w0 = vertex.color2.x;\n" + " const float w1 = vertex.color2.y;\n" + " const float w2 = vertex.color2.z;\n" + " const float w3 = vertex.color2.w;\n" + "\n" + " float4 matX, matY, matZ; // must be float4 for vec4\n" + " int joint = int( vertex.color.x * 255.1 * 3.0 );\n" + " matX = matrices[int( joint + 0 )] * w0;\n" + " matY = matrices[int( joint + 1 )] * w0;\n" + " matZ = matrices[int( joint + 2 )] * w0;\n" + "\n" + " joint = int( vertex.color.y * 255.1 * 3.0 );\n" + " matX += matrices[int( joint + 0 )] * w1;\n" + " matY += matrices[int( joint + 1 )] * w1;\n" + " matZ += matrices[int( joint + 2 )] * w1;\n" + "\n" + " joint = int( vertex.color.z * 255.1 * 3.0 );\n" + " matX += matrices[int( joint + 0 )] * w2;\n" + " matY += matrices[int( joint + 1 )] * w2;\n" + " matZ += matrices[int( joint + 2 )] * w2;\n" + "\n" + " joint = int( vertex.color.w * 255.1 * 3.0 );\n" + " matX += matrices[int( joint + 0 )] * w3;\n" + " matY += matrices[int( joint + 1 )] * w3;\n" + " matZ += matrices[int( joint + 2 )] * w3;\n" + "\n" + " float3 normal;\n" + " normal.x = dot3( matX, vNormal );\n" + " normal.y = dot3( matY, vNormal );\n" + " normal.z = dot3( matZ, vNormal );\n" + " normal = normalize( normal );\n" + "\n" + " float4 modelPosition;\n" + " modelPosition.x = dot4( matX, vertex.position );\n" + " modelPosition.y = dot4( matY, vertex.position );\n" + " modelPosition.z = dot4( matZ, vertex.position );\n" + " modelPosition.w = 1.0;\n" + "\n" + "#else\n" + "\n" + " float4 modelPosition = vertex.position;\n" + " float4 normal = vNormal;\n" + "\n" + "#endif\n" + "\n" + " result.position.x = dot4( modelPosition, rpMVPmatrixX );\n" + " result.position.y = dot4( modelPosition, rpMVPmatrixY );\n" + " result.position.z = dot4( modelPosition, rpMVPmatrixZ );\n" + " result.position.w = dot4( modelPosition, rpMVPmatrixW );\n" + "\n" + " result.texcoord1.x = dot3( normal, rpModelMatrixX );\n" + " result.texcoord1.y = dot3( normal, rpModelMatrixY );\n" + " result.texcoord1.z = dot3( normal, rpModelMatrixZ );\n" + "\n" + " float4 worldPosition;\n" + " worldPosition.x = dot4( modelPosition, rpModelMatrixX );\n" + " worldPosition.y = dot4( modelPosition, rpModelMatrixY );\n" + " worldPosition.z = dot4( modelPosition, rpModelMatrixZ );\n" + " worldPosition.w = dot4( modelPosition, rpModelMatrixW );\n" + " result.texcoord0 = worldPosition.xyz;\n" + "\n" + " result.color = sRGBAToLinearRGBA( rpColor );\n" + "}\n" + "\n" + + }, + { "renderprogs/builtin/fog/blendLight.ps.hlsl", "/*\n" diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index 019f2bb4..73efde88 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -1937,7 +1937,7 @@ static srfTriangles_t* R_MakeZeroOneSphereTris() verts[ numVerts ].SetTexCoord( s * S, r * R ); verts[ numVerts ].xyz = idVec3( x, y, z ) * radius; - verts[ numVerts ].SetNormal( -x, -y, -z ); + verts[ numVerts ].SetNormal( x, y, z ); verts[ numVerts ].SetColor( 0xffffffff ); numVerts++; diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 2666c221..20eaa655 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -35,6 +35,17 @@ If you have questions concerning this license or the applicable additional terms static const int MAX_LIGHTGRID_ATLAS_SIZE = 4096; static const int MAX_AREA_LIGHTGRID_POINTS = ( MAX_LIGHTGRID_ATLAS_SIZE / LIGHTGRID_IRRADIANCE_SIZE ) * ( MAX_LIGHTGRID_ATLAS_SIZE / LIGHTGRID_IRRADIANCE_SIZE ); +LightGrid::LightGrid() +{ + lightGridSize.Set( 64, 64, 128 ); + //lightGridPoints.Clear(); + + area = -1; + validGridPoints = 0; + + irradianceImage = NULL; +} + void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, const idRenderWorld* world, int _area ) { //idLib::Printf( "----- SetupLightGrid -----\n" ); @@ -86,15 +97,8 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con idStr fullname; - for( int i = 0; i < lightGridPoints.Num(); i++ ) - { - lightGridPoint_t* gridPoint = &lightGridPoints[i]; - - gridPoint->irradianceImage = NULL; - - fullname.Format( "env/%s/area%i_lightgridpoint%i_amb", basename.c_str(), area, i ); - gridPoint->irradianceImage = globalImages->ImageFromFile( fullname, TF_LINEAR, TR_CLAMP, TD_R11G11B10F, CF_2D ); - } + fullname.Format( "env/%s/area%i_lightgrid_amb", basename.c_str(), area ); + irradianceImage = globalImages->ImageFromFile( fullname, TF_NEAREST, TR_CLAMP, TD_R11G11B10F, CF_2D ); #else for( int i = 0; i < lightGridPoints.Num(); i++ ) { diff --git a/neo/renderer/RenderWorld_local.h b/neo/renderer/RenderWorld_local.h index cfe4de05..11bb9e13 100644 --- a/neo/renderer/RenderWorld_local.h +++ b/neo/renderer/RenderWorld_local.h @@ -67,9 +67,6 @@ struct lightGridPoint_t bool valid; // is not in solid area SphericalHarmonicsT SH4; - - // TODO REMOVE just for testing - idImage* irradianceImage; }; class LightGrid @@ -84,7 +81,9 @@ public: idList lightGridPoints; int validGridPoints; - //LightGrid(); + idImage* irradianceImage; + + LightGrid(); // setup light grid for given world bounds void SetupLightGrid( const idBounds& bounds, const char* baseName, const idRenderWorld* world, int _area ); From 0596300c4578a33b3c2c0662b95f56ac3da77116 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Thu, 15 Apr 2021 15:01:31 +0200 Subject: [PATCH 08/26] Combined lightgrid trilerp with IBL PBR lighting --- base/renderprogs/_manifest.lua | 2 + .../lighting/ambient_lightgrid_IBL.ps.hlsl | 414 ++++++++++++ .../lighting/ambient_lightgrid_IBL.vs.hlsl | 200 ++++++ neo/renderer/OpenGL/RenderDebug_GL.cpp | 6 +- neo/renderer/RenderBackend.cpp | 84 ++- neo/renderer/RenderCommon.h | 6 + neo/renderer/RenderProgs.cpp | 12 + neo/renderer/RenderProgs.h | 29 + neo/renderer/RenderProgs_embedded.h | 625 ++++++++++++++++++ neo/renderer/tr_frontend_main.cpp | 22 +- 10 files changed, 1397 insertions(+), 3 deletions(-) create mode 100644 base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl create mode 100644 base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.vs.hlsl diff --git a/base/renderprogs/_manifest.lua b/base/renderprogs/_manifest.lua index 7878a186..6c98de7a 100644 --- a/base/renderprogs/_manifest.lua +++ b/base/renderprogs/_manifest.lua @@ -42,6 +42,8 @@ return "builtin/lighting/ambient_lighting.vs.hlsl", "builtin/lighting/ambient_lighting_IBL.ps.hlsl", "builtin/lighting/ambient_lighting_IBL.vs.hlsl", + "builtin/lighting/ambient_lightgrid_IBL.ps.hlsl", + "builtin/lighting/ambient_lightgrid_IBL.vs.hlsl", "builtin/lighting/interaction.ps.hlsl", "builtin/lighting/interaction.vs.hlsl", "builtin/lighting/interactionAmbient.ps.hlsl", diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl new file mode 100644 index 00000000..38d06221 --- /dev/null +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl @@ -0,0 +1,414 @@ +/* +=========================================================================== + +Doom 3 BFG Edition GPL Source Code +Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. +Copyright (C) 2013-2021 Robert Beckebans + +This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). + +Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 BFG Edition Source Code. If not, see . + +In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ + +#include "renderprogs/global.inc.hlsl" + +#include "renderprogs/BRDF.inc.hlsl" + + +// *INDENT-OFF* +uniform sampler2D samp0 : register(s0); // texture 0 is the per-surface normal map +uniform sampler2D samp1 : register(s1); // texture 1 is the per-surface specular or roughness/metallic/AO mixer map +uniform sampler2D samp2 : register(s2); // texture 2 is the per-surface baseColor map +uniform sampler2D samp3 : register(s3); // texture 3 is the BRDF LUT +uniform sampler2D samp4 : register(s4); // texture 4 is SSAO + +uniform sampler2D samp7 : register(s7); // texture 7 is the irradiance cube map +uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map + +struct PS_IN +{ + half4 position : VPOS; + half4 texcoord0 : TEXCOORD0_centroid; + half4 texcoord1 : TEXCOORD1_centroid; + half4 texcoord2 : TEXCOORD2_centroid; + half4 texcoord3 : TEXCOORD3_centroid; + half4 texcoord4 : TEXCOORD4_centroid; + half4 texcoord5 : TEXCOORD5_centroid; + half4 texcoord6 : TEXCOORD6_centroid; + half4 texcoord7 : TEXCOORD7_centroid; + half4 color : COLOR0; +}; + +struct PS_OUT +{ + half4 color : COLOR; +}; +// *INDENT-ON* + + +float3 lightGridOrigin = float3( -192.0, -128.0, 0 ); +float3 lightGridSize = float3( 64.0, 64.0, 128.0 ); +int3 lightGridBounds = int3( 7, 7, 3 ); + +int3 GetBaseGridCoord( float3 origin ) +{ + int3 pos; + + float3 lightOrigin = origin - lightGridOrigin; + for( int i = 0; i < 3; i++ ) + { + float v; + + v = lightOrigin[i] * ( 1.0f / lightGridSize[i] ); + pos[i] = int( floor( v ) ); + + if( pos[i] < 0 ) + { + pos[i] = 0; + } + else if( pos[i] >= lightGridBounds[i] - 1 ) + { + pos[i] = lightGridBounds[i] - 1; + } + } + + return pos; +} + + +// RB: TODO OPTIMIZE +// this is a straight port of idBounds::RayIntersection +bool AABBRayIntersection( float3 b[2], float3 start, float3 dir, out float scale ) +{ + int i, ax0, ax1, ax2, side, inside; + float f; + float3 hit; + + ax0 = -1; + inside = 0; + for( i = 0; i < 3; i++ ) + { + if( start[i] < b[0][i] ) + { + side = 0; + } + else if( start[i] > b[1][i] ) + { + side = 1; + } + else + { + inside++; + continue; + } + if( dir[i] == 0.0f ) + { + continue; + } + + f = ( start[i] - b[side][i] ); + + if( ax0 < 0 || abs( f ) > abs( scale * dir[i] ) ) + { + scale = - ( f / dir[i] ); + ax0 = i; + } + } + + if( ax0 < 0 ) + { + scale = 0.0f; + + // return true if the start point is inside the bounds + return ( inside == 3 ); + } + + ax1 = ( ax0 + 1 ) % 3; + ax2 = ( ax0 + 2 ) % 3; + hit[ax1] = start[ax1] + scale * dir[ax1]; + hit[ax2] = start[ax2] + scale * dir[ax2]; + + return ( hit[ax1] >= b[0][ax1] && hit[ax1] <= b[1][ax1] && + hit[ax2] >= b[0][ax2] && hit[ax2] <= b[1][ax2] ); +} + +void main( PS_IN fragment, out PS_OUT result ) +{ + half4 bumpMap = tex2D( samp0, fragment.texcoord0.xy ); + half4 YCoCG = tex2D( samp2, fragment.texcoord1.xy ); + half4 specMapSRGB = tex2D( samp1, fragment.texcoord2.xy ); + half4 specMap = sRGBAToLinearRGBA( specMapSRGB ); + + half3 diffuseMap = sRGBToLinearRGB( ConvertYCoCgToRGB( YCoCG ) ); + + half3 localNormal; +#if defined(USE_NORMAL_FMT_RGB8) + localNormal.xy = bumpMap.rg - 0.5; +#else + localNormal.xy = bumpMap.wy - 0.5; +#endif + localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) ); + localNormal = normalize( localNormal ); + + float3 globalNormal; + globalNormal.x = dot3( localNormal, fragment.texcoord4 ); + globalNormal.y = dot3( localNormal, fragment.texcoord5 ); + globalNormal.z = dot3( localNormal, fragment.texcoord6 ); + globalNormal = normalize( globalNormal ); + + float3 globalPosition = fragment.texcoord7.xyz; + + // RB: rpGlobalLightOrigin is global view origin + float3 globalEye = normalize( rpGlobalLightOrigin.xyz - globalPosition ); + + float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal ); + reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalEye ); + +#if 1 + // parallax box correction using portal area bounds + float hitScale; + float3 bounds[2]; + bounds[0].x = rpWobbleSkyX.x; + bounds[0].y = rpWobbleSkyX.y; + bounds[0].z = rpWobbleSkyX.z; + + bounds[1].x = rpWobbleSkyY.x; + bounds[1].y = rpWobbleSkyY.y; + bounds[1].z = rpWobbleSkyY.z; + + // global fragment position + float3 rayStart = fragment.texcoord7.xyz; + + // we can't start inside the box so move this outside and use the reverse path + rayStart += reflectionVector * 10000.0; + + // only do a box <-> ray intersection test if we use a local cubemap + if( ( rpWobbleSkyX.w > 0.0 ) && AABBRayIntersection( bounds, rayStart, -reflectionVector, hitScale ) ) + { + float3 hitPoint = rayStart - reflectionVector * hitScale; + + // rpWobbleSkyZ is cubemap center + reflectionVector = hitPoint - rpWobbleSkyZ.xyz; + } +#endif + + half vDotN = saturate( dot3( globalEye, globalNormal ) ); + +#if defined( USE_PBR ) + const half metallic = specMapSRGB.g; + const half roughness = specMapSRGB.r; + const half glossiness = 1.0 - roughness; + + // the vast majority of real-world materials (anything not metal or gems) have F(0°) + // values in a very narrow range (~0.02 - 0.08) + + // approximate non-metals with linear RGB 0.04 which is 0.08 * 0.5 (default in UE4) + const half3 dielectricColor = half3( 0.04 ); + + // derive diffuse and specular from albedo(m) base color + const half3 baseColor = diffuseMap; + + half3 diffuseColor = baseColor * ( 1.0 - metallic ); + half3 specularColor = lerp( dielectricColor, baseColor, metallic ); + +#if defined( DEBUG_PBR ) + diffuseColor = half3( 0.0, 0.0, 0.0 ); + specularColor = half3( 0.0, 1.0, 0.0 ); +#endif + + float3 kS = Fresnel_SchlickRoughness( specularColor, vDotN, roughness ); + float3 kD = ( float3( 1.0, 1.0, 1.0 ) - kS ) * ( 1.0 - metallic ); + +#else + const float roughness = EstimateLegacyRoughness( specMapSRGB.rgb ); + + half3 diffuseColor = diffuseMap; + half3 specularColor = specMap.rgb; + +#if defined( DEBUG_PBR ) + diffuseColor = half3( 0.0, 0.0, 0.0 ); + specularColor = half3( 1.0, 0.0, 0.0 ); +#endif + + float3 kS = Fresnel_SchlickRoughness( specularColor, vDotN, roughness ); + + // NOTE: metalness is missing + float3 kD = ( float3( 1.0, 1.0, 1.0 ) - kS ); + +#endif + + //diffuseColor = half3( 1.0, 1.0, 1.0 ); + //diffuseColor = half3( 0.0, 0.0, 0.0 ); + + // calculate the screen texcoord in the 0.0 to 1.0 range + //float2 screenTexCoord = vposToScreenPosTexCoord( fragment.position.xy ); + float2 screenTexCoord = fragment.position.xy * rpWindowCoord.xy; + + float ao = 1.0; + ao = tex2D( samp4, screenTexCoord ).r; + //diffuseColor.rgb *= ao; + + // evaluate diffuse IBL + + float2 normalizedOctCoord = octEncode( globalNormal ); + float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5; + +// lightgrid atlas + float invXY = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[1] ) ); + float invZ = ( 1.0 / lightGridBounds[2] ); + + normalizedOctCoordZeroOne.x *= invXY; + normalizedOctCoordZeroOne.y *= invZ; + + int3 gridCoord; + float3 frac; + float3 lightOrigin = globalPosition - lightGridOrigin; + + for( int i = 0; i < 3; i++ ) + { + float v; + + v = lightOrigin[i] * ( 1.0f / lightGridSize[i] ); + gridCoord[i] = int( floor( v ) ); + frac[ i ] = v - gridCoord[ i ]; + + if( gridCoord[i] < 0 ) + { + gridCoord[i] = 0; + } + else if( gridCoord[i] >= lightGridBounds[i] - 1 ) + { + gridCoord[i] = lightGridBounds[i] - 1; + } + } + + // trilerp the light value + int3 gridStep; + + gridStep[0] = 1; + gridStep[1] = lightGridBounds[0]; + gridStep[2] = lightGridBounds[0] * lightGridBounds[1]; + + float totalFactor = 0.0; + float3 irradiance; + + /* + for( int i = 0; i < 8; i++ ) + { + for( int j = 0; j < 3; j++ ) + { + if( i & ( 1 << j ) ) + + results in these offsets + */ + const float3 cornerOffsets[8] = float3[]( + float3( 0.0, 0.0, 0.0 ), + float3( 1.0, 0.0, 0.0 ), + float3( 0.0, 2.0, 0.0 ), + float3( 1.0, 2.0, 0.0 ), + float3( 0.0, 0.0, 4.0 ), + float3( 1.0, 0.0, 4.0 ), + float3( 0.0, 2.0, 4.0 ), + float3( 1.0, 2.0, 4.0 ) ); + + for( int i = 0; i < 8; i++ ) + { + float factor = 1.0; + + int3 gridCoord2 = gridCoord; + + for( int j = 0; j < 3; j++ ) + { + if( cornerOffsets[ i ][ j ] > 0.0f ) + { + factor *= frac[ j ]; + + gridCoord2[ j ] += 1; + } + else + { + factor *= ( 1.0f - frac[ j ] ); + } + } + + float2 atlasOffset; + + atlasOffset.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[1] * gridStep[1] ) * invXY; + atlasOffset.y = ( gridCoord2[2] * invZ ); + + irradiance += tex2D( samp7, normalizedOctCoordZeroOne + atlasOffset ).rgb * factor; + + totalFactor += factor; + } + + if( totalFactor > 0 && totalFactor < 0.99 ) + { + totalFactor = 1.0f / totalFactor; + + irradiance *= totalFactor; + } + +// lightgrid atlas + + + float3 diffuseLight = ( kD * irradiance * diffuseColor ) * ao * ( rpDiffuseModifier.xyz * 1.0 ); + + // evaluate specular IBL + + // should be 8 = numMips - 1, 256^2 = 9 mips + const float MAX_REFLECTION_LOD = 10.0; + float mip = clamp( ( roughness * MAX_REFLECTION_LOD ), 0.0, MAX_REFLECTION_LOD ); + //float mip = 0.0; + + normalizedOctCoord = octEncode( reflectionVector ); + normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5; + + float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb; + //radiance = float3( 0.0 ); + + float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg; + +#if 0 + result.color.rgb = float3( envBRDF.x, envBRDF.y, 0.0 ); + result.color.w = fragment.color.a; + return; +#endif + + float specAO = ComputeSpecularAO( vDotN, ao, roughness ); + float3 specularLight = radiance * ( kS * envBRDF.x + float3( envBRDF.y ) ) * specAO * ( rpSpecularModifier.xyz * 0.5 ); + +#if 0 + // Marmoset Horizon Fade trick + const half horizonFade = 1.3; + half horiz = saturate( 1.0 + horizonFade * saturate( dot3( reflectionVector, globalNormal ) ) ); + horiz *= horiz; + //horiz = clamp( horiz, 0.0, 1.0 ); +#endif + + half3 lightColor = sRGBToLinearRGB( rpAmbientColor.rgb ); + + //result.color.rgb = diffuseLight; + //result.color.rgb = diffuseLight * lightColor; + //result.color.rgb = specularLight; + result.color.rgb = ( diffuseLight + specularLight ) * lightColor * fragment.color.rgb; + //result.color.rgb = localNormal.xyz * 0.5 + 0.5; + //result.color.rgb = float3( ao ); + result.color.w = fragment.color.a; +} diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.vs.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.vs.hlsl new file mode 100644 index 00000000..35bd0b7b --- /dev/null +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.vs.hlsl @@ -0,0 +1,200 @@ +/* +=========================================================================== + +Doom 3 BFG Edition GPL Source Code +Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. +Copyright (C) 2013-2015 Robert Beckebans + +This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). + +Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Doom 3 BFG Edition Source Code. If not, see . + +In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. + +If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. + +=========================================================================== +*/ + +#include "renderprogs/global.inc.hlsl" + + +#if defined( USE_GPU_SKINNING ) +uniform matrices_ubo { float4 matrices[408]; }; +#endif + +// *INDENT-OFF* +struct VS_IN { + float4 position : POSITION; + float2 texcoord : TEXCOORD0; + float4 normal : NORMAL; + float4 tangent : TANGENT; + float4 color : COLOR0; + float4 color2 : COLOR1; +}; + +struct VS_OUT { + float4 position : POSITION; + float4 texcoord0 : TEXCOORD0; + float4 texcoord1 : TEXCOORD1; + float4 texcoord2 : TEXCOORD2; + float4 texcoord3 : TEXCOORD3; + float4 texcoord4 : TEXCOORD4; + float4 texcoord5 : TEXCOORD5; + float4 texcoord6 : TEXCOORD6; + float4 texcoord7 : TEXCOORD7; + float4 color : COLOR0; +}; +// *INDENT-ON* + +void main( VS_IN vertex, out VS_OUT result ) +{ + + float4 vNormal = vertex.normal * 2.0 - 1.0; + float4 vTangent = vertex.tangent * 2.0 - 1.0; + float3 vBitangent = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w; + +#if defined( USE_GPU_SKINNING ) + //-------------------------------------------------------------- + // GPU transformation of the normal / tangent / bitangent + // + // multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 ) + //-------------------------------------------------------------- + const float w0 = vertex.color2.x; + const float w1 = vertex.color2.y; + const float w2 = vertex.color2.z; + const float w3 = vertex.color2.w; + + float4 matX, matY, matZ; // must be float4 for vec4 + int joint = int( vertex.color.x * 255.1 * 3.0 ); + matX = matrices[int( joint + 0 )] * w0; + matY = matrices[int( joint + 1 )] * w0; + matZ = matrices[int( joint + 2 )] * w0; + + joint = int( vertex.color.y * 255.1 * 3.0 ); + matX += matrices[int( joint + 0 )] * w1; + matY += matrices[int( joint + 1 )] * w1; + matZ += matrices[int( joint + 2 )] * w1; + + joint = int( vertex.color.z * 255.1 * 3.0 ); + matX += matrices[int( joint + 0 )] * w2; + matY += matrices[int( joint + 1 )] * w2; + matZ += matrices[int( joint + 2 )] * w2; + + joint = int( vertex.color.w * 255.1 * 3.0 ); + matX += matrices[int( joint + 0 )] * w3; + matY += matrices[int( joint + 1 )] * w3; + matZ += matrices[int( joint + 2 )] * w3; + + float3 normal; + normal.x = dot3( matX, vNormal ); + normal.y = dot3( matY, vNormal ); + normal.z = dot3( matZ, vNormal ); + normal = normalize( normal ); + + float3 tangent; + tangent.x = dot3( matX, vTangent ); + tangent.y = dot3( matY, vTangent ); + tangent.z = dot3( matZ, vTangent ); + tangent = normalize( tangent ); + + float3 bitangent; + bitangent.x = dot3( matX, vBitangent ); + bitangent.y = dot3( matY, vBitangent ); + bitangent.z = dot3( matZ, vBitangent ); + bitangent = normalize( bitangent ); + + float4 modelPosition; + modelPosition.x = dot4( matX, vertex.position ); + modelPosition.y = dot4( matY, vertex.position ); + modelPosition.z = dot4( matZ, vertex.position ); + modelPosition.w = 1.0; + +#else + float4 modelPosition = vertex.position; + float3 normal = vNormal.xyz; + float3 tangent = vTangent.xyz; + float3 bitangent = vBitangent.xyz; +#endif + + result.position.x = dot4( modelPosition, rpMVPmatrixX ); + result.position.y = dot4( modelPosition, rpMVPmatrixY ); + result.position.z = dot4( modelPosition, rpMVPmatrixZ ); + result.position.w = dot4( modelPosition, rpMVPmatrixW ); + + float4 defaultTexCoord = float4( 0.0f, 0.5f, 0.0f, 1.0f ); + + //calculate vector to light + //float4 toLight = rpLocalLightOrigin; + float4 toLight = normalize( float4( 0.0f, 0.5f, 1.0f, 1.0f ) ); + + //-------------------------------------------------------------- + + + //# textures 0 takes the base coordinates by the texture matrix + result.texcoord0 = defaultTexCoord; + result.texcoord0.x = dot4( vertex.texcoord.xy, rpBumpMatrixS ); + result.texcoord0.y = dot4( vertex.texcoord.xy, rpBumpMatrixT ); + + //# textures 1 takes the base coordinates by the texture matrix + result.texcoord1 = defaultTexCoord; + result.texcoord1.x = dot4( vertex.texcoord.xy, rpDiffuseMatrixS ); + result.texcoord1.y = dot4( vertex.texcoord.xy, rpDiffuseMatrixT ); + + //# textures 2 takes the base coordinates by the texture matrix + result.texcoord2 = defaultTexCoord; + result.texcoord2.x = dot4( vertex.texcoord.xy, rpSpecularMatrixS ); + result.texcoord2.y = dot4( vertex.texcoord.xy, rpSpecularMatrixT ); + + //# calculate normalized vector to viewer in R1 + //result.texcoord3 = modelPosition; + + float4 toEye = normalize( rpLocalViewOrigin - modelPosition ); + + result.texcoord3.x = dot3( toEye, rpModelMatrixX ); + result.texcoord3.y = dot3( toEye, rpModelMatrixY ); + result.texcoord3.z = dot3( toEye, rpModelMatrixZ ); + + result.texcoord4.x = dot3( tangent, rpModelMatrixX ); + result.texcoord5.x = dot3( tangent, rpModelMatrixY ); + result.texcoord6.x = dot3( tangent, rpModelMatrixZ ); + + result.texcoord4.y = dot3( bitangent, rpModelMatrixX ); + result.texcoord5.y = dot3( bitangent, rpModelMatrixY ); + result.texcoord6.y = dot3( bitangent, rpModelMatrixZ ); + + result.texcoord4.z = dot3( normal, rpModelMatrixX ); + result.texcoord5.z = dot3( normal, rpModelMatrixY ); + result.texcoord6.z = dot3( normal, rpModelMatrixZ ); + + float4 worldPosition; + worldPosition.x = dot4( modelPosition, rpModelMatrixX ); + worldPosition.y = dot4( modelPosition, rpModelMatrixY ); + worldPosition.z = dot4( modelPosition, rpModelMatrixZ ); + worldPosition.w = dot4( modelPosition, rpModelMatrixW ); + result.texcoord7 = worldPosition; + +#if defined( USE_GPU_SKINNING ) + // for joint transformation of the tangent space, we use color and + // color2 for weighting information, so hopefully there aren't any + // effects that need vertex color... + result.color = float4( 1.0f, 1.0f, 1.0f, 1.0f ); +#else + //# generate the vertex color, which can be 1.0, color, or 1.0 - color + //# for 1.0 : env[16] = 0, env[17] = 1 + //# for color : env[16] = 1, env[17] = 0 + //# for 1.0-color : env[16] = -1, env[17] = 1 + result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd; +#endif +} \ No newline at end of file diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index f8684580..2a88cc0a 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1972,6 +1972,8 @@ void idRenderBackend::DBG_ShowLightGrid() gridPoint = &area->lightGrid.lightGridPoints[ gridPointIndex ]; totalFactor = 0; + idVec3 cornerOffsets[8]; + for( int i = 0; i < 8; i++ ) { float factor = 1.0; @@ -1981,7 +1983,9 @@ void idRenderBackend::DBG_ShowLightGrid() for( int j = 0; j < 3; j++ ) { - if( i & ( 1 << j ) ) + cornerOffsets[i][j] = i & ( 1 << j ); + + if( cornerOffsets[i][j] > 0.0f ) { factor *= frac[j]; diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 96f1f59b..f4af42dc 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -1323,7 +1323,89 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas const textureUsage_t specUsage = din->specularImage->GetUsage(); // RB begin - if( useIBL ) + if( useIBL && viewDef->useLightGrid ) + { + idVec4 probeMins, probeMaxs, probeCenter; + + probeMins[0] = viewDef->globalProbeBounds[0][0]; + probeMins[1] = viewDef->globalProbeBounds[0][1]; + probeMins[2] = viewDef->globalProbeBounds[0][2]; + probeMins[3] = viewDef->globalProbeBounds.IsCleared() ? 0.0f : 1.0f; + + probeMaxs[0] = viewDef->globalProbeBounds[1][0]; + probeMaxs[1] = viewDef->globalProbeBounds[1][1]; + probeMaxs[2] = viewDef->globalProbeBounds[1][2]; + probeMaxs[3] = 0.0f; + + idVec3 center = viewDef->globalProbeBounds.GetCenter(); + probeCenter.Set( center.x, center.y, center.z, 1.0f ); + + SetVertexParm( RENDERPARM_WOBBLESKY_X, probeMins.ToFloatPtr() ); + SetVertexParm( RENDERPARM_WOBBLESKY_Y, probeMaxs.ToFloatPtr() ); + SetVertexParm( RENDERPARM_WOBBLESKY_Z, probeCenter.ToFloatPtr() ); + + if( specUsage == TD_SPECULAR_PBR_RMAO || specUsage == TD_SPECULAR_PBR_RMAOD ) + { + // PBR path with roughness, metal and AO + if( din->surf->jointCache ) + { + renderProgManager.BindShader_ImageBasedLightGridSkinned_PBR(); + } + else + { + renderProgManager.BindShader_ImageBasedLightGrid_PBR(); + } + } + else + { + if( din->surf->jointCache ) + { + renderProgManager.BindShader_ImageBasedLightGridSkinned(); + } + else + { + renderProgManager.BindShader_ImageBasedLightGrid(); + } + } + + GL_SelectTexture( INTERACTION_TEXUNIT_FALLOFF ); + globalImages->brdfLutImage->Bind(); + + GL_SelectTexture( INTERACTION_TEXUNIT_PROJECTION ); +#if defined( USE_VULKAN ) + globalImages->whiteImage->Bind(); +#else + if( !r_useSSAO.GetBool() ) + { + globalImages->whiteImage->Bind(); + } + else + { + globalImages->ambientOcclusionImage[0]->Bind(); + } +#endif + + GL_SelectTexture( INTERACTION_TEXUNIT_AMBIENT_CUBE1 ); + if( viewDef->irradianceImage ) + { + viewDef->irradianceImage->Bind(); + } + else + { + globalImages->defaultUACIrradianceCube->Bind(); + } + + GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE1 ); + if( viewDef->radianceImage ) + { + viewDef->radianceImage->Bind(); + } + else + { + globalImages->defaultUACRadianceCube->Bind(); + } + } + else if( useIBL ) { idVec4 probeMins, probeMaxs, probeCenter; diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index 9e45b250..17910cbe 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -636,6 +636,12 @@ struct viewDef_t idRenderMatrix inverseBaseEnvProbeProject; // the matrix for deforming the 'zeroOneCubeModel' to exactly cover the environent probe volume in world space idImage* irradianceImage; // cubemap image used for diffuse IBL by backend idImage* radianceImage; // cubemap image used for specular IBL by backend + + // lightGrid + bool useLightGrid; + idVec3 lightGridOrigin; + idVec3 lightGridSize; + int lightGridBounds[3]; // RB end }; diff --git a/neo/renderer/RenderProgs.cpp b/neo/renderer/RenderProgs.cpp index cfb9c982..329df96f 100644 --- a/neo/renderer/RenderProgs.cpp +++ b/neo/renderer/RenderProgs.cpp @@ -109,10 +109,17 @@ void idRenderProgManager::Init() { BUILTIN_VERTEX_COLOR, "builtin/vertex_color", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, { BUILTIN_AMBIENT_LIGHTING, "builtin/lighting/ambient_lighting", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, { BUILTIN_AMBIENT_LIGHTING_SKINNED, "builtin/lighting/ambient_lighting", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, + { BUILTIN_AMBIENT_LIGHTING_IBL, "builtin/lighting/ambient_lighting_IBL", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, { BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED, "builtin/lighting/ambient_lighting_IBL", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, { BUILTIN_AMBIENT_LIGHTING_IBL_PBR, "builtin/lighting/ambient_lighting_IBL", "_PBR", BIT( USE_PBR ), false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, { BUILTIN_AMBIENT_LIGHTING_IBL_PBR_SKINNED, "builtin/lighting/ambient_lighting_IBL", "_PBR_skinned", BIT( USE_GPU_SKINNING | USE_PBR ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, + + { BUILTIN_AMBIENT_LIGHTGRID_IBL, "builtin/lighting/ambient_lightgrid_IBL", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, + { BUILTIN_AMBIENT_LIGHTGRID_IBL_SKINNED, "builtin/lighting/ambient_lightgrid_IBL", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, + { BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR, "builtin/lighting/ambient_lightgrid_IBL", "_PBR", BIT( USE_PBR ), false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, + { BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR_SKINNED, "builtin/lighting/ambient_lightgrid_IBL", "_PBR_skinned", BIT( USE_GPU_SKINNING | USE_PBR ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, + { BUILTIN_SMALL_GEOMETRY_BUFFER, "builtin/gbuffer", "", 0, false, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, { BUILTIN_SMALL_GEOMETRY_BUFFER_SKINNED, "builtin/gbuffer", "_skinned", BIT( USE_GPU_SKINNING ), true, SHADER_STAGE_DEFAULT, LAYOUT_DRAW_VERT }, // RB end @@ -279,8 +286,13 @@ void idRenderProgManager::Init() renderProgs[builtinShaders[BUILTIN_DEBUG_LIGHTGRID_SKINNED]].usesJoints = true; renderProgs[builtinShaders[BUILTIN_DEBUG_OCTAHEDRON_SKINNED]].usesJoints = true; renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTING_SKINNED]].usesJoints = true; + renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED]].usesJoints = true; renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTING_IBL_PBR_SKINNED]].usesJoints = true; + + renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTGRID_IBL_SKINNED]].usesJoints = true; + renderProgs[builtinShaders[BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR_SKINNED]].usesJoints = true; + renderProgs[builtinShaders[BUILTIN_SMALL_GEOMETRY_BUFFER_SKINNED]].usesJoints = true; renderProgs[builtinShaders[BUILTIN_INTERACTION_SHADOW_MAPPING_SPOT_SKINNED]].usesJoints = true; renderProgs[builtinShaders[BUILTIN_INTERACTION_SHADOW_MAPPING_POINT_SKINNED]].usesJoints = true; diff --git a/neo/renderer/RenderProgs.h b/neo/renderer/RenderProgs.h index 76114f8b..59f97fed 100644 --- a/neo/renderer/RenderProgs.h +++ b/neo/renderer/RenderProgs.h @@ -311,6 +311,28 @@ public: BindShader_Builtin( BUILTIN_AMBIENT_LIGHTING_IBL_PBR_SKINNED ); } + + void BindShader_ImageBasedLightGrid() + { + BindShader_Builtin( BUILTIN_AMBIENT_LIGHTGRID_IBL ); + } + + void BindShader_ImageBasedLightGridSkinned() + { + BindShader_Builtin( BUILTIN_AMBIENT_LIGHTGRID_IBL_SKINNED ); + } + + void BindShader_ImageBasedLightGrid_PBR() + { + BindShader_Builtin( BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR ); + } + + void BindShader_ImageBasedLightGridSkinned_PBR() + { + BindShader_Builtin( BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR_SKINNED ); + } + + void BindShader_SmallGeometryBuffer() { BindShader_Builtin( BUILTIN_SMALL_GEOMETRY_BUFFER ); @@ -741,10 +763,17 @@ private: BUILTIN_VERTEX_COLOR, BUILTIN_AMBIENT_LIGHTING, BUILTIN_AMBIENT_LIGHTING_SKINNED, + BUILTIN_AMBIENT_LIGHTING_IBL, BUILTIN_AMBIENT_LIGHTING_IBL_SKINNED, BUILTIN_AMBIENT_LIGHTING_IBL_PBR, BUILTIN_AMBIENT_LIGHTING_IBL_PBR_SKINNED, + + BUILTIN_AMBIENT_LIGHTGRID_IBL, + BUILTIN_AMBIENT_LIGHTGRID_IBL_SKINNED, + BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR, + BUILTIN_AMBIENT_LIGHTGRID_IBL_PBR_SKINNED, + BUILTIN_SMALL_GEOMETRY_BUFFER, BUILTIN_SMALL_GEOMETRY_BUFFER_SKINNED, // RB end diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index 2d797e87..644bdc9c 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -5229,6 +5229,631 @@ static const cgShaderDef_t cg_renderprogs[] = }, + { + "renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl", + "/*\n" + "===========================================================================\n" + "\n" + "Doom 3 BFG Edition GPL Source Code\n" + "Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.\n" + "Copyright (C) 2013-2021 Robert Beckebans\n" + "\n" + "This file is part of the Doom 3 BFG Edition GPL Source Code (\"Doom 3 BFG Edition Source Code\").\n" + "\n" + "Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation, either version 3 of the License, or\n" + "(at your option) any later version.\n" + "\n" + "Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License\n" + "along with Doom 3 BFG Edition Source Code. If not, see .\n" + "\n" + "In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.\n" + "\n" + "If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.\n" + "\n" + "===========================================================================\n" + "*/\n" + "\n" + "#include \"renderprogs/global.inc.hlsl\"\n" + "\n" + "#include \"renderprogs/BRDF.inc.hlsl\"\n" + "\n" + "\n" + "// *INDENT-OFF*\n" + "uniform sampler2D samp0 : register(s0); // texture 0 is the per-surface normal map\n" + "uniform sampler2D samp1 : register(s1); // texture 1 is the per-surface specular or roughness/metallic/AO mixer map\n" + "uniform sampler2D samp2 : register(s2); // texture 2 is the per-surface baseColor map \n" + "uniform sampler2D samp3 : register(s3); // texture 3 is the BRDF LUT\n" + "uniform sampler2D samp4 : register(s4); // texture 4 is SSAO\n" + "\n" + "uniform sampler2D samp7 : register(s7); // texture 7 is the irradiance cube map\n" + "uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map\n" + "\n" + "struct PS_IN \n" + "{\n" + " half4 position : VPOS;\n" + " half4 texcoord0 : TEXCOORD0_centroid;\n" + " half4 texcoord1 : TEXCOORD1_centroid;\n" + " half4 texcoord2 : TEXCOORD2_centroid;\n" + " half4 texcoord3 : TEXCOORD3_centroid;\n" + " half4 texcoord4 : TEXCOORD4_centroid;\n" + " half4 texcoord5 : TEXCOORD5_centroid;\n" + " half4 texcoord6 : TEXCOORD6_centroid;\n" + " half4 texcoord7 : TEXCOORD7_centroid;\n" + " half4 color : COLOR0;\n" + "};\n" + "\n" + "struct PS_OUT\n" + "{\n" + " half4 color : COLOR;\n" + "};\n" + "// *INDENT-ON*\n" + "\n" + "\n" + "float3 lightGridOrigin = float3( -192.0, -128.0, 0 );\n" + "float3 lightGridSize = float3( 64.0, 64.0, 128.0 );\n" + "int3 lightGridBounds = int3( 7, 7, 3 );\n" + "\n" + "int3 GetBaseGridCoord( float3 origin )\n" + "{\n" + " int3 pos;\n" + "\n" + " float3 lightOrigin = origin - lightGridOrigin;\n" + " for( int i = 0; i < 3; i++ )\n" + " {\n" + " float v;\n" + "\n" + " v = lightOrigin[i] * ( 1.0f / lightGridSize[i] );\n" + " pos[i] = int( floor( v ) );\n" + "\n" + " if( pos[i] < 0 )\n" + " {\n" + " pos[i] = 0;\n" + " }\n" + " else if( pos[i] >= lightGridBounds[i] - 1 )\n" + " {\n" + " pos[i] = lightGridBounds[i] - 1;\n" + " }\n" + " }\n" + "\n" + " return pos;\n" + "}\n" + "\n" + "\n" + "// RB: TODO OPTIMIZE\n" + "// this is a straight port of idBounds::RayIntersection\n" + "bool AABBRayIntersection( float3 b[2], float3 start, float3 dir, out float scale )\n" + "{\n" + " int i, ax0, ax1, ax2, side, inside;\n" + " float f;\n" + " float3 hit;\n" + "\n" + " ax0 = -1;\n" + " inside = 0;\n" + " for( i = 0; i < 3; i++ )\n" + " {\n" + " if( start[i] < b[0][i] )\n" + " {\n" + " side = 0;\n" + " }\n" + " else if( start[i] > b[1][i] )\n" + " {\n" + " side = 1;\n" + " }\n" + " else\n" + " {\n" + " inside++;\n" + " continue;\n" + " }\n" + " if( dir[i] == 0.0f )\n" + " {\n" + " continue;\n" + " }\n" + "\n" + " f = ( start[i] - b[side][i] );\n" + "\n" + " if( ax0 < 0 || abs( f ) > abs( scale * dir[i] ) )\n" + " {\n" + " scale = - ( f / dir[i] );\n" + " ax0 = i;\n" + " }\n" + " }\n" + "\n" + " if( ax0 < 0 )\n" + " {\n" + " scale = 0.0f;\n" + "\n" + " // return true if the start point is inside the bounds\n" + " return ( inside == 3 );\n" + " }\n" + "\n" + " ax1 = ( ax0 + 1 ) % 3;\n" + " ax2 = ( ax0 + 2 ) % 3;\n" + " hit[ax1] = start[ax1] + scale * dir[ax1];\n" + " hit[ax2] = start[ax2] + scale * dir[ax2];\n" + "\n" + " return ( hit[ax1] >= b[0][ax1] && hit[ax1] <= b[1][ax1] &&\n" + " hit[ax2] >= b[0][ax2] && hit[ax2] <= b[1][ax2] );\n" + "}\n" + "\n" + "void main( PS_IN fragment, out PS_OUT result )\n" + "{\n" + " half4 bumpMap = tex2D( samp0, fragment.texcoord0.xy );\n" + " half4 YCoCG = tex2D( samp2, fragment.texcoord1.xy );\n" + " half4 specMapSRGB = tex2D( samp1, fragment.texcoord2.xy );\n" + " half4 specMap = sRGBAToLinearRGBA( specMapSRGB );\n" + "\n" + " half3 diffuseMap = sRGBToLinearRGB( ConvertYCoCgToRGB( YCoCG ) );\n" + "\n" + " half3 localNormal;\n" + "#if defined(USE_NORMAL_FMT_RGB8)\n" + " localNormal.xy = bumpMap.rg - 0.5;\n" + "#else\n" + " localNormal.xy = bumpMap.wy - 0.5;\n" + "#endif\n" + " localNormal.z = sqrt( abs( dot( localNormal.xy, localNormal.xy ) - 0.25 ) );\n" + " localNormal = normalize( localNormal );\n" + "\n" + " float3 globalNormal;\n" + " globalNormal.x = dot3( localNormal, fragment.texcoord4 );\n" + " globalNormal.y = dot3( localNormal, fragment.texcoord5 );\n" + " globalNormal.z = dot3( localNormal, fragment.texcoord6 );\n" + " globalNormal = normalize( globalNormal );\n" + "\n" + " float3 globalPosition = fragment.texcoord7.xyz;\n" + "\n" + " // RB: rpGlobalLightOrigin is global view origin\n" + " float3 globalEye = normalize( rpGlobalLightOrigin.xyz - globalPosition );\n" + "\n" + " float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal );\n" + " reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalEye );\n" + "\n" + "#if 1\n" + " // parallax box correction using portal area bounds\n" + " float hitScale;\n" + " float3 bounds[2];\n" + " bounds[0].x = rpWobbleSkyX.x;\n" + " bounds[0].y = rpWobbleSkyX.y;\n" + " bounds[0].z = rpWobbleSkyX.z;\n" + "\n" + " bounds[1].x = rpWobbleSkyY.x;\n" + " bounds[1].y = rpWobbleSkyY.y;\n" + " bounds[1].z = rpWobbleSkyY.z;\n" + "\n" + " // global fragment position\n" + " float3 rayStart = fragment.texcoord7.xyz;\n" + "\n" + " // we can't start inside the box so move this outside and use the reverse path\n" + " rayStart += reflectionVector * 10000.0;\n" + "\n" + " // only do a box <-> ray intersection test if we use a local cubemap\n" + " if( ( rpWobbleSkyX.w > 0.0 ) && AABBRayIntersection( bounds, rayStart, -reflectionVector, hitScale ) )\n" + " {\n" + " float3 hitPoint = rayStart - reflectionVector * hitScale;\n" + "\n" + " // rpWobbleSkyZ is cubemap center\n" + " reflectionVector = hitPoint - rpWobbleSkyZ.xyz;\n" + " }\n" + "#endif\n" + "\n" + " half vDotN = saturate( dot3( globalEye, globalNormal ) );\n" + "\n" + "#if defined( USE_PBR )\n" + " const half metallic = specMapSRGB.g;\n" + " const half roughness = specMapSRGB.r;\n" + " const half glossiness = 1.0 - roughness;\n" + "\n" + " // the vast majority of real-world materials (anything not metal or gems) have F(0°)\n" + " // values in a very narrow range (~0.02 - 0.08)\n" + "\n" + " // approximate non-metals with linear RGB 0.04 which is 0.08 * 0.5 (default in UE4)\n" + " const half3 dielectricColor = half3( 0.04 );\n" + "\n" + " // derive diffuse and specular from albedo(m) base color\n" + " const half3 baseColor = diffuseMap;\n" + "\n" + " half3 diffuseColor = baseColor * ( 1.0 - metallic );\n" + " half3 specularColor = lerp( dielectricColor, baseColor, metallic );\n" + "\n" + "#if defined( DEBUG_PBR )\n" + " diffuseColor = half3( 0.0, 0.0, 0.0 );\n" + " specularColor = half3( 0.0, 1.0, 0.0 );\n" + "#endif\n" + "\n" + " float3 kS = Fresnel_SchlickRoughness( specularColor, vDotN, roughness );\n" + " float3 kD = ( float3( 1.0, 1.0, 1.0 ) - kS ) * ( 1.0 - metallic );\n" + "\n" + "#else\n" + " const float roughness = EstimateLegacyRoughness( specMapSRGB.rgb );\n" + "\n" + " half3 diffuseColor = diffuseMap;\n" + " half3 specularColor = specMap.rgb;\n" + "\n" + "#if defined( DEBUG_PBR )\n" + " diffuseColor = half3( 0.0, 0.0, 0.0 );\n" + " specularColor = half3( 1.0, 0.0, 0.0 );\n" + "#endif\n" + "\n" + " float3 kS = Fresnel_SchlickRoughness( specularColor, vDotN, roughness );\n" + "\n" + " // NOTE: metalness is missing\n" + " float3 kD = ( float3( 1.0, 1.0, 1.0 ) - kS );\n" + "\n" + "#endif\n" + "\n" + " //diffuseColor = half3( 1.0, 1.0, 1.0 );\n" + " //diffuseColor = half3( 0.0, 0.0, 0.0 );\n" + "\n" + " // calculate the screen texcoord in the 0.0 to 1.0 range\n" + " //float2 screenTexCoord = vposToScreenPosTexCoord( fragment.position.xy );\n" + " float2 screenTexCoord = fragment.position.xy * rpWindowCoord.xy;\n" + "\n" + " float ao = 1.0;\n" + " ao = tex2D( samp4, screenTexCoord ).r;\n" + " //diffuseColor.rgb *= ao;\n" + "\n" + " // evaluate diffuse IBL\n" + "\n" + " float2 normalizedOctCoord = octEncode( globalNormal );\n" + " float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n" + "\n" + "// lightgrid atlas\n" + " float invXY = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[1] ) );\n" + " float invZ = ( 1.0 / lightGridBounds[2] );\n" + "\n" + " normalizedOctCoordZeroOne.x *= invXY;\n" + " normalizedOctCoordZeroOne.y *= invZ;\n" + "\n" + " int3 gridCoord;\n" + " float3 frac;\n" + " float3 lightOrigin = globalPosition - lightGridOrigin;\n" + "\n" + " for( int i = 0; i < 3; i++ )\n" + " {\n" + " float v;\n" + "\n" + " v = lightOrigin[i] * ( 1.0f / lightGridSize[i] );\n" + " gridCoord[i] = int( floor( v ) );\n" + " frac[ i ] = v - gridCoord[ i ];\n" + "\n" + " if( gridCoord[i] < 0 )\n" + " {\n" + " gridCoord[i] = 0;\n" + " }\n" + " else if( gridCoord[i] >= lightGridBounds[i] - 1 )\n" + " {\n" + " gridCoord[i] = lightGridBounds[i] - 1;\n" + " }\n" + " }\n" + "\n" + " // trilerp the light value\n" + " int3 gridStep;\n" + "\n" + " gridStep[0] = 1;\n" + " gridStep[1] = lightGridBounds[0];\n" + " gridStep[2] = lightGridBounds[0] * lightGridBounds[1];\n" + "\n" + " float totalFactor = 0.0;\n" + " float3 irradiance;\n" + "\n" + " /*\n" + " for( int i = 0; i < 8; i++ )\n" + " {\n" + " for( int j = 0; j < 3; j++ )\n" + " {\n" + " if( i & ( 1 << j ) )\n" + "\n" + " results in these offsets\n" + " */\n" + " const float3 cornerOffsets[8] = float3[](\n" + " float3( 0.0, 0.0, 0.0 ),\n" + " float3( 1.0, 0.0, 0.0 ),\n" + " float3( 0.0, 2.0, 0.0 ),\n" + " float3( 1.0, 2.0, 0.0 ),\n" + " float3( 0.0, 0.0, 4.0 ),\n" + " float3( 1.0, 0.0, 4.0 ),\n" + " float3( 0.0, 2.0, 4.0 ),\n" + " float3( 1.0, 2.0, 4.0 ) );\n" + "\n" + " for( int i = 0; i < 8; i++ )\n" + " {\n" + " float factor = 1.0;\n" + "\n" + " int3 gridCoord2 = gridCoord;\n" + "\n" + " for( int j = 0; j < 3; j++ )\n" + " {\n" + " if( cornerOffsets[ i ][ j ] > 0.0f )\n" + " {\n" + " factor *= frac[ j ];\n" + "\n" + " gridCoord2[ j ] += 1;\n" + " }\n" + " else\n" + " {\n" + " factor *= ( 1.0f - frac[ j ] );\n" + " }\n" + " }\n" + "\n" + " float2 atlasOffset;\n" + "\n" + " atlasOffset.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[1] * gridStep[1] ) * invXY;\n" + " atlasOffset.y = ( gridCoord2[2] * invZ );\n" + "\n" + " irradiance += tex2D( samp7, normalizedOctCoordZeroOne + atlasOffset ).rgb * factor;\n" + "\n" + " totalFactor += factor;\n" + " }\n" + "\n" + " if( totalFactor > 0 && totalFactor < 0.99 )\n" + " {\n" + " totalFactor = 1.0f / totalFactor;\n" + "\n" + " irradiance *= totalFactor;\n" + " }\n" + "\n" + "// lightgrid atlas\n" + "\n" + "\n" + " float3 diffuseLight = ( kD * irradiance * diffuseColor ) * ao * ( rpDiffuseModifier.xyz * 1.0 );\n" + "\n" + " // evaluate specular IBL\n" + "\n" + " // should be 8 = numMips - 1, 256^2 = 9 mips\n" + " const float MAX_REFLECTION_LOD = 10.0;\n" + " float mip = clamp( ( roughness * MAX_REFLECTION_LOD ), 0.0, MAX_REFLECTION_LOD );\n" + " //float mip = 0.0;\n" + "\n" + " normalizedOctCoord = octEncode( reflectionVector );\n" + " normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n" + "\n" + " float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb;\n" + " //radiance = float3( 0.0 );\n" + "\n" + " float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg;\n" + "\n" + "#if 0\n" + " result.color.rgb = float3( envBRDF.x, envBRDF.y, 0.0 );\n" + " result.color.w = fragment.color.a;\n" + " return;\n" + "#endif\n" + "\n" + " float specAO = ComputeSpecularAO( vDotN, ao, roughness );\n" + " float3 specularLight = radiance * ( kS * envBRDF.x + float3( envBRDF.y ) ) * specAO * ( rpSpecularModifier.xyz * 0.5 );\n" + "\n" + "#if 0\n" + " // Marmoset Horizon Fade trick\n" + " const half horizonFade = 1.3;\n" + " half horiz = saturate( 1.0 + horizonFade * saturate( dot3( reflectionVector, globalNormal ) ) );\n" + " horiz *= horiz;\n" + " //horiz = clamp( horiz, 0.0, 1.0 );\n" + "#endif\n" + "\n" + " half3 lightColor = sRGBToLinearRGB( rpAmbientColor.rgb );\n" + "\n" + " //result.color.rgb = diffuseLight;\n" + " //result.color.rgb = diffuseLight * lightColor;\n" + " //result.color.rgb = specularLight;\n" + " result.color.rgb = ( diffuseLight + specularLight ) * lightColor * fragment.color.rgb;\n" + " //result.color.rgb = localNormal.xyz * 0.5 + 0.5;\n" + " //result.color.rgb = float3( ao );\n" + " result.color.w = fragment.color.a;\n" + "}\n" + "\n" + + }, + + { + "renderprogs/builtin/lighting/ambient_lightgrid_IBL.vs.hlsl", + "/*\n" + "===========================================================================\n" + "\n" + "Doom 3 BFG Edition GPL Source Code\n" + "Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.\n" + "Copyright (C) 2013-2015 Robert Beckebans\n" + "\n" + "This file is part of the Doom 3 BFG Edition GPL Source Code (\"Doom 3 BFG Edition Source Code\").\n" + "\n" + "Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify\n" + "it under the terms of the GNU General Public License as published by\n" + "the Free Software Foundation, either version 3 of the License, or\n" + "(at your option) any later version.\n" + "\n" + "Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,\n" + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + "GNU General Public License for more details.\n" + "\n" + "You should have received a copy of the GNU General Public License\n" + "along with Doom 3 BFG Edition Source Code. If not, see .\n" + "\n" + "In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.\n" + "\n" + "If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.\n" + "\n" + "===========================================================================\n" + "*/\n" + "\n" + "#include \"renderprogs/global.inc.hlsl\"\n" + "\n" + "\n" + "#if defined( USE_GPU_SKINNING )\n" + "uniform matrices_ubo { float4 matrices[408]; };\n" + "#endif\n" + "\n" + "// *INDENT-OFF*\n" + "struct VS_IN {\n" + " float4 position : POSITION;\n" + " float2 texcoord : TEXCOORD0;\n" + " float4 normal : NORMAL;\n" + " float4 tangent : TANGENT;\n" + " float4 color : COLOR0;\n" + " float4 color2 : COLOR1;\n" + "};\n" + "\n" + "struct VS_OUT {\n" + " float4 position : POSITION;\n" + " float4 texcoord0 : TEXCOORD0;\n" + " float4 texcoord1 : TEXCOORD1;\n" + " float4 texcoord2 : TEXCOORD2;\n" + " float4 texcoord3 : TEXCOORD3;\n" + " float4 texcoord4 : TEXCOORD4;\n" + " float4 texcoord5 : TEXCOORD5;\n" + " float4 texcoord6 : TEXCOORD6;\n" + " float4 texcoord7 : TEXCOORD7;\n" + " float4 color : COLOR0;\n" + "};\n" + "// *INDENT-ON*\n" + "\n" + "void main( VS_IN vertex, out VS_OUT result )\n" + "{\n" + "\n" + " float4 vNormal = vertex.normal * 2.0 - 1.0;\n" + " float4 vTangent = vertex.tangent * 2.0 - 1.0;\n" + " float3 vBitangent = cross( vNormal.xyz, vTangent.xyz ) * vTangent.w;\n" + "\n" + "#if defined( USE_GPU_SKINNING )\n" + " //--------------------------------------------------------------\n" + " // GPU transformation of the normal / tangent / bitangent\n" + " //\n" + " // multiplying with 255.1 give us the same result and is faster than floor( w * 255 + 0.5 )\n" + " //--------------------------------------------------------------\n" + " const float w0 = vertex.color2.x;\n" + " const float w1 = vertex.color2.y;\n" + " const float w2 = vertex.color2.z;\n" + " const float w3 = vertex.color2.w;\n" + "\n" + " float4 matX, matY, matZ; // must be float4 for vec4\n" + " int joint = int( vertex.color.x * 255.1 * 3.0 );\n" + " matX = matrices[int( joint + 0 )] * w0;\n" + " matY = matrices[int( joint + 1 )] * w0;\n" + " matZ = matrices[int( joint + 2 )] * w0;\n" + "\n" + " joint = int( vertex.color.y * 255.1 * 3.0 );\n" + " matX += matrices[int( joint + 0 )] * w1;\n" + " matY += matrices[int( joint + 1 )] * w1;\n" + " matZ += matrices[int( joint + 2 )] * w1;\n" + "\n" + " joint = int( vertex.color.z * 255.1 * 3.0 );\n" + " matX += matrices[int( joint + 0 )] * w2;\n" + " matY += matrices[int( joint + 1 )] * w2;\n" + " matZ += matrices[int( joint + 2 )] * w2;\n" + "\n" + " joint = int( vertex.color.w * 255.1 * 3.0 );\n" + " matX += matrices[int( joint + 0 )] * w3;\n" + " matY += matrices[int( joint + 1 )] * w3;\n" + " matZ += matrices[int( joint + 2 )] * w3;\n" + "\n" + " float3 normal;\n" + " normal.x = dot3( matX, vNormal );\n" + " normal.y = dot3( matY, vNormal );\n" + " normal.z = dot3( matZ, vNormal );\n" + " normal = normalize( normal );\n" + "\n" + " float3 tangent;\n" + " tangent.x = dot3( matX, vTangent );\n" + " tangent.y = dot3( matY, vTangent );\n" + " tangent.z = dot3( matZ, vTangent );\n" + " tangent = normalize( tangent );\n" + "\n" + " float3 bitangent;\n" + " bitangent.x = dot3( matX, vBitangent );\n" + " bitangent.y = dot3( matY, vBitangent );\n" + " bitangent.z = dot3( matZ, vBitangent );\n" + " bitangent = normalize( bitangent );\n" + "\n" + " float4 modelPosition;\n" + " modelPosition.x = dot4( matX, vertex.position );\n" + " modelPosition.y = dot4( matY, vertex.position );\n" + " modelPosition.z = dot4( matZ, vertex.position );\n" + " modelPosition.w = 1.0;\n" + "\n" + "#else\n" + " float4 modelPosition = vertex.position;\n" + " float3 normal = vNormal.xyz;\n" + " float3 tangent = vTangent.xyz;\n" + " float3 bitangent = vBitangent.xyz;\n" + "#endif\n" + "\n" + " result.position.x = dot4( modelPosition, rpMVPmatrixX );\n" + " result.position.y = dot4( modelPosition, rpMVPmatrixY );\n" + " result.position.z = dot4( modelPosition, rpMVPmatrixZ );\n" + " result.position.w = dot4( modelPosition, rpMVPmatrixW );\n" + "\n" + " float4 defaultTexCoord = float4( 0.0f, 0.5f, 0.0f, 1.0f );\n" + "\n" + " //calculate vector to light\n" + " //float4 toLight = rpLocalLightOrigin;\n" + " float4 toLight = normalize( float4( 0.0f, 0.5f, 1.0f, 1.0f ) );\n" + "\n" + " //--------------------------------------------------------------\n" + "\n" + "\n" + " //# textures 0 takes the base coordinates by the texture matrix\n" + " result.texcoord0 = defaultTexCoord;\n" + " result.texcoord0.x = dot4( vertex.texcoord.xy, rpBumpMatrixS );\n" + " result.texcoord0.y = dot4( vertex.texcoord.xy, rpBumpMatrixT );\n" + "\n" + " //# textures 1 takes the base coordinates by the texture matrix\n" + " result.texcoord1 = defaultTexCoord;\n" + " result.texcoord1.x = dot4( vertex.texcoord.xy, rpDiffuseMatrixS );\n" + " result.texcoord1.y = dot4( vertex.texcoord.xy, rpDiffuseMatrixT );\n" + "\n" + " //# textures 2 takes the base coordinates by the texture matrix\n" + " result.texcoord2 = defaultTexCoord;\n" + " result.texcoord2.x = dot4( vertex.texcoord.xy, rpSpecularMatrixS );\n" + " result.texcoord2.y = dot4( vertex.texcoord.xy, rpSpecularMatrixT );\n" + "\n" + " //# calculate normalized vector to viewer in R1\n" + " //result.texcoord3 = modelPosition;\n" + "\n" + " float4 toEye = normalize( rpLocalViewOrigin - modelPosition );\n" + "\n" + " result.texcoord3.x = dot3( toEye, rpModelMatrixX );\n" + " result.texcoord3.y = dot3( toEye, rpModelMatrixY );\n" + " result.texcoord3.z = dot3( toEye, rpModelMatrixZ );\n" + "\n" + " result.texcoord4.x = dot3( tangent, rpModelMatrixX );\n" + " result.texcoord5.x = dot3( tangent, rpModelMatrixY );\n" + " result.texcoord6.x = dot3( tangent, rpModelMatrixZ );\n" + "\n" + " result.texcoord4.y = dot3( bitangent, rpModelMatrixX );\n" + " result.texcoord5.y = dot3( bitangent, rpModelMatrixY );\n" + " result.texcoord6.y = dot3( bitangent, rpModelMatrixZ );\n" + "\n" + " result.texcoord4.z = dot3( normal, rpModelMatrixX );\n" + " result.texcoord5.z = dot3( normal, rpModelMatrixY );\n" + " result.texcoord6.z = dot3( normal, rpModelMatrixZ );\n" + "\n" + " float4 worldPosition;\n" + " worldPosition.x = dot4( modelPosition, rpModelMatrixX );\n" + " worldPosition.y = dot4( modelPosition, rpModelMatrixY );\n" + " worldPosition.z = dot4( modelPosition, rpModelMatrixZ );\n" + " worldPosition.w = dot4( modelPosition, rpModelMatrixW );\n" + " result.texcoord7 = worldPosition;\n" + "\n" + "#if defined( USE_GPU_SKINNING )\n" + " // for joint transformation of the tangent space, we use color and\n" + " // color2 for weighting information, so hopefully there aren't any\n" + " // effects that need vertex color...\n" + " result.color = float4( 1.0f, 1.0f, 1.0f, 1.0f );\n" + "#else\n" + " //# generate the vertex color, which can be 1.0, color, or 1.0 - color\n" + " //# for 1.0 : env[16] = 0, env[17] = 1\n" + " //# for color : env[16] = 1, env[17] = 0\n" + " //# for 1.0-color : env[16] = -1, env[17] = 1\n" + " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" + "#endif\n" + "}\n" + + }, + { "renderprogs/builtin/lighting/interaction.ps.hlsl", "/*\n" diff --git a/neo/renderer/tr_frontend_main.cpp b/neo/renderer/tr_frontend_main.cpp index e9199c01..5adfb5f3 100644 --- a/neo/renderer/tr_frontend_main.cpp +++ b/neo/renderer/tr_frontend_main.cpp @@ -549,6 +549,22 @@ void R_RenderView( viewDef_t* parms ) tr.viewDef->irradianceImage = globalImages->defaultUACIrradianceCube; tr.viewDef->radianceImage = globalImages->defaultUACRadianceCube; + bool useLightGrid = tr.viewDef->useLightGrid = false; + + portalArea_t* area = &tr.primaryWorld->portalAreas[tr.viewDef->areaNum]; + if( area->lightGrid.irradianceImage && !area->lightGrid.irradianceImage->IsDefaulted() ) + { + tr.viewDef->irradianceImage = area->lightGrid.irradianceImage; + tr.viewDef->useLightGrid = useLightGrid = true; + + for( int i = 0; i < 3; i++ ) + { + tr.viewDef->lightGridOrigin[i] = area->lightGrid.lightGridOrigin[i]; + tr.viewDef->lightGridSize[i] = area->lightGrid.lightGridSize[i]; + tr.viewDef->lightGridBounds[i] = area->lightGrid.lightGridBounds[i]; + } + } + for( viewEnvprobe_t* vProbe = tr.viewDef->viewEnvprobes; vProbe != NULL; vProbe = vProbe->next ) { float dist = ( tr.viewDef->renderView.vieworg - vProbe->globalOrigin ).Length(); @@ -557,7 +573,11 @@ void R_RenderView( viewDef_t* parms ) if( vProbe->irradianceImage->IsLoaded() && !vProbe->irradianceImage->IsDefaulted() ) { tr.viewDef->globalProbeBounds = vProbe->globalProbeBounds; - tr.viewDef->irradianceImage = vProbe->irradianceImage; + + if( !useLightGrid ) + { + tr.viewDef->irradianceImage = vProbe->irradianceImage; + } tr.viewDef->radianceImage = vProbe->radianceImage; bestDist = dist; From 275243241614a8628fd92170cc46d9955686680d Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Thu, 15 Apr 2021 16:09:39 +0200 Subject: [PATCH 09/26] Use dynamic light grid size in shaders --- .../builtin/debug/lightgrid.ps.hlsl | 12 +++-- .../lighting/ambient_lightgrid_IBL.ps.hlsl | 52 ++++++------------- .../lighting/ambient_lighting_IBL.ps.hlsl | 12 ++--- neo/renderer/OpenGL/RenderDebug_GL.cpp | 11 ++-- neo/renderer/RenderBackend.cpp | 15 ++++-- neo/renderer/RenderProgs.h | 1 - 6 files changed, 48 insertions(+), 55 deletions(-) diff --git a/base/renderprogs/builtin/debug/lightgrid.ps.hlsl b/base/renderprogs/builtin/debug/lightgrid.ps.hlsl index 14f564d2..02b61813 100644 --- a/base/renderprogs/builtin/debug/lightgrid.ps.hlsl +++ b/base/renderprogs/builtin/debug/lightgrid.ps.hlsl @@ -46,12 +46,12 @@ struct PS_OUT { // *INDENT-ON* -float3 lightGridOrigin = float3( -192.0, -128.0, 0 ); -float3 lightGridSize = float3( 64.0, 64.0, 128.0 ); -int3 lightGridBounds = int3( 7, 7, 3 ); - int3 GetBaseGridCoord( float3 origin ) { + float3 lightGridOrigin = rpGlobalLightOrigin.xyz; + float3 lightGridSize = rpJitterTexScale.xyz; + int3 lightGridBounds = int3( rpJitterTexOffset.x, rpJitterTexOffset.y, rpJitterTexOffset.z ); + int3 pos; float3 lightOrigin = origin - lightGridOrigin; @@ -87,6 +87,10 @@ void main( PS_IN fragment, out PS_OUT result ) float2 normalizedOctCoord = octEncode( globalNormal ); float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5; + float3 lightGridOrigin = rpGlobalLightOrigin.xyz; + float3 lightGridSize = rpJitterTexScale.xyz; + int3 lightGridBounds = int3( rpJitterTexOffset.x, rpJitterTexOffset.y, rpJitterTexOffset.z ); + float invXY = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[1] ) ); float invZ = ( 1.0 / lightGridBounds[2] ); diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl index 38d06221..30932c86 100644 --- a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl @@ -63,36 +63,6 @@ struct PS_OUT // *INDENT-ON* -float3 lightGridOrigin = float3( -192.0, -128.0, 0 ); -float3 lightGridSize = float3( 64.0, 64.0, 128.0 ); -int3 lightGridBounds = int3( 7, 7, 3 ); - -int3 GetBaseGridCoord( float3 origin ) -{ - int3 pos; - - float3 lightOrigin = origin - lightGridOrigin; - for( int i = 0; i < 3; i++ ) - { - float v; - - v = lightOrigin[i] * ( 1.0f / lightGridSize[i] ); - pos[i] = int( floor( v ) ); - - if( pos[i] < 0 ) - { - pos[i] = 0; - } - else if( pos[i] >= lightGridBounds[i] - 1 ) - { - pos[i] = lightGridBounds[i] - 1; - } - } - - return pos; -} - - // RB: TODO OPTIMIZE // this is a straight port of idBounds::RayIntersection bool AABBRayIntersection( float3 b[2], float3 start, float3 dir, out float scale ) @@ -175,15 +145,14 @@ void main( PS_IN fragment, out PS_OUT result ) float3 globalPosition = fragment.texcoord7.xyz; - // RB: rpGlobalLightOrigin is global view origin - float3 globalEye = normalize( rpGlobalLightOrigin.xyz - globalPosition ); + float3 globalView = normalize( rpGlobalEyePos.xyz - globalPosition ); - float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal ); - reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalEye ); + float3 reflectionVector = globalNormal * dot3( globalView, globalNormal ); + reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalView ); #if 1 // parallax box correction using portal area bounds - float hitScale; + float hitScale = 0.0; float3 bounds[2]; bounds[0].x = rpWobbleSkyX.x; bounds[0].y = rpWobbleSkyX.y; @@ -209,7 +178,7 @@ void main( PS_IN fragment, out PS_OUT result ) } #endif - half vDotN = saturate( dot3( globalEye, globalNormal ) ); + half vDotN = saturate( dot3( globalView, globalNormal ) ); #if defined( USE_PBR ) const half metallic = specMapSRGB.g; @@ -271,6 +240,15 @@ void main( PS_IN fragment, out PS_OUT result ) float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5; // lightgrid atlas + + //float3 lightGridOrigin = float3( -192.0, -128.0, 0 ); + //float3 lightGridSize = float3( 64.0, 64.0, 128.0 ); + //int3 lightGridBounds = int3( 7, 7, 3 ); + + float3 lightGridOrigin = rpGlobalLightOrigin.xyz; + float3 lightGridSize = rpJitterTexScale.xyz; + int3 lightGridBounds = int3( rpJitterTexOffset.x, rpJitterTexOffset.y, rpJitterTexOffset.z ); + float invXY = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[1] ) ); float invZ = ( 1.0 / lightGridBounds[2] ); @@ -307,7 +285,7 @@ void main( PS_IN fragment, out PS_OUT result ) gridStep[2] = lightGridBounds[0] * lightGridBounds[1]; float totalFactor = 0.0; - float3 irradiance; + float3 irradiance = float3( 0.0, 0.0, 0.0 ); /* for( int i = 0; i < 8; i++ ) diff --git a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl index a99daa64..981c9ded 100644 --- a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl @@ -62,6 +62,7 @@ struct PS_OUT }; // *INDENT-ON* + // RB: TODO OPTIMIZE // this is a straight port of idBounds::RayIntersection bool AABBRayIntersection( float3 b[2], float3 start, float3 dir, out float scale ) @@ -144,15 +145,14 @@ void main( PS_IN fragment, out PS_OUT result ) float3 globalPosition = fragment.texcoord7.xyz; - // RB: rpGlobalLightOrigin is global view origin - float3 globalEye = normalize( rpGlobalLightOrigin.xyz - globalPosition ); + float3 globalView = normalize( rpGlobalEyePos.xyz - globalPosition ); - float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal ); - reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalEye ); + float3 reflectionVector = globalNormal * dot3( globalView, globalNormal ); + reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalView ); #if 1 // parallax box correction using portal area bounds - float hitScale; + float hitScale = 0.0; float3 bounds[2]; bounds[0].x = rpWobbleSkyX.x; bounds[0].y = rpWobbleSkyX.y; @@ -178,7 +178,7 @@ void main( PS_IN fragment, out PS_OUT result ) } #endif - half vDotN = saturate( dot3( globalEye, globalNormal ) ); + half vDotN = saturate( dot3( globalView, globalNormal ) ); #if defined( USE_PBR ) const half metallic = specMapSRGB.g; diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index 2a88cc0a..5bed7dc6 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1815,9 +1815,14 @@ void idRenderBackend::DBG_ShowLightGrid() const int numColors = 7; static idVec4 colors[numColors] = { colorBlack, colorBlue, colorCyan, colorGreen, colorYellow, colorRed, colorWhite }; - // use rpGlobalLightOrigin for camera center - idVec4 globalViewOrigin( viewDef->renderView.vieworg.x, viewDef->renderView.vieworg.y, viewDef->renderView.vieworg.z, 1.0f ); - renderProgManager.SetUniformValue( RENDERPARM_GLOBALLIGHTORIGIN, globalViewOrigin.ToFloatPtr() ); + // use rpGlobalLightOrigin for lightGrid center + idVec4 lightGridOrigin( area->lightGrid.lightGridOrigin.x, area->lightGrid.lightGridOrigin.y, area->lightGrid.lightGridOrigin.z, 1.0f ); + idVec4 lightGridSize( area->lightGrid.lightGridSize.x, area->lightGrid.lightGridSize.y, area->lightGrid.lightGridSize.z, 1.0f ); + idVec4 lightGridBounds( area->lightGrid.lightGridBounds[0], area->lightGrid.lightGridBounds[1], area->lightGrid.lightGridBounds[2], 1.0f ); + + renderProgManager.SetUniformValue( RENDERPARM_GLOBALLIGHTORIGIN, lightGridOrigin.ToFloatPtr() ); + renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXSCALE, lightGridSize.ToFloatPtr() ); + renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXOFFSET, lightGridBounds.ToFloatPtr() ); for( int i = 0; i < area->lightGrid.lightGridPoints.Num(); i++ ) { diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index f4af42dc..4c3d424d 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -1344,6 +1344,17 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas SetVertexParm( RENDERPARM_WOBBLESKY_Y, probeMaxs.ToFloatPtr() ); SetVertexParm( RENDERPARM_WOBBLESKY_Z, probeCenter.ToFloatPtr() ); + //SetVertexParm( RENDERPARM_WOBBLESK_Z, probeCenter.ToFloatPtr() ); + + // use rpGlobalLightOrigin for lightGrid center + idVec4 lightGridOrigin( viewDef->lightGridOrigin.x, viewDef->lightGridOrigin.y, viewDef->lightGridOrigin.z, 1.0f ); + idVec4 lightGridSize( viewDef->lightGridSize.x, viewDef->lightGridSize.y, viewDef->lightGridSize.z, 1.0f ); + idVec4 lightGridBounds( viewDef->lightGridBounds[0], viewDef->lightGridBounds[1], viewDef->lightGridBounds[2], 1.0f ); + + renderProgManager.SetUniformValue( RENDERPARM_GLOBALLIGHTORIGIN, lightGridOrigin.ToFloatPtr() ); + renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXSCALE, lightGridSize.ToFloatPtr() ); + renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXOFFSET, lightGridBounds.ToFloatPtr() ); + if( specUsage == TD_SPECULAR_PBR_RMAO || specUsage == TD_SPECULAR_PBR_RMAOD ) { // PBR path with roughness, metal and AO @@ -2311,10 +2322,6 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr renderProgManager.SetRenderParm( RENDERPARM_AMBIENT_COLOR, ambientColor.ToFloatPtr() ); - // use rpGlobalLightOrigin for camera center - idVec4 globalViewOrigin( viewDef->renderView.vieworg.x, viewDef->renderView.vieworg.y, viewDef->renderView.vieworg.z, 1.0f ); - SetVertexParm( RENDERPARM_GLOBALLIGHTORIGIN, globalViewOrigin.ToFloatPtr() ); - // setup renderparms assuming we will be drawing trivial surfaces first RB_SetupForFastPathInteractions( diffuseColor, specularColor ); diff --git a/neo/renderer/RenderProgs.h b/neo/renderer/RenderProgs.h index 59f97fed..3709606e 100644 --- a/neo/renderer/RenderProgs.h +++ b/neo/renderer/RenderProgs.h @@ -147,7 +147,6 @@ enum renderParm_t // RB begin RENDERPARM_AMBIENT_COLOR, -// RENDERPARM_GLOBALVIEWORIGIN, RENDERPARM_GLOBALLIGHTORIGIN, RENDERPARM_JITTERTEXSCALE, RENDERPARM_JITTERTEXOFFSET, From 15a9411161e9bf0f65cba9a5d62660e209bdcd7f Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Thu, 15 Apr 2021 18:06:50 +0200 Subject: [PATCH 10/26] Changed lightgrid texture layout --- .../builtin/debug/lightgrid.ps.hlsl | 12 +-- .../lighting/ambient_lightgrid_IBL.ps.hlsl | 12 +-- neo/renderer/RenderProgs_embedded.h | 100 +++++++----------- neo/renderer/RenderWorld_lightgrid.cpp | 22 ++-- 4 files changed, 69 insertions(+), 77 deletions(-) diff --git a/base/renderprogs/builtin/debug/lightgrid.ps.hlsl b/base/renderprogs/builtin/debug/lightgrid.ps.hlsl index 02b61813..61b4bd40 100644 --- a/base/renderprogs/builtin/debug/lightgrid.ps.hlsl +++ b/base/renderprogs/builtin/debug/lightgrid.ps.hlsl @@ -91,11 +91,11 @@ void main( PS_IN fragment, out PS_OUT result ) float3 lightGridSize = rpJitterTexScale.xyz; int3 lightGridBounds = int3( rpJitterTexOffset.x, rpJitterTexOffset.y, rpJitterTexOffset.z ); - float invXY = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[1] ) ); - float invZ = ( 1.0 / lightGridBounds[2] ); + float invXZ = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[2] ) ); + float invY = ( 1.0 / lightGridBounds[1] ); - normalizedOctCoordZeroOne.x *= invXY; - normalizedOctCoordZeroOne.y *= invZ; + normalizedOctCoordZeroOne.x *= invXZ; + normalizedOctCoordZeroOne.y *= invY; int3 gridStep; @@ -105,8 +105,8 @@ void main( PS_IN fragment, out PS_OUT result ) int3 gridCoord = GetBaseGridCoord( globalPosition ); - normalizedOctCoordZeroOne.x += ( gridCoord[0] * gridStep[0] + gridCoord[1] * gridStep[1] ) * invXY; - normalizedOctCoordZeroOne.y += ( gridCoord[2] * invZ ); + normalizedOctCoordZeroOne.x += ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * invXZ; + normalizedOctCoordZeroOne.y += ( gridCoord[1] * invY ); float4 envMap = tex2D( samp0, normalizedOctCoordZeroOne ); diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl index 30932c86..c459e1a1 100644 --- a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl @@ -249,11 +249,11 @@ void main( PS_IN fragment, out PS_OUT result ) float3 lightGridSize = rpJitterTexScale.xyz; int3 lightGridBounds = int3( rpJitterTexOffset.x, rpJitterTexOffset.y, rpJitterTexOffset.z ); - float invXY = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[1] ) ); - float invZ = ( 1.0 / lightGridBounds[2] ); + float invXZ = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[2] ) ); + float invY = ( 1.0 / lightGridBounds[1] ); - normalizedOctCoordZeroOne.x *= invXY; - normalizedOctCoordZeroOne.y *= invZ; + normalizedOctCoordZeroOne.x *= invXZ; + normalizedOctCoordZeroOne.y *= invY; int3 gridCoord; float3 frac; @@ -328,8 +328,8 @@ void main( PS_IN fragment, out PS_OUT result ) float2 atlasOffset; - atlasOffset.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[1] * gridStep[1] ) * invXY; - atlasOffset.y = ( gridCoord2[2] * invZ ); + atlasOffset.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * invXZ; + atlasOffset.y = ( gridCoord2[1] * invY ); irradiance += tex2D( samp7, normalizedOctCoordZeroOne + atlasOffset ).rgb * factor; diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index 644bdc9c..0cd0f58e 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -2811,12 +2811,12 @@ static const cgShaderDef_t cg_renderprogs[] = "// *INDENT-ON*\n" "\n" "\n" - "float3 lightGridOrigin = float3( -192.0, -128.0, 0 );\n" - "float3 lightGridSize = float3( 64.0, 64.0, 128.0 );\n" - "int3 lightGridBounds = int3( 7, 7, 3 );\n" - "\n" "int3 GetBaseGridCoord( float3 origin )\n" "{\n" + " float3 lightGridOrigin = rpGlobalLightOrigin.xyz;\n" + " float3 lightGridSize = rpJitterTexScale.xyz;\n" + " int3 lightGridBounds = int3( rpJitterTexOffset.x, rpJitterTexOffset.y, rpJitterTexOffset.z );\n" + "\n" " int3 pos;\n" "\n" " float3 lightOrigin = origin - lightGridOrigin;\n" @@ -2852,11 +2852,15 @@ static const cgShaderDef_t cg_renderprogs[] = " float2 normalizedOctCoord = octEncode( globalNormal );\n" " float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n" "\n" - " float invXY = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[1] ) );\n" - " float invZ = ( 1.0 / lightGridBounds[2] );\n" + " float3 lightGridOrigin = rpGlobalLightOrigin.xyz;\n" + " float3 lightGridSize = rpJitterTexScale.xyz;\n" + " int3 lightGridBounds = int3( rpJitterTexOffset.x, rpJitterTexOffset.y, rpJitterTexOffset.z );\n" "\n" - " normalizedOctCoordZeroOne.x *= invXY;\n" - " normalizedOctCoordZeroOne.y *= invZ;\n" + " float invXZ = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[2] ) );\n" + " float invY = ( 1.0 / lightGridBounds[1] );\n" + "\n" + " normalizedOctCoordZeroOne.x *= invXZ;\n" + " normalizedOctCoordZeroOne.y *= invY;\n" "\n" " int3 gridStep;\n" "\n" @@ -2866,8 +2870,8 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " int3 gridCoord = GetBaseGridCoord( globalPosition );\n" "\n" - " normalizedOctCoordZeroOne.x += ( gridCoord[0] * gridStep[0] + gridCoord[1] * gridStep[1] ) * invXY;\n" - " normalizedOctCoordZeroOne.y += ( gridCoord[2] * invZ );\n" + " normalizedOctCoordZeroOne.x += ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * invXZ;\n" + " normalizedOctCoordZeroOne.y += ( gridCoord[1] * invY );\n" "\n" " float4 envMap = tex2D( samp0, normalizedOctCoordZeroOne );\n" "\n" @@ -4798,6 +4802,7 @@ static const cgShaderDef_t cg_renderprogs[] = "};\n" "// *INDENT-ON*\n" "\n" + "\n" "// RB: TODO OPTIMIZE\n" "// this is a straight port of idBounds::RayIntersection\n" "bool AABBRayIntersection( float3 b[2], float3 start, float3 dir, out float scale )\n" @@ -4880,15 +4885,14 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " float3 globalPosition = fragment.texcoord7.xyz;\n" "\n" - " // RB: rpGlobalLightOrigin is global view origin\n" - " float3 globalEye = normalize( rpGlobalLightOrigin.xyz - globalPosition );\n" + " float3 globalView = normalize( rpGlobalEyePos.xyz - globalPosition );\n" "\n" - " float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal );\n" - " reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalEye );\n" + " float3 reflectionVector = globalNormal * dot3( globalView, globalNormal );\n" + " reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalView );\n" "\n" "#if 1\n" " // parallax box correction using portal area bounds\n" - " float hitScale;\n" + " float hitScale = 0.0;\n" " float3 bounds[2];\n" " bounds[0].x = rpWobbleSkyX.x;\n" " bounds[0].y = rpWobbleSkyX.y;\n" @@ -4914,7 +4918,7 @@ static const cgShaderDef_t cg_renderprogs[] = " }\n" "#endif\n" "\n" - " half vDotN = saturate( dot3( globalEye, globalNormal ) );\n" + " half vDotN = saturate( dot3( globalView, globalNormal ) );\n" "\n" "#if defined( USE_PBR )\n" " const half metallic = specMapSRGB.g;\n" @@ -5296,36 +5300,6 @@ static const cgShaderDef_t cg_renderprogs[] = "// *INDENT-ON*\n" "\n" "\n" - "float3 lightGridOrigin = float3( -192.0, -128.0, 0 );\n" - "float3 lightGridSize = float3( 64.0, 64.0, 128.0 );\n" - "int3 lightGridBounds = int3( 7, 7, 3 );\n" - "\n" - "int3 GetBaseGridCoord( float3 origin )\n" - "{\n" - " int3 pos;\n" - "\n" - " float3 lightOrigin = origin - lightGridOrigin;\n" - " for( int i = 0; i < 3; i++ )\n" - " {\n" - " float v;\n" - "\n" - " v = lightOrigin[i] * ( 1.0f / lightGridSize[i] );\n" - " pos[i] = int( floor( v ) );\n" - "\n" - " if( pos[i] < 0 )\n" - " {\n" - " pos[i] = 0;\n" - " }\n" - " else if( pos[i] >= lightGridBounds[i] - 1 )\n" - " {\n" - " pos[i] = lightGridBounds[i] - 1;\n" - " }\n" - " }\n" - "\n" - " return pos;\n" - "}\n" - "\n" - "\n" "// RB: TODO OPTIMIZE\n" "// this is a straight port of idBounds::RayIntersection\n" "bool AABBRayIntersection( float3 b[2], float3 start, float3 dir, out float scale )\n" @@ -5408,15 +5382,14 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " float3 globalPosition = fragment.texcoord7.xyz;\n" "\n" - " // RB: rpGlobalLightOrigin is global view origin\n" - " float3 globalEye = normalize( rpGlobalLightOrigin.xyz - globalPosition );\n" + " float3 globalView = normalize( rpGlobalEyePos.xyz - globalPosition );\n" "\n" - " float3 reflectionVector = globalNormal * dot3( globalEye, globalNormal );\n" - " reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalEye );\n" + " float3 reflectionVector = globalNormal * dot3( globalView, globalNormal );\n" + " reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalView );\n" "\n" "#if 1\n" " // parallax box correction using portal area bounds\n" - " float hitScale;\n" + " float hitScale = 0.0;\n" " float3 bounds[2];\n" " bounds[0].x = rpWobbleSkyX.x;\n" " bounds[0].y = rpWobbleSkyX.y;\n" @@ -5442,7 +5415,7 @@ static const cgShaderDef_t cg_renderprogs[] = " }\n" "#endif\n" "\n" - " half vDotN = saturate( dot3( globalEye, globalNormal ) );\n" + " half vDotN = saturate( dot3( globalView, globalNormal ) );\n" "\n" "#if defined( USE_PBR )\n" " const half metallic = specMapSRGB.g;\n" @@ -5504,11 +5477,20 @@ static const cgShaderDef_t cg_renderprogs[] = " float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n" "\n" "// lightgrid atlas\n" - " float invXY = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[1] ) );\n" - " float invZ = ( 1.0 / lightGridBounds[2] );\n" "\n" - " normalizedOctCoordZeroOne.x *= invXY;\n" - " normalizedOctCoordZeroOne.y *= invZ;\n" + " //float3 lightGridOrigin = float3( -192.0, -128.0, 0 );\n" + " //float3 lightGridSize = float3( 64.0, 64.0, 128.0 );\n" + " //int3 lightGridBounds = int3( 7, 7, 3 );\n" + "\n" + " float3 lightGridOrigin = rpGlobalLightOrigin.xyz;\n" + " float3 lightGridSize = rpJitterTexScale.xyz;\n" + " int3 lightGridBounds = int3( rpJitterTexOffset.x, rpJitterTexOffset.y, rpJitterTexOffset.z );\n" + "\n" + " float invXZ = ( 1.0 / ( lightGridBounds[0] * lightGridBounds[2] ) );\n" + " float invY = ( 1.0 / lightGridBounds[1] );\n" + "\n" + " normalizedOctCoordZeroOne.x *= invXZ;\n" + " normalizedOctCoordZeroOne.y *= invY;\n" "\n" " int3 gridCoord;\n" " float3 frac;\n" @@ -5540,7 +5522,7 @@ static const cgShaderDef_t cg_renderprogs[] = " gridStep[2] = lightGridBounds[0] * lightGridBounds[1];\n" "\n" " float totalFactor = 0.0;\n" - " float3 irradiance;\n" + " float3 irradiance = float3( 0.0, 0.0, 0.0 );\n" "\n" " /*\n" " for( int i = 0; i < 8; i++ )\n" @@ -5583,8 +5565,8 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " float2 atlasOffset;\n" "\n" - " atlasOffset.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[1] * gridStep[1] ) * invXY;\n" - " atlasOffset.y = ( gridCoord2[2] * invZ );\n" + " atlasOffset.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * invXZ;\n" + " atlasOffset.y = ( gridCoord2[1] * invY );\n" "\n" " irradiance += tex2D( samp7, normalizedOctCoordZeroOne + atlasOffset ).rgb * factor;\n" "\n" diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 20eaa655..bb6ef4d2 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -670,10 +670,20 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) } */ +#if 1 + int a = tr.primaryWorld->PointInArea( tr.primaryView->renderView.vieworg ); + if( a == -1 ) + { + return; + } +#else for( int a = 0; a < tr.primaryWorld->NumAreas(); a++ ) +#endif { portalArea_t* area = &tr.primaryWorld->portalAreas[a]; + idLib::Printf( "Shooting %i grid probes area %i...\n\n", area->lightGrid.lightGridPoints.Num(), a ); + CommandlineProgressBar progressBar( area->lightGrid.lightGridPoints.Num() ); if( !useThreads ) { @@ -789,15 +799,15 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) - int atlasWidth = area->lightGrid.lightGridBounds[0] * area->lightGrid.lightGridBounds[1] * LIGHTGRID_IRRADIANCE_SIZE; - int atlasHeight = area->lightGrid.lightGridBounds[2] * LIGHTGRID_IRRADIANCE_SIZE; + int atlasWidth = area->lightGrid.lightGridBounds[0] * area->lightGrid.lightGridBounds[2] * LIGHTGRID_IRRADIANCE_SIZE; + int atlasHeight = area->lightGrid.lightGridBounds[1] * LIGHTGRID_IRRADIANCE_SIZE; idTempArray irradianceAtlas( atlasWidth * atlasHeight * 3 ); - // fill everything with solid red + // fill everything with solid black for( int i = 0; i < ( atlasWidth * atlasHeight ); i++ ) { - irradianceAtlas[i * 3 + 0] = F32toF16( 1.0f ); + irradianceAtlas[i * 3 + 0] = F32toF16( 0.0f ); irradianceAtlas[i * 3 + 1] = F32toF16( 0.0f ); irradianceAtlas[i * 3 + 2] = F32toF16( 0.0f ); } @@ -815,8 +825,8 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) { // gridPoint = lightGridPoints[ gridCoord[0] * gridStep[0] + gridCoord[1] * gridStep[1] + gridCoord[2] * gridStep[2] ]; - int xx = x + ( job->gridCoord[0] * gridStep[0] + job->gridCoord[1] * gridStep[1] ) * LIGHTGRID_IRRADIANCE_SIZE; - int yy = y + job->gridCoord[2] * LIGHTGRID_IRRADIANCE_SIZE; + int xx = x + ( job->gridCoord[0] * gridStep[0] + job->gridCoord[2] * gridStep[1] ) * LIGHTGRID_IRRADIANCE_SIZE; + int yy = y + job->gridCoord[1] * LIGHTGRID_IRRADIANCE_SIZE; irradianceAtlas[( yy * atlasWidth + xx ) * 3 + 0] = job->outBuffer[( y * LIGHTGRID_IRRADIANCE_SIZE + x ) * 3 + 0]; irradianceAtlas[( yy * atlasWidth + xx ) * 3 + 1] = job->outBuffer[( y * LIGHTGRID_IRRADIANCE_SIZE + x ) * 3 + 1]; From 25b14756bb297e93ff1fd163a3c42ab25372016f Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Thu, 15 Apr 2021 21:28:50 +0200 Subject: [PATCH 11/26] Use first valid lightgrid of viewEntity areas --- .../lighting/ambient_lightgrid_IBL.ps.hlsl | 6 +-- neo/renderer/OpenGL/RenderDebug_GL.cpp | 2 +- neo/renderer/RenderBackend.cpp | 17 ++---- neo/renderer/RenderCommon.h | 16 +++--- neo/renderer/RenderProgs_embedded.h | 6 +-- neo/renderer/RenderWorld_lightgrid.cpp | 52 +++++++++++++------ neo/renderer/RenderWorld_local.h | 10 +++- neo/renderer/tr_frontend_addmodels.cpp | 27 ++++++++++ neo/renderer/tr_frontend_main.cpp | 21 +------- 9 files changed, 93 insertions(+), 64 deletions(-) diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl index c459e1a1..91d4622e 100644 --- a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl @@ -336,7 +336,7 @@ void main( PS_IN fragment, out PS_OUT result ) totalFactor += factor; } - if( totalFactor > 0 && totalFactor < 0.99 ) + if( totalFactor > 0.0 && totalFactor < 0.9999 ) { totalFactor = 1.0f / totalFactor; @@ -372,7 +372,7 @@ void main( PS_IN fragment, out PS_OUT result ) float specAO = ComputeSpecularAO( vDotN, ao, roughness ); float3 specularLight = radiance * ( kS * envBRDF.x + float3( envBRDF.y ) ) * specAO * ( rpSpecularModifier.xyz * 0.5 ); -#if 0 +#if 1 // Marmoset Horizon Fade trick const half horizonFade = 1.3; half horiz = saturate( 1.0 + horizonFade * saturate( dot3( reflectionVector, globalNormal ) ) ); @@ -385,7 +385,7 @@ void main( PS_IN fragment, out PS_OUT result ) //result.color.rgb = diffuseLight; //result.color.rgb = diffuseLight * lightColor; //result.color.rgb = specularLight; - result.color.rgb = ( diffuseLight + specularLight ) * lightColor * fragment.color.rgb; + result.color.rgb = ( diffuseLight + specularLight * horiz ) * lightColor * fragment.color.rgb; //result.color.rgb = localNormal.xyz * 0.5 + 0.5; //result.color.rgb = float3( ao ); result.color.w = fragment.color.a; diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index 5bed7dc6..37ee6bc0 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1886,7 +1886,7 @@ void idRenderBackend::DBG_ShowLightGrid() renderProgManager.BindShader_DebugLightGrid(); GL_SelectTexture( 0 ); - area->lightGrid.irradianceImage->Bind(); + area->lightGrid.GetIrradianceImage()->Bind(); #endif idRenderMatrix modelRenderMatrix; diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 4c3d424d..35251fc2 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -1323,7 +1323,7 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas const textureUsage_t specUsage = din->specularImage->GetUsage(); // RB begin - if( useIBL && viewDef->useLightGrid ) + if( useIBL && currentSpace->useLightGrid ) { idVec4 probeMins, probeMaxs, probeCenter; @@ -1347,9 +1347,9 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas //SetVertexParm( RENDERPARM_WOBBLESK_Z, probeCenter.ToFloatPtr() ); // use rpGlobalLightOrigin for lightGrid center - idVec4 lightGridOrigin( viewDef->lightGridOrigin.x, viewDef->lightGridOrigin.y, viewDef->lightGridOrigin.z, 1.0f ); - idVec4 lightGridSize( viewDef->lightGridSize.x, viewDef->lightGridSize.y, viewDef->lightGridSize.z, 1.0f ); - idVec4 lightGridBounds( viewDef->lightGridBounds[0], viewDef->lightGridBounds[1], viewDef->lightGridBounds[2], 1.0f ); + idVec4 lightGridOrigin( currentSpace->lightGridOrigin.x, currentSpace->lightGridOrigin.y, currentSpace->lightGridOrigin.z, 1.0f ); + idVec4 lightGridSize( currentSpace->lightGridSize.x, currentSpace->lightGridSize.y, currentSpace->lightGridSize.z, 1.0f ); + idVec4 lightGridBounds( currentSpace->lightGridBounds[0], currentSpace->lightGridBounds[1], currentSpace->lightGridBounds[2], 1.0f ); renderProgManager.SetUniformValue( RENDERPARM_GLOBALLIGHTORIGIN, lightGridOrigin.ToFloatPtr() ); renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXSCALE, lightGridSize.ToFloatPtr() ); @@ -1397,14 +1397,7 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas #endif GL_SelectTexture( INTERACTION_TEXUNIT_AMBIENT_CUBE1 ); - if( viewDef->irradianceImage ) - { - viewDef->irradianceImage->Bind(); - } - else - { - globalImages->defaultUACIrradianceCube->Bind(); - } + currentSpace->irradianceAtlasImage->Bind(); GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE1 ); if( viewDef->radianceImage ) diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index 17910cbe..648d9f5e 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -450,6 +450,15 @@ struct viewEntity_t // be linked to the lights or added to the drawsurf list in a serial code section drawSurf_t* drawSurfs; + // RB: use light grid of the best area this entity is in + bool useLightGrid; + idImage* irradianceAtlasImage; + + idVec3 lightGridOrigin; + idVec3 lightGridSize; + int lightGridBounds[3]; + // RB end + // R_AddSingleModel will build a chain of parameters here to setup shadow volumes staticShadowVolumeParms_t* staticShadowVolumes; dynamicShadowVolumeParms_t* dynamicShadowVolumes; @@ -636,13 +645,6 @@ struct viewDef_t idRenderMatrix inverseBaseEnvProbeProject; // the matrix for deforming the 'zeroOneCubeModel' to exactly cover the environent probe volume in world space idImage* irradianceImage; // cubemap image used for diffuse IBL by backend idImage* radianceImage; // cubemap image used for specular IBL by backend - - // lightGrid - bool useLightGrid; - idVec3 lightGridOrigin; - idVec3 lightGridSize; - int lightGridBounds[3]; - // RB end }; diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index 0cd0f58e..2fc4b16a 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -5573,7 +5573,7 @@ static const cgShaderDef_t cg_renderprogs[] = " totalFactor += factor;\n" " }\n" "\n" - " if( totalFactor > 0 && totalFactor < 0.99 )\n" + " if( totalFactor > 0.0 && totalFactor < 0.9999 )\n" " {\n" " totalFactor = 1.0f / totalFactor;\n" "\n" @@ -5609,7 +5609,7 @@ static const cgShaderDef_t cg_renderprogs[] = " float specAO = ComputeSpecularAO( vDotN, ao, roughness );\n" " float3 specularLight = radiance * ( kS * envBRDF.x + float3( envBRDF.y ) ) * specAO * ( rpSpecularModifier.xyz * 0.5 );\n" "\n" - "#if 0\n" + "#if 1\n" " // Marmoset Horizon Fade trick\n" " const half horizonFade = 1.3;\n" " half horiz = saturate( 1.0 + horizonFade * saturate( dot3( reflectionVector, globalNormal ) ) );\n" @@ -5622,7 +5622,7 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.color.rgb = diffuseLight;\n" " //result.color.rgb = diffuseLight * lightColor;\n" " //result.color.rgb = specularLight;\n" - " result.color.rgb = ( diffuseLight + specularLight ) * lightColor * fragment.color.rgb;\n" + " result.color.rgb = ( diffuseLight + specularLight * horiz ) * lightColor * fragment.color.rgb;\n" " //result.color.rgb = localNormal.xyz * 0.5 + 0.5;\n" " //result.color.rgb = float3( ao );\n" " result.color.w = fragment.color.a;\n" diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index bb6ef4d2..df9c303c 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -88,25 +88,25 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con idLib::Printf( "area %i %9u x %" PRIuSIZE " = lightGridSize = (%.2fMB)\n", area, numGridPoints, sizeof( lightGridPoint_t ), ( float )( lightGridPoints.MemoryUsed() ) / ( 1024.0f * 1024.0f ) ); CalculateLightGridPointPositions( world, area ); - } - // try to load existing lightgrid data + // try to load existing lightgrid data #if 1 - idStr basename = mapName; - basename.StripFileExtension(); + idStr basename = mapName; + basename.StripFileExtension(); - idStr fullname; + idStr fullname; - fullname.Format( "env/%s/area%i_lightgrid_amb", basename.c_str(), area ); - irradianceImage = globalImages->ImageFromFile( fullname, TF_NEAREST, TR_CLAMP, TD_R11G11B10F, CF_2D ); + fullname.Format( "env/%s/area%i_lightgrid_amb", basename.c_str(), area ); + irradianceImage = globalImages->ImageFromFile( fullname, TF_NEAREST, TR_CLAMP, TD_R11G11B10F, CF_2D ); #else - for( int i = 0; i < lightGridPoints.Num(); i++ ) - { - lightGridPoint_t* gridPoint = &lightGridPoints[i]; + for( int i = 0; i < lightGridPoints.Num(); i++ ) + { + lightGridPoint_t* gridPoint = &lightGridPoints[i]; - gridPoint->irradianceImage = NULL; - } + gridPoint->irradianceImage = NULL; + } #endif + } } void LightGrid::GetBaseGridCoord( const idVec3& origin, int gridCoord[3] ) @@ -634,6 +634,12 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) static const char* envDirection[6] = { "_px", "_nx", "_py", "_ny", "_pz", "_nz" }; + if( args.Argc() != 1 && args.Argc() != 2 ) + { + common->Printf( "USAGE: generateLightData [limit] (limit is max probes per BSP area)\n" ); + return; + } + if( !tr.primaryWorld ) { common->Printf( "No primary world loaded.\n" ); @@ -654,6 +660,14 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) return; } + int limit = MAX_AREA_LIGHTGRID_POINTS; + if( args.Argc() >= 2 ) + { + limit = atoi( args.Argv( 1 ) ); + } + + idLib::Printf( "Using limit = %i\n", limit ); + const viewDef_t primary = *tr.primaryView; //-------------------------------------------- @@ -670,7 +684,7 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) } */ -#if 1 +#if 0 int a = tr.primaryWorld->PointInArea( tr.primaryView->renderView.vieworg ); if( a == -1 ) { @@ -682,9 +696,15 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) { portalArea_t* area = &tr.primaryWorld->portalAreas[a]; - idLib::Printf( "Shooting %i grid probes area %i...\n\n", area->lightGrid.lightGridPoints.Num(), a ); + int numGridPoints = Min( area->lightGrid.lightGridPoints.Num(), limit ); + if( numGridPoints == 0 ) + { + continue; + } - CommandlineProgressBar progressBar( area->lightGrid.lightGridPoints.Num() ); + idLib::Printf( "Shooting %i grid probes area %i...\n", numGridPoints, a ); + + CommandlineProgressBar progressBar( numGridPoints ); if( !useThreads ) { progressBar.Start(); @@ -711,7 +731,7 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) gridCoord[2] = k; lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[ gridCoord[0] * gridStep[0] + gridCoord[1] * gridStep[1] + gridCoord[2] * gridStep[2] ]; - if( !gridPoint->valid ) + if( !gridPoint->valid || ( tr.lightGridJobs.Num() >= limit ) ) { progressBar.Increment(); continue; diff --git a/neo/renderer/RenderWorld_local.h b/neo/renderer/RenderWorld_local.h index 11bb9e13..2ab9038e 100644 --- a/neo/renderer/RenderWorld_local.h +++ b/neo/renderer/RenderWorld_local.h @@ -71,6 +71,9 @@ struct lightGridPoint_t class LightGrid { +private: + idImage* irradianceImage; + public: idVec3 lightGridOrigin; idVec3 lightGridSize; @@ -81,8 +84,6 @@ public: idList lightGridPoints; int validGridPoints; - idImage* irradianceImage; - LightGrid(); // setup light grid for given world bounds @@ -96,6 +97,11 @@ public: idVec3 GetGridCoordDebugColor( int gridCoord[3] ); idVec3 GetProbeIndexDebugColor( const int probeIndex ); + idImage* GetIrradianceImage() const + { + return irradianceImage; + } + // fetch grid lighting on a per object basis void SetupEntityGridLighting( idRenderEntityLocal* def ); diff --git a/neo/renderer/tr_frontend_addmodels.cpp b/neo/renderer/tr_frontend_addmodels.cpp index 3d09e054..7affc283 100644 --- a/neo/renderer/tr_frontend_addmodels.cpp +++ b/neo/renderer/tr_frontend_addmodels.cpp @@ -373,6 +373,9 @@ void R_AddSingleModel( viewEntity_t* vEntity ) vEntity->staticShadowVolumes = NULL; vEntity->dynamicShadowVolumes = NULL; + // RB + vEntity->useLightGrid = false; + // globals we really should pass in... const viewDef_t* viewDef = tr.viewDef; @@ -549,6 +552,30 @@ void R_AddSingleModel( viewEntity_t* vEntity ) } } + // RB: use first valid lightgrid + for( areaReference_t* ref = entityDef->entityRefs; ref != NULL; ref = ref->ownerNext ) + { + idImage* lightGridImage = ref->area->lightGrid.GetIrradianceImage(); + + if( ref->area->lightGrid.lightGridPoints.Num() && lightGridImage && !lightGridImage->IsDefaulted() ) + { + vEntity->useLightGrid = true; + vEntity->irradianceAtlasImage = lightGridImage; + + for( int i = 0; i < 3; i++ ) + { + vEntity->lightGridOrigin[i] = ref->area->lightGrid.lightGridOrigin[i]; + vEntity->lightGridSize[i] = ref->area->lightGrid.lightGridSize[i]; + vEntity->lightGridBounds[i] = ref->area->lightGrid.lightGridBounds[i]; + } + + break; + } + } + + + // RB end + //--------------------------- // copy matrix related stuff for back-end use // and setup a render matrix for faster culling diff --git a/neo/renderer/tr_frontend_main.cpp b/neo/renderer/tr_frontend_main.cpp index 5adfb5f3..54d17e19 100644 --- a/neo/renderer/tr_frontend_main.cpp +++ b/neo/renderer/tr_frontend_main.cpp @@ -549,22 +549,6 @@ void R_RenderView( viewDef_t* parms ) tr.viewDef->irradianceImage = globalImages->defaultUACIrradianceCube; tr.viewDef->radianceImage = globalImages->defaultUACRadianceCube; - bool useLightGrid = tr.viewDef->useLightGrid = false; - - portalArea_t* area = &tr.primaryWorld->portalAreas[tr.viewDef->areaNum]; - if( area->lightGrid.irradianceImage && !area->lightGrid.irradianceImage->IsDefaulted() ) - { - tr.viewDef->irradianceImage = area->lightGrid.irradianceImage; - tr.viewDef->useLightGrid = useLightGrid = true; - - for( int i = 0; i < 3; i++ ) - { - tr.viewDef->lightGridOrigin[i] = area->lightGrid.lightGridOrigin[i]; - tr.viewDef->lightGridSize[i] = area->lightGrid.lightGridSize[i]; - tr.viewDef->lightGridBounds[i] = area->lightGrid.lightGridBounds[i]; - } - } - for( viewEnvprobe_t* vProbe = tr.viewDef->viewEnvprobes; vProbe != NULL; vProbe = vProbe->next ) { float dist = ( tr.viewDef->renderView.vieworg - vProbe->globalOrigin ).Length(); @@ -574,10 +558,7 @@ void R_RenderView( viewDef_t* parms ) { tr.viewDef->globalProbeBounds = vProbe->globalProbeBounds; - if( !useLightGrid ) - { - tr.viewDef->irradianceImage = vProbe->irradianceImage; - } + tr.viewDef->irradianceImage = vProbe->irradianceImage; tr.viewDef->radianceImage = vProbe->radianceImage; bestDist = dist; From 36e7b2e86ecc7369e3ba7fac48044c139a1a256d Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Fri, 16 Apr 2021 10:37:12 +0200 Subject: [PATCH 12/26] Skip entire area if lightgrid count exceeds limit --- neo/renderer/RenderWorld_lightgrid.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index df9c303c..70f0dbae 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -696,8 +696,11 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) { portalArea_t* area = &tr.primaryWorld->portalAreas[a]; - int numGridPoints = Min( area->lightGrid.lightGridPoints.Num(), limit ); - if( numGridPoints == 0 ) + //int numGridPoints = Min( area->lightGrid.lightGridPoints.Num(), limit ); + //if( numGridPoints == 0 ) + + int numGridPoints = area->lightGrid.lightGridPoints.Num(); + if( numGridPoints == 0 || numGridPoints > limit ) { continue; } From b0238772a848c76b92663bb911b86345e7266f1a Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Fri, 16 Apr 2021 13:21:43 +0200 Subject: [PATCH 13/26] It's now bakeEnvironmentProbes and bakeLightGrids --- neo/renderer/OpenGL/RenderDebug_GL.cpp | 153 ++++++++++++++----------- neo/renderer/RenderWorld_envprobes.cpp | 2 +- neo/renderer/RenderWorld_lightgrid.cpp | 4 +- 3 files changed, 89 insertions(+), 70 deletions(-) diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index 37ee6bc0..1dc900b5 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1801,110 +1801,127 @@ void idRenderBackend::DBG_ShowLightGrid() idMat3 axis; axis.Identity(); - //for( int a = 0; a < tr.primaryWorld->NumAreas(); a++ ) - // only show current area - int a = tr.primaryWorld->PointInArea( viewDef->renderView.vieworg ); - if( a == -1 ) + int cameraArea = tr.primaryWorld->PointInArea( viewDef->renderView.vieworg ); + if( cameraArea == -1 && r_showLightGrid.GetInteger() < 3 ) { return; } - portalArea_t* area = &tr.primaryWorld->portalAreas[a]; - const int numColors = 7; static idVec4 colors[numColors] = { colorBlack, colorBlue, colorCyan, colorGreen, colorYellow, colorRed, colorWhite }; - // use rpGlobalLightOrigin for lightGrid center - idVec4 lightGridOrigin( area->lightGrid.lightGridOrigin.x, area->lightGrid.lightGridOrigin.y, area->lightGrid.lightGridOrigin.z, 1.0f ); - idVec4 lightGridSize( area->lightGrid.lightGridSize.x, area->lightGrid.lightGridSize.y, area->lightGrid.lightGridSize.z, 1.0f ); - idVec4 lightGridBounds( area->lightGrid.lightGridBounds[0], area->lightGrid.lightGridBounds[1], area->lightGrid.lightGridBounds[2], 1.0f ); - - renderProgManager.SetUniformValue( RENDERPARM_GLOBALLIGHTORIGIN, lightGridOrigin.ToFloatPtr() ); - renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXSCALE, lightGridSize.ToFloatPtr() ); - renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXOFFSET, lightGridBounds.ToFloatPtr() ); - - for( int i = 0; i < area->lightGrid.lightGridPoints.Num(); i++ ) + for( int a = 0; a < tr.primaryWorld->NumAreas(); a++ ) { - lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i]; - if( !gridPoint->valid ) + if( r_showLightGrid.GetInteger() < 3 && ( cameraArea != a ) ) { continue; } - idVec3 distanceToCam = gridPoint->origin - viewDef->renderView.vieworg; - if( distanceToCam.LengthSqr() > ( 1024 * 1024 ) ) + portalArea_t* area = &tr.primaryWorld->portalAreas[a]; + + // use rpGlobalLightOrigin for lightGrid center + idVec4 lightGridOrigin( area->lightGrid.lightGridOrigin.x, area->lightGrid.lightGridOrigin.y, area->lightGrid.lightGridOrigin.z, 1.0f ); + idVec4 lightGridSize( area->lightGrid.lightGridSize.x, area->lightGrid.lightGridSize.y, area->lightGrid.lightGridSize.z, 1.0f ); + idVec4 lightGridBounds( area->lightGrid.lightGridBounds[0], area->lightGrid.lightGridBounds[1], area->lightGrid.lightGridBounds[2], 1.0f ); + + renderProgManager.SetUniformValue( RENDERPARM_GLOBALLIGHTORIGIN, lightGridOrigin.ToFloatPtr() ); + renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXSCALE, lightGridSize.ToFloatPtr() ); + renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXOFFSET, lightGridBounds.ToFloatPtr() ); + + for( int i = 0; i < area->lightGrid.lightGridPoints.Num(); i++ ) { - continue; - } + lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i]; + if( !gridPoint->valid ) + { + continue; + } + + idVec3 distanceToCam = gridPoint->origin - viewDef->renderView.vieworg; + if( distanceToCam.LengthSqr() > ( 1024 * 1024 ) && r_showLightGrid.GetInteger() < 3 ) + { + continue; + } #if 0 - if( i > 53 ) - { - break; - } + if( i > 53 ) + { + break; + } #endif - // move center into the cube so we can void using negative results with GetBaseGridCoord - idVec3 gridPointOrigin = gridPoint->origin + idVec3( 4, 4, 4 ); + // move center into the cube so we can void using negative results with GetBaseGridCoord + idVec3 gridPointOrigin = gridPoint->origin + idVec3( 4, 4, 4 ); - idVec4 localViewOrigin( 1.0f ); - idVec4 globalViewOrigin; - globalViewOrigin.x = viewDef->renderView.vieworg.x; - globalViewOrigin.y = viewDef->renderView.vieworg.y; - globalViewOrigin.z = viewDef->renderView.vieworg.z; - globalViewOrigin.w = 1.0f; + idVec4 localViewOrigin( 1.0f ); + idVec4 globalViewOrigin; + globalViewOrigin.x = viewDef->renderView.vieworg.x; + globalViewOrigin.y = viewDef->renderView.vieworg.y; + globalViewOrigin.z = viewDef->renderView.vieworg.z; + globalViewOrigin.w = 1.0f; - float modelMatrix[16]; - R_AxisToModelMatrix( axis, gridPointOrigin, modelMatrix ); + float modelMatrix[16]; + R_AxisToModelMatrix( axis, gridPointOrigin, modelMatrix ); - R_GlobalPointToLocal( modelMatrix, viewDef->renderView.vieworg, localViewOrigin.ToVec3() ); + R_GlobalPointToLocal( modelMatrix, viewDef->renderView.vieworg, localViewOrigin.ToVec3() ); - renderProgManager.SetUniformValue( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); // rpLocalViewOrigin + renderProgManager.SetUniformValue( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); // rpLocalViewOrigin - // RB: if we want to get the normals in world space so we need the model -> world matrix - idRenderMatrix modelMatrix2; - idRenderMatrix::Transpose( *( idRenderMatrix* )modelMatrix, modelMatrix2 ); + // RB: if we want to get the normals in world space so we need the model -> world matrix + idRenderMatrix modelMatrix2; + idRenderMatrix::Transpose( *( idRenderMatrix* )modelMatrix, modelMatrix2 ); - renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_X, &modelMatrix2[0][0] ); - renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_Y, &modelMatrix2[1][0] ); - renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_Z, &modelMatrix2[2][0] ); - renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_W, &modelMatrix2[3][0] ); + renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_X, &modelMatrix2[0][0] ); + renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_Y, &modelMatrix2[1][0] ); + renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_Z, &modelMatrix2[2][0] ); + renderProgManager.SetUniformValue( RENDERPARM_MODELMATRIX_W, &modelMatrix2[3][0] ); #if 0 - renderProgManager.BindShader_Color(); + renderProgManager.BindShader_Color(); - int gridCoord[3]; - area->lightGrid.GetBaseGridCoord( gridPoint->origin, gridCoord ); + int gridCoord[3]; + area->lightGrid.GetBaseGridCoord( gridPoint->origin, gridCoord ); - idVec3 color = area->lightGrid.GetGridCoordDebugColor( gridCoord ); - //idVec3 color = area->lightGrid.GetProbeIndexDebugColor( i ); - //idVec4 color = colors[ i % numColors ]; - GL_Color( color ); + idVec3 color = area->lightGrid.GetGridCoordDebugColor( gridCoord ); + //idVec3 color = area->lightGrid.GetProbeIndexDebugColor( i ); + //idVec4 color = colors[ i % numColors ]; + GL_Color( color ); #else - renderProgManager.BindShader_DebugLightGrid(); - GL_SelectTexture( 0 ); - area->lightGrid.GetIrradianceImage()->Bind(); + if( r_showLightGrid.GetInteger() == 4 ) + { + renderProgManager.BindShader_Color(); + + idVec4 color = colors[ a % numColors ]; + GL_Color( color ); + } + else + { + renderProgManager.BindShader_DebugLightGrid(); + + GL_SelectTexture( 0 ); + area->lightGrid.GetIrradianceImage()->Bind(); + } #endif - idRenderMatrix modelRenderMatrix; - idRenderMatrix::CreateFromOriginAxis( gridPoint->origin, axis, modelRenderMatrix ); + idRenderMatrix modelRenderMatrix; + idRenderMatrix::CreateFromOriginAxis( gridPoint->origin, axis, modelRenderMatrix ); - // calculate the matrix that transforms the unit cube to exactly cover the model in world space - const float size = 3.0f; - idBounds debugBounds( idVec3( -size ), idVec3( size ) ); + // calculate the matrix that transforms the unit cube to exactly cover the model in world space + const float size = 3.0f; + idBounds debugBounds( idVec3( -size ), idVec3( size ) ); - idRenderMatrix inverseBaseModelProject; - idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject ); + idRenderMatrix inverseBaseModelProject; + idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject ); - idRenderMatrix invProjectMVPMatrix; - idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix ); - RB_SetMVP( invProjectMVPMatrix ); + idRenderMatrix invProjectMVPMatrix; + idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix ); + RB_SetMVP( invProjectMVPMatrix ); - DrawElementsWithCounters( &zeroOneSphereSurface ); - //DrawElementsWithCounters( &zeroOneCubeSurface ); + DrawElementsWithCounters( &zeroOneSphereSurface ); + //DrawElementsWithCounters( &zeroOneCubeSurface ); + } } if( r_showLightGrid.GetInteger() == 2 ) @@ -1921,6 +1938,8 @@ void idRenderBackend::DBG_ShowLightGrid() int gridStep[3]; float totalFactor; + portalArea_t* area = &tr.primaryWorld->portalAreas[cameraArea]; + renderProgManager.BindShader_Color(); lightOrigin = viewDef->renderView.vieworg; diff --git a/neo/renderer/RenderWorld_envprobes.cpp b/neo/renderer/RenderWorld_envprobes.cpp index a4e034bd..a8f78950 100644 --- a/neo/renderer/RenderWorld_envprobes.cpp +++ b/neo/renderer/RenderWorld_envprobes.cpp @@ -974,7 +974,7 @@ void R_MakeAmbientMap( const char* baseName, const char* suffix, int outSize, bo } } -CONSOLE_COMMAND( generateEnvironmentProbes, "Generate environment probes", NULL ) +CONSOLE_COMMAND( bakeEnvironmentProbes, "Bake environment probes", NULL ) { idStr fullname; idStr baseName; diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 70f0dbae..9df45030 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -623,7 +623,7 @@ void R_MakeAmbientGridPoint( const char* baseName, const char* suffix, int outSi } #endif -CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) +CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) { idStr baseName; idStr filename; @@ -636,7 +636,7 @@ CONSOLE_COMMAND( generateLightGrid, "Generate light grid data", NULL ) if( args.Argc() != 1 && args.Argc() != 2 ) { - common->Printf( "USAGE: generateLightData [limit] (limit is max probes per BSP area)\n" ); + common->Printf( "USAGE: bakeLightGrids [limit] (limit is max probes per BSP area)\n" ); return; } From 5c03286448a7a831a30ca9dc99e3c331ea47ea7a Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Fri, 16 Apr 2021 21:16:44 +0200 Subject: [PATCH 14/26] Move light grid sampling origins around if in solid like q3map1 did --- .../lighting/ambient_lightgrid_IBL.ps.hlsl | 17 ++-- neo/renderer/OpenGL/RenderDebug_GL.cpp | 17 +++- neo/renderer/RenderCommon.h | 2 +- neo/renderer/RenderProgs_embedded.h | 17 ++-- neo/renderer/RenderWorld_lightgrid.cpp | 82 +++++++++++++++++-- 5 files changed, 114 insertions(+), 21 deletions(-) diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl index 91d4622e..365cc2f2 100644 --- a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl @@ -263,7 +263,7 @@ void main( PS_IN fragment, out PS_OUT result ) { float v; - v = lightOrigin[i] * ( 1.0f / lightGridSize[i] ); + v = lightOrigin[i] * ( 1.0 / lightGridSize[i] ); gridCoord[i] = int( floor( v ) ); frac[ i ] = v - gridCoord[ i ]; @@ -314,7 +314,7 @@ void main( PS_IN fragment, out PS_OUT result ) for( int j = 0; j < 3; j++ ) { - if( cornerOffsets[ i ][ j ] > 0.0f ) + if( cornerOffsets[ i ][ j ] > 0.0 ) { factor *= frac[ j ]; @@ -322,7 +322,7 @@ void main( PS_IN fragment, out PS_OUT result ) } else { - factor *= ( 1.0f - frac[ j ] ); + factor *= ( 1.0 - frac[ j ] ); } } @@ -331,14 +331,21 @@ void main( PS_IN fragment, out PS_OUT result ) atlasOffset.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * invXZ; atlasOffset.y = ( gridCoord2[1] * invY ); - irradiance += tex2D( samp7, normalizedOctCoordZeroOne + atlasOffset ).rgb * factor; + float3 color = tex2D( samp7, normalizedOctCoordZeroOne + atlasOffset ).rgb; + if( ( color.r + color.g + color.b ) < 0.0001 ) + { + // ignore samples in walls + continue; + } + + irradiance += color * factor; totalFactor += factor; } if( totalFactor > 0.0 && totalFactor < 0.9999 ) { - totalFactor = 1.0f / totalFactor; + totalFactor = 1.0 / totalFactor; irradiance *= totalFactor; } diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index 1dc900b5..25fd54ac 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -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-2016 Robert Beckebans +Copyright (C) 2014-2021 Robert Beckebans Copyright (C) 2014-2016 Kot in Action Creative Artel Copyright (C) 2016-2017 Dustin Land @@ -1809,7 +1809,7 @@ void idRenderBackend::DBG_ShowLightGrid() } const int numColors = 7; - static idVec4 colors[numColors] = { colorBlack, colorBlue, colorCyan, colorGreen, colorYellow, colorRed, colorWhite }; + static idVec4 colors[numColors] = { colorBrown, colorBlue, colorCyan, colorGreen, colorYellow, colorRed, colorWhite }; for( int a = 0; a < tr.primaryWorld->NumAreas(); a++ ) { @@ -1832,7 +1832,7 @@ void idRenderBackend::DBG_ShowLightGrid() for( int i = 0; i < area->lightGrid.lightGridPoints.Num(); i++ ) { lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i]; - if( !gridPoint->valid ) + if( !gridPoint->valid && r_showLightGrid.GetInteger() < 3 ) { continue; } @@ -1893,7 +1893,16 @@ void idRenderBackend::DBG_ShowLightGrid() { renderProgManager.BindShader_Color(); - idVec4 color = colors[ a % numColors ]; + idVec4 color; + if( !gridPoint->valid ) + { + color = colorPurple; + } + else + { + color = colors[ a % numColors ]; + } + GL_Color( color ); } else diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index 648d9f5e..e09b51c0 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -518,7 +518,7 @@ static const int LIGHTGRID_IRRADIANCE_SIZE = 32; struct calcLightGridPointParms_t { // input - byte* buffers[6]; // HDR RGB16F standard OpenGL cubemap sides + byte* radiance[6]; // HDR RGB16F standard OpenGL cubemap sides int gridCoord[3]; int outWidth; // LIGHTGRID_IRRADIANCE_SIZE diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index 2fc4b16a..95d68c89 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -5500,7 +5500,7 @@ static const cgShaderDef_t cg_renderprogs[] = " {\n" " float v;\n" "\n" - " v = lightOrigin[i] * ( 1.0f / lightGridSize[i] );\n" + " v = lightOrigin[i] * ( 1.0 / lightGridSize[i] );\n" " gridCoord[i] = int( floor( v ) );\n" " frac[ i ] = v - gridCoord[ i ];\n" "\n" @@ -5551,7 +5551,7 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " for( int j = 0; j < 3; j++ )\n" " {\n" - " if( cornerOffsets[ i ][ j ] > 0.0f )\n" + " if( cornerOffsets[ i ][ j ] > 0.0 )\n" " {\n" " factor *= frac[ j ];\n" "\n" @@ -5559,7 +5559,7 @@ static const cgShaderDef_t cg_renderprogs[] = " }\n" " else\n" " {\n" - " factor *= ( 1.0f - frac[ j ] );\n" + " factor *= ( 1.0 - frac[ j ] );\n" " }\n" " }\n" "\n" @@ -5568,14 +5568,21 @@ static const cgShaderDef_t cg_renderprogs[] = " atlasOffset.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * invXZ;\n" " atlasOffset.y = ( gridCoord2[1] * invY );\n" "\n" - " irradiance += tex2D( samp7, normalizedOctCoordZeroOne + atlasOffset ).rgb * factor;\n" + " float3 color = tex2D( samp7, normalizedOctCoordZeroOne + atlasOffset ).rgb;\n" "\n" + " if( ( color.r + color.g + color.b ) < 0.0001 )\n" + " {\n" + " // ignore samples in walls\n" + " continue;\n" + " }\n" + "\n" + " irradiance += color * factor;\n" " totalFactor += factor;\n" " }\n" "\n" " if( totalFactor > 0.0 && totalFactor < 0.9999 )\n" " {\n" - " totalFactor = 1.0f / totalFactor;\n" + " totalFactor = 1.0 / totalFactor;\n" "\n" " irradiance *= totalFactor;\n" " }\n" diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 9df45030..30d0ba1a 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -32,7 +32,7 @@ If you have questions concerning this license or the applicable additional terms #include "RenderCommon.h" -static const int MAX_LIGHTGRID_ATLAS_SIZE = 4096; +static const int MAX_LIGHTGRID_ATLAS_SIZE = 1024; static const int MAX_AREA_LIGHTGRID_POINTS = ( MAX_LIGHTGRID_ATLAS_SIZE / LIGHTGRID_IRRADIANCE_SIZE ) * ( MAX_LIGHTGRID_ATLAS_SIZE / LIGHTGRID_IRRADIANCE_SIZE ); LightGrid::LightGrid() @@ -266,7 +266,77 @@ void LightGrid::CalculateLightGridPointPositions( const idRenderWorld* world, in gridPoint->valid = ( world->PointInArea( gridPoint->origin ) != -1 ); if( !gridPoint->valid ) { - invalidCount++; + idVec3 origin; + idVec3 baseOrigin; + int step; + + baseOrigin = gridPoint->origin; + + // RB: do what q3map1 did - try to nudge the origin around to find a valid point + for( step = 9; step <= 18; step += 9 ) + { + for( int c = 0; c < 8; c++ ) + { + origin = baseOrigin; + if( c & 1 ) + { + origin[0] += step; + } + else + { + origin[0] -= step; + } + if( c & 2 ) + { + origin[1] += step; + } + else + { + origin[1] -= step; + } + if( c & 4 ) + { + origin[2] += step; + } + else + { + origin[2] -= step; + } + + if( world->PointInArea( origin ) != -1 ) + { + // point is not in the void + gridPoint->valid = true; + gridPoint->origin = origin; + break; + } + } + + if( i != 8 ) + { + break; + } + } + + /* + if( step > 18 ) + { + // can't find a valid point at all + for( i = 0; i < 3; i++ ) + { + gridPoint->ambient[i] = 0; + gridPoint->directed[i] = 0; + } + gridPoint->latLong[0] = 0; + gridPoint->latLong[1] = 0; + return; + } + */ + + if( !gridPoint->valid ) + { + invalidCount++; + } } p++; @@ -369,7 +439,7 @@ void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) for( int i = 0; i < 6; i++ ) { - buffers[ i ] = ( halfFloat_t* ) parms->buffers[ i ]; + buffers[ i ] = ( halfFloat_t* ) parms->radiance[ i ]; } const float invDstSize = 1.0f / float( parms->outHeight ); @@ -760,7 +830,7 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) //tr.TakeScreenshot( size, size, fullname, blends, &ref, EXR ); byte* float16FRGB = tr.CaptureRenderToBuffer( captureSize, captureSize, &ref ); - jobParms->buffers[ side ] = float16FRGB; + jobParms->radiance[ side ] = float16FRGB; #if 0 if( i < 3 ) @@ -859,9 +929,9 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) for( int i = 0; i < 6; i++ ) { - if( job->buffers[i] ) + if( job->radiance[i] ) { - Mem_Free( job->buffers[i] ); + Mem_Free( job->radiance[i] ); } } From cb0e5348043ba69d859db433ba9df2f441f1ed8b Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sat, 17 Apr 2021 21:06:19 +0200 Subject: [PATCH 15/26] First draft of new .lightgrid file format to store volume settings --- neo/framework/DeclManager.cpp | 10 +- neo/renderer/OpenGL/RenderDebug_GL.cpp | 2 +- neo/renderer/RenderCommon.h | 5 +- neo/renderer/RenderWorld_envprobes.cpp | 14 +- neo/renderer/RenderWorld_lightgrid.cpp | 495 +++++++++++++++++++++---- neo/renderer/RenderWorld_local.h | 25 +- 6 files changed, 456 insertions(+), 95 deletions(-) diff --git a/neo/framework/DeclManager.cpp b/neo/framework/DeclManager.cpp index c5fded1d..cc20c193 100644 --- a/neo/framework/DeclManager.cpp +++ b/neo/framework/DeclManager.cpp @@ -2091,15 +2091,15 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args ) bool exportModels = false; - if( !idStr::Icmp( args.Argv( 1 ), "models" ) ) + if( !idStr::Icmp( args.Argv( 1 ), "nomodels" ) ) { - exportModels = true; - common->Printf( "exporting entity decls to FGDs with models:\n" ); + exportModels = false; + common->Printf( "exporting entity decls to FGDs without models:\n" ); } else { - exportModels = false; - common->Printf( "exporting entity decls to FGDs:\n" ); + exportModels = true; + common->Printf( "exporting entity decls to FGDs with models:\n" ); } if( exportModels ) diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index 25fd54ac..c0dcc898 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1889,7 +1889,7 @@ void idRenderBackend::DBG_ShowLightGrid() GL_Color( color ); #else - if( r_showLightGrid.GetInteger() == 4 ) + if( r_showLightGrid.GetInteger() == 4 || !area->lightGrid.GetIrradianceImage() ) { renderProgManager.BindShader_Color(); diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index e09b51c0..fe4dc241 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -525,7 +525,8 @@ struct calcLightGridPointParms_t int outHeight; // output - SphericalHarmonicsT SH4; + SphericalHarmonicsT shRadiance; // L3 Spherical Harmonics + halfFloat_t* outBuffer; // HDR R11G11B11F octahedron LIGHTGRID_IRRADIANCE_SIZE^2 int time; // execution time in milliseconds }; @@ -1447,6 +1448,8 @@ public: void Reset() { count = 0; + tics = 0; + nextTicCount = 0; } }; diff --git a/neo/renderer/RenderWorld_envprobes.cpp b/neo/renderer/RenderWorld_envprobes.cpp index a8f78950..ab3b9981 100644 --- a/neo/renderer/RenderWorld_envprobes.cpp +++ b/neo/renderer/RenderWorld_envprobes.cpp @@ -579,10 +579,10 @@ void CalculateIrradianceJob( calcEnvprobeParms_t* parms ) progressBar.Start(); } - // build L4 Spherical Harmonics from source image - SphericalHarmonicsT shRadiance; + // build L3 Spherical Harmonics from source image + SphericalHarmonicsT shRadiance; - for( int i = 0; i < shSize( 4 ); i++ ) + for( int i = 0; i < shSize( 3 ); i++ ) { shRadiance[i].Zero(); } @@ -664,7 +664,7 @@ void CalculateIrradianceJob( calcEnvprobeParms_t* parms ) float texelArea = CubemapTexelSolidAngle( uu, vv, invDstSize ); - const SphericalHarmonicsT& sh = shEvaluate<4>( dir ); + const SphericalHarmonicsT& sh = shEvaluate<3>( dir ); bool shValid = true; for( int i = 0; i < 25; i++ ) @@ -726,10 +726,10 @@ void CalculateIrradianceJob( calcEnvprobeParms_t* parms ) idVec3 outColor( 0, 0, 0 ); #if 1 - // generate ambient colors by evaluating the L4 Spherical Harmonics - SphericalHarmonicsT shDirection = shEvaluate<4>( dir ); + // generate ambient colors by evaluating the L3 Spherical Harmonics + SphericalHarmonicsT shDirection = shEvaluate<3>( dir ); - idVec3 sampleIrradianceSh = shEvaluateDiffuse( shRadiance, dir ) / idMath::PI; + idVec3 sampleIrradianceSh = shEvaluateDiffuse( shRadiance, dir ) / idMath::PI; outColor[0] = Max( 0.0f, sampleIrradianceSh.x ); outColor[1] = Max( 0.0f, sampleIrradianceSh.y ); diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 30d0ba1a..0bed4604 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -32,21 +32,30 @@ If you have questions concerning this license or the applicable additional terms #include "RenderCommon.h" -static const int MAX_LIGHTGRID_ATLAS_SIZE = 1024; +#define LGRID_FILE_EXT "lightgrid" +#define LGRID_BINARYFILE_EXT "blightgrid" +#define LGRID_FILEID "LGRID" +#define LGRID_FILEVERSION "1.00" + +#define STORE_LIGHTGRID_SHDATA 0 + +static const byte BLGRID_VERSION = 2; +static const unsigned int BLGRID_MAGIC = ( 'P' << 24 ) | ( 'R' << 16 ) | ( 'O' << 8 ) | BLGRID_VERSION; + + + +static const int MAX_LIGHTGRID_ATLAS_SIZE = 2048; static const int MAX_AREA_LIGHTGRID_POINTS = ( MAX_LIGHTGRID_ATLAS_SIZE / LIGHTGRID_IRRADIANCE_SIZE ) * ( MAX_LIGHTGRID_ATLAS_SIZE / LIGHTGRID_IRRADIANCE_SIZE ); LightGrid::LightGrid() { lightGridSize.Set( 64, 64, 128 ); - //lightGridPoints.Clear(); - area = -1; - validGridPoints = 0; irradianceImage = NULL; } -void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, const idRenderWorld* world, int _area ) +void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, const idRenderWorld* world, int _area, int limit ) { //idLib::Printf( "----- SetupLightGrid -----\n" ); @@ -54,12 +63,18 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con lightGridPoints.Clear(); area = _area; - validGridPoints = 0; idVec3 maxs; int j = 0; - int numGridPoints = MAX_AREA_LIGHTGRID_POINTS + 1; - while( numGridPoints > MAX_AREA_LIGHTGRID_POINTS ) + + int maxGridPoints = MAX_AREA_LIGHTGRID_POINTS; + if( limit >= 100 && limit < MAX_AREA_LIGHTGRID_POINTS ) + { + maxGridPoints = limit; + } + + int numGridPoints = maxGridPoints + 1; + while( numGridPoints > maxGridPoints ) { for( int i = 0; i < 3; i++ ) { @@ -70,7 +85,7 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con numGridPoints = lightGridBounds[0] * lightGridBounds[1] * lightGridBounds[2]; - if( numGridPoints > MAX_AREA_LIGHTGRID_POINTS ) + if( numGridPoints > maxGridPoints ) { lightGridSize[ j++ % 3 ] += 16.0f; } @@ -80,32 +95,12 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con { lightGridPoints.SetNum( numGridPoints ); + idLib::Printf( "area %i (%i x %i x %i) = %i grid points \n", area, lightGridBounds[0], lightGridBounds[1], lightGridBounds[2], numGridPoints ); idLib::Printf( "area %i grid size (%i %i %i)\n", area, ( int )lightGridSize[0], ( int )lightGridSize[1], ( int )lightGridSize[2] ); idLib::Printf( "area %i grid bounds (%i %i %i)\n", area, ( int )lightGridBounds[0], ( int )lightGridBounds[1], ( int )lightGridBounds[2] ); - - idLib::Printf( "area %i (%i x %i x %i) = %i grid points \n", area, lightGridBounds[0], lightGridBounds[1], lightGridBounds[2], numGridPoints ); - idLib::Printf( "area %i %9u x %" PRIuSIZE " = lightGridSize = (%.2fMB)\n", area, numGridPoints, sizeof( lightGridPoint_t ), ( float )( lightGridPoints.MemoryUsed() ) / ( 1024.0f * 1024.0f ) ); CalculateLightGridPointPositions( world, area ); - - // try to load existing lightgrid data -#if 1 - idStr basename = mapName; - basename.StripFileExtension(); - - idStr fullname; - - fullname.Format( "env/%s/area%i_lightgrid_amb", basename.c_str(), area ); - irradianceImage = globalImages->ImageFromFile( fullname, TF_NEAREST, TR_CLAMP, TD_R11G11B10F, CF_2D ); -#else - for( int i = 0; i < lightGridPoints.Num(); i++ ) - { - lightGridPoint_t* gridPoint = &lightGridPoints[i]; - - gridPoint->irradianceImage = NULL; - } -#endif } } @@ -271,7 +266,7 @@ void LightGrid::CalculateLightGridPointPositions( const idRenderWorld* world, in int step; baseOrigin = gridPoint->origin; - +#if 1 // RB: do what q3map1 did - try to nudge the origin around to find a valid point for( step = 9; step <= 18; step += 9 ) { @@ -317,6 +312,7 @@ void LightGrid::CalculateLightGridPointPositions( const idRenderWorld* world, in break; } } +#endif /* if( step > 18 ) @@ -344,7 +340,7 @@ void LightGrid::CalculateLightGridPointPositions( const idRenderWorld* world, in } } - validGridPoints = p - invalidCount; + //validGridPoints = p - invalidCount; idLib::Printf( "area %i: %i of %i grid points in empty space (%.2f%%)\n", area, invalidCount, lightGridPoints.Num(), ( ( float ) invalidCount / lightGridPoints.Num() ) * 100 ); } @@ -353,19 +349,375 @@ void idRenderWorldLocal::SetupLightGrid() { idLib::Printf( "----- SetupLightGrid -----\n" ); - int totalGridPoints = 0; + idStrStatic< MAX_OSPATH > baseName = mapName; + baseName.StripFileExtension(); + + idStr filename; + filename.Format( "%s.lightgrid", baseName.c_str() ); + bool loaded = LoadLightGridFile( filename ); + if( loaded ) + { + // try to load existing lightgrid image data + for( int i = 0; i < numPortalAreas; i++ ) + { + portalArea_t* area = &portalAreas[i]; + + filename.Format( "env/%s/area%i_lightgrid_amb", baseName.c_str(), i ); + area->lightGrid.irradianceImage = globalImages->ImageFromFile( filename, TF_NEAREST, TR_CLAMP, TD_R11G11B10F, CF_2D ); + } + } + else + { + for( int i = 0; i < numPortalAreas; i++ ) + { + portalArea_t* area = &portalAreas[i]; + + area->lightGrid.SetupLightGrid( area->globalBounds, mapName, this, i, -1 ); + } + } +} + +/* +=============================================================================== + +Reading / Writing of light grids files + +=============================================================================== +*/ + +void idRenderWorldLocal::WriteLightGridsToFile( const char* filename ) +{ + idFile* fp; + idStr name; + + name = filename; + name.SetFileExtension( LGRID_FILE_EXT ); + + common->Printf( "writing %s\n", name.c_str() ); + fp = fileSystem->OpenFileWrite( name, "fs_basepath" ); + if( !fp ) + { + common->Warning( "idCollisionModelManagerLocal::WriteCollisionModelsToFile: Error opening file %s\n", name.c_str() ); + return; + } + + // write file id and version + fp->WriteFloatString( "%s \"%s\"\n\n", LGRID_FILEID, LGRID_FILEVERSION ); + + // write the map file crc + //fp->WriteFloatString( "%u\n\n", mapFileCRC ); + for( int i = 0; i < numPortalAreas; i++ ) { portalArea_t* area = &portalAreas[i]; - area->lightGrid.SetupLightGrid( area->globalBounds, mapName, this, i ); - - totalGridPoints += area->lightGrid.validGridPoints; + WriteLightGrid( fp, area->lightGrid ); } - idLib::Printf( "total valid light grid points %i\n", totalGridPoints ); + fileSystem->CloseFile( fp ); } +void idRenderWorldLocal::WriteLightGrid( idFile* fp, const LightGrid& lightGrid ) +{ + fp->WriteFloatString( "lightGridPoints { /* area = */ %i /* numLightGridPoints = */ %i\n", lightGrid.area, lightGrid.lightGridPoints.Num() ); + + fp->WriteFloatString( "/* gridMins */ " ); + fp->WriteFloatString( "\t ( %f %f %f )\n", lightGrid.lightGridOrigin[0], lightGrid.lightGridOrigin[1], lightGrid.lightGridOrigin[2] ); + + fp->WriteFloatString( "/* gridSize */ " ); + fp->WriteFloatString( "\t ( %f %f %f )\n", lightGrid.lightGridSize[0], lightGrid.lightGridSize[1], lightGrid.lightGridSize[2] ); + + fp->WriteFloatString( "/* gridBounds */ " ); + fp->WriteFloatString( "%i %i %i\n\n", lightGrid.lightGridBounds[0], lightGrid.lightGridBounds[1], lightGrid.lightGridBounds[2] ); + + for( int i = 0 ; i < lightGrid.lightGridPoints.Num() ; i++ ) + { + 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] ); + +#if STORE_LIGHTGRID_SHDATA + // spherical harmonic + fp->WriteFloatString( "( " ); + + for( int j = 0; j < shSize( 3 ); j++ ) + { + fp->WriteFloatString( "%f %f %f ", gridPoint->shRadiance[j][0], gridPoint->shRadiance[j][1], gridPoint->shRadiance[j][2] ); + } + + fp->WriteFloatString( ")\n" ); +#endif + } + + fp->WriteFloatString( "}\n\n" ); +} + + +bool idRenderWorldLocal::LoadLightGridFile( const char* name ) +{ + idToken token; + idLexer* src; + //unsigned int crc; + + // load it + idStrStatic< MAX_OSPATH > fileName = name; + + // check for generated file + idStrStatic< MAX_OSPATH > generatedFileName = fileName; + generatedFileName.Insert( "generated/", 0 ); + generatedFileName.SetFileExtension( LGRID_BINARYFILE_EXT ); + + // if we are reloading the same map, check the timestamp + // and try to skip all the work + ID_TIME_T currentTimeStamp = fileSystem->GetTimestamp( fileName ); + + // see if we have a generated version of this + bool loaded = false; + +#if 1 + idFileLocal file( fileSystem->OpenFileReadMemory( generatedFileName ) ); + if( file != NULL ) + { + int numEntries = 0; + //int magic = 0; + file->ReadBig( numEntries ); + //file->ReadString( mapName ); + //file->ReadBig( crc ); + idStrStatic< 32 > fileID; + idStrStatic< 32 > fileVersion; + file->ReadString( fileID ); + file->ReadString( fileVersion ); + if( fileID == LGRID_FILEID && fileVersion == LGRID_FILEVERSION ) //&& crc == mapFileCRC && numEntries > 0 ) + { + loaded = true; + for( int i = 0; i < numEntries; i++ ) + { + idStrStatic< MAX_OSPATH > type; + file->ReadString( type ); + type.ToLower(); + + if( type == "lightgridpoints" ) + { + ReadBinaryLightGridPoints( file ); + } + else + { + idLib::Error( "Binary proc file failed, unexpected type %s\n", type.c_str() ); + } + } + } + } +#endif + + if( !loaded ) + { + fileName.SetFileExtension( LGRID_FILE_EXT ); + src = new( TAG_RENDER ) idLexer( fileName, LEXFL_NOSTRINGCONCAT | LEXFL_NODOLLARPRECOMPILE ); + if( !src->IsLoaded() ) + { + delete src; + return false; + } + + int numEntries = 0; + idFileLocal outputFile( fileSystem->OpenFileWrite( generatedFileName, "fs_basepath" ) ); + if( outputFile != NULL ) + { + outputFile->WriteBig( numEntries ); + //outputFile->WriteString( mapName ); + //outputFile->WriteBig( mapFileCRC ); + outputFile->WriteString( LGRID_FILEID ); + outputFile->WriteString( LGRID_FILEVERSION ); + } + + if( !src->ExpectTokenString( LGRID_FILEID ) ) + { + common->Warning( "%s is not an CM file.", fileName.c_str() ); + delete src; + return false; + } + + if( !src->ReadToken( &token ) || token != LGRID_FILEVERSION ) + { + common->Warning( "%s has version %s instead of %s", fileName.c_str(), token.c_str(), LGRID_FILEVERSION ); + delete src; + return false; + } + + //if( !src->ExpectTokenType( TT_NUMBER, TT_INTEGER, &token ) ) + //{ + // common->Warning( "%s has no map file CRC", fileName.c_str() ); + // delete src; + // return false; + //} + + //crc = token.GetUnsignedLongValue(); + //if( mapFileCRC && crc != mapFileCRC ) + //{ + // common->Printf( "%s is out of date\n", fileName.c_str() ); + // delete src; + // return false; + //} + + // parse the file + while( 1 ) + { + if( !src->ReadToken( &token ) ) + { + break; + } + + if( token == "lightGridPoints" ) + { + ParseLightGridPoints( src, outputFile ); + + numEntries++; + continue; + } + + src->Error( "idRenderWorldLocal::LoadLightGridFile: bad token \"%s\"", token.c_str() ); + } + + delete src; + + if( outputFile != NULL ) + { + outputFile->Seek( 0, FS_SEEK_SET ); + outputFile->WriteBig( numEntries ); + } + } + + return true; +} + +void idRenderWorldLocal::ParseLightGridPoints( idLexer* src, idFile* fileOut ) +{ + src->ExpectTokenString( "{" ); + + int areaIndex = src->ParseInt(); + if( areaIndex < 0 || areaIndex >= NumAreas() ) + { + src->Error( "ParseLightGridPoints: bad area index %i", areaIndex ); + return; + } + + int numLightGridPoints = src->ParseInt(); + if( numLightGridPoints < 0 ) + { + src->Error( "ParseLightGridPoints: bad numLightGridPoints" ); + return; + } + + if( fileOut != NULL ) + { + // write out the type so the binary reader knows what to instantiate + fileOut->WriteString( "lightGridPoints" ); + } + + portalArea_t* area = &portalAreas[areaIndex]; + area->lightGrid.area = areaIndex; + + // gridMins + src->Parse1DMatrix( 3, area->lightGrid.lightGridOrigin.ToFloatPtr() ); + src->Parse1DMatrix( 3, area->lightGrid.lightGridSize.ToFloatPtr() ); + for( int i = 0; i < 3; i++ ) + { + area->lightGrid.lightGridBounds[i] = src->ParseInt(); + } + + area->lightGrid.lightGridPoints.SetNum( numLightGridPoints ); + + idLib::Printf( "area %i (%i x %i x %i) = %i grid points \n", areaIndex, area->lightGrid.lightGridBounds[0], area->lightGrid.lightGridBounds[1], area->lightGrid.lightGridBounds[2], numLightGridPoints ); + idLib::Printf( "area %i grid size (%i %i %i)\n", areaIndex, ( int )area->lightGrid.lightGridSize[0], ( int )area->lightGrid.lightGridSize[1], ( int )area->lightGrid.lightGridSize[2] ); + idLib::Printf( "area %i grid bounds (%i %i %i)\n", areaIndex, ( int )area->lightGrid.lightGridBounds[0], ( int )area->lightGrid.lightGridBounds[1], ( int )area->lightGrid.lightGridBounds[2] ); + idLib::Printf( "area %i %9u x %" PRIuSIZE " = lightGridSize = (%.2fMB)\n", areaIndex, numLightGridPoints, sizeof( lightGridPoint_t ), ( float )( area->lightGrid.lightGridPoints.MemoryUsed() ) / ( 1024.0f * 1024.0f ) ); + + if( fileOut != NULL ) + { + fileOut->WriteBig( areaIndex ); + fileOut->WriteBig( numLightGridPoints ); + fileOut->WriteBig( area->lightGrid.lightGridOrigin ); + fileOut->WriteBig( area->lightGrid.lightGridSize ); + fileOut->WriteBigArray( area->lightGrid.lightGridBounds, 3 ); + } + + for( int i = 0; i < numLightGridPoints; i++ ) + { + lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i]; + + gridPoint->valid = src->ParseInt(); + + src->Parse1DMatrix( 3, gridPoint->origin.ToFloatPtr() ); +#if STORE_LIGHTGRID_SHDATA + src->Parse1DMatrix( shSize( 3 ) * 3, gridPoint->shRadiance[0].ToFloatPtr() ); +#endif + + if( fileOut != NULL ) + { + fileOut->WriteBig( gridPoint->valid ); + fileOut->WriteBig( gridPoint->origin ); + +#if STORE_LIGHTGRID_SHDATA + fileOut->WriteBigArray( gridPoint->shRadiance[0].ToFloatPtr(), shSize( 3 ) * 3 ); +#endif + } + } + + src->ExpectTokenString( "}" ); +} + +void idRenderWorldLocal::ReadBinaryLightGridPoints( idFile* file ) +{ + int areaIndex; + file->ReadBig( areaIndex ); + + if( areaIndex < 0 || areaIndex >= NumAreas() ) + { + idLib::Error( "ReadBinaryLightGridPoints: bad area index %i", areaIndex ); + return; + } + + int numLightGridPoints = 0; + file->ReadBig( numLightGridPoints ); + if( numLightGridPoints < 0 ) + { + idLib::Error( "ReadBinaryLightGridPoints: bad numLightGridPoints" ); + return; + } + + portalArea_t* area = &portalAreas[areaIndex]; + area->lightGrid.area = areaIndex; + + // gridMins + file->ReadBig( area->lightGrid.lightGridOrigin ); + file->ReadBig( area->lightGrid.lightGridSize ); + file->ReadBigArray( area->lightGrid.lightGridBounds, 3 ); + + area->lightGrid.lightGridPoints.SetNum( numLightGridPoints ); + + idLib::Printf( "area %i (%i x %i x %i) = %i grid points \n", areaIndex, area->lightGrid.lightGridBounds[0], area->lightGrid.lightGridBounds[1], area->lightGrid.lightGridBounds[2], numLightGridPoints ); + idLib::Printf( "area %i grid size (%i %i %i)\n", areaIndex, ( int )area->lightGrid.lightGridSize[0], ( int )area->lightGrid.lightGridSize[1], ( int )area->lightGrid.lightGridSize[2] ); + idLib::Printf( "area %i grid bounds (%i %i %i)\n", areaIndex, ( int )area->lightGrid.lightGridBounds[0], ( int )area->lightGrid.lightGridBounds[1], ( int )area->lightGrid.lightGridBounds[2] ); + idLib::Printf( "area %i %9u x %" PRIuSIZE " = lightGridSize = (%.2fMB)\n", areaIndex, numLightGridPoints, sizeof( lightGridPoint_t ), ( float )( area->lightGrid.lightGridPoints.MemoryUsed() ) / ( 1024.0f * 1024.0f ) ); + + for( int i = 0; i < numLightGridPoints; i++ ) + { + lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i]; + + file->ReadBig( gridPoint->valid ); + file->ReadBig( gridPoint->origin ); + + //file->ReadBigArray( gridPoint->shRadiance[0].ToFloatPtr(), shSize( 3 ) * 3 ); + } +} + +/* +=============================================================================== + +Baking light grids files + +=============================================================================== +*/ static const char* envDirection[6] = { "_px", "_nx", "_py", "_ny", "_pz", "_nz" }; @@ -448,10 +800,10 @@ void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) const idVec2i sourceImageSize( parms->outHeight, parms->outHeight ); - // build L4 Spherical Harmonics from source image - SphericalHarmonicsT shRadiance; + // build L3 Spherical Harmonics from source image + SphericalHarmonicsT shRadiance; - for( int i = 0; i < shSize( 4 ); i++ ) + for( int i = 0; i < shSize( 3 ); i++ ) { shRadiance[i].Zero(); } @@ -510,8 +862,6 @@ void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) // build SH by iterating over all cubemap pixels - //idVec4 dstRect = R_CalculateMipRect( parms->outHeight, 0 ); - for( int side = 0; side < 6; side++ ) { for( int x = 0; x < sourceImageSize.x; x++ ) @@ -533,10 +883,10 @@ void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) float texelArea = CubemapTexelSolidAngle( uu, vv, invDstSize ); - const SphericalHarmonicsT& sh = shEvaluate<4>( dir ); + const SphericalHarmonicsT& sh = shEvaluate<3>( dir ); bool shValid = true; - for( int i = 0; i < 25; i++ ) + for( int i = 0; i < shSize( 3 ); i++ ) { if( IsNAN( sh[i] ) ) { @@ -555,6 +905,11 @@ void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) #endif + for( int i = 0; i < shSize( 3 ); i++ ) + { + parms->shRadiance[i] = shRadiance[i]; + } + // reset image to black for( int x = 0; x < parms->outWidth; x++ ) { @@ -580,10 +935,10 @@ void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) idVec3 outColor( 0, 0, 0 ); #if 1 - // generate ambient colors by evaluating the L4 Spherical Harmonics - SphericalHarmonicsT shDirection = shEvaluate<4>( dir ); + // generate ambient colors by evaluating the L3 Spherical Harmonics + SphericalHarmonicsT shDirection = shEvaluate<3>( dir ); - idVec3 sampleIrradianceSh = shEvaluateDiffuse( shRadiance, dir ) / idMath::PI; + idVec3 sampleIrradianceSh = shEvaluateDiffuse( shRadiance, dir ) / idMath::PI; outColor[0] = Max( 0.0f, sampleIrradianceSh.x ); outColor[1] = Max( 0.0f, sampleIrradianceSh.y ); @@ -744,33 +1099,25 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) // CAPTURE SCENE LIGHTING TO CUBEMAPS //-------------------------------------------- - /* - int totalGridPoints = 0; - for( int a = 0; a < tr.primaryWorld->NumAreas(); a++ ) - { - portalArea_t* area = &tr.primaryWorld->portalAreas[a]; - totalGridPoints += area->lightGrid.lightGridPoints.Num(); - } - */ - -#if 0 - int a = tr.primaryWorld->PointInArea( tr.primaryView->renderView.vieworg ); - if( a == -1 ) - { - return; - } -#else for( int a = 0; a < tr.primaryWorld->NumAreas(); a++ ) -#endif { portalArea_t* area = &tr.primaryWorld->portalAreas[a]; //int numGridPoints = Min( area->lightGrid.lightGridPoints.Num(), limit ); //if( numGridPoints == 0 ) + //int numGridPoints = area->lightGrid.lightGridPoints.Num(); + //if( numGridPoints == 0 || numGridPoints > limit ) + //{ + // continue; + //} + + area->lightGrid.SetupLightGrid( area->globalBounds, tr.primaryWorld->mapName, tr.primaryWorld, a, limit ); + +#if 1 int numGridPoints = area->lightGrid.lightGridPoints.Num(); - if( numGridPoints == 0 || numGridPoints > limit ) + if( numGridPoints == 0 ) { continue; } @@ -804,7 +1151,7 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) gridCoord[2] = k; lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[ gridCoord[0] * gridStep[0] + gridCoord[1] * gridStep[1] + gridCoord[2] * gridStep[2] ]; - if( !gridPoint->valid || ( tr.lightGridJobs.Num() >= limit ) ) + if( !gridPoint->valid ) { progressBar.Increment(); continue; @@ -909,15 +1256,10 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) { calcLightGridPointParms_t* job = tr.lightGridJobs[ j ]; - //filename.Format( "env/%s/area%i_lightgridpoint%i_amb.exr", baseName.c_str(), a, j ); - //R_WriteEXR( filename.c_str(), ( byte* )job->outBuffer, 3, job->outWidth, job->outHeight, "fs_basepath" ); - for( int x = 0; x < LIGHTGRID_IRRADIANCE_SIZE; x++ ) { for( int y = 0; y < LIGHTGRID_IRRADIANCE_SIZE; y++ ) { - // gridPoint = lightGridPoints[ gridCoord[0] * gridStep[0] + gridCoord[1] * gridStep[1] + gridCoord[2] * gridStep[2] ]; - int xx = x + ( job->gridCoord[0] * gridStep[0] + job->gridCoord[2] * gridStep[1] ) * LIGHTGRID_IRRADIANCE_SIZE; int yy = y + job->gridCoord[1] * LIGHTGRID_IRRADIANCE_SIZE; @@ -927,6 +1269,13 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) } } + // backup SH L3 data + lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[ job->gridCoord[0] * gridStep[0] + job->gridCoord[1] * gridStep[1] + job->gridCoord[2] * gridStep[2] ]; + for( int i = 0; i < shSize( 3 ); i++ ) + { + gridPoint->shRadiance[i] = job->shRadiance[i]; + } + for( int i = 0; i < 6; i++ ) { if( job->radiance[i] ) @@ -949,7 +1298,11 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) end = Sys_Milliseconds(); common->Printf( "computed light grid irradiance for area %i in %5.1f seconds\n\n", a, ( end - start ) * 0.001f ); +#endif } + + filename.Format( "%s.lightgrid", baseName.c_str() ); + tr.primaryWorld->WriteLightGridsToFile( filename ); } #if 0 diff --git a/neo/renderer/RenderWorld_local.h b/neo/renderer/RenderWorld_local.h index 2ab9038e..653425cc 100644 --- a/neo/renderer/RenderWorld_local.h +++ b/neo/renderer/RenderWorld_local.h @@ -64,30 +64,27 @@ typedef struct doublePortal_s struct lightGridPoint_t { idVec3 origin; // not saved to .proc - bool valid; // is not in solid area + byte valid; // is not in the void - SphericalHarmonicsT SH4; + SphericalHarmonicsT shRadiance; // L4 Spherical Harmonics }; class LightGrid { -private: - idImage* irradianceImage; - public: idVec3 lightGridOrigin; idVec3 lightGridSize; int lightGridBounds[3]; - int area; -//public: idList lightGridPoints; - int validGridPoints; + + int area; + idImage* irradianceImage; LightGrid(); // setup light grid for given world bounds - void SetupLightGrid( const idBounds& bounds, const char* baseName, const idRenderWorld* world, int _area ); + void SetupLightGrid( const idBounds& bounds, const char* baseName, const idRenderWorld* world, int _area, int limit ); void GetBaseGridCoord( const idVec3& origin, int gridCoord[3] ); @@ -395,8 +392,16 @@ public: //-------------------------- // RenderWorld_lightgrid.cpp -private: +//private: void SetupLightGrid(); + + void WriteLightGridsToFile( const char* filename ); + void WriteLightGrid( idFile* fp, const LightGrid& lightGrid ); + + bool LoadLightGridFile( const char* name ); + + void ParseLightGridPoints( idLexer* src, idFile* fileOut ); + void ReadBinaryLightGridPoints( idFile* file ); // RB end }; From 6bad4df47ebb075c24cc0bb30851534083b53337 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sat, 17 Apr 2021 21:07:39 +0200 Subject: [PATCH 16/26] Lowered film grain intensity --- base/renderprogs/builtin/post/postprocess.ps.hlsl | 2 +- neo/renderer/RenderProgs_embedded.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base/renderprogs/builtin/post/postprocess.ps.hlsl b/base/renderprogs/builtin/post/postprocess.ps.hlsl index 4945bc08..6f59362f 100644 --- a/base/renderprogs/builtin/post/postprocess.ps.hlsl +++ b/base/renderprogs/builtin/post/postprocess.ps.hlsl @@ -66,7 +66,7 @@ struct PS_OUT #define USE_CAS 0 #define USE_DITHERING 1 -#define Dithering_QuantizationSteps 8.0 // 8.0 = 2 ^ 3 quantization bits +#define Dithering_QuantizationSteps 16.0 // 8.0 = 2 ^ 3 quantization bits #define Dithering_NoiseBoost 1.0 #define Dithering_Wide 1.0 #define DITHER_IN_LINEAR_SPACE 0 diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index 95d68c89..0e411c78 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -8290,7 +8290,7 @@ static const cgShaderDef_t cg_renderprogs[] = "#define USE_CAS 0\n" "\n" "#define USE_DITHERING 1\n" - "#define Dithering_QuantizationSteps 8.0 // 8.0 = 2 ^ 3 quantization bits\n" + "#define Dithering_QuantizationSteps 16.0 // 8.0 = 2 ^ 3 quantization bits\n" "#define Dithering_NoiseBoost 1.0\n" "#define Dithering_Wide 1.0\n" "#define DITHER_IN_LINEAR_SPACE 0\n" From 03c5e0273b7ae91a394df6ccef894a1a5a39ee24 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sun, 18 Apr 2021 21:20:29 +0200 Subject: [PATCH 17/26] Small bugfixes and r_useHDR 1 is now fixed for OpenGL --- .../lighting/ambient_lightgrid_IBL.ps.hlsl | 9 ++++- .../lighting/ambient_lighting_IBL.ps.hlsl | 7 ++-- neo/renderer/OpenGL/Image_GL.cpp | 39 +++++++------------ neo/renderer/OpenGL/RenderBackend_GL.cpp | 35 ----------------- neo/renderer/RenderCommon.h | 9 ++++- neo/renderer/RenderSystem.h | 1 - neo/renderer/RenderSystem_init.cpp | 5 +-- neo/renderer/RenderWorld_lightgrid.cpp | 38 ++++++++++++++++-- neo/renderer/RenderWorld_local.h | 2 + 9 files changed, 73 insertions(+), 72 deletions(-) diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl index 365cc2f2..0a330fcc 100644 --- a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl @@ -150,7 +150,7 @@ void main( PS_IN fragment, out PS_OUT result ) float3 reflectionVector = globalNormal * dot3( globalView, globalNormal ); reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalView ); -#if 1 +#if 0 // parallax box correction using portal area bounds float hitScale = 0.0; float3 bounds[2]; @@ -368,6 +368,12 @@ void main( PS_IN fragment, out PS_OUT result ) float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb; //radiance = float3( 0.0 ); + // RB: HACK dim down room radiance by better local irradiance brightness + //float luma = PhotoLuma( irradiance ); + //float luma = dot( irradiance, LUMINANCE_LINEAR.rgb ); + //float luma = length( irradiance.rgb ); + //radiance *= ( luma * rpSpecularModifier.x * 3.0 ); + float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg; #if 0 @@ -388,6 +394,7 @@ void main( PS_IN fragment, out PS_OUT result ) #endif half3 lightColor = sRGBToLinearRGB( rpAmbientColor.rgb ); + //half3 lightColor = ( rpAmbientColor.rgb ); //result.color.rgb = diffuseLight; //result.color.rgb = diffuseLight * lightColor; diff --git a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl index 981c9ded..582324ec 100644 --- a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl @@ -150,7 +150,7 @@ void main( PS_IN fragment, out PS_OUT result ) float3 reflectionVector = globalNormal * dot3( globalView, globalNormal ); reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalView ); -#if 1 +#if 0 // parallax box correction using portal area bounds float hitScale = 0.0; float3 bounds[2]; @@ -266,7 +266,7 @@ void main( PS_IN fragment, out PS_OUT result ) float specAO = ComputeSpecularAO( vDotN, ao, roughness ); float3 specularLight = radiance * ( kS * envBRDF.x + float3( envBRDF.y ) ) * specAO * ( rpSpecularModifier.xyz * 0.5 ); -#if 0 +#if 1 // Marmoset Horizon Fade trick const half horizonFade = 1.3; half horiz = saturate( 1.0 + horizonFade * saturate( dot3( reflectionVector, globalNormal ) ) ); @@ -275,11 +275,12 @@ void main( PS_IN fragment, out PS_OUT result ) #endif half3 lightColor = sRGBToLinearRGB( rpAmbientColor.rgb ); + //half3 lightColor = ( rpAmbientColor.rgb ); //result.color.rgb = diffuseLight; //result.color.rgb = diffuseLight * lightColor; //result.color.rgb = specularLight; - result.color.rgb = ( diffuseLight + specularLight ) * lightColor * fragment.color.rgb; + result.color.rgb = ( diffuseLight + specularLight * horiz ) * lightColor * fragment.color.rgb; //result.color.rgb = localNormal.xyz * 0.5 + 0.5; //result.color.rgb = float3( ao ); result.color.w = fragment.color.a; diff --git a/neo/renderer/OpenGL/Image_GL.cpp b/neo/renderer/OpenGL/Image_GL.cpp index 80a8dad4..ac447078 100644 --- a/neo/renderer/OpenGL/Image_GL.cpp +++ b/neo/renderer/OpenGL/Image_GL.cpp @@ -615,70 +615,62 @@ void idImage::AllocImage() GL_CheckErrors(); PurgeImage(); - int sRGB = r_useSRGB.GetInteger(); - switch( opts.format ) { case FMT_RGBA8: - //internalFormat = GL_RGBA8; - //internalFormat = ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) ) ? GL_SRGB8_ALPHA8 : GL_RGBA8; - internalFormat = ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) ) ? GL_SRGB8_ALPHA8 : GL_RGBA8; + internalFormat = GL_RGBA8; dataFormat = GL_RGBA; dataType = GL_UNSIGNED_BYTE; break; + case FMT_XRGB8: - internalFormat = ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) ) ? GL_SRGB : GL_RGB; + internalFormat = GL_RGB; dataFormat = GL_RGBA; dataType = GL_UNSIGNED_BYTE; break; + case FMT_RGB565: - //internalFormat = ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) ) ? GL_SRGB : GL_RGB; internalFormat = GL_RGB; dataFormat = GL_RGB; dataType = GL_UNSIGNED_SHORT_5_6_5; break; + case FMT_ALPHA: -#if 1 - if( ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) ) ) - { - internalFormat = GL_SRGB; - dataFormat = GL_RED; - } - else -#endif - { - internalFormat = GL_R8; - dataFormat = GL_RED; - } + internalFormat = GL_R8; + dataFormat = GL_RED; dataType = GL_UNSIGNED_BYTE; break; + case FMT_L8A8: internalFormat = GL_RG8; dataFormat = GL_RG; dataType = GL_UNSIGNED_BYTE; break; + case FMT_LUM8: internalFormat = GL_R8; dataFormat = GL_RED; dataType = GL_UNSIGNED_BYTE; break; + case FMT_INT8: internalFormat = GL_R8; dataFormat = GL_RED; dataType = GL_UNSIGNED_BYTE; break; + case FMT_DXT1: - internalFormat = ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) ) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - //internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; dataFormat = GL_RGBA; dataType = GL_UNSIGNED_BYTE; break; + case FMT_DXT5: - internalFormat = ( glConfig.sRGBFramebufferAvailable && ( sRGB == 1 || sRGB == 3 ) && opts.colorFormat != CFM_YCOCG_DXT5 && opts.colorFormat != CFM_NORMAL_DXT5 ) ? GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - //internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; dataFormat = GL_RGBA; dataType = GL_UNSIGNED_BYTE; break; + case FMT_DEPTH: internalFormat = GL_DEPTH_COMPONENT; dataFormat = GL_DEPTH_COMPONENT; @@ -731,7 +723,6 @@ void idImage::AllocImage() internalFormat = GL_R11F_G11F_B10F; dataFormat = GL_RGB; dataType = GL_UNSIGNED_INT_10F_11F_11F_REV; - //dataType = GL_FLOAT; break; default: diff --git a/neo/renderer/OpenGL/RenderBackend_GL.cpp b/neo/renderer/OpenGL/RenderBackend_GL.cpp index 0329538f..2700a2e1 100644 --- a/neo/renderer/OpenGL/RenderBackend_GL.cpp +++ b/neo/renderer/OpenGL/RenderBackend_GL.cpp @@ -263,10 +263,6 @@ static void R_CheckPortableExtensions() glConfig.seamlessCubeMapAvailable = GLEW_ARB_seamless_cube_map != 0; r_useSeamlessCubeMap.SetModified(); // the CheckCvars() next frame will enable / disable it - // GL_ARB_framebuffer_sRGB - glConfig.sRGBFramebufferAvailable = GLEW_ARB_framebuffer_sRGB != 0; - r_useSRGB.SetModified(); // the CheckCvars() next frame will enable / disable it - // GL_ARB_vertex_buffer_object if( glConfig.driverType == GLDRV_OPENGL_MESA_CORE_PROFILE ) { @@ -1407,21 +1403,6 @@ void idRenderBackend::GL_Clear( bool color, bool depth, bool stencil, byte stenc glClear( clearFlags ); // RB begin - /* - if( r_useHDR.GetBool() && clearHDR && globalFramebuffers.hdrFBO != NULL ) - { - bool isDefaultFramebufferActive = Framebuffer::IsDefaultFramebufferActive(); - - globalFramebuffers.hdrFBO->Bind(); - glClear( clearFlags ); - - if( isDefaultFramebufferActive ) - { - Framebuffer::Unbind(); - } - } - */ - if( r_useHDR.GetBool() && clearHDR ) { bool isDefaultFramebufferActive = Framebuffer::IsDefaultFramebufferActive(); @@ -1518,22 +1499,6 @@ void idRenderBackend::CheckCVars() } } - if( r_useSRGB.IsModified() ) - { - r_useSRGB.ClearModified(); - if( glConfig.sRGBFramebufferAvailable ) - { - if( r_useSRGB.GetBool() && r_useSRGB.GetInteger() != 3 ) - { - glEnable( GL_FRAMEBUFFER_SRGB ); - } - else - { - glDisable( GL_FRAMEBUFFER_SRGB ); - } - } - } - if( r_antiAliasing.IsModified() ) { switch( r_antiAliasing.GetInteger() ) diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index fe4dc241..4745e649 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -1058,7 +1058,6 @@ extern idCVar r_useShadowDepthBounds; // use depth bounds test on individual sh extern idCVar r_useShadowMapping; // use shadow mapping instead of stencil shadows extern idCVar r_useHalfLambertLighting; // use Half-Lambert lighting instead of classic Lambert extern idCVar r_useHDR; -extern idCVar r_useSRGB; extern idCVar r_useSeamlessCubeMap; // RB end @@ -1451,6 +1450,14 @@ public: tics = 0; nextTicCount = 0; } + + void Reset( int expected ) + { + expectedCount = expected; + count = 0; + tics = 0; + nextTicCount = 0; + } }; /* diff --git a/neo/renderer/RenderSystem.h b/neo/renderer/RenderSystem.h index 4db32ab6..88fcfa18 100644 --- a/neo/renderer/RenderSystem.h +++ b/neo/renderer/RenderSystem.h @@ -199,7 +199,6 @@ struct glconfig_t bool anisotropicFilterAvailable; bool textureLODBiasAvailable; bool seamlessCubeMapAvailable; - bool sRGBFramebufferAvailable; bool vertexBufferObjectAvailable; bool mapBufferRangeAvailable; bool vertexArrayObjectAvailable; diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index 73efde88..4b5ac273 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -86,7 +86,6 @@ idCVar r_useNodeCommonChildren( "r_useNodeCommonChildren", "1", CVAR_RENDERER | idCVar r_useShadowSurfaceScissor( "r_useShadowSurfaceScissor", "1", CVAR_RENDERER | CVAR_BOOL, "scissor shadows by the scissor rect of the interaction surfaces" ); idCVar r_useCachedDynamicModels( "r_useCachedDynamicModels", "1", CVAR_RENDERER | CVAR_BOOL, "cache snapshots of dynamic models" ); idCVar r_useSeamlessCubeMap( "r_useSeamlessCubeMap", "1", CVAR_RENDERER | CVAR_BOOL, "use ARB_seamless_cube_map if available" ); -idCVar r_useSRGB( "r_useSRGB", "0", CVAR_RENDERER | CVAR_INTEGER | CVAR_ARCHIVE, "1 = both texture and framebuffer, 2 = framebuffer only, 3 = texture only" ); idCVar r_maxAnisotropicFiltering( "r_maxAnisotropicFiltering", "8", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "limit aniso filtering" ); idCVar r_useTrilinearFiltering( "r_useTrilinearFiltering", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "Extra quality filtering" ); // RB: not used anymore @@ -262,9 +261,9 @@ idCVar r_shadowMapSunDepthBiasScale( "r_shadowMapSunDepthBiasScale", "0.999991", // RB: HDR parameters #if defined( USE_VULKAN ) - idCVar r_useHDR( "r_useHDR", "0", CVAR_RENDERER | CVAR_ROM | CVAR_STATIC | CVAR_BOOL, "use high dynamic range rendering" ); + idCVar r_useHDR( "r_useHDR", "0", CVAR_RENDERER | CVAR_ROM | CVAR_STATIC | CVAR_BOOL, "Can't be changed, is broken on Vulkan backend" ); #else - idCVar r_useHDR( "r_useHDR", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "use high dynamic range rendering" ); + idCVar r_useHDR( "r_useHDR", "1", CVAR_RENDERER | CVAR_ROM | CVAR_STATIC | CVAR_BOOL, "Can't be changed: Use high dynamic range rendering" ); #endif idCVar r_hdrAutoExposure( "r_hdrAutoExposure", "0", CVAR_RENDERER | CVAR_BOOL, "EXPENSIVE: enables adapative HDR tone mapping otherwise the exposure is derived by r_exposure" ); diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 0bed4604..9ac2039d 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -95,7 +95,7 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con { lightGridPoints.SetNum( numGridPoints ); - idLib::Printf( "area %i (%i x %i x %i) = %i grid points \n", area, lightGridBounds[0], lightGridBounds[1], lightGridBounds[2], numGridPoints ); + idLib::Printf( "\narea %i (%i x %i x %i) = %i grid points \n", area, lightGridBounds[0], lightGridBounds[1], lightGridBounds[2], numGridPoints ); idLib::Printf( "area %i grid size (%i %i %i)\n", area, ( int )lightGridSize[0], ( int )lightGridSize[1], ( int )lightGridSize[2] ); idLib::Printf( "area %i grid bounds (%i %i %i)\n", area, ( int )lightGridBounds[0], ( int )lightGridBounds[1], ( int )lightGridBounds[2] ); idLib::Printf( "area %i %9u x %" PRIuSIZE " = lightGridSize = (%.2fMB)\n", area, numGridPoints, sizeof( lightGridPoint_t ), ( float )( lightGridPoints.MemoryUsed() ) / ( 1024.0f * 1024.0f ) ); @@ -226,6 +226,21 @@ idVec3 LightGrid::GetProbeIndexDebugColor( const int probeIndex ) return GetGridCoordDebugColor( gridCoord ); } +int LightGrid::CountValidGridPoints() const +{ + int validCount = 0; + + for( int i = 0; i < lightGridPoints.Num(); i += 1 ) + { + if( lightGridPoints[i].valid > 0 ) + { + validCount++; + } + } + + return validCount; +} + void LightGrid::CalculateLightGridPointPositions( const idRenderWorld* world, int area ) { // calculate grid point positions @@ -368,12 +383,19 @@ void idRenderWorldLocal::SetupLightGrid() } else { + int totalGridPoints = 0; + for( int i = 0; i < numPortalAreas; i++ ) { portalArea_t* area = &portalAreas[i]; area->lightGrid.SetupLightGrid( area->globalBounds, mapName, this, i, -1 ); + + totalGridPoints += area->lightGrid.CountValidGridPoints(); } + + idLib::Printf( "----------------------------------\n" ); + idLib::Printf( "Total valid light grid points %i\n", totalGridPoints ); } } @@ -627,7 +649,7 @@ void idRenderWorldLocal::ParseLightGridPoints( idLexer* src, idFile* fileOut ) area->lightGrid.lightGridPoints.SetNum( numLightGridPoints ); - idLib::Printf( "area %i (%i x %i x %i) = %i grid points \n", areaIndex, area->lightGrid.lightGridBounds[0], area->lightGrid.lightGridBounds[1], area->lightGrid.lightGridBounds[2], numLightGridPoints ); + idLib::Printf( "\narea %i (%i x %i x %i) = %i grid points \n", areaIndex, area->lightGrid.lightGridBounds[0], area->lightGrid.lightGridBounds[1], area->lightGrid.lightGridBounds[2], numLightGridPoints ); idLib::Printf( "area %i grid size (%i %i %i)\n", areaIndex, ( int )area->lightGrid.lightGridSize[0], ( int )area->lightGrid.lightGridSize[1], ( int )area->lightGrid.lightGridSize[2] ); idLib::Printf( "area %i grid bounds (%i %i %i)\n", areaIndex, ( int )area->lightGrid.lightGridBounds[0], ( int )area->lightGrid.lightGridBounds[1], ( int )area->lightGrid.lightGridBounds[2] ); idLib::Printf( "area %i %9u x %" PRIuSIZE " = lightGridSize = (%.2fMB)\n", areaIndex, numLightGridPoints, sizeof( lightGridPoint_t ), ( float )( area->lightGrid.lightGridPoints.MemoryUsed() ) / ( 1024.0f * 1024.0f ) ); @@ -695,7 +717,7 @@ void idRenderWorldLocal::ReadBinaryLightGridPoints( idFile* file ) area->lightGrid.lightGridPoints.SetNum( numLightGridPoints ); - idLib::Printf( "area %i (%i x %i x %i) = %i grid points \n", areaIndex, area->lightGrid.lightGridBounds[0], area->lightGrid.lightGridBounds[1], area->lightGrid.lightGridBounds[2], numLightGridPoints ); + idLib::Printf( "\narea %i (%i x %i x %i) = %i grid points \n", areaIndex, area->lightGrid.lightGridBounds[0], area->lightGrid.lightGridBounds[1], area->lightGrid.lightGridBounds[2], numLightGridPoints ); idLib::Printf( "area %i grid size (%i %i %i)\n", areaIndex, ( int )area->lightGrid.lightGridSize[0], ( int )area->lightGrid.lightGridSize[1], ( int )area->lightGrid.lightGridSize[2] ); idLib::Printf( "area %i grid bounds (%i %i %i)\n", areaIndex, ( int )area->lightGrid.lightGridBounds[0], ( int )area->lightGrid.lightGridBounds[1], ( int )area->lightGrid.lightGridBounds[2] ); idLib::Printf( "area %i %9u x %" PRIuSIZE " = lightGridSize = (%.2fMB)\n", areaIndex, numLightGridPoints, sizeof( lightGridPoint_t ), ( float )( area->lightGrid.lightGridPoints.MemoryUsed() ) / ( 1024.0f * 1024.0f ) ); @@ -1099,6 +1121,7 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) // CAPTURE SCENE LIGHTING TO CUBEMAPS //-------------------------------------------- + int totalStart = Sys_Milliseconds(); for( int a = 0; a < tr.primaryWorld->NumAreas(); a++ ) { @@ -1205,7 +1228,7 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) if( !useThreads ) { - progressBar.Reset(); + progressBar.Reset( tr.lightGridJobs.Num() ); progressBar.Start(); } @@ -1301,6 +1324,13 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) #endif } + + int totalEnd = Sys_Milliseconds(); + + common->Printf( "Baked light grid irradiance in %5.1f minutes\n\n", ( totalEnd - totalStart ) / ( 1000.0f * 60 ) ); + + // everything went ok so let's save the configurations to disc + // so we can load the texture atlases with the correct subdivisions next time filename.Format( "%s.lightgrid", baseName.c_str() ); tr.primaryWorld->WriteLightGridsToFile( filename ); } diff --git a/neo/renderer/RenderWorld_local.h b/neo/renderer/RenderWorld_local.h index 653425cc..c2c58b4c 100644 --- a/neo/renderer/RenderWorld_local.h +++ b/neo/renderer/RenderWorld_local.h @@ -94,6 +94,8 @@ public: idVec3 GetGridCoordDebugColor( int gridCoord[3] ); idVec3 GetProbeIndexDebugColor( const int probeIndex ); + int CountValidGridPoints() const; + idImage* GetIrradianceImage() const { return irradianceImage; From d11fae0c20d0a5a915f63689fa6efb6f230d2d3c Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Mon, 19 Apr 2021 00:44:41 +0200 Subject: [PATCH 18/26] Don't write .exr files for empty light grid areas --- neo/renderer/RenderWorld_lightgrid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 9ac2039d..52ef8b5c 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -1139,7 +1139,7 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) area->lightGrid.SetupLightGrid( area->globalBounds, tr.primaryWorld->mapName, tr.primaryWorld, a, limit ); #if 1 - int numGridPoints = area->lightGrid.lightGridPoints.Num(); + int numGridPoints = area->lightGrid.CountValidGridPoints(); if( numGridPoints == 0 ) { continue; From f3ee2baac885a7478d3d7c51cf053b18318ce27e Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Fri, 23 Apr 2021 00:21:22 +0200 Subject: [PATCH 19/26] Enable linear filtering for octahedron lightgrid probes --- .../builtin/debug/lightgrid.ps.hlsl | 17 ++++- .../builtin/debug/octahedron.ps.hlsl | 14 +++- .../lighting/ambient_lightgrid_IBL.ps.hlsl | 17 ++++- neo/renderer/Framebuffer.h | 2 +- neo/renderer/Image.h | 5 ++ neo/renderer/Image_load.cpp | 2 +- neo/renderer/OpenGL/RenderDebug_GL.cpp | 15 +++++ neo/renderer/RenderBackend.cpp | 5 ++ neo/renderer/RenderCommon.h | 2 +- neo/renderer/RenderProgs_embedded.h | 64 ++++++++++++++++--- neo/renderer/RenderWorld_defs.cpp | 4 +- neo/renderer/RenderWorld_envprobes.cpp | 37 ++++++++++- neo/renderer/RenderWorld_lightgrid.cpp | 29 ++++++--- neo/renderer/RenderWorld_local.h | 1 + 14 files changed, 182 insertions(+), 32 deletions(-) diff --git a/base/renderprogs/builtin/debug/lightgrid.ps.hlsl b/base/renderprogs/builtin/debug/lightgrid.ps.hlsl index 61b4bd40..2733321c 100644 --- a/base/renderprogs/builtin/debug/lightgrid.ps.hlsl +++ b/base/renderprogs/builtin/debug/lightgrid.ps.hlsl @@ -75,8 +75,6 @@ int3 GetBaseGridCoord( float3 origin ) return pos; } - - void main( PS_IN fragment, out PS_OUT result ) { const int LIGHTGRID_IRRADIANCE_SIZE = 32; @@ -108,7 +106,20 @@ void main( PS_IN fragment, out PS_OUT result ) normalizedOctCoordZeroOne.x += ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * invXZ; normalizedOctCoordZeroOne.y += ( gridCoord[1] * invY ); - float4 envMap = tex2D( samp0, normalizedOctCoordZeroOne ); + // offset by one pixel border bleed size for linear filtering +#if 1 + float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( 32.0 / ( 34.0 * 1.0 ) ) ); + + float2 probeTopLeftPosition; + probeTopLeftPosition.x = ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * 2.0 + 1.0; + probeTopLeftPosition.y = ( gridCoord[1] ) * 2.0 + 1.0; + + float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw; + + normalizedOctCoordZeroOne.xy = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions; +#endif + + float4 envMap = texture( samp0, normalizedOctCoordZeroOne, 0 ); result.color = float4( envMap.xyz, 1.0f ) * 1.0 * fragment.color; } diff --git a/base/renderprogs/builtin/debug/octahedron.ps.hlsl b/base/renderprogs/builtin/debug/octahedron.ps.hlsl index 8ef576de..7f8170ab 100644 --- a/base/renderprogs/builtin/debug/octahedron.ps.hlsl +++ b/base/renderprogs/builtin/debug/octahedron.ps.hlsl @@ -58,7 +58,17 @@ void main( PS_IN fragment, out PS_OUT result ) float2 normalizedOctCoord = octEncode( reflectionVector ); float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5; - float4 envMap = tex2D( samp0, normalizedOctCoordZeroOne ); + // offset by one pixel border bleed size for linear filtering + float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( rpCascadeDistances.x - float( 2.0 ) ) ) / rpCascadeDistances.xy; - result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color; + float2 probeTopLeftPosition = float2( 1.0, 1.0 ); + float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw; + + normalizedOctCoordZeroOne.xy = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions; + + //normalizedOctCoordZeroOne = TextureCoordFromDirection( reflectionVector, 0, int( rpCascadeDistances.x ), int( rpCascadeDistances.y ), int( rpCascadeDistances.x ) - 2 ); + + float4 envMap = texture( samp0, normalizedOctCoordZeroOne, 0 ); + + result.color = float4( envMap.xyz, 1.0f ) * fragment.color * 1.0; } diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl index 0a330fcc..7987cade 100644 --- a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl @@ -331,7 +331,22 @@ void main( PS_IN fragment, out PS_OUT result ) atlasOffset.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * invXZ; atlasOffset.y = ( gridCoord2[1] * invY ); - float3 color = tex2D( samp7, normalizedOctCoordZeroOne + atlasOffset ).rgb; + // offset by one pixel border bleed size for linear filtering +#if 1 + float2 octCoordNormalizedToTextureDimensions = ( ( normalizedOctCoordZeroOne + atlasOffset ) * ( 32.0 / ( 34.0 * 1.0 ) ) ); + + float2 probeTopLeftPosition; + probeTopLeftPosition.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * 2.0 + 1.0; + probeTopLeftPosition.y = ( gridCoord2[1] ) * 2.0 + 1.0; + + float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw; + + float2 atlasCoord = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions; +#else + float2 atlasCoord = normalizedOctCoordZeroOne + atlasOffset; +#endif + + float3 color = texture( samp7, atlasCoord, 0 ).rgb; if( ( color.r + color.g + color.b ) < 0.0001 ) { diff --git a/neo/renderer/Framebuffer.h b/neo/renderer/Framebuffer.h index 2069b794..3a455ff4 100644 --- a/neo/renderer/Framebuffer.h +++ b/neo/renderer/Framebuffer.h @@ -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 RADIANCE_CUBEMAP_SIZE = 256; -static const int IRRADIANCE_CUBEMAP_SIZE = 128; +static const int IRRADIANCE_CUBEMAP_SIZE = 34; #if 1 static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 2048, 1024, 512, 512, 256 }; diff --git a/neo/renderer/Image.h b/neo/renderer/Image.h index 537257ca..c5c8698f 100644 --- a/neo/renderer/Image.h +++ b/neo/renderer/Image.h @@ -309,6 +309,11 @@ public: return opts.height; } + idVec2i GetUploadResolution() const + { + return idVec2i( opts.width, opts.height ); + } + void SetReferencedOutsideLevelLoad() { referencedOutsideLevelLoad = true; diff --git a/neo/renderer/Image_load.cpp b/neo/renderer/Image_load.cpp index 928ae1f0..35653df9 100644 --- a/neo/renderer/Image_load.cpp +++ b/neo/renderer/Image_load.cpp @@ -736,7 +736,7 @@ void idImage::Reload( bool force ) if( !force ) { ID_TIME_T current; - if( cubeFiles != CF_2D ) + if( cubeFiles == CF_NATIVE || cubeFiles == CF_CAMERA ) { R_LoadCubeImages( imgName, cubeFiles, NULL, NULL, ¤t ); } diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index c0dcc898..48df6ffe 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1756,16 +1756,26 @@ void idRenderBackend::DBG_ShowViewEnvprobes() renderProgManager.SetUniformValue( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); // rpLocalViewOrigin + idVec4 textureSize; + GL_SelectTexture( 0 ); if( r_showViewEnvprobes.GetInteger() >= 2 ) { vProbe->irradianceImage->Bind(); + + idVec2i res = vProbe->irradianceImage->GetUploadResolution(); + textureSize.Set( res.x, res.y, 1.0f / res.x, 1.0f / res.y ); } else { vProbe->radianceImage->Bind(); + + idVec2i res = vProbe->radianceImage->GetUploadResolution(); + textureSize.Set( res.x, res.y, 1.0f / res.x, 1.0f / res.y ); } + renderProgManager.SetUniformValue( RENDERPARM_CASCADEDISTANCES, textureSize.ToFloatPtr() ); + DrawElementsWithCounters( &zeroOneSphereSurface ); // non-hidden lines @@ -1911,6 +1921,11 @@ void idRenderBackend::DBG_ShowLightGrid() GL_SelectTexture( 0 ); area->lightGrid.GetIrradianceImage()->Bind(); + + idVec2i res = area->lightGrid.GetIrradianceImage()->GetUploadResolution(); + idVec4 textureSize( res.x, res.y, 1.0f / res.x, 1.0f / res.y ); + + renderProgManager.SetUniformValue( RENDERPARM_CASCADEDISTANCES, textureSize.ToFloatPtr() ); } #endif diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 35251fc2..24ef280c 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -1399,6 +1399,11 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas GL_SelectTexture( INTERACTION_TEXUNIT_AMBIENT_CUBE1 ); currentSpace->irradianceAtlasImage->Bind(); + idVec2i res = currentSpace->irradianceAtlasImage->GetUploadResolution(); + idVec4 textureSize( res.x, res.y, 1.0f / res.x, 1.0f / res.y ); + + renderProgManager.SetUniformValue( RENDERPARM_CASCADEDISTANCES, textureSize.ToFloatPtr() ); + GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE1 ); if( viewDef->radianceImage ) { diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index 4745e649..f96f1656 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -513,7 +513,7 @@ struct calcEnvprobeParms_t -static const int LIGHTGRID_IRRADIANCE_SIZE = 32; +static const int LIGHTGRID_IRRADIANCE_SIZE = ( 16 * 2 ) + 2; struct calcLightGridPointParms_t { diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index 0e411c78..f5678b9e 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -2627,9 +2627,19 @@ static const cgShaderDef_t cg_renderprogs[] = " float2 normalizedOctCoord = octEncode( reflectionVector );\n" " float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n" "\n" - " float4 envMap = tex2D( samp0, normalizedOctCoordZeroOne );\n" + " // offset by one pixel border bleed size for linear filtering\n" + " float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( rpCascadeDistances.x - float( 2.0 ) ) ) / rpCascadeDistances.xy;\n" "\n" - " result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color;\n" + " float2 probeTopLeftPosition = float2( 1.0, 1.0 );\n" + " float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw;\n" + "\n" + " normalizedOctCoordZeroOne.xy = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions;\n" + "\n" + " //normalizedOctCoordZeroOne = TextureCoordFromDirection( reflectionVector, 0, int( rpCascadeDistances.x ), int( rpCascadeDistances.y ), int( rpCascadeDistances.x ) - 2 );\n" + "\n" + " float4 envMap = texture( samp0, normalizedOctCoordZeroOne, 0 );\n" + "\n" + " result.color = float4( envMap.xyz, 1.0f ) * fragment.color * 1.0;\n" "}\n" "\n" @@ -2840,8 +2850,6 @@ static const cgShaderDef_t cg_renderprogs[] = " return pos;\n" "}\n" "\n" - "\n" - "\n" "void main( PS_IN fragment, out PS_OUT result )\n" "{\n" " const int LIGHTGRID_IRRADIANCE_SIZE = 32;\n" @@ -2873,7 +2881,20 @@ static const cgShaderDef_t cg_renderprogs[] = " normalizedOctCoordZeroOne.x += ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * invXZ;\n" " normalizedOctCoordZeroOne.y += ( gridCoord[1] * invY );\n" "\n" - " float4 envMap = tex2D( samp0, normalizedOctCoordZeroOne );\n" + " // offset by one pixel border bleed size for linear filtering\n" + "#if 1\n" + " float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( 32.0 / ( 34.0 * 1.0 ) ) );\n" + "\n" + " float2 probeTopLeftPosition;\n" + " probeTopLeftPosition.x = ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * 2.0 + 1.0;\n" + " probeTopLeftPosition.y = ( gridCoord[1] ) * 2.0 + 1.0;\n" + "\n" + " float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw;\n" + "\n" + " normalizedOctCoordZeroOne.xy = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions;\n" + "#endif\n" + "\n" + " float4 envMap = texture( samp0, normalizedOctCoordZeroOne, 0 );\n" "\n" " result.color = float4( envMap.xyz, 1.0f ) * 1.0 * fragment.color;\n" "}\n" @@ -4890,7 +4911,7 @@ static const cgShaderDef_t cg_renderprogs[] = " float3 reflectionVector = globalNormal * dot3( globalView, globalNormal );\n" " reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalView );\n" "\n" - "#if 1\n" + "#if 0\n" " // parallax box correction using portal area bounds\n" " float hitScale = 0.0;\n" " float3 bounds[2];\n" @@ -5006,7 +5027,7 @@ static const cgShaderDef_t cg_renderprogs[] = " float specAO = ComputeSpecularAO( vDotN, ao, roughness );\n" " float3 specularLight = radiance * ( kS * envBRDF.x + float3( envBRDF.y ) ) * specAO * ( rpSpecularModifier.xyz * 0.5 );\n" "\n" - "#if 0\n" + "#if 1\n" " // Marmoset Horizon Fade trick\n" " const half horizonFade = 1.3;\n" " half horiz = saturate( 1.0 + horizonFade * saturate( dot3( reflectionVector, globalNormal ) ) );\n" @@ -5015,11 +5036,12 @@ static const cgShaderDef_t cg_renderprogs[] = "#endif\n" "\n" " half3 lightColor = sRGBToLinearRGB( rpAmbientColor.rgb );\n" + " //half3 lightColor = ( rpAmbientColor.rgb );\n" "\n" " //result.color.rgb = diffuseLight;\n" " //result.color.rgb = diffuseLight * lightColor;\n" " //result.color.rgb = specularLight;\n" - " result.color.rgb = ( diffuseLight + specularLight ) * lightColor * fragment.color.rgb;\n" + " result.color.rgb = ( diffuseLight + specularLight * horiz ) * lightColor * fragment.color.rgb;\n" " //result.color.rgb = localNormal.xyz * 0.5 + 0.5;\n" " //result.color.rgb = float3( ao );\n" " result.color.w = fragment.color.a;\n" @@ -5387,7 +5409,7 @@ static const cgShaderDef_t cg_renderprogs[] = " float3 reflectionVector = globalNormal * dot3( globalView, globalNormal );\n" " reflectionVector = normalize( ( reflectionVector * 2.0f ) - globalView );\n" "\n" - "#if 1\n" + "#if 0\n" " // parallax box correction using portal area bounds\n" " float hitScale = 0.0;\n" " float3 bounds[2];\n" @@ -5568,7 +5590,22 @@ static const cgShaderDef_t cg_renderprogs[] = " atlasOffset.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * invXZ;\n" " atlasOffset.y = ( gridCoord2[1] * invY );\n" "\n" - " float3 color = tex2D( samp7, normalizedOctCoordZeroOne + atlasOffset ).rgb;\n" + " // offset by one pixel border bleed size for linear filtering\n" + "#if 1\n" + " float2 octCoordNormalizedToTextureDimensions = ( ( normalizedOctCoordZeroOne + atlasOffset ) * ( 32.0 / ( 34.0 * 1.0 ) ) );\n" + "\n" + " float2 probeTopLeftPosition;\n" + " probeTopLeftPosition.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * 2.0 + 1.0;\n" + " probeTopLeftPosition.y = ( gridCoord2[1] ) * 2.0 + 1.0;\n" + "\n" + " float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw;\n" + "\n" + " float2 atlasCoord = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions;\n" + "#else\n" + " float2 atlasCoord = normalizedOctCoordZeroOne + atlasOffset;\n" + "#endif\n" + "\n" + " float3 color = texture( samp7, atlasCoord, 0 ).rgb;\n" "\n" " if( ( color.r + color.g + color.b ) < 0.0001 )\n" " {\n" @@ -5605,6 +5642,12 @@ static const cgShaderDef_t cg_renderprogs[] = " float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb;\n" " //radiance = float3( 0.0 );\n" "\n" + " // RB: HACK dim down room radiance by better local irradiance brightness\n" + " //float luma = PhotoLuma( irradiance );\n" + " //float luma = dot( irradiance, LUMINANCE_LINEAR.rgb );\n" + " //float luma = length( irradiance.rgb );\n" + " //radiance *= ( luma * rpSpecularModifier.x * 3.0 );\n" + "\n" " float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg;\n" "\n" "#if 0\n" @@ -5625,6 +5668,7 @@ static const cgShaderDef_t cg_renderprogs[] = "#endif\n" "\n" " half3 lightColor = sRGBToLinearRGB( rpAmbientColor.rgb );\n" + " //half3 lightColor = ( rpAmbientColor.rgb );\n" "\n" " //result.color.rgb = diffuseLight;\n" " //result.color.rgb = diffuseLight * lightColor;\n" diff --git a/neo/renderer/RenderWorld_defs.cpp b/neo/renderer/RenderWorld_defs.cpp index d48b6f0f..c8b12b77 100644 --- a/neo/renderer/RenderWorld_defs.cpp +++ b/neo/renderer/RenderWorld_defs.cpp @@ -769,10 +769,10 @@ void R_DeriveEnvprobeData( RenderEnvprobeLocal* probe ) // TODO get preconvolved cubemaps fullname.Format( "env/%s/envprobe%i_amb", basename.c_str(), probeIndex ); - probe->irradianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); + probe->irradianceImage = globalImages->ImageFromFile( fullname, TF_LINEAR, TR_REPEAT, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); fullname.Format( "env/%s/envprobe%i_spec", basename.c_str(), probeIndex ); - probe->radianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); + probe->radianceImage = globalImages->ImageFromFile( fullname, TF_LINEAR, TR_REPEAT, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); // ------------------------------------ // compute the probe projection matrix diff --git a/neo/renderer/RenderWorld_envprobes.cpp b/neo/renderer/RenderWorld_envprobes.cpp index ab3b9981..c05ce36d 100644 --- a/neo/renderer/RenderWorld_envprobes.cpp +++ b/neo/renderer/RenderWorld_envprobes.cpp @@ -449,16 +449,32 @@ idVec2 IntegrateBRDF( float NdotV, float roughness, int sampleCount ) // Compute normalized oct coord, mapping top left of top left pixel to (-1,-1) -idVec2 NormalizedOctCoord( int x, int y, const int probeSideLength ) +idVec2 NormalizedOctCoord( int x, int y, const int probeWithBorderSide ) { - const int margin = 0; +#if 0 + // 1 pixel border + const int margin = 1; - int probeWithBorderSide = probeSideLength + margin; + int probeSideLength = Max( 2, probeWithBorderSide - ( margin * 2 ) ); + + idVec2 octFragCoord; + octFragCoord.x = idMath::ClampInt( 0, probeSideLength - 1, x - margin ); + octFragCoord.y = idMath::ClampInt( 0, probeSideLength - 1, y - margin ); + + return ( idVec2( octFragCoord ) ) * ( 2.0f / float( probeSideLength ) ) - idVec2( 1.0f, 1.0f ); +#else + + const int margin = 2; + + // RB: FIXME - margin * 2 is wrong but looks better + int probeSideLength = Max( 2, probeWithBorderSide - ( margin * 2 ) ); 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 ); + +#endif } /* @@ -1093,6 +1109,21 @@ CONSOLE_COMMAND( bakeEnvironmentProbes, "Bake environment probes", NULL ) int end = Sys_Milliseconds(); common->Printf( "convolved probes in %5.1f seconds\n\n", ( end - start ) * 0.001f ); + + //-------------------------------------------- + // LOAD CONVOLVED OCTAHEDRONS INTO THE GPU + //-------------------------------------------- + for( int i = 0; i < tr.primaryWorld->envprobeDefs.Num(); i++ ) + { + RenderEnvprobeLocal* def = tr.primaryWorld->envprobeDefs[i]; + if( def == NULL ) + { + continue; + } + + def->irradianceImage->Reload( false ); + def->radianceImage->Reload( false ); + } } /* diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 52ef8b5c..60e260b0 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -372,14 +372,7 @@ void idRenderWorldLocal::SetupLightGrid() bool loaded = LoadLightGridFile( filename ); if( loaded ) { - // try to load existing lightgrid image data - for( int i = 0; i < numPortalAreas; i++ ) - { - portalArea_t* area = &portalAreas[i]; - - filename.Format( "env/%s/area%i_lightgrid_amb", baseName.c_str(), i ); - area->lightGrid.irradianceImage = globalImages->ImageFromFile( filename, TF_NEAREST, TR_CLAMP, TD_R11G11B10F, CF_2D ); - } + LoadLightGridImages(); } else { @@ -399,6 +392,24 @@ void idRenderWorldLocal::SetupLightGrid() } } +void idRenderWorldLocal::LoadLightGridImages() +{ + idLib::Printf( "----- LoadLightGridImages -----\n" ); + + idStrStatic< MAX_OSPATH > baseName = mapName; + baseName.StripFileExtension(); + + idStr filename; + + // try to load existing lightgrid image data + for( int i = 0; i < numPortalAreas; i++ ) + { + portalArea_t* area = &portalAreas[i]; + filename.Format( "env/%s/area%i_lightgrid_amb", baseName.c_str(), i ); + area->lightGrid.irradianceImage = globalImages->ImageFromFile( filename, TF_LINEAR, TR_CLAMP, TD_R11G11B10F, CF_2D ); + } +} + /* =============================================================================== @@ -1333,6 +1344,8 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) // so we can load the texture atlases with the correct subdivisions next time filename.Format( "%s.lightgrid", baseName.c_str() ); tr.primaryWorld->WriteLightGridsToFile( filename ); + + tr.primaryWorld->LoadLightGridImages(); } #if 0 diff --git a/neo/renderer/RenderWorld_local.h b/neo/renderer/RenderWorld_local.h index c2c58b4c..ac5d292c 100644 --- a/neo/renderer/RenderWorld_local.h +++ b/neo/renderer/RenderWorld_local.h @@ -401,6 +401,7 @@ public: void WriteLightGrid( idFile* fp, const LightGrid& lightGrid ); bool LoadLightGridFile( const char* name ); + void LoadLightGridImages(); void ParseLightGridPoints( idLexer* src, idFile* fileOut ); void ReadBinaryLightGridPoints( idFile* file ); From 8d1e7c5afdc9c1b3e492497b0a7690ba65a3f056 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Fri, 23 Apr 2021 00:36:14 +0200 Subject: [PATCH 20/26] Lowered irradiance probe resolution to ( 16 + 2 )^2 --- .../builtin/debug/lightgrid.ps.hlsl | 2 +- .../lighting/ambient_lightgrid_IBL.ps.hlsl | 2 +- neo/renderer/RenderCommon.h | 2 +- neo/renderer/RenderProgs_embedded.h | 510 +++++++++--------- neo/renderer/RenderWorld_lightgrid.cpp | 14 +- 5 files changed, 270 insertions(+), 260 deletions(-) diff --git a/base/renderprogs/builtin/debug/lightgrid.ps.hlsl b/base/renderprogs/builtin/debug/lightgrid.ps.hlsl index 2733321c..0689db74 100644 --- a/base/renderprogs/builtin/debug/lightgrid.ps.hlsl +++ b/base/renderprogs/builtin/debug/lightgrid.ps.hlsl @@ -108,7 +108,7 @@ void main( PS_IN fragment, out PS_OUT result ) // offset by one pixel border bleed size for linear filtering #if 1 - float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( 32.0 / ( 34.0 * 1.0 ) ) ); + float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( 16.0 / 18.0 ) ); float2 probeTopLeftPosition; probeTopLeftPosition.x = ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * 2.0 + 1.0; diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl index 7987cade..a8e77824 100644 --- a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl @@ -333,7 +333,7 @@ void main( PS_IN fragment, out PS_OUT result ) // offset by one pixel border bleed size for linear filtering #if 1 - float2 octCoordNormalizedToTextureDimensions = ( ( normalizedOctCoordZeroOne + atlasOffset ) * ( 32.0 / ( 34.0 * 1.0 ) ) ); + float2 octCoordNormalizedToTextureDimensions = ( ( normalizedOctCoordZeroOne + atlasOffset ) * ( 16.0 / 18.0 ) ); float2 probeTopLeftPosition; probeTopLeftPosition.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * 2.0 + 1.0; diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index f96f1656..4c5a947e 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -513,7 +513,7 @@ struct calcEnvprobeParms_t -static const int LIGHTGRID_IRRADIANCE_SIZE = ( 16 * 2 ) + 2; +static const int LIGHTGRID_IRRADIANCE_SIZE = ( 16 * 1 ) + 2; struct calcLightGridPointParms_t { diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index f5678b9e..f41bf7f8 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -475,9 +475,9 @@ static const cgShaderDef_t cg_renderprogs[] = " return color;\n" "}\n" "\n" - + }, - + { "renderprogs/skinning.inc.hlsl", "/*\n" @@ -558,9 +558,9 @@ static const cgShaderDef_t cg_renderprogs[] = "result.position.y = dot4( modelPosition, rpMVPmatrixY );\n" "result.position.z = dot4( modelPosition, rpMVPmatrixZ );\n" "result.position.w = dot4( modelPosition, rpMVPmatrixW );\n" - + }, - + { "renderprogs/builtin/post/SMAA.inc.hlsl", "/**\n" @@ -2011,9 +2011,9 @@ static const cgShaderDef_t cg_renderprogs[] = "//-----------------------------------------------------------------------------\n" "#endif // SMAA_INCLUDE_PS\n" "\n" - + }, - + { "renderprogs/BRDF.inc.hlsl", "/*\n" @@ -2179,9 +2179,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" "\n" "\n" - + }, - + { "renderprogs/builtin/debug/debug_shadowmap.ps.hlsl", "/*\n" @@ -2239,9 +2239,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = texture( samp0, tc );// * rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/debug/debug_shadowmap.vs.hlsl", "/*\n" @@ -2309,9 +2309,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord0.y = dot4( vertex.texcoord.xy, rpTextureMatrixT );\n" " }\n" "}\n" - + }, - + { "renderprogs/builtin/debug/shadowDebug.ps.hlsl", "/*\n" @@ -2357,9 +2357,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/debug/shadowDebug.vs.hlsl", "/*\n" @@ -2413,9 +2413,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( vPos, rpMVPmatrixZ );\n" " result.position.w = dot4( vPos, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/debug/shadowDebug_skinned.ps.hlsl", "/*\n" @@ -2461,9 +2461,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/debug/shadowDebug_skinned.vs.hlsl", "/*\n" @@ -2562,9 +2562,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( vPos, rpMVPmatrixZ );\n" " result.position.w = dot4( vPos, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/debug/octahedron.ps.hlsl", "/*\n" @@ -2642,9 +2642,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( envMap.xyz, 1.0f ) * fragment.color * 1.0;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/debug/octahedron.vs.hlsl", "/*\n" @@ -2768,9 +2768,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = sRGBAToLinearRGBA( rpColor );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/debug/lightgrid.ps.hlsl", "/*\n" @@ -2883,7 +2883,7 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " // offset by one pixel border bleed size for linear filtering\n" "#if 1\n" - " float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( 32.0 / ( 34.0 * 1.0 ) ) );\n" + " float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( 16.0 / 18.0 ) );\n" "\n" " float2 probeTopLeftPosition;\n" " probeTopLeftPosition.x = ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * 2.0 + 1.0;\n" @@ -2899,9 +2899,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( envMap.xyz, 1.0f ) * 1.0 * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/debug/lightgrid.vs.hlsl", "/*\n" @@ -3031,9 +3031,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = sRGBAToLinearRGBA( rpColor );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/fog/blendLight.ps.hlsl", "/*\n" @@ -3096,9 +3096,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = c;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/fog/blendLight.vs.hlsl", "/*\n" @@ -3165,9 +3165,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord1.y = 0.5;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/fog/fog.ps.hlsl", "/*\n" @@ -3231,9 +3231,9 @@ static const cgShaderDef_t cg_renderprogs[] = "}\n" "\n" "\n" - + }, - + { "renderprogs/builtin/fog/fog.vs.hlsl", "/*\n" @@ -3297,9 +3297,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord1.y = dot4( vertex.position, rpTexGen1T );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/fog/fog_skinned.ps.hlsl", "/*\n" @@ -3363,9 +3363,9 @@ static const cgShaderDef_t cg_renderprogs[] = "}\n" "\n" "\n" - + }, - + { "renderprogs/builtin/fog/fog_skinned.vs.hlsl", "/*\n" @@ -3472,9 +3472,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord1.y = dot4( modelPosition, rpTexGen1T );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/bumpyenvironment.ps.hlsl", "/*\n" @@ -3557,9 +3557,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/bumpyenvironment.vs.hlsl", "/*\n" @@ -3646,9 +3646,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/legacy/bumpyenvironment_skinned.ps.hlsl", "/*\n" @@ -3732,9 +3732,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/bumpyenvironment_skinned.vs.hlsl", "/*\n" @@ -3879,9 +3879,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/legacy/environment.ps.hlsl", "/*\n" @@ -3945,9 +3945,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/environment.vs.hlsl", "/*\n" @@ -4014,9 +4014,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = sRGBAToLinearRGBA( rpColor );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/environment_skinned.ps.hlsl", "/*\n" @@ -4080,9 +4080,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/environment_skinned.vs.hlsl", "/*\n" @@ -4197,9 +4197,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = rpColor;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/skybox.ps.hlsl", "/*\n" @@ -4252,9 +4252,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = sRGBAToLinearRGBA( texCUBE( samp0, fragment.texcoord0 ) ) * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/skybox.vs.hlsl", "/*\n" @@ -4316,9 +4316,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/wobblesky.ps.hlsl", "/*\n" @@ -4371,9 +4371,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = sRGBAToLinearRGBA( texCUBE( samp0, fragment.texcoord0 ) ) * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/wobblesky.vs.hlsl", "/*\n" @@ -4438,9 +4438,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/ambient_lighting.ps.hlsl", "/*\n" @@ -4546,9 +4546,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.w = fragment.color.a;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/ambient_lighting.vs.hlsl", "/*\n" @@ -4754,9 +4754,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl", "/*\n" @@ -5047,9 +5047,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.w = fragment.color.a;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/ambient_lighting_IBL.vs.hlsl", "/*\n" @@ -5252,9 +5252,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl", "/*\n" @@ -5592,7 +5592,7 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " // offset by one pixel border bleed size for linear filtering\n" "#if 1\n" - " float2 octCoordNormalizedToTextureDimensions = ( ( normalizedOctCoordZeroOne + atlasOffset ) * ( 32.0 / ( 34.0 * 1.0 ) ) );\n" + " float2 octCoordNormalizedToTextureDimensions = ( ( normalizedOctCoordZeroOne + atlasOffset ) * ( 16.0 / 18.0 ) );\n" "\n" " float2 probeTopLeftPosition;\n" " probeTopLeftPosition.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * 2.0 + 1.0;\n" @@ -5679,9 +5679,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.w = fragment.color.a;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/ambient_lightgrid_IBL.vs.hlsl", "/*\n" @@ -5884,9 +5884,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/interaction.ps.hlsl", "/*\n" @@ -6058,9 +6058,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.a = 1.0;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/interaction.vs.hlsl", "/*\n" @@ -6262,9 +6262,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/interactionAmbient.ps.hlsl", "/*\n" @@ -6372,9 +6372,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.w = 1.0;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/interactionAmbient.vs.hlsl", "/*\n" @@ -6494,9 +6494,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //# for 1.0-color : env[16] = -1, env[17] = 1\n" " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/interactionAmbient_skinned.ps.hlsl", "/*\n" @@ -6604,9 +6604,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.w = 1.0;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/interactionAmbient_skinned.vs.hlsl", "/*\n" @@ -6785,9 +6785,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //# for 1.0-color : env[16] = -1, env[17] = 1\n" " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/interactionSM.ps.hlsl", "/*\n" @@ -7249,9 +7249,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.a = 1.0;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/interactionSM.vs.hlsl", "/*\n" @@ -7476,9 +7476,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/shadow.ps.hlsl", "/*\n" @@ -7524,9 +7524,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/shadow.vs.hlsl", "/*\n" @@ -7580,9 +7580,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( vPos, rpMVPmatrixZ );\n" " result.position.w = dot4( vPos, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/shadow_skinned.ps.hlsl", "/*\n" @@ -7628,9 +7628,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/shadow_skinned.vs.hlsl", "/*\n" @@ -7729,9 +7729,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( vPos, rpMVPmatrixZ );\n" " result.position.w = dot4( vPos, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/post/fxaa.ps.hlsl", "/*\n" @@ -7848,9 +7848,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = colorSample;\n" "}\n" - + }, - + { "renderprogs/builtin/post/fxaa.vs.hlsl", "/*\n" @@ -7904,9 +7904,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/post/hdr_glare_chromatic.ps.hlsl", "/*\n" @@ -8041,9 +8041,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.color = float4( sumColor / sumSpectrum, 1.0 );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/hdr_glare_chromatic.vs.hlsl", "/*\n" @@ -8102,9 +8102,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/post/motionBlur.ps.hlsl", "/*\n" @@ -8208,9 +8208,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( sum * invScale, 1.0 );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/motionBlur.vs.hlsl", "/*\n" @@ -8261,9 +8261,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/post/postprocess.ps.hlsl", "/*\n" @@ -8891,9 +8891,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/postprocess.vs.hlsl", "/*\n" @@ -8952,9 +8952,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/post/screen.ps.hlsl", "/*\n" @@ -9012,9 +9012,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/screen.vs.hlsl", "/*\n" @@ -9073,9 +9073,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/post/SMAA_blending_weight_calc.ps.hlsl", "/*\n" @@ -9164,9 +9164,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/SMAA_blending_weight_calc.vs.hlsl", "/*\n" @@ -9244,9 +9244,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.texcoord4.st = pixcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/post/SMAA_edge_detection.ps.hlsl", "/*\n" @@ -9326,9 +9326,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/SMAA_edge_detection.vs.hlsl", "/*\n" @@ -9403,9 +9403,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord2 = offset[1];\n" " result.texcoord3 = offset[2];\n" "}\n" - + }, - + { "renderprogs/builtin/post/SMAA_final.ps.hlsl", "/*\n" @@ -9483,9 +9483,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/SMAA_final.vs.hlsl", "/*\n" @@ -9553,9 +9553,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.texcoord1 = offset;\n" "}\n" - + }, - + { "renderprogs/builtin/post/tonemap.ps.hlsl", "/*\n" @@ -9829,9 +9829,9 @@ static const cgShaderDef_t cg_renderprogs[] = "#endif\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/tonemap.vs.hlsl", "/*\n" @@ -9890,9 +9890,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/SSAO/AmbientOcclusion_AO.ps.hlsl", "/**\n" @@ -10368,9 +10368,9 @@ static const cgShaderDef_t cg_renderprogs[] = "#endif\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/SSAO/AmbientOcclusion_AO.vs.hlsl", "/*\n" @@ -10423,9 +10423,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/SSAO/AmbientOcclusion_blur.ps.hlsl", "/**\n" @@ -10821,9 +10821,9 @@ static const cgShaderDef_t cg_renderprogs[] = "#endif\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/SSAO/AmbientOcclusion_blur.vs.hlsl", "/*\n" @@ -10876,9 +10876,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/SSAO/AmbientOcclusion_minify.ps.hlsl", "/**\n" @@ -10965,9 +10965,9 @@ static const cgShaderDef_t cg_renderprogs[] = "#endif\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/SSAO/AmbientOcclusion_minify.vs.hlsl", "/*\n" @@ -11020,9 +11020,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/SSGI/DeepGBufferRadiosity_radiosity.ps.hlsl", "\n" @@ -11584,9 +11584,9 @@ static const cgShaderDef_t cg_renderprogs[] = "#endif\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/SSGI/DeepGBufferRadiosity_radiosity.vs.hlsl", "/*\n" @@ -11639,9 +11639,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/SSGI/DeepGBufferRadiosity_blur.ps.hlsl", "/**\n" @@ -12024,9 +12024,9 @@ static const cgShaderDef_t cg_renderprogs[] = " blurResult = sum / ( totalWeight + epsilon );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/SSGI/DeepGBufferRadiosity_blur.vs.hlsl", "/*\n" @@ -12079,9 +12079,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/video/bink.ps.hlsl", "/*\n" @@ -12151,9 +12151,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = sRGBAToLinearRGBA( color );\n" "}\n" - + }, - + { "renderprogs/builtin/video/bink.vs.hlsl", "/*\n" @@ -12211,9 +12211,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/video/bink_gui.ps.hlsl", "/*\n" @@ -12286,9 +12286,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.xyz = color.xyz * color.w;\n" " result.color.w = color.w;\n" "}\n" - + }, - + { "renderprogs/builtin/video/bink_gui.vs.hlsl", "/*\n" @@ -12353,9 +12353,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = swizzleColor( vertex.color );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/VR/stereoDeGhost.ps.hlsl", "/*\n" @@ -12401,9 +12401,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/VR/stereoDeGhost.vs.hlsl", "/*\n" @@ -12458,9 +12458,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( vertex.position, rpMVPmatrixZ );\n" " result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/VR/stereoInterlace.ps.hlsl", "/*\n" @@ -12519,9 +12519,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = tex2D( samp1, vec2( fragment.texcoord0 ) );\n" " }\n" "}\n" - + }, - + { "renderprogs/builtin/VR/stereoInterlace.vs.hlsl", "/*\n" @@ -12576,9 +12576,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/VR/stereoWarp.ps.hlsl", "/*\n" @@ -12660,9 +12660,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = tex2D( samp0, warped );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/VR/stereoWarp.vs.hlsl", "/*\n" @@ -12716,9 +12716,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/color.ps.hlsl", "/*\n" @@ -12764,9 +12764,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/color.vs.hlsl", "/*\n" @@ -12871,9 +12871,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/depth.ps.hlsl", "/*\n" @@ -12919,9 +12919,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = float4( 0.0, 0.0, 0.0, 1.0 );\n" "}\n" - + }, - + { "renderprogs/builtin/depth.vs.hlsl", "/*\n" @@ -12972,9 +12972,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( vertex.position, rpMVPmatrixZ );\n" " result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/depth_skinned.ps.hlsl", "/*\n" @@ -13020,9 +13020,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = float4( 0.0, 0.0, 0.0, 1.0 );\n" "}\n" - + }, - + { "renderprogs/builtin/depth_skinned.vs.hlsl", "/*\n" @@ -13118,9 +13118,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( modelPosition, rpMVPmatrixZ );\n" " result.position.w = dot4( modelPosition, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/gbuffer.ps.hlsl", "/*\n" @@ -13209,9 +13209,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.a = 1.0;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/gbuffer.vs.hlsl", "/*\n" @@ -13397,9 +13397,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/gui.ps.hlsl", "/*\n" @@ -13454,9 +13454,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.xyz = color.xyz * color.w;\n" " result.color.w = color.w;\n" "}\n" - + }, - + { "renderprogs/builtin/gui.vs.hlsl", "/*\n" @@ -13521,9 +13521,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = swizzleColor( vertex.color );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/texture.ps.hlsl", "/*\n" @@ -13576,9 +13576,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.color = textureLod( samp0, fragment.texcoord0, 2.0 ) * rpColor;\n" " //result.color = float4( 0.0, 1.0, 0.0, 1.0 ) * rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/texture.vs.hlsl", "/*\n" @@ -13646,9 +13646,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord0.y = dot4( vertex.texcoord.xy, rpTextureMatrixT );\n" " }\n" "}\n" - + }, - + { "renderprogs/builtin/texture_color.ps.hlsl", "/*\n" @@ -13702,9 +13702,9 @@ static const cgShaderDef_t cg_renderprogs[] = " clip( color.a - rpAlphaTest.x );\n" " result.color = sRGBAToLinearRGBA( color );\n" "}\n" - + }, - + { "renderprogs/builtin/texture_color.vs.hlsl", "/*\n" @@ -13776,9 +13776,9 @@ static const cgShaderDef_t cg_renderprogs[] = " float4 vertexColor = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" " result.color = vertexColor * rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/texture_color_skinned.ps.hlsl", "/*\n" @@ -13832,9 +13832,9 @@ static const cgShaderDef_t cg_renderprogs[] = " clip( color.a - rpAlphaTest.x );\n" " result.color = sRGBAToLinearRGBA( color );\n" "}\n" - + }, - + { "renderprogs/builtin/texture_color_skinned.vs.hlsl", "/*\n" @@ -13947,9 +13947,9 @@ static const cgShaderDef_t cg_renderprogs[] = " float4 vertexColor = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" " result.color = vertexColor * rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/texture_color_texgen.ps.hlsl", "/*\n" @@ -14009,9 +14009,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = sRGBAToLinearRGBA( texSample ) * fragment.color;\n" "}\n" - + }, - + { "renderprogs/builtin/texture_color_texgen.vs.hlsl", "/*\n" @@ -14084,9 +14084,9 @@ static const cgShaderDef_t cg_renderprogs[] = " float4 vertexColor = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" " result.color = vertexColor * rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/vertex_color.ps.hlsl", "/*\n" @@ -14139,9 +14139,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = sRGBAToLinearRGBA( fragment.color );\n" "}\n" - + }, - + { "renderprogs/builtin/vertex_color.vs.hlsl", "/*\n" @@ -14202,9 +14202,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = swizzleColor( vertex.color );\n" "}\n" - + }, - + { "renderprogs/bloodorb1_capture.ps.hlsl", "/*\n" @@ -14263,9 +14263,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = lerp( accumSample, currentRenderSample, maskSample.a );\n" "}\n" - + }, - + { "renderprogs/bloodorb1_capture.vs.hlsl", "/*\n" @@ -14331,9 +14331,9 @@ static const cgShaderDef_t cg_renderprogs[] = " // pass through texcoords\n" " result.texcoord1 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/bloodorb2_capture.ps.hlsl", "/*\n" @@ -14398,9 +14398,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = lerp( accumSample, currentRenderSample, maskSample.a );\n" "}\n" - + }, - + { "renderprogs/bloodorb2_capture.vs.hlsl", "/*\n" @@ -14476,9 +14476,9 @@ static const cgShaderDef_t cg_renderprogs[] = " // pass through for currentrender\n" " result.texcoord2 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/bloodorb3_capture.ps.hlsl", "/*\n" @@ -14555,9 +14555,9 @@ static const cgShaderDef_t cg_renderprogs[] = " accumColor = lerp( accumColor, currentRenderSample, maskSample.a );\n" " result.color = accumColor;\n" "}\n" - + }, - + { "renderprogs/bloodorb3_capture.vs.hlsl", "/*\n" @@ -14640,9 +14640,9 @@ static const cgShaderDef_t cg_renderprogs[] = " const float4 colorFactor = rpUser2;\n" " result.texcoord4 = colorFactor.xx;\n" "}\n" - + }, - + { "renderprogs/bloodorb_draw.ps.hlsl", "/*\n" @@ -14700,9 +14700,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = lerp( accumSample, currentRenderSample, maskSample.a );\n" "}\n" - + }, - + { "renderprogs/bloodorb_draw.vs.hlsl", "/*\n" @@ -14761,9 +14761,9 @@ static const cgShaderDef_t cg_renderprogs[] = " // pass through texcoords\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/colorProcess.ps.hlsl", "/*\n" @@ -14818,9 +14818,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = lerp( src, target, fragment.texcoord0.z );\n" "}\n" "\n" - + }, - + { "renderprogs/colorProcess.vs.hlsl", "/*\n" @@ -14890,9 +14890,9 @@ static const cgShaderDef_t cg_renderprogs[] = "}\n" "\n" "\n" - + }, - + { "renderprogs/enviroSuit.ps.hlsl", "/*\n" @@ -14956,9 +14956,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = tex2D( samp0, screenTexCoord );\n" "\n" "}\n" - + }, - + { "renderprogs/enviroSuit.vs.hlsl", "/*\n" @@ -15026,9 +15026,9 @@ static const cgShaderDef_t cg_renderprogs[] = " const float4 deformMagnitude = rpUser1;\n" " result.color = deformMagnitude;\n" "}\n" - + }, - + { "renderprogs/heatHazeWithMask.ps.hlsl", "/*\n" @@ -15101,9 +15101,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = ( tex2D( samp0, screenTexCoord ) );\n" "}\n" - + }, - + { "renderprogs/heatHazeWithMask.vs.hlsl", "/*\n" @@ -15200,9 +15200,9 @@ static const cgShaderDef_t cg_renderprogs[] = " const float4 deformMagnitude = rpUser1;\n" " result.texcoord2 = x * deformMagnitude;\n" "}\n" - + }, - + { "renderprogs/heatHazeWithMaskAndVertex.ps.hlsl", "/*\n" @@ -15277,9 +15277,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = ( tex2D( samp0, screenTexCoord ) );\n" "}\n" - + }, - + { "renderprogs/heatHazeWithMaskAndVertex.vs.hlsl", "/*\n" @@ -15378,9 +15378,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord2 = x * deformMagnitude;\n" " result.color = swizzleColor( vertex.color );\n" "}\n" - + }, - + { "renderprogs/heathaze.ps.hlsl", "/*\n" @@ -15445,9 +15445,9 @@ static const cgShaderDef_t cg_renderprogs[] = " // load the screen render\n" " result.color = ( tex2D( samp0, screenTexCoord.xy ) );\n" "}\n" - + }, - + { "renderprogs/heathaze.vs.hlsl", "/*\n" @@ -15542,9 +15542,9 @@ static const cgShaderDef_t cg_renderprogs[] = " const float4 deformMagnitude = rpUser1;\n" " result.texcoord1 = x * deformMagnitude;\n" "}\n" - + }, - + {0, 0}, - + }; diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 60e260b0..760640a0 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -405,8 +405,16 @@ void idRenderWorldLocal::LoadLightGridImages() for( int i = 0; i < numPortalAreas; i++ ) { portalArea_t* area = &portalAreas[i]; - filename.Format( "env/%s/area%i_lightgrid_amb", baseName.c_str(), i ); - area->lightGrid.irradianceImage = globalImages->ImageFromFile( filename, TF_LINEAR, TR_CLAMP, TD_R11G11B10F, CF_2D ); + + if( !area->lightGrid.irradianceImage ) + { + filename.Format( "env/%s/area%i_lightgrid_amb", baseName.c_str(), i ); + area->lightGrid.irradianceImage = globalImages->ImageFromFile( filename, TF_LINEAR, TR_CLAMP, TD_R11G11B10F, CF_2D ); + } + else + { + area->lightGrid.irradianceImage->Reload( false ); + } } } @@ -452,6 +460,8 @@ void idRenderWorldLocal::WriteLightGridsToFile( const char* filename ) void idRenderWorldLocal::WriteLightGrid( idFile* fp, const LightGrid& lightGrid ) { + // TODO write used irradiance resolution + fp->WriteFloatString( "lightGridPoints { /* area = */ %i /* numLightGridPoints = */ %i\n", lightGrid.area, lightGrid.lightGridPoints.Num() ); fp->WriteFloatString( "/* gridMins */ " ); From f7e898bb6189c9b8d0997764baca161a9a76a205 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Fri, 23 Apr 2021 00:55:53 +0200 Subject: [PATCH 21/26] PBR spec probes shouldn't be linear filtered --- neo/renderer/RenderProgs_embedded.h | 506 ++++++++++++++-------------- neo/renderer/RenderWorld_defs.cpp | 2 +- 2 files changed, 254 insertions(+), 254 deletions(-) diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index f41bf7f8..1ec68587 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -475,9 +475,9 @@ static const cgShaderDef_t cg_renderprogs[] = " return color;\n" "}\n" "\n" - + }, - + { "renderprogs/skinning.inc.hlsl", "/*\n" @@ -558,9 +558,9 @@ static const cgShaderDef_t cg_renderprogs[] = "result.position.y = dot4( modelPosition, rpMVPmatrixY );\n" "result.position.z = dot4( modelPosition, rpMVPmatrixZ );\n" "result.position.w = dot4( modelPosition, rpMVPmatrixW );\n" - + }, - + { "renderprogs/builtin/post/SMAA.inc.hlsl", "/**\n" @@ -2011,9 +2011,9 @@ static const cgShaderDef_t cg_renderprogs[] = "//-----------------------------------------------------------------------------\n" "#endif // SMAA_INCLUDE_PS\n" "\n" - + }, - + { "renderprogs/BRDF.inc.hlsl", "/*\n" @@ -2179,9 +2179,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" "\n" "\n" - + }, - + { "renderprogs/builtin/debug/debug_shadowmap.ps.hlsl", "/*\n" @@ -2239,9 +2239,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = texture( samp0, tc );// * rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/debug/debug_shadowmap.vs.hlsl", "/*\n" @@ -2309,9 +2309,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord0.y = dot4( vertex.texcoord.xy, rpTextureMatrixT );\n" " }\n" "}\n" - + }, - + { "renderprogs/builtin/debug/shadowDebug.ps.hlsl", "/*\n" @@ -2357,9 +2357,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/debug/shadowDebug.vs.hlsl", "/*\n" @@ -2413,9 +2413,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( vPos, rpMVPmatrixZ );\n" " result.position.w = dot4( vPos, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/debug/shadowDebug_skinned.ps.hlsl", "/*\n" @@ -2461,9 +2461,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/debug/shadowDebug_skinned.vs.hlsl", "/*\n" @@ -2562,9 +2562,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( vPos, rpMVPmatrixZ );\n" " result.position.w = dot4( vPos, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/debug/octahedron.ps.hlsl", "/*\n" @@ -2642,9 +2642,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( envMap.xyz, 1.0f ) * fragment.color * 1.0;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/debug/octahedron.vs.hlsl", "/*\n" @@ -2768,9 +2768,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = sRGBAToLinearRGBA( rpColor );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/debug/lightgrid.ps.hlsl", "/*\n" @@ -2899,9 +2899,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( envMap.xyz, 1.0f ) * 1.0 * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/debug/lightgrid.vs.hlsl", "/*\n" @@ -3031,9 +3031,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = sRGBAToLinearRGBA( rpColor );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/fog/blendLight.ps.hlsl", "/*\n" @@ -3096,9 +3096,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = c;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/fog/blendLight.vs.hlsl", "/*\n" @@ -3165,9 +3165,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord1.y = 0.5;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/fog/fog.ps.hlsl", "/*\n" @@ -3231,9 +3231,9 @@ static const cgShaderDef_t cg_renderprogs[] = "}\n" "\n" "\n" - + }, - + { "renderprogs/builtin/fog/fog.vs.hlsl", "/*\n" @@ -3297,9 +3297,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord1.y = dot4( vertex.position, rpTexGen1T );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/fog/fog_skinned.ps.hlsl", "/*\n" @@ -3363,9 +3363,9 @@ static const cgShaderDef_t cg_renderprogs[] = "}\n" "\n" "\n" - + }, - + { "renderprogs/builtin/fog/fog_skinned.vs.hlsl", "/*\n" @@ -3472,9 +3472,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord1.y = dot4( modelPosition, rpTexGen1T );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/bumpyenvironment.ps.hlsl", "/*\n" @@ -3557,9 +3557,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/bumpyenvironment.vs.hlsl", "/*\n" @@ -3646,9 +3646,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/legacy/bumpyenvironment_skinned.ps.hlsl", "/*\n" @@ -3732,9 +3732,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/bumpyenvironment_skinned.vs.hlsl", "/*\n" @@ -3879,9 +3879,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/legacy/environment.ps.hlsl", "/*\n" @@ -3945,9 +3945,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/environment.vs.hlsl", "/*\n" @@ -4014,9 +4014,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = sRGBAToLinearRGBA( rpColor );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/environment_skinned.ps.hlsl", "/*\n" @@ -4080,9 +4080,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( sRGBToLinearRGB( envMap.xyz ), 1.0f ) * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/environment_skinned.vs.hlsl", "/*\n" @@ -4197,9 +4197,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = rpColor;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/skybox.ps.hlsl", "/*\n" @@ -4252,9 +4252,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = sRGBAToLinearRGBA( texCUBE( samp0, fragment.texcoord0 ) ) * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/skybox.vs.hlsl", "/*\n" @@ -4316,9 +4316,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/wobblesky.ps.hlsl", "/*\n" @@ -4371,9 +4371,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = sRGBAToLinearRGBA( texCUBE( samp0, fragment.texcoord0 ) ) * fragment.color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/legacy/wobblesky.vs.hlsl", "/*\n" @@ -4438,9 +4438,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/ambient_lighting.ps.hlsl", "/*\n" @@ -4546,9 +4546,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.w = fragment.color.a;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/ambient_lighting.vs.hlsl", "/*\n" @@ -4754,9 +4754,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl", "/*\n" @@ -5047,9 +5047,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.w = fragment.color.a;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/ambient_lighting_IBL.vs.hlsl", "/*\n" @@ -5252,9 +5252,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl", "/*\n" @@ -5679,9 +5679,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.w = fragment.color.a;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/ambient_lightgrid_IBL.vs.hlsl", "/*\n" @@ -5884,9 +5884,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/interaction.ps.hlsl", "/*\n" @@ -6058,9 +6058,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.a = 1.0;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/interaction.vs.hlsl", "/*\n" @@ -6262,9 +6262,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/interactionAmbient.ps.hlsl", "/*\n" @@ -6372,9 +6372,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.w = 1.0;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/interactionAmbient.vs.hlsl", "/*\n" @@ -6494,9 +6494,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //# for 1.0-color : env[16] = -1, env[17] = 1\n" " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/interactionAmbient_skinned.ps.hlsl", "/*\n" @@ -6604,9 +6604,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.w = 1.0;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/interactionAmbient_skinned.vs.hlsl", "/*\n" @@ -6785,9 +6785,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //# for 1.0-color : env[16] = -1, env[17] = 1\n" " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/interactionSM.ps.hlsl", "/*\n" @@ -7249,9 +7249,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.a = 1.0;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/lighting/interactionSM.vs.hlsl", "/*\n" @@ -7476,9 +7476,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/shadow.ps.hlsl", "/*\n" @@ -7524,9 +7524,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/shadow.vs.hlsl", "/*\n" @@ -7580,9 +7580,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( vPos, rpMVPmatrixZ );\n" " result.position.w = dot4( vPos, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/shadow_skinned.ps.hlsl", "/*\n" @@ -7628,9 +7628,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/lighting/shadow_skinned.vs.hlsl", "/*\n" @@ -7729,9 +7729,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( vPos, rpMVPmatrixZ );\n" " result.position.w = dot4( vPos, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/post/fxaa.ps.hlsl", "/*\n" @@ -7848,9 +7848,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = colorSample;\n" "}\n" - + }, - + { "renderprogs/builtin/post/fxaa.vs.hlsl", "/*\n" @@ -7904,9 +7904,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/post/hdr_glare_chromatic.ps.hlsl", "/*\n" @@ -8041,9 +8041,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.color = float4( sumColor / sumSpectrum, 1.0 );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/hdr_glare_chromatic.vs.hlsl", "/*\n" @@ -8102,9 +8102,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/post/motionBlur.ps.hlsl", "/*\n" @@ -8208,9 +8208,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = float4( sum * invScale, 1.0 );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/motionBlur.vs.hlsl", "/*\n" @@ -8261,9 +8261,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/post/postprocess.ps.hlsl", "/*\n" @@ -8891,9 +8891,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/postprocess.vs.hlsl", "/*\n" @@ -8952,9 +8952,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/post/screen.ps.hlsl", "/*\n" @@ -9012,9 +9012,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/screen.vs.hlsl", "/*\n" @@ -9073,9 +9073,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/post/SMAA_blending_weight_calc.ps.hlsl", "/*\n" @@ -9164,9 +9164,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/SMAA_blending_weight_calc.vs.hlsl", "/*\n" @@ -9244,9 +9244,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.texcoord4.st = pixcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/post/SMAA_edge_detection.ps.hlsl", "/*\n" @@ -9326,9 +9326,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/SMAA_edge_detection.vs.hlsl", "/*\n" @@ -9403,9 +9403,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord2 = offset[1];\n" " result.texcoord3 = offset[2];\n" "}\n" - + }, - + { "renderprogs/builtin/post/SMAA_final.ps.hlsl", "/*\n" @@ -9483,9 +9483,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = color;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/SMAA_final.vs.hlsl", "/*\n" @@ -9553,9 +9553,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.texcoord1 = offset;\n" "}\n" - + }, - + { "renderprogs/builtin/post/tonemap.ps.hlsl", "/*\n" @@ -9829,9 +9829,9 @@ static const cgShaderDef_t cg_renderprogs[] = "#endif\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/post/tonemap.vs.hlsl", "/*\n" @@ -9890,9 +9890,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/SSAO/AmbientOcclusion_AO.ps.hlsl", "/**\n" @@ -10368,9 +10368,9 @@ static const cgShaderDef_t cg_renderprogs[] = "#endif\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/SSAO/AmbientOcclusion_AO.vs.hlsl", "/*\n" @@ -10423,9 +10423,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/SSAO/AmbientOcclusion_blur.ps.hlsl", "/**\n" @@ -10821,9 +10821,9 @@ static const cgShaderDef_t cg_renderprogs[] = "#endif\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/SSAO/AmbientOcclusion_blur.vs.hlsl", "/*\n" @@ -10876,9 +10876,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/SSAO/AmbientOcclusion_minify.ps.hlsl", "/**\n" @@ -10965,9 +10965,9 @@ static const cgShaderDef_t cg_renderprogs[] = "#endif\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/SSAO/AmbientOcclusion_minify.vs.hlsl", "/*\n" @@ -11020,9 +11020,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/SSGI/DeepGBufferRadiosity_radiosity.ps.hlsl", "\n" @@ -11584,9 +11584,9 @@ static const cgShaderDef_t cg_renderprogs[] = "#endif\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/SSGI/DeepGBufferRadiosity_radiosity.vs.hlsl", "/*\n" @@ -11639,9 +11639,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/SSGI/DeepGBufferRadiosity_blur.ps.hlsl", "/**\n" @@ -12024,9 +12024,9 @@ static const cgShaderDef_t cg_renderprogs[] = " blurResult = sum / ( totalWeight + epsilon );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/SSGI/DeepGBufferRadiosity_blur.vs.hlsl", "/*\n" @@ -12079,9 +12079,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position = vertex.position;\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/video/bink.ps.hlsl", "/*\n" @@ -12151,9 +12151,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = sRGBAToLinearRGBA( color );\n" "}\n" - + }, - + { "renderprogs/builtin/video/bink.vs.hlsl", "/*\n" @@ -12211,9 +12211,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/video/bink_gui.ps.hlsl", "/*\n" @@ -12286,9 +12286,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.xyz = color.xyz * color.w;\n" " result.color.w = color.w;\n" "}\n" - + }, - + { "renderprogs/builtin/video/bink_gui.vs.hlsl", "/*\n" @@ -12353,9 +12353,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = swizzleColor( vertex.color );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/VR/stereoDeGhost.ps.hlsl", "/*\n" @@ -12401,9 +12401,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/VR/stereoDeGhost.vs.hlsl", "/*\n" @@ -12458,9 +12458,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( vertex.position, rpMVPmatrixZ );\n" " result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/VR/stereoInterlace.ps.hlsl", "/*\n" @@ -12519,9 +12519,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = tex2D( samp1, vec2( fragment.texcoord0 ) );\n" " }\n" "}\n" - + }, - + { "renderprogs/builtin/VR/stereoInterlace.vs.hlsl", "/*\n" @@ -12576,9 +12576,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/VR/stereoWarp.ps.hlsl", "/*\n" @@ -12660,9 +12660,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = tex2D( samp0, warped );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/VR/stereoWarp.vs.hlsl", "/*\n" @@ -12716,9 +12716,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/builtin/color.ps.hlsl", "/*\n" @@ -12764,9 +12764,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/color.vs.hlsl", "/*\n" @@ -12871,9 +12871,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/depth.ps.hlsl", "/*\n" @@ -12919,9 +12919,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = float4( 0.0, 0.0, 0.0, 1.0 );\n" "}\n" - + }, - + { "renderprogs/builtin/depth.vs.hlsl", "/*\n" @@ -12972,9 +12972,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( vertex.position, rpMVPmatrixZ );\n" " result.position.w = dot4( vertex.position, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/depth_skinned.ps.hlsl", "/*\n" @@ -13020,9 +13020,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = float4( 0.0, 0.0, 0.0, 1.0 );\n" "}\n" - + }, - + { "renderprogs/builtin/depth_skinned.vs.hlsl", "/*\n" @@ -13118,9 +13118,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.position.z = dot4( modelPosition, rpMVPmatrixZ );\n" " result.position.w = dot4( modelPosition, rpMVPmatrixW );\n" "}\n" - + }, - + { "renderprogs/builtin/gbuffer.ps.hlsl", "/*\n" @@ -13209,9 +13209,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.a = 1.0;\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/gbuffer.vs.hlsl", "/*\n" @@ -13397,9 +13397,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" "#endif\n" "}\n" - + }, - + { "renderprogs/builtin/gui.ps.hlsl", "/*\n" @@ -13454,9 +13454,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color.xyz = color.xyz * color.w;\n" " result.color.w = color.w;\n" "}\n" - + }, - + { "renderprogs/builtin/gui.vs.hlsl", "/*\n" @@ -13521,9 +13521,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = swizzleColor( vertex.color );\n" "}\n" "\n" - + }, - + { "renderprogs/builtin/texture.ps.hlsl", "/*\n" @@ -13576,9 +13576,9 @@ static const cgShaderDef_t cg_renderprogs[] = " //result.color = textureLod( samp0, fragment.texcoord0, 2.0 ) * rpColor;\n" " //result.color = float4( 0.0, 1.0, 0.0, 1.0 ) * rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/texture.vs.hlsl", "/*\n" @@ -13646,9 +13646,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord0.y = dot4( vertex.texcoord.xy, rpTextureMatrixT );\n" " }\n" "}\n" - + }, - + { "renderprogs/builtin/texture_color.ps.hlsl", "/*\n" @@ -13702,9 +13702,9 @@ static const cgShaderDef_t cg_renderprogs[] = " clip( color.a - rpAlphaTest.x );\n" " result.color = sRGBAToLinearRGBA( color );\n" "}\n" - + }, - + { "renderprogs/builtin/texture_color.vs.hlsl", "/*\n" @@ -13776,9 +13776,9 @@ static const cgShaderDef_t cg_renderprogs[] = " float4 vertexColor = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" " result.color = vertexColor * rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/texture_color_skinned.ps.hlsl", "/*\n" @@ -13832,9 +13832,9 @@ static const cgShaderDef_t cg_renderprogs[] = " clip( color.a - rpAlphaTest.x );\n" " result.color = sRGBAToLinearRGBA( color );\n" "}\n" - + }, - + { "renderprogs/builtin/texture_color_skinned.vs.hlsl", "/*\n" @@ -13947,9 +13947,9 @@ static const cgShaderDef_t cg_renderprogs[] = " float4 vertexColor = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" " result.color = vertexColor * rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/texture_color_texgen.ps.hlsl", "/*\n" @@ -14009,9 +14009,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = sRGBAToLinearRGBA( texSample ) * fragment.color;\n" "}\n" - + }, - + { "renderprogs/builtin/texture_color_texgen.vs.hlsl", "/*\n" @@ -14084,9 +14084,9 @@ static const cgShaderDef_t cg_renderprogs[] = " float4 vertexColor = ( swizzleColor( vertex.color ) * rpVertexColorModulate ) + rpVertexColorAdd;\n" " result.color = vertexColor * rpColor;\n" "}\n" - + }, - + { "renderprogs/builtin/vertex_color.ps.hlsl", "/*\n" @@ -14139,9 +14139,9 @@ static const cgShaderDef_t cg_renderprogs[] = "{\n" " result.color = sRGBAToLinearRGBA( fragment.color );\n" "}\n" - + }, - + { "renderprogs/builtin/vertex_color.vs.hlsl", "/*\n" @@ -14202,9 +14202,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = swizzleColor( vertex.color );\n" "}\n" - + }, - + { "renderprogs/bloodorb1_capture.ps.hlsl", "/*\n" @@ -14263,9 +14263,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = lerp( accumSample, currentRenderSample, maskSample.a );\n" "}\n" - + }, - + { "renderprogs/bloodorb1_capture.vs.hlsl", "/*\n" @@ -14331,9 +14331,9 @@ static const cgShaderDef_t cg_renderprogs[] = " // pass through texcoords\n" " result.texcoord1 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/bloodorb2_capture.ps.hlsl", "/*\n" @@ -14398,9 +14398,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = lerp( accumSample, currentRenderSample, maskSample.a );\n" "}\n" - + }, - + { "renderprogs/bloodorb2_capture.vs.hlsl", "/*\n" @@ -14476,9 +14476,9 @@ static const cgShaderDef_t cg_renderprogs[] = " // pass through for currentrender\n" " result.texcoord2 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/bloodorb3_capture.ps.hlsl", "/*\n" @@ -14555,9 +14555,9 @@ static const cgShaderDef_t cg_renderprogs[] = " accumColor = lerp( accumColor, currentRenderSample, maskSample.a );\n" " result.color = accumColor;\n" "}\n" - + }, - + { "renderprogs/bloodorb3_capture.vs.hlsl", "/*\n" @@ -14640,9 +14640,9 @@ static const cgShaderDef_t cg_renderprogs[] = " const float4 colorFactor = rpUser2;\n" " result.texcoord4 = colorFactor.xx;\n" "}\n" - + }, - + { "renderprogs/bloodorb_draw.ps.hlsl", "/*\n" @@ -14700,9 +14700,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = lerp( accumSample, currentRenderSample, maskSample.a );\n" "}\n" - + }, - + { "renderprogs/bloodorb_draw.vs.hlsl", "/*\n" @@ -14761,9 +14761,9 @@ static const cgShaderDef_t cg_renderprogs[] = " // pass through texcoords\n" " result.texcoord0 = vertex.texcoord;\n" "}\n" - + }, - + { "renderprogs/colorProcess.ps.hlsl", "/*\n" @@ -14818,9 +14818,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = lerp( src, target, fragment.texcoord0.z );\n" "}\n" "\n" - + }, - + { "renderprogs/colorProcess.vs.hlsl", "/*\n" @@ -14890,9 +14890,9 @@ static const cgShaderDef_t cg_renderprogs[] = "}\n" "\n" "\n" - + }, - + { "renderprogs/enviroSuit.ps.hlsl", "/*\n" @@ -14956,9 +14956,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.color = tex2D( samp0, screenTexCoord );\n" "\n" "}\n" - + }, - + { "renderprogs/enviroSuit.vs.hlsl", "/*\n" @@ -15026,9 +15026,9 @@ static const cgShaderDef_t cg_renderprogs[] = " const float4 deformMagnitude = rpUser1;\n" " result.color = deformMagnitude;\n" "}\n" - + }, - + { "renderprogs/heatHazeWithMask.ps.hlsl", "/*\n" @@ -15101,9 +15101,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = ( tex2D( samp0, screenTexCoord ) );\n" "}\n" - + }, - + { "renderprogs/heatHazeWithMask.vs.hlsl", "/*\n" @@ -15200,9 +15200,9 @@ static const cgShaderDef_t cg_renderprogs[] = " const float4 deformMagnitude = rpUser1;\n" " result.texcoord2 = x * deformMagnitude;\n" "}\n" - + }, - + { "renderprogs/heatHazeWithMaskAndVertex.ps.hlsl", "/*\n" @@ -15277,9 +15277,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " result.color = ( tex2D( samp0, screenTexCoord ) );\n" "}\n" - + }, - + { "renderprogs/heatHazeWithMaskAndVertex.vs.hlsl", "/*\n" @@ -15378,9 +15378,9 @@ static const cgShaderDef_t cg_renderprogs[] = " result.texcoord2 = x * deformMagnitude;\n" " result.color = swizzleColor( vertex.color );\n" "}\n" - + }, - + { "renderprogs/heathaze.ps.hlsl", "/*\n" @@ -15445,9 +15445,9 @@ static const cgShaderDef_t cg_renderprogs[] = " // load the screen render\n" " result.color = ( tex2D( samp0, screenTexCoord.xy ) );\n" "}\n" - + }, - + { "renderprogs/heathaze.vs.hlsl", "/*\n" @@ -15542,9 +15542,9 @@ static const cgShaderDef_t cg_renderprogs[] = " const float4 deformMagnitude = rpUser1;\n" " result.texcoord1 = x * deformMagnitude;\n" "}\n" - + }, - + {0, 0}, - + }; diff --git a/neo/renderer/RenderWorld_defs.cpp b/neo/renderer/RenderWorld_defs.cpp index c8b12b77..e8df5681 100644 --- a/neo/renderer/RenderWorld_defs.cpp +++ b/neo/renderer/RenderWorld_defs.cpp @@ -772,7 +772,7 @@ void R_DeriveEnvprobeData( RenderEnvprobeLocal* probe ) probe->irradianceImage = globalImages->ImageFromFile( fullname, TF_LINEAR, TR_REPEAT, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); fullname.Format( "env/%s/envprobe%i_spec", basename.c_str(), probeIndex ); - probe->radianceImage = globalImages->ImageFromFile( fullname, TF_LINEAR, TR_REPEAT, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); + probe->radianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_REPEAT, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); // ------------------------------------ // compute the probe projection matrix From dcf9cc4e6de9d207eca6bde91886eb910c5e587f Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Mon, 26 Apr 2021 16:31:04 +0200 Subject: [PATCH 22/26] Store irradiance probe resolution and border size --- .../builtin/debug/lightgrid.ps.hlsl | 10 +- .../lighting/ambient_lightgrid_IBL.ps.hlsl | 8 +- neo/framework/DeclManager.cpp | 22 ++-- neo/renderer/OpenGL/RenderDebug_GL.cpp | 8 ++ neo/renderer/RenderBackend.cpp | 12 +- neo/renderer/RenderCommon.h | 7 +- neo/renderer/RenderProgs_embedded.h | 18 ++- neo/renderer/RenderWorld_lightgrid.cpp | 104 ++++++++++++++---- neo/renderer/RenderWorld_local.h | 2 + neo/renderer/tr_frontend_addmodels.cpp | 4 +- neo/tools/compilers/dmap/map.cpp | 2 +- 11 files changed, 147 insertions(+), 50 deletions(-) diff --git a/base/renderprogs/builtin/debug/lightgrid.ps.hlsl b/base/renderprogs/builtin/debug/lightgrid.ps.hlsl index 0689db74..44cb95f9 100644 --- a/base/renderprogs/builtin/debug/lightgrid.ps.hlsl +++ b/base/renderprogs/builtin/debug/lightgrid.ps.hlsl @@ -108,11 +108,15 @@ void main( PS_IN fragment, out PS_OUT result ) // offset by one pixel border bleed size for linear filtering #if 1 - float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( 16.0 / 18.0 ) ); + // rpScreenCorrectionFactor.x = probeSize - borderSize, e.g. ( 18 - 2 ) = 16 + // rpScreenCorrectionFactor.y = probeSize including border, e.g = 18 + // rpScreenCorrectionFactor.z = borderSize e.g = 2 + // rpScreenCorrectionFactor.w = probeSize factor accounting account offset border, e.g = ( 16 / 18 ) = 0.8888 + float2 octCoordNormalizedToTextureDimensions = normalizedOctCoordZeroOne * rpScreenCorrectionFactor.w; float2 probeTopLeftPosition; - probeTopLeftPosition.x = ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * 2.0 + 1.0; - probeTopLeftPosition.y = ( gridCoord[1] ) * 2.0 + 1.0; + probeTopLeftPosition.x = ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5; + probeTopLeftPosition.y = ( gridCoord[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5; float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw; diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl index a8e77824..d5271330 100644 --- a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl @@ -333,11 +333,13 @@ void main( PS_IN fragment, out PS_OUT result ) // offset by one pixel border bleed size for linear filtering #if 1 - float2 octCoordNormalizedToTextureDimensions = ( ( normalizedOctCoordZeroOne + atlasOffset ) * ( 16.0 / 18.0 ) ); + // rpScreenCorrectionFactor.w = probeSize factor accounting account offset border, e.g = ( 16 / 18 ) = 0.8888 + float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne + atlasOffset ) * rpScreenCorrectionFactor.w; + // rpScreenCorrectionFactor.z = borderSize e.g = 2 float2 probeTopLeftPosition; - probeTopLeftPosition.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * 2.0 + 1.0; - probeTopLeftPosition.y = ( gridCoord2[1] ) * 2.0 + 1.0; + probeTopLeftPosition.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5; + probeTopLeftPosition.y = ( gridCoord2[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5; float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw; diff --git a/neo/framework/DeclManager.cpp b/neo/framework/DeclManager.cpp index cc20c193..d2a08eae 100644 --- a/neo/framework/DeclManager.cpp +++ b/neo/framework/DeclManager.cpp @@ -2040,7 +2040,7 @@ struct evarPrefix_t const char* prefix; }; -const evarPrefix_t EvarPrefixes[] = +static const evarPrefix_t EvarPrefixes[] = { { EVAR_STRING, "editor_var " }, { EVAR_INT, "editor_int " }, @@ -2053,15 +2053,15 @@ const evarPrefix_t EvarPrefixes[] = { EVAR_SOUND, "editor_snd "} }; -const int NumEvarPrefixes = sizeof( EvarPrefixes ) / sizeof( evarPrefix_t ); +static const int NumEvarPrefixes = sizeof( EvarPrefixes ) / sizeof( evarPrefix_t ); -typedef struct evar_s +struct LocalEvar_t { int type; idStr fullname; idStr name; idStr desc; -} evar_t; +}; #include // idDeclModelDef @@ -2361,14 +2361,14 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args ) } // collect editor specific spawn flags - idList evars; + idList evars; for( int i = 0; i < NumEvarPrefixes; i++ ) { kv = decl->dict.MatchPrefix( EvarPrefixes[i].prefix ); while( kv ) { - evar_t ev; + LocalEvar_t ev; ev.fullname = kv->GetKey(); kv->GetKey().Right( kv->GetKey().Length() - strlen( EvarPrefixes[i].prefix ), ev.name ); ev.desc = kv->GetValue(); @@ -2386,7 +2386,7 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args ) // add missing property to control the radius - evar_t ev; + LocalEvar_t ev; ev.fullname = "editor_int light"; ev.name = "light"; ev.desc = "light radius"; @@ -2401,7 +2401,7 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args ) { // entities with dynamic models - evar_t ev; + LocalEvar_t ev; ev.fullname = "editor_model model"; ev.name = "model"; ev.desc = "Model Selection (ex mapobjects/model.obj)"; @@ -2437,7 +2437,7 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args ) //} // is it an editor var or a regular spawn argument? - evar_t* ev = nullptr; + LocalEvar_t* ev = nullptr; int vc = evars.Num(); for( int j = 0; j < vc; j++ ) { @@ -2464,7 +2464,7 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args ) // add editor_vars that aren't already covered by the default vars for( int i = 0; i < evars.Num(); i++ ) { - const evar_t* ev = &evars[ i ]; + const LocalEvar_t* ev = &evars[ i ]; const idKeyValue* kv2 = dictToWrite.FindKey( ev->name ); if( !kv2 ) @@ -2538,7 +2538,7 @@ void idDeclManagerLocal::ExportDeclsToTrenchBroom_f( const idCmdArgs& args ) kv = dictToWrite.GetKeyVal( i ); // is it an editor var or a regular spawn argument? - evar_t* ev = nullptr; + LocalEvar_t* ev = nullptr; int vc = evars.Num(); for( int j = 0; j < vc; j++ ) { diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index 48df6ffe..7f24b73c 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1839,6 +1839,14 @@ void idRenderBackend::DBG_ShowLightGrid() renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXSCALE, lightGridSize.ToFloatPtr() ); renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXOFFSET, lightGridBounds.ToFloatPtr() ); + // individual probe sizes on the atlas image + idVec4 probeSize; + probeSize[0] = area->lightGrid.imageSingleProbeSize - area->lightGrid.imageBorderSize; + probeSize[1] = area->lightGrid.imageSingleProbeSize; + probeSize[2] = area->lightGrid.imageBorderSize; + probeSize[3] = float( area->lightGrid.imageSingleProbeSize - area->lightGrid.imageBorderSize ) / area->lightGrid.imageSingleProbeSize; + renderProgManager.SetUniformValue( RENDERPARM_SCREENCORRECTIONFACTOR, probeSize.ToFloatPtr() ); // rpScreenCorrectionFactor + for( int i = 0; i < area->lightGrid.lightGridPoints.Num(); i++ ) { lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[i]; diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 24ef280c..3ddb88af 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -1355,6 +1355,14 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXSCALE, lightGridSize.ToFloatPtr() ); renderProgManager.SetUniformValue( RENDERPARM_JITTERTEXOFFSET, lightGridBounds.ToFloatPtr() ); + // individual probe sizes on the atlas image + idVec4 probeSize; + probeSize[0] = currentSpace->lightGridAtlasSingleProbeSize - currentSpace->lightGridAtlasBorderSize; + probeSize[1] = currentSpace->lightGridAtlasSingleProbeSize; + probeSize[2] = currentSpace->lightGridAtlasBorderSize; + probeSize[3] = float( currentSpace->lightGridAtlasSingleProbeSize - currentSpace->lightGridAtlasBorderSize ) / currentSpace->lightGridAtlasSingleProbeSize; + renderProgManager.SetUniformValue( RENDERPARM_SCREENCORRECTIONFACTOR, probeSize.ToFloatPtr() ); // rpScreenCorrectionFactor + if( specUsage == TD_SPECULAR_PBR_RMAO || specUsage == TD_SPECULAR_PBR_RMAOD ) { // PBR path with roughness, metal and AO @@ -1397,9 +1405,9 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas #endif GL_SelectTexture( INTERACTION_TEXUNIT_AMBIENT_CUBE1 ); - currentSpace->irradianceAtlasImage->Bind(); + currentSpace->lightGridAtlasImage->Bind(); - idVec2i res = currentSpace->irradianceAtlasImage->GetUploadResolution(); + idVec2i res = currentSpace->lightGridAtlasImage->GetUploadResolution(); idVec4 textureSize( res.x, res.y, 1.0f / res.x, 1.0f / res.y ); renderProgManager.SetUniformValue( RENDERPARM_CASCADEDISTANCES, textureSize.ToFloatPtr() ); diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index 4c5a947e..90413b40 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -452,7 +452,9 @@ struct viewEntity_t // RB: use light grid of the best area this entity is in bool useLightGrid; - idImage* irradianceAtlasImage; + idImage* lightGridAtlasImage; + int lightGridAtlasSingleProbeSize; // including border + int lightGridAtlasBorderSize; idVec3 lightGridOrigin; idVec3 lightGridSize; @@ -513,7 +515,8 @@ struct calcEnvprobeParms_t -static const int LIGHTGRID_IRRADIANCE_SIZE = ( 16 * 1 ) + 2; +static const int LIGHTGRID_IRRADIANCE_BORDER_SIZE = 2; // one pixel border all around the octahedron so 2 on each side +static const int LIGHTGRID_IRRADIANCE_SIZE = ( 16 * 1 ) + LIGHTGRID_IRRADIANCE_BORDER_SIZE; struct calcLightGridPointParms_t { diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index 1ec68587..402ecae2 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -2883,11 +2883,15 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " // offset by one pixel border bleed size for linear filtering\n" "#if 1\n" - " float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( 16.0 / 18.0 ) );\n" + " // rpScreenCorrectionFactor.x = probeSize - borderSize, e.g. ( 18 - 2 ) = 16\n" + " // rpScreenCorrectionFactor.y = probeSize including border, e.g = 18\n" + " // rpScreenCorrectionFactor.z = borderSize e.g = 2\n" + " // rpScreenCorrectionFactor.w = probeSize factor accounting account offset border, e.g = ( 16 / 18 ) = 0.8888\n" + " float2 octCoordNormalizedToTextureDimensions = normalizedOctCoordZeroOne * rpScreenCorrectionFactor.w;\n" "\n" " float2 probeTopLeftPosition;\n" - " probeTopLeftPosition.x = ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * 2.0 + 1.0;\n" - " probeTopLeftPosition.y = ( gridCoord[1] ) * 2.0 + 1.0;\n" + " probeTopLeftPosition.x = ( gridCoord[0] * gridStep[0] + gridCoord[2] * gridStep[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5;\n" + " probeTopLeftPosition.y = ( gridCoord[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5;\n" "\n" " float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw;\n" "\n" @@ -5592,11 +5596,13 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " // offset by one pixel border bleed size for linear filtering\n" "#if 1\n" - " float2 octCoordNormalizedToTextureDimensions = ( ( normalizedOctCoordZeroOne + atlasOffset ) * ( 16.0 / 18.0 ) );\n" + " // rpScreenCorrectionFactor.w = probeSize factor accounting account offset border, e.g = ( 16 / 18 ) = 0.8888\n" + " float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne + atlasOffset ) * rpScreenCorrectionFactor.w;\n" "\n" + " // rpScreenCorrectionFactor.z = borderSize e.g = 2\n" " float2 probeTopLeftPosition;\n" - " probeTopLeftPosition.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * 2.0 + 1.0;\n" - " probeTopLeftPosition.y = ( gridCoord2[1] ) * 2.0 + 1.0;\n" + " probeTopLeftPosition.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5;\n" + " probeTopLeftPosition.y = ( gridCoord2[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5;\n" "\n" " float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw;\n" "\n" diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 760640a0..47961442 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -35,15 +35,13 @@ If you have questions concerning this license or the applicable additional terms #define LGRID_FILE_EXT "lightgrid" #define LGRID_BINARYFILE_EXT "blightgrid" #define LGRID_FILEID "LGRID" -#define LGRID_FILEVERSION "1.00" #define STORE_LIGHTGRID_SHDATA 0 -static const byte BLGRID_VERSION = 2; +static const byte BLGRID_VERSION = 3; static const unsigned int BLGRID_MAGIC = ( 'P' << 24 ) | ( 'R' << 16 ) | ( 'O' << 8 ) | BLGRID_VERSION; - static const int MAX_LIGHTGRID_ATLAS_SIZE = 2048; static const int MAX_AREA_LIGHTGRID_POINTS = ( MAX_LIGHTGRID_ATLAS_SIZE / LIGHTGRID_IRRADIANCE_SIZE ) * ( MAX_LIGHTGRID_ATLAS_SIZE / LIGHTGRID_IRRADIANCE_SIZE ); @@ -53,6 +51,8 @@ LightGrid::LightGrid() area = -1; irradianceImage = NULL; + imageSingleProbeSize = LIGHTGRID_IRRADIANCE_SIZE; + imageBorderSize = LIGHTGRID_IRRADIANCE_BORDER_SIZE; } void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, const idRenderWorld* world, int _area, int limit ) @@ -64,6 +64,9 @@ void LightGrid::SetupLightGrid( const idBounds& bounds, const char* mapName, con area = _area; + imageSingleProbeSize = LIGHTGRID_IRRADIANCE_SIZE; + imageBorderSize = LIGHTGRID_IRRADIANCE_BORDER_SIZE; + idVec3 maxs; int j = 0; @@ -443,7 +446,7 @@ void idRenderWorldLocal::WriteLightGridsToFile( const char* filename ) } // write file id and version - fp->WriteFloatString( "%s \"%s\"\n\n", LGRID_FILEID, LGRID_FILEVERSION ); + fp->WriteFloatString( "%s \"%i\"\n\n", LGRID_FILEID, BLGRID_VERSION ); // write the map file crc //fp->WriteFloatString( "%u\n\n", mapFileCRC ); @@ -460,9 +463,7 @@ void idRenderWorldLocal::WriteLightGridsToFile( const char* filename ) void idRenderWorldLocal::WriteLightGrid( idFile* fp, const LightGrid& lightGrid ) { - // TODO write used irradiance resolution - - fp->WriteFloatString( "lightGridPoints { /* area = */ %i /* numLightGridPoints = */ %i\n", lightGrid.area, lightGrid.lightGridPoints.Num() ); + fp->WriteFloatString( "lightGridPoints { /* area = */ %i /* numLightGridPoints = */ %i /* imageSingleProbeSize = */ %i /* imageBorderSize = */ %i \n", lightGrid.area, lightGrid.lightGridPoints.Num(), lightGrid.imageSingleProbeSize, lightGrid.imageBorderSize ); fp->WriteFloatString( "/* gridMins */ " ); fp->WriteFloatString( "\t ( %f %f %f )\n", lightGrid.lightGridOrigin[0], lightGrid.lightGridOrigin[1], lightGrid.lightGridOrigin[2] ); @@ -522,15 +523,10 @@ bool idRenderWorldLocal::LoadLightGridFile( const char* name ) if( file != NULL ) { int numEntries = 0; - //int magic = 0; + int magic = 0; + file->ReadBig( magic ); file->ReadBig( numEntries ); - //file->ReadString( mapName ); - //file->ReadBig( crc ); - idStrStatic< 32 > fileID; - idStrStatic< 32 > fileVersion; - file->ReadString( fileID ); - file->ReadString( fileVersion ); - if( fileID == LGRID_FILEID && fileVersion == LGRID_FILEVERSION ) //&& crc == mapFileCRC && numEntries > 0 ) + if( magic == BLGRID_MAGIC && numEntries > 0 ) { loaded = true; for( int i = 0; i < numEntries; i++ ) @@ -566,11 +562,9 @@ bool idRenderWorldLocal::LoadLightGridFile( const char* name ) idFileLocal outputFile( fileSystem->OpenFileWrite( generatedFileName, "fs_basepath" ) ); if( outputFile != NULL ) { + int magic = BLGRID_MAGIC; + outputFile->WriteBig( magic ); outputFile->WriteBig( numEntries ); - //outputFile->WriteString( mapName ); - //outputFile->WriteBig( mapFileCRC ); - outputFile->WriteString( LGRID_FILEID ); - outputFile->WriteString( LGRID_FILEVERSION ); } if( !src->ExpectTokenString( LGRID_FILEID ) ) @@ -580,9 +574,35 @@ bool idRenderWorldLocal::LoadLightGridFile( const char* name ) return false; } - if( !src->ReadToken( &token ) || token != LGRID_FILEVERSION ) + int lightGridVersion = 0; + if( !src->ReadToken( &token ) ) { - common->Warning( "%s has version %s instead of %s", fileName.c_str(), token.c_str(), LGRID_FILEVERSION ); + src->Error( "couldn't read expected integer" ); + delete src; + return false; + } + if( token.type == TT_PUNCTUATION && token == "-" ) + { + src->ExpectTokenType( TT_NUMBER, TT_INTEGER, &token ); + lightGridVersion = -( ( signed int ) token.GetIntValue() ); + } + else if( token.type != TT_NUMBER && token.subtype != TT_STRING && token.subtype != TT_NAME ) + { + src->Error( "expected integer value or string, found '%s'", token.c_str() ); + } + + if( token.type == TT_NUMBER ) + { + lightGridVersion = token.GetIntValue(); + } + else if( token.type == TT_STRING || token.subtype == TT_NAME ) + { + lightGridVersion = atoi( token ); + } + + if( lightGridVersion != BLGRID_VERSION ) + { + common->Warning( "%s has version %i instead of %i", fileName.c_str(), lightGridVersion, BLGRID_VERSION ); delete src; return false; } @@ -626,6 +646,8 @@ bool idRenderWorldLocal::LoadLightGridFile( const char* name ) if( outputFile != NULL ) { outputFile->Seek( 0, FS_SEEK_SET ); + int magic = BLGRID_MAGIC; + outputFile->WriteBig( magic ); outputFile->WriteBig( numEntries ); } } @@ -651,6 +673,20 @@ void idRenderWorldLocal::ParseLightGridPoints( idLexer* src, idFile* fileOut ) return; } + int imageProbeSize = src->ParseInt(); + if( imageProbeSize < 8 ) + { + src->Error( "ParseLightGridPoints: bad single image probe size %i", imageProbeSize ); + return; + } + + int imageBorderSize = src->ParseInt(); + if( imageBorderSize < 0 ) + { + src->Error( "ParseLightGridPoints: bad probe border size %i", imageBorderSize ); + return; + } + if( fileOut != NULL ) { // write out the type so the binary reader knows what to instantiate @@ -660,6 +696,9 @@ void idRenderWorldLocal::ParseLightGridPoints( idLexer* src, idFile* fileOut ) portalArea_t* area = &portalAreas[areaIndex]; area->lightGrid.area = areaIndex; + area->lightGrid.imageSingleProbeSize = imageProbeSize; + area->lightGrid.imageBorderSize = imageBorderSize; + // gridMins src->Parse1DMatrix( 3, area->lightGrid.lightGridOrigin.ToFloatPtr() ); src->Parse1DMatrix( 3, area->lightGrid.lightGridSize.ToFloatPtr() ); @@ -674,11 +713,14 @@ void idRenderWorldLocal::ParseLightGridPoints( idLexer* src, idFile* fileOut ) idLib::Printf( "area %i grid size (%i %i %i)\n", areaIndex, ( int )area->lightGrid.lightGridSize[0], ( int )area->lightGrid.lightGridSize[1], ( int )area->lightGrid.lightGridSize[2] ); idLib::Printf( "area %i grid bounds (%i %i %i)\n", areaIndex, ( int )area->lightGrid.lightGridBounds[0], ( int )area->lightGrid.lightGridBounds[1], ( int )area->lightGrid.lightGridBounds[2] ); idLib::Printf( "area %i %9u x %" PRIuSIZE " = lightGridSize = (%.2fMB)\n", areaIndex, numLightGridPoints, sizeof( lightGridPoint_t ), ( float )( area->lightGrid.lightGridPoints.MemoryUsed() ) / ( 1024.0f * 1024.0f ) ); + idLib::Printf( "area %i probe size (%i %i)\n", areaIndex, imageProbeSize, imageBorderSize ); if( fileOut != NULL ) { fileOut->WriteBig( areaIndex ); fileOut->WriteBig( numLightGridPoints ); + fileOut->WriteBig( imageProbeSize ); + fileOut->WriteBig( imageBorderSize ); fileOut->WriteBig( area->lightGrid.lightGridOrigin ); fileOut->WriteBig( area->lightGrid.lightGridSize ); fileOut->WriteBigArray( area->lightGrid.lightGridBounds, 3 ); @@ -728,9 +770,28 @@ void idRenderWorldLocal::ReadBinaryLightGridPoints( idFile* file ) return; } + int imageProbeSize = 0; + file->ReadBig( imageProbeSize ); + if( imageProbeSize < 0 ) + { + idLib::Error( "ReadBinaryLightGridPoints: bad imageProbeSize %i", imageProbeSize ); + return; + } + + int imageBorderSize = 0; + file->ReadBig( imageBorderSize ); + if( imageBorderSize < 0 ) + { + idLib::Error( "ReadBinaryLightGridPoints: bad imageBorderSize %i", imageBorderSize ); + return; + } + portalArea_t* area = &portalAreas[areaIndex]; area->lightGrid.area = areaIndex; + area->lightGrid.imageSingleProbeSize = imageProbeSize; + area->lightGrid.imageBorderSize = imageBorderSize; + // gridMins file->ReadBig( area->lightGrid.lightGridOrigin ); file->ReadBig( area->lightGrid.lightGridSize ); @@ -742,6 +803,7 @@ void idRenderWorldLocal::ReadBinaryLightGridPoints( idFile* file ) idLib::Printf( "area %i grid size (%i %i %i)\n", areaIndex, ( int )area->lightGrid.lightGridSize[0], ( int )area->lightGrid.lightGridSize[1], ( int )area->lightGrid.lightGridSize[2] ); idLib::Printf( "area %i grid bounds (%i %i %i)\n", areaIndex, ( int )area->lightGrid.lightGridBounds[0], ( int )area->lightGrid.lightGridBounds[1], ( int )area->lightGrid.lightGridBounds[2] ); idLib::Printf( "area %i %9u x %" PRIuSIZE " = lightGridSize = (%.2fMB)\n", areaIndex, numLightGridPoints, sizeof( lightGridPoint_t ), ( float )( area->lightGrid.lightGridPoints.MemoryUsed() ) / ( 1024.0f * 1024.0f ) ); + idLib::Printf( "area %i probe size (%i %i)\n", areaIndex, imageProbeSize, imageBorderSize ); for( int i = 0; i < numLightGridPoints; i++ ) { diff --git a/neo/renderer/RenderWorld_local.h b/neo/renderer/RenderWorld_local.h index ac5d292c..512d2438 100644 --- a/neo/renderer/RenderWorld_local.h +++ b/neo/renderer/RenderWorld_local.h @@ -80,6 +80,8 @@ public: int area; idImage* irradianceImage; + int imageSingleProbeSize; // including border + int imageBorderSize; LightGrid(); diff --git a/neo/renderer/tr_frontend_addmodels.cpp b/neo/renderer/tr_frontend_addmodels.cpp index 7affc283..c73e8fd4 100644 --- a/neo/renderer/tr_frontend_addmodels.cpp +++ b/neo/renderer/tr_frontend_addmodels.cpp @@ -560,7 +560,9 @@ void R_AddSingleModel( viewEntity_t* vEntity ) if( ref->area->lightGrid.lightGridPoints.Num() && lightGridImage && !lightGridImage->IsDefaulted() ) { vEntity->useLightGrid = true; - vEntity->irradianceAtlasImage = lightGridImage; + vEntity->lightGridAtlasImage = lightGridImage; + vEntity->lightGridAtlasSingleProbeSize = ref->area->lightGrid.imageSingleProbeSize; + vEntity->lightGridAtlasBorderSize = ref->area->lightGrid.imageBorderSize; for( int i = 0; i < 3; i++ ) { diff --git a/neo/tools/compilers/dmap/map.cpp b/neo/tools/compilers/dmap/map.cpp index e2024788..82a41a50 100644 --- a/neo/tools/compilers/dmap/map.cpp +++ b/neo/tools/compilers/dmap/map.cpp @@ -3,7 +3,7 @@ Doom 3 GPL Source Code Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. -Copyright (C) 2013-2015 Robert Beckebans +Copyright (C) 2013-2021 Robert Beckebans This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?). From b96b085d0438509f87fbabca3f6fe84e2789257e Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Tue, 27 Apr 2021 14:15:11 +0200 Subject: [PATCH 23/26] Don't use 1 pixel border for non-lightgrid octahedrons --- .../builtin/debug/octahedron.ps.hlsl | 2 + .../lighting/ambient_lighting_IBL.ps.hlsl | 26 ++++++- neo/renderer/Framebuffer.h | 2 +- neo/renderer/RenderBackend.cpp | 2 +- neo/renderer/RenderCommon.h | 4 +- neo/renderer/RenderProgs_embedded.h | 28 ++++++- neo/renderer/RenderSystem_init.cpp | 2 + neo/renderer/RenderWorld_defs.cpp | 4 +- neo/renderer/RenderWorld_envprobes.cpp | 21 +++-- neo/renderer/RenderWorld_lightgrid.cpp | 76 +++---------------- 10 files changed, 83 insertions(+), 84 deletions(-) diff --git a/base/renderprogs/builtin/debug/octahedron.ps.hlsl b/base/renderprogs/builtin/debug/octahedron.ps.hlsl index 7f8170ab..0ad3c269 100644 --- a/base/renderprogs/builtin/debug/octahedron.ps.hlsl +++ b/base/renderprogs/builtin/debug/octahedron.ps.hlsl @@ -59,12 +59,14 @@ void main( PS_IN fragment, out PS_OUT result ) float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5; // offset by one pixel border bleed size for linear filtering +#if 0 float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( rpCascadeDistances.x - float( 2.0 ) ) ) / rpCascadeDistances.xy; float2 probeTopLeftPosition = float2( 1.0, 1.0 ); float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw; normalizedOctCoordZeroOne.xy = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions; +#endif //normalizedOctCoordZeroOne = TextureCoordFromDirection( reflectionVector, 0, int( rpCascadeDistances.x ), int( rpCascadeDistances.y ), int( rpCascadeDistances.x ) - 2 ); diff --git a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl index 582324ec..7593007c 100644 --- a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl @@ -119,6 +119,26 @@ bool AABBRayIntersection( float3 b[2], float3 start, float3 dir, out float scale hit[ax2] >= b[0][ax2] && hit[ax2] <= b[1][ax2] ); } + +float2 OctTexCoord( float3 worldDir ) +{ + float2 normalizedOctCoord = octEncode( worldDir ); + float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5; + + // offset by one pixel border bleed size for linear filtering +#if 0 + // texcoord sizes in rpCascadeDistances are not valid + float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( rpCascadeDistances.x - float( 2.0 ) ) ) / rpCascadeDistances.xy; + + float2 probeTopLeftPosition = float2( 1.0, 1.0 ); + float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw; + + normalizedOctCoordZeroOne.xy = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions; +#endif + + return normalizedOctCoordZeroOne; +} + void main( PS_IN fragment, out PS_OUT result ) { half4 bumpMap = tex2D( samp0, fragment.texcoord0.xy ); @@ -236,8 +256,7 @@ void main( PS_IN fragment, out PS_OUT result ) // evaluate diffuse IBL - float2 normalizedOctCoord = octEncode( globalNormal ); - float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5; + float2 normalizedOctCoordZeroOne = OctTexCoord( globalNormal ); float3 irradiance = tex2D( samp7, normalizedOctCoordZeroOne ).rgb; float3 diffuseLight = ( kD * irradiance * diffuseColor ) * ao * ( rpDiffuseModifier.xyz * 1.0 ); @@ -249,8 +268,7 @@ void main( PS_IN fragment, out PS_OUT result ) float mip = clamp( ( roughness * MAX_REFLECTION_LOD ), 0.0, MAX_REFLECTION_LOD ); //float mip = 0.0; - normalizedOctCoord = octEncode( reflectionVector ); - normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5; + normalizedOctCoordZeroOne = OctTexCoord( reflectionVector ); float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb; //radiance = float3( 0.0 ); diff --git a/neo/renderer/Framebuffer.h b/neo/renderer/Framebuffer.h index 3a455ff4..2fc7e8cf 100644 --- a/neo/renderer/Framebuffer.h +++ b/neo/renderer/Framebuffer.h @@ -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 RADIANCE_CUBEMAP_SIZE = 256; -static const int IRRADIANCE_CUBEMAP_SIZE = 34; +static const int IRRADIANCE_CUBEMAP_SIZE = 30 + 2; #if 1 static int shadowMapResolutions[MAX_SHADOWMAP_RESOLUTIONS] = { 2048, 1024, 512, 512, 256 }; diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 3ddb88af..3beb3125 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -1323,7 +1323,7 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas const textureUsage_t specUsage = din->specularImage->GetUsage(); // RB begin - if( useIBL && currentSpace->useLightGrid ) + if( useIBL && currentSpace->useLightGrid && r_useLightGrid.GetBool() ) { idVec4 probeMins, probeMaxs, probeCenter; diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index 90413b40..248d4102 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -516,7 +516,7 @@ struct calcEnvprobeParms_t static const int LIGHTGRID_IRRADIANCE_BORDER_SIZE = 2; // one pixel border all around the octahedron so 2 on each side -static const int LIGHTGRID_IRRADIANCE_SIZE = ( 16 * 1 ) + LIGHTGRID_IRRADIANCE_BORDER_SIZE; +static const int LIGHTGRID_IRRADIANCE_SIZE = 30 + LIGHTGRID_IRRADIANCE_BORDER_SIZE; struct calcLightGridPointParms_t { @@ -1208,6 +1208,8 @@ extern idCVar r_pbrDebug; extern idCVar r_showViewEnvprobes; extern idCVar r_showLightGrid; // show Quake 3 style light grid points +extern idCVar r_useLightGrid; + extern idCVar r_exposure; // RB end diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index 402ecae2..c56b7ce6 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -2628,12 +2628,14 @@ static const cgShaderDef_t cg_renderprogs[] = " float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n" "\n" " // offset by one pixel border bleed size for linear filtering\n" + "#if 0\n" " float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( rpCascadeDistances.x - float( 2.0 ) ) ) / rpCascadeDistances.xy;\n" "\n" " float2 probeTopLeftPosition = float2( 1.0, 1.0 );\n" " float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw;\n" "\n" " normalizedOctCoordZeroOne.xy = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions;\n" + "#endif\n" "\n" " //normalizedOctCoordZeroOne = TextureCoordFromDirection( reflectionVector, 0, int( rpCascadeDistances.x ), int( rpCascadeDistances.y ), int( rpCascadeDistances.x ) - 2 );\n" "\n" @@ -4884,6 +4886,26 @@ static const cgShaderDef_t cg_renderprogs[] = " hit[ax2] >= b[0][ax2] && hit[ax2] <= b[1][ax2] );\n" "}\n" "\n" + "\n" + "float2 OctTexCoord( float3 worldDir )\n" + "{\n" + " float2 normalizedOctCoord = octEncode( worldDir );\n" + " float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n" + "\n" + " // offset by one pixel border bleed size for linear filtering\n" + "#if 0\n" + " // texcoord sizes in rpCascadeDistances are not valid\n" + " float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne * ( rpCascadeDistances.x - float( 2.0 ) ) ) / rpCascadeDistances.xy;\n" + "\n" + " float2 probeTopLeftPosition = float2( 1.0, 1.0 );\n" + " float2 normalizedProbeTopLeftPosition = probeTopLeftPosition * rpCascadeDistances.zw;\n" + "\n" + " normalizedOctCoordZeroOne.xy = normalizedProbeTopLeftPosition + octCoordNormalizedToTextureDimensions;\n" + "#endif\n" + "\n" + " return normalizedOctCoordZeroOne;\n" + "}\n" + "\n" "void main( PS_IN fragment, out PS_OUT result )\n" "{\n" " half4 bumpMap = tex2D( samp0, fragment.texcoord0.xy );\n" @@ -5001,8 +5023,7 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " // evaluate diffuse IBL\n" "\n" - " float2 normalizedOctCoord = octEncode( globalNormal );\n" - " float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n" + " float2 normalizedOctCoordZeroOne = OctTexCoord( globalNormal );\n" "\n" " float3 irradiance = tex2D( samp7, normalizedOctCoordZeroOne ).rgb;\n" " float3 diffuseLight = ( kD * irradiance * diffuseColor ) * ao * ( rpDiffuseModifier.xyz * 1.0 );\n" @@ -5014,8 +5035,7 @@ static const cgShaderDef_t cg_renderprogs[] = " float mip = clamp( ( roughness * MAX_REFLECTION_LOD ), 0.0, MAX_REFLECTION_LOD );\n" " //float mip = 0.0;\n" "\n" - " normalizedOctCoord = octEncode( reflectionVector );\n" - " normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n" + " normalizedOctCoordZeroOne = OctTexCoord( reflectionVector );\n" "\n" " float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb;\n" " //radiance = float3( 0.0 );\n" diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index 4b5ac273..63e97e76 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -301,6 +301,8 @@ idCVar r_pbrDebug( "r_pbrDebug", "0", CVAR_RENDERER | CVAR_INTEGER, "show which idCVar r_showViewEnvprobes( "r_showViewEnvprobes", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = displays the bounding boxes of all view environment probes, 2 = show irradiance" ); idCVar r_showLightGrid( "r_showLightGrid", "0", CVAR_RENDERER | CVAR_INTEGER, "show Quake 3 style light grid points" ); +idCVar r_useLightGrid( "r_useLightGrid", "1", CVAR_RENDERER | CVAR_BOOL, "" ); + idCVar r_exposure( "r_exposure", "0.5", CVAR_ARCHIVE | CVAR_RENDERER | CVAR_FLOAT, "HDR exposure or LDR brightness [0.0 .. 1.0]", 0.0f, 1.0f ); // RB end diff --git a/neo/renderer/RenderWorld_defs.cpp b/neo/renderer/RenderWorld_defs.cpp index e8df5681..bbac89d2 100644 --- a/neo/renderer/RenderWorld_defs.cpp +++ b/neo/renderer/RenderWorld_defs.cpp @@ -769,10 +769,10 @@ void R_DeriveEnvprobeData( RenderEnvprobeLocal* probe ) // TODO get preconvolved cubemaps fullname.Format( "env/%s/envprobe%i_amb", basename.c_str(), probeIndex ); - probe->irradianceImage = globalImages->ImageFromFile( fullname, TF_LINEAR, TR_REPEAT, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); + probe->irradianceImage = globalImages->ImageFromFile( fullname, TF_LINEAR, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); fullname.Format( "env/%s/envprobe%i_spec", basename.c_str(), probeIndex ); - probe->radianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_REPEAT, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); + probe->radianceImage = globalImages->ImageFromFile( fullname, TF_DEFAULT, TR_CLAMP, TD_R11G11B10F, CF_2D_PACKED_MIPCHAIN ); // ------------------------------------ // compute the probe projection matrix diff --git a/neo/renderer/RenderWorld_envprobes.cpp b/neo/renderer/RenderWorld_envprobes.cpp index c05ce36d..0ada648b 100644 --- a/neo/renderer/RenderWorld_envprobes.cpp +++ b/neo/renderer/RenderWorld_envprobes.cpp @@ -467,6 +467,7 @@ idVec2 NormalizedOctCoord( int x, int y, const int probeWithBorderSide ) const int margin = 2; // RB: FIXME - margin * 2 is wrong but looks better + // figure out why int probeSideLength = Max( 2, probeWithBorderSide - ( margin * 2 ) ); idVec2 octFragCoord = idVec2( ( x - margin ) % probeWithBorderSide, ( y - margin ) % probeWithBorderSide ); @@ -477,6 +478,16 @@ idVec2 NormalizedOctCoord( int x, int y, const int probeWithBorderSide ) #endif } +static inline idVec2 NormalizedOctCoordNoBorder( int x, int y, const int probeWithBorderSide ) +{ + int probeSideLength = probeWithBorderSide; + + idVec2 octFragCoord = idVec2( x % probeWithBorderSide, y % 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 ); +} + /* static inline float LatLongTexelArea( const idVec2i& pos, const idVec2i& imageSize ) { @@ -615,7 +626,7 @@ void CalculateIrradianceJob( calcEnvprobeParms_t* parms ) { for( int y = dstRect.y; y < ( dstRect.y + dstRect.w ); y++ ) { - idVec2 octCoord = NormalizedOctCoord( x, y, dstRect.z ); + idVec2 octCoord = NormalizedOctCoordNoBorder( x, y, dstRect.z ); // convert UV coord to 3D direction idVec3 dir; @@ -727,11 +738,11 @@ void CalculateIrradianceJob( calcEnvprobeParms_t* parms ) if( mip > 0 ) { // move back to [0, 1] coords - octCoord = NormalizedOctCoord( x - dstRect.x, y - dstRect.y, dstRect.z ); + octCoord = NormalizedOctCoordNoBorder( x - dstRect.x, y - dstRect.y, dstRect.z ); } else { - octCoord = NormalizedOctCoord( x, y, dstRect.z ); + octCoord = NormalizedOctCoordNoBorder( x, y, dstRect.z ); } // convert UV coord to 3D direction @@ -838,11 +849,11 @@ void CalculateRadianceJob( calcEnvprobeParms_t* parms ) if( mip > 0 ) { // move back to [0, 1] coords - octCoord = NormalizedOctCoord( x - dstRect.x, y - dstRect.y, dstRect.z ); + octCoord = NormalizedOctCoordNoBorder( x - dstRect.x, y - dstRect.y, dstRect.z ); } else { - octCoord = NormalizedOctCoord( x, y, dstRect.z ); + octCoord = NormalizedOctCoordNoBorder( x, y, dstRect.z ); } // convert UV coord to 3D direction diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index 47961442..d19e0c1b 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -38,7 +38,7 @@ If you have questions concerning this license or the applicable additional terms #define STORE_LIGHTGRID_SHDATA 0 -static const byte BLGRID_VERSION = 3; +static const byte BLGRID_VERSION = 4; static const unsigned int BLGRID_MAGIC = ( 'P' << 24 ) | ( 'R' << 16 ) | ( 'O' << 8 ) | BLGRID_VERSION; @@ -513,7 +513,7 @@ bool idRenderWorldLocal::LoadLightGridFile( const char* name ) // if we are reloading the same map, check the timestamp // and try to skip all the work - ID_TIME_T currentTimeStamp = fileSystem->GetTimestamp( fileName ); + ID_TIME_T sourceTimeStamp = fileSystem->GetTimestamp( fileName ); // see if we have a generated version of this bool loaded = false; @@ -524,11 +524,14 @@ bool idRenderWorldLocal::LoadLightGridFile( const char* name ) { int numEntries = 0; int magic = 0; + ID_TIME_T storedTimeStamp; file->ReadBig( magic ); + file->ReadBig( storedTimeStamp ); file->ReadBig( numEntries ); - if( magic == BLGRID_MAGIC && numEntries > 0 ) + if( ( magic == BLGRID_MAGIC ) && ( sourceTimeStamp == storedTimeStamp ) && ( numEntries > 0 ) ) { loaded = true; + for( int i = 0; i < numEntries; i++ ) { idStrStatic< MAX_OSPATH > type; @@ -564,6 +567,7 @@ bool idRenderWorldLocal::LoadLightGridFile( const char* name ) { int magic = BLGRID_MAGIC; outputFile->WriteBig( magic ); + outputFile->WriteBig( sourceTimeStamp ); outputFile->WriteBig( numEntries ); } @@ -646,8 +650,10 @@ bool idRenderWorldLocal::LoadLightGridFile( const char* name ) if( outputFile != NULL ) { outputFile->Seek( 0, FS_SEEK_SET ); + int magic = BLGRID_MAGIC; outputFile->WriteBig( magic ); + outputFile->WriteBig( sourceTimeStamp ); outputFile->WriteBig( numEntries ); } } @@ -913,58 +919,6 @@ void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) shRadiance[i].Zero(); } -#if 0 - - // build SH by only iterating over the octahedron - // RB: not used because I don't know the texel area of an octahedron pixel and the cubemap texel area is too small - // however it would be nice to use this because it would be 6 times faster - - idVec4 dstRect = R_CalculateMipRect( parms->outHeight, 0 ); - - for( int x = dstRect.x; x < ( dstRect.x + dstRect.z ); x++ ) - { - for( int y = dstRect.y; y < ( dstRect.y + dstRect.w ); y++ ) - { - idVec2 octCoord = NormalizedOctCoord( x, y, dstRect.z ); - - // convert UV coord to 3D direction - idVec3 dir; - - dir.FromOctahedral( octCoord ); - - float u, v; - idVec3 radiance; - R_SampleCubeMapHDR( dir, parms->outHeight, buffers, &radiance[0], u, v ); - - //radiance = dir * 0.5 + idVec3( 0.5f, 0.5f, 0.5f ); - - // convert from [0 .. size-1] to [-1.0 + invSize .. 1.0 - invSize] - const float uu = 2.0f * ( u * invDstSize ) - 1.0f; - const float vv = 2.0f * ( v * invDstSize ) - 1.0f; - - float texelArea = CubemapTexelSolidAngle( uu, vv, invDstSize ); - - const SphericalHarmonicsT& sh = shEvaluate<4>( dir ); - - bool shValid = true; - for( int i = 0; i < 25; i++ ) - { - if( IsNAN( sh[i] ) ) - { - shValid = false; - break; - } - } - - if( shValid ) - { - shAddWeighted( shRadiance, sh, radiance * texelArea ); - } - } - } - -#else - // build SH by iterating over all cubemap pixels for( int side = 0; side < 6; side++ ) @@ -1008,8 +962,6 @@ void CalculateLightGridPointJob( calcLightGridPointParms_t* parms ) } } -#endif - for( int i = 0; i < shSize( 3 ); i++ ) { parms->shRadiance[i] = shRadiance[i]; @@ -1259,7 +1211,7 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) lightGridPoint_t* gridPoint = &area->lightGrid.lightGridPoints[ gridCoord[0] * gridStep[0] + gridCoord[1] * gridStep[1] + gridCoord[2] * gridStep[2] ]; if( !gridPoint->valid ) { - progressBar.Increment(); + //progressBar.Increment(); continue; } @@ -1284,14 +1236,6 @@ CONSOLE_COMMAND( bakeLightGrids, "Bake irradiance/vis light grid data", NULL ) byte* float16FRGB = tr.CaptureRenderToBuffer( captureSize, captureSize, &ref ); jobParms->radiance[ side ] = float16FRGB; - -#if 0 - if( i < 3 ) - { - filename.Format( "env/%s/area%i_lightgridpoint%i%s.exr", baseName.c_str(), a, i, extension ); - R_WriteEXR( filename, float16FRGB, 3, size, size, "fs_basepath" ); - } -#endif } tr.lightGridJobs.Append( jobParms ); From 167085385be74516ba606d183a8b6a4c9ac98721 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Tue, 27 Apr 2021 19:14:55 +0200 Subject: [PATCH 24/26] Fixed bad lighting with objects behind the area light grid bounds --- .../builtin/lighting/ambient_lightgrid_IBL.ps.hlsl | 11 +++++++++-- neo/renderer/RenderProgs_embedded.h | 11 +++++++++-- neo/renderer/RenderWorld_lightgrid.cpp | 5 +++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl index d5271330..5490f298 100644 --- a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl @@ -263,15 +263,19 @@ void main( PS_IN fragment, out PS_OUT result ) { float v; - v = lightOrigin[i] * ( 1.0 / lightGridSize[i] ); + // walls can be sampled behind the grid sometimes so avoid negative weights + v = max( 0, lightOrigin[i] * ( 1.0 / lightGridSize[i] ) ); gridCoord[i] = int( floor( v ) ); frac[ i ] = v - gridCoord[ i ]; + /* if( gridCoord[i] < 0 ) { gridCoord[i] = 0; } - else if( gridCoord[i] >= lightGridBounds[i] - 1 ) + else + */ + if( gridCoord[i] >= lightGridBounds[i] - 1 ) { gridCoord[i] = lightGridBounds[i] - 1; } @@ -326,6 +330,9 @@ void main( PS_IN fragment, out PS_OUT result ) } } + // build P + //float3 P = lightGridOrigin + ( gridCoord2[0] * gridStep[0] + gridCoord2[1] * gridStep[1] + gridCoord2[2] * gridStep[2] ); + float2 atlasOffset; atlasOffset.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * invXZ; diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index c56b7ce6..ea58d2b5 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -5546,15 +5546,19 @@ static const cgShaderDef_t cg_renderprogs[] = " {\n" " float v;\n" "\n" - " v = lightOrigin[i] * ( 1.0 / lightGridSize[i] );\n" + " // walls can be sampled behind the grid sometimes so avoid negative weights\n" + " v = max( 0, lightOrigin[i] * ( 1.0 / lightGridSize[i] ) );\n" " gridCoord[i] = int( floor( v ) );\n" " frac[ i ] = v - gridCoord[ i ];\n" "\n" + " /*\n" " if( gridCoord[i] < 0 )\n" " {\n" " gridCoord[i] = 0;\n" " }\n" - " else if( gridCoord[i] >= lightGridBounds[i] - 1 )\n" + " else\n" + " */\n" + " if( gridCoord[i] >= lightGridBounds[i] - 1 )\n" " {\n" " gridCoord[i] = lightGridBounds[i] - 1;\n" " }\n" @@ -5609,6 +5613,9 @@ static const cgShaderDef_t cg_renderprogs[] = " }\n" " }\n" "\n" + " // build P\n" + " //float3 P = lightGridOrigin + ( gridCoord2[0] * gridStep[0] + gridCoord2[1] * gridStep[1] + gridCoord2[2] * gridStep[2] );\n" + "\n" " float2 atlasOffset;\n" "\n" " atlasOffset.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * invXZ;\n" diff --git a/neo/renderer/RenderWorld_lightgrid.cpp b/neo/renderer/RenderWorld_lightgrid.cpp index d19e0c1b..a69a0b90 100644 --- a/neo/renderer/RenderWorld_lightgrid.cpp +++ b/neo/renderer/RenderWorld_lightgrid.cpp @@ -35,6 +35,7 @@ If you have questions concerning this license or the applicable additional terms #define LGRID_FILE_EXT "lightgrid" #define LGRID_BINARYFILE_EXT "blightgrid" #define LGRID_FILEID "LGRID" +const byte LGRID_VERSION = 3; #define STORE_LIGHTGRID_SHDATA 0 @@ -604,9 +605,9 @@ bool idRenderWorldLocal::LoadLightGridFile( const char* name ) lightGridVersion = atoi( token ); } - if( lightGridVersion != BLGRID_VERSION ) + if( lightGridVersion != LGRID_VERSION ) { - common->Warning( "%s has version %i instead of %i", fileName.c_str(), lightGridVersion, BLGRID_VERSION ); + common->Warning( "%s has version %i instead of %i", fileName.c_str(), lightGridVersion, LGRID_VERSION ); delete src; return false; } From 0b4be8c73a5fb65ca723d1c7ab28e2d1600c6eb2 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Wed, 28 Apr 2021 15:44:33 +0200 Subject: [PATCH 25/26] Added interpolation of the 3 nearest reflection probes --- .../lighting/ambient_lightgrid_IBL.ps.hlsl | 12 +- .../lighting/ambient_lighting_IBL.ps.hlsl | 8 +- neo/renderer/OpenGL/RenderDebug_GL.cpp | 159 +++++++++++++++++- neo/renderer/RenderBackend.cpp | 52 +++--- neo/renderer/RenderCommon.h | 6 +- neo/renderer/RenderProgs_embedded.h | 20 ++- neo/renderer/tr_frontend_main.cpp | 144 +++++++++++++--- neo/renderer/tr_trisurf.cpp | 80 ++++++++- 8 files changed, 416 insertions(+), 65 deletions(-) diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl index 5490f298..a681d850 100644 --- a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl @@ -40,7 +40,11 @@ uniform sampler2D samp3 : register(s3); // texture 3 is the BRDF LUT uniform sampler2D samp4 : register(s4); // texture 4 is SSAO uniform sampler2D samp7 : register(s7); // texture 7 is the irradiance cube map -uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map +uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map 1 +uniform sampler2D samp9 : register(s9); // texture 9 is the radiance cube map 2 +uniform sampler2D samp10 : register(s10); // texture 10 is the radiance cube map 3 + +uniform float4 rpUser0 : register( c128 ); struct PS_IN { @@ -343,6 +347,7 @@ void main( PS_IN fragment, out PS_OUT result ) // rpScreenCorrectionFactor.w = probeSize factor accounting account offset border, e.g = ( 16 / 18 ) = 0.8888 float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne + atlasOffset ) * rpScreenCorrectionFactor.w; + // skip by default 2 pixels for each grid cell and offset the start position by (1,1) // rpScreenCorrectionFactor.z = borderSize e.g = 2 float2 probeTopLeftPosition; probeTopLeftPosition.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5; @@ -389,7 +394,10 @@ void main( PS_IN fragment, out PS_OUT result ) normalizedOctCoord = octEncode( reflectionVector ); normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5; - float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb; + float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpUser0.x; + radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpUser0.y; + radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpUser0.z; + //radiance = float3( 0.0 ); // RB: HACK dim down room radiance by better local irradiance brightness diff --git a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl index 7593007c..9859d3c6 100644 --- a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl @@ -40,7 +40,9 @@ uniform sampler2D samp3 : register(s3); // texture 3 is the BRDF LUT uniform sampler2D samp4 : register(s4); // texture 4 is SSAO uniform sampler2D samp7 : register(s7); // texture 7 is the irradiance cube map -uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map +uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map 1 +uniform sampler2D samp9 : register(s9); // texture 9 is the radiance cube map 2 +uniform sampler2D samp10 : register(s10); // texture 10 is the radiance cube map 3 struct PS_IN { @@ -270,7 +272,9 @@ void main( PS_IN fragment, out PS_OUT result ) normalizedOctCoordZeroOne = OctTexCoord( reflectionVector ); - float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb; + float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpGlobalLightOrigin.x; + radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpGlobalLightOrigin.y; + radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpGlobalLightOrigin.z; //radiance = float3( 0.0 ); float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg; diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index 7f24b73c..fed113ad 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -1702,9 +1702,38 @@ void idRenderBackend::DBG_ShowLights() ============== RB_ShowViewEnvprobes -Visualize all environemnt probes used in the current scene +Visualize all environment probes used in the current scene ============== */ +class idSort_DebugCompareViewEnvprobe : public idSort_Quick< RenderEnvprobeLocal*, idSort_DebugCompareViewEnvprobe > +{ + idVec3 viewOrigin; + +public: + idSort_DebugCompareViewEnvprobe( const idVec3& origin ) + { + viewOrigin = origin; + } + + int Compare( RenderEnvprobeLocal* const& a, RenderEnvprobeLocal* const& b ) const + { + float adist = ( viewOrigin - a->parms.origin ).LengthSqr(); + float bdist = ( viewOrigin - b->parms.origin ).LengthSqr(); + + if( adist < bdist ) + { + return -1; + } + + if( adist > bdist ) + { + return 1; + } + + return 0; + } +}; + void idRenderBackend::DBG_ShowViewEnvprobes() { if( !r_showViewEnvprobes.GetInteger() ) @@ -1794,6 +1823,134 @@ void idRenderBackend::DBG_ShowViewEnvprobes() } #endif } + + + //if( r_showViewEnvprobes.GetInteger() >= 3 ) + if( tr.primaryWorld ) + { + /* + idList viewEnvprobes; + for( viewEnvprobe_t* vProbe = viewDef->viewEnvprobes; vProbe != NULL; vProbe = vProbe->next ) + { + viewEnvprobes.AddUnique( vProbe ); + } + */ + + idList viewEnvprobes; + for( int i = 0; i < tr.primaryWorld->envprobeDefs.Num(); i++ ) + { + RenderEnvprobeLocal* vProbe = tr.primaryWorld->envprobeDefs[i]; + if( vProbe ) + { + viewEnvprobes.AddUnique( vProbe ); + } + } + + if( viewEnvprobes.Num() == 0 ) + { + return; + } + + idVec3 testOrigin = viewDef->renderView.vieworg; + //testOrigin += viewDef->renderView.viewaxis[0] * 150.0f; + //testOrigin -= viewDef->renderView.viewaxis[2] * 16.0f; + + // sort by distance + viewEnvprobes.SortWithTemplate( idSort_DebugCompareViewEnvprobe( testOrigin ) ); + + // draw 3 nearest probes + renderProgManager.BindShader_Color(); + + const int numColors = 3; + static idVec4 colors[numColors] = { colorRed, colorGreen, colorBlue }; + + // form a triangle of the 3 closest probes + idVec3 verts[3]; + for( int i = 0; i < 3; i++ ) + { + verts[i] = viewEnvprobes[0]->parms.origin; + } + + for( int i = 0; i < viewEnvprobes.Num() && i < 3; i++ ) + { + RenderEnvprobeLocal* vProbe = viewEnvprobes[i]; + + verts[i] = vProbe->parms.origin; + } + + idVec3 closest = R_ClosestPointPointTriangle( testOrigin, verts[0], verts[1], verts[2] ); + idVec3 barycentricWeights; + + // find the barycentric coordinates + float denom = idWinding::TriangleArea( verts[0], verts[1], verts[2] ); + if( denom == 0 ) + { + // all points at same location + barycentricWeights.Set( 1, 0, 0 ); + } + else + { + float a, b, c; + + a = idWinding::TriangleArea( closest, verts[1], verts[2] ) / denom; + b = idWinding::TriangleArea( closest, verts[2], verts[0] ) / denom; + c = idWinding::TriangleArea( closest, verts[0], verts[1] ) / denom; + + barycentricWeights.Set( a, b, c ); + } + + idMat3 axis; + axis.Identity(); + + for( int i = 0; i < viewEnvprobes.Num() && i < 3; i++ ) + { + RenderEnvprobeLocal* vProbe = viewEnvprobes[i]; + + verts[i] = vProbe->parms.origin; + + //GL_Color( colors[i] ); + + idVec4 color = Lerp( colorBlack, colors[i], barycentricWeights[i] ); + GL_Color( color ); + + idRenderMatrix modelRenderMatrix; + idRenderMatrix::CreateFromOriginAxis( vProbe->parms.origin, axis, modelRenderMatrix ); + + // calculate the matrix that transforms the unit cube to exactly cover the model in world space + const float size = 16.0f; + idBounds debugBounds( idVec3( -size ), idVec3( size ) ); + + idRenderMatrix inverseBaseModelProject; + idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject ); + + idRenderMatrix invProjectMVPMatrix; + idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix ); + RB_SetMVP( invProjectMVPMatrix ); + + DrawElementsWithCounters( &zeroOneSphereSurface ); + } + + // draw closest hit + { + GL_Color( colorYellow ); + + idRenderMatrix modelRenderMatrix; + idRenderMatrix::CreateFromOriginAxis( closest, axis, modelRenderMatrix ); + + // calculate the matrix that transforms the unit cube to exactly cover the model in world space + const float size = 4.0f; + idBounds debugBounds( idVec3( -size ), idVec3( size ) ); + + idRenderMatrix inverseBaseModelProject; + idRenderMatrix::OffsetScaleForBounds( modelRenderMatrix, debugBounds, inverseBaseModelProject ); + + idRenderMatrix invProjectMVPMatrix; + idRenderMatrix::Multiply( viewDef->worldSpace.mvp, inverseBaseModelProject, invProjectMVPMatrix ); + RB_SetMVP( invProjectMVPMatrix ); + + DrawElementsWithCounters( &zeroOneSphereSurface ); + } + } } void idRenderBackend::DBG_ShowLightGrid() diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 3beb3125..d3dfdd2f 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -1200,9 +1200,13 @@ const int INTERACTION_TEXUNIT_JITTER = 6; #if defined( USE_VULKAN ) const int INTERACTION_TEXUNIT_AMBIENT_CUBE1 = 5; const int INTERACTION_TEXUNIT_SPECULAR_CUBE1 = 6; + const int INTERACTION_TEXUNIT_SPECULAR_CUBE2 = 7; + const int INTERACTION_TEXUNIT_SPECULAR_CUBE3 = 8; #else const int INTERACTION_TEXUNIT_AMBIENT_CUBE1 = 7; const int INTERACTION_TEXUNIT_SPECULAR_CUBE1 = 8; + const int INTERACTION_TEXUNIT_SPECULAR_CUBE2 = 9; + const int INTERACTION_TEXUNIT_SPECULAR_CUBE3 = 10; #endif /* @@ -1344,8 +1348,6 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas SetVertexParm( RENDERPARM_WOBBLESKY_Y, probeMaxs.ToFloatPtr() ); SetVertexParm( RENDERPARM_WOBBLESKY_Z, probeCenter.ToFloatPtr() ); - //SetVertexParm( RENDERPARM_WOBBLESK_Z, probeCenter.ToFloatPtr() ); - // use rpGlobalLightOrigin for lightGrid center idVec4 lightGridOrigin( currentSpace->lightGridOrigin.x, currentSpace->lightGridOrigin.y, currentSpace->lightGridOrigin.z, 1.0f ); idVec4 lightGridSize( currentSpace->lightGridSize.x, currentSpace->lightGridSize.y, currentSpace->lightGridSize.z, 1.0f ); @@ -1363,6 +1365,9 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas probeSize[3] = float( currentSpace->lightGridAtlasSingleProbeSize - currentSpace->lightGridAtlasBorderSize ) / currentSpace->lightGridAtlasSingleProbeSize; renderProgManager.SetUniformValue( RENDERPARM_SCREENCORRECTIONFACTOR, probeSize.ToFloatPtr() ); // rpScreenCorrectionFactor + // specular cubemap blend weights + renderProgManager.SetUniformValue( RENDERPARM_USER0, viewDef->radianceImageBlends.ToFloatPtr() ); + if( specUsage == TD_SPECULAR_PBR_RMAO || specUsage == TD_SPECULAR_PBR_RMAOD ) { // PBR path with roughness, metal and AO @@ -1413,14 +1418,13 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas renderProgManager.SetUniformValue( RENDERPARM_CASCADEDISTANCES, textureSize.ToFloatPtr() ); GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE1 ); - if( viewDef->radianceImage ) - { - viewDef->radianceImage->Bind(); - } - else - { - globalImages->defaultUACRadianceCube->Bind(); - } + viewDef->radianceImages[0]->Bind(); + + GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE2 ); + viewDef->radianceImages[1]->Bind(); + + GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE3 ); + viewDef->radianceImages[2]->Bind(); } else if( useIBL ) { @@ -1443,6 +1447,9 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas SetVertexParm( RENDERPARM_WOBBLESKY_Y, probeMaxs.ToFloatPtr() ); SetVertexParm( RENDERPARM_WOBBLESKY_Z, probeCenter.ToFloatPtr() ); + // specular cubemap blend weights + renderProgManager.SetUniformValue( RENDERPARM_GLOBALLIGHTORIGIN, viewDef->radianceImageBlends.ToFloatPtr() ); + if( specUsage == TD_SPECULAR_PBR_RMAO || specUsage == TD_SPECULAR_PBR_RMAOD ) { // PBR path with roughness, metal and AO @@ -1484,26 +1491,17 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas } #endif - // TODO bind the 3 closest probes GL_SelectTexture( INTERACTION_TEXUNIT_AMBIENT_CUBE1 ); - if( viewDef->irradianceImage ) - { - viewDef->irradianceImage->Bind(); - } - else - { - globalImages->defaultUACIrradianceCube->Bind(); - } + viewDef->irradianceImage->Bind(); GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE1 ); - if( viewDef->radianceImage ) - { - viewDef->radianceImage->Bind(); - } - else - { - globalImages->defaultUACRadianceCube->Bind(); - } + viewDef->radianceImages[0]->Bind(); + + GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE2 ); + viewDef->radianceImages[1]->Bind(); + + GL_SelectTexture( INTERACTION_TEXUNIT_SPECULAR_CUBE3 ); + viewDef->radianceImages[2]->Bind(); } else if( setInteractionShader ) { diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index 248d4102..09ef1a09 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -648,7 +648,8 @@ struct viewDef_t idBounds globalProbeBounds; idRenderMatrix inverseBaseEnvProbeProject; // the matrix for deforming the 'zeroOneCubeModel' to exactly cover the environent probe volume in world space idImage* irradianceImage; // cubemap image used for diffuse IBL by backend - idImage* radianceImage; // cubemap image used for specular IBL by backend + idImage* radianceImages[3]; // cubemap image used for specular IBL by backend + idVec4 radianceImageBlends; // blending weights }; @@ -1613,6 +1614,9 @@ void R_InitDrawSurfFromTri( drawSurf_t& ds, srfTriangles_t& tri ); // time, rather than being re-created each frame in the frame temporary buffers. void R_CreateStaticBuffersForTri( srfTriangles_t& tri ); +// RB +idVec3 R_ClosestPointPointTriangle( const idVec3& point, const idVec3& vertex1, const idVec3& vertex2, const idVec3& vertex3 ); + // deformable meshes precalculate as much as possible from a base frame, then generate // complete srfTriangles_t from just a new set of vertexes struct deformInfo_t diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index ea58d2b5..04cbd26d 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -4807,7 +4807,9 @@ static const cgShaderDef_t cg_renderprogs[] = "uniform sampler2D samp4 : register(s4); // texture 4 is SSAO\n" "\n" "uniform sampler2D samp7 : register(s7); // texture 7 is the irradiance cube map\n" - "uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map\n" + "uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map 1\n" + "uniform sampler2D samp9 : register(s9); // texture 9 is the radiance cube map 2\n" + "uniform sampler2D samp10 : register(s10); // texture 10 is the radiance cube map 3\n" "\n" "struct PS_IN \n" "{\n" @@ -5037,7 +5039,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " normalizedOctCoordZeroOne = OctTexCoord( reflectionVector );\n" "\n" - " float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb;\n" + " float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpGlobalLightOrigin.x;\n" + " radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpGlobalLightOrigin.y;\n" + " radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpGlobalLightOrigin.z;\n" " //radiance = float3( 0.0 );\n" "\n" " float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg;\n" @@ -5323,7 +5327,11 @@ static const cgShaderDef_t cg_renderprogs[] = "uniform sampler2D samp4 : register(s4); // texture 4 is SSAO\n" "\n" "uniform sampler2D samp7 : register(s7); // texture 7 is the irradiance cube map\n" - "uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map\n" + "uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map 1\n" + "uniform sampler2D samp9 : register(s9); // texture 9 is the radiance cube map 2\n" + "uniform sampler2D samp10 : register(s10); // texture 10 is the radiance cube map 3\n" + "\n" + "uniform float4 rpUser0 : register( c128 );\n" "\n" "struct PS_IN \n" "{\n" @@ -5626,6 +5634,7 @@ static const cgShaderDef_t cg_renderprogs[] = " // rpScreenCorrectionFactor.w = probeSize factor accounting account offset border, e.g = ( 16 / 18 ) = 0.8888\n" " float2 octCoordNormalizedToTextureDimensions = ( normalizedOctCoordZeroOne + atlasOffset ) * rpScreenCorrectionFactor.w;\n" "\n" + " // skip by default 2 pixels for each grid cell and offset the start position by (1,1)\n" " // rpScreenCorrectionFactor.z = borderSize e.g = 2\n" " float2 probeTopLeftPosition;\n" " probeTopLeftPosition.x = ( gridCoord2[0] * gridStep[0] + gridCoord2[2] * gridStep[1] ) * rpScreenCorrectionFactor.z + rpScreenCorrectionFactor.z * 0.5;\n" @@ -5672,7 +5681,10 @@ static const cgShaderDef_t cg_renderprogs[] = " normalizedOctCoord = octEncode( reflectionVector );\n" " normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n" "\n" - " float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb;\n" + " float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpUser0.x;\n" + " radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpUser0.y;\n" + " radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpUser0.z;\n" + "\n" " //radiance = float3( 0.0 );\n" "\n" " // RB: HACK dim down room radiance by better local irradiance brightness\n" diff --git a/neo/renderer/tr_frontend_main.cpp b/neo/renderer/tr_frontend_main.cpp index 54d17e19..82a60885 100644 --- a/neo/renderer/tr_frontend_main.cpp +++ b/neo/renderer/tr_frontend_main.cpp @@ -454,6 +454,121 @@ static void R_SetupSplitFrustums( viewDef_t* viewDef ) } } } + +class idSort_CompareEnvprobe : public idSort_Quick< RenderEnvprobeLocal*, idSort_CompareEnvprobe > +{ + idVec3 viewOrigin; + +public: + idSort_CompareEnvprobe( const idVec3& origin ) + { + viewOrigin = origin; + } + + int Compare( RenderEnvprobeLocal* const& a, RenderEnvprobeLocal* const& b ) const + { + float adist = ( viewOrigin - a->parms.origin ).LengthSqr(); + float bdist = ( viewOrigin - b->parms.origin ).LengthSqr(); + + if( adist < bdist ) + { + return -1; + } + + if( adist > bdist ) + { + return 1; + } + + return 0; + } +}; + +static void R_FindClosestEnvironmentProbes() +{ + // set safe defaults + tr.viewDef->globalProbeBounds.Clear(); + + tr.viewDef->irradianceImage = globalImages->defaultUACIrradianceCube; + tr.viewDef->radianceImageBlends.Set( 1, 0, 0, 0 ); + for( int i = 0; i < 3; i++ ) + { + tr.viewDef->radianceImages[i] = globalImages->defaultUACRadianceCube; + } + + // early out + if( tr.viewDef->areaNum == -1 || tr.viewDef->isSubview ) + { + return; + } + + idList viewEnvprobes; + for( int i = 0; i < tr.primaryWorld->envprobeDefs.Num(); i++ ) + { + RenderEnvprobeLocal* vProbe = tr.primaryWorld->envprobeDefs[i]; + if( vProbe ) + { + viewEnvprobes.AddUnique( vProbe ); + } + } + + if( viewEnvprobes.Num() == 0 ) + { + return; + } + + idVec3 testOrigin = tr.viewDef->renderView.vieworg; + + // sort by distance + // RB: each Doom 3 level has ~50 - 150 probes so this should be ok for each frame + viewEnvprobes.SortWithTemplate( idSort_CompareEnvprobe( testOrigin ) ); + + RenderEnvprobeLocal* nearest = viewEnvprobes[0]; + tr.viewDef->globalProbeBounds = nearest->globalProbeBounds; + tr.viewDef->irradianceImage = nearest->irradianceImage; + + // form a triangle of the 3 closest probes + idVec3 verts[3]; + for( int i = 0; i < 3; i++ ) + { + verts[i] = viewEnvprobes[0]->parms.origin; + } + + for( int i = 0; i < viewEnvprobes.Num() && i < 3; i++ ) + { + RenderEnvprobeLocal* vProbe = viewEnvprobes[i]; + + verts[i] = vProbe->parms.origin; + } + + idVec3 closest = R_ClosestPointPointTriangle( testOrigin, verts[0], verts[1], verts[2] ); + idVec3 bary; + + // find the barycentric coordinates + float denom = idWinding::TriangleArea( verts[0], verts[1], verts[2] ); + if( denom == 0 ) + { + // all points at same location + bary.Set( 1, 0, 0 ); + } + else + { + float a, b, c; + + a = idWinding::TriangleArea( closest, verts[1], verts[2] ) / denom; + b = idWinding::TriangleArea( closest, verts[2], verts[0] ) / denom; + c = idWinding::TriangleArea( closest, verts[0], verts[1] ) / denom; + + bary.Set( a, b, c ); + } + + tr.viewDef->radianceImageBlends.Set( bary.x, bary.y, bary.z, 0.0f ); + + for( int i = 0; i < viewEnvprobes.Num() && i < 3; i++ ) + { + tr.viewDef->radianceImages[i] = viewEnvprobes[i]->radianceImage; + } +} // RB end /* @@ -539,33 +654,8 @@ void R_RenderView( viewDef_t* parms ) } } - // RB: find closest environment probe - if( tr.viewDef->areaNum != -1 && !tr.viewDef->isSubview ) - { - float bestDist = idMath::INFINITY; - - tr.viewDef->globalProbeBounds.Clear(); - - tr.viewDef->irradianceImage = globalImages->defaultUACIrradianceCube; - tr.viewDef->radianceImage = globalImages->defaultUACRadianceCube; - - for( viewEnvprobe_t* vProbe = tr.viewDef->viewEnvprobes; vProbe != NULL; vProbe = vProbe->next ) - { - float dist = ( tr.viewDef->renderView.vieworg - vProbe->globalOrigin ).Length(); - if( ( dist < bestDist ) ) - { - if( vProbe->irradianceImage->IsLoaded() && !vProbe->irradianceImage->IsDefaulted() ) - { - tr.viewDef->globalProbeBounds = vProbe->globalProbeBounds; - - tr.viewDef->irradianceImage = vProbe->irradianceImage; - tr.viewDef->radianceImage = vProbe->radianceImage; - - bestDist = dist; - } - } - } - } + // RB: find closest environment probes so we can interpolate between them in the ambient shaders + R_FindClosestEnvironmentProbes(); // write everything needed to the demo file if( common->WriteDemo() ) diff --git a/neo/renderer/tr_trisurf.cpp b/neo/renderer/tr_trisurf.cpp index 8800676e..d77554a7 100644 --- a/neo/renderer/tr_trisurf.cpp +++ b/neo/renderer/tr_trisurf.cpp @@ -2367,4 +2367,82 @@ static void SetUpMikkTSpaceContext( SMikkTSpaceContext* context ) context->m_pInterface = &mikkTSpaceInterface.mkInterface; } -// SP end \ No newline at end of file +// SP end + + +// RB: Determines the closest point between a point and a triangle +idVec3 R_ClosestPointPointTriangle( const idVec3& point, const idVec3& vertex1, const idVec3& vertex2, const idVec3& vertex3 ) +{ + idVec3 result; + + // Source: Real-Time Collision Detection by Christer Ericson + // Reference: Page 136 + + // check if P in vertex region outside A + idVec3 ab = vertex2 - vertex1; + idVec3 ac = vertex3 - vertex1; + idVec3 ap = point - vertex1; + + float d1 = ( ab * ap ); + float d2 = ( ac * ap ); + if( d1 <= 0.0f && d2 <= 0.0f ) + { + result = vertex1; //Barycentric coordinates (1,0,0) + return result; + } + + // Check if P in vertex region outside B + idVec3 bp = point - vertex2; + float d3 = ( ab * bp ); + float d4 = ( ac * bp ); + if( d3 >= 0.0f && d4 <= d3 ) + { + result = vertex2; // barycentric coordinates (0,1,0) + return result; + } + + // Check if P in edge region of AB, if so return projection of P onto AB + float vc = d1 * d4 - d3 * d2; + if( vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f ) + { + float v = d1 / ( d1 - d3 ); + result = vertex1 + v * ab; //Barycentric coordinates (1-v,v,0) + return result; + } + + // Check if P in vertex region outside C + idVec3 cp = point - vertex3; + float d5 = ( ab * cp ); + float d6 = ( ac * cp ); + if( d6 >= 0.0f && d5 <= d6 ) + { + result = vertex3; //Barycentric coordinates (0,0,1) + return result; + } + + // Check if P in edge region of AC, if so return projection of P onto AC + float vb = d5 * d2 - d1 * d6; + if( vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f ) + { + float w = d2 / ( d2 - d6 ); + result = vertex1 + w * ac; //Barycentric coordinates (1-w,0,w) + return result; + } + + // Check if P in edge region of BC, if so return projection of P onto BC + float va = d3 * d6 - d5 * d4; + if( va <= 0.0f && ( d4 - d3 ) >= 0.0f && ( d5 - d6 ) >= 0.0f ) + { + float w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); + result = vertex2 + w * ( vertex3 - vertex2 ); //Barycentric coordinates (0,1-w,w) + return result; + } + + // P inside face region. Compute Q through its barycentric coordinates (u,v,w) + float denom = 1.0f / ( va + vb + vc ); + float v2 = vb * denom; + float w2 = vc * denom; + result = vertex1 + ab * v2 + ac * w2; //= u*vertex1 + v*vertex2 + w*vertex3, u = va * denom = 1.0f - v - w + + return result; +} \ No newline at end of file From d5b9fbc7e8d78c0ec35e35085a7bd97eb4339e05 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Thu, 29 Apr 2021 12:52:40 +0200 Subject: [PATCH 26/26] Fixed crash in glslang when compiling new lightgrid shaders --- .../lighting/ambient_lightgrid_IBL.ps.hlsl | 9 ++--- .../lighting/ambient_lightgrid_IBL.vs.hlsl | 4 --- .../lighting/ambient_lighting_IBL.ps.hlsl | 6 ++-- neo/renderer/RenderBackend.cpp | 35 ++----------------- neo/renderer/RenderProgs_embedded.h | 19 ++++------ 5 files changed, 14 insertions(+), 59 deletions(-) diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl index a681d850..d4b0c4d1 100644 --- a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.ps.hlsl @@ -44,8 +44,6 @@ uniform sampler2D samp8 : register(s8); // texture 8 is the radiance cube map 1 uniform sampler2D samp9 : register(s9); // texture 9 is the radiance cube map 2 uniform sampler2D samp10 : register(s10); // texture 10 is the radiance cube map 3 -uniform float4 rpUser0 : register( c128 ); - struct PS_IN { half4 position : VPOS; @@ -394,10 +392,9 @@ void main( PS_IN fragment, out PS_OUT result ) normalizedOctCoord = octEncode( reflectionVector ); normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5; - float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpUser0.x; - radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpUser0.y; - radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpUser0.z; - + float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.x; + radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.y; + radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.z; //radiance = float3( 0.0 ); // RB: HACK dim down room radiance by better local irradiance brightness diff --git a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.vs.hlsl b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.vs.hlsl index 35bd0b7b..d405e89f 100644 --- a/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.vs.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lightgrid_IBL.vs.hlsl @@ -135,10 +135,6 @@ void main( VS_IN vertex, out VS_OUT result ) float4 defaultTexCoord = float4( 0.0f, 0.5f, 0.0f, 1.0f ); - //calculate vector to light - //float4 toLight = rpLocalLightOrigin; - float4 toLight = normalize( float4( 0.0f, 0.5f, 1.0f, 1.0f ) ); - //-------------------------------------------------------------- diff --git a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl index 9859d3c6..c35b5dcc 100644 --- a/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl +++ b/base/renderprogs/builtin/lighting/ambient_lighting_IBL.ps.hlsl @@ -272,9 +272,9 @@ void main( PS_IN fragment, out PS_OUT result ) normalizedOctCoordZeroOne = OctTexCoord( reflectionVector ); - float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpGlobalLightOrigin.x; - radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpGlobalLightOrigin.y; - radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpGlobalLightOrigin.z; + float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.x; + radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.y; + radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.z; //radiance = float3( 0.0 ); float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg; diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index d3dfdd2f..6882a0b8 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -1366,7 +1366,7 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas renderProgManager.SetUniformValue( RENDERPARM_SCREENCORRECTIONFACTOR, probeSize.ToFloatPtr() ); // rpScreenCorrectionFactor // specular cubemap blend weights - renderProgManager.SetUniformValue( RENDERPARM_USER0, viewDef->radianceImageBlends.ToFloatPtr() ); + renderProgManager.SetUniformValue( RENDERPARM_LOCALLIGHTORIGIN, viewDef->radianceImageBlends.ToFloatPtr() ); if( specUsage == TD_SPECULAR_PBR_RMAO || specUsage == TD_SPECULAR_PBR_RMAOD ) { @@ -1448,7 +1448,7 @@ void idRenderBackend::DrawSingleInteraction( drawInteraction_t* din, bool useFas SetVertexParm( RENDERPARM_WOBBLESKY_Z, probeCenter.ToFloatPtr() ); // specular cubemap blend weights - renderProgManager.SetUniformValue( RENDERPARM_GLOBALLIGHTORIGIN, viewDef->radianceImageBlends.ToFloatPtr() ); + renderProgManager.SetUniformValue( RENDERPARM_LOCALLIGHTORIGIN, viewDef->radianceImageBlends.ToFloatPtr() ); if( specUsage == TD_SPECULAR_PBR_RMAO || specUsage == TD_SPECULAR_PBR_RMAOD ) { @@ -2411,16 +2411,6 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr R_GlobalPointToLocal( drawSurf->space->modelMatrix, viewDef->renderView.vieworg, localViewOrigin.ToVec3() ); SetVertexParm( RENDERPARM_LOCALVIEWORIGIN, localViewOrigin.ToFloatPtr() ); - //if( !isWorldModel ) - //{ - // // tranform the light direction into model local space - // idVec3 globalLightDirection( 0.0f, 0.0f, -1.0f ); // HACK - // idVec4 localLightDirection( 0.0f ); - // R_GlobalVectorToLocal( drawSurf->space->modelMatrix, globalLightDirection, localLightDirection.ToVec3() ); - // - // SetVertexParm( RENDERPARM_LOCALLIGHTORIGIN, localLightDirection.ToFloatPtr() ); - //} - // RB: if we want to store the normals in world space so we need the model -> world matrix idRenderMatrix modelMatrix; idRenderMatrix::Transpose( *( idRenderMatrix* )drawSurf->space->modelMatrix, modelMatrix ); @@ -2433,27 +2423,6 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr SetVertexParms( RENDERPARM_MODELVIEWMATRIX_X, modelViewMatrixTranspose, 4 ); } -#if 0 - if( !isWorldModel ) - { - idVec4 directedColor; - directedColor.x = drawSurf->space->gridDirectedLight.x; - directedColor.y = drawSurf->space->gridDirectedLight.y; - directedColor.z = drawSurf->space->gridDirectedLight.z; - directedColor.w = 1; - - idVec4 ambientColor; - ambientColor.x = drawSurf->space->gridAmbientLight.x; - ambientColor.y = drawSurf->space->gridAmbientLight.y; - ambientColor.z = drawSurf->space->gridAmbientLight.z; - ambientColor.w = 1; - - renderProgManager.SetRenderParm( RENDERPARM_COLOR, directedColor.ToFloatPtr() ); - renderProgManager.SetRenderParm( RENDERPARM_AMBIENT_COLOR, ambientColor.ToFloatPtr() ); - } - float ambientBoost = r_useHDR.GetBool() ? 1.5 : 1.0; -#endif - /* uint64 surfGLState = 0; diff --git a/neo/renderer/RenderProgs_embedded.h b/neo/renderer/RenderProgs_embedded.h index 04cbd26d..0d517972 100644 --- a/neo/renderer/RenderProgs_embedded.h +++ b/neo/renderer/RenderProgs_embedded.h @@ -5039,9 +5039,9 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " normalizedOctCoordZeroOne = OctTexCoord( reflectionVector );\n" "\n" - " float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpGlobalLightOrigin.x;\n" - " radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpGlobalLightOrigin.y;\n" - " radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpGlobalLightOrigin.z;\n" + " float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.x;\n" + " radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.y;\n" + " radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.z;\n" " //radiance = float3( 0.0 );\n" "\n" " float2 envBRDF = texture( samp3, float2( max( vDotN, 0.0 ), roughness ) ).rg;\n" @@ -5331,8 +5331,6 @@ static const cgShaderDef_t cg_renderprogs[] = "uniform sampler2D samp9 : register(s9); // texture 9 is the radiance cube map 2\n" "uniform sampler2D samp10 : register(s10); // texture 10 is the radiance cube map 3\n" "\n" - "uniform float4 rpUser0 : register( c128 );\n" - "\n" "struct PS_IN \n" "{\n" " half4 position : VPOS;\n" @@ -5681,10 +5679,9 @@ static const cgShaderDef_t cg_renderprogs[] = " normalizedOctCoord = octEncode( reflectionVector );\n" " normalizedOctCoordZeroOne = ( normalizedOctCoord + float2( 1.0 ) ) * 0.5;\n" "\n" - " float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpUser0.x;\n" - " radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpUser0.y;\n" - " radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpUser0.z;\n" - "\n" + " float3 radiance = textureLod( samp8, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.x;\n" + " radiance += textureLod( samp9, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.y;\n" + " radiance += textureLod( samp10, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.z;\n" " //radiance = float3( 0.0 );\n" "\n" " // RB: HACK dim down room radiance by better local irradiance brightness\n" @@ -5866,10 +5863,6 @@ static const cgShaderDef_t cg_renderprogs[] = "\n" " float4 defaultTexCoord = float4( 0.0f, 0.5f, 0.0f, 1.0f );\n" "\n" - " //calculate vector to light\n" - " //float4 toLight = rpLocalLightOrigin;\n" - " float4 toLight = normalize( float4( 0.0f, 0.5f, 1.0f, 1.0f ) );\n" - "\n" " //--------------------------------------------------------------\n" "\n" "\n"