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
1 change: 1 addition & 0 deletions src/common/Color.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ inline void convertFromSRGB( float* v, bool accurate = true )
v[ 2 ] = convertFromSRGB( v[ 2 ], accurate );
}

// Beware: this instantly loses precision, there are less than 256 possible outputs!
inline void convertFromSRGB( byte* bytes, bool accurate = true )
{
vec3_t v;
Expand Down
19 changes: 14 additions & 5 deletions src/engine/renderer/tr_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2237,7 +2237,7 @@ static void RB_RenderDebugUtils()

// set uniforms
gl_genericShader->SetUniform_AlphaTest( GLS_ATEST_NONE );
SetUniform_ColorModulateColorGen( gl_genericShader, colorGen_t::CGEN_VERTEX, alphaGen_t::AGEN_VERTEX );
SetUniform_ColorModulateColorGen( gl_genericShader, colorGen_t::CGEN_VERTEX, alphaGen_t::AGEN_IDENTITY );
SetUniform_Color( gl_genericShader, Color::Black );

GL_State( GLS_DEFAULT );
Expand All @@ -2263,8 +2263,6 @@ static void RB_RenderDebugUtils()
for ( y = 0; y < tr.world->lightGridBounds[ 1 ]; y++ ) {
for ( x = 0; x < tr.world->lightGridBounds[ 0 ]; x++ ) {
vec3_t origin;
Color::Color ambientColor;
Color::Color directedColor;
vec3_t lightDir;

VectorCopy( tr.world->lightGridOrigin, origin );
Expand All @@ -2277,8 +2275,19 @@ static void RB_RenderDebugUtils()
continue;
}

R_LightForPoint( origin, ambientColor.ToArray(),
directedColor.ToArray(), lightDir );
// read out grid...
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 );

VectorNegate( lightDir, lightDir );

length = 8;
Expand Down
93 changes: 53 additions & 40 deletions src/engine/renderer/tr_bsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3400,7 +3400,7 @@ static void R_SetConstantColorLightGrid( const byte color[3] )
gridPoint2->direction[ 0 ] = floatToSnorm8(0.0f);
gridPoint2->direction[ 1 ] = floatToSnorm8(0.0f);
gridPoint2->direction[ 2 ] = floatToSnorm8(1.0f);
gridPoint2->unused = 0;
gridPoint2->isSet = 255;

w->lightGridData1 = gridPoint1;
w->lightGridData2 = gridPoint2;
Expand All @@ -3411,7 +3411,11 @@ static void R_SetConstantColorLightGrid( const byte color[3] )
imageParams.wrapType = wrapTypeEnum_t::WT_EDGE_CLAMP;

tr.lightGrid1Image = R_Create3DImage("<lightGrid1>", (const byte *)w->lightGridData1, w->lightGridBounds[ 0 ], w->lightGridBounds[ 1 ], w->lightGridBounds[ 2 ], imageParams );
tr.lightGrid2Image = R_Create3DImage("<lightGrid2>", (const byte *)w->lightGridData2, w->lightGridBounds[ 0 ], w->lightGridBounds[ 1 ], w->lightGridBounds[ 2 ], imageParams );

if ( glConfig.deluxeMapping )
{
tr.lightGrid2Image = R_Create3DImage("<lightGrid2>", (const byte *)w->lightGridData2, w->lightGridBounds[ 0 ], w->lightGridBounds[ 1 ], w->lightGridBounds[ 2 ], imageParams );
}
}

/*
Expand Down Expand Up @@ -3539,14 +3543,18 @@ void R_LoadLightGrid( lump_t *l )
tmpAmbient[ 2 ] = in->ambient[ 2 ];
tmpAmbient[ 3 ] = 255;

/* Make sure we don't change the (0, 0, 0) points because those are points in walls,
which we'll fill up by interpolating nearby points later */
if ( tmpAmbient[ 0 ] == 0 && tmpAmbient[ 1 ] == 0 && tmpAmbient[ 2 ] == 0 )
{
continue;
}

tmpDirected[ 0 ] = in->directed[ 0 ];
tmpDirected[ 1 ] = in->directed[ 1 ];
tmpDirected[ 2 ] = in->directed[ 2 ];
tmpDirected[ 3 ] = 255;

R_LinearizeLightingColorBytes( tmpAmbient );
R_LinearizeLightingColorBytes( tmpDirected );

R_ColorShiftLightingBytes( tmpAmbient );
R_ColorShiftLightingBytes( tmpDirected );

Expand All @@ -3556,55 +3564,53 @@ void R_LoadLightGrid( lump_t *l )
directedColor[ j ] = tmpDirected[ j ] * ( 1.0f / 255.0f );
}

if ( tr.worldLinearizeTexture )
{
convertFromSRGB( ambientColor );
convertFromSRGB( directedColor );
}

const float forceAmbient = r_forceAmbient.Get();
if ( ambientColor[0] < forceAmbient &&
ambientColor[1] < forceAmbient &&
ambientColor[2] < forceAmbient &&
/* Make sure we don't change the (0, 0, 0) points because those are points in walls,
which we'll fill up by interpolating nearby points later */
( ambientColor[0] != 0 ||
ambientColor[1] != 0 ||
ambientColor[2] != 0 ) ) {
ambientColor[2] < forceAmbient )
{
VectorSet( ambientColor, forceAmbient, forceAmbient, forceAmbient );
}

// standard spherical coordinates to cartesian coordinates conversion

// decode X as cos( lat ) * sin( long )
// decode Y as sin( lat ) * sin( long )
// decode Z as cos( long )

// RB: having a look in NormalToLatLong used by q3map2 shows the order of latLong
// Lng = 0 at (1,0,0), 90 at (0,1,0), etc., encoded in 8-bit sine table format
// Lat = 0 at (0,0,1) to 180 (0,0,-1), encoded in 8-bit sine table format
// (so the upper bit of lat is wasted)

// Lat = 0 at (1,0,0) to 360 (-1,0,0), encoded in 8-bit sine table format
// Lng = 0 at (0,0,1) to 180 (0,0,-1), encoded in 8-bit sine table format
lat = DEG2RAD( in->latLong[ 0 ] * ( 360.0f / 255.0f ) );
lng = DEG2RAD( in->latLong[ 1 ] * ( 360.0f / 255.0f ) );

lat = DEG2RAD( in->latLong[ 1 ] * ( 360.0f / 255.0f ) );
lng = DEG2RAD( in->latLong[ 0 ] * ( 360.0f / 255.0f ) );

direction[ 0 ] = cosf( lat ) * sinf( lng );
direction[ 1 ] = sinf( lat ) * sinf( lng );
direction[ 2 ] = cosf( lng );
direction[ 0 ] = cosf( lng ) * sinf( lat );
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 ]) );

// Avoid division-by-zero.
float ambientLength = VectorLength(ambientColor);
float directedLength = VectorLength(directedColor);
float length = ambientLength + directedLength;
gridPoint1->ambientPart = length ? floatToUnorm8( ambientLength / length ) : 0;
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 ] );
gridPoint2->unused = 0;
gridPoint2->isSet = 255;
}

// fill in gridpoints with zero light (samples in walls) to avoid
// darkening of objects near walls
// FIXME: the interpolation includes other interpolated data points so the
// result depends on iteration order
gridPoint1 = w->lightGridData1;
gridPoint2 = w->lightGridData2;

Expand All @@ -3621,10 +3627,10 @@ void R_LoadLightGrid( lump_t *l )
from[ 0 ] = i - 1;
to[ 0 ] = i + 1;

if( gridPoint1->color[ 0 ] ||
gridPoint1->color[ 1 ] ||
gridPoint1->color[ 2 ] )
if ( gridPoint2->isSet )
{
continue;
}

scale = R_InterpolateLightGrid( w, from, to, factors,
ambientColor, directedColor,
Expand All @@ -3645,7 +3651,7 @@ void R_LoadLightGrid( lump_t *l )
gridPoint2->direction[0] = 128 + floatToSnorm8(direction[0]);
gridPoint2->direction[1] = 128 + floatToSnorm8(direction[1]);
gridPoint2->direction[2] = 128 + floatToSnorm8(direction[2]);
gridPoint2->unused = 0;
gridPoint2->isSet = 255;
}
}
}
Expand All @@ -3657,7 +3663,11 @@ void R_LoadLightGrid( lump_t *l )
imageParams.wrapType = wrapTypeEnum_t::WT_EDGE_CLAMP;

tr.lightGrid1Image = R_Create3DImage("<lightGrid1>", (const byte *)w->lightGridData1, w->lightGridBounds[ 0 ], w->lightGridBounds[ 1 ], w->lightGridBounds[ 2 ], imageParams );
tr.lightGrid2Image = R_Create3DImage("<lightGrid2>", (const byte *)w->lightGridData2, w->lightGridBounds[ 0 ], w->lightGridBounds[ 1 ], w->lightGridBounds[ 2 ], imageParams );

if ( glConfig.deluxeMapping )
{
tr.lightGrid2Image = R_Create3DImage("<lightGrid2>", (const byte *)w->lightGridData2, w->lightGridBounds[ 0 ], w->lightGridBounds[ 1 ], w->lightGridBounds[ 2 ], imageParams );
}

Log::Debug("%i light grid points created", w->numLightGridPoints );
}
Expand Down Expand Up @@ -4618,14 +4628,13 @@ static void SetWorldLight() {
tr.modelLight = lightMode_t::GRID;
}

if ( glConfig.deluxeMapping ) {
// Enable deluxe mapping emulation if light direction grid is there.
if ( tr.lightGrid2Image ) {
// Game model surfaces use grid lighting, they don't have vertex light colors.
tr.modelDeluxe = deluxeMode_t::GRID;
// Enable deluxe mapping emulation if light direction grid is there.
if ( tr.lightGrid2Image ) {
ASSERT( glConfig.deluxeMapping );
// Game model surfaces use grid lighting, they don't have vertex light colors.
tr.modelDeluxe = deluxeMode_t::GRID;

// Only game models use emulated deluxe map from light direction grid.
}
// Only game models use emulated deluxe map from light direction grid.
}
}

Expand Down Expand Up @@ -4678,7 +4687,11 @@ static void SetConstUniforms() {
}

globalUBOProxy->SetUniform_LightGrid1Bindless( GL_BindToTMU( BIND_LIGHTGRID1, tr.lightGrid1Image ) );
globalUBOProxy->SetUniform_LightGrid2Bindless( GL_BindToTMU( BIND_LIGHTGRID2, tr.lightGrid2Image ) );

if ( tr.lightGrid2Image )
{
globalUBOProxy->SetUniform_LightGrid2Bindless( GL_BindToTMU( BIND_LIGHTGRID2, tr.lightGrid2Image ) );
}
}

if ( glConfig.usingMaterialSystem ) {
Expand Down
2 changes: 1 addition & 1 deletion src/engine/renderer/tr_light.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ float R_InterpolateLightGrid( world_t *w, int from[3], int to[3],
gp1 = w->lightGridData1 + x * gridStep[ 0 ] + y * gridStep[ 1 ] + z * gridStep[ 2 ];
gp2 = w->lightGridData2 + x * gridStep[ 0 ] + y * gridStep[ 1 ] + z * gridStep[ 2 ];

if ( !( gp1->color[ 0 ] || gp1->color[ 1 ] || gp1->color[ 2 ]) )
if ( !gp2->isSet )
{
continue; // ignore samples in walls
}
Expand Down
5 changes: 3 additions & 2 deletions src/engine/renderer/tr_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -1704,7 +1704,8 @@ enum
struct bspGridPoint2_t
{
byte direction[3];
byte unused;
// use 0 and 255 as the boolean values so that the image uploader skips the alpha component
byte isSet;
};

struct AABB {
Expand Down Expand Up @@ -3229,7 +3230,7 @@ void GLimp_LogComment_( std::string comment );

@param tetraVerts[0..2] are the ground vertices, tetraVerts[3] is the pyramid offset
*/
void Tess_AddTetrahedron( vec4_t tetraVerts[ 4 ], const Color::Color& color );
void Tess_AddTetrahedron( vec4_t tetraVerts[ 4 ], Color::Color color );

void Tess_AddCube( const vec3_t position, const vec3_t minSize, const vec3_t maxSize, const Color::Color& color );
void Tess_AddCubeWithNormals( const vec3_t position, const vec3_t minSize, const vec3_t maxSize, const Color::Color& color );
Expand Down
3 changes: 2 additions & 1 deletion src/engine/renderer/tr_surface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,12 +399,13 @@ void Tess_AddQuadStamp2WithNormals( vec4_t quadVerts[ 4 ], const Color::Color& c
}

// Defines ATTR_POSITION, ATTR_COLOR
void Tess_AddTetrahedron( vec4_t tetraVerts[ 4 ], const Color::Color& colorf )
void Tess_AddTetrahedron( vec4_t tetraVerts[ 4 ], Color::Color colorf )
{
int k;

Tess_CheckOverflow( 12, 12 );

colorf.Clamp();
Color::Color32Bit color = colorf;

// ground triangle
Expand Down
Loading