DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

tr_frontend_addmodels.cpp (46005B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 
     29 #pragma hdrstop
     30 #include "../idlib/precompiled.h"
     31 
     32 #include "tr_local.h"
     33 #include "Model_local.h"
     34 
     35 idCVar r_skipStaticShadows( "r_skipStaticShadows", "0", CVAR_RENDERER | CVAR_BOOL, "skip static shadows" );
     36 idCVar r_skipDynamicShadows( "r_skipDynamicShadows", "0", CVAR_RENDERER | CVAR_BOOL, "skip dynamic shadows" );
     37 idCVar r_useParallelAddModels( "r_useParallelAddModels", "1", CVAR_RENDERER | CVAR_BOOL, "add all models in parallel with jobs" );
     38 idCVar r_useParallelAddShadows( "r_useParallelAddShadows", "1", CVAR_RENDERER | CVAR_INTEGER, "0 = off, 1 = threaded", 0, 1 );
     39 idCVar r_useShadowPreciseInsideTest( "r_useShadowPreciseInsideTest", "1", CVAR_RENDERER | CVAR_BOOL, "use a precise and more expensive test to determine whether the view is inside a shadow volume" );
     40 idCVar r_cullDynamicShadowTriangles( "r_cullDynamicShadowTriangles", "1", CVAR_RENDERER | CVAR_BOOL, "cull occluder triangles that are outside the light frustum so they do not contribute to the dynamic shadow volume" );
     41 idCVar r_cullDynamicLightTriangles( "r_cullDynamicLightTriangles", "1", CVAR_RENDERER | CVAR_BOOL, "cull surface triangles that are outside the light frustum so they do not get rendered for interactions" );
     42 idCVar r_forceShadowCaps( "r_forceShadowCaps", "0", CVAR_RENDERER | CVAR_BOOL, "0 = skip rendering shadow caps if view is outside shadow volume, 1 = always render shadow caps" );
     43 
     44 static const float CHECK_BOUNDS_EPSILON = 1.0f;
     45 
     46 /*
     47 ==================
     48 R_SortViewEntities
     49 ==================
     50 */
     51 viewEntity_t * R_SortViewEntities( viewEntity_t * vEntities ) {
     52 	SCOPED_PROFILE_EVENT( "R_SortViewEntities" );
     53 
     54 	// We want to avoid having a single AddModel for something complex be
     55 	// the last thing processed and hurt the parallel occupancy, so
     56 	// sort dynamic models first, _area models second, then everything else.
     57 	viewEntity_t * dynamics = NULL;
     58 	viewEntity_t * areas = NULL;
     59 	viewEntity_t * others = NULL;
     60 	for ( viewEntity_t * vEntity = vEntities; vEntity != NULL; ) {
     61 		viewEntity_t * next = vEntity->next;
     62 		const idRenderModel * model = vEntity->entityDef->parms.hModel;
     63 		if ( model->IsDynamicModel() != DM_STATIC ) {
     64 			vEntity->next = dynamics;
     65 			dynamics = vEntity;
     66 		} else if ( model->IsStaticWorldModel() ) {
     67 			vEntity->next = areas;
     68 			areas = vEntity;
     69 		} else {
     70 			vEntity->next = others;
     71 			others = vEntity;
     72 		}
     73 		vEntity = next;
     74 	}
     75 
     76 	// concatenate the lists
     77 	viewEntity_t * all = others;
     78 
     79 	for ( viewEntity_t * vEntity = areas; vEntity != NULL; ) {
     80 		viewEntity_t * next = vEntity->next;
     81 		vEntity->next = all;
     82 		all = vEntity;
     83 		vEntity = next;
     84 	}
     85 
     86 	for ( viewEntity_t * vEntity = dynamics; vEntity != NULL; ) {
     87 		viewEntity_t * next = vEntity->next;
     88 		vEntity->next = all;
     89 		all = vEntity;
     90 		vEntity = next;
     91 	}
     92 
     93 	return all;
     94 }
     95 
     96 /*
     97 ==================
     98 R_ClearEntityDefDynamicModel
     99 
    100 If we know the reference bounds stays the same, we
    101 only need to do this on entity update, not the full
    102 R_FreeEntityDefDerivedData
    103 ==================
    104 */
    105 void R_ClearEntityDefDynamicModel( idRenderEntityLocal *def ) {
    106 	// free all the interaction surfaces
    107 	for ( idInteraction *inter = def->firstInteraction; inter != NULL && !inter->IsEmpty(); inter = inter->entityNext ) {
    108 		inter->FreeSurfaces();
    109 	}
    110 
    111 	// clear the dynamic model if present
    112 	if ( def->dynamicModel ) {
    113 		// this is copied from cachedDynamicModel, so it doesn't need to be freed
    114 		def->dynamicModel = NULL;
    115 	}
    116 	def->dynamicModelFrameCount = 0;
    117 }
    118 
    119 /*
    120 ==================
    121 R_IssueEntityDefCallback
    122 ==================
    123 */
    124 bool R_IssueEntityDefCallback( idRenderEntityLocal *def ) {
    125 	idBounds oldBounds = def->localReferenceBounds;
    126 
    127 	def->archived = false;		// will need to be written to the demo file
    128 
    129 	bool update;
    130 	if ( tr.viewDef != NULL ) {
    131 		update = def->parms.callback( &def->parms, &tr.viewDef->renderView );
    132 	} else {
    133 		update = def->parms.callback( &def->parms, NULL );
    134 	}
    135 	tr.pc.c_entityDefCallbacks++;
    136 
    137 	if ( def->parms.hModel == NULL ) {
    138 		common->Error( "R_IssueEntityDefCallback: dynamic entity callback didn't set model" );
    139 	}
    140 
    141 	if ( r_checkBounds.GetBool() ) {
    142 		if (	oldBounds[0][0] > def->localReferenceBounds[0][0] + CHECK_BOUNDS_EPSILON ||
    143 				oldBounds[0][1] > def->localReferenceBounds[0][1] + CHECK_BOUNDS_EPSILON ||
    144 				oldBounds[0][2] > def->localReferenceBounds[0][2] + CHECK_BOUNDS_EPSILON ||
    145 				oldBounds[1][0] < def->localReferenceBounds[1][0] - CHECK_BOUNDS_EPSILON ||
    146 				oldBounds[1][1] < def->localReferenceBounds[1][1] - CHECK_BOUNDS_EPSILON ||
    147 				oldBounds[1][2] < def->localReferenceBounds[1][2] - CHECK_BOUNDS_EPSILON ) {
    148 			common->Printf( "entity %i callback extended reference bounds\n", def->index );
    149 		}
    150 	}
    151 
    152 	return update;
    153 }
    154 
    155 /*
    156 ===================
    157 R_EntityDefDynamicModel
    158 
    159 This is also called by the game code for idRenderWorldLocal::ModelTrace(), and idRenderWorldLocal::Trace() which is bad for performance...
    160 
    161 Issues a deferred entity callback if necessary.
    162 If the model isn't dynamic, it returns the original.
    163 Returns the cached dynamic model if present, otherwise creates it.
    164 ===================
    165 */
    166 idRenderModel *R_EntityDefDynamicModel( idRenderEntityLocal *def ) {
    167 	if ( def->dynamicModelFrameCount == tr.frameCount ) {
    168 		return def->dynamicModel;
    169 	}
    170 
    171 	// allow deferred entities to construct themselves
    172 	bool callbackUpdate;
    173 	if ( def->parms.callback != NULL ) {
    174 		SCOPED_PROFILE_EVENT( "R_IssueEntityDefCallback" );
    175 		callbackUpdate = R_IssueEntityDefCallback( def );
    176 	} else {
    177 		callbackUpdate = false;
    178 	}
    179 
    180 	idRenderModel *model = def->parms.hModel;
    181 
    182 	if ( model == NULL ) {
    183 		common->Error( "R_EntityDefDynamicModel: NULL model" );
    184 		return NULL;
    185 	}
    186 
    187 	if ( model->IsDynamicModel() == DM_STATIC ) {
    188 		def->dynamicModel = NULL;
    189 		def->dynamicModelFrameCount = 0;
    190 		return model;
    191 	}
    192 
    193 	// continously animating models (particle systems, etc) will have their snapshot updated every single view
    194 	if ( callbackUpdate || ( model->IsDynamicModel() == DM_CONTINUOUS && def->dynamicModelFrameCount != tr.frameCount ) ) {
    195 		R_ClearEntityDefDynamicModel( def );
    196 	}
    197 
    198 	// if we don't have a snapshot of the dynamic model, generate it now
    199 	if ( def->dynamicModel == NULL ) {
    200 
    201 		SCOPED_PROFILE_EVENT( "InstantiateDynamicModel" );
    202 
    203 		// instantiate the snapshot of the dynamic model, possibly reusing memory from the cached snapshot
    204 		def->cachedDynamicModel = model->InstantiateDynamicModel( &def->parms, tr.viewDef, def->cachedDynamicModel );
    205 
    206 		if ( def->cachedDynamicModel != NULL && r_checkBounds.GetBool() ) {
    207 			idBounds b = def->cachedDynamicModel->Bounds();
    208 			if (	b[0][0] < def->localReferenceBounds[0][0] - CHECK_BOUNDS_EPSILON ||
    209 					b[0][1] < def->localReferenceBounds[0][1] - CHECK_BOUNDS_EPSILON ||
    210 					b[0][2] < def->localReferenceBounds[0][2] - CHECK_BOUNDS_EPSILON ||
    211 					b[1][0] > def->localReferenceBounds[1][0] + CHECK_BOUNDS_EPSILON ||
    212 					b[1][1] > def->localReferenceBounds[1][1] + CHECK_BOUNDS_EPSILON ||
    213 					b[1][2] > def->localReferenceBounds[1][2] + CHECK_BOUNDS_EPSILON ) {
    214 				common->Printf( "entity %i dynamic model exceeded reference bounds\n", def->index );
    215 			}
    216 		}
    217 
    218 		def->dynamicModel = def->cachedDynamicModel;
    219 		def->dynamicModelFrameCount = tr.frameCount;
    220 	}
    221 
    222 	// set model depth hack value
    223 	if ( def->dynamicModel != NULL && model->DepthHack() != 0.0f && tr.viewDef != NULL ) {
    224 		idPlane eye, clip;
    225 		idVec3 ndc;
    226 		R_TransformModelToClip( def->parms.origin, tr.viewDef->worldSpace.modelViewMatrix, tr.viewDef->projectionMatrix, eye, clip );
    227 		R_TransformClipToDevice( clip, ndc );
    228 		def->parms.modelDepthHack = model->DepthHack() * ( 1.0f - ndc.z );
    229 	} else {
    230 		def->parms.modelDepthHack = 0.0f;
    231 	}
    232 
    233 	return def->dynamicModel;
    234 }
    235 
    236 /*
    237 ===================
    238 R_SetupDrawSurfShader
    239 ===================
    240 */
    241 void R_SetupDrawSurfShader( drawSurf_t * drawSurf, const idMaterial * shader, const renderEntity_t * renderEntity ) {
    242 	drawSurf->material = shader;
    243 	drawSurf->sort = shader->GetSort();
    244 
    245 	// process the shader expressions for conditionals / color / texcoords
    246 	const float	*constRegs = shader->ConstantRegisters();
    247 	if ( likely( constRegs != NULL ) ) {
    248 		// shader only uses constant values
    249 		drawSurf->shaderRegisters = constRegs;
    250 	} else {
    251 		// by default evaluate with the entityDef's shader parms
    252 		const float * shaderParms = renderEntity->shaderParms;
    253 
    254 		// a reference shader will take the calculated stage color value from another shader
    255 		// and use that for the parm0-parm3 of the current shader, which allows a stage of
    256 		// a light model and light flares to pick up different flashing tables from
    257 		// different light shaders
    258 		float generatedShaderParms[MAX_ENTITY_SHADER_PARMS];
    259 		if ( unlikely( renderEntity->referenceShader != NULL ) ) {
    260 			// evaluate the reference shader to find our shader parms
    261 			float refRegs[MAX_EXPRESSION_REGISTERS];
    262 			renderEntity->referenceShader->EvaluateRegisters( refRegs, renderEntity->shaderParms,
    263 																tr.viewDef->renderView.shaderParms,
    264 																tr.viewDef->renderView.time[renderEntity->timeGroup] * 0.001f, renderEntity->referenceSound );
    265 
    266 			const shaderStage_t * pStage = renderEntity->referenceShader->GetStage( 0 );
    267 
    268 			memcpy( generatedShaderParms, renderEntity->shaderParms, sizeof( generatedShaderParms ) );
    269 			generatedShaderParms[0] = refRegs[ pStage->color.registers[0] ];
    270 			generatedShaderParms[1] = refRegs[ pStage->color.registers[1] ];
    271 			generatedShaderParms[2] = refRegs[ pStage->color.registers[2] ];
    272 
    273 			shaderParms = generatedShaderParms;
    274 		}
    275 
    276 		// allocte frame memory for the shader register values
    277 		float * regs = (float *)R_FrameAlloc( shader->GetNumRegisters() * sizeof( float ), FRAME_ALLOC_SHADER_REGISTER );
    278 		drawSurf->shaderRegisters = regs;
    279 
    280 		// process the shader expressions for conditionals / color / texcoords
    281 		shader->EvaluateRegisters( regs, shaderParms, tr.viewDef->renderView.shaderParms,
    282 										tr.viewDef->renderView.time[renderEntity->timeGroup] * 0.001f, renderEntity->referenceSound );
    283 	}
    284 }
    285 
    286 /*
    287 ===================
    288 R_SetupDrawSurfJoints
    289 ===================
    290 */
    291 void R_SetupDrawSurfJoints( drawSurf_t * drawSurf, const srfTriangles_t * tri, const idMaterial * shader ) {
    292 	if ( tri->staticModelWithJoints == NULL || !r_useGPUSkinning.GetBool() ) {
    293 		drawSurf->jointCache = 0;
    294 		return;
    295 	}
    296 
    297 	idRenderModelStatic * model = tri->staticModelWithJoints;
    298 	assert( model->jointsInverted != NULL );
    299 
    300 	if ( !vertexCache.CacheIsCurrent( model->jointsInvertedBuffer ) ) {
    301 		const int alignment = glConfig.uniformBufferOffsetAlignment;
    302 		model->jointsInvertedBuffer = vertexCache.AllocJoint( model->jointsInverted, ALIGN( model->numInvertedJoints * sizeof( idJointMat ), alignment ) );
    303 	}
    304 	drawSurf->jointCache = model->jointsInvertedBuffer;
    305 }
    306 
    307 /*
    308 ===================
    309 R_AddSingleModel
    310 
    311 May be run in parallel.
    312 
    313 Here is where dynamic models actually get instantiated, and necessary
    314 interaction surfaces get created. This is all done on a sort-by-model
    315 basis to keep source data in cache (most likely L2) as any interactions
    316 and shadows are generated, since dynamic models will typically be lit by
    317 two or more lights.
    318 ===================
    319 */
    320 void R_AddSingleModel( viewEntity_t * vEntity ) {
    321 	// we will add all interaction surfs here, to be chained to the lights in later serial code
    322 	vEntity->drawSurfs = NULL;
    323 	vEntity->staticShadowVolumes = NULL;
    324 	vEntity->dynamicShadowVolumes = NULL;
    325 
    326 	// globals we really should pass in...
    327 	const viewDef_t * viewDef = tr.viewDef;
    328 
    329 	idRenderEntityLocal * entityDef = vEntity->entityDef;
    330 	const renderEntity_t * renderEntity = &entityDef->parms;
    331 	const idRenderWorldLocal * world = entityDef->world;
    332 
    333 	if ( viewDef->isXraySubview && entityDef->parms.xrayIndex == 1 ) {
    334 		return;
    335 	} else if ( !viewDef->isXraySubview && entityDef->parms.xrayIndex == 2 ) {
    336 		return;
    337 	}
    338 
    339 	SCOPED_PROFILE_EVENT( renderEntity->hModel == NULL ? "Unknown Model" : renderEntity->hModel->Name() );
    340 
    341 	// calculate the znear for testing whether or not the view is inside a shadow projection
    342 	const float znear = ( viewDef->renderView.cramZNear ) ? ( r_znear.GetFloat() * 0.25f ) : r_znear.GetFloat();
    343 
    344 	// if the entity wasn't seen through a portal chain, it was added just for light shadows
    345 	const bool modelIsVisible = !vEntity->scissorRect.IsEmpty();
    346 	const bool addInteractions = modelIsVisible && ( !viewDef->isXraySubview || entityDef->parms.xrayIndex == 2 );
    347 	const int entityIndex = entityDef->index;
    348 
    349 	//---------------------------
    350 	// Find which of the visible lights contact this entity
    351 	//
    352 	// If the entity doesn't accept light or cast shadows from any surface,
    353 	// this can be skipped.
    354 	//
    355 	// OPTIMIZE: world areas can assume all referenced lights are used
    356 	//---------------------------
    357 	int	numContactedLights = 0;
    358 	static const int MAX_CONTACTED_LIGHTS = 128;
    359 	viewLight_t * contactedLights[MAX_CONTACTED_LIGHTS];
    360 	idInteraction * staticInteractions[MAX_CONTACTED_LIGHTS];
    361 
    362 	if ( renderEntity->hModel == NULL ||
    363 			renderEntity->hModel->ModelHasInteractingSurfaces() ||
    364 			renderEntity->hModel->ModelHasShadowCastingSurfaces() ) {
    365 		SCOPED_PROFILE_EVENT( "Find lights" );
    366 		for ( viewLight_t * vLight = viewDef->viewLights; vLight != NULL; vLight = vLight->next ) {
    367 			if ( vLight->scissorRect.IsEmpty() ) {
    368 				continue;
    369 			}
    370 			if ( vLight->entityInteractionState != NULL ) {
    371 				// new code path, everything was done in AddLight
    372 				if ( vLight->entityInteractionState[entityIndex] == viewLight_t::INTERACTION_YES ) {
    373 					contactedLights[numContactedLights] = vLight;
    374 					staticInteractions[numContactedLights] = world->interactionTable[vLight->lightDef->index * world->interactionTableWidth + entityIndex];
    375 					if ( ++numContactedLights == MAX_CONTACTED_LIGHTS ) {
    376 						break;
    377 					}
    378 				}
    379 				continue;
    380 			}
    381 
    382 			const idRenderLightLocal * lightDef = vLight->lightDef;
    383 
    384 			if ( !lightDef->globalLightBounds.IntersectsBounds( entityDef->globalReferenceBounds ) ) {
    385 				continue;
    386 			}
    387 
    388 			if ( R_CullModelBoundsToLight( lightDef, entityDef->localReferenceBounds, entityDef->modelRenderMatrix ) ) {
    389 				continue;
    390 			}
    391 
    392 			if ( !modelIsVisible ) {
    393 				// some lights have their center of projection outside the world
    394 				if ( lightDef->areaNum != -1 ) {
    395 					// if no part of the model is in an area that is connected to
    396 					// the light center (it is behind a solid, closed door), we can ignore it
    397 					bool areasConnected = false;
    398 					for ( areaReference_t *ref = entityDef->entityRefs; ref != NULL; ref = ref->ownerNext ) {
    399 						if ( world->AreasAreConnected( lightDef->areaNum, ref->area->areaNum, PS_BLOCK_VIEW ) ) {
    400 							areasConnected = true;
    401 							break;
    402 						}
    403 					}
    404 					if ( areasConnected == false ) {
    405 						// can't possibly be seen or shadowed
    406 						continue;
    407 					}
    408 				}
    409 
    410 				// check more precisely for shadow visibility
    411 				idBounds shadowBounds;
    412 				R_ShadowBounds( entityDef->globalReferenceBounds, lightDef->globalLightBounds, lightDef->globalLightOrigin, shadowBounds );
    413 
    414 				// this doesn't say that the shadow can't effect anything, only that it can't
    415 				// effect anything in the view
    416 				if ( idRenderMatrix::CullBoundsToMVP( viewDef->worldSpace.mvp, shadowBounds ) ) {
    417 					continue;
    418 				}
    419 			}
    420 			contactedLights[numContactedLights] = vLight;
    421 			staticInteractions[numContactedLights] = world->interactionTable[vLight->lightDef->index * world->interactionTableWidth + entityIndex];
    422 			if ( ++numContactedLights == MAX_CONTACTED_LIGHTS ) {
    423 				break;
    424 			}
    425 		}
    426 	}
    427 
    428 	// if we aren't visible and none of the shadows stretch into the view,
    429 	// we don't need to do anything else
    430 	if ( !modelIsVisible && numContactedLights == 0 ) {
    431 		return;
    432 	}
    433 
    434 	//---------------------------
    435 	// create a dynamic model if the geometry isn't static
    436 	//---------------------------
    437 	idRenderModel * model = R_EntityDefDynamicModel( entityDef );
    438 	if ( model == NULL || model->NumSurfaces() <= 0 ) {
    439 		return;
    440 	}
    441 
    442 	// add the lightweight blood decal surfaces if the model is directly visible
    443 	if ( modelIsVisible ) {
    444 		assert( !vEntity->scissorRect.IsEmpty() );
    445 
    446 		if ( entityDef->decals != NULL && !r_skipDecals.GetBool() ) {
    447 			entityDef->decals->CreateDeferredDecals( model );
    448 
    449 			unsigned int numDrawSurfs = entityDef->decals->GetNumDecalDrawSurfs();
    450 			for ( unsigned int i = 0; i < numDrawSurfs; i++ ) {
    451 				drawSurf_t * decalDrawSurf = entityDef->decals->CreateDecalDrawSurf( vEntity, i );
    452 				if ( decalDrawSurf != NULL ) {
    453 					decalDrawSurf->linkChain = NULL;
    454 					decalDrawSurf->nextOnLight = vEntity->drawSurfs;
    455 					vEntity->drawSurfs = decalDrawSurf;
    456 				}
    457 			}
    458 		}
    459 
    460 		if ( entityDef->overlays != NULL && !r_skipOverlays.GetBool() ) {
    461 			entityDef->overlays->CreateDeferredOverlays( model );
    462 
    463 			unsigned int numDrawSurfs = entityDef->overlays->GetNumOverlayDrawSurfs();
    464 			for ( unsigned int i = 0; i < numDrawSurfs; i++ ) {
    465 				drawSurf_t * overlayDrawSurf = entityDef->overlays->CreateOverlayDrawSurf( vEntity, model, i );
    466 				if ( overlayDrawSurf != NULL ) {
    467 					overlayDrawSurf->linkChain = NULL;
    468 					overlayDrawSurf->nextOnLight = vEntity->drawSurfs;
    469 					vEntity->drawSurfs = overlayDrawSurf;
    470 				}
    471 			}
    472 		}
    473 	}
    474 
    475 	//---------------------------
    476 	// copy matrix related stuff for back-end use
    477 	// and setup a render matrix for faster culling
    478 	//---------------------------
    479 	vEntity->modelDepthHack = renderEntity->modelDepthHack;
    480 	vEntity->weaponDepthHack = renderEntity->weaponDepthHack;
    481 	vEntity->skipMotionBlur = renderEntity->skipMotionBlur;
    482 
    483 	memcpy( vEntity->modelMatrix, entityDef->modelMatrix, sizeof( vEntity->modelMatrix ) );
    484 	R_MatrixMultiply( entityDef->modelMatrix, viewDef->worldSpace.modelViewMatrix, vEntity->modelViewMatrix );
    485 
    486 	idRenderMatrix viewMat;
    487 	idRenderMatrix::Transpose( *(idRenderMatrix *)vEntity->modelViewMatrix, viewMat );
    488 	idRenderMatrix::Multiply( viewDef->projectionRenderMatrix, viewMat, vEntity->mvp );
    489 	if ( renderEntity->weaponDepthHack ) {
    490 		idRenderMatrix::ApplyDepthHack( vEntity->mvp );
    491 	}
    492 	if ( renderEntity->modelDepthHack != 0.0f ) {
    493 		idRenderMatrix::ApplyModelDepthHack( vEntity->mvp, renderEntity->modelDepthHack );
    494 	}
    495 
    496 	// local light and view origins are used to determine if the view is definitely outside
    497 	// an extruded shadow volume, which means we can skip drawing the end caps
    498 	idVec3 localViewOrigin;
    499 	R_GlobalPointToLocal( vEntity->modelMatrix, viewDef->renderView.vieworg, localViewOrigin );
    500 
    501 	//---------------------------
    502 	// add all the model surfaces
    503 	//---------------------------
    504 	for ( int surfaceNum = 0; surfaceNum < model->NumSurfaces(); surfaceNum++ ) {
    505 		const modelSurface_t *surf = model->Surface( surfaceNum );
    506 
    507 		// for debugging, only show a single surface at a time
    508 		if ( r_singleSurface.GetInteger() >= 0 && surfaceNum != r_singleSurface.GetInteger() ) {
    509 			continue;
    510 		}
    511 
    512 		srfTriangles_t * tri = surf->geometry;
    513 		if ( tri == NULL ) {
    514 			continue;
    515 		}
    516 		if ( tri->numIndexes == NULL ) {
    517 			continue;		// happens for particles
    518 		}
    519 		const idMaterial * shader = surf->shader;
    520 		if ( shader == NULL ) {
    521 			continue;
    522 		}
    523 		if ( !shader->IsDrawn() ) {
    524 			continue;		// collision hulls, etc
    525 		}
    526 
    527 		// RemapShaderBySkin
    528 		if ( entityDef->parms.customShader != NULL ) {
    529 			// this is sort of a hack, but causes deformed surfaces to map to empty surfaces,
    530 			// so the item highlight overlay doesn't highlight the autosprite surface
    531 			if ( shader->Deform() ) {
    532 				continue;
    533 			}
    534 			shader = entityDef->parms.customShader;
    535 		} else if ( entityDef->parms.customSkin ) {
    536 			shader = entityDef->parms.customSkin->RemapShaderBySkin( shader );
    537 			if ( shader == NULL ) {
    538 				continue;
    539 			}
    540 			if ( !shader->IsDrawn() ) {
    541 				continue;
    542 			}
    543 		}
    544 
    545 		// optionally override with the renderView->globalMaterial
    546 		if ( tr.primaryRenderView.globalMaterial != NULL ) {
    547 			shader = tr.primaryRenderView.globalMaterial;
    548 		}
    549 
    550 		SCOPED_PROFILE_EVENT( shader->GetName() );
    551 
    552 		// debugging tool to make sure we have the correct pre-calculated bounds
    553 		if ( r_checkBounds.GetBool() ) {
    554 			for ( int j = 0; j < tri->numVerts; j++ ) {
    555 				int k;
    556 				for ( k = 0; k < 3; k++ ) {
    557 					if ( tri->verts[j].xyz[k] > tri->bounds[1][k] + CHECK_BOUNDS_EPSILON
    558 						|| tri->verts[j].xyz[k] < tri->bounds[0][k] - CHECK_BOUNDS_EPSILON ) {
    559 						common->Printf( "bad tri->bounds on %s:%s\n", entityDef->parms.hModel->Name(), shader->GetName() );
    560 						break;
    561 					}
    562 					if ( tri->verts[j].xyz[k] > entityDef->localReferenceBounds[1][k] + CHECK_BOUNDS_EPSILON
    563 						|| tri->verts[j].xyz[k] < entityDef->localReferenceBounds[0][k] - CHECK_BOUNDS_EPSILON ) {
    564 						common->Printf( "bad referenceBounds on %s:%s\n", entityDef->parms.hModel->Name(), shader->GetName() );
    565 						break;
    566 					}
    567 				}
    568 				if ( k != 3 ) {
    569 					break;
    570 				}
    571 			}
    572 		}
    573 
    574 		// view frustum culling for the precise surface bounds, which is tighter
    575 		// than the entire entity reference bounds
    576 		// If the entire model wasn't visible, there is no need to check the
    577 		// individual surfaces.
    578 		const bool surfaceDirectlyVisible = modelIsVisible && !idRenderMatrix::CullBoundsToMVP( vEntity->mvp, tri->bounds );
    579 		const bool gpuSkinned = ( tri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() );
    580 
    581 		//--------------------------
    582 		// base drawing surface
    583 		//--------------------------
    584 		drawSurf_t * baseDrawSurf = NULL;
    585 		if ( surfaceDirectlyVisible ) {
    586 			// make sure we have an ambient cache and all necessary normals / tangents
    587 			if ( !vertexCache.CacheIsCurrent( tri->indexCache ) ) {
    588 				tri->indexCache = vertexCache.AllocIndex( tri->indexes, ALIGN( tri->numIndexes * sizeof( triIndex_t ), INDEX_CACHE_ALIGN ) );
    589 			}
    590 			if ( !vertexCache.CacheIsCurrent( tri->ambientCache ) ) {
    591 				// we are going to use it for drawing, so make sure we have the tangents and normals
    592 				if ( shader->ReceivesLighting() && !tri->tangentsCalculated ) {
    593 					assert( tri->staticModelWithJoints == NULL );
    594 					R_DeriveTangents( tri );
    595 					assert( false );	// this should no longer be hit
    596 				}
    597 				tri->ambientCache = vertexCache.AllocVertex( tri->verts, ALIGN( tri->numVerts * sizeof( idDrawVert ), VERTEX_CACHE_ALIGN ) );
    598 			}
    599 
    600 			// add the surface for drawing
    601 			// we can re-use some of the values for light interaction surfaces			
    602 			baseDrawSurf = (drawSurf_t *)R_FrameAlloc( sizeof( *baseDrawSurf ), FRAME_ALLOC_DRAW_SURFACE );
    603 			baseDrawSurf->frontEndGeo = tri;
    604 			baseDrawSurf->space = vEntity;
    605 			baseDrawSurf->scissorRect = vEntity->scissorRect;
    606 			baseDrawSurf->extraGLState = 0;
    607 			baseDrawSurf->renderZFail = 0;
    608 
    609 			R_SetupDrawSurfShader( baseDrawSurf, shader, renderEntity );
    610 
    611 			// Check for deformations (eyeballs, flares, etc)
    612 			const deform_t shaderDeform = shader->Deform();
    613 			if ( shaderDeform != DFRM_NONE ) {
    614 				drawSurf_t * deformDrawSurf = R_DeformDrawSurf( baseDrawSurf );
    615 				if ( deformDrawSurf != NULL ) {
    616 					// any deforms may have created multiple draw surfaces
    617 					for ( drawSurf_t * surf = deformDrawSurf, * next = NULL; surf != NULL; surf = next ) {
    618 						next = surf->nextOnLight;
    619 
    620 						surf->linkChain = NULL;
    621 						surf->nextOnLight = vEntity->drawSurfs;
    622 						vEntity->drawSurfs = surf;
    623 					}
    624 				}
    625 			}
    626 
    627 			// Most deform source surfaces do not need to be rendered.
    628 			// However, particles are rendered in conjunction with the source surface.
    629 			if ( shaderDeform == DFRM_NONE || shaderDeform == DFRM_PARTICLE || shaderDeform == DFRM_PARTICLE2 ) {
    630 				// copy verts and indexes to this frame's hardware memory if they aren't already there
    631 				if ( !vertexCache.CacheIsCurrent( tri->ambientCache ) ) {
    632 					tri->ambientCache = vertexCache.AllocVertex( tri->verts, ALIGN( tri->numVerts * sizeof( tri->verts[0] ), VERTEX_CACHE_ALIGN ) );
    633 				}
    634 				if ( !vertexCache.CacheIsCurrent( tri->indexCache ) ) {
    635 					tri->indexCache = vertexCache.AllocIndex( tri->indexes, ALIGN( tri->numIndexes * sizeof( tri->indexes[0] ), INDEX_CACHE_ALIGN ) );
    636 				}
    637 
    638 				R_SetupDrawSurfJoints( baseDrawSurf, tri, shader );
    639 
    640 				baseDrawSurf->numIndexes = tri->numIndexes;
    641 				baseDrawSurf->ambientCache = tri->ambientCache;
    642 				baseDrawSurf->indexCache = tri->indexCache;
    643 				baseDrawSurf->shadowCache = 0;
    644 
    645 				baseDrawSurf->linkChain = NULL;		// link to the view
    646 				baseDrawSurf->nextOnLight = vEntity->drawSurfs;
    647 				vEntity->drawSurfs = baseDrawSurf;
    648 			}
    649 		}
    650 
    651 		//----------------------------------------
    652 		// add all light interactions
    653 		//----------------------------------------
    654 		for ( int contactedLight = 0; contactedLight < numContactedLights; contactedLight++ ) {
    655 			viewLight_t * vLight = contactedLights[contactedLight];
    656 			const idRenderLightLocal * lightDef = vLight->lightDef;
    657 			const idInteraction * interaction = staticInteractions[contactedLight];
    658 
    659 			// check for a static interaction
    660 			surfaceInteraction_t *surfInter = NULL;
    661 			if ( interaction > INTERACTION_EMPTY && interaction->staticInteraction ) {
    662 				// we have a static interaction that was calculated accurately
    663 				assert( model->NumSurfaces() == interaction->numSurfaces );
    664 				surfInter = &interaction->surfaces[surfaceNum];
    665 			} else {
    666 				// try to do a more precise cull of this model surface to the light
    667 				if ( R_CullModelBoundsToLight( lightDef, tri->bounds, entityDef->modelRenderMatrix ) ) {
    668 					continue;
    669 				}
    670 			}
    671 			
    672 			// "invisible ink" lights and shaders (imp spawn drawing on walls, etc)
    673 			if ( shader->Spectrum() != lightDef->lightShader->Spectrum() ) {
    674 				continue;
    675 			}
    676 
    677 			// Calculate the local light origin to determine if the view is inside the shadow
    678 			// projection and to calculate the triangle facing for dynamic shadow volumes.
    679 			idVec3 localLightOrigin;
    680 			R_GlobalPointToLocal( vEntity->modelMatrix, lightDef->globalLightOrigin, localLightOrigin );
    681 
    682 			//--------------------------
    683 			// surface light interactions
    684 			//--------------------------
    685 
    686 			dynamicShadowVolumeParms_t * dynamicShadowParms = NULL;
    687 
    688 			if ( addInteractions && surfaceDirectlyVisible && shader->ReceivesLighting() ) {
    689 				// static interactions can commonly find that no triangles from a surface
    690 				// contact the light, even when the total model does
    691 				if ( surfInter == NULL || surfInter->lightTrisIndexCache > 0 ) {
    692 					// create a drawSurf for this interaction
    693 					drawSurf_t * lightDrawSurf = (drawSurf_t *)R_FrameAlloc( sizeof( *lightDrawSurf ), FRAME_ALLOC_DRAW_SURFACE );
    694 
    695 					if ( surfInter != NULL ) {
    696 						// optimized static interaction
    697 						lightDrawSurf->numIndexes = surfInter->numLightTrisIndexes;
    698 						lightDrawSurf->indexCache = surfInter->lightTrisIndexCache;
    699 					} else {
    700 						// throw the entire source surface at it without any per-triangle culling
    701 						lightDrawSurf->numIndexes = tri->numIndexes;
    702 						lightDrawSurf->indexCache = tri->indexCache;
    703 
    704 						// optionally cull the triangles to the light volume
    705 						if ( r_cullDynamicLightTriangles.GetBool() ) {
    706 
    707 							vertCacheHandle_t lightIndexCache = vertexCache.AllocIndex( NULL, ALIGN( lightDrawSurf->numIndexes * sizeof( triIndex_t ), INDEX_CACHE_ALIGN ) );
    708 							if ( vertexCache.CacheIsCurrent( lightIndexCache ) ) {
    709 								lightDrawSurf->indexCache = lightIndexCache;
    710 
    711 								dynamicShadowParms = (dynamicShadowVolumeParms_t *)R_FrameAlloc( sizeof( dynamicShadowParms[0] ), FRAME_ALLOC_SHADOW_VOLUME_PARMS );
    712 
    713 								dynamicShadowParms->verts = tri->verts;
    714 								dynamicShadowParms->numVerts = tri->numVerts;
    715 								dynamicShadowParms->indexes = tri->indexes;
    716 								dynamicShadowParms->numIndexes = tri->numIndexes;
    717 								dynamicShadowParms->silEdges = tri->silEdges;
    718 								dynamicShadowParms->numSilEdges = tri->numSilEdges;
    719 								dynamicShadowParms->joints = gpuSkinned ? tri->staticModelWithJoints->jointsInverted : NULL;
    720 								dynamicShadowParms->numJoints = gpuSkinned ? tri->staticModelWithJoints->numInvertedJoints : 0;
    721 								dynamicShadowParms->triangleBounds = tri->bounds;
    722 								dynamicShadowParms->triangleMVP = vEntity->mvp;
    723 								dynamicShadowParms->localLightOrigin = localLightOrigin;
    724 								dynamicShadowParms->localViewOrigin = localViewOrigin;
    725 								idRenderMatrix::Multiply( vLight->lightDef->baseLightProject, entityDef->modelRenderMatrix, dynamicShadowParms->localLightProject );
    726 								dynamicShadowParms->zNear = znear;
    727 								dynamicShadowParms->lightZMin = vLight->scissorRect.zmin;
    728 								dynamicShadowParms->lightZMax = vLight->scissorRect.zmax;
    729 								dynamicShadowParms->cullShadowTrianglesToLight = false;
    730 								dynamicShadowParms->forceShadowCaps = false;
    731 								dynamicShadowParms->useShadowPreciseInsideTest = false;
    732 								dynamicShadowParms->useShadowDepthBounds = false;
    733 								dynamicShadowParms->tempFacing = NULL;
    734 								dynamicShadowParms->tempCulled = NULL;
    735 								dynamicShadowParms->tempVerts = NULL;
    736 								dynamicShadowParms->indexBuffer = NULL;
    737 								dynamicShadowParms->shadowIndices = NULL;
    738 								dynamicShadowParms->maxShadowIndices = 0;
    739 								dynamicShadowParms->numShadowIndices = NULL;
    740 								dynamicShadowParms->lightIndices = (triIndex_t *)vertexCache.MappedIndexBuffer( lightIndexCache );
    741 								dynamicShadowParms->maxLightIndices = lightDrawSurf->numIndexes;
    742 								dynamicShadowParms->numLightIndices = &lightDrawSurf->numIndexes;
    743 								dynamicShadowParms->renderZFail = NULL;
    744 								dynamicShadowParms->shadowZMin = NULL;
    745 								dynamicShadowParms->shadowZMax = NULL;
    746 								dynamicShadowParms->shadowVolumeState = & lightDrawSurf->shadowVolumeState;
    747 
    748 								lightDrawSurf->shadowVolumeState = SHADOWVOLUME_UNFINISHED;
    749 
    750 								dynamicShadowParms->next = vEntity->dynamicShadowVolumes;
    751 								vEntity->dynamicShadowVolumes = dynamicShadowParms;
    752 							}
    753 						}
    754 					}
    755 					lightDrawSurf->ambientCache = tri->ambientCache;
    756 					lightDrawSurf->shadowCache = 0;
    757 					lightDrawSurf->frontEndGeo = tri;
    758 					lightDrawSurf->space = vEntity;
    759 					lightDrawSurf->material = shader;
    760 					lightDrawSurf->extraGLState = 0;
    761 					lightDrawSurf->scissorRect = vLight->scissorRect; // interactionScissor;
    762 					lightDrawSurf->sort = 0.0f;
    763 					lightDrawSurf->renderZFail = 0;
    764 					lightDrawSurf->shaderRegisters = baseDrawSurf->shaderRegisters;
    765 
    766 					R_SetupDrawSurfJoints( lightDrawSurf, tri, shader );
    767 
    768 					// Determine which linked list to add the light surface to.
    769 					// There will only be localSurfaces if the light casts shadows and
    770 					// there are surfaces with NOSELFSHADOW.
    771 					if ( shader->Coverage() == MC_TRANSLUCENT ) {
    772 						lightDrawSurf->linkChain = &vLight->translucentInteractions;
    773 					} else if ( !lightDef->parms.noShadows && shader->TestMaterialFlag( MF_NOSELFSHADOW ) ) {
    774 						lightDrawSurf->linkChain = &vLight->localInteractions;
    775 					} else {
    776 						lightDrawSurf->linkChain = &vLight->globalInteractions;
    777 					}
    778 					lightDrawSurf->nextOnLight = vEntity->drawSurfs;
    779 					vEntity->drawSurfs = lightDrawSurf;
    780 				}
    781 			}
    782 
    783 			//--------------------------
    784 			// surface shadows
    785 			//--------------------------
    786 
    787 			if ( !shader->SurfaceCastsShadow() ) {
    788 				continue;
    789 			}
    790 			if ( !lightDef->LightCastsShadows() ) {
    791 				continue;
    792 			}
    793 			if ( tri->silEdges == NULL ) {
    794 				continue;		// can happen for beam models (shouldn't use a shadow casting material, though...)
    795 			}
    796 
    797 			// if the static shadow does not have any shadows
    798 			if ( surfInter != NULL && surfInter->numShadowIndexes == 0 ) {
    799 				continue;
    800 			}
    801 
    802 			// some entities, like view weapons, don't cast any shadows
    803 			if ( entityDef->parms.noShadow ) {
    804 				continue;
    805 			}
    806 
    807 			// No shadow if it's suppressed for this light.
    808 			if ( entityDef->parms.suppressShadowInLightID && entityDef->parms.suppressShadowInLightID == lightDef->parms.lightId ) {
    809 				continue;
    810 			}
    811 
    812 			if ( lightDef->parms.prelightModel && lightDef->lightHasMoved == false &&
    813 					entityDef->parms.hModel->IsStaticWorldModel() && !r_skipPrelightShadows.GetBool() ) {
    814 				// static light / world model shadow interacitons
    815 				// are always captured in the prelight shadow volume
    816 				continue;
    817 			}
    818 
    819 			// If the shadow is drawn (or translucent), but the model isn't, we must include the shadow caps
    820 			// because we may be able to see into the shadow volume even though the view is outside it.
    821 			// This happens for the player world weapon and possibly some animations in multiplayer.
    822 			const bool forceShadowCaps = !addInteractions || r_forceShadowCaps.GetBool();
    823 
    824 			drawSurf_t * shadowDrawSurf = (drawSurf_t *)R_FrameAlloc( sizeof( *shadowDrawSurf ), FRAME_ALLOC_DRAW_SURFACE );
    825 
    826 			if ( surfInter != NULL ) {
    827 				shadowDrawSurf->numIndexes = 0;
    828 				shadowDrawSurf->indexCache = surfInter->shadowIndexCache;
    829 				shadowDrawSurf->shadowCache = tri->shadowCache;
    830 				shadowDrawSurf->scissorRect = vLight->scissorRect;		// default to the light scissor and light depth bounds
    831 				shadowDrawSurf->shadowVolumeState = SHADOWVOLUME_DONE;	// assume the shadow volume is done in case r_skipStaticShadows is set
    832 
    833 				if ( !r_skipStaticShadows.GetBool() ) {
    834 					staticShadowVolumeParms_t * staticShadowParms = (staticShadowVolumeParms_t *)R_FrameAlloc( sizeof( staticShadowParms[0] ), FRAME_ALLOC_SHADOW_VOLUME_PARMS );
    835 
    836 					staticShadowParms->verts = tri->staticShadowVertexes;
    837 					staticShadowParms->numVerts = tri->numVerts * 2;
    838 					staticShadowParms->indexes = surfInter->shadowIndexes;
    839 					staticShadowParms->numIndexes = surfInter->numShadowIndexes;
    840 					staticShadowParms->numShadowIndicesWithCaps = surfInter->numShadowIndexes;
    841 					staticShadowParms->numShadowIndicesNoCaps = surfInter->numShadowIndexesNoCaps;
    842 					staticShadowParms->triangleBounds = tri->bounds;
    843 					staticShadowParms->triangleMVP = vEntity->mvp;
    844 					staticShadowParms->localLightOrigin = localLightOrigin;
    845 					staticShadowParms->localViewOrigin = localViewOrigin;
    846 					staticShadowParms->zNear = znear;
    847 					staticShadowParms->lightZMin = vLight->scissorRect.zmin;
    848 					staticShadowParms->lightZMax = vLight->scissorRect.zmax;
    849 					staticShadowParms->forceShadowCaps = forceShadowCaps;
    850 					staticShadowParms->useShadowPreciseInsideTest = r_useShadowPreciseInsideTest.GetBool();
    851 					staticShadowParms->useShadowDepthBounds = r_useShadowDepthBounds.GetBool();
    852 					staticShadowParms->numShadowIndices = & shadowDrawSurf->numIndexes;
    853 					staticShadowParms->renderZFail = & shadowDrawSurf->renderZFail;
    854 					staticShadowParms->shadowZMin = & shadowDrawSurf->scissorRect.zmin;
    855 					staticShadowParms->shadowZMax = & shadowDrawSurf->scissorRect.zmax;
    856 					staticShadowParms->shadowVolumeState = & shadowDrawSurf->shadowVolumeState;
    857 
    858 					shadowDrawSurf->shadowVolumeState = SHADOWVOLUME_UNFINISHED;
    859 
    860 					staticShadowParms->next = vEntity->staticShadowVolumes;
    861 					vEntity->staticShadowVolumes = staticShadowParms;
    862 				}
    863 
    864 			} else {
    865 				// When CPU skinning the dynamic shadow verts of a dynamic model may not have been copied to buffer memory yet.
    866 				if ( !vertexCache.CacheIsCurrent( tri->shadowCache ) ) {
    867 					assert( !gpuSkinned );	// the shadow cache should be static when using GPU skinning
    868 					// Extracts just the xyz values from a set of full size drawverts, and
    869 					// duplicates them with w set to 0 and 1 for the vertex program to project.
    870 					// This is constant for any number of lights, the vertex program takes care
    871 					// of projecting the verts to infinity for a particular light.
    872 					tri->shadowCache = vertexCache.AllocVertex( NULL, ALIGN( tri->numVerts * 2 * sizeof( idShadowVert ), VERTEX_CACHE_ALIGN ) );
    873 					idShadowVert * shadowVerts = (idShadowVert *)vertexCache.MappedVertexBuffer( tri->shadowCache );
    874 					idShadowVert::CreateShadowCache( shadowVerts, tri->verts, tri->numVerts );
    875 				}
    876 
    877 				const int maxShadowVolumeIndexes = tri->numSilEdges * 6 + tri->numIndexes * 2;
    878 
    879 				shadowDrawSurf->numIndexes = 0;
    880 				shadowDrawSurf->indexCache = vertexCache.AllocIndex( NULL, ALIGN( maxShadowVolumeIndexes * sizeof( triIndex_t ), INDEX_CACHE_ALIGN ) );
    881 				shadowDrawSurf->shadowCache = tri->shadowCache;
    882 				shadowDrawSurf->scissorRect = vLight->scissorRect;		// default to the light scissor and light depth bounds
    883 				shadowDrawSurf->shadowVolumeState = SHADOWVOLUME_DONE;	// assume the shadow volume is done in case the index cache allocation failed
    884 
    885 				// if the index cache was successfully allocated then setup the parms to create a shadow volume in parallel
    886 				if ( vertexCache.CacheIsCurrent( shadowDrawSurf->indexCache ) && !r_skipDynamicShadows.GetBool() ) {
    887 
    888 					// if the parms were not already allocated for culling interaction triangles to the light frustum
    889 					if ( dynamicShadowParms == NULL ) {
    890 						dynamicShadowParms = (dynamicShadowVolumeParms_t *)R_FrameAlloc( sizeof( dynamicShadowParms[0] ), FRAME_ALLOC_SHADOW_VOLUME_PARMS );
    891 					} else {
    892 						// the shadow volume will be rendered first so when the interaction surface is drawn the triangles have been culled for sure
    893 						*dynamicShadowParms->shadowVolumeState = SHADOWVOLUME_DONE;
    894 					}
    895 
    896 					dynamicShadowParms->verts = tri->verts;
    897 					dynamicShadowParms->numVerts = tri->numVerts;
    898 					dynamicShadowParms->indexes = tri->indexes;
    899 					dynamicShadowParms->numIndexes = tri->numIndexes;
    900 					dynamicShadowParms->silEdges = tri->silEdges;
    901 					dynamicShadowParms->numSilEdges = tri->numSilEdges;
    902 					dynamicShadowParms->joints = gpuSkinned ? tri->staticModelWithJoints->jointsInverted : NULL;
    903 					dynamicShadowParms->numJoints = gpuSkinned ? tri->staticModelWithJoints->numInvertedJoints : 0;
    904 					dynamicShadowParms->triangleBounds = tri->bounds;
    905 					dynamicShadowParms->triangleMVP = vEntity->mvp;
    906 					dynamicShadowParms->localLightOrigin = localLightOrigin;
    907 					dynamicShadowParms->localViewOrigin = localViewOrigin;
    908 					idRenderMatrix::Multiply( vLight->lightDef->baseLightProject, entityDef->modelRenderMatrix, dynamicShadowParms->localLightProject );
    909 					dynamicShadowParms->zNear = znear;
    910 					dynamicShadowParms->lightZMin = vLight->scissorRect.zmin;
    911 					dynamicShadowParms->lightZMax = vLight->scissorRect.zmax;
    912 					dynamicShadowParms->cullShadowTrianglesToLight = r_cullDynamicShadowTriangles.GetBool();
    913 					dynamicShadowParms->forceShadowCaps = forceShadowCaps;
    914 					dynamicShadowParms->useShadowPreciseInsideTest = r_useShadowPreciseInsideTest.GetBool();
    915 					dynamicShadowParms->useShadowDepthBounds = r_useShadowDepthBounds.GetBool();
    916 					dynamicShadowParms->tempFacing = NULL;
    917 					dynamicShadowParms->tempCulled = NULL;
    918 					dynamicShadowParms->tempVerts = NULL;
    919 					dynamicShadowParms->indexBuffer = NULL;
    920 					dynamicShadowParms->shadowIndices = (triIndex_t *)vertexCache.MappedIndexBuffer( shadowDrawSurf->indexCache );
    921 					dynamicShadowParms->maxShadowIndices = maxShadowVolumeIndexes;
    922 					dynamicShadowParms->numShadowIndices = & shadowDrawSurf->numIndexes;
    923 					// dynamicShadowParms->lightIndices may have already been set for the interaction surface
    924 					// dynamicShadowParms->maxLightIndices may have already been set for the interaction surface
    925 					// dynamicShadowParms->numLightIndices may have already been set for the interaction surface
    926 					dynamicShadowParms->renderZFail = & shadowDrawSurf->renderZFail;
    927 					dynamicShadowParms->shadowZMin = & shadowDrawSurf->scissorRect.zmin;
    928 					dynamicShadowParms->shadowZMax = & shadowDrawSurf->scissorRect.zmax;
    929 					dynamicShadowParms->shadowVolumeState = & shadowDrawSurf->shadowVolumeState;
    930 
    931 					shadowDrawSurf->shadowVolumeState = SHADOWVOLUME_UNFINISHED;
    932 
    933 					// if the parms we not already linked for culling interaction triangles to the light frustum
    934 					if ( dynamicShadowParms->lightIndices == NULL ) {
    935 						dynamicShadowParms->next = vEntity->dynamicShadowVolumes;
    936 						vEntity->dynamicShadowVolumes = dynamicShadowParms;
    937 					}
    938 
    939 					tr.pc.c_createShadowVolumes++;
    940 				}
    941 			}
    942 
    943 			assert( vertexCache.CacheIsCurrent( shadowDrawSurf->shadowCache ) );
    944 			assert( vertexCache.CacheIsCurrent( shadowDrawSurf->indexCache ) );
    945 
    946 			shadowDrawSurf->ambientCache = 0;
    947 			shadowDrawSurf->frontEndGeo = NULL;
    948 			shadowDrawSurf->space = vEntity;
    949 			shadowDrawSurf->material = NULL;
    950 			shadowDrawSurf->extraGLState = 0;
    951 			shadowDrawSurf->sort = 0.0f;
    952 			shadowDrawSurf->shaderRegisters = NULL;
    953 
    954 			R_SetupDrawSurfJoints( shadowDrawSurf, tri, NULL );
    955 
    956 			// determine which linked list to add the shadow surface to
    957 			shadowDrawSurf->linkChain = shader->TestMaterialFlag( MF_NOSELFSHADOW ) ? &vLight->localShadows : &vLight->globalShadows;
    958 			shadowDrawSurf->nextOnLight = vEntity->drawSurfs;
    959 			vEntity->drawSurfs = shadowDrawSurf;
    960 		}
    961 	}
    962 }
    963 
    964 REGISTER_PARALLEL_JOB( R_AddSingleModel, "R_AddSingleModel" );
    965 
    966 /*
    967 =================
    968 R_LinkDrawSurfToView
    969 
    970 Als called directly by GuiModel
    971 =================
    972 */
    973 void R_LinkDrawSurfToView( drawSurf_t * drawSurf, viewDef_t * viewDef ) {
    974 	// if it doesn't fit, resize the list
    975 	if ( viewDef->numDrawSurfs == viewDef->maxDrawSurfs ) {
    976 		drawSurf_t **old = viewDef->drawSurfs;
    977 		int count;
    978 
    979 		if ( viewDef->maxDrawSurfs == 0 ) {
    980 			viewDef->maxDrawSurfs = INITIAL_DRAWSURFS;
    981 			count = 0;
    982 		} else {
    983 			count = viewDef->maxDrawSurfs * sizeof( viewDef->drawSurfs[0] );
    984 			viewDef->maxDrawSurfs *= 2;
    985 		}
    986 		viewDef->drawSurfs = (drawSurf_t **)R_FrameAlloc( viewDef->maxDrawSurfs * sizeof( viewDef->drawSurfs[0] ), FRAME_ALLOC_DRAW_SURFACE_POINTER );
    987 		memcpy( viewDef->drawSurfs, old, count );
    988 	}
    989 	
    990 	viewDef->drawSurfs[viewDef->numDrawSurfs] = drawSurf;
    991 	viewDef->numDrawSurfs++;
    992 }
    993 
    994 /*
    995 ===================
    996 R_AddModels
    997 
    998 The end result of running this is the addition of drawSurf_t to the
    999 tr.viewDef->drawSurfs[] array and light link chains, along with
   1000 frameData and vertexCache allocations to support the drawSurfs.
   1001 ===================
   1002 */
   1003 void R_AddModels() {
   1004 	SCOPED_PROFILE_EVENT( "R_AddModels" );
   1005 
   1006 	tr.viewDef->viewEntitys = R_SortViewEntities( tr.viewDef->viewEntitys );
   1007 
   1008 	//-------------------------------------------------
   1009 	// Go through each view entity that is either visible to the view, or to
   1010 	// any light that intersects the view (for shadows).
   1011 	//-------------------------------------------------
   1012 
   1013 	if ( r_useParallelAddModels.GetBool() ) {
   1014 		for ( viewEntity_t * vEntity = tr.viewDef->viewEntitys; vEntity != NULL; vEntity = vEntity->next ) {
   1015 			tr.frontEndJobList->AddJob( (jobRun_t)R_AddSingleModel, vEntity );
   1016 		}
   1017 		tr.frontEndJobList->Submit();
   1018 		tr.frontEndJobList->Wait();
   1019 	} else {
   1020 		for ( viewEntity_t * vEntity = tr.viewDef->viewEntitys; vEntity != NULL; vEntity = vEntity->next ) {
   1021 			R_AddSingleModel( vEntity );
   1022 		}
   1023 	}
   1024 
   1025 	//-------------------------------------------------
   1026 	// Kick off jobs to setup static and dynamic shadow volumes.
   1027 	//-------------------------------------------------
   1028 
   1029 	if ( r_useParallelAddShadows.GetInteger() == 1 ) {
   1030 		for ( viewEntity_t * vEntity = tr.viewDef->viewEntitys; vEntity != NULL; vEntity = vEntity->next ) {
   1031 			for ( staticShadowVolumeParms_t * shadowParms = vEntity->staticShadowVolumes; shadowParms != NULL; shadowParms = shadowParms->next ) {
   1032 				tr.frontEndJobList->AddJob( (jobRun_t)StaticShadowVolumeJob, shadowParms );
   1033 			}
   1034 			for ( dynamicShadowVolumeParms_t * shadowParms = vEntity->dynamicShadowVolumes; shadowParms != NULL; shadowParms = shadowParms->next ) {
   1035 				tr.frontEndJobList->AddJob( (jobRun_t)DynamicShadowVolumeJob, shadowParms );
   1036 			}
   1037 			vEntity->staticShadowVolumes = NULL;
   1038 			vEntity->dynamicShadowVolumes = NULL;
   1039 		}
   1040 		tr.frontEndJobList->Submit();
   1041 		// wait here otherwise the shadow volume index buffer may be unmapped before all shadow volumes have been constructed
   1042 		tr.frontEndJobList->Wait();
   1043 	} else {
   1044 		int start = Sys_Microseconds();
   1045 
   1046 		for ( viewEntity_t * vEntity = tr.viewDef->viewEntitys; vEntity != NULL; vEntity = vEntity->next ) {
   1047 			for ( staticShadowVolumeParms_t * shadowParms = vEntity->staticShadowVolumes; shadowParms != NULL; shadowParms = shadowParms->next ) {
   1048 				StaticShadowVolumeJob( shadowParms );
   1049 			}
   1050 			for ( dynamicShadowVolumeParms_t * shadowParms = vEntity->dynamicShadowVolumes; shadowParms != NULL; shadowParms = shadowParms->next ) {
   1051 				DynamicShadowVolumeJob( shadowParms );
   1052 			}
   1053 			vEntity->staticShadowVolumes = NULL;
   1054 			vEntity->dynamicShadowVolumes = NULL;
   1055 		}
   1056 
   1057 		int end = Sys_Microseconds();
   1058 		backEnd.pc.shadowMicroSec += end - start;
   1059 	}
   1060 
   1061 	//-------------------------------------------------
   1062 	// Move the draw surfs to the view.
   1063 	//-------------------------------------------------
   1064 
   1065 	tr.viewDef->numDrawSurfs = 0;	// clear the ambient surface list
   1066 	tr.viewDef->maxDrawSurfs = 0;	// will be set to INITIAL_DRAWSURFS on R_LinkDrawSurfToView
   1067 
   1068 	for ( viewEntity_t * vEntity = tr.viewDef->viewEntitys; vEntity != NULL; vEntity = vEntity->next ) {
   1069 		for ( drawSurf_t * ds = vEntity->drawSurfs; ds != NULL; ) {
   1070 			drawSurf_t * next = ds->nextOnLight;
   1071 			if ( ds->linkChain == NULL ) {
   1072 				R_LinkDrawSurfToView( ds, tr.viewDef );
   1073 			} else {
   1074 				ds->nextOnLight = *ds->linkChain;
   1075 				*ds->linkChain = ds;
   1076 			}
   1077 			ds = next;
   1078 		}
   1079 		vEntity->drawSurfs = NULL;
   1080 	}
   1081 }