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
2 changes: 2 additions & 0 deletions src/engine/renderer/gl_shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,8 @@ static std::string GenEngineConstants() {

AddDefine( str, "r_tileStep", glState.tileStep[0], glState.tileStep[1] );

AddDefine( str, "LIGHTGRID_AVERAGE_COSINE", tr.lightGridAverageCosine );

if ( glConfig.realtimeLighting )
{
AddDefine( str, "r_realtimeLighting", 1 );
Expand Down
16 changes: 11 additions & 5 deletions src/engine/renderer/glsl_source/computeLight_fp.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,19 @@ vec4 EnvironmentalSpecularFactor( vec3 viewDir, vec3 normal )
// lighting helper functions

#if defined(USE_GRID_LIGHTING) || defined(USE_GRID_DELUXE_MAPPING)
void ReadLightGrid( in vec4 texel, in float lightFactor, out vec3 ambientColor, out vec3 lightColor ) {
float ambientScale = 2.0 * texel.a;
float directedScale = 2.0 - ambientScale;
ambientColor = ambientScale * texel.rgb;
lightColor = directedScale * texel.rgb;
void ReadLightGrid( in vec4 texel1, in vec4 texel2, in float lightFactor, out vec3 lightDir, out vec3 ambientColor, out vec3 lightColor ) {
vec3 totalColor = (1.0 + LIGHTGRID_AVERAGE_COSINE) * texel1.rgb;
float total1Norm = totalColor.r + totalColor.g + totalColor.b;
vec3 scaledLightDir = 2.0 * (texel2.xyz - (128.0 / 255.0));
float directed1Norm = 3.0 * length(scaledLightDir);
float directedFraction = clamp((LIGHTGRID_AVERAGE_COSINE * directed1Norm) / total1Norm, 0.0, 1.0);
float directedScale = directedFraction / LIGHTGRID_AVERAGE_COSINE;
float ambientScale = 1.0 - directedFraction;
ambientColor = ambientScale * totalColor;
lightColor = directedScale * totalColor;
ambientColor *= lightFactor;
lightColor *= lightFactor;
lightDir = normalize(scaledLightDir);
}
#endif

Expand Down
19 changes: 9 additions & 10 deletions src/engine/renderer/glsl_source/lightMapping_fp.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,10 @@ void main()
vec4 color;
color.a = diffuse.a;

#if defined(USE_GRID_LIGHTING) || defined(USE_GRID_DELUXE_MAPPING)
// Compute light grid position.
vec3 lightGridPos = (var_Position - u_LightGridOrigin) * u_LightGridScale;
#endif

#if defined(USE_DELUXE_MAPPING)
// Compute light direction in world space from deluxe map.
vec4 deluxe = texture2D(u_DeluxeMap, var_TexLight);
vec3 lightDir = normalize(2.0 * deluxe.xyz - 1.0);
#elif defined(USE_GRID_DELUXE_MAPPING)
// Compute light direction in world space from light grid.
vec4 texel = texture3D(u_LightGrid2, lightGridPos);
vec3 lightDir = normalize(texel.xyz - (128.0 / 255.0));
#endif

float lightFactor = ColorModulateToLightFactor( u_ColorModulateColorGen );
Expand All @@ -156,8 +147,16 @@ void main()
color.rgb = vec3(0.0);
#else
// Compute light color from lightgrid.
vec3 lightGridPos = (var_Position - u_LightGridOrigin) * u_LightGridScale;
vec4 texel1 = texture3D(u_LightGrid1, lightGridPos);
#if defined(USE_GRID_DELUXE_MAPPING)
vec4 texel2 = texture3D(u_LightGrid2, lightGridPos);
#else
vec4 texel2 = vec4(128.0 / 255.0); // zero direction vector
#endif
vec3 lightDir;
vec3 ambientColor, lightColor;
ReadLightGrid(texture3D(u_LightGrid1, lightGridPos), lightFactor, ambientColor, lightColor);
ReadLightGrid(texel1, texel2, lightFactor, lightDir, ambientColor, lightColor);

color.rgb = ambientColor * r_AmbientScale * diffuse.rgb;
#endif
Expand Down
15 changes: 10 additions & 5 deletions src/engine/renderer/tr_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2223,14 +2223,19 @@ static void RB_RenderDebugUtils()
int gridIndex = x + tr.world->lightGridBounds[ 0 ] * ( y + tr.world->lightGridBounds[ 1 ] * z );
const bspGridPoint1_t *gp1 = tr.world->lightGridData1 + gridIndex;
const bspGridPoint2_t *gp2 = tr.world->lightGridData2 + gridIndex;
Color::Color generalColor = Color::Adapt( gp1->color );
float ambientScale = 2.0f * unorm8ToFloat( gp1->ambientPart );
float directedScale = 2.0f - ambientScale;
Color::Color ambientColor = generalColor * ambientScale;
Color::Color directedColor = generalColor * directedScale;
lightDir[ 0 ] = snorm8ToFloat( gp2->direction[ 0 ] - 128 );
lightDir[ 1 ] = snorm8ToFloat( gp2->direction[ 1 ] - 128 );
lightDir[ 2 ] = snorm8ToFloat( gp2->direction[ 2 ] - 128 );
Color::Color totalColor = Color::Adapt( gp1->color );
totalColor *= 1.0f + tr.lightGridAverageCosine;
float total1Norm = totalColor.Red() + totalColor.Green() + totalColor.Blue();
float directed1Norm = 3.0f * VectorLength( lightDir );
float directedFraction = ( tr.lightGridAverageCosine * directed1Norm ) / total1Norm;
float directedScale = directedFraction / tr.lightGridAverageCosine;
float ambientScale = 1.0 - directedFraction;
Color::Color ambientColor = totalColor * ambientScale;
Color::Color directedColor = totalColor * directedScale;
VectorNormalize( lightDir );

VectorNegate( lightDir, lightDir );

Expand Down
74 changes: 35 additions & 39 deletions src/engine/renderer/tr_bsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3438,14 +3438,13 @@ static void R_SetConstantColorLightGrid( const byte color[3] )
bspGridPoint1_t *gridPoint1 = (bspGridPoint1_t *) ri.Hunk_Alloc( sizeof( bspGridPoint1_t ) + sizeof( bspGridPoint2_t ), ha_pref::h_low );
bspGridPoint2_t *gridPoint2 = (bspGridPoint2_t *) (gridPoint1 + w->numLightGridPoints);

// default some white light from above
gridPoint1->color[ 0 ] = color[0];
gridPoint1->color[ 1 ] = color[1];
gridPoint1->color[ 2 ] = color[2];
gridPoint1->ambientPart = 128;
// directed part comes from above; ambient color and directed color are both `color`
VectorCopy( color, gridPoint1->color );
gridPoint1->unused = 255;
gridPoint2->direction[ 0 ] = 128 + floatToSnorm8( 0.0f );
gridPoint2->direction[ 1 ] = 128 + floatToSnorm8( 0.0f );
gridPoint2->direction[ 2 ] = 128 + floatToSnorm8( 1.0f );
gridPoint2->direction[ 2 ] = 128 + floatToSnorm8(
( color[ 0 ] + color[ 1 ] + color[ 2 ] ) / ( 3.0f * 255 ) );
gridPoint2->isSet = 255;

w->lightGridData1 = gridPoint1;
Expand Down Expand Up @@ -3496,7 +3495,6 @@ void R_LoadLightGrid( lump_t *l )
float weights[ 3 ] = { 0.25f, 0.5f, 0.25f };
float *factors[ 3 ] = { weights, weights, weights };
vec3_t ambientColor, directedColor, direction;
float scale;

if ( tr.ambientLightSet ) {
const byte color[3]{ floatToUnorm8( tr.ambientLight[0] ), floatToUnorm8( tr.ambientLight[1] ),
Expand Down Expand Up @@ -3637,19 +3635,26 @@ void R_LoadLightGrid( lump_t *l )
direction[ 1 ] = sinf( lng ) * sinf( lat );
direction[ 2 ] = cosf( lat );

// Pack data into an bspGridPoint
gridPoint1->color[ 0 ] = floatToUnorm8( 0.5f * (ambientColor[ 0 ] + directedColor[ 0 ]) );
gridPoint1->color[ 1 ] = floatToUnorm8( 0.5f * (ambientColor[ 1 ] + directedColor[ 1 ]) );
gridPoint1->color[ 2 ] = floatToUnorm8( 0.5f * (ambientColor[ 2 ] + directedColor[ 2 ]) );

float ambientLength = VectorLength(ambientColor);
float directedLength = VectorLength(directedColor);
float length = ambientLength + directedLength;
gridPoint1->ambientPart = floatToUnorm8( ambientLength / length );

gridPoint2->direction[0] = 128 + floatToSnorm8( direction[ 0 ] );
gridPoint2->direction[1] = 128 + floatToSnorm8( direction[ 1 ] );
gridPoint2->direction[2] = 128 + floatToSnorm8( direction[ 2 ] );
// Separate ambient and directed colors are not implemented, so this is the total average light
// (averaged over all direction vectors). The result is scaled down to fit in [0, 1].
float colorScale = 1.0f / ( 1.0f + tr.lightGridAverageCosine );
gridPoint1->color[ 0 ] = floatToUnorm8( ( ambientColor[ 0 ] + tr.lightGridAverageCosine * directedColor[ 0 ] ) * colorScale );
gridPoint1->color[ 1 ] = floatToUnorm8( ( ambientColor[ 1 ] + tr.lightGridAverageCosine * directedColor[ 1 ] ) * colorScale );
gridPoint1->color[ 2 ] = floatToUnorm8( ( ambientColor[ 2 ] + tr.lightGridAverageCosine * directedColor[ 2 ] ) * colorScale );
gridPoint1->unused = 255;

// The length of the direction vector is used to determine how much directed light there is.
// When adjacent grid points have opposing directions that (partially) cancel each other upon
// interpolation, the GLSL will see a smaller direction vector and put more light into the
// ambient part. "How much light" is determined using the 1-norm (Maybe it should be
// luma-aware?) since that is preserved under interpolation.
// TODO: send the directed contribution to zero if it is worse than random? If you had perfectly
// ambient white light with a total of sum of A, you'd get a directed color of 0.25*A and an ambient color
// of 0.1875*A. So if the directed to ambient ratio is lower than that, the direction is surely garbage.
float dirScale = ( directedColor[ 0 ] + directedColor[ 1 ] + directedColor[ 2 ] ) / 3.0f;
gridPoint2->direction[0] = 128 + floatToSnorm8( dirScale * direction[ 0 ] );
gridPoint2->direction[1] = 128 + floatToSnorm8( dirScale * direction[ 1 ] );
gridPoint2->direction[2] = 128 + floatToSnorm8( dirScale * direction[ 2 ] );
gridPoint2->isSet = 255;
}

Expand Down Expand Up @@ -3678,27 +3683,18 @@ void R_LoadLightGrid( lump_t *l )
continue;
}

scale = R_InterpolateLightGrid( w, from, to, factors,
ambientColor, directedColor,
direction );
if( scale > 0.0f ) {
scale = 1.0f / scale;

VectorScale( ambientColor, scale, ambientColor );
VectorScale( directedColor, scale, directedColor );
VectorScale( direction, scale, direction );
vec3_t interpolatedColor, interpolatedDir;
R_InterpolateLightGrid( w, from, to, factors, interpolatedColor, interpolatedDir );

gridPoint1->color[0] = floatToUnorm8( interpolatedColor[ 0 ] );
gridPoint1->color[1] = floatToUnorm8( interpolatedColor[ 1 ] );
gridPoint1->color[2] = floatToUnorm8( interpolatedColor[ 2 ] );
gridPoint1->unused = 255;

gridPoint1->color[0] = floatToUnorm8(0.5f * (ambientColor[0] + directedColor[0]));
gridPoint1->color[1] = floatToUnorm8(0.5f * (ambientColor[1] + directedColor[1]));
gridPoint1->color[2] = floatToUnorm8(0.5f * (ambientColor[2] + directedColor[2]));
gridPoint1->ambientPart = floatToUnorm8(VectorLength(ambientColor) / (VectorLength(ambientColor) + VectorLength(directedColor)));

gridPoint2->direction[0] = 128 + floatToSnorm8(direction[0]);
gridPoint2->direction[1] = 128 + floatToSnorm8(direction[1]);
gridPoint2->direction[2] = 128 + floatToSnorm8(direction[2]);
gridPoint2->isSet = 255;
}
gridPoint2->direction[0] = 128 + floatToSnorm8( interpolatedDir[ 0 ] );
gridPoint2->direction[1] = 128 + floatToSnorm8( interpolatedDir[ 1 ] );
gridPoint2->direction[2] = 128 + floatToSnorm8( interpolatedDir[ 2 ] );
gridPoint2->isSet = 255;
}
}
}
Expand Down
15 changes: 15 additions & 0 deletions src/engine/renderer/tr_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1350,6 +1350,21 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p
}
}

if ( glConfig.deluxeMapping )
{
// Average value of max(0, dot(random vector, light dir)) over the unit sphere, used to
// compare directed lighting's average contribution with ambient. See TraceGrid in light.c in
// q3map2 for more information about this calculation. Though if we took half-Lambert lighting's
// cosine modification into account it would be 1/3 instead of 1/4.
tr.lightGridAverageCosine = 0.25f;
}
else
{
// Boost it when deluxe is disabled because otherwise it's too dark. Normals tend to line up
// with the light direction better than chance.
tr.lightGridAverageCosine = 0.4f;
}

R_NoiseInit();

R_Register();
Expand Down
27 changes: 12 additions & 15 deletions src/engine/renderer/tr_light.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,17 @@ LIGHT SAMPLING
=============================================================================
*/

float R_InterpolateLightGrid( world_t *w, int from[3], int to[3],
float *factors[3], vec3_t ambientLight,
vec3_t directedLight, vec3_t lightDir ) {
void R_InterpolateLightGrid( world_t *w, int from[3], int to[3], float *factors[3],
vec3_t lightColor, vec3_t lightDir )
{
float totalFactor = 0.0f, factor;
float *xFactor, *yFactor, *zFactor;
int gridStep[ 3 ];
int x, y, z;
bspGridPoint1_t *gp1;
bspGridPoint2_t *gp2;

VectorClear( ambientLight );
VectorClear( directedLight );
VectorClear( lightColor );
VectorClear( lightDir );

gridStep[ 0 ] = 1;
Expand Down Expand Up @@ -80,18 +79,16 @@ float R_InterpolateLightGrid( world_t *w, int from[3], int to[3],
lightDir[ 1 ] += factor * snorm8ToFloat( gp2->direction[ 1 ] - 128 );
lightDir[ 2 ] += factor * snorm8ToFloat( gp2->direction[ 2 ] - 128 );

float ambientScale = 2.0f * unorm8ToFloat( gp1->ambientPart );
float directedScale = 2.0f - ambientScale;

ambientLight[ 0 ] += factor * ambientScale * unorm8ToFloat( gp1->color[ 0 ] );
ambientLight[ 1 ] += factor * ambientScale * unorm8ToFloat( gp1->color[ 1 ] );
ambientLight[ 2 ] += factor * ambientScale * unorm8ToFloat( gp1->color[ 2 ] );
directedLight[ 0 ] += factor * directedScale * unorm8ToFloat( gp1->color[ 0 ] );
directedLight[ 1 ] += factor * directedScale * unorm8ToFloat( gp1->color[ 1 ] );
directedLight[ 2 ] += factor * directedScale * unorm8ToFloat( gp1->color[ 2 ] );
lightColor[ 0 ] += factor * unorm8ToFloat( gp1->color[ 0 ] );
lightColor[ 1 ] += factor * unorm8ToFloat( gp1->color[ 1 ] );
lightColor[ 2 ] += factor * unorm8ToFloat( gp1->color[ 2 ] );
}
}
}

return totalFactor;
if ( totalFactor > 0.0f )
{
VectorScale( lightDir, 1.0f / totalFactor, lightDir );
VectorScale( lightColor, 1.0f / totalFactor, lightColor );
}
}
8 changes: 4 additions & 4 deletions src/engine/renderer/tr_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -1690,7 +1690,7 @@ enum
struct bspGridPoint1_t
{
byte color[3];
byte ambientPart;
byte unused;
};
struct bspGridPoint2_t
{
Expand Down Expand Up @@ -2498,6 +2498,7 @@ enum
vec3_t ambientLight;
bool ambientLightSet = false;

float lightGridAverageCosine;
image_t *lightGrid1Image;
image_t *lightGrid2Image;

Expand Down Expand Up @@ -3263,9 +3264,8 @@ void GLimp_LogComment_( std::string comment );
============================================================
*/

float R_InterpolateLightGrid( world_t *w, int from[3], int to[3],
float *factors[3], vec3_t ambientLight,
vec3_t directedLight, vec3_t lightDir );
void R_InterpolateLightGrid( world_t *w, int from[3], int to[3], float *factors[3],
vec3_t lightColor, vec3_t lightDir );

/*
============================================================
Expand Down
Loading