Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/engine/renderer/glsl_source/lighttile_fp.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ void main() {
or use compute shaders with atomics so we can have a variable amount of lights for each tile. */
for( uint i = uint( u_lightLayer ); i < uint( u_numLights ); i += uint( NUM_LIGHT_LAYERS ) ) {
Light l = GetLight( i );
// Directional lights (sun) have infinite extent, so always include them in tiles
if ( l.type == 2 ) {
pushIdxs( ( i / uint( NUM_LIGHT_LAYERS ) ) + 1u, lightCount, idxs );
lightCount++;
if( lightCount == lightsPerLayer ) {
break;
}
continue;
}

vec3 center = ( u_ModelMatrix * vec4( l.center, 1.0 ) ).xyz;
float radius = max( 2.0 * l.radius, 2.0 * 32.0 ); // Avoid artifacts with weak light sources

Expand Down
130 changes: 126 additions & 4 deletions src/engine/renderer/tr_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ static Cvar::Cvar<bool> r_clear( "r_clear", "Clear screen before painting over i
Cvar::Cvar<bool> r_drawSky( "r_drawSky", "Draw the sky (clear the sky if disabled)", Cvar::NONE, true );
static Cvar::Cvar<int> r_showEntityBounds(
"r_showEntityBounds", "show bboxes used for culling (1: wireframe; 2: translucent solid)", Cvar::CHEAT, 0);
static Cvar::Cvar<bool> r_showDynamicLights(
"r_showDynamicLights", "visualize dynamic lights with tetrahedrons", Cvar::CHEAT, false );

void GL_Bind( image_t *image )
{
Expand Down Expand Up @@ -1303,7 +1305,7 @@ static void RenderDepthTiles()
{
RB_PrepareForSamplingDepthMap();
}

TransitionMSAAToMain( GL_DEPTH_BUFFER_BIT );

// 1st step
Expand All @@ -1319,7 +1321,7 @@ static void RenderDepthTiles()

gl_depthtile1Shader->SetUniform_zFar( zParams );
gl_depthtile1Shader->SetUniform_DepthMapBindless(
GL_BindToTMU( 0, tr.currentDepthImage )
GL_BindToTMU( 0, tr.currentDepthImage )
);

matrix_t ortho;
Expand Down Expand Up @@ -1753,7 +1755,7 @@ void RB_CameraPostFX() {
// tr.mainFBO
R_BindNullFBO();
gl_cameraEffectsShader->SetUniform_CurrentMapBindless(
GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] )
GL_BindToTMU( 0, tr.currentRenderImage[backEnd.currentMainFBO] )
);

if ( glConfig.colorGrading ) {
Expand Down Expand Up @@ -2312,6 +2314,125 @@ static void RB_RenderDebugUtils()
Tess_End();
}

if ( r_showDynamicLights.Get() && backEnd.refdef.numLights > 0 )
{
gl_genericShader->SetVertexSkinning( false );
gl_genericShader->SetVertexAnimation( false );
gl_genericShader->SetTCGenEnvironment( false );
gl_genericShader->SetTCGenLightmap( false );
gl_genericShader->SetDepthFade( false );
gl_genericShader->SetDeform( 0 );
gl_genericShader->BindProgram();

GL_State( GLS_DEFAULT );
GL_Cull( cullType_t::CT_TWO_SIDED );

// set uniforms
gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE );
SetUniform_ColorModulateColorGen( gl_genericShader, colorGen_t::CGEN_VERTEX,
alphaGen_t::AGEN_VERTEX );
SetUniform_Color( gl_genericShader, Color::Black );
gl_genericShader->SetUniform_ColorMapBindless( GL_BindToTMU( 0, tr.whiteImage ) );
gl_genericShader->SetUniform_TextureMatrix( matrixIdentity );

// set up the transformation matrix
backEnd.orientation = backEnd.viewParms.world;
GL_LoadModelViewMatrix( backEnd.orientation.modelViewMatrix );
gl_genericShader->SetUniform_ModelViewProjectionMatrix(
glState.modelViewProjectionMatrix[ glState.stackIndex ] );

Tess_Begin( Tess_StageIteratorDebug, nullptr, true, -1, 0 );
GL_CheckErrors();

const refLight_t *lights = backEnd.refdef.lights;
for ( int i = 0; i < backEnd.refdef.numLights; ++i )
{
const refLight_t &light = lights[ i ];
// We can't really visualize directional lights since they don't
// have an origin or a radius.
if ( light.rlType >= refLightType_t::RL_DIRECTIONAL )
{
continue;
}

vec3_t baseOrigin;
VectorCopy( light.origin, baseOrigin );

if ( light.radius <= 0.0f )
{
Log::Warn( "Light with index %d has no radius", i );
}

auto addArrow = [ & ]( const vec3_t dirInput, const Color::Color &arrowColor )
{
vec3_t dir;
VectorCopy( dirInput, dir );
if ( VectorNormalize( dir ) == 0.0f )
{
VectorSet( dir, 0.0f, 0.0f, 1.0f );
}
// idk why we need to negate here, but the arrow points the wrong way otherwise.
VectorNegate( dir, dir );

vec3_t tip;
VectorMA( baseOrigin, light.radius, dir, tip );

vec3_t tmp;
vec3_t tmp2;
vec3_t tmp3;
PerpendicularVector( tmp, dir );
VectorScale( tmp, light.radius * 0.2f, tmp2 );
VectorMA( tmp2, light.radius * 0.3f, dir, tmp2 );

vec4_t tetraVerts[ 4 ];
for ( int k = 0; k < 3; k++ )
{
RotatePointAroundVector( tmp3, dir, tmp2, k * 120.0f );
VectorAdd( tmp3, baseOrigin, tmp3 );
VectorCopy( tmp3, tetraVerts[ k ] );
tetraVerts[ k ][ 3 ] = 1.0f;
}

VectorCopy( baseOrigin, tetraVerts[ 3 ] );
tetraVerts[ 3 ][ 3 ] = 1.0f;
Tess_AddTetrahedron( tetraVerts, arrowColor );

VectorCopy( tip, tetraVerts[ 3 ] );
tetraVerts[ 3 ][ 3 ] = 1.0f;

Tess_AddTetrahedron( tetraVerts, arrowColor );
};

Color::Color color;
switch ( light.rlType )
{
case refLightType_t::RL_PROJ:
color = Color::LtGrey;
addArrow( light.projTarget, color );
break;
default:
color = Color::MdGrey;
{
static const vec3_t kOmniDirs[ 6 ] = {
{ 1.0f, 0.0f, 0.0f },
{ -1.0f, 0.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f },
{ 0.0f, -1.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, -1.0f}
};
for ( int dirIndex = 0; dirIndex < 6; ++dirIndex )
{
addArrow( kOmniDirs[ dirIndex ], color );
}
}
break;
}
}

Tess_End();
}

if ( r_showBspNodes->integer )
{
if ( ( backEnd.refdef.rdflags & ( RDF_NOWORLDMODEL ) ) || !tr.world )
Expand Down Expand Up @@ -2879,7 +3000,7 @@ static void RB_RenderPostProcess()

static void SetFrameUniforms() {
// This can happen with glsl_restart/vid_restart in R_SyncRenderThread()
if ( !stagingBuffer.Active() ) {
if ( !stagingBuffer.Active() || globalUBOProxy == nullptr ) {
return;
}

Expand Down Expand Up @@ -3489,6 +3610,7 @@ const RenderCommand *SetupLightsCommand::ExecuteSelf( ) const
default:
break;
}
VectorNormalize( buffer[i].direction );
}

glUnmapBuffer( bufferTarget );
Expand Down
99 changes: 98 additions & 1 deletion src/engine/renderer/tr_scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ static void RE_RenderCubeProbeFace( const refdef_t* originalRefdef ) {
Log::Warn( "Cube probe face out of range! (%i/%i)", probeID, tr.cubeProbes.size() );
return;
}

refdef_t refdef{};
const int faceID = globalID % 6;

Expand Down Expand Up @@ -467,6 +467,94 @@ static void RE_RenderCubeProbeFace( const refdef_t* originalRefdef ) {

}

// Debug spot light (projected) injection
static Cvar::Cvar<bool> r_debugProjLight( "r_debugProjLight", "inject a directional sun light each frame", Cvar::NONE, false );
static Cvar::Range<Cvar::Cvar<float>> r_debugProjLightYaw( "r_debugProjLightYaw", "debug projected yaw in degrees", Cvar::NONE, 45.0f, -360.0f, 360.0f );
static Cvar::Range<Cvar::Cvar<float>> r_debugProjLightPitch( "r_debugProjLightPitch", "debug projected pitch in degrees", Cvar::NONE, -60.0f, -89.0f, 89.0f );
static Cvar::Cvar<float> r_debugProjLightIntensity( "r_debugProjLightIntensity", "debug projected intensity (scale)", Cvar::NONE, 1.0f );
static Cvar::Cvar<float> r_debugProjLightRadius( "r_debugProjLightRadius", "debug projected radius (size)", Cvar::NONE, 100.0f );
static Cvar::Range<Cvar::Cvar<float>> r_debugProjLightR( "r_debugProjLightR", "debug projected color R", Cvar::NONE, 1.0f, 0.0f, 1.0f );
static Cvar::Range<Cvar::Cvar<float>> r_debugProjLightG( "r_debugProjLightG", "debug projected color G", Cvar::NONE, 1.0f, 0.0f, 1.0f );
static Cvar::Range<Cvar::Cvar<float>> r_debugProjLightB( "r_debugProjLightB", "debug projected color B", Cvar::NONE, 1.0f, 0.0f, 1.0f );
static Cvar::Cvar<float> r_debugProjLightOriginX( "r_debugProjLightOriginX", "debug projected origin X", Cvar::NONE, 0.0f );
static Cvar::Cvar<float> r_debugProjLightOriginY( "r_debugProjLightOriginY", "debug projected origin Y", Cvar::NONE, 0.0f );
static Cvar::Cvar<float> r_debugProjLightOriginZ( "r_debugProjLightOriginZ", "debug projected origin Z", Cvar::NONE, 0.0f );
static Cvar::Cvar<float> r_debugProjLightAngle( "r_debugProjLightAngle", "debug projected angle",
Cvar::NONE, 60.0f );

static void AddDebugProjectedLight()
{
if ( r_numLights + 1 >= MAX_REF_LIGHTS )
{
return;
}
refLight_t *light = &backEndData[ tr.smpFrame ]->lights[ r_numLights++ ];
*light = {};
light->rlType = refLightType_t::RL_PROJ;
// Compute direction from yaw/pitch cvars (in degrees)
float yaw = DEG2RAD( r_debugProjLightYaw.Get() );
float pitch = DEG2RAD( r_debugProjLightPitch.Get() );
// Right-handed: X forward, Y left, Z up. Direction vector components:
light->projTarget[ 0 ] = cosf( pitch ) * cosf( yaw );
light->projTarget[ 1 ] = cosf( pitch ) * sinf( yaw );
light->projTarget[ 2 ] = sinf( pitch );

vec3_t dir;
VectorCopy( light->projTarget, dir );
VectorNormalize( dir );

PerpendicularVector( light->projUp, dir );

float upLen = VectorLength( light->projUp );
float tgtLen = VectorLength( light->projTarget );

VectorScale( light->projUp, tanf( DEG2RAD( r_debugProjLightAngle.Get() ) ) / upLen / tgtLen,
light->projUp );

// Color and intensity
light->color[ 0 ] = r_debugProjLightR.Get();
light->color[ 1 ] = r_debugProjLightG.Get();
light->color[ 2 ] = r_debugProjLightB.Get();
light->scale = r_debugProjLightIntensity.Get();
light->radius = r_debugProjLightRadius.Get();
light->origin[ 0 ] = r_debugProjLightOriginX.Get();
light->origin[ 1 ] = r_debugProjLightOriginY.Get();
light->origin[ 2 ] = r_debugProjLightOriginZ.Get();
}

// Debug sun light (directional) injection
Cvar::Cvar<bool> r_debugSun( "r_debugSun", "inject a directional sun light each frame", Cvar::NONE, false );
Cvar::Range<Cvar::Cvar<float>> r_debugSunYaw( "r_debugSunYaw", "debug sun yaw in degrees", Cvar::NONE, 45.0f, -360.0f, 360.0f );
Cvar::Range<Cvar::Cvar<float>> r_debugSunPitch( "r_debugSunPitch", "debug sun pitch in degrees", Cvar::NONE, -60.0f, -89.0f, 89.0f );
Cvar::Range<Cvar::Cvar<float>> r_debugSunIntensity( "r_debugSunIntensity", "debug sun intensity (scale)", Cvar::NONE, 1.0f, 0.0f, 100.0f );
Cvar::Range<Cvar::Cvar<float>> r_debugSunR( "r_debugSunR", "debug sun color R", Cvar::NONE, 1.0f, 0.0f, 10.0f );
Cvar::Range<Cvar::Cvar<float>> r_debugSunG( "r_debugSunG", "debug sun color G", Cvar::NONE, 1.0f, 0.0f, 10.0f );
Cvar::Range<Cvar::Cvar<float>> r_debugSunB( "r_debugSunB", "debug sun color B", Cvar::NONE, 1.0f, 0.0f, 10.0f );

static void AddDebugSunLight()
{
if ( r_numLights + 1 >= MAX_REF_LIGHTS )
{
return;
}
refLight_t *sun = &backEndData[ tr.smpFrame ]->lights[ r_numLights++ ];
*sun = {};
sun->rlType = refLightType_t::RL_DIRECTIONAL;
// Compute direction from yaw/pitch cvars (in degrees)
float yaw = DEG2RAD( r_debugSunYaw.Get() );
float pitch = DEG2RAD( r_debugSunPitch.Get() );
// Right-handed: X forward, Y left, Z up. Direction vector components:
sun->projTarget[ 0 ] = cosf( pitch ) * cosf( yaw );
sun->projTarget[ 1 ] = cosf( pitch ) * sinf( yaw );
sun->projTarget[ 2 ] = sinf( pitch );
VectorNormalize( sun->projTarget );
// Color and intensity
sun->color[ 0 ] = r_debugSunR.Get();
sun->color[ 1 ] = r_debugSunG.Get();
sun->color[ 2 ] = r_debugSunB.Get();
sun->scale = r_debugSunIntensity.Get();
}

/*
@@@@@@@@@@@@@@@@@@@@@
RE_RenderScene
Expand Down Expand Up @@ -542,6 +630,15 @@ void RE_RenderScene( const refdef_t *fd )
}
}

if ( r_debugProjLight.Get() )
{
AddDebugProjectedLight();
}
if ( r_debugSun.Get() )
{
AddDebugSunLight();
}

// derived info
if ( r_forceRendererTime.Get() >= 0 ) {
tr.refdef.floatTime = float( double( r_forceRendererTime.Get() ) * 0.001 );
Expand Down
21 changes: 11 additions & 10 deletions src/engine/renderer/tr_shade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ static void EnableAvailableFeatures()
glConfig.usingGeometryCache = glConfig.usingMaterialSystem && glConfig.geometryCacheAvailable;
}

// For shaders that require map data for compile-time values
// For shaders that require map data for compile-time values
void GLSL_InitWorldShaders() {
// make sure the render thread is stopped
R_SyncRenderThread();
Expand Down Expand Up @@ -256,11 +256,6 @@ static void GLSL_InitGPUShadersOrError()
gl_depthReductionShader->MarkProgramForBuilding();
}

if ( tr.world ) // this only happens with /glsl_restart
{
GLSL_InitWorldShaders();
}

if ( glConfig.realtimeLighting )
{
gl_shaderManager.LoadShader( gl_depthtile1Shader );
Expand Down Expand Up @@ -344,7 +339,7 @@ static void GLSL_InitGPUShadersOrError()

gl_contrastShader->MarkProgramForBuilding();
}

// portal process effect
gl_shaderManager.LoadShader( gl_portalShader );

Expand Down Expand Up @@ -397,6 +392,12 @@ static void GLSL_InitGPUShadersOrError()
gl_shaderManager.PostProcessGlobalUniforms();
gl_shaderManager.InitShaders();

// Init world shaders last so that everyhthing is already initialized.
if ( tr.world ) // this only happens with /glsl_restart
{
GLSL_InitWorldShaders();
}

if ( r_lazyShaders.Get() == 0 )
{
gl_shaderManager.BuildAll( false );
Expand Down Expand Up @@ -1481,7 +1482,7 @@ void Render_heatHaze( shaderStage_t *pStage )

// bind u_NormalMap
gl_heatHazeShader->SetUniform_NormalMapBindless(
GL_BindToTMU( 0, pStage->bundle[TB_NORMALMAP].image[0] )
GL_BindToTMU( 0, pStage->bundle[TB_NORMALMAP].image[0] )
);

if ( pStage->enableNormalMapping )
Expand All @@ -1497,7 +1498,7 @@ void Render_heatHaze( shaderStage_t *pStage )

// bind u_CurrentMap
gl_heatHazeShader->SetUniform_CurrentMapBindless(
GL_BindToTMU( 1, tr.currentRenderImage[backEnd.currentMainFBO] )
GL_BindToTMU( 1, tr.currentRenderImage[backEnd.currentMainFBO] )
);

gl_heatHazeShader->SetRequiredVertexPointers();
Expand All @@ -1507,7 +1508,7 @@ void Render_heatHaze( shaderStage_t *pStage )
// copy to foreground image
R_BindFBO( tr.mainFBO[ backEnd.currentMainFBO ] );
gl_heatHazeShader->SetUniform_CurrentMapBindless(
GL_BindToTMU( 1, tr.currentRenderImage[1 - backEnd.currentMainFBO] )
GL_BindToTMU( 1, tr.currentRenderImage[1 - backEnd.currentMainFBO] )
);
gl_heatHazeShader->SetUniform_DeformMagnitude( 0.0f );
Tess_DrawElements();
Expand Down
Loading