From 26faa5797aba8773dcb1f0eba4fa5d68dbfee898 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Wed, 14 Apr 2021 12:55:46 +0200 Subject: [PATCH] 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] );