diff --git a/src/engine/null/null_renderer.cpp b/src/engine/null/null_renderer.cpp index 4c9c27dd6e..a95ad46380 100644 --- a/src/engine/null/null_renderer.cpp +++ b/src/engine/null/null_renderer.cpp @@ -126,7 +126,6 @@ bool RE_LoadDynamicShader( const char*, const char* ) } void RE_Finish() { } void RE_TakeVideoFrame( int, int, byte*, byte*, bool ) { } -void RE_AddRefLightToScene( const refLight_t* ) { } int RE_RegisterAnimation( const char* ) { return 1; @@ -259,7 +258,6 @@ refexport_t *GetRefAPI( int, refimport_t* ) re.Finish = RE_Finish; re.TakeVideoFrame = RE_TakeVideoFrame; - re.AddRefLightToScene = RE_AddRefLightToScene; // RB: alternative skeletal animation system re.RegisterAnimation = RE_RegisterAnimation; diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index df8cd92652..361a685842 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -1977,23 +1977,6 @@ static void RB_SetupLightForLighting( trRefLight_t *light ) GL_VertexAttribsState( ATTR_POSITION | ATTR_COLOR ); Tess_DrawElements(); - // draw light volume - if ( light->isStatic && light->frustumVBO && light->frustumIBO ) - { - gl_genericShader->SetUniform_ColorModulate( colorGen_t::CGEN_CUSTOM_RGB, alphaGen_t::AGEN_CUSTOM ); - gl_genericShader->SetUniform_Color( Color::Yellow ); - - R_BindVBO( light->frustumVBO ); - R_BindIBO( light->frustumIBO ); - - GL_VertexAttribsState( ATTR_POSITION ); - - tess.numVertexes = light->frustumVerts; - tess.numIndexes = light->frustumIndexes; - - Tess_DrawElements(); - } - tess.multiDrawPrimitives = 0; tess.numIndexes = 0; tess.numVertexes = 0; @@ -3493,25 +3476,7 @@ static void RB_RenderDebugUtils() Tess_Begin( Tess_StageIteratorDebug, nullptr, nullptr, true, -1, 0 ); - if ( light->isStatic && light->frustumVBO && light->frustumIBO ) { - // go back to the world modelview matrix - backEnd.orientation = backEnd.viewParms.world; - GL_LoadModelViewMatrix( backEnd.viewParms.world.modelViewMatrix ); - gl_genericShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - gl_genericShader->SetUniform_ModelMatrix( backEnd.orientation.transformMatrix ); - - R_BindVBO( light->frustumVBO ); - R_BindIBO( light->frustumIBO ); - - GL_VertexAttribsState( ATTR_POSITION ); - - tess.numVertexes = light->frustumVerts; - tess.numIndexes = light->frustumIndexes; - } - else - { - // set up the transformation matrix R_RotateLightForViewParms( light, &backEnd.viewParms, &backEnd.orientation ); @@ -5365,11 +5330,6 @@ RB_SetupLights */ const RenderCommand *SetupLightsCommand::ExecuteSelf( ) const { - if ( !glConfig2.realtimeLighting ) - { - return this + 1; - } - int numLights; GLenum bufferTarget = glConfig2.uniformBufferObjectAvailable ? GL_UNIFORM_BUFFER : GL_PIXEL_UNPACK_BUFFER; diff --git a/src/engine/renderer/tr_bsp.cpp b/src/engine/renderer/tr_bsp.cpp index ea9784a0a7..3f3cb9a0d2 100644 --- a/src/engine/renderer/tr_bsp.cpp +++ b/src/engine/renderer/tr_bsp.cpp @@ -35,15 +35,8 @@ RE_LoadWorldMap(const char *name); */ static world_t s_worldData; -static int s_lightCount; -static std::vector s_interactions; static byte *fileBase; -static int c_redundantInteractions; -static int c_vboWorldSurfaces; -static int c_vboLightSurfaces; -static int c_vboShadowSurfaces; - //=============================================================================== /* @@ -4272,19 +4265,11 @@ R_LoadEntities */ void R_LoadEntities( lump_t *l, std::string &externalEntities ) { - int i; - const char *p, *pOld, *token; + const char *p, *token; char *s; char keyname[ MAX_TOKEN_CHARS ]; char value[ MAX_TOKEN_CHARS ]; world_t *w; - bool isLight = false; - int numEntities = 0; - int numLights = 0; - int numOmniLights = 0; - int numProjLights = 0; - int numParallelLights = 0; - trRefLight_t *light; Log::Debug("...loading entities" ); @@ -4449,2012 +4434,211 @@ void R_LoadEntities( lump_t *l, std::string &externalEntities ) continue; } } +} + +/* +================= +R_GetEntityToken +================= +*/ +bool R_GetEntityToken( char *buffer, int size ) +{ + const char *s; - pOld = p; - numEntities = 1; // parsed worldspawn so far + s = COM_Parse2( &s_worldData.entityParsePoint ); + Q_strncpyz( buffer, s, size ); - // count lights - while ( true ) + if ( !s_worldData.entityParsePoint || !s[ 0 ] ) { - // parse { - token = COM_ParseExt2( &p, true ); + s_worldData.entityParsePoint = s_worldData.entityString; + return false; + } + else + { + return true; + } +} - if ( !*token ) - { - // end of entities string - break; - } +static const int HASHTABLE_SIZE = 7919; // 32749 // 2039 /* prime, use % */ +#define HASH_USE_EPSILON - if ( *token != '{' ) - { - Log::Warn("expected { found '%s'", token ); - break; - } +#ifdef HASH_USE_EPSILON +#define HASH_XYZ_EPSILON 256.0f +#define HASH_XYZ_EPSILONSPACE_MULTIPLIER 1.f / HASH_XYZ_EPSILON +#endif - // new entity - isLight = false; +unsigned int VertexCoordGenerateHash( const vec3_t xyz ) +{ + unsigned int hash = 0; - // parse epairs - while ( true ) - { - // parse key - token = COM_ParseExt2( &p, true ); +#ifndef HASH_USE_EPSILON + hash += ~( * ( ( unsigned int * ) &xyz[ 0 ] ) << 15 ); + hash ^= ( * ( ( unsigned int * ) &xyz[ 0 ] ) >> 10 ); + hash += ( * ( ( unsigned int * ) &xyz[ 1 ] ) << 3 ); + hash ^= ( * ( ( unsigned int * ) &xyz[ 1 ] ) >> 6 ); + hash += ~( * ( ( unsigned int * ) &xyz[ 2 ] ) << 11 ); + hash ^= ( * ( ( unsigned int * ) &xyz[ 2 ] ) >> 16 ); +#else + vec3_t xyz_epsilonspace; - if ( *token == '}' ) - { - break; - } + VectorScale( xyz, HASH_XYZ_EPSILONSPACE_MULTIPLIER, xyz_epsilonspace ); + xyz_epsilonspace[ 0 ] = floor( xyz_epsilonspace[ 0 ] ); + xyz_epsilonspace[ 1 ] = floor( xyz_epsilonspace[ 1 ] ); + xyz_epsilonspace[ 2 ] = floor( xyz_epsilonspace[ 2 ] ); - if ( !*token ) - { - Log::Warn("EOF without closing bracket" ); - break; - } + hash += ~( * ( ( unsigned int * ) &xyz_epsilonspace[ 0 ] ) << 15 ); + hash ^= ( * ( ( unsigned int * ) &xyz_epsilonspace[ 0 ] ) >> 10 ); + hash += ( * ( ( unsigned int * ) &xyz_epsilonspace[ 1 ] ) << 3 ); + hash ^= ( * ( ( unsigned int * ) &xyz_epsilonspace[ 1 ] ) >> 6 ); + hash += ~( * ( ( unsigned int * ) &xyz_epsilonspace[ 2 ] ) << 11 ); + hash ^= ( * ( ( unsigned int * ) &xyz_epsilonspace[ 2 ] ) >> 16 ); - Q_strncpyz( keyname, token, sizeof( keyname ) ); +#endif - // parse value - token = COM_ParseExt2( &p, false ); + hash = hash % ( HASHTABLE_SIZE ); + return hash; +} - if ( !*token ) - { - Log::Warn("missing value for key '%s'", keyname ); - continue; - } +vertexHash_t **NewVertexHashTable() +{ + vertexHash_t **hashTable = (vertexHash_t**) Z_Calloc( HASHTABLE_SIZE * sizeof( vertexHash_t * ) ); + return hashTable; +} - Q_strncpyz( value, token, sizeof( value ) ); +void FreeVertexHashTable( vertexHash_t **hashTable ) +{ + int i; + vertexHash_t *vertexHash; + vertexHash_t *nextVertexHash; - // check if this entity is a light - if ( !Q_stricmp( keyname, "classname" ) && !Q_stricmp( value, "light" ) ) - { - isLight = true; - } - } + if ( hashTable == nullptr ) + { + return; + } - if ( *token != '}' ) + for ( i = 0; i < HASHTABLE_SIZE; i++ ) + { + if ( hashTable[ i ] ) { - Log::Warn("expected } found '%s'", token ); - break; - } + nextVertexHash = nullptr; - if ( isLight ) - { - numLights++; - } + for ( vertexHash = hashTable[ i ]; vertexHash; vertexHash = nextVertexHash ) + { + nextVertexHash = vertexHash->next; - numEntities++; + Z_Free( vertexHash ); + } + } } - Log::Debug("%i total entities counted", numEntities ); - Log::Debug("%i total lights counted", numLights ); - - s_worldData.numLights = numLights; + Z_Free( hashTable ); +} - // Tr3B: FIXME add 1 dummy light so we don't trash the hunk memory system ... - s_worldData.lights = (trRefLight_t*) ri.Hunk_Alloc( ( s_worldData.numLights + 1 ) * sizeof( trRefLight_t ), ha_pref::h_low ); +vertexHash_t *FindVertexInHashTable( vertexHash_t **hashTable, const vec3_t xyz, float distance ) +{ + unsigned int hash; + vertexHash_t *vertexHash; - // basic light setup - for ( i = 0, light = s_worldData.lights; i < s_worldData.numLights; i++, light++ ) + if ( hashTable == nullptr || xyz == nullptr ) { - QuatClear( light->l.rotation ); - VectorClear( light->l.center ); - - light->l.color[ 0 ] = 1; - light->l.color[ 1 ] = 1; - light->l.color[ 2 ] = 1; - - light->l.scale = r_lightScale->value; - - light->l.radius = 300.0f; - - VectorClear( light->l.projTarget ); - VectorClear( light->l.projRight ); - VectorClear( light->l.projUp ); - VectorClear( light->l.projStart ); - VectorClear( light->l.projEnd ); - - light->l.inverseShadows = false; - - light->isStatic = true; - light->noRadiosity = false; - light->additive = true; - - light->shadowLOD = 0; + return nullptr; } - // parse lights - p = pOld; - numEntities = 1; - light = &s_worldData.lights[ 0 ]; + hash = VertexCoordGenerateHash( xyz ); - while ( true ) + for ( vertexHash = hashTable[ hash ]; vertexHash; vertexHash = vertexHash->next ) { - // parse { - token = COM_ParseExt2( &p, true ); +#ifndef HASH_USE_EPSILON - if ( !*token ) + if ( ( vertexHash->vcd.xyz[ 0 ] != xyz[ 0 ] || vertexHash->vcd.xyz[ 1 ] != xyz[ 1 ] || + vertexHash->vcd.xyz[ 2 ] != xyz[ 2 ] ) ) { - // end of entities string - break; + continue; } - if ( *token != '{' ) +#elif 1 + + if ( Distance( xyz, vertexHash->xyz ) > distance ) { - Log::Warn("expected { found '%s'", token ); - break; + continue; } - // new entity - isLight = false; +#else - // parse epairs - while ( true ) + if ( ( fabsf( xyz[ 0 ] - vertexHash->vcd.xyz[ 0 ] ) ) > HASH_XYZ_EPSILON || + ( fabsf( xyz[ 1 ] - vertexHash->vcd.xyz[ 1 ] ) ) > HASH_XYZ_EPSILON || + ( fabsf( xyz[ 2 ] - vertexHash->vcd.xyz[ 2 ] ) ) > HASH_XYZ_EPSILON ) { - // parse key - token = COM_ParseExt2( &p, true ); - - if ( *token == '}' ) - { - break; - } + continue; + } - if ( !*token ) - { - Log::Warn("EOF without closing bracket" ); - break; - } +#endif + return vertexHash; + } - Q_strncpyz( keyname, token, sizeof( keyname ) ); + return nullptr; +} - // parse value - token = COM_ParseExt2( &p, false ); +vertexHash_t *AddVertexToHashTable( vertexHash_t **hashTable, vec3_t xyz, void *data ) +{ + unsigned int hash; + vertexHash_t *vertexHash; - if ( !*token ) - { - Log::Warn("missing value for key '%s'", keyname ); - continue; - } + if ( hashTable == nullptr || xyz == nullptr ) + { + return nullptr; + } - Q_strncpyz( value, token, sizeof( value ) ); + vertexHash = (vertexHash_t*) Z_AllocUninit( sizeof( vertexHash_t ) ); - // check if this entity is a light - if ( !Q_stricmp( keyname, "classname" ) && !Q_stricmp( value, "light" ) ) - { - isLight = true; - } - // check for origin - else if ( !Q_stricmp( keyname, "origin" ) || !Q_stricmp( keyname, "light_origin" ) ) - { - sscanf( value, "%f %f %f", &light->l.origin[ 0 ], &light->l.origin[ 1 ], &light->l.origin[ 2 ] ); - s = &value[ 0 ]; - } - // check for center - else if ( !Q_stricmp( keyname, "light_center" ) ) - { - sscanf( value, "%f %f %f", &light->l.center[ 0 ], &light->l.center[ 1 ], &light->l.center[ 2 ] ); - s = &value[ 0 ]; - } - // check for color - else if ( !Q_stricmp( keyname, "_color" ) ) - { - sscanf( value, "%f %f %f", &light->l.color[ 0 ], &light->l.color[ 1 ], &light->l.color[ 2 ] ); - s = &value[ 0 ]; - } - // check for radius - else if ( !Q_stricmp( keyname, "light_radius" ) ) - { - vec_t rad_y, rad_z; - sscanf( value, "%f %f %f", &light->l.radius, &rad_y, &rad_z ); - if( rad_y != light->l.radius || rad_z != light->l.radius ) - Log::Warn( "non-spherical light" ); - s = &value[ 0 ]; - } - // check for light_target - else if ( !Q_stricmp( keyname, "light_target" ) ) - { - sscanf( value, "%f %f %f", &light->l.projTarget[ 0 ], &light->l.projTarget[ 1 ], &light->l.projTarget[ 2 ] ); - s = &value[ 0 ]; - light->l.rlType = refLightType_t::RL_PROJ; - } - // check for light_right - else if ( !Q_stricmp( keyname, "light_right" ) ) - { - sscanf( value, "%f %f %f", &light->l.projRight[ 0 ], &light->l.projRight[ 1 ], &light->l.projRight[ 2 ] ); - s = &value[ 0 ]; - light->l.rlType = refLightType_t::RL_PROJ; - } - // check for light_up - else if ( !Q_stricmp( keyname, "light_up" ) ) - { - sscanf( value, "%f %f %f", &light->l.projUp[ 0 ], &light->l.projUp[ 1 ], &light->l.projUp[ 2 ] ); - s = &value[ 0 ]; - light->l.rlType = refLightType_t::RL_PROJ; - } - // check for light_start - else if ( !Q_stricmp( keyname, "light_start" ) ) - { - sscanf( value, "%f %f %f", &light->l.projStart[ 0 ], &light->l.projStart[ 1 ], &light->l.projStart[ 2 ] ); - s = &value[ 0 ]; - light->l.rlType = refLightType_t::RL_PROJ; - } - // check for light_end - else if ( !Q_stricmp( keyname, "light_end" ) ) - { - sscanf( value, "%f %f %f", &light->l.projEnd[ 0 ], &light->l.projEnd[ 1 ], &light->l.projEnd[ 2 ] ); - s = &value[ 0 ]; - light->l.rlType = refLightType_t::RL_PROJ; - } - // check for radius - else if ( !Q_stricmp( keyname, "light" ) || !Q_stricmp( keyname, "_light" ) ) - { - light->l.radius = atof( value ); - } - // check for scale - else if ( !Q_stricmp( keyname, "light_scale" ) ) - { - light->l.scale = atof( value ); + hash = VertexCoordGenerateHash( xyz ); - if ( light->l.scale >= r_lightScale->value ) - { - light->l.scale = r_lightScale->value; - } - } - // check for light shader - else if ( !Q_stricmp( keyname, "texture" ) ) - { - light->l.attenuationShader = RE_RegisterShader( value, RSF_LIGHT_ATTENUATION ); - } - // check for rotation - else if ( !Q_stricmp( keyname, "rotation" ) || !Q_stricmp( keyname, "light_rotation" ) ) - { - matrix_t rotation; + VectorCopy( xyz, vertexHash->xyz ); + vertexHash->data = data; - sscanf( value, "%f %f %f %f %f %f %f %f %f", &rotation[ 0 ], &rotation[ 1 ], &rotation[ 2 ], - &rotation[ 4 ], &rotation[ 5 ], &rotation[ 6 ], &rotation[ 8 ], &rotation[ 9 ], &rotation[ 10 ] ); + // link into table + vertexHash->next = hashTable[ hash ]; + hashTable[ hash ] = vertexHash; - QuatFromMatrix( light->l.rotation, rotation ); - } - // check if this light does not cast any shadows - else if ( !Q_stricmp( keyname, "noshadows" ) && !Q_stricmp( value, "1" ) ) - { - light->l.noShadows = true; - } - // check if this light does not contribute to the global lightmapping - else if ( !Q_stricmp( keyname, "noradiosity" ) && !Q_stricmp( value, "1" ) ) - { - light->noRadiosity = true; - } - // check if this light is a parallel sun light - else if ( !Q_stricmp( keyname, "parallel" ) && !Q_stricmp( value, "1" ) ) - { - light->l.rlType = refLightType_t::RL_DIRECTIONAL; - } - } + return vertexHash; +} - if ( *token != '}' ) - { - Log::Warn("expected } found '%s'", token ); - break; - } +void GL_BindNearestCubeMap( int unit, const vec3_t xyz ) +{ + float distance, maxDistance; + cubemapProbe_t *cubeProbe; + unsigned int hash; + vertexHash_t *vertexHash; - if ( !isLight ) - { - // reset rotation because it may be set to the rotation of other entities - QuatClear( light->l.rotation ); - } - else - { - if ( ( numOmniLights + numProjLights + numParallelLights ) < s_worldData.numLights ) - { - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - numOmniLights++; - break; + if ( !r_reflectionMapping->integer ) + { + return; + } - case refLightType_t::RL_PROJ: - numProjLights++; - break; + if ( tr.cubeHashTable == nullptr || xyz == nullptr ) + { + return; + } - case refLightType_t::RL_DIRECTIONAL: - numParallelLights++; - break; + maxDistance = 9999999.0f; - default: - break; - } + hash = VertexCoordGenerateHash( xyz ); + image_t *autoCubeImage = tr.whiteCubeImage; - light++; - } - } + for ( vertexHash = tr.cubeHashTable[ hash ]; vertexHash; vertexHash = vertexHash->next ) + { + cubeProbe = (cubemapProbe_t*) vertexHash->data; - numEntities++; - } + distance = Distance( cubeProbe->origin, xyz ); - if ( ( numOmniLights + numProjLights + numParallelLights ) != s_worldData.numLights ) - { - Sys::Drop( "counted %i lights and parsed %i lights", s_worldData.numLights, ( numOmniLights + numProjLights + numParallelLights ) ); + if ( distance < maxDistance ) + { + autoCubeImage = cubeProbe->cubemap; + maxDistance = distance; + } } - Log::Debug("%i total entities parsed", numEntities ); - Log::Debug("%i total lights parsed", numOmniLights + numProjLights ); - Log::Debug("%i omni-directional lights parsed", numOmniLights ); - Log::Debug("%i projective lights parsed", numProjLights ); - Log::Debug("%i directional lights parsed", numParallelLights ); -} - -/* -================= -R_GetEntityToken -================= -*/ -bool R_GetEntityToken( char *buffer, int size ) -{ - const char *s; - - s = COM_Parse2( &s_worldData.entityParsePoint ); - Q_strncpyz( buffer, s, size ); - - if ( !s_worldData.entityParsePoint || !s[ 0 ] ) - { - s_worldData.entityParsePoint = s_worldData.entityString; - return false; - } - else - { - return true; - } -} - -/* -================= -R_PrecacheInteraction -================= -*/ -static void R_PrecacheInteraction( trRefLight_t *light, bspSurface_t *surface ) -{ - interactionCache_t *iaCache; - - iaCache = (interactionCache_t*) ri.Hunk_Alloc( sizeof( *iaCache ), ha_pref::h_low ); - s_interactions.push_back( iaCache ); - - // connect to interaction grid - if ( !light->firstInteractionCache ) - { - light->firstInteractionCache = iaCache; - } - - if ( light->lastInteractionCache ) - { - light->lastInteractionCache->next = iaCache; - } - - light->lastInteractionCache = iaCache; - - iaCache->next = nullptr; - iaCache->surface = surface; - - iaCache->redundant = false; -} - -/* -================ -R_PrecacheGenericSurfInteraction -================ -*/ -static bool R_PrecacheGenericSurfInteraction( srfGeneric_t *face, trRefLight_t *light ) -{ - return BoundsIntersect( face->bounds[ 0 ], face->bounds[ 1 ], light->worldBounds[ 0 ], light->worldBounds[ 1 ] ); -} - -/* -====================== -R_PrecacheInteractionSurface -====================== -*/ -static void R_PrecacheInteractionSurface( bspSurface_t *surf, trRefLight_t *light ) -{ - bool intersects; - - if ( surf->lightCount == s_lightCount ) - { - return; // already checked this surface - } - - surf->lightCount = s_lightCount; - - // skip all surfaces that don't matter for lighting only pass - if ( surf->shader->isSky || ( !surf->shader->interactLight && surf->shader->noShadows ) ) - { - return; - } - - switch ( *surf->data ) - { - case surfaceType_t::SF_FACE: - case surfaceType_t::SF_GRID: - case surfaceType_t::SF_TRIANGLES: - intersects = R_PrecacheGenericSurfInteraction( ( srfGeneric_t * ) surf->data, light ); - break; - default: - intersects = false; - break; - } - - if ( intersects ) - { - R_PrecacheInteraction( light, surf ); - } -} - -/* -================ -R_RecursivePrecacheInteractionNode -================ -*/ -static void R_RecursivePrecacheInteractionNode( bspNode_t *node, trRefLight_t *light ) -{ - int r; - - do - { - - if ( node->contents != -1 ) - { - break; - } - - // node is just a decision point, so go down both sides - // since we don't care about sort orders, just go positive to negative - r = BoxOnPlaneSide( light->worldBounds[ 0 ], light->worldBounds[ 1 ], node->plane ); - - switch ( r ) - { - case 1: - node = node->children[ 0 ]; - break; - - case 2: - node = node->children[ 1 ]; - break; - - case 3: - default: - // recurse down the children, front side first - R_RecursivePrecacheInteractionNode( node->children[ 0 ], light ); - - // tail recurse - node = node->children[ 1 ]; - break; - } - } - while ( true ); - - { - // leaf node, so add mark surfaces - int c; - bspSurface_t *surf, **mark; - vec3_t worldBounds[ 2 ]; - - // add the individual surfaces - mark = s_worldData.markSurfaces + node->firstMarkSurface; - c = node->numMarkSurfaces; - - while ( c-- ) - { - // the surface may have already been added if it - // spans multiple leafs - surf = *mark; - R_PrecacheInteractionSurface( surf, light ); - mark++; - } - - VectorCopy( node->mins, worldBounds[ 0 ] ); - VectorCopy( node->maxs, worldBounds[ 1 ] ); - - if ( node->numMarkSurfaces > 0 && R_CullLightWorldBounds( light, worldBounds ) != cullResult_t::CULL_OUT ) - { - link_t *l; - - l = ( link_t *)ri.Hunk_Alloc( sizeof( *l ), ha_pref::h_low ); - InitLink( l, node ); - - InsertLink( l, &light->leafs ); - } - } -} - -/* -================= -R_CreateInteractionVBO -================= -*/ -static interactionVBO_t *R_CreateInteractionVBO( trRefLight_t *light ) -{ - interactionVBO_t *iaVBO; - - iaVBO = (interactionVBO_t*) ri.Hunk_Alloc( sizeof( *iaVBO ), ha_pref::h_low ); - - // connect to interaction grid - if ( !light->firstInteractionVBO ) - { - light->firstInteractionVBO = iaVBO; - } - - if ( light->lastInteractionVBO ) - { - light->lastInteractionVBO->next = iaVBO; - } - - light->lastInteractionVBO = iaVBO; - iaVBO->next = nullptr; - - return iaVBO; -} - -/* -================= -InteractionCacheCompare -compare function for qsort() -================= -*/ -static int InteractionCacheCompare( const void *a, const void *b ) -{ - interactionCache_t *aa, *bb; - - aa = * ( interactionCache_t ** ) a; - bb = * ( interactionCache_t ** ) b; - - // shader first - if ( aa->surface->shader < bb->surface->shader ) - { - return -1; - } - - else if ( aa->surface->shader > bb->surface->shader ) - { - return 1; - } - - // then alphaTest - if ( aa->surface->shader->alphaTest < bb->surface->shader->alphaTest ) - { - return -1; - } - - else if ( aa->surface->shader->alphaTest > bb->surface->shader->alphaTest ) - { - return 1; - } - - return 0; -} - -static int UpdateLightTriangles( const srfVert_t *verts, int numTriangles, srfTriangle_t *triangles, shader_t *surfaceShader, - trRefLight_t *light ) -{ - int i; - srfTriangle_t *tri; - int numFacing; - - numFacing = 0; - - for ( i = 0, tri = triangles; i < numTriangles; i++, tri++ ) - { - vec3_t pos[ 3 ]; - float d; - - VectorCopy( verts[ tri->indexes[ 0 ] ].xyz, pos[ 0 ] ); - VectorCopy( verts[ tri->indexes[ 1 ] ].xyz, pos[ 1 ] ); - VectorCopy( verts[ tri->indexes[ 2 ] ].xyz, pos[ 2 ] ); - - plane_t triPlane; - if ( PlaneFromPoints( triPlane, pos[ 0 ], pos[ 1 ], pos[ 2 ] ) ) - { - - if ( light->l.rlType == refLightType_t::RL_DIRECTIONAL ) - { - vec3_t lightDirection; - - // light direction is from surface to light - VectorCopy( tr.sunDirection, lightDirection ); - - d = DotProduct( triPlane.normal, lightDirection ); - - tri->facingLight = surfaceShader->cullType == CT_TWO_SIDED || ( d > 0 && surfaceShader->cullType != CT_BACK_SIDED ); - } - else - { - // check if light origin is behind triangle - d = DotProduct( triPlane.normal, light->origin ) - triPlane.dist; - - tri->facingLight = surfaceShader->cullType == CT_TWO_SIDED || ( d > 0 && surfaceShader->cullType != CT_BACK_SIDED ); - } - } - else - { - tri->facingLight = true; // FIXME ? - } - - if ( R_CullLightTriangle( light, pos ) == cullResult_t::CULL_OUT ) - { - tri->facingLight = false; - } - - if ( tri->facingLight ) - { - numFacing++; - } - } - - return numFacing; -} - -/* -=============== -R_CreateVBOLightMeshes -=============== -*/ -static void R_CreateVBOLightMeshes( trRefLight_t *light ) -{ - int i, j, k, l; - - int numVerts; - - int numTriangles, numLitTriangles; - srfTriangle_t *tri; - glIndex_t *indexes; - - interactionVBO_t *iaVBO; - - interactionCache_t *iaCache, *iaCache2; - interactionCache_t **iaCachesSorted; - int numCaches; - - shader_t *shader, *oldShader; - - bspSurface_t *surface; - - srfVBOMesh_t *vboSurf; - vec3_t bounds[ 2 ]; - - if ( !r_vboLighting->integer ) - { - return; - } - - if ( !light->firstInteractionCache ) - { - // this light has no interactions precached - return; - } - - // count number of interaction caches - numCaches = 0; - - for ( iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next ) - { - if ( iaCache->redundant ) - { - continue; - } - - surface = iaCache->surface; - - if ( !surface->shader->interactLight ) - { - continue; - } - - if ( surface->shader->isPortal ) - { - continue; - } - - numCaches++; - } - - // build interaction caches list - iaCachesSorted = (interactionCache_t**) ri.Hunk_AllocateTempMemory( numCaches * sizeof( iaCachesSorted[ 0 ] ) ); - - numCaches = 0; - - for ( iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next ) - { - if ( iaCache->redundant ) - { - continue; - } - - surface = iaCache->surface; - - if ( !surface->shader->interactLight ) - { - continue; - } - - if ( surface->shader->isPortal ) - { - continue; - } - - iaCachesSorted[ numCaches ] = iaCache; - numCaches++; - } - - // sort interaction caches by shader - qsort( iaCachesSorted, numCaches, sizeof( *iaCachesSorted ), InteractionCacheCompare ); - - // create a VBO for each shader - shader = oldShader = nullptr; - - for ( k = 0; k < numCaches; k++ ) - { - iaCache = iaCachesSorted[ k ]; - - iaCache->mergedIntoVBO = true; - - shader = iaCache->surface->shader; - - if ( shader != oldShader ) - { - oldShader = shader; - - // count vertices and indices - numVerts = 0; - numTriangles = 0; - - ClearBounds( bounds[ 0 ], bounds[ 1 ] ); - - for ( l = k; l < numCaches; l++ ) - { - iaCache2 = iaCachesSorted[ l ]; - - surface = iaCache2->surface; - - if ( surface->shader != shader ) - { - continue; - } - - if ( *surface->data == surfaceType_t::SF_FACE ) - { - srfSurfaceFace_t *srf = ( srfSurfaceFace_t * ) surface->data; - - if ( srf->numTriangles ) - { - numLitTriangles = UpdateLightTriangles( s_worldData.verts, srf->numTriangles, s_worldData.triangles + srf->firstTriangle, surface->shader, light ); - - if ( numLitTriangles ) - { - BoundsAdd( bounds[ 0 ], bounds[ 1 ], srf->bounds[ 0 ], srf->bounds[ 1 ] ); - } - - numTriangles += numLitTriangles; - } - - if ( srf->numVerts ) - { - numVerts += srf->numVerts; - } - } - else if ( *surface->data == surfaceType_t::SF_GRID ) - { - srfGridMesh_t *srf = ( srfGridMesh_t * ) surface->data; - - if ( srf->numTriangles ) - { - numLitTriangles = UpdateLightTriangles( s_worldData.verts, srf->numTriangles, s_worldData.triangles + srf->firstTriangle, surface->shader, light ); - - if ( numLitTriangles ) - { - BoundsAdd( bounds[ 0 ], bounds[ 1 ], srf->bounds[ 0 ], srf->bounds[ 1 ] ); - } - - numTriangles += numLitTriangles; - } - - if ( srf->numVerts ) - { - numVerts += srf->numVerts; - } - } - else if ( *surface->data == surfaceType_t::SF_TRIANGLES ) - { - srfTriangles_t *srf = ( srfTriangles_t * ) surface->data; - - if ( srf->numTriangles ) - { - numLitTriangles = UpdateLightTriangles( s_worldData.verts, srf->numTriangles, s_worldData.triangles + srf->firstTriangle, surface->shader, light ); - - if ( numLitTriangles ) - { - BoundsAdd( bounds[ 0 ], bounds[ 1 ], srf->bounds[ 0 ], srf->bounds[ 1 ] ); - } - - numTriangles += numLitTriangles; - } - - if ( srf->numVerts ) - { - numVerts += srf->numVerts; - } - } - } - - if ( !numVerts || !numTriangles ) - { - continue; - } - - // create surface - vboSurf = (srfVBOMesh_t*) ri.Hunk_Alloc( sizeof( *vboSurf ), ha_pref::h_low ); - vboSurf->surfaceType = surfaceType_t::SF_VBO_MESH; - vboSurf->numIndexes = numTriangles * 3; - vboSurf->numVerts = numVerts; - vboSurf->lightmapNum = -1; - - VectorCopy( bounds[ 0 ], vboSurf->bounds[ 0 ] ); - VectorCopy( bounds[ 1 ], vboSurf->bounds[ 1 ] ); - - // create arrays - indexes = (glIndex_t*) ri.Hunk_AllocateTempMemory( 3 * numTriangles * sizeof( glIndex_t ) ); - numTriangles = 0; - - // build triangle indices - for ( l = k; l < numCaches; l++ ) - { - iaCache2 = iaCachesSorted[ l ]; - - surface = iaCache2->surface; - - if ( surface->shader != shader ) - { - continue; - } - - if ( *surface->data == surfaceType_t::SF_FACE ) - { - srfSurfaceFace_t *srf = ( srfSurfaceFace_t * ) surface->data; - - for ( i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++ ) - { - if ( tri->facingLight ) - { - for ( j = 0; j < 3; j++ ) - { - indexes[ 3 * numTriangles + j ] = tri->indexes[ j ]; - } - - numTriangles++; - } - } - } - else if ( *surface->data == surfaceType_t::SF_GRID ) - { - srfGridMesh_t *srf = ( srfGridMesh_t * ) surface->data; - - for ( i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++ ) - { - if ( tri->facingLight ) - { - for ( j = 0; j < 3; j++ ) - { - indexes[ 3 * numTriangles + j ] = tri->indexes[ j ]; - } - - numTriangles++; - } - } - } - else if ( *surface->data == surfaceType_t::SF_TRIANGLES ) - { - srfTriangles_t *srf = ( srfTriangles_t * ) surface->data; - - for ( i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++ ) - { - if ( tri->facingLight ) - { - for ( j = 0; j < 3; j++ ) - { - indexes[ 3 * numTriangles + j ] = tri->indexes[ j ]; - } - - numTriangles++; - } - } - } - } - - vboSurf->vbo = s_worldData.vbo; - vboSurf->ibo = R_CreateStaticIBO( va( "staticLightMesh_IBO %i", c_vboLightSurfaces ), indexes, 3 * numTriangles ); - - ri.Hunk_FreeTempMemory( indexes ); - - // add everything needed to the light - iaVBO = R_CreateInteractionVBO( light ); - iaVBO->shader = shader; - iaVBO->vboLightMesh = vboSurf; - - c_vboLightSurfaces++; - } - } - - ri.Hunk_FreeTempMemory( iaCachesSorted ); -} - -/* -=============== -R_CreateVBOShadowMeshes -=============== -*/ -static void R_CreateVBOShadowMeshes( trRefLight_t *light ) -{ - int i, j, k, l; - - int numVerts; - - int numTriangles, numLitTriangles; - glIndex_t *indexes; - srfTriangle_t *tri; - - interactionVBO_t *iaVBO; - - interactionCache_t *iaCache, *iaCache2; - interactionCache_t **iaCachesSorted; - int numCaches; - - shader_t *shader, *oldShader; - bool alphaTest, oldAlphaTest; - - bspSurface_t *surface; - - srfVBOMesh_t *vboSurf; - vec3_t bounds[ 2 ]; - - if ( !r_vboShadows->integer ) - { - return; - } - - if ( !glConfig2.shadowMapping ) - { - return; - } - - if ( !light->firstInteractionCache ) - { - // this light has no interactions precached - return; - } - - if ( light->l.noShadows ) - { - return; - } - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - return; - - case refLightType_t::RL_DIRECTIONAL: - case refLightType_t::RL_PROJ: - break; - - default: - return; - } - - // count number of interaction caches - numCaches = 0; - - for ( iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next ) - { - if ( iaCache->redundant ) - { - continue; - } - - surface = iaCache->surface; - - if ( !surface->shader->interactLight ) - { - continue; - } - - if ( surface->shader->isSky ) - { - continue; - } - - if ( surface->shader->noShadows ) - { - continue; - } - - if (surface->shader->sort > Util::ordinal(shaderSort_t::SS_OPAQUE)) - { - continue; - } - - if ( surface->shader->isPortal ) - { - continue; - } - - numCaches++; - } - - // build interaction caches list - iaCachesSorted = (interactionCache_t**) ri.Hunk_AllocateTempMemory( numCaches * sizeof( iaCachesSorted[ 0 ] ) ); - - numCaches = 0; - - for ( iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next ) - { - if ( iaCache->redundant ) - { - continue; - } - - surface = iaCache->surface; - - if ( !surface->shader->interactLight ) - { - continue; - } - - if ( surface->shader->isSky ) - { - continue; - } - - if ( surface->shader->noShadows ) - { - continue; - } - - if ( surface->shader->sort > Util::ordinal(shaderSort_t::SS_OPAQUE) ) - { - continue; - } - - if ( surface->shader->isPortal ) - { - continue; - } - - iaCachesSorted[ numCaches ] = iaCache; - numCaches++; - } - - // sort interaction caches by shader - qsort( iaCachesSorted, numCaches, sizeof( *iaCachesSorted ), InteractionCacheCompare ); - - // create a VBO for each shader - shader = oldShader = nullptr; - oldAlphaTest = alphaTest = true; - - for ( k = 0; k < numCaches; k++ ) - { - iaCache = iaCachesSorted[ k ]; - - shader = iaCache->surface->shader; - alphaTest = shader->alphaTest; - - iaCache->mergedIntoVBO = true; - - if ( alphaTest ? shader != oldShader : alphaTest != oldAlphaTest ) - { - oldShader = shader; - oldAlphaTest = alphaTest; - - // count vertices and indices - numVerts = 0; - numTriangles = 0; - - ClearBounds( bounds[ 0 ], bounds[ 1 ] ); - - for ( l = k; l < numCaches; l++ ) - { - iaCache2 = iaCachesSorted[ l ]; - - surface = iaCache2->surface; - - if ( alphaTest ) - { - if ( surface->shader != shader ) - { - break; - } - } - else - { - if ( surface->shader->alphaTest != alphaTest ) - { - break; - } - } - - if ( *surface->data == surfaceType_t::SF_FACE ) - { - srfSurfaceFace_t *srf = ( srfSurfaceFace_t * ) surface->data; - - if ( srf->numTriangles ) - { - numLitTriangles = UpdateLightTriangles( s_worldData.verts, srf->numTriangles, s_worldData.triangles + srf->firstTriangle, surface->shader, light ); - - if ( numLitTriangles ) - { - BoundsAdd( bounds[ 0 ], bounds[ 1 ], srf->bounds[ 0 ], srf->bounds[ 1 ] ); - } - - numTriangles += numLitTriangles; - } - - if ( srf->numVerts ) - { - numVerts += srf->numVerts; - } - } - else if ( *surface->data == surfaceType_t::SF_GRID ) - { - srfGridMesh_t *srf = ( srfGridMesh_t * ) surface->data; - - if ( srf->numTriangles ) - { - numLitTriangles = UpdateLightTriangles( s_worldData.verts, srf->numTriangles, s_worldData.triangles + srf->firstTriangle, surface->shader, light ); - - if ( numLitTriangles ) - { - BoundsAdd( bounds[ 0 ], bounds[ 1 ], srf->bounds[ 0 ], srf->bounds[ 1 ] ); - } - - numTriangles += numLitTriangles; - } - - if ( srf->numVerts ) - { - numVerts += srf->numVerts; - } - } - else if ( *surface->data == surfaceType_t::SF_TRIANGLES ) - { - srfTriangles_t *srf = ( srfTriangles_t * ) surface->data; - - if ( srf->numTriangles ) - { - numLitTriangles = UpdateLightTriangles( s_worldData.verts, srf->numTriangles, s_worldData.triangles + srf->firstTriangle, surface->shader, light ); - - if ( numLitTriangles ) - { - BoundsAdd( bounds[ 0 ], bounds[ 1 ], srf->bounds[ 0 ], srf->bounds[ 1 ] ); - } - - numTriangles += numLitTriangles; - } - - if ( srf->numVerts ) - { - numVerts += srf->numVerts; - } - } - } - - if ( !numVerts || !numTriangles ) - { - continue; - } - - // create surface - vboSurf = (srfVBOMesh_t*) ri.Hunk_Alloc( sizeof( *vboSurf ), ha_pref::h_low ); - vboSurf->surfaceType = surfaceType_t::SF_VBO_MESH; - vboSurf->numIndexes = numTriangles * 3; - vboSurf->numVerts = numVerts; - vboSurf->lightmapNum = -1; - - VectorCopy( bounds[ 0 ], vboSurf->bounds[ 0 ] ); - VectorCopy( bounds[ 1 ], vboSurf->bounds[ 1 ] ); - - // create arrays - indexes = (glIndex_t*) ri.Hunk_AllocateTempMemory( 3 * numTriangles * sizeof( glIndex_t ) ); - numTriangles = 0; - - // build triangle indices - for ( l = k; l < numCaches; l++ ) - { - iaCache2 = iaCachesSorted[ l ]; - - surface = iaCache2->surface; - - if ( alphaTest ) - { - if ( surface->shader != shader ) - { - break; - } - } - else - { - if ( surface->shader->alphaTest != alphaTest ) - { - break; - } - } - - if ( *surface->data == surfaceType_t::SF_FACE ) - { - srfSurfaceFace_t *srf = ( srfSurfaceFace_t * ) surface->data; - - for ( i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++ ) - { - if ( tri->facingLight ) - { - for ( j = 0; j < 3; j++ ) - { - indexes[ 3 * numTriangles + j ] = tri->indexes[ j ]; - } - - numTriangles++; - } - } - } - else if ( *surface->data == surfaceType_t::SF_GRID ) - { - srfGridMesh_t *srf = ( srfGridMesh_t * ) surface->data; - - for ( i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++ ) - { - if ( tri->facingLight ) - { - for ( j = 0; j < 3; j++ ) - { - indexes[ 3 * numTriangles + j ] = tri->indexes[ j ]; - } - - numTriangles++; - } - } - } - else if ( *surface->data == surfaceType_t::SF_TRIANGLES ) - { - srfTriangles_t *srf = ( srfTriangles_t * ) surface->data; - - for ( i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++ ) - { - if ( tri->facingLight ) - { - for ( j = 0; j < 3; j++ ) - { - indexes[ 3 * numTriangles + j ] = tri->indexes[ j ]; - } - - numTriangles++; - } - } - } - } - - vboSurf->vbo = s_worldData.vbo; - vboSurf->ibo = R_CreateStaticIBO( va( "staticShadowMesh_IBO %i", c_vboLightSurfaces ), indexes, 3 * numTriangles ); - - ri.Hunk_FreeTempMemory( indexes ); - - // add everything needed to the light - iaVBO = R_CreateInteractionVBO( light ); - iaVBO->shader = shader; - iaVBO->vboShadowMesh = vboSurf; - - c_vboShadowSurfaces++; - } - } - - ri.Hunk_FreeTempMemory( iaCachesSorted ); -} - -/* -=============== -R_CreateVBOShadowCubeMeshes -=============== -*/ -static void R_CreateVBOShadowCubeMeshes( trRefLight_t *light ) -{ - int i, j, k, l; - - int numVerts; - - int numTriangles; - glIndex_t *indexes; - srfTriangle_t *tri; - - interactionVBO_t *iaVBO; - - interactionCache_t *iaCache, *iaCache2; - interactionCache_t **iaCachesSorted; - int numCaches; - - shader_t *shader, *oldShader; - bool alphaTest, oldAlphaTest; - int cubeSide; - - bspSurface_t *surface; - - srfVBOMesh_t *vboSurf; - - if ( !r_vboShadows->integer ) - { - return; - } - - if ( !glConfig2.shadowMapping ) - { - return; - } - - if ( !light->firstInteractionCache ) - { - // this light has no interactions precached - return; - } - - if ( light->l.noShadows ) - { - return; - } - - if ( light->l.rlType != refLightType_t::RL_OMNI ) - { - return; - } - - // count number of interaction caches - numCaches = 0; - - for ( iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next ) - { - if ( iaCache->redundant ) - { - continue; - } - - surface = iaCache->surface; - - if ( !surface->shader->interactLight ) - { - continue; - } - - if ( surface->shader->isSky ) - { - continue; - } - - if ( surface->shader->noShadows ) - { - continue; - } - - if ( surface->shader->sort > Util::ordinal(shaderSort_t::SS_OPAQUE)) - { - continue; - } - - if ( surface->shader->isPortal ) - { - continue; - } - - numCaches++; - } - - // build interaction caches list - iaCachesSorted = (interactionCache_t**) ri.Hunk_AllocateTempMemory( numCaches * sizeof( iaCachesSorted[ 0 ] ) ); - - numCaches = 0; - - for ( iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next ) - { - if ( iaCache->redundant ) - { - continue; - } - - surface = iaCache->surface; - - if ( !surface->shader->interactLight ) - { - continue; - } - - if ( surface->shader->isSky ) - { - continue; - } - - if ( surface->shader->noShadows ) - { - continue; - } - - if ( surface->shader->sort > Util::ordinal(shaderSort_t::SS_OPAQUE) ) - { - continue; - } - - if ( surface->shader->isPortal ) - { - continue; - } - - iaCachesSorted[ numCaches ] = iaCache; - numCaches++; - } - - // sort interaction caches by shader - qsort( iaCachesSorted, numCaches, sizeof( *iaCachesSorted ), InteractionCacheCompare ); - - // create a VBO for each shader - for ( cubeSide = 0; cubeSide < 6; cubeSide++ ) - { - shader = oldShader = nullptr; - oldAlphaTest = alphaTest = true; - - for ( k = 0; k < numCaches; k++ ) - { - iaCache = iaCachesSorted[ k ]; - shader = iaCache->surface->shader; - alphaTest = shader->alphaTest; - - iaCache->mergedIntoVBO = true; - - if ( alphaTest ? shader != oldShader : alphaTest != oldAlphaTest ) - { - oldShader = shader; - oldAlphaTest = alphaTest; - - // count vertices and indices - numVerts = 0; - numTriangles = 0; - - for ( l = k; l < numCaches; l++ ) - { - iaCache2 = iaCachesSorted[ l ]; - - surface = iaCache2->surface; - - if ( alphaTest ) - { - if ( surface->shader != shader ) - { - break; - } - } - else - { - if ( surface->shader->alphaTest != alphaTest ) - { - break; - } - } - - if ( !( iaCache2->cubeSideBits & ( 1 << cubeSide ) ) ) - { - continue; - } - - if ( *surface->data == surfaceType_t::SF_FACE ) - { - srfSurfaceFace_t *srf = ( srfSurfaceFace_t * ) surface->data; - - if ( srf->numTriangles ) - { - numTriangles += - UpdateLightTriangles( s_worldData.verts, srf->numTriangles, - s_worldData.triangles + srf->firstTriangle, surface->shader, light ); - } - - if ( srf->numVerts ) - { - numVerts += srf->numVerts; - } - } - else if ( *surface->data == surfaceType_t::SF_GRID ) - { - srfGridMesh_t *srf = ( srfGridMesh_t * ) surface->data; - - if ( srf->numTriangles ) - { - numTriangles += - UpdateLightTriangles( s_worldData.verts, srf->numTriangles, - s_worldData.triangles + srf->firstTriangle, surface->shader, light ); - } - - if ( srf->numVerts ) - { - numVerts += srf->numVerts; - } - } - else if ( *surface->data == surfaceType_t::SF_TRIANGLES ) - { - srfTriangles_t *srf = ( srfTriangles_t * ) surface->data; - - if ( srf->numTriangles ) - { - numTriangles += - UpdateLightTriangles( s_worldData.verts, srf->numTriangles, - s_worldData.triangles + srf->firstTriangle, surface->shader, light ); - } - - if ( srf->numVerts ) - { - numVerts += srf->numVerts; - } - } - } - - if ( !numVerts || !numTriangles ) - { - continue; - } - - // create surface - vboSurf = (srfVBOMesh_t*) ri.Hunk_Alloc( sizeof( *vboSurf ), ha_pref::h_low ); - vboSurf->surfaceType = surfaceType_t::SF_VBO_MESH; - vboSurf->numIndexes = numTriangles * 3; - vboSurf->numVerts = numVerts; - vboSurf->lightmapNum = -1; - ZeroBounds( vboSurf->bounds[ 0 ], vboSurf->bounds[ 1 ] ); - - // create arrays - indexes = (glIndex_t*) ri.Hunk_AllocateTempMemory( 3 * numTriangles * sizeof( glIndex_t ) ); - numTriangles = 0; - - // build triangle indices - for ( l = k; l < numCaches; l++ ) - { - iaCache2 = iaCachesSorted[ l ]; - - surface = iaCache2->surface; - - if ( alphaTest ) - { - if ( surface->shader != shader ) - { - break; - } - } - else - { - if ( surface->shader->alphaTest != alphaTest ) - { - break; - } - } - - if ( !( iaCache2->cubeSideBits & ( 1 << cubeSide ) ) ) - { - continue; - } - - if ( *surface->data == surfaceType_t::SF_FACE ) - { - srfSurfaceFace_t *srf = ( srfSurfaceFace_t * ) surface->data; - - for ( i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++ ) - { - if ( tri->facingLight ) - { - for ( j = 0; j < 3; j++ ) - { - indexes[ 3 * numTriangles + j ] = tri->indexes[ j ]; - } - - numTriangles++; - } - } - } - else if ( *surface->data == surfaceType_t::SF_GRID ) - { - srfGridMesh_t *srf = ( srfGridMesh_t * ) surface->data; - - for ( i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++ ) - { - if ( tri->facingLight ) - { - for ( j = 0; j < 3; j++ ) - { - indexes[ 3 * numTriangles + j ] = tri->indexes[ j ]; - } - - numTriangles++; - } - } - } - else if ( *surface->data == surfaceType_t::SF_TRIANGLES ) - { - srfTriangles_t *srf = ( srfTriangles_t * ) surface->data; - - for ( i = 0, tri = s_worldData.triangles + srf->firstTriangle; i < srf->numTriangles; i++, tri++ ) - { - if ( tri->facingLight ) - { - for ( j = 0; j < 3; j++ ) - { - indexes[ 3 * numTriangles + j ] = tri->indexes[ j ]; - } - - numTriangles++; - } - } - } - } - - vboSurf->vbo = s_worldData.vbo; - vboSurf->ibo = R_CreateStaticIBO( va( "staticShadowPyramidMesh_IBO %i", c_vboShadowSurfaces ), indexes, numTriangles ); - - ri.Hunk_FreeTempMemory( indexes ); - - // add everything needed to the light - iaVBO = R_CreateInteractionVBO( light ); - iaVBO->cubeSideBits = ( 1 << cubeSide ); - iaVBO->shader = shader; - iaVBO->vboShadowMesh = vboSurf; - - c_vboShadowSurfaces++; - } - } - } - - ri.Hunk_FreeTempMemory( iaCachesSorted ); -} - -static void R_CalcInteractionCubeSideBits( trRefLight_t *light ) -{ - interactionCache_t *iaCache; - bspSurface_t *surface; - vec3_t localBounds[ 2 ]; - - if ( !glConfig2.shadowMapping ) - { - return; - } - - if ( !light->firstInteractionCache ) - { - // this light has no interactions precached - return; - } - - if ( light->l.noShadows ) - { - // actually noShadows lights are quite bad concerning this optimization - return; - } - - if ( light->l.rlType != refLightType_t::RL_OMNI ) - { - return; - } - - { - for ( iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next ) - { - surface = iaCache->surface; - - if ( *surface->data == surfaceType_t::SF_FACE || *surface->data == surfaceType_t::SF_GRID || *surface->data == surfaceType_t::SF_TRIANGLES ) - { - srfGeneric_t *gen; - - gen = ( srfGeneric_t * ) surface->data; - - VectorCopy( gen->bounds[ 0 ], localBounds[ 0 ] ); - VectorCopy( gen->bounds[ 1 ], localBounds[ 1 ] ); - } - else - { - iaCache->cubeSideBits = CUBESIDE_CLIPALL; - continue; - } - - light->shadowLOD = 0; // important for R_CalcLightCubeSideBits - iaCache->cubeSideBits = R_CalcLightCubeSideBits( light, localBounds ); - } - } -} - -/* -============= -R_PrecacheInteractions -============= -*/ -void R_PrecacheInteractions() -{ - int i; - trRefLight_t *light; - bspSurface_t *surface; - int startTime, endTime; - - startTime = ri.Milliseconds(); - - // reset surfaces' viewCount - s_lightCount = 0; - - for ( i = 0, surface = s_worldData.surfaces; i < s_worldData.numSurfaces; i++, surface++ ) - { - surface->lightCount = -1; - } - - c_redundantInteractions = 0; - c_vboWorldSurfaces = 0; - c_vboLightSurfaces = 0; - c_vboShadowSurfaces = 0; - - Log::Debug("...precaching %i lights", s_worldData.numLights ); - - for ( i = 0; i < s_worldData.numLights; i++ ) - { - light = &s_worldData.lights[ i ]; - - if ( tr.worldLightMapping && !light->noRadiosity ) - { - continue; - } - - // set up light transform matrix - MatrixSetupTransformFromQuat( light->transformMatrix, light->l.rotation, light->l.origin ); - - // set up light origin for lighting and shadowing - R_SetupLightOrigin( light ); - - // set up model to light view matrix - R_SetupLightView( light ); - - // set up projection - R_SetupLightProjection( light ); - - // calc local bounds for culling - R_SetupLightLocalBounds( light ); - - // setup world bounds for intersection tests - R_SetupLightWorldBounds( light ); - - // setup frustum planes for intersection tests - R_SetupLightFrustum( light ); - - // setup interactions - light->firstInteractionCache = nullptr; - light->lastInteractionCache = nullptr; - - light->firstInteractionVBO = nullptr; - light->lastInteractionVBO = nullptr; - - // perform culling and add all the potentially visible surfaces - s_lightCount++; - QueueInit( &light->leafs ); - R_RecursivePrecacheInteractionNode( s_worldData.nodes, light ); - - // create a static VBO surface for each light geometry batch - R_CreateVBOLightMeshes( light ); - - // create a static VBO surface for each shadow geometry batch - R_CreateVBOShadowMeshes( light ); - - // calculate pyramid bits for each interaction in omni-directional lights - R_CalcInteractionCubeSideBits( light ); - - // create a static VBO surface for each light geometry batch inside a cubemap pyramid - R_CreateVBOShadowCubeMeshes( light ); - } - - // move interactions grow list to hunk - s_worldData.numInteractions = s_interactions.size(); - s_worldData.interactions = (interactionCache_t**) ri.Hunk_Alloc( s_worldData.numInteractions * sizeof( *s_worldData.interactions ), ha_pref::h_low ); - - for ( i = 0; i < s_worldData.numInteractions; i++ ) - { - s_worldData.interactions[ i ] = s_interactions[ i ]; - } - - s_interactions.clear(); - - Log::Debug("%i interactions precached", s_worldData.numInteractions ); - Log::Debug("%i interactions were hidden in shadows", c_redundantInteractions ); - - if ( glConfig2.shadowMapping ) - { - // only interesting for omni-directional shadow mapping - Log::Debug("%i omni pyramid tests", tr.pc.c_pyramidTests ); - Log::Debug("%i omni pyramid surfaces visible", tr.pc.c_pyramid_cull_ent_in ); - Log::Debug("%i omni pyramid surfaces clipped", tr.pc.c_pyramid_cull_ent_clip ); - Log::Debug("%i omni pyramid surfaces culled", tr.pc.c_pyramid_cull_ent_out ); - } - - endTime = ri.Milliseconds(); - - Log::Debug("lights precaching time = %5.2f seconds", ( endTime - startTime ) / 1000.0 ); -} - -static const int HASHTABLE_SIZE = 7919; // 32749 // 2039 /* prime, use % */ -#define HASH_USE_EPSILON - -#ifdef HASH_USE_EPSILON -#define HASH_XYZ_EPSILON 256.0f -#define HASH_XYZ_EPSILONSPACE_MULTIPLIER 1.f / HASH_XYZ_EPSILON -#endif - -unsigned int VertexCoordGenerateHash( const vec3_t xyz ) -{ - unsigned int hash = 0; - -#ifndef HASH_USE_EPSILON - hash += ~( * ( ( unsigned int * ) &xyz[ 0 ] ) << 15 ); - hash ^= ( * ( ( unsigned int * ) &xyz[ 0 ] ) >> 10 ); - hash += ( * ( ( unsigned int * ) &xyz[ 1 ] ) << 3 ); - hash ^= ( * ( ( unsigned int * ) &xyz[ 1 ] ) >> 6 ); - hash += ~( * ( ( unsigned int * ) &xyz[ 2 ] ) << 11 ); - hash ^= ( * ( ( unsigned int * ) &xyz[ 2 ] ) >> 16 ); -#else - vec3_t xyz_epsilonspace; - - VectorScale( xyz, HASH_XYZ_EPSILONSPACE_MULTIPLIER, xyz_epsilonspace ); - xyz_epsilonspace[ 0 ] = floor( xyz_epsilonspace[ 0 ] ); - xyz_epsilonspace[ 1 ] = floor( xyz_epsilonspace[ 1 ] ); - xyz_epsilonspace[ 2 ] = floor( xyz_epsilonspace[ 2 ] ); - - hash += ~( * ( ( unsigned int * ) &xyz_epsilonspace[ 0 ] ) << 15 ); - hash ^= ( * ( ( unsigned int * ) &xyz_epsilonspace[ 0 ] ) >> 10 ); - hash += ( * ( ( unsigned int * ) &xyz_epsilonspace[ 1 ] ) << 3 ); - hash ^= ( * ( ( unsigned int * ) &xyz_epsilonspace[ 1 ] ) >> 6 ); - hash += ~( * ( ( unsigned int * ) &xyz_epsilonspace[ 2 ] ) << 11 ); - hash ^= ( * ( ( unsigned int * ) &xyz_epsilonspace[ 2 ] ) >> 16 ); - -#endif - - hash = hash % ( HASHTABLE_SIZE ); - return hash; -} - -vertexHash_t **NewVertexHashTable() -{ - vertexHash_t **hashTable = (vertexHash_t**) Z_Calloc( HASHTABLE_SIZE * sizeof( vertexHash_t * ) ); - return hashTable; -} - -void FreeVertexHashTable( vertexHash_t **hashTable ) -{ - int i; - vertexHash_t *vertexHash; - vertexHash_t *nextVertexHash; - - if ( hashTable == nullptr ) - { - return; - } - - for ( i = 0; i < HASHTABLE_SIZE; i++ ) - { - if ( hashTable[ i ] ) - { - nextVertexHash = nullptr; - - for ( vertexHash = hashTable[ i ]; vertexHash; vertexHash = nextVertexHash ) - { - nextVertexHash = vertexHash->next; - - Z_Free( vertexHash ); - } - } - } - - Z_Free( hashTable ); -} - -vertexHash_t *FindVertexInHashTable( vertexHash_t **hashTable, const vec3_t xyz, float distance ) -{ - unsigned int hash; - vertexHash_t *vertexHash; - - if ( hashTable == nullptr || xyz == nullptr ) - { - return nullptr; - } - - hash = VertexCoordGenerateHash( xyz ); - - for ( vertexHash = hashTable[ hash ]; vertexHash; vertexHash = vertexHash->next ) - { -#ifndef HASH_USE_EPSILON - - if ( ( vertexHash->vcd.xyz[ 0 ] != xyz[ 0 ] || vertexHash->vcd.xyz[ 1 ] != xyz[ 1 ] || - vertexHash->vcd.xyz[ 2 ] != xyz[ 2 ] ) ) - { - continue; - } - -#elif 1 - - if ( Distance( xyz, vertexHash->xyz ) > distance ) - { - continue; - } - -#else - - if ( ( fabsf( xyz[ 0 ] - vertexHash->vcd.xyz[ 0 ] ) ) > HASH_XYZ_EPSILON || - ( fabsf( xyz[ 1 ] - vertexHash->vcd.xyz[ 1 ] ) ) > HASH_XYZ_EPSILON || - ( fabsf( xyz[ 2 ] - vertexHash->vcd.xyz[ 2 ] ) ) > HASH_XYZ_EPSILON ) - { - continue; - } - -#endif - return vertexHash; - } - - return nullptr; -} - -vertexHash_t *AddVertexToHashTable( vertexHash_t **hashTable, vec3_t xyz, void *data ) -{ - unsigned int hash; - vertexHash_t *vertexHash; - - if ( hashTable == nullptr || xyz == nullptr ) - { - return nullptr; - } - - vertexHash = (vertexHash_t*) Z_AllocUninit( sizeof( vertexHash_t ) ); - - hash = VertexCoordGenerateHash( xyz ); - - VectorCopy( xyz, vertexHash->xyz ); - vertexHash->data = data; - - // link into table - vertexHash->next = hashTable[ hash ]; - hashTable[ hash ] = vertexHash; - - return vertexHash; -} - -void GL_BindNearestCubeMap( int unit, const vec3_t xyz ) -{ - float distance, maxDistance; - cubemapProbe_t *cubeProbe; - unsigned int hash; - vertexHash_t *vertexHash; - - if ( !r_reflectionMapping->integer ) - { - return; - } - - if ( tr.cubeHashTable == nullptr || xyz == nullptr ) - { - return; - } - - maxDistance = 9999999.0f; - - hash = VertexCoordGenerateHash( xyz ); - image_t *autoCubeImage = tr.whiteCubeImage; - - for ( vertexHash = tr.cubeHashTable[ hash ]; vertexHash; vertexHash = vertexHash->next ) - { - cubeProbe = (cubemapProbe_t*) vertexHash->data; - - distance = Distance( cubeProbe->origin, xyz ); - - if ( distance < maxDistance ) - { - autoCubeImage = cubeProbe->cubemap; - maxDistance = distance; - } - } - - GL_BindToTMU( unit, autoCubeImage ); + GL_BindToTMU( unit, autoCubeImage ); } void R_FindTwoNearestCubeMaps( const vec3_t position, cubemapProbe_t **cubeProbeNearest, cubemapProbe_t **cubeProbeSecondNearest ) @@ -6931,10 +5115,6 @@ void RE_LoadWorldMap( const char *name ) R_CreateWorldVBO(); R_CreateClusters(); - // we precache interactions between lights and surfaces - // to reduce the polygon count - R_PrecacheInteractions(); - if ( tr.hasSkybox ) { FinishSkybox(); } diff --git a/src/engine/renderer/tr_cmds.cpp b/src/engine/renderer/tr_cmds.cpp index 2a83149cfe..86fee74dfd 100644 --- a/src/engine/renderer/tr_cmds.cpp +++ b/src/engine/renderer/tr_cmds.cpp @@ -47,10 +47,10 @@ void R_PerformanceCounters() backEnd.pc.c_vertexes, backEnd.pc.c_indexes / 3 ); Log::Notice("%i lights %i bout %i pvsout %i interactions", - tr.pc.c_dlights + tr.pc.c_slights, + tr.pc.c_dlights, tr.pc.c_box_cull_light_out, tr.pc.c_pvs_cull_light_out, - tr.pc.c_dlightInteractions + tr.pc.c_slightInteractions ); + tr.pc.c_dlightInteractions ); Log::Notice("%i draws %i vbos %i ibos %i verts %i tris", backEnd.pc.c_drawElements, @@ -84,8 +84,6 @@ void R_PerformanceCounters() Log::Notice("dlight srf:%i culled:%i", tr.pc.c_dlightSurfaces, tr.pc.c_dlightSurfacesCulled ); Log::Notice("dlights:%i interactions:%i", tr.pc.c_dlights, tr.pc.c_dlightInteractions ); - - Log::Notice("slights:%i interactions:%i", tr.pc.c_slights, tr.pc.c_slightInteractions ); } else if ( r_speeds->integer == Util::ordinal(renderSpeeds_t::RSPEEDS_SHADOWCUBE_CULLING )) { @@ -252,6 +250,12 @@ R_AddSetupLightsCmd */ void R_AddSetupLightsCmd() { + if ( !glConfig2.realtimeLighting || + r_realtimeLightingRenderer.Get() != Util::ordinal( realtimeLightingRenderer_t::TILED ) ) + { + return; + } + SetupLightsCommand *cmd; cmd = R_GetRenderCommand(); diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index 84da539589..6dbb0ed8b0 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -80,8 +80,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Util::ordinal(realtimeLightingRenderer_t::LEGACY), Util::ordinal(realtimeLightingRenderer_t::TILED) ); Cvar::Cvar r_realtimeLighting( "r_realtimeLighting", "enable realtime light rendering", Cvar::NONE, true ); - Cvar::Cvar r_dynamicLight( "r_dynamicLight", "enable dynamic lights (if realtime lighting is enabled)", Cvar::NONE, true ); - Cvar::Cvar r_staticLight( "r_staticLight", "enable BSP entity lights (if realtime lighting is enabled)", Cvar::NONE, true ); cvar_t *r_realtimeLightingCastShadows; cvar_t *r_precomputedLighting; Cvar::Cvar r_mapOverBrightBits("r_mapOverBrightBits", "default map light color shift", Cvar::NONE, 2); @@ -249,8 +247,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *r_vboFaces; cvar_t *r_vboCurves; cvar_t *r_vboTriangles; - cvar_t *r_vboShadows; - cvar_t *r_vboLighting; cvar_t *r_vboModels; cvar_t *r_vboVertexSkinning; @@ -933,11 +929,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p Log::Notice( "GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB: %d", glConfig2.maxTexIndirections ); } - if ( glConfig2.occlusionQueryAvailable ) - { - Log::Notice("Occlusion query bits: %d", glConfig2.occlusionQueryBits ); - } - if ( glConfig2.drawBuffersAvailable ) { Log::Notice("GL_MAX_DRAW_BUFFERS: %d", glConfig2.maxDrawBuffers ); @@ -1187,8 +1178,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p r_vboFaces = Cvar_Get( "r_vboFaces", "1", CVAR_CHEAT ); r_vboCurves = Cvar_Get( "r_vboCurves", "1", CVAR_CHEAT ); r_vboTriangles = Cvar_Get( "r_vboTriangles", "1", CVAR_CHEAT ); - r_vboShadows = Cvar_Get( "r_vboShadows", "1", CVAR_CHEAT ); - r_vboLighting = Cvar_Get( "r_vboLighting", "1", CVAR_CHEAT ); r_vboModels = Cvar_Get( "r_vboModels", "1", CVAR_LATCH ); r_vboVertexSkinning = Cvar_Get( "r_vboVertexSkinning", "1", CVAR_LATCH ); @@ -1218,8 +1207,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p Cvar::Latch( r_realtimeLightingRenderer ); Cvar::Latch( r_realtimeLighting ); - Cvar::Latch( r_dynamicLight ); - Cvar::Latch( r_staticLight ); Cvar::Latch( r_materialSystem ); r_drawworld = Cvar_Get( "r_drawworld", "1", CVAR_CHEAT ); @@ -1670,8 +1657,6 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p // XreaL BEGIN re.TakeVideoFrame = RE_TakeVideoFrame; - re.AddRefLightToScene = RE_AddRefLightToScene; - re.RegisterAnimation = RE_RegisterAnimation; re.CheckSkeleton = RE_CheckSkeleton; re.BuildSkeleton = RE_BuildSkeleton; diff --git a/src/engine/renderer/tr_light.cpp b/src/engine/renderer/tr_light.cpp index cbc60a7a37..c134b3ea5f 100644 --- a/src/engine/renderer/tr_light.cpp +++ b/src/engine/renderer/tr_light.cpp @@ -684,36 +684,6 @@ void R_SetupLightFrustum( trRefLight_t *light ) default: break; } - - if ( light->isStatic ) - { - R_SyncRenderThread(); - - Tess_MapVBOs(true); - Tess_Begin( Tess_StageIteratorDummy, nullptr, nullptr, true, -1, 0 ); - - R_TessLight( light ); - - vboData_t data{}; - data.xyz = ( vec3_t * ) ri.Hunk_AllocateTempMemory( tess.numVertexes * sizeof( *data.xyz ) ); - - for (unsigned i = 0; i < tess.numVertexes; i++ ) - { - // transform to world space - MatrixTransformPoint( light->transformMatrix, tess.verts[ i ].xyz, data.xyz[ i ] ); - } - data.numVerts = tess.numVertexes; - - light->frustumVBO = R_CreateStaticVBO( "staticLightFrustum_VBO", data, vboLayout_t::VBO_LAYOUT_POSITION ); - light->frustumIBO = R_CreateStaticIBO( "staticLightFrustum_IBO", tess.indexes, tess.numIndexes ); - - ri.Hunk_FreeTempMemory( data.xyz ); - - light->frustumVerts = tess.numVertexes; - light->frustumIndexes = tess.numIndexes; - - Tess_Clear(); - } } /* @@ -966,14 +936,7 @@ bool R_AddLightInteraction( trRefLight_t *light, surfaceType_t *surface, shader_ ia->scissorWidth = light->scissor.coords[ 2 ] - light->scissor.coords[ 0 ]; ia->scissorHeight = light->scissor.coords[ 3 ] - light->scissor.coords[ 1 ]; - if ( light->isStatic ) - { - tr.pc.c_slightInteractions++; - } - else - { - tr.pc.c_dlightInteractions++; - } + tr.pc.c_dlightInteractions++; return true; } @@ -1567,33 +1530,16 @@ void R_SetupLightShader( trRefLight_t *light ) { if ( !light->l.attenuationShader ) { - if ( light->isStatic ) + switch ( light->l.rlType ) { - switch ( light->l.rlType ) - { - default: - case refLightType_t::RL_OMNI: - light->shader = tr.defaultPointLightShader; - break; - - case refLightType_t::RL_PROJ: - light->shader = tr.defaultProjectedLightShader; - break; - } - } - else - { - switch ( light->l.rlType ) - { - default: - case refLightType_t::RL_OMNI: - light->shader = tr.defaultDynamicLightShader; - break; + default: + case refLightType_t::RL_OMNI: + light->shader = tr.defaultDynamicLightShader; + break; - case refLightType_t::RL_PROJ: - light->shader = tr.defaultProjectedLightShader; - break; - } + case refLightType_t::RL_PROJ: + light->shader = tr.defaultProjectedLightShader; + break; } } else @@ -1618,65 +1564,6 @@ void R_ComputeFinalAttenuation( shaderStage_t *pStage, trRefLight_t *light ) MatrixMultiply( matrix, light->attenuationMatrix, light->attenuationMatrix2 ); } -/* -================= -R_CullLightPoint - -Returns CULL_IN, CULL_CLIP, or CULL_OUT -================= -*/ -cullResult_t R_CullLightPoint( trRefLight_t *light, const vec3_t p ) -{ - int i; - cplane_t *frust; - float dist; - - // check against frustum planes - for ( i = 0; i < 6; i++ ) - { - frust = &light->frustum[ i ]; - - dist = DotProduct( p, frust->normal ) - frust->dist; - - if ( dist < 0 ) - { - // completely outside frustum - return cullResult_t::CULL_OUT; - } - } - - // completely inside frustum - return cullResult_t::CULL_IN; -} - -/* -================= -R_CullLightTriangle - -Returns CULL_IN, CULL_CLIP, or CULL_OUT -================= -*/ -cullResult_t R_CullLightTriangle( trRefLight_t *light, vec3_t verts[ 3 ] ) -{ - int i; - vec3_t worldBounds[ 2 ]; - - if ( r_nocull->integer ) - { - return cullResult_t::CULL_CLIP; - } - - // calc AABB of the triangle - ClearBounds( worldBounds[ 0 ], worldBounds[ 1 ] ); - - for ( i = 0; i < 3; i++ ) - { - AddPointToBounds( verts[ i ], worldBounds[ 0 ], worldBounds[ 1 ] ); - } - - return R_CullLightWorldBounds( light, worldBounds ); -} - /* ================= R_CullLightTriangle diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index ebba4b5c56..efb0ac4753 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -370,43 +370,13 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED }; CUBESIDE_CLIPALL = 1 | 2 | 4 | 8 | 16 | 32 }; - struct link_t - { - void *data; - link_t *prev, *next; - }; - - inline void InitLink( link_t *l, void *data ) - { - l->data = data; - l->prev = l->next = l; - } - - inline void InsertLink( link_t *l, link_t *sentinel ) - { - l->next = sentinel->next; - l->prev = sentinel; - - l->next->prev = l; - l->prev->next = l; - } - - inline void QueueInit( link_t *l ) - { - l->data = nullptr; - l->prev = l->next = l; - } - // a trRefLight_t has all the information passed in by // the client game, as well as some locally derived info struct trRefLight_t { - // public from client game refLight_t l; // local - bool isStatic; // loaded from the BSP entities lump - bool noRadiosity; // this is a pure realtime light that was not considered by XMap2 bool additive; // texture detail is lost tho when the lightmap is dark vec3_t origin; // l.origin + rotated l.center vec3_t transformed; // origin in local coordinate system @@ -423,7 +393,6 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED }; matrix_t attenuationMatrix; // attenuation * (light view * entity transform) matrix_t attenuationMatrix2; // attenuation * tcMod matrices - cullResult_t cull; vec3_t localBounds[ 2 ]; vec3_t worldBounds[ 2 ]; float sphereRadius; // calculated from localBounds @@ -435,25 +404,11 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED }; frustum_t frustum; plane_t localFrustum[ 6 ]; - struct VBO_t *frustumVBO; - - struct IBO_t *frustumIBO; - - uint16_t frustumIndexes; - uint16_t frustumVerts; screenRect_t scissor; struct shader_t *shader; - struct interactionCache_t *firstInteractionCache; // only used by static lights - - struct interactionCache_t *lastInteractionCache; // only used by static lights - - struct interactionVBO_t *firstInteractionVBO; // only used by static lights - - struct interactionVBO_t *lastInteractionVBO; // only used by static lights - struct interaction_t *firstInteraction; struct interaction_t *lastInteraction; @@ -463,8 +418,6 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED }; uint16_t numLightOnlyInteractions; bool noSort; // don't sort interactions by material - link_t leafs; - int visCounts[ MAX_VISCOUNTS ]; // node needs to be traversed if current }; @@ -1686,35 +1639,6 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED }; IA_DEFAULTCLIP = IA_LIGHT | IA_SHADOWCLIP }; -// an interactionCache is a node between a light and a precached world surface - struct interactionCache_t - { - interactionType_t type; - - struct bspSurface_t *surface; - - byte cubeSideBits; - bool redundant; - bool mergedIntoVBO; - - interactionCache_t *next; - }; - - struct interactionVBO_t - { - interactionType_t type; - - byte cubeSideBits; - - struct shader_t *shader; - - struct srfVBOMesh_t *vboLightMesh; - - struct srfVBOMesh_t *vboShadowMesh; - - interactionVBO_t *next; - }; - // an interaction is a node between a light and any surface struct interaction_t { @@ -1771,7 +1695,6 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED }; struct srfTriangle_t { int indexes[ 3 ]; - bool facingLight; }; // ydnar: plain map drawsurfaces must match this header @@ -2041,12 +1964,6 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED }; bspGridPoint2_t *lightGridData2; int numLightGridPoints; - int numLights; - trRefLight_t *lights; - - int numInteractions; - interactionCache_t **interactions; - int numClusters; int clusterBytes; @@ -2411,10 +2328,6 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED }; int c_nodes; int c_leafs; - int c_slights; - int c_slightSurfaces; - int c_slightInteractions; - int c_dlights; int c_dlightSurfaces; int c_dlightSurfacesCulled; @@ -2823,8 +2736,6 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED }; extern Cvar::Cvar r_fastsky; // Controls whether sky should be cleared or drawn. extern Cvar::Range> r_realtimeLightingRenderer; extern Cvar::Cvar r_realtimeLighting; - extern Cvar::Cvar r_dynamicLight; - extern Cvar::Cvar r_staticLight; extern cvar_t *r_realtimeLightingCastShadows; extern cvar_t *r_precomputedLighting; extern Cvar::Cvar r_mapOverBrightBits; @@ -2975,8 +2886,6 @@ enum class realtimeLightingRenderer_t { LEGACY, TILED }; extern cvar_t *r_vboFaces; extern cvar_t *r_vboCurves; extern cvar_t *r_vboTriangles; - extern cvar_t *r_vboShadows; - extern cvar_t *r_vboLighting; extern cvar_t *r_vboModels; extern cvar_t *r_vboVertexSkinning; @@ -3464,7 +3373,6 @@ inline bool checkGLErrors() bool R_inPVVS( const vec3_t p1, const vec3_t p2 ); void R_AddWorldInteractions( trRefLight_t *light ); - void R_AddPrecachedWorldInteractions( trRefLight_t *light ); /* ============================================================ @@ -3514,9 +3422,6 @@ inline bool checkGLErrors() byte R_CalcLightCubeSideBits( trRefLight_t *light, vec3_t worldBounds[ 2 ] ); - cullResult_t R_CullLightPoint( trRefLight_t *light, const vec3_t p ); - - cullResult_t R_CullLightTriangle( trRefLight_t *light, vec3_t verts[ 3 ] ); cullResult_t R_CullLightWorldBounds( trRefLight_t *light, vec3_t worldBounds[ 2 ] ); void R_ComputeFinalAttenuation( shaderStage_t *pStage, trRefLight_t *light ); @@ -3617,7 +3522,6 @@ inline bool checkGLErrors() void RE_ClearScene(); void RE_AddRefEntityToScene( const refEntity_t *ent ); - void RE_AddRefLightToScene( const refLight_t *light ); void RE_AddPolyToSceneQ3A( qhandle_t hShader, int numVerts, const polyVert_t *verts, int num ); void RE_AddPolyToSceneET( qhandle_t hShader, int numVerts, const polyVert_t *verts ); diff --git a/src/engine/renderer/tr_main.cpp b/src/engine/renderer/tr_main.cpp index 83fdd30a6e..97f23bb14b 100644 --- a/src/engine/renderer/tr_main.cpp +++ b/src/engine/renderer/tr_main.cpp @@ -2299,8 +2299,6 @@ void R_AddLightInteractions() { int i; trRefLight_t *light; - bspNode_t *leaf; - link_t *l; realtimeLightingRenderer_t realtimeLightingRenderer = realtimeLightingRenderer_t( r_realtimeLightingRenderer.Get() ); @@ -2310,48 +2308,13 @@ void R_AddLightInteractions() { light = tr.currentLight = &tr.refdef.lights[ i ]; - if ( light->isStatic ) + if ( !light->l.inverseShadows ) { - if ( !glConfig2.staticLight ) - { - continue; - } - - if ( ( r_precomputedLighting->integer || tr.worldLight != lightMode_t::MAP ) && !light->noRadiosity ) - { - continue; - } - if ( realtimeLightingRenderer == realtimeLightingRenderer_t::TILED ) - { - tr.refdef.numShaderLights++; - tr.pc.c_slights++; - } - - light->cull = cullResult_t::CULL_OUT; - continue; - } - else if ( light->l.inverseShadows ) - { - if ( !glConfig2.dynamicLight ) - { - light->cull = CULL_OUT; - continue; - } - } - else - { - if ( !glConfig2.dynamicLight ) - { - light->cull = cullResult_t::CULL_OUT; - continue; - } - else if ( realtimeLightingRenderer == realtimeLightingRenderer_t::TILED ) { tr.refdef.numShaderLights++; tr.pc.c_dlights++; - light->cull = cullResult_t::CULL_OUT; continue; } } @@ -2362,57 +2325,6 @@ void R_AddLightInteractions() R_RotateLightForViewParms( light, &tr.viewParms, &tr.orientation ); // calc local bounds for culling - if ( light->isStatic ) - { - // ignore if not in PVS - if ( !r_noLightVisCull->integer ) - { - for ( l = light->leafs.next; l != &light->leafs; l = l->next ) - { - if ( !l || !l->data ) - { - // something odd happens with the prev/next pointers if ri.Hunk_Alloc was used - break; - } - - leaf = ( bspNode_t * ) l->data; - - if ( leaf->visCounts[ tr.visIndex ] == tr.visCounts[ tr.visIndex ] ) - { - light->visCounts[ tr.visIndex ] = tr.visCounts[ tr.visIndex ]; - } - } - - if ( light->visCounts[ tr.visIndex ] != tr.visCounts[ tr.visIndex ] ) - { - tr.pc.c_pvs_cull_light_out++; - light->cull = cullResult_t::CULL_OUT; - continue; - } - } - - // look if we have to draw the light including its interactions - switch ( R_CullLocalBox( light->localBounds ) ) - { - case cullResult_t::CULL_IN: - default: - tr.pc.c_box_cull_light_in++; - light->cull = cullResult_t::CULL_IN; - break; - - case cullResult_t::CULL_CLIP: - tr.pc.c_box_cull_light_clip++; - light->cull = cullResult_t::CULL_CLIP; - break; - - case cullResult_t::CULL_OUT: - // light is not visible so skip other light setup stuff to save speed - tr.pc.c_box_cull_light_out++; - light->cull = cullResult_t::CULL_OUT; - continue; - } - } - else { // set up light transform matrix MatrixSetupTransformFromQuat( light->transformMatrix, light->l.rotation, light->l.origin ); @@ -2435,18 +2347,15 @@ void R_AddLightInteractions() case cullResult_t::CULL_IN: default: tr.pc.c_box_cull_light_in++; - light->cull = cullResult_t::CULL_IN; break; case cullResult_t::CULL_CLIP: tr.pc.c_box_cull_light_clip++; - light->cull = cullResult_t::CULL_CLIP; break; case cullResult_t::CULL_OUT: // light is not visible so skip other light setup stuff to save speed tr.pc.c_box_cull_light_out++; - light->cull = cullResult_t::CULL_OUT; continue; } @@ -2460,7 +2369,6 @@ void R_AddLightInteractions() if ( !BoundsIntersect ( light->worldBounds[ 0 ], light->worldBounds[ 1 ], tr.viewParms.visBounds[ 0 ], tr.viewParms.visBounds[ 1 ] ) ) { - light->cull = cullResult_t::CULL_OUT; continue; } } @@ -2483,185 +2391,20 @@ void R_AddLightInteractions() light->numLightOnlyInteractions = 0; light->noSort = false; - if ( light->isStatic ) - { - R_AddPrecachedWorldInteractions( light ); - } - else - { - R_AddWorldInteractions( light ); - } - + R_AddWorldInteractions( light ); R_AddEntityInteractions( light ); if ( light->numInteractions && light->numInteractions != light->numShadowOnlyInteractions ) { R_SortInteractions( light ); - if ( light->isStatic ) - { - tr.pc.c_slights++; - } - else - { - tr.pc.c_dlights++; - } + tr.pc.c_dlights++; } else { // skip all interactions of this light because it caused only shadow volumes // but no lighting tr.refdef.numInteractions -= light->numInteractions; - light->cull = cullResult_t::CULL_OUT; - } - } -} - -void R_AddLightBoundsToVisBounds() -{ - int i; - trRefLight_t *light; - bspNode_t *leaf; - link_t *l; - - for ( i = 0; i < tr.refdef.numLights; i++ ) - { - light = tr.currentLight = &tr.refdef.lights[ i ]; - - if ( light->isStatic ) - { - if ( !glConfig2.staticLight ) - { - continue; - } - - if ( ( r_precomputedLighting->integer || tr.worldLight != lightMode_t::MAP ) && !light->noRadiosity ) - { - continue; - } - } - else - { - if ( !glConfig2.dynamicLight ) - { - continue; - } - - if( r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) - { - continue; - } - } - - // we must set up parts of tr.or for light culling - R_RotateLightForViewParms( light, &tr.viewParms, &tr.orientation ); - - // calc local bounds for culling - if ( light->isStatic ) - { - // ignore if not in PVS - if ( !r_noLightVisCull->integer ) - { - for ( l = light->leafs.next; l != &light->leafs; l = l->next ) - { - if ( !l || !l->data ) - { - // something odd happens with the prev/next pointers if ri.Hunk_Alloc was used - break; - } - - leaf = ( bspNode_t * ) l->data; - - if ( leaf->visCounts[ tr.visIndex ] == tr.visCounts[ tr.visIndex ] ) - { - light->visCounts[ tr.visIndex ] = tr.visCounts[ tr.visIndex ]; - } - } - - if ( light->visCounts[ tr.visIndex ] != tr.visCounts[ tr.visIndex ] ) - { - continue; - } - } - - // look if we have to draw the light including its interactions - switch ( R_CullLocalBox( light->localBounds ) ) - { - case cullResult_t::CULL_IN: - default: - break; - - case cullResult_t::CULL_CLIP: - break; - - case cullResult_t::CULL_OUT: - continue; - } - } - else - { - // set up light transform matrix - MatrixSetupTransformFromQuat( light->transformMatrix, light->l.rotation, light->l.origin ); - - // set up light origin for lighting and shadowing - R_SetupLightOrigin( light ); - - // set up model to light view matrix - R_SetupLightView( light ); - - // set up projection - R_SetupLightProjection( light ); - - // calc local bounds for culling - R_SetupLightLocalBounds( light ); - - // look if we have to draw the light including its interactions - switch ( R_CullLocalBox( light->localBounds ) ) - { - case cullResult_t::CULL_IN: - default: - break; - - case cullResult_t::CULL_CLIP: - break; - - case cullResult_t::CULL_OUT: - continue; - } - - // setup world bounds for intersection tests - R_SetupLightWorldBounds( light ); - } - - // add to z buffer bounds - if ( light->worldBounds[ 0 ][ 0 ] < tr.viewParms.visBounds[ 0 ][ 0 ] ) - { - tr.viewParms.visBounds[ 0 ][ 0 ] = light->worldBounds[ 0 ][ 0 ]; - } - - if ( light->worldBounds[ 0 ][ 1 ] < tr.viewParms.visBounds[ 0 ][ 1 ] ) - { - tr.viewParms.visBounds[ 0 ][ 1 ] = light->worldBounds[ 0 ][ 1 ]; - } - - if ( light->worldBounds[ 0 ][ 2 ] < tr.viewParms.visBounds[ 0 ][ 2 ] ) - { - tr.viewParms.visBounds[ 0 ][ 2 ] = light->worldBounds[ 0 ][ 2 ]; - } - - if ( light->worldBounds[ 1 ][ 0 ] > tr.viewParms.visBounds[ 1 ][ 0 ] ) - { - tr.viewParms.visBounds[ 1 ][ 0 ] = light->worldBounds[ 1 ][ 0 ]; - } - - if ( light->worldBounds[ 1 ][ 1 ] > tr.viewParms.visBounds[ 1 ][ 1 ] ) - { - tr.viewParms.visBounds[ 1 ][ 1 ] = light->worldBounds[ 1 ][ 1 ]; - } - - if ( light->worldBounds[ 1 ][ 2 ] > tr.viewParms.visBounds[ 1 ][ 2 ] ) - { - tr.viewParms.visBounds[ 1 ][ 2 ] = light->worldBounds[ 1 ][ 2 ]; } } } @@ -2798,10 +2541,6 @@ void R_RenderView( viewParms_t *parms ) R_AddPolygonSurfaces(); - // we have tr.viewParms.visBounds set and now we need to add the light bounds - // or we get wrong occlusion query results - R_AddLightBoundsToVisBounds(); - // set the projection matrix now that we have the world bounded // this needs to be done before entities are // added, because they use the projection diff --git a/src/engine/renderer/tr_public.h b/src/engine/renderer/tr_public.h index 62ac333898..23e842858c 100644 --- a/src/engine/renderer/tr_public.h +++ b/src/engine/renderer/tr_public.h @@ -71,9 +71,6 @@ struct glconfig2_t int maxCubeMapTextureSize; - bool occlusionQueryAvailable; - int occlusionQueryBits; - char shadingLanguageVersionString[ MAX_STRING_CHARS ]; int shadingLanguageVersion; @@ -133,8 +130,6 @@ struct glconfig2_t bool depthClampAvailable; bool realtimeLighting; - bool dynamicLight; - bool staticLight; bool shadowMapping; shadowingMode_t shadowingMode; bool deluxeMapping; @@ -237,8 +232,6 @@ struct refexport_t // XreaL BEGIN void ( *TakeVideoFrame )( int h, int w, byte *captureBuffer, byte *encodeBuffer, bool motionJpeg ); - void ( *AddRefLightToScene )( const refLight_t *light ); - // RB: alternative skeletal animation system qhandle_t ( *RegisterAnimation )( const char *name ); int ( *CheckSkeleton )( refSkeleton_t *skel, qhandle_t model, qhandle_t anim ); diff --git a/src/engine/renderer/tr_scene.cpp b/src/engine/renderer/tr_scene.cpp index 659e195544..a5157d54e8 100644 --- a/src/engine/renderer/tr_scene.cpp +++ b/src/engine/renderer/tr_scene.cpp @@ -24,6 +24,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tr_local.h" #include "Material.h" +static Cvar::Cvar r_drawDynamicLights( + "r_drawDynamicLights", "render dynamic lights (if realtime lighting is enabled)", Cvar::NONE, true ); + static int r_firstSceneDrawSurf; static int r_firstSceneInteraction; @@ -276,102 +279,6 @@ void RE_AddRefEntityToScene( const refEntity_t *ent ) r_numEntities++; } -/* -===================== -RE_AddRefLightToScene -===================== -*/ -void RE_AddRefLightToScene( const refLight_t *l ) -{ - trRefLight_t *light; - - if ( !tr.registered ) - { - return; - } - - if ( r_numLights >= MAX_REF_LIGHTS ) - { - return; - } - - if ( l->radius <= 0 && !VectorLength( l->projTarget ) ) - { - return; - } - - if (l->rlType >= refLightType_t::RL_MAX_REF_LIGHT_TYPE) - { - Sys::Drop("RE_AddRefLightToScene: bad rlType %s", Util::enum_str(l->rlType)); - } - - light = &backEndData[ tr.smpFrame ]->lights[ r_numLights++ ]; - light->l = *l; - - light->isStatic = false; - light->additive = true; - - if ( light->l.scale <= 0 ) - { - light->l.scale = r_lightScale->value; - } - - if ( light->l.scale >= r_lightScale->value ) - { - light->l.scale = r_lightScale->value; - } - - if ( !r_realtimeLightingCastShadows->integer && !light->l.inverseShadows ) - { - light->l.noShadows = true; - } -} - -/* -===================== -R_AddWorldLightsToScene -===================== -*/ -static void R_AddWorldLightsToScene() -{ - int i; - trRefLight_t *light; - - if ( !glConfig2.staticLight ) - { - return; - } - - if ( !tr.registered ) - { - return; - } - - if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) - { - return; - } - - for ( i = 0; i < tr.world->numLights; i++ ) - { - light = tr.currentLight = &tr.world->lights[ i ]; - - if ( r_numLights >= MAX_REF_LIGHTS ) - { - return; - } - - if ( !light->firstInteractionCache ) - { - // this light has no interactions precached - continue; - } - - backEndData[ tr.smpFrame ]->lights[ r_numLights ] = *light; - r_numLights++; - } -} - /* ===================== RE_AddDynamicLightToScene @@ -383,7 +290,7 @@ void RE_AddDynamicLightToSceneET( const vec3_t org, float radius, float intensit { trRefLight_t *light; - if ( !glConfig2.dynamicLight ) + if ( !glConfig2.realtimeLighting || !r_drawDynamicLights.Get() ) { return; } @@ -445,7 +352,6 @@ void RE_AddDynamicLightToSceneET( const vec3_t org, float radius, float intensit light->restrictInteractionLast = -1; } - light->isStatic = false; light->additive = true; if( light->l.inverseShadows ) @@ -663,8 +569,6 @@ void RE_RenderScene( const refdef_t *fd ) } } - R_AddWorldLightsToScene(); - // derived info tr.refdef.floatTime = float(double(tr.refdef.time) * 0.001); diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index ff43b8e2aa..6022485a6f 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -57,10 +57,6 @@ static void EnableAvailableFeatures() } } - // Enable different kinds of dynamic lights. - glConfig2.dynamicLight = glConfig2.realtimeLighting && r_dynamicLight.Get(); - glConfig2.staticLight = glConfig2.realtimeLighting && r_staticLight.Get(); - glConfig2.shadowingMode = shadowingMode_t( r_shadows.Get() ); glConfig2.shadowMapping = glConfig2.shadowingMode >= shadowingMode_t::SHADOWING_ESM16; @@ -1063,12 +1059,13 @@ void Render_lightMapping( shaderStage_t *pStage ) gl_lightMappingShader->SetUniform_ModelViewProjectionMatrix( glState.modelViewProjectionMatrix[ glState.stackIndex ] ); - gl_lightMappingShader->SetUniform_numLights( backEnd.refdef.numLights ); - - if( glConfig2.realtimeLighting ) + if ( glConfig2.realtimeLighting && + r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) { if ( backEnd.refdef.numShaderLights > 0 ) - { + { + gl_lightMappingShader->SetUniform_numLights( backEnd.refdef.numLights ); + if( glConfig2.uniformBufferObjectAvailable ) { gl_lightMappingShader->SetUniformBlock_Lights( tr.dlightUBO ); @@ -1078,15 +1075,16 @@ void Render_lightMapping( shaderStage_t *pStage ) GL_BindToTMU( BIND_LIGHTS, tr.dlightImage ) ); } - } - // bind u_LightTiles - if ( r_realtimeLightingRenderer.Get() == Util::ordinal( realtimeLightingRenderer_t::TILED ) ) - { + // bind u_LightTiles gl_lightMappingShader->SetUniform_LightTilesIntBindless( GL_BindToTMU( BIND_LIGHTTILES, tr.lighttileRenderImage ) ); } + else + { + gl_lightMappingShader->SetUniform_numLights( 0 ); + } } // u_DeformGen @@ -1522,11 +1520,6 @@ static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, gl_forwardLightingShader_omniXYZ->SetUniform_NormalScale( normalScale ); } - // bind u_MaterialMap - gl_forwardLightingShader_omniXYZ->SetUniform_MaterialMapBindless( - GL_BindToTMU( 2, pStage->bundle[TB_MATERIALMAP].image[0] ) - ); - // FIXME: physical mapping is not implemented. if ( pStage->enableSpecularMapping ) { @@ -1534,6 +1527,11 @@ static void Render_forwardLighting_DBS_omni( shaderStage_t *pStage, float maxSpec = RB_EvalExpression( &pStage->specularExponentMax, r_specularExponentMax->value ); gl_forwardLightingShader_omniXYZ->SetUniform_SpecularExponent( minSpec, maxSpec ); + + // bind u_MaterialMap + gl_forwardLightingShader_omniXYZ->SetUniform_MaterialMapBindless( + GL_BindToTMU( 2, pStage->bundle[TB_MATERIALMAP].image[0] ) + ); } // bind u_AttenuationMapXY diff --git a/src/engine/renderer/tr_world.cpp b/src/engine/renderer/tr_world.cpp index f9863de2e0..e6918a4af6 100644 --- a/src/engine/renderer/tr_world.cpp +++ b/src/engine/renderer/tr_world.cpp @@ -240,7 +240,7 @@ static void R_AddInteractionSurface( bspSurface_t *surf, trRefLight_t *light, in if ( R_CullLightSurface( surf->data, surf->shader, light, &cubeSideBits ) ) { - if ( !light->isStatic && firstAddition ) + if ( firstAddition ) { tr.pc.c_dlightSurfacesCulled++; } @@ -251,14 +251,7 @@ static void R_AddInteractionSurface( bspSurface_t *surf, trRefLight_t *light, in if ( firstAddition ) { - if ( light->isStatic ) - { - tr.pc.c_slightSurfaces++; - } - else - { - tr.pc.c_dlightSurfaces++; - } + tr.pc.c_dlightSurfaces++; } } @@ -918,153 +911,3 @@ void R_AddWorldInteractions( trRefLight_t *light ) R_RecursiveInteractionNode( tr.world->nodes, light, FRUSTUM_CLIPALL, interactionBits ); } - -/* -============= -R_AddPrecachedWorldInteractions -============= -*/ -void R_AddPrecachedWorldInteractions( trRefLight_t *light ) -{ - interactionType_t iaType = IA_DEFAULT; - - if ( !r_drawworld->integer ) - { - return; - } - - if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) - { - return; - } - - if ( !light->firstInteractionCache ) - { - // this light has no interactions precached - return; - } - - tr.currentEntity = &tr.worldEntity; - - if ( ( r_vboShadows->integer || r_vboLighting->integer ) ) - { - interactionCache_t *iaCache; - interactionVBO_t *iaVBO; - srfVBOMesh_t *srf; - shader_t *shader; - bspSurface_t *surface; - - // this can be shadow mapping or shadowless lighting - for ( iaVBO = light->firstInteractionVBO; iaVBO; iaVBO = iaVBO->next ) - { - if ( !iaVBO->vboLightMesh ) - { - continue; - } - - srf = iaVBO->vboLightMesh; - shader = iaVBO->shader; - - switch ( light->l.rlType ) - { - case refLightType_t::RL_OMNI: - R_AddLightInteraction( light, ( surfaceType_t * ) srf, shader, CUBESIDE_CLIPALL, IA_LIGHT ); - break; - - case refLightType_t::RL_DIRECTIONAL: - case refLightType_t::RL_PROJ: - R_AddLightInteraction( light, ( surfaceType_t * ) srf, shader, CUBESIDE_CLIPALL, IA_LIGHT ); - break; - - default: - R_AddLightInteraction( light, ( surfaceType_t * ) srf, shader, CUBESIDE_CLIPALL, IA_DEFAULT ); - break; - } - } - - // add meshes for shadowmap generation if any - for ( iaVBO = light->firstInteractionVBO; iaVBO; iaVBO = iaVBO->next ) - { - if ( !iaVBO->vboShadowMesh ) - { - continue; - } - - srf = iaVBO->vboShadowMesh; - shader = iaVBO->shader; - - R_AddLightInteraction( light, ( surfaceType_t * ) srf, shader, iaVBO->cubeSideBits, IA_SHADOW ); - } - - // add interactions that couldn't be merged into VBOs - for ( iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next ) - { - if ( iaCache->redundant ) - { - continue; - } - - if ( iaCache->mergedIntoVBO ) - { - continue; - } - - surface = iaCache->surface; - - // Tr3B - this surface is maybe not in this view but it may still cast a shadow - // into this view - if ( surface->viewCount != tr.viewCountNoReset ) - { - if ( !glConfig2.shadowMapping || light->l.noShadows ) - { - continue; - } - else - { - iaType = IA_SHADOW; - } - } - else - { - iaType = iaCache->type; - } - - R_AddLightInteraction( light, surface->data, surface->shader, iaCache->cubeSideBits, iaType ); - } - } - else - { - interactionCache_t *iaCache; - bspSurface_t *surface; - - for ( iaCache = light->firstInteractionCache; iaCache; iaCache = iaCache->next ) - { - if ( iaCache->redundant ) - { - continue; - } - - surface = iaCache->surface; - - // Tr3B - this surface is maybe not in this view but it may still cast a shadow - // into this view - if ( surface->viewCount != tr.viewCountNoReset ) - { - if ( !glConfig2.shadowMapping || light->l.noShadows ) - { - continue; - } - else - { - iaType = IA_SHADOW; - } - } - else - { - iaType = iaCache->type; - } - - R_AddLightInteraction( light, surface->data, surface->shader, iaCache->cubeSideBits, iaType ); - } - } -} diff --git a/src/engine/sys/sdl_glimp.cpp b/src/engine/sys/sdl_glimp.cpp index d9f312789b..2298eba571 100644 --- a/src/engine/sys/sdl_glimp.cpp +++ b/src/engine/sys/sdl_glimp.cpp @@ -110,8 +110,6 @@ static Cvar::Cvar r_ext_draw_buffers( "r_ext_draw_buffers", "Use GL_EXT_draw_buffers if available", Cvar::NONE, true ); static Cvar::Cvar r_ext_gpu_shader4( "r_ext_gpu_shader4", "Use GL_EXT_gpu_shader4 if available", Cvar::NONE, true ); -static Cvar::Cvar r_ext_occlusion_query( "r_ext_occlusion_query", - "Use GL_EXT_occlusion_query if available", Cvar::NONE, true ); static Cvar::Range> r_ext_texture_filter_anisotropic( "r_ext_texture_filter_anisotropic", "Use GL_EXT_texture_filter_anisotropic if available: anisotropy value", Cvar::NONE, 4.0f, 0.0f, 16.0f ); static Cvar::Cvar r_ext_texture_float( "r_ext_texture_float", @@ -1981,7 +1979,6 @@ static void GLimp_InitExtensions() Cvar::Latch( r_arb_uniform_buffer_object ); Cvar::Latch( r_ext_draw_buffers ); Cvar::Latch( r_ext_gpu_shader4 ); - Cvar::Latch( r_ext_occlusion_query ); Cvar::Latch( r_ext_texture_filter_anisotropic ); Cvar::Latch( r_ext_texture_float ); Cvar::Latch( r_ext_texture_integer ); @@ -2242,15 +2239,6 @@ static void GLimp_InitExtensions() glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE, &glConfig2.maxRenderbufferSize ); glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, &glConfig2.maxColorAttachments ); - // made required in OpenGL 1.5 - glConfig2.occlusionQueryAvailable = false; - glConfig2.occlusionQueryBits = 0; - if ( r_ext_occlusion_query.Get() ) - { - glConfig2.occlusionQueryAvailable = true; - glGetQueryiv( GL_SAMPLES_PASSED, GL_QUERY_COUNTER_BITS, &glConfig2.occlusionQueryBits ); - } - // made required in OpenGL 2.0 glConfig2.drawBuffersAvailable = false; if ( r_ext_draw_buffers.Get() )