tr_light.cpp 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 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 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. 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.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "tr_local.h"
  23. static const float CHECK_BOUNDS_EPSILON = 1.0f;
  24. /*
  25. ===========================================================================================
  26. VERTEX CACHE GENERATORS
  27. ===========================================================================================
  28. */
  29. /*
  30. ==================
  31. R_CreateAmbientCache
  32. Create it if needed
  33. ==================
  34. */
  35. bool R_CreateAmbientCache( srfTriangles_t *tri, bool needsLighting ) {
  36. if ( tri->ambientCache ) {
  37. return true;
  38. }
  39. // we are going to use it for drawing, so make sure we have the tangents and normals
  40. if ( needsLighting && !tri->tangentsCalculated ) {
  41. R_DeriveTangents( tri );
  42. }
  43. vertexCache.Alloc( tri->verts, tri->numVerts * sizeof( tri->verts[0] ), &tri->ambientCache );
  44. if ( !tri->ambientCache ) {
  45. return false;
  46. }
  47. return true;
  48. }
  49. /*
  50. ==================
  51. R_CreateLightingCache
  52. Returns false if the cache couldn't be allocated, in which case the surface should be skipped.
  53. ==================
  54. */
  55. bool R_CreateLightingCache( const idRenderEntityLocal *ent, const idRenderLightLocal *light, srfTriangles_t *tri ) {
  56. idVec3 localLightOrigin;
  57. // fogs and blends don't need light vectors
  58. if ( light->lightShader->IsFogLight() || light->lightShader->IsBlendLight() ) {
  59. return true;
  60. }
  61. // not needed if we have vertex programs
  62. if ( tr.backEndRendererHasVertexPrograms ) {
  63. return true;
  64. }
  65. R_GlobalPointToLocal( ent->modelMatrix, light->globalLightOrigin, localLightOrigin );
  66. int size = tri->ambientSurface->numVerts * sizeof( lightingCache_t );
  67. lightingCache_t *cache = (lightingCache_t *)_alloca16( size );
  68. #if 1
  69. SIMDProcessor->CreateTextureSpaceLightVectors( &cache[0].localLightVector, localLightOrigin,
  70. tri->ambientSurface->verts, tri->ambientSurface->numVerts, tri->indexes, tri->numIndexes );
  71. #else
  72. bool *used = (bool *)_alloca16( tri->ambientSurface->numVerts * sizeof( used[0] ) );
  73. memset( used, 0, tri->ambientSurface->numVerts * sizeof( used[0] ) );
  74. // because the interaction may be a very small subset of the full surface,
  75. // it makes sense to only deal with the verts used
  76. for ( int j = 0; j < tri->numIndexes; j++ ) {
  77. int i = tri->indexes[j];
  78. if ( used[i] ) {
  79. continue;
  80. }
  81. used[i] = true;
  82. idVec3 lightDir;
  83. const idDrawVert *v;
  84. v = &tri->ambientSurface->verts[i];
  85. lightDir = localLightOrigin - v->xyz;
  86. cache[i].localLightVector[0] = lightDir * v->tangents[0];
  87. cache[i].localLightVector[1] = lightDir * v->tangents[1];
  88. cache[i].localLightVector[2] = lightDir * v->normal;
  89. }
  90. #endif
  91. vertexCache.Alloc( cache, size, &tri->lightingCache );
  92. if ( !tri->lightingCache ) {
  93. return false;
  94. }
  95. return true;
  96. }
  97. /*
  98. ==================
  99. R_CreatePrivateShadowCache
  100. This is used only for a specific light
  101. ==================
  102. */
  103. void R_CreatePrivateShadowCache( srfTriangles_t *tri ) {
  104. if ( !tri->shadowVertexes ) {
  105. return;
  106. }
  107. vertexCache.Alloc( tri->shadowVertexes, tri->numVerts * sizeof( *tri->shadowVertexes ), &tri->shadowCache );
  108. }
  109. /*
  110. ==================
  111. R_CreateVertexProgramShadowCache
  112. This is constant for any number of lights, the vertex program
  113. takes care of projecting the verts to infinity.
  114. ==================
  115. */
  116. void R_CreateVertexProgramShadowCache( srfTriangles_t *tri ) {
  117. if ( tri->verts == NULL ) {
  118. return;
  119. }
  120. shadowCache_t *temp = (shadowCache_t *)_alloca16( tri->numVerts * 2 * sizeof( shadowCache_t ) );
  121. #if 1
  122. SIMDProcessor->CreateVertexProgramShadowCache( &temp->xyz, tri->verts, tri->numVerts );
  123. #else
  124. int numVerts = tri->numVerts;
  125. const idDrawVert *verts = tri->verts;
  126. for ( int i = 0; i < numVerts; i++ ) {
  127. const float *v = verts[i].xyz.ToFloatPtr();
  128. temp[i*2+0].xyz[0] = v[0];
  129. temp[i*2+1].xyz[0] = v[0];
  130. temp[i*2+0].xyz[1] = v[1];
  131. temp[i*2+1].xyz[1] = v[1];
  132. temp[i*2+0].xyz[2] = v[2];
  133. temp[i*2+1].xyz[2] = v[2];
  134. temp[i*2+0].xyz[3] = 1.0f; // on the model surface
  135. temp[i*2+1].xyz[3] = 0.0f; // will be projected to infinity
  136. }
  137. #endif
  138. vertexCache.Alloc( temp, tri->numVerts * 2 * sizeof( shadowCache_t ), &tri->shadowCache );
  139. }
  140. /*
  141. ==================
  142. R_SkyboxTexGen
  143. ==================
  144. */
  145. void R_SkyboxTexGen( drawSurf_t *surf, const idVec3 &viewOrg ) {
  146. int i;
  147. idVec3 localViewOrigin;
  148. R_GlobalPointToLocal( surf->space->modelMatrix, viewOrg, localViewOrigin );
  149. int numVerts = surf->geo->numVerts;
  150. int size = numVerts * sizeof( idVec3 );
  151. idVec3 *texCoords = (idVec3 *) _alloca16( size );
  152. const idDrawVert *verts = surf->geo->verts;
  153. for ( i = 0; i < numVerts; i++ ) {
  154. texCoords[i][0] = verts[i].xyz[0] - localViewOrigin[0];
  155. texCoords[i][1] = verts[i].xyz[1] - localViewOrigin[1];
  156. texCoords[i][2] = verts[i].xyz[2] - localViewOrigin[2];
  157. }
  158. surf->dynamicTexCoords = vertexCache.AllocFrameTemp( texCoords, size );
  159. }
  160. /*
  161. ==================
  162. R_WobbleskyTexGen
  163. ==================
  164. */
  165. void R_WobbleskyTexGen( drawSurf_t *surf, const idVec3 &viewOrg ) {
  166. int i;
  167. idVec3 localViewOrigin;
  168. const int *parms = surf->material->GetTexGenRegisters();
  169. float wobbleDegrees = surf->shaderRegisters[ parms[0] ];
  170. float wobbleSpeed = surf->shaderRegisters[ parms[1] ];
  171. float rotateSpeed = surf->shaderRegisters[ parms[2] ];
  172. wobbleDegrees = wobbleDegrees * idMath::PI / 180;
  173. wobbleSpeed = wobbleSpeed * 2 * idMath::PI / 60;
  174. rotateSpeed = rotateSpeed * 2 * idMath::PI / 60;
  175. // very ad-hoc "wobble" transform
  176. float transform[16];
  177. float a = tr.viewDef->floatTime * wobbleSpeed;
  178. float s = sin( a ) * sin( wobbleDegrees );
  179. float c = cos( a ) * sin( wobbleDegrees );
  180. float z = cos( wobbleDegrees );
  181. idVec3 axis[3];
  182. axis[2][0] = c;
  183. axis[2][1] = s;
  184. axis[2][2] = z;
  185. axis[1][0] = -sin( a * 2 ) * sin( wobbleDegrees );
  186. axis[1][2] = -s * sin( wobbleDegrees );
  187. axis[1][1] = sqrt( 1.0f - ( axis[1][0] * axis[1][0] + axis[1][2] * axis[1][2] ) );
  188. // make the second vector exactly perpendicular to the first
  189. axis[1] -= ( axis[2] * axis[1] ) * axis[2];
  190. axis[1].Normalize();
  191. // construct the third with a cross
  192. axis[0].Cross( axis[1], axis[2] );
  193. // add the rotate
  194. s = sin( rotateSpeed * tr.viewDef->floatTime );
  195. c = cos( rotateSpeed * tr.viewDef->floatTime );
  196. transform[0] = axis[0][0] * c + axis[1][0] * s;
  197. transform[4] = axis[0][1] * c + axis[1][1] * s;
  198. transform[8] = axis[0][2] * c + axis[1][2] * s;
  199. transform[1] = axis[1][0] * c - axis[0][0] * s;
  200. transform[5] = axis[1][1] * c - axis[0][1] * s;
  201. transform[9] = axis[1][2] * c - axis[0][2] * s;
  202. transform[2] = axis[2][0];
  203. transform[6] = axis[2][1];
  204. transform[10] = axis[2][2];
  205. transform[3] = transform[7] = transform[11] = 0.0f;
  206. transform[12] = transform[13] = transform[14] = 0.0f;
  207. R_GlobalPointToLocal( surf->space->modelMatrix, viewOrg, localViewOrigin );
  208. int numVerts = surf->geo->numVerts;
  209. int size = numVerts * sizeof( idVec3 );
  210. idVec3 *texCoords = (idVec3 *) _alloca16( size );
  211. const idDrawVert *verts = surf->geo->verts;
  212. for ( i = 0; i < numVerts; i++ ) {
  213. idVec3 v;
  214. v[0] = verts[i].xyz[0] - localViewOrigin[0];
  215. v[1] = verts[i].xyz[1] - localViewOrigin[1];
  216. v[2] = verts[i].xyz[2] - localViewOrigin[2];
  217. R_LocalPointToGlobal( transform, v, texCoords[i] );
  218. }
  219. surf->dynamicTexCoords = vertexCache.AllocFrameTemp( texCoords, size );
  220. }
  221. /*
  222. =================
  223. R_SpecularTexGen
  224. Calculates the specular coordinates for cards without vertex programs.
  225. =================
  226. */
  227. static void R_SpecularTexGen( drawSurf_t *surf, const idVec3 &globalLightOrigin, const idVec3 &viewOrg ) {
  228. const srfTriangles_t *tri;
  229. idVec3 localLightOrigin;
  230. idVec3 localViewOrigin;
  231. R_GlobalPointToLocal( surf->space->modelMatrix, globalLightOrigin, localLightOrigin );
  232. R_GlobalPointToLocal( surf->space->modelMatrix, viewOrg, localViewOrigin );
  233. tri = surf->geo;
  234. // FIXME: change to 3 component?
  235. int size = tri->numVerts * sizeof( idVec4 );
  236. idVec4 *texCoords = (idVec4 *) _alloca16( size );
  237. #if 1
  238. SIMDProcessor->CreateSpecularTextureCoords( texCoords, localLightOrigin, localViewOrigin,
  239. tri->verts, tri->numVerts, tri->indexes, tri->numIndexes );
  240. #else
  241. bool *used = (bool *)_alloca16( tri->numVerts * sizeof( used[0] ) );
  242. memset( used, 0, tri->numVerts * sizeof( used[0] ) );
  243. // because the interaction may be a very small subset of the full surface,
  244. // it makes sense to only deal with the verts used
  245. for ( int j = 0; j < tri->numIndexes; j++ ) {
  246. int i = tri->indexes[j];
  247. if ( used[i] ) {
  248. continue;
  249. }
  250. used[i] = true;
  251. float ilength;
  252. const idDrawVert *v = &tri->verts[i];
  253. idVec3 lightDir = localLightOrigin - v->xyz;
  254. idVec3 viewDir = localViewOrigin - v->xyz;
  255. ilength = idMath::RSqrt( lightDir * lightDir );
  256. lightDir[0] *= ilength;
  257. lightDir[1] *= ilength;
  258. lightDir[2] *= ilength;
  259. ilength = idMath::RSqrt( viewDir * viewDir );
  260. viewDir[0] *= ilength;
  261. viewDir[1] *= ilength;
  262. viewDir[2] *= ilength;
  263. lightDir += viewDir;
  264. texCoords[i][0] = lightDir * v->tangents[0];
  265. texCoords[i][1] = lightDir * v->tangents[1];
  266. texCoords[i][2] = lightDir * v->normal;
  267. texCoords[i][3] = 1;
  268. }
  269. #endif
  270. surf->dynamicTexCoords = vertexCache.AllocFrameTemp( texCoords, size );
  271. }
  272. //=======================================================================================================
  273. /*
  274. =============
  275. R_SetEntityDefViewEntity
  276. If the entityDef isn't already on the viewEntity list, create
  277. a viewEntity and add it to the list with an empty scissor rect.
  278. This does not instantiate dynamic models for the entity yet.
  279. =============
  280. */
  281. viewEntity_t *R_SetEntityDefViewEntity( idRenderEntityLocal *def ) {
  282. viewEntity_t *vModel;
  283. if ( def->viewCount == tr.viewCount ) {
  284. return def->viewEntity;
  285. }
  286. def->viewCount = tr.viewCount;
  287. // set the model and modelview matricies
  288. vModel = (viewEntity_t *)R_ClearedFrameAlloc( sizeof( *vModel ) );
  289. vModel->entityDef = def;
  290. // the scissorRect will be expanded as the model bounds is accepted into visible portal chains
  291. vModel->scissorRect.Clear();
  292. // copy the model and weapon depth hack for back-end use
  293. vModel->modelDepthHack = def->parms.modelDepthHack;
  294. vModel->weaponDepthHack = def->parms.weaponDepthHack;
  295. R_AxisToModelMatrix( def->parms.axis, def->parms.origin, vModel->modelMatrix );
  296. // we may not have a viewDef if we are just creating shadows at entity creation time
  297. if ( tr.viewDef ) {
  298. myGlMultMatrix( vModel->modelMatrix, tr.viewDef->worldSpace.modelViewMatrix, vModel->modelViewMatrix );
  299. vModel->next = tr.viewDef->viewEntitys;
  300. tr.viewDef->viewEntitys = vModel;
  301. }
  302. def->viewEntity = vModel;
  303. return vModel;
  304. }
  305. /*
  306. ====================
  307. R_TestPointInViewLight
  308. ====================
  309. */
  310. static const float INSIDE_LIGHT_FRUSTUM_SLOP = 32;
  311. // this needs to be greater than the dist from origin to corner of near clip plane
  312. static bool R_TestPointInViewLight( const idVec3 &org, const idRenderLightLocal *light ) {
  313. int i;
  314. idVec3 local;
  315. for ( i = 0 ; i < 6 ; i++ ) {
  316. float d = light->frustum[i].Distance( org );
  317. if ( d > INSIDE_LIGHT_FRUSTUM_SLOP ) {
  318. return false;
  319. }
  320. }
  321. return true;
  322. }
  323. /*
  324. ===================
  325. R_PointInFrustum
  326. Assumes positive sides face outward
  327. ===================
  328. */
  329. static bool R_PointInFrustum( idVec3 &p, idPlane *planes, int numPlanes ) {
  330. for ( int i = 0 ; i < numPlanes ; i++ ) {
  331. float d = planes[i].Distance( p );
  332. if ( d > 0 ) {
  333. return false;
  334. }
  335. }
  336. return true;
  337. }
  338. /*
  339. =============
  340. R_SetLightDefViewLight
  341. If the lightDef isn't already on the viewLight list, create
  342. a viewLight and add it to the list with an empty scissor rect.
  343. =============
  344. */
  345. viewLight_t *R_SetLightDefViewLight( idRenderLightLocal *light ) {
  346. viewLight_t *vLight;
  347. if ( light->viewCount == tr.viewCount ) {
  348. return light->viewLight;
  349. }
  350. light->viewCount = tr.viewCount;
  351. // add to the view light chain
  352. vLight = (viewLight_t *)R_ClearedFrameAlloc( sizeof( *vLight ) );
  353. vLight->lightDef = light;
  354. // the scissorRect will be expanded as the light bounds is accepted into visible portal chains
  355. vLight->scissorRect.Clear();
  356. // calculate the shadow cap optimization states
  357. vLight->viewInsideLight = R_TestPointInViewLight( tr.viewDef->renderView.vieworg, light );
  358. if ( !vLight->viewInsideLight ) {
  359. vLight->viewSeesShadowPlaneBits = 0;
  360. for ( int i = 0 ; i < light->numShadowFrustums ; i++ ) {
  361. float d = light->shadowFrustums[i].planes[5].Distance( tr.viewDef->renderView.vieworg );
  362. if ( d < INSIDE_LIGHT_FRUSTUM_SLOP ) {
  363. vLight->viewSeesShadowPlaneBits|= 1 << i;
  364. }
  365. }
  366. } else {
  367. // this should not be referenced in this case
  368. vLight->viewSeesShadowPlaneBits = 63;
  369. }
  370. // see if the light center is in view, which will allow us to cull invisible shadows
  371. vLight->viewSeesGlobalLightOrigin = R_PointInFrustum( light->globalLightOrigin, tr.viewDef->frustum, 4 );
  372. // copy data used by backend
  373. vLight->globalLightOrigin = light->globalLightOrigin;
  374. vLight->lightProject[0] = light->lightProject[0];
  375. vLight->lightProject[1] = light->lightProject[1];
  376. vLight->lightProject[2] = light->lightProject[2];
  377. vLight->lightProject[3] = light->lightProject[3];
  378. vLight->fogPlane = light->frustum[5];
  379. vLight->frustumTris = light->frustumTris;
  380. vLight->falloffImage = light->falloffImage;
  381. vLight->lightShader = light->lightShader;
  382. vLight->shaderRegisters = NULL; // allocated and evaluated in R_AddLightSurfaces
  383. // link the view light
  384. vLight->next = tr.viewDef->viewLights;
  385. tr.viewDef->viewLights = vLight;
  386. light->viewLight = vLight;
  387. return vLight;
  388. }
  389. /*
  390. =================
  391. idRenderWorldLocal::CreateLightDefInteractions
  392. When a lightDef is determined to effect the view (contact the frustum and non-0 light), it will check to
  393. make sure that it has interactions for all the entityDefs that it might possibly contact.
  394. This does not guarantee that all possible interactions for this light are generated, only that
  395. the ones that may effect the current view are generated. so it does need to be called every view.
  396. This does not cause entityDefs to create dynamic models, all work is done on the referenceBounds.
  397. All entities that have non-empty interactions with viewLights will
  398. have viewEntities made for them and be put on the viewEntity list,
  399. even if their surfaces aren't visible, because they may need to cast shadows.
  400. Interactions are usually removed when a entityDef or lightDef is modified, unless the change
  401. is known to not effect them, so there is no danger of getting a stale interaction, we just need to
  402. check that needed ones are created.
  403. An interaction can be at several levels:
  404. Don't interact (but share an area) (numSurfaces = 0)
  405. Entity reference bounds touches light frustum, but surfaces haven't been generated (numSurfaces = -1)
  406. Shadow surfaces have been generated, but light surfaces have not. The shadow surface may still be empty due to bounds being conservative.
  407. Both shadow and light surfaces have been generated. Either or both surfaces may still be empty due to conservative bounds.
  408. =================
  409. */
  410. void idRenderWorldLocal::CreateLightDefInteractions( idRenderLightLocal *ldef ) {
  411. areaReference_t *eref;
  412. areaReference_t *lref;
  413. idRenderEntityLocal *edef;
  414. portalArea_t *area;
  415. idInteraction *inter;
  416. for ( lref = ldef->references ; lref ; lref = lref->ownerNext ) {
  417. area = lref->area;
  418. // check all the models in this area
  419. for ( eref = area->entityRefs.areaNext ; eref != &area->entityRefs ; eref = eref->areaNext ) {
  420. edef = eref->entity;
  421. // if the entity doesn't have any light-interacting surfaces, we could skip this,
  422. // but we don't want to instantiate dynamic models yet, so we can't check that on
  423. // most things
  424. // if the entity isn't viewed
  425. if ( tr.viewDef && edef->viewCount != tr.viewCount ) {
  426. // if the light doesn't cast shadows, skip
  427. if ( !ldef->lightShader->LightCastsShadows() ) {
  428. continue;
  429. }
  430. // if we are suppressing its shadow in this view, skip
  431. if ( !r_skipSuppress.GetBool() ) {
  432. if ( edef->parms.suppressShadowInViewID && edef->parms.suppressShadowInViewID == tr.viewDef->renderView.viewID ) {
  433. continue;
  434. }
  435. if ( edef->parms.suppressShadowInLightID && edef->parms.suppressShadowInLightID == ldef->parms.lightId ) {
  436. continue;
  437. }
  438. }
  439. }
  440. // some big outdoor meshes are flagged to not create any dynamic interactions
  441. // when the level designer knows that nearby moving lights shouldn't actually hit them
  442. if ( edef->parms.noDynamicInteractions && edef->world->generateAllInteractionsCalled ) {
  443. continue;
  444. }
  445. // if any of the edef's interaction match this light, we don't
  446. // need to consider it.
  447. if ( r_useInteractionTable.GetBool() && this->interactionTable ) {
  448. // allocating these tables may take several megs on big maps, but it saves 3% to 5% of
  449. // the CPU time. The table is updated at interaction::AllocAndLink() and interaction::UnlinkAndFree()
  450. int index = ldef->index * this->interactionTableWidth + edef->index;
  451. inter = this->interactionTable[ index ];
  452. if ( inter ) {
  453. // if this entity wasn't in view already, the scissor rect will be empty,
  454. // so it will only be used for shadow casting
  455. if ( !inter->IsEmpty() ) {
  456. R_SetEntityDefViewEntity( edef );
  457. }
  458. continue;
  459. }
  460. } else {
  461. // scan the doubly linked lists, which may have several dozen entries
  462. // we could check either model refs or light refs for matches, but it is
  463. // assumed that there will be less lights in an area than models
  464. // so the entity chains should be somewhat shorter (they tend to be fairly close).
  465. for ( inter = edef->firstInteraction; inter != NULL; inter = inter->entityNext ) {
  466. if ( inter->lightDef == ldef ) {
  467. break;
  468. }
  469. }
  470. // if we already have an interaction, we don't need to do anything
  471. if ( inter != NULL ) {
  472. // if this entity wasn't in view already, the scissor rect will be empty,
  473. // so it will only be used for shadow casting
  474. if ( !inter->IsEmpty() ) {
  475. R_SetEntityDefViewEntity( edef );
  476. }
  477. continue;
  478. }
  479. }
  480. //
  481. // create a new interaction, but don't do any work other than bbox to frustum culling
  482. //
  483. idInteraction *inter = idInteraction::AllocAndLink( edef, ldef );
  484. // do a check of the entity reference bounds against the light frustum,
  485. // trying to avoid creating a viewEntity if it hasn't been already
  486. float modelMatrix[16];
  487. float *m;
  488. if ( edef->viewCount == tr.viewCount ) {
  489. m = edef->viewEntity->modelMatrix;
  490. } else {
  491. R_AxisToModelMatrix( edef->parms.axis, edef->parms.origin, modelMatrix );
  492. m = modelMatrix;
  493. }
  494. if ( R_CullLocalBox( edef->referenceBounds, m, 6, ldef->frustum ) ) {
  495. inter->MakeEmpty();
  496. continue;
  497. }
  498. // we will do a more precise per-surface check when we are checking the entity
  499. // if this entity wasn't in view already, the scissor rect will be empty,
  500. // so it will only be used for shadow casting
  501. R_SetEntityDefViewEntity( edef );
  502. }
  503. }
  504. }
  505. //===============================================================================================================
  506. /*
  507. =================
  508. R_LinkLightSurf
  509. =================
  510. */
  511. void R_LinkLightSurf( const drawSurf_t **link, const srfTriangles_t *tri, const viewEntity_t *space,
  512. const idRenderLightLocal *light, const idMaterial *shader, const idScreenRect &scissor, bool viewInsideShadow ) {
  513. drawSurf_t *drawSurf;
  514. if ( !space ) {
  515. space = &tr.viewDef->worldSpace;
  516. }
  517. drawSurf = (drawSurf_t *)R_FrameAlloc( sizeof( *drawSurf ) );
  518. drawSurf->geo = tri;
  519. drawSurf->space = space;
  520. drawSurf->material = shader;
  521. drawSurf->scissorRect = scissor;
  522. drawSurf->dsFlags = 0;
  523. if ( viewInsideShadow ) {
  524. drawSurf->dsFlags |= DSF_VIEW_INSIDE_SHADOW;
  525. }
  526. if ( !shader ) {
  527. // shadows won't have a shader
  528. drawSurf->shaderRegisters = NULL;
  529. } else {
  530. // process the shader expressions for conditionals / color / texcoords
  531. const float *constRegs = shader->ConstantRegisters();
  532. if ( constRegs ) {
  533. // this shader has only constants for parameters
  534. drawSurf->shaderRegisters = constRegs;
  535. } else {
  536. // FIXME: share with the ambient surface?
  537. float *regs = (float *)R_FrameAlloc( shader->GetNumRegisters() * sizeof( float ) );
  538. drawSurf->shaderRegisters = regs;
  539. shader->EvaluateRegisters( regs, space->entityDef->parms.shaderParms, tr.viewDef, space->entityDef->parms.referenceSound );
  540. }
  541. // calculate the specular coordinates if we aren't using vertex programs
  542. if ( !tr.backEndRendererHasVertexPrograms && !r_skipSpecular.GetBool() && tr.backEndRenderer != BE_ARB ) {
  543. R_SpecularTexGen( drawSurf, light->globalLightOrigin, tr.viewDef->renderView.vieworg );
  544. // if we failed to allocate space for the specular calculations, drop the surface
  545. if ( !drawSurf->dynamicTexCoords ) {
  546. return;
  547. }
  548. }
  549. }
  550. // actually link it in
  551. drawSurf->nextOnLight = *link;
  552. *link = drawSurf;
  553. }
  554. /*
  555. ======================
  556. R_ClippedLightScissorRectangle
  557. ======================
  558. */
  559. idScreenRect R_ClippedLightScissorRectangle( viewLight_t *vLight ) {
  560. int i, j;
  561. const idRenderLightLocal *light = vLight->lightDef;
  562. idScreenRect r;
  563. idFixedWinding w;
  564. r.Clear();
  565. for ( i = 0 ; i < 6 ; i++ ) {
  566. const idWinding *ow = light->frustumWindings[i];
  567. // projected lights may have one of the frustums degenerated
  568. if ( !ow ) {
  569. continue;
  570. }
  571. // the light frustum planes face out from the light,
  572. // so the planes that have the view origin on the negative
  573. // side will be the "back" faces of the light, which must have
  574. // some fragment inside the portalStack to be visible
  575. if ( light->frustum[i].Distance( tr.viewDef->renderView.vieworg ) >= 0 ) {
  576. continue;
  577. }
  578. w = *ow;
  579. // now check the winding against each of the frustum planes
  580. for ( j = 0; j < 5; j++ ) {
  581. if ( !w.ClipInPlace( -tr.viewDef->frustum[j] ) ) {
  582. break;
  583. }
  584. }
  585. // project these points to the screen and add to bounds
  586. for ( j = 0; j < w.GetNumPoints(); j++ ) {
  587. idPlane eye, clip;
  588. idVec3 ndc;
  589. R_TransformModelToClip( w[j].ToVec3(), tr.viewDef->worldSpace.modelViewMatrix, tr.viewDef->projectionMatrix, eye, clip );
  590. if ( clip[3] <= 0.01f ) {
  591. clip[3] = 0.01f;
  592. }
  593. R_TransformClipToDevice( clip, tr.viewDef, ndc );
  594. float windowX = 0.5f * ( 1.0f + ndc[0] ) * ( tr.viewDef->viewport.x2 - tr.viewDef->viewport.x1 );
  595. float windowY = 0.5f * ( 1.0f + ndc[1] ) * ( tr.viewDef->viewport.y2 - tr.viewDef->viewport.y1 );
  596. if ( windowX > tr.viewDef->scissor.x2 ) {
  597. windowX = tr.viewDef->scissor.x2;
  598. } else if ( windowX < tr.viewDef->scissor.x1 ) {
  599. windowX = tr.viewDef->scissor.x1;
  600. }
  601. if ( windowY > tr.viewDef->scissor.y2 ) {
  602. windowY = tr.viewDef->scissor.y2;
  603. } else if ( windowY < tr.viewDef->scissor.y1 ) {
  604. windowY = tr.viewDef->scissor.y1;
  605. }
  606. r.AddPoint( windowX, windowY );
  607. }
  608. }
  609. // add the fudge boundary
  610. r.Expand();
  611. return r;
  612. }
  613. /*
  614. ==================
  615. R_CalcLightScissorRectangle
  616. The light screen bounds will be used to crop the scissor rect during
  617. stencil clears and interaction drawing
  618. ==================
  619. */
  620. int c_clippedLight, c_unclippedLight;
  621. idScreenRect R_CalcLightScissorRectangle( viewLight_t *vLight ) {
  622. idScreenRect r;
  623. srfTriangles_t *tri;
  624. idPlane eye, clip;
  625. idVec3 ndc;
  626. if ( vLight->lightDef->parms.pointLight ) {
  627. idBounds bounds;
  628. idRenderLightLocal *lightDef = vLight->lightDef;
  629. tr.viewDef->viewFrustum.ProjectionBounds( idBox( lightDef->parms.origin, lightDef->parms.lightRadius, lightDef->parms.axis ), bounds );
  630. return R_ScreenRectFromViewFrustumBounds( bounds );
  631. }
  632. if ( r_useClippedLightScissors.GetInteger() == 2 ) {
  633. return R_ClippedLightScissorRectangle( vLight );
  634. }
  635. r.Clear();
  636. tri = vLight->lightDef->frustumTris;
  637. for ( int i = 0 ; i < tri->numVerts ; i++ ) {
  638. R_TransformModelToClip( tri->verts[i].xyz, tr.viewDef->worldSpace.modelViewMatrix,
  639. tr.viewDef->projectionMatrix, eye, clip );
  640. // if it is near clipped, clip the winding polygons to the view frustum
  641. if ( clip[3] <= 1 ) {
  642. c_clippedLight++;
  643. if ( r_useClippedLightScissors.GetInteger() ) {
  644. return R_ClippedLightScissorRectangle( vLight );
  645. } else {
  646. r.x1 = r.y1 = 0;
  647. r.x2 = ( tr.viewDef->viewport.x2 - tr.viewDef->viewport.x1 ) - 1;
  648. r.y2 = ( tr.viewDef->viewport.y2 - tr.viewDef->viewport.y1 ) - 1;
  649. return r;
  650. }
  651. }
  652. R_TransformClipToDevice( clip, tr.viewDef, ndc );
  653. float windowX = 0.5f * ( 1.0f + ndc[0] ) * ( tr.viewDef->viewport.x2 - tr.viewDef->viewport.x1 );
  654. float windowY = 0.5f * ( 1.0f + ndc[1] ) * ( tr.viewDef->viewport.y2 - tr.viewDef->viewport.y1 );
  655. if ( windowX > tr.viewDef->scissor.x2 ) {
  656. windowX = tr.viewDef->scissor.x2;
  657. } else if ( windowX < tr.viewDef->scissor.x1 ) {
  658. windowX = tr.viewDef->scissor.x1;
  659. }
  660. if ( windowY > tr.viewDef->scissor.y2 ) {
  661. windowY = tr.viewDef->scissor.y2;
  662. } else if ( windowY < tr.viewDef->scissor.y1 ) {
  663. windowY = tr.viewDef->scissor.y1;
  664. }
  665. r.AddPoint( windowX, windowY );
  666. }
  667. // add the fudge boundary
  668. r.Expand();
  669. c_unclippedLight++;
  670. return r;
  671. }
  672. /*
  673. =================
  674. R_AddLightSurfaces
  675. Calc the light shader values, removing any light from the viewLight list
  676. if it is determined to not have any visible effect due to being flashed off or turned off.
  677. Adds entities to the viewEntity list if they are needed for shadow casting.
  678. Add any precomputed shadow volumes.
  679. Removes lights from the viewLights list if they are completely
  680. turned off, or completely off screen.
  681. Create any new interactions needed between the viewLights
  682. and the viewEntitys due to game movement
  683. =================
  684. */
  685. void R_AddLightSurfaces( void ) {
  686. viewLight_t *vLight;
  687. idRenderLightLocal *light;
  688. viewLight_t **ptr;
  689. // go through each visible light, possibly removing some from the list
  690. ptr = &tr.viewDef->viewLights;
  691. while ( *ptr ) {
  692. vLight = *ptr;
  693. light = vLight->lightDef;
  694. const idMaterial *lightShader = light->lightShader;
  695. if ( !lightShader ) {
  696. common->Error( "R_AddLightSurfaces: NULL lightShader" );
  697. }
  698. // see if we are suppressing the light in this view
  699. if ( !r_skipSuppress.GetBool() ) {
  700. if ( light->parms.suppressLightInViewID
  701. && light->parms.suppressLightInViewID == tr.viewDef->renderView.viewID ) {
  702. *ptr = vLight->next;
  703. light->viewCount = -1;
  704. continue;
  705. }
  706. if ( light->parms.allowLightInViewID
  707. && light->parms.allowLightInViewID != tr.viewDef->renderView.viewID ) {
  708. *ptr = vLight->next;
  709. light->viewCount = -1;
  710. continue;
  711. }
  712. }
  713. // evaluate the light shader registers
  714. float *lightRegs =(float *)R_FrameAlloc( lightShader->GetNumRegisters() * sizeof( float ) );
  715. vLight->shaderRegisters = lightRegs;
  716. lightShader->EvaluateRegisters( lightRegs, light->parms.shaderParms, tr.viewDef, light->parms.referenceSound );
  717. // if this is a purely additive light and no stage in the light shader evaluates
  718. // to a positive light value, we can completely skip the light
  719. if ( !lightShader->IsFogLight() && !lightShader->IsBlendLight() ) {
  720. int lightStageNum;
  721. for ( lightStageNum = 0 ; lightStageNum < lightShader->GetNumStages() ; lightStageNum++ ) {
  722. const shaderStage_t *lightStage = lightShader->GetStage( lightStageNum );
  723. // ignore stages that fail the condition
  724. if ( !lightRegs[ lightStage->conditionRegister ] ) {
  725. continue;
  726. }
  727. const int *registers = lightStage->color.registers;
  728. // snap tiny values to zero to avoid lights showing up with the wrong color
  729. if ( lightRegs[ registers[0] ] < 0.001f ) {
  730. lightRegs[ registers[0] ] = 0.0f;
  731. }
  732. if ( lightRegs[ registers[1] ] < 0.001f ) {
  733. lightRegs[ registers[1] ] = 0.0f;
  734. }
  735. if ( lightRegs[ registers[2] ] < 0.001f ) {
  736. lightRegs[ registers[2] ] = 0.0f;
  737. }
  738. // FIXME: when using the following values the light shows up bright red when using nvidia drivers/hardware
  739. // this seems to have been fixed ?
  740. //lightRegs[ registers[0] ] = 1.5143074e-005f;
  741. //lightRegs[ registers[1] ] = 1.5483369e-005f;
  742. //lightRegs[ registers[2] ] = 1.7014690e-005f;
  743. if ( lightRegs[ registers[0] ] > 0.0f ||
  744. lightRegs[ registers[1] ] > 0.0f ||
  745. lightRegs[ registers[2] ] > 0.0f ) {
  746. break;
  747. }
  748. }
  749. if ( lightStageNum == lightShader->GetNumStages() ) {
  750. // we went through all the stages and didn't find one that adds anything
  751. // remove the light from the viewLights list, and change its frame marker
  752. // so interaction generation doesn't think the light is visible and
  753. // create a shadow for it
  754. *ptr = vLight->next;
  755. light->viewCount = -1;
  756. continue;
  757. }
  758. }
  759. if ( r_useLightScissors.GetBool() ) {
  760. // calculate the screen area covered by the light frustum
  761. // which will be used to crop the stencil cull
  762. idScreenRect scissorRect = R_CalcLightScissorRectangle( vLight );
  763. // intersect with the portal crossing scissor rectangle
  764. vLight->scissorRect.Intersect( scissorRect );
  765. if ( r_showLightScissors.GetBool() ) {
  766. R_ShowColoredScreenRect( vLight->scissorRect, light->index );
  767. }
  768. }
  769. #if 0
  770. // this never happens, because CullLightByPortals() does a more precise job
  771. if ( vLight->scissorRect.IsEmpty() ) {
  772. // this light doesn't touch anything on screen, so remove it from the list
  773. *ptr = vLight->next;
  774. continue;
  775. }
  776. #endif
  777. // this one stays on the list
  778. ptr = &vLight->next;
  779. // if we are doing a soft-shadow novelty test, regenerate the light with
  780. // a random offset every time
  781. if ( r_lightSourceRadius.GetFloat() != 0.0f ) {
  782. for ( int i = 0 ; i < 3 ; i++ ) {
  783. light->globalLightOrigin[i] += r_lightSourceRadius.GetFloat() * ( -1 + 2 * (rand()&0xfff)/(float)0xfff );
  784. }
  785. }
  786. // create interactions with all entities the light may touch, and add viewEntities
  787. // that may cast shadows, even if they aren't directly visible. Any real work
  788. // will be deferred until we walk through the viewEntities
  789. tr.viewDef->renderWorld->CreateLightDefInteractions( light );
  790. tr.pc.c_viewLights++;
  791. // fog lights will need to draw the light frustum triangles, so make sure they
  792. // are in the vertex cache
  793. if ( lightShader->IsFogLight() ) {
  794. if ( !light->frustumTris->ambientCache ) {
  795. if ( !R_CreateAmbientCache( light->frustumTris, false ) ) {
  796. // skip if we are out of vertex memory
  797. continue;
  798. }
  799. }
  800. // touch the surface so it won't get purged
  801. vertexCache.Touch( light->frustumTris->ambientCache );
  802. }
  803. // add the prelight shadows for the static world geometry
  804. if ( light->parms.prelightModel && r_useOptimizedShadows.GetBool() ) {
  805. if ( !light->parms.prelightModel->NumSurfaces() ) {
  806. common->Error( "no surfs in prelight model '%s'", light->parms.prelightModel->Name() );
  807. }
  808. srfTriangles_t *tri = light->parms.prelightModel->Surface( 0 )->geometry;
  809. if ( !tri->shadowVertexes ) {
  810. common->Error( "R_AddLightSurfaces: prelight model '%s' without shadowVertexes", light->parms.prelightModel->Name() );
  811. }
  812. // these shadows will all have valid bounds, and can be culled normally
  813. if ( r_useShadowCulling.GetBool() ) {
  814. if ( R_CullLocalBox( tri->bounds, tr.viewDef->worldSpace.modelMatrix, 5, tr.viewDef->frustum ) ) {
  815. continue;
  816. }
  817. }
  818. // if we have been purged, re-upload the shadowVertexes
  819. if ( !tri->shadowCache ) {
  820. R_CreatePrivateShadowCache( tri );
  821. if ( !tri->shadowCache ) {
  822. continue;
  823. }
  824. }
  825. // touch the shadow surface so it won't get purged
  826. vertexCache.Touch( tri->shadowCache );
  827. if ( !tri->indexCache && r_useIndexBuffers.GetBool() ) {
  828. vertexCache.Alloc( tri->indexes, tri->numIndexes * sizeof( tri->indexes[0] ), &tri->indexCache, true );
  829. }
  830. if ( tri->indexCache ) {
  831. vertexCache.Touch( tri->indexCache );
  832. }
  833. R_LinkLightSurf( &vLight->globalShadows, tri, NULL, light, NULL, vLight->scissorRect, true /* FIXME? */ );
  834. }
  835. }
  836. }
  837. //===============================================================================================================
  838. /*
  839. ==================
  840. R_IssueEntityDefCallback
  841. ==================
  842. */
  843. bool R_IssueEntityDefCallback( idRenderEntityLocal *def ) {
  844. bool update;
  845. idBounds oldBounds;
  846. if ( r_checkBounds.GetBool() ) {
  847. oldBounds = def->referenceBounds;
  848. }
  849. def->archived = false; // will need to be written to the demo file
  850. tr.pc.c_entityDefCallbacks++;
  851. if ( tr.viewDef ) {
  852. update = def->parms.callback( &def->parms, &tr.viewDef->renderView );
  853. } else {
  854. update = def->parms.callback( &def->parms, NULL );
  855. }
  856. if ( !def->parms.hModel ) {
  857. common->Error( "R_IssueEntityDefCallback: dynamic entity callback didn't set model" );
  858. }
  859. if ( r_checkBounds.GetBool() ) {
  860. if ( oldBounds[0][0] > def->referenceBounds[0][0] + CHECK_BOUNDS_EPSILON ||
  861. oldBounds[0][1] > def->referenceBounds[0][1] + CHECK_BOUNDS_EPSILON ||
  862. oldBounds[0][2] > def->referenceBounds[0][2] + CHECK_BOUNDS_EPSILON ||
  863. oldBounds[1][0] < def->referenceBounds[1][0] - CHECK_BOUNDS_EPSILON ||
  864. oldBounds[1][1] < def->referenceBounds[1][1] - CHECK_BOUNDS_EPSILON ||
  865. oldBounds[1][2] < def->referenceBounds[1][2] - CHECK_BOUNDS_EPSILON ) {
  866. common->Printf( "entity %i callback extended reference bounds\n", def->index );
  867. }
  868. }
  869. return update;
  870. }
  871. /*
  872. ===================
  873. R_EntityDefDynamicModel
  874. Issues a deferred entity callback if necessary.
  875. If the model isn't dynamic, it returns the original.
  876. Returns the cached dynamic model if present, otherwise creates
  877. it and any necessary overlays
  878. ===================
  879. */
  880. idRenderModel *R_EntityDefDynamicModel( idRenderEntityLocal *def ) {
  881. bool callbackUpdate;
  882. // allow deferred entities to construct themselves
  883. if ( def->parms.callback ) {
  884. callbackUpdate = R_IssueEntityDefCallback( def );
  885. } else {
  886. callbackUpdate = false;
  887. }
  888. idRenderModel *model = def->parms.hModel;
  889. if ( !model ) {
  890. common->Error( "R_EntityDefDynamicModel: NULL model" );
  891. }
  892. if ( model->IsDynamicModel() == DM_STATIC ) {
  893. def->dynamicModel = NULL;
  894. def->dynamicModelFrameCount = 0;
  895. return model;
  896. }
  897. // continously animating models (particle systems, etc) will have their snapshot updated every single view
  898. if ( callbackUpdate || ( model->IsDynamicModel() == DM_CONTINUOUS && def->dynamicModelFrameCount != tr.frameCount ) ) {
  899. R_ClearEntityDefDynamicModel( def );
  900. }
  901. // if we don't have a snapshot of the dynamic model, generate it now
  902. if ( !def->dynamicModel ) {
  903. // instantiate the snapshot of the dynamic model, possibly reusing memory from the cached snapshot
  904. def->cachedDynamicModel = model->InstantiateDynamicModel( &def->parms, tr.viewDef, def->cachedDynamicModel );
  905. if ( def->cachedDynamicModel ) {
  906. // add any overlays to the snapshot of the dynamic model
  907. if ( def->overlay && !r_skipOverlays.GetBool() ) {
  908. def->overlay->AddOverlaySurfacesToModel( def->cachedDynamicModel );
  909. } else {
  910. idRenderModelOverlay::RemoveOverlaySurfacesFromModel( def->cachedDynamicModel );
  911. }
  912. if ( r_checkBounds.GetBool() ) {
  913. idBounds b = def->cachedDynamicModel->Bounds();
  914. if ( b[0][0] < def->referenceBounds[0][0] - CHECK_BOUNDS_EPSILON ||
  915. b[0][1] < def->referenceBounds[0][1] - CHECK_BOUNDS_EPSILON ||
  916. b[0][2] < def->referenceBounds[0][2] - CHECK_BOUNDS_EPSILON ||
  917. b[1][0] > def->referenceBounds[1][0] + CHECK_BOUNDS_EPSILON ||
  918. b[1][1] > def->referenceBounds[1][1] + CHECK_BOUNDS_EPSILON ||
  919. b[1][2] > def->referenceBounds[1][2] + CHECK_BOUNDS_EPSILON ) {
  920. common->Printf( "entity %i dynamic model exceeded reference bounds\n", def->index );
  921. }
  922. }
  923. }
  924. def->dynamicModel = def->cachedDynamicModel;
  925. def->dynamicModelFrameCount = tr.frameCount;
  926. }
  927. // set model depth hack value
  928. if ( def->dynamicModel && model->DepthHack() != 0.0f && tr.viewDef ) {
  929. idPlane eye, clip;
  930. idVec3 ndc;
  931. R_TransformModelToClip( def->parms.origin, tr.viewDef->worldSpace.modelViewMatrix, tr.viewDef->projectionMatrix, eye, clip );
  932. R_TransformClipToDevice( clip, tr.viewDef, ndc );
  933. def->parms.modelDepthHack = model->DepthHack() * ( 1.0f - ndc.z );
  934. }
  935. // FIXME: if any of the surfaces have deforms, create a frame-temporary model with references to the
  936. // undeformed surfaces. This would allow deforms to be light interacting.
  937. return def->dynamicModel;
  938. }
  939. /*
  940. =================
  941. R_AddDrawSurf
  942. =================
  943. */
  944. void R_AddDrawSurf( const srfTriangles_t *tri, const viewEntity_t *space, const renderEntity_t *renderEntity,
  945. const idMaterial *shader, const idScreenRect &scissor ) {
  946. drawSurf_t *drawSurf;
  947. const float *shaderParms;
  948. static float refRegs[MAX_EXPRESSION_REGISTERS]; // don't put on stack, or VC++ will do a page touch
  949. float generatedShaderParms[MAX_ENTITY_SHADER_PARMS];
  950. drawSurf = (drawSurf_t *)R_FrameAlloc( sizeof( *drawSurf ) );
  951. drawSurf->geo = tri;
  952. drawSurf->space = space;
  953. drawSurf->material = shader;
  954. drawSurf->scissorRect = scissor;
  955. drawSurf->sort = shader->GetSort() + tr.sortOffset;
  956. drawSurf->dsFlags = 0;
  957. // bumping this offset each time causes surfaces with equal sort orders to still
  958. // deterministically draw in the order they are added
  959. tr.sortOffset += 0.000001f;
  960. // if it doesn't fit, resize the list
  961. if ( tr.viewDef->numDrawSurfs == tr.viewDef->maxDrawSurfs ) {
  962. drawSurf_t **old = tr.viewDef->drawSurfs;
  963. int count;
  964. if ( tr.viewDef->maxDrawSurfs == 0 ) {
  965. tr.viewDef->maxDrawSurfs = INITIAL_DRAWSURFS;
  966. count = 0;
  967. } else {
  968. count = tr.viewDef->maxDrawSurfs * sizeof( tr.viewDef->drawSurfs[0] );
  969. tr.viewDef->maxDrawSurfs *= 2;
  970. }
  971. tr.viewDef->drawSurfs = (drawSurf_t **)R_FrameAlloc( tr.viewDef->maxDrawSurfs * sizeof( tr.viewDef->drawSurfs[0] ) );
  972. memcpy( tr.viewDef->drawSurfs, old, count );
  973. }
  974. tr.viewDef->drawSurfs[tr.viewDef->numDrawSurfs] = drawSurf;
  975. tr.viewDef->numDrawSurfs++;
  976. // process the shader expressions for conditionals / color / texcoords
  977. const float *constRegs = shader->ConstantRegisters();
  978. if ( constRegs ) {
  979. // shader only uses constant values
  980. drawSurf->shaderRegisters = constRegs;
  981. } else {
  982. float *regs = (float *)R_FrameAlloc( shader->GetNumRegisters() * sizeof( float ) );
  983. drawSurf->shaderRegisters = regs;
  984. // a reference shader will take the calculated stage color value from another shader
  985. // and use that for the parm0-parm3 of the current shader, which allows a stage of
  986. // a light model and light flares to pick up different flashing tables from
  987. // different light shaders
  988. if ( renderEntity->referenceShader ) {
  989. // evaluate the reference shader to find our shader parms
  990. const shaderStage_t *pStage;
  991. renderEntity->referenceShader->EvaluateRegisters( refRegs, renderEntity->shaderParms, tr.viewDef, renderEntity->referenceSound );
  992. pStage = renderEntity->referenceShader->GetStage(0);
  993. memcpy( generatedShaderParms, renderEntity->shaderParms, sizeof( generatedShaderParms ) );
  994. generatedShaderParms[0] = refRegs[ pStage->color.registers[0] ];
  995. generatedShaderParms[1] = refRegs[ pStage->color.registers[1] ];
  996. generatedShaderParms[2] = refRegs[ pStage->color.registers[2] ];
  997. shaderParms = generatedShaderParms;
  998. } else {
  999. // evaluate with the entityDef's shader parms
  1000. shaderParms = renderEntity->shaderParms;
  1001. }
  1002. float oldFloatTime;
  1003. int oldTime;
  1004. if ( space->entityDef && space->entityDef->parms.timeGroup ) {
  1005. oldFloatTime = tr.viewDef->floatTime;
  1006. oldTime = tr.viewDef->renderView.time;
  1007. tr.viewDef->floatTime = game->GetTimeGroupTime( space->entityDef->parms.timeGroup ) * 0.001;
  1008. tr.viewDef->renderView.time = game->GetTimeGroupTime( space->entityDef->parms.timeGroup );
  1009. }
  1010. shader->EvaluateRegisters( regs, shaderParms, tr.viewDef, renderEntity->referenceSound );
  1011. if ( space->entityDef && space->entityDef->parms.timeGroup ) {
  1012. tr.viewDef->floatTime = oldFloatTime;
  1013. tr.viewDef->renderView.time = oldTime;
  1014. }
  1015. }
  1016. // check for deformations
  1017. R_DeformDrawSurf( drawSurf );
  1018. // skybox surfaces need a dynamic texgen
  1019. switch( shader->Texgen() ) {
  1020. case TG_SKYBOX_CUBE:
  1021. R_SkyboxTexGen( drawSurf, tr.viewDef->renderView.vieworg );
  1022. break;
  1023. case TG_WOBBLESKY_CUBE:
  1024. R_WobbleskyTexGen( drawSurf, tr.viewDef->renderView.vieworg );
  1025. break;
  1026. }
  1027. // check for gui surfaces
  1028. idUserInterface *gui = NULL;
  1029. if ( !space->entityDef ) {
  1030. gui = shader->GlobalGui();
  1031. } else {
  1032. int guiNum = shader->GetEntityGui() - 1;
  1033. if ( guiNum >= 0 && guiNum < MAX_RENDERENTITY_GUI ) {
  1034. gui = renderEntity->gui[ guiNum ];
  1035. }
  1036. if ( gui == NULL ) {
  1037. gui = shader->GlobalGui();
  1038. }
  1039. }
  1040. if ( gui ) {
  1041. // force guis on the fast time
  1042. float oldFloatTime;
  1043. int oldTime;
  1044. oldFloatTime = tr.viewDef->floatTime;
  1045. oldTime = tr.viewDef->renderView.time;
  1046. tr.viewDef->floatTime = game->GetTimeGroupTime( 1 ) * 0.001;
  1047. tr.viewDef->renderView.time = game->GetTimeGroupTime( 1 );
  1048. idBounds ndcBounds;
  1049. if ( !R_PreciseCullSurface( drawSurf, ndcBounds ) ) {
  1050. // did we ever use this to forward an entity color to a gui that didn't set color?
  1051. // memcpy( tr.guiShaderParms, shaderParms, sizeof( tr.guiShaderParms ) );
  1052. R_RenderGuiSurf( gui, drawSurf );
  1053. }
  1054. tr.viewDef->floatTime = oldFloatTime;
  1055. tr.viewDef->renderView.time = oldTime;
  1056. }
  1057. // we can't add subviews at this point, because that would
  1058. // increment tr.viewCount, messing up the rest of the surface
  1059. // adds for this view
  1060. }
  1061. /*
  1062. ===============
  1063. R_AddAmbientDrawsurfs
  1064. Adds surfaces for the given viewEntity
  1065. Walks through the viewEntitys list and creates drawSurf_t for each surface of
  1066. each viewEntity that has a non-empty scissorRect
  1067. ===============
  1068. */
  1069. static void R_AddAmbientDrawsurfs( viewEntity_t *vEntity ) {
  1070. int i, total;
  1071. idRenderEntityLocal *def;
  1072. srfTriangles_t *tri;
  1073. idRenderModel *model;
  1074. const idMaterial *shader;
  1075. def = vEntity->entityDef;
  1076. if ( def->dynamicModel ) {
  1077. model = def->dynamicModel;
  1078. } else {
  1079. model = def->parms.hModel;
  1080. }
  1081. // add all the surfaces
  1082. total = model->NumSurfaces();
  1083. for ( i = 0 ; i < total ; i++ ) {
  1084. const modelSurface_t *surf = model->Surface( i );
  1085. // for debugging, only show a single surface at a time
  1086. if ( r_singleSurface.GetInteger() >= 0 && i != r_singleSurface.GetInteger() ) {
  1087. continue;
  1088. }
  1089. tri = surf->geometry;
  1090. if ( !tri ) {
  1091. continue;
  1092. }
  1093. if ( !tri->numIndexes ) {
  1094. continue;
  1095. }
  1096. shader = surf->shader;
  1097. shader = R_RemapShaderBySkin( shader, def->parms.customSkin, def->parms.customShader );
  1098. R_GlobalShaderOverride( &shader );
  1099. if ( !shader ) {
  1100. continue;
  1101. }
  1102. if ( !shader->IsDrawn() ) {
  1103. continue;
  1104. }
  1105. // debugging tool to make sure we are have the correct pre-calculated bounds
  1106. if ( r_checkBounds.GetBool() ) {
  1107. int j, k;
  1108. for ( j = 0 ; j < tri->numVerts ; j++ ) {
  1109. for ( k = 0 ; k < 3 ; k++ ) {
  1110. if ( tri->verts[j].xyz[k] > tri->bounds[1][k] + CHECK_BOUNDS_EPSILON
  1111. || tri->verts[j].xyz[k] < tri->bounds[0][k] - CHECK_BOUNDS_EPSILON ) {
  1112. common->Printf( "bad tri->bounds on %s:%s\n", def->parms.hModel->Name(), shader->GetName() );
  1113. break;
  1114. }
  1115. if ( tri->verts[j].xyz[k] > def->referenceBounds[1][k] + CHECK_BOUNDS_EPSILON
  1116. || tri->verts[j].xyz[k] < def->referenceBounds[0][k] - CHECK_BOUNDS_EPSILON ) {
  1117. common->Printf( "bad referenceBounds on %s:%s\n", def->parms.hModel->Name(), shader->GetName() );
  1118. break;
  1119. }
  1120. }
  1121. if ( k != 3 ) {
  1122. break;
  1123. }
  1124. }
  1125. }
  1126. if ( !R_CullLocalBox( tri->bounds, vEntity->modelMatrix, 5, tr.viewDef->frustum ) ) {
  1127. def->visibleCount = tr.viewCount;
  1128. // make sure we have an ambient cache
  1129. if ( !R_CreateAmbientCache( tri, shader->ReceivesLighting() ) ) {
  1130. // don't add anything if the vertex cache was too full to give us an ambient cache
  1131. return;
  1132. }
  1133. // touch it so it won't get purged
  1134. vertexCache.Touch( tri->ambientCache );
  1135. if ( r_useIndexBuffers.GetBool() && !tri->indexCache ) {
  1136. vertexCache.Alloc( tri->indexes, tri->numIndexes * sizeof( tri->indexes[0] ), &tri->indexCache, true );
  1137. }
  1138. if ( tri->indexCache ) {
  1139. vertexCache.Touch( tri->indexCache );
  1140. }
  1141. // add the surface for drawing
  1142. R_AddDrawSurf( tri, vEntity, &vEntity->entityDef->parms, shader, vEntity->scissorRect );
  1143. // ambientViewCount is used to allow light interactions to be rejected
  1144. // if the ambient surface isn't visible at all
  1145. tri->ambientViewCount = tr.viewCount;
  1146. }
  1147. }
  1148. // add the lightweight decal surfaces
  1149. for ( idRenderModelDecal *decal = def->decals; decal; decal = decal->Next() ) {
  1150. decal->AddDecalDrawSurf( vEntity );
  1151. }
  1152. }
  1153. /*
  1154. ==================
  1155. R_CalcEntityScissorRectangle
  1156. ==================
  1157. */
  1158. idScreenRect R_CalcEntityScissorRectangle( viewEntity_t *vEntity ) {
  1159. idBounds bounds;
  1160. idRenderEntityLocal *def = vEntity->entityDef;
  1161. tr.viewDef->viewFrustum.ProjectionBounds( idBox( def->referenceBounds, def->parms.origin, def->parms.axis ), bounds );
  1162. return R_ScreenRectFromViewFrustumBounds( bounds );
  1163. }
  1164. /*
  1165. ===================
  1166. R_AddModelSurfaces
  1167. Here is where dynamic models actually get instantiated, and necessary
  1168. interactions get created. This is all done on a sort-by-model basis
  1169. to keep source data in cache (most likely L2) as any interactions and
  1170. shadows are generated, since dynamic models will typically be lit by
  1171. two or more lights.
  1172. ===================
  1173. */
  1174. void R_AddModelSurfaces( void ) {
  1175. viewEntity_t *vEntity;
  1176. idInteraction *inter, *next;
  1177. idRenderModel *model;
  1178. // clear the ambient surface list
  1179. tr.viewDef->numDrawSurfs = 0;
  1180. tr.viewDef->maxDrawSurfs = 0; // will be set to INITIAL_DRAWSURFS on R_AddDrawSurf
  1181. // go through each entity that is either visible to the view, or to
  1182. // any light that intersects the view (for shadows)
  1183. for ( vEntity = tr.viewDef->viewEntitys; vEntity; vEntity = vEntity->next ) {
  1184. if ( r_useEntityScissors.GetBool() ) {
  1185. // calculate the screen area covered by the entity
  1186. idScreenRect scissorRect = R_CalcEntityScissorRectangle( vEntity );
  1187. // intersect with the portal crossing scissor rectangle
  1188. vEntity->scissorRect.Intersect( scissorRect );
  1189. if ( r_showEntityScissors.GetBool() ) {
  1190. R_ShowColoredScreenRect( vEntity->scissorRect, vEntity->entityDef->index );
  1191. }
  1192. }
  1193. float oldFloatTime;
  1194. int oldTime;
  1195. game->SelectTimeGroup( vEntity->entityDef->parms.timeGroup );
  1196. if ( vEntity->entityDef->parms.timeGroup ) {
  1197. oldFloatTime = tr.viewDef->floatTime;
  1198. oldTime = tr.viewDef->renderView.time;
  1199. tr.viewDef->floatTime = game->GetTimeGroupTime( vEntity->entityDef->parms.timeGroup ) * 0.001;
  1200. tr.viewDef->renderView.time = game->GetTimeGroupTime( vEntity->entityDef->parms.timeGroup );
  1201. }
  1202. if ( tr.viewDef->isXraySubview && vEntity->entityDef->parms.xrayIndex == 1 ) {
  1203. if ( vEntity->entityDef->parms.timeGroup ) {
  1204. tr.viewDef->floatTime = oldFloatTime;
  1205. tr.viewDef->renderView.time = oldTime;
  1206. }
  1207. continue;
  1208. } else if ( !tr.viewDef->isXraySubview && vEntity->entityDef->parms.xrayIndex == 2 ) {
  1209. if ( vEntity->entityDef->parms.timeGroup ) {
  1210. tr.viewDef->floatTime = oldFloatTime;
  1211. tr.viewDef->renderView.time = oldTime;
  1212. }
  1213. continue;
  1214. }
  1215. // add the ambient surface if it has a visible rectangle
  1216. if ( !vEntity->scissorRect.IsEmpty() ) {
  1217. model = R_EntityDefDynamicModel( vEntity->entityDef );
  1218. if ( model == NULL || model->NumSurfaces() <= 0 ) {
  1219. if ( vEntity->entityDef->parms.timeGroup ) {
  1220. tr.viewDef->floatTime = oldFloatTime;
  1221. tr.viewDef->renderView.time = oldTime;
  1222. }
  1223. continue;
  1224. }
  1225. R_AddAmbientDrawsurfs( vEntity );
  1226. tr.pc.c_visibleViewEntities++;
  1227. } else {
  1228. tr.pc.c_shadowViewEntities++;
  1229. }
  1230. //
  1231. // for all the entity / light interactions on this entity, add them to the view
  1232. //
  1233. if ( tr.viewDef->isXraySubview ) {
  1234. if ( vEntity->entityDef->parms.xrayIndex == 2 ) {
  1235. for ( inter = vEntity->entityDef->firstInteraction; inter != NULL && !inter->IsEmpty(); inter = next ) {
  1236. next = inter->entityNext;
  1237. if ( inter->lightDef->viewCount != tr.viewCount ) {
  1238. continue;
  1239. }
  1240. inter->AddActiveInteraction();
  1241. }
  1242. }
  1243. } else {
  1244. // all empty interactions are at the end of the list so once the
  1245. // first is encountered all the remaining interactions are empty
  1246. for ( inter = vEntity->entityDef->firstInteraction; inter != NULL && !inter->IsEmpty(); inter = next ) {
  1247. next = inter->entityNext;
  1248. // skip any lights that aren't currently visible
  1249. // this is run after any lights that are turned off have already
  1250. // been removed from the viewLights list, and had their viewCount cleared
  1251. if ( inter->lightDef->viewCount != tr.viewCount ) {
  1252. continue;
  1253. }
  1254. inter->AddActiveInteraction();
  1255. }
  1256. }
  1257. if ( vEntity->entityDef->parms.timeGroup ) {
  1258. tr.viewDef->floatTime = oldFloatTime;
  1259. tr.viewDef->renderView.time = oldTime;
  1260. }
  1261. }
  1262. }
  1263. /*
  1264. =====================
  1265. R_RemoveUnecessaryViewLights
  1266. =====================
  1267. */
  1268. void R_RemoveUnecessaryViewLights( void ) {
  1269. viewLight_t *vLight;
  1270. // go through each visible light
  1271. for ( vLight = tr.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
  1272. // if the light didn't have any lit surfaces visible, there is no need to
  1273. // draw any of the shadows. We still keep the vLight for debugging
  1274. // draws
  1275. if ( !vLight->localInteractions && !vLight->globalInteractions && !vLight->translucentInteractions ) {
  1276. vLight->localShadows = NULL;
  1277. vLight->globalShadows = NULL;
  1278. }
  1279. }
  1280. if ( r_useShadowSurfaceScissor.GetBool() ) {
  1281. // shrink the light scissor rect to only intersect the surfaces that will actually be drawn.
  1282. // This doesn't seem to actually help, perhaps because the surface scissor
  1283. // rects aren't actually the surface, but only the portal clippings.
  1284. for ( vLight = tr.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
  1285. const drawSurf_t *surf;
  1286. idScreenRect surfRect;
  1287. if ( !vLight->lightShader->LightCastsShadows() ) {
  1288. continue;
  1289. }
  1290. surfRect.Clear();
  1291. for ( surf = vLight->globalInteractions ; surf ; surf = surf->nextOnLight ) {
  1292. surfRect.Union( surf->scissorRect );
  1293. }
  1294. for ( surf = vLight->localShadows ; surf ; surf = surf->nextOnLight ) {
  1295. const_cast<drawSurf_t *>(surf)->scissorRect.Intersect( surfRect );
  1296. }
  1297. for ( surf = vLight->localInteractions ; surf ; surf = surf->nextOnLight ) {
  1298. surfRect.Union( surf->scissorRect );
  1299. }
  1300. for ( surf = vLight->globalShadows ; surf ; surf = surf->nextOnLight ) {
  1301. const_cast<drawSurf_t *>(surf)->scissorRect.Intersect( surfRect );
  1302. }
  1303. for ( surf = vLight->translucentInteractions ; surf ; surf = surf->nextOnLight ) {
  1304. surfRect.Union( surf->scissorRect );
  1305. }
  1306. vLight->scissorRect.Intersect( surfRect );
  1307. }
  1308. }
  1309. }