RenderSystem_init.cpp 86 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348
  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. // Vista OpenGL wrapper check
  24. #ifdef _WIN32
  25. #include "../sys/win32/win_local.h"
  26. #endif
  27. // functions that are not called every frame
  28. glconfig_t glConfig;
  29. static void GfxInfo_f( void );
  30. const char *r_rendererArgs[] = { "best", "arb", "arb2", "Cg", "exp", "nv10", "nv20", "r200", NULL };
  31. idCVar r_inhibitFragmentProgram( "r_inhibitFragmentProgram", "0", CVAR_RENDERER | CVAR_BOOL, "ignore the fragment program extension" );
  32. idCVar r_glDriver( "r_glDriver", "", CVAR_RENDERER, "\"opengl32\", etc." );
  33. idCVar r_useLightPortalFlow( "r_useLightPortalFlow", "1", CVAR_RENDERER | CVAR_BOOL, "use a more precise area reference determination" );
  34. idCVar r_multiSamples( "r_multiSamples", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "number of antialiasing samples" );
  35. idCVar r_mode( "r_mode", "5", CVAR_ARCHIVE | CVAR_RENDERER | CVAR_INTEGER, "video mode number" );
  36. idCVar r_displayRefresh( "r_displayRefresh", "0", CVAR_RENDERER | CVAR_INTEGER | CVAR_NOCHEAT, "optional display refresh rate option for vid mode", 0.0f, 200.0f );
  37. idCVar r_fullscreen( "r_fullscreen", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "0 = windowed, 1 = full screen" );
  38. idCVar r_customWidth( "r_customWidth", "3840", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "custom screen width. set r_mode to -1 to activate" );
  39. idCVar r_customHeight( "r_customHeight", "1080", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "custom screen height. set r_mode to -1 to activate" );
  40. idCVar r_singleTriangle( "r_singleTriangle", "0", CVAR_RENDERER | CVAR_BOOL, "only draw a single triangle per primitive" );
  41. idCVar r_checkBounds( "r_checkBounds", "0", CVAR_RENDERER | CVAR_BOOL, "compare all surface bounds with precalculated ones" );
  42. idCVar r_useNV20MonoLights( "r_useNV20MonoLights", "1", CVAR_RENDERER | CVAR_INTEGER, "use pass optimization for mono lights" );
  43. idCVar r_useConstantMaterials( "r_useConstantMaterials", "1", CVAR_RENDERER | CVAR_BOOL, "use pre-calculated material registers if possible" );
  44. idCVar r_useTripleTextureARB( "r_useTripleTextureARB", "1", CVAR_RENDERER | CVAR_BOOL, "cards with 3+ texture units do a two pass instead of three pass" );
  45. idCVar r_useSilRemap( "r_useSilRemap", "1", CVAR_RENDERER | CVAR_BOOL, "consider verts with the same XYZ, but different ST the same for shadows" );
  46. idCVar r_useNodeCommonChildren( "r_useNodeCommonChildren", "1", CVAR_RENDERER | CVAR_BOOL, "stop pushing reference bounds early when possible" );
  47. idCVar r_useShadowProjectedCull( "r_useShadowProjectedCull", "1", CVAR_RENDERER | CVAR_BOOL, "discard triangles outside light volume before shadowing" );
  48. idCVar r_useShadowVertexProgram( "r_useShadowVertexProgram", "1", CVAR_RENDERER | CVAR_BOOL, "do the shadow projection in the vertex program on capable cards" );
  49. idCVar r_useShadowSurfaceScissor( "r_useShadowSurfaceScissor", "1", CVAR_RENDERER | CVAR_BOOL, "scissor shadows by the scissor rect of the interaction surfaces" );
  50. idCVar r_useInteractionTable( "r_useInteractionTable", "1", CVAR_RENDERER | CVAR_BOOL, "create a full entityDefs * lightDefs table to make finding interactions faster" );
  51. idCVar r_useTurboShadow( "r_useTurboShadow", "1", CVAR_RENDERER | CVAR_BOOL, "use the infinite projection with W technique for dynamic shadows" );
  52. idCVar r_useTwoSidedStencil( "r_useTwoSidedStencil", "1", CVAR_RENDERER | CVAR_BOOL, "do stencil shadows in one pass with different ops on each side" );
  53. idCVar r_useDeferredTangents( "r_useDeferredTangents", "1", CVAR_RENDERER | CVAR_BOOL, "defer tangents calculations after deform" );
  54. idCVar r_useCachedDynamicModels( "r_useCachedDynamicModels", "1", CVAR_RENDERER | CVAR_BOOL, "cache snapshots of dynamic models" );
  55. idCVar r_useVertexBuffers( "r_useVertexBuffers", "1", CVAR_RENDERER | CVAR_INTEGER, "use ARB_vertex_buffer_object for vertexes", 0, 1, idCmdSystem::ArgCompletion_Integer<0,1> );
  56. idCVar r_useIndexBuffers( "r_useIndexBuffers", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "use ARB_vertex_buffer_object for indexes", 0, 1, idCmdSystem::ArgCompletion_Integer<0,1> );
  57. idCVar r_useStateCaching( "r_useStateCaching", "1", CVAR_RENDERER | CVAR_BOOL, "avoid redundant state changes in GL_*() calls" );
  58. idCVar r_useInfiniteFarZ( "r_useInfiniteFarZ", "1", CVAR_RENDERER | CVAR_BOOL, "use the no-far-clip-plane trick" );
  59. idCVar r_znear( "r_znear", "3", CVAR_RENDERER | CVAR_FLOAT, "near Z clip plane distance", 0.001f, 200.0f );
  60. idCVar r_ignoreGLErrors( "r_ignoreGLErrors", "1", CVAR_RENDERER | CVAR_BOOL, "ignore GL errors" );
  61. idCVar r_finish( "r_finish", "0", CVAR_RENDERER | CVAR_BOOL, "force a call to glFinish() every frame" );
  62. idCVar r_swapInterval( "r_swapInterval", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "changes wglSwapIntarval (v-sync)" );
  63. idCVar r_gamma( "r_gamma", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_FLOAT, "changes gamma tables", 0.5f, 3.0f );
  64. idCVar r_brightness( "r_brightness", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_FLOAT, "changes gamma tables", 0.5f, 2.0f );
  65. idCVar r_renderer( "r_renderer", "best", CVAR_RENDERER | CVAR_ARCHIVE, "hardware specific renderer path to use", r_rendererArgs, idCmdSystem::ArgCompletion_String<r_rendererArgs> );
  66. idCVar r_jitter( "r_jitter", "0", CVAR_RENDERER | CVAR_BOOL, "randomly subpixel jitter the projection matrix" );
  67. idCVar r_skipSuppress( "r_skipSuppress", "0", CVAR_RENDERER | CVAR_BOOL, "ignore the per-view suppressions" );
  68. idCVar r_skipPostProcess( "r_skipPostProcess", "0", CVAR_RENDERER | CVAR_BOOL, "skip all post-process renderings" );
  69. idCVar r_skipLightScale( "r_skipLightScale", "0", CVAR_RENDERER | CVAR_BOOL, "don't do any post-interaction light scaling, makes things dim on low-dynamic range cards" );
  70. idCVar r_skipInteractions( "r_skipInteractions", "0", CVAR_RENDERER | CVAR_BOOL, "skip all light/surface interaction drawing" );
  71. idCVar r_skipDynamicTextures( "r_skipDynamicTextures", "0", CVAR_RENDERER | CVAR_BOOL, "don't dynamically create textures" );
  72. idCVar r_skipCopyTexture( "r_skipCopyTexture", "0", CVAR_RENDERER | CVAR_BOOL, "do all rendering, but don't actually copyTexSubImage2D" );
  73. idCVar r_skipBackEnd( "r_skipBackEnd", "0", CVAR_RENDERER | CVAR_BOOL, "don't draw anything" );
  74. idCVar r_skipRender( "r_skipRender", "0", CVAR_RENDERER | CVAR_BOOL, "skip 3D rendering, but pass 2D" );
  75. idCVar r_skipRenderContext( "r_skipRenderContext", "0", CVAR_RENDERER | CVAR_BOOL, "NULL the rendering context during backend 3D rendering" );
  76. idCVar r_skipTranslucent( "r_skipTranslucent", "0", CVAR_RENDERER | CVAR_BOOL, "skip the translucent interaction rendering" );
  77. idCVar r_skipAmbient( "r_skipAmbient", "0", CVAR_RENDERER | CVAR_BOOL, "bypasses all non-interaction drawing" );
  78. idCVar r_skipNewAmbient( "r_skipNewAmbient", "0", CVAR_RENDERER | CVAR_BOOL | CVAR_ARCHIVE, "bypasses all vertex/fragment program ambient drawing" );
  79. idCVar r_skipBlendLights( "r_skipBlendLights", "0", CVAR_RENDERER | CVAR_BOOL, "skip all blend lights" );
  80. idCVar r_skipFogLights( "r_skipFogLights", "0", CVAR_RENDERER | CVAR_BOOL, "skip all fog lights" );
  81. idCVar r_skipDeforms( "r_skipDeforms", "0", CVAR_RENDERER | CVAR_BOOL, "leave all deform materials in their original state" );
  82. idCVar r_skipFrontEnd( "r_skipFrontEnd", "0", CVAR_RENDERER | CVAR_BOOL, "bypasses all front end work, but 2D gui rendering still draws" );
  83. idCVar r_skipUpdates( "r_skipUpdates", "0", CVAR_RENDERER | CVAR_BOOL, "1 = don't accept any entity or light updates, making everything static" );
  84. idCVar r_skipOverlays( "r_skipOverlays", "0", CVAR_RENDERER | CVAR_BOOL, "skip overlay surfaces" );
  85. idCVar r_skipSpecular( "r_skipSpecular", "0", CVAR_RENDERER | CVAR_BOOL | CVAR_CHEAT | CVAR_ARCHIVE, "use black for specular1" );
  86. idCVar r_skipBump( "r_skipBump", "0", CVAR_RENDERER | CVAR_BOOL | CVAR_ARCHIVE, "uses a flat surface instead of the bump map" );
  87. idCVar r_skipDiffuse( "r_skipDiffuse", "0", CVAR_RENDERER | CVAR_BOOL, "use black for diffuse" );
  88. idCVar r_skipROQ( "r_skipROQ", "0", CVAR_RENDERER | CVAR_BOOL, "skip ROQ decoding" );
  89. idCVar r_ignore( "r_ignore", "0", CVAR_RENDERER, "used for random debugging without defining new vars" );
  90. idCVar r_ignore2( "r_ignore2", "0", CVAR_RENDERER, "used for random debugging without defining new vars" );
  91. idCVar r_usePreciseTriangleInteractions( "r_usePreciseTriangleInteractions", "0", CVAR_RENDERER | CVAR_BOOL, "1 = do winding clipping to determine if each ambiguous tri should be lit" );
  92. idCVar r_useCulling( "r_useCulling", "2", CVAR_RENDERER | CVAR_INTEGER, "0 = none, 1 = sphere, 2 = sphere + box", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  93. idCVar r_useLightCulling( "r_useLightCulling", "3", CVAR_RENDERER | CVAR_INTEGER, "0 = none, 1 = box, 2 = exact clip of polyhedron faces, 3 = also areas", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  94. idCVar r_useLightScissors( "r_useLightScissors", "1", CVAR_RENDERER | CVAR_BOOL, "1 = use custom scissor rectangle for each light" );
  95. idCVar r_useClippedLightScissors( "r_useClippedLightScissors", "1", CVAR_RENDERER | CVAR_INTEGER, "0 = full screen when near clipped, 1 = exact when near clipped, 2 = exact always", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  96. idCVar r_useEntityCulling( "r_useEntityCulling", "1", CVAR_RENDERER | CVAR_BOOL, "0 = none, 1 = box" );
  97. idCVar r_useEntityScissors( "r_useEntityScissors", "0", CVAR_RENDERER | CVAR_BOOL, "1 = use custom scissor rectangle for each entity" );
  98. idCVar r_useInteractionCulling( "r_useInteractionCulling", "1", CVAR_RENDERER | CVAR_BOOL, "1 = cull interactions" );
  99. idCVar r_useInteractionScissors( "r_useInteractionScissors", "2", CVAR_RENDERER | CVAR_INTEGER, "1 = use a custom scissor rectangle for each shadow interaction, 2 = also crop using portal scissors", -2, 2, idCmdSystem::ArgCompletion_Integer<-2,2> );
  100. idCVar r_useShadowCulling( "r_useShadowCulling", "1", CVAR_RENDERER | CVAR_BOOL, "try to cull shadows from partially visible lights" );
  101. idCVar r_useFrustumFarDistance( "r_useFrustumFarDistance", "0", CVAR_RENDERER | CVAR_FLOAT, "if != 0 force the view frustum far distance to this distance" );
  102. idCVar r_logFile( "r_logFile", "0", CVAR_RENDERER | CVAR_INTEGER, "number of frames to emit GL logs" );
  103. //BC ATI video cards have issues with r_clear being a non-zero value.
  104. idCVar r_clear( "r_clear", "0", CVAR_RENDERER, "force screen clear every frame, 1 = purple, 2 = black, 'r g b' = custom" );
  105. idCVar r_offsetFactor( "r_offsetfactor", "0", CVAR_RENDERER | CVAR_FLOAT, "polygon offset parameter" );
  106. idCVar r_offsetUnits( "r_offsetunits", "-600", CVAR_RENDERER | CVAR_FLOAT, "polygon offset parameter" );
  107. idCVar r_shadowPolygonOffset( "r_shadowPolygonOffset", "-1", CVAR_RENDERER | CVAR_FLOAT, "bias value added to depth test for stencil shadow drawing" );
  108. idCVar r_shadowPolygonFactor( "r_shadowPolygonFactor", "0", CVAR_RENDERER | CVAR_FLOAT, "scale value for stencil shadow drawing" );
  109. idCVar r_frontBuffer( "r_frontBuffer", "0", CVAR_RENDERER | CVAR_BOOL, "draw to front buffer for debugging" );
  110. idCVar r_skipSubviews( "r_skipSubviews", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = don't render any gui elements on surfaces" );
  111. idCVar r_skipGuiShaders( "r_skipGuiShaders", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = skip all gui elements on surfaces, 2 = skip drawing but still handle events, 3 = draw but skip events", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  112. idCVar r_skipParticles( "r_skipParticles", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = skip all particle systems", 0, 1, idCmdSystem::ArgCompletion_Integer<0,1> );
  113. idCVar r_subviewOnly( "r_subviewOnly", "0", CVAR_RENDERER | CVAR_BOOL, "1 = don't render main view, allowing subviews to be debugged" );
  114. idCVar r_shadows( "r_shadows", "1", CVAR_RENDERER | CVAR_BOOL | CVAR_ARCHIVE, "enable shadows" );
  115. idCVar r_testARBProgram( "r_testARBProgram", "0", CVAR_RENDERER | CVAR_BOOL, "experiment with vertex/fragment programs" );
  116. idCVar r_testGamma( "r_testGamma", "0", CVAR_RENDERER | CVAR_FLOAT, "if > 0 draw a grid pattern to test gamma levels", 0, 195 );
  117. idCVar r_testGammaBias( "r_testGammaBias", "0", CVAR_RENDERER | CVAR_FLOAT, "if > 0 draw a grid pattern to test gamma levels" );
  118. idCVar r_testStepGamma( "r_testStepGamma", "0", CVAR_RENDERER | CVAR_FLOAT, "if > 0 draw a grid pattern to test gamma levels" );
  119. idCVar r_lightScale( "r_lightScale", "2", CVAR_RENDERER | CVAR_FLOAT, "all light intensities are multiplied by this" );
  120. idCVar r_lightSourceRadius( "r_lightSourceRadius", "0", CVAR_RENDERER | CVAR_FLOAT, "for soft-shadow sampling" );
  121. idCVar r_flareSize( "r_flareSize", "1", CVAR_RENDERER | CVAR_FLOAT, "scale the flare deforms from the material def" );
  122. idCVar r_useExternalShadows( "r_useExternalShadows", "1", CVAR_RENDERER | CVAR_INTEGER, "1 = skip drawing caps when outside the light volume, 2 = force to no caps for testing", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  123. idCVar r_useOptimizedShadows( "r_useOptimizedShadows", "1", CVAR_RENDERER | CVAR_BOOL, "use the dmap generated static shadow volumes" );
  124. idCVar r_useScissor( "r_useScissor", "1", CVAR_RENDERER | CVAR_BOOL, "scissor clip as portals and lights are processed" );
  125. idCVar r_useCombinerDisplayLists( "r_useCombinerDisplayLists", "1", CVAR_RENDERER | CVAR_BOOL | CVAR_NOCHEAT, "put all nvidia register combiner programming in display lists" );
  126. idCVar r_useDepthBoundsTest( "r_useDepthBoundsTest", "1", CVAR_RENDERER | CVAR_BOOL, "use depth bounds test to reduce shadow fill" );
  127. idCVar r_screenFraction( "r_screenFraction", "100", CVAR_RENDERER | CVAR_INTEGER, "for testing fill rate, the resolution of the entire screen can be changed" );
  128. idCVar r_demonstrateBug( "r_demonstrateBug", "0", CVAR_RENDERER | CVAR_BOOL, "used during development to show IHV's their problems" );
  129. idCVar r_usePortals( "r_usePortals", "1", CVAR_RENDERER | CVAR_BOOL, " 1 = use portals to perform area culling, otherwise draw everything" );
  130. idCVar r_singleLight( "r_singleLight", "-1", CVAR_RENDERER | CVAR_INTEGER, "suppress all but one light" );
  131. idCVar r_singleEntity( "r_singleEntity", "-1", CVAR_RENDERER | CVAR_INTEGER, "suppress all but one entity" );
  132. idCVar r_singleSurface( "r_singleSurface", "-1", CVAR_RENDERER | CVAR_INTEGER, "suppress all but one surface on each entity" );
  133. idCVar r_singleArea( "r_singleArea", "0", CVAR_RENDERER | CVAR_BOOL, "only draw the portal area the view is actually in" );
  134. idCVar r_forceLoadImages( "r_forceLoadImages", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "draw all images to screen after registration" );
  135. idCVar r_orderIndexes( "r_orderIndexes", "1", CVAR_RENDERER | CVAR_BOOL, "perform index reorganization to optimize vertex use" );
  136. idCVar r_lightAllBackFaces( "r_lightAllBackFaces", "0", CVAR_RENDERER | CVAR_BOOL, "light all the back faces, even when they would be shadowed" );
  137. // visual debugging info
  138. idCVar r_showPortals( "r_showPortals", "0", CVAR_RENDERER | CVAR_BOOL, "draw portal outlines in color based on passed / not passed" );
  139. idCVar r_showUnsmoothedTangents( "r_showUnsmoothedTangents", "0", CVAR_RENDERER | CVAR_BOOL, "if 1, put all nvidia register combiner programming in display lists" );
  140. idCVar r_showSilhouette( "r_showSilhouette", "0", CVAR_RENDERER | CVAR_BOOL, "highlight edges that are casting shadow planes" );
  141. idCVar r_showVertexColor( "r_showVertexColor", "0", CVAR_RENDERER | CVAR_BOOL, "draws all triangles with the solid vertex color" );
  142. idCVar r_showUpdates( "r_showUpdates", "0", CVAR_RENDERER | CVAR_BOOL, "report entity and light updates and ref counts" );
  143. idCVar r_showDemo( "r_showDemo", "0", CVAR_RENDERER | CVAR_BOOL, "report reads and writes to the demo file" );
  144. idCVar r_showDynamic( "r_showDynamic", "0", CVAR_RENDERER | CVAR_BOOL, "report stats on dynamic surface generation" );
  145. idCVar r_showLightScale( "r_showLightScale", "0", CVAR_RENDERER | CVAR_BOOL, "report the scale factor applied to drawing for overbrights" );
  146. idCVar r_showDefs( "r_showDefs", "0", CVAR_RENDERER | CVAR_BOOL, "report the number of modeDefs and lightDefs in view" );
  147. idCVar r_showTrace( "r_showTrace", "0", CVAR_RENDERER | CVAR_INTEGER, "show the intersection of an eye trace with the world", idCmdSystem::ArgCompletion_Integer<0,2> );
  148. idCVar r_showIntensity( "r_showIntensity", "0", CVAR_RENDERER | CVAR_BOOL, "draw the screen colors based on intensity, red = 0, green = 128, blue = 255" );
  149. idCVar r_showImages( "r_showImages", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = show all images instead of rendering, 2 = show in proportional size", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  150. idCVar r_showSmp( "r_showSmp", "0", CVAR_RENDERER | CVAR_BOOL, "show which end (front or back) is blocking" );
  151. idCVar r_showLights( "r_showLights", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = just print volumes numbers, highlighting ones covering the view, 2 = also draw planes of each volume, 3 = also draw edges of each volume", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  152. idCVar r_showShadows( "r_showShadows", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = visualize the stencil shadow volumes, 2 = draw filled in", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  153. idCVar r_showShadowCount( "r_showShadowCount", "0", CVAR_RENDERER | CVAR_INTEGER, "colors screen based on shadow volume depth complexity, >= 2 = print overdraw count based on stencil index values, 3 = only show turboshadows, 4 = only show static shadows", 0, 4, idCmdSystem::ArgCompletion_Integer<0,4> );
  154. idCVar r_showLightScissors( "r_showLightScissors", "0", CVAR_RENDERER | CVAR_BOOL, "show light scissor rectangles" );
  155. idCVar r_showEntityScissors( "r_showEntityScissors", "0", CVAR_RENDERER | CVAR_BOOL, "show entity scissor rectangles" );
  156. idCVar r_showInteractionFrustums( "r_showInteractionFrustums", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = show a frustum for each interaction, 2 = also draw lines to light origin, 3 = also draw entity bbox", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  157. idCVar r_showInteractionScissors( "r_showInteractionScissors", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = show screen rectangle which contains the interaction frustum, 2 = also draw construction lines", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  158. idCVar r_showLightCount( "r_showLightCount", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = colors surfaces based on light count, 2 = also count everything through walls, 3 = also print overdraw", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  159. idCVar r_showViewEntitys( "r_showViewEntitys", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = displays the bounding boxes of all view models, 2 = print index numbers" );
  160. idCVar r_showTris( "r_showTris", "0", CVAR_RENDERER | CVAR_INTEGER, "enables wireframe rendering of the world, 1 = only draw visible ones, 2 = draw all front facing, 3 = draw all", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  161. idCVar r_showSurfaceInfo( "r_showSurfaceInfo", "0", CVAR_RENDERER | CVAR_BOOL, "show surface material name under crosshair" );
  162. idCVar r_showNormals( "r_showNormals", "0", CVAR_RENDERER | CVAR_FLOAT, "draws wireframe normals" );
  163. idCVar r_showMemory( "r_showMemory", "0", CVAR_RENDERER | CVAR_BOOL, "print frame memory utilization" );
  164. idCVar r_showCull( "r_showCull", "0", CVAR_RENDERER | CVAR_BOOL, "report sphere and box culling stats" );
  165. idCVar r_showInteractions( "r_showInteractions", "0", CVAR_RENDERER | CVAR_BOOL, "report interaction generation activity" );
  166. idCVar r_showDepth( "r_showDepth", "0", CVAR_RENDERER | CVAR_BOOL, "display the contents of the depth buffer and the depth range" );
  167. idCVar r_showSurfaces( "r_showSurfaces", "0", CVAR_RENDERER | CVAR_BOOL, "report surface/light/shadow counts" );
  168. idCVar r_showPrimitives( "r_showPrimitives", "0", CVAR_RENDERER | CVAR_INTEGER, "report drawsurf/index/vertex counts" );
  169. idCVar r_showEdges( "r_showEdges", "0", CVAR_RENDERER | CVAR_BOOL, "draw the sil edges" );
  170. idCVar r_showTexturePolarity( "r_showTexturePolarity", "0", CVAR_RENDERER | CVAR_BOOL, "shade triangles by texture area polarity" );
  171. idCVar r_showTangentSpace( "r_showTangentSpace", "0", CVAR_RENDERER | CVAR_INTEGER, "shade triangles by tangent space, 1 = use 1st tangent vector, 2 = use 2nd tangent vector, 3 = use normal vector", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  172. idCVar r_showDominantTri( "r_showDominantTri", "0", CVAR_RENDERER | CVAR_BOOL, "draw lines from vertexes to center of dominant triangles" );
  173. idCVar r_showAlloc( "r_showAlloc", "0", CVAR_RENDERER | CVAR_BOOL, "report alloc/free counts" );
  174. idCVar r_showTextureVectors( "r_showTextureVectors", "0", CVAR_RENDERER | CVAR_FLOAT, " if > 0 draw each triangles texture (tangent) vectors" );
  175. idCVar r_showOverDraw( "r_showOverDraw", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = geometry overdraw, 2 = light interaction overdraw, 3 = geometry and light interaction overdraw", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  176. idCVar r_lockSurfaces( "r_lockSurfaces", "0", CVAR_RENDERER | CVAR_BOOL, "allow moving the view point without changing the composition of the scene, including culling" );
  177. idCVar r_useEntityCallbacks( "r_useEntityCallbacks", "1", CVAR_RENDERER | CVAR_BOOL, "if 0, issue the callback immediately at update time, rather than defering" );
  178. idCVar r_showSkel( "r_showSkel", "0", CVAR_RENDERER | CVAR_INTEGER, "draw the skeleton when model animates, 1 = draw model with skeleton, 2 = draw skeleton only", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  179. idCVar r_jointNameScale( "r_jointNameScale", "0.02", CVAR_RENDERER | CVAR_FLOAT, "size of joint names when r_showskel is set to 1" );
  180. idCVar r_jointNameOffset( "r_jointNameOffset", "0.5", CVAR_RENDERER | CVAR_FLOAT, "offset of joint names when r_showskel is set to 1" );
  181. idCVar r_cgVertexProfile( "r_cgVertexProfile", "best", CVAR_RENDERER | CVAR_ARCHIVE, "arbvp1, vp20, vp30" );
  182. idCVar r_cgFragmentProfile( "r_cgFragmentProfile", "best", CVAR_RENDERER | CVAR_ARCHIVE, "arbfp1, fp30" );
  183. idCVar r_debugLineDepthTest( "r_debugLineDepthTest", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "perform depth test on debug lines" );
  184. idCVar r_debugLineWidth( "r_debugLineWidth", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "width of debug lines" );
  185. idCVar r_debugArrowStep( "r_debugArrowStep", "120", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "step size of arrow cone line rotation in degrees", 0, 120 );
  186. idCVar r_debugPolygonFilled( "r_debugPolygonFilled", "1", CVAR_RENDERER | CVAR_BOOL, "draw a filled polygon" );
  187. idCVar r_materialOverride( "r_materialOverride", "", CVAR_RENDERER, "overrides all materials", idCmdSystem::ArgCompletion_Decl<DECL_MATERIAL> );
  188. idCVar r_debugRenderToTexture( "r_debugRenderToTexture", "0", CVAR_RENDERER | CVAR_INTEGER, "" );
  189. void ( APIENTRY * qglMultiTexCoord2fARB )( GLenum texture, GLfloat s, GLfloat t );
  190. void ( APIENTRY * qglMultiTexCoord2fvARB )( GLenum texture, GLfloat *st );
  191. void ( APIENTRY * qglActiveTextureARB )( GLenum texture );
  192. void ( APIENTRY * qglClientActiveTextureARB )( GLenum texture );
  193. void ( APIENTRY *qglCombinerParameterfvNV )( GLenum pname, const GLfloat *params );
  194. void ( APIENTRY *qglCombinerParameterivNV )( GLenum pname, const GLint *params );
  195. void ( APIENTRY *qglCombinerParameterfNV )( GLenum pname, const GLfloat param );
  196. void ( APIENTRY *qglCombinerParameteriNV )( GLenum pname, const GLint param );
  197. void ( APIENTRY *qglCombinerInputNV )( GLenum stage, GLenum portion, GLenum variable, GLenum input,
  198. GLenum mapping, GLenum componentUsage );
  199. void ( APIENTRY *qglCombinerOutputNV )( GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput,
  200. GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct,
  201. GLboolean cdDotProduct, GLboolean muxSum );
  202. void ( APIENTRY *qglFinalCombinerInputNV )( GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage );
  203. void (APIENTRY *qglVertexArrayRangeNV)( GLsizei length, void *pointer );
  204. // TTimo: wgl vs glX
  205. // http://oss.sgi.com/projects/ogl-sample/registry/NV/vertex_array_range.txt
  206. // since APIs are the same anyway, let's be wgl/glX agnostic
  207. void *(APIENTRY *qAllocateMemoryNV)( GLsizei size, float readFrequency, float writeFrequency, float priority);
  208. void (APIENTRY *qFreeMemoryNV)( void *pointer );
  209. #ifdef GLX_VERSION_1_1
  210. #define Q_ALLOCATE_MEMORY_NV "glXAllocateMemoryNV"
  211. #define Q_FREE_MEMORY_NV "glXFreeMemoryNV"
  212. #else
  213. #define Q_ALLOCATE_MEMORY_NV "wglAllocateMemoryNV"
  214. #define Q_FREE_MEMORY_NV "wglFreeMemoryNV"
  215. #endif
  216. void (APIENTRY *qglTexImage3D)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *);
  217. void (APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * );
  218. // ATI_fragment_shader
  219. PFNGLGENFRAGMENTSHADERSATIPROC qglGenFragmentShadersATI;
  220. PFNGLBINDFRAGMENTSHADERATIPROC qglBindFragmentShaderATI;
  221. PFNGLDELETEFRAGMENTSHADERATIPROC qglDeleteFragmentShaderATI;
  222. PFNGLBEGINFRAGMENTSHADERATIPROC qglBeginFragmentShaderATI;
  223. PFNGLENDFRAGMENTSHADERATIPROC qglEndFragmentShaderATI;
  224. PFNGLPASSTEXCOORDATIPROC qglPassTexCoordATI;
  225. PFNGLSAMPLEMAPATIPROC qglSampleMapATI;
  226. PFNGLCOLORFRAGMENTOP1ATIPROC qglColorFragmentOp1ATI;
  227. PFNGLCOLORFRAGMENTOP2ATIPROC qglColorFragmentOp2ATI;
  228. PFNGLCOLORFRAGMENTOP3ATIPROC qglColorFragmentOp3ATI;
  229. PFNGLALPHAFRAGMENTOP1ATIPROC qglAlphaFragmentOp1ATI;
  230. PFNGLALPHAFRAGMENTOP2ATIPROC qglAlphaFragmentOp2ATI;
  231. PFNGLALPHAFRAGMENTOP3ATIPROC qglAlphaFragmentOp3ATI;
  232. PFNGLSETFRAGMENTSHADERCONSTANTATIPROC qglSetFragmentShaderConstantATI;
  233. // EXT_stencil_two_side
  234. PFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT;
  235. // ATI_separate_stencil
  236. PFNGLSTENCILOPSEPARATEATIPROC qglStencilOpSeparateATI;
  237. PFNGLSTENCILFUNCSEPARATEATIPROC qglStencilFuncSeparateATI;
  238. // ARB_texture_compression
  239. PFNGLCOMPRESSEDTEXIMAGE2DARBPROC qglCompressedTexImage2DARB;
  240. PFNGLGETCOMPRESSEDTEXIMAGEARBPROC qglGetCompressedTexImageARB;
  241. // ARB_vertex_buffer_object
  242. PFNGLBINDBUFFERARBPROC qglBindBufferARB;
  243. PFNGLDELETEBUFFERSARBPROC qglDeleteBuffersARB;
  244. PFNGLGENBUFFERSARBPROC qglGenBuffersARB;
  245. PFNGLISBUFFERARBPROC qglIsBufferARB;
  246. PFNGLBUFFERDATAARBPROC qglBufferDataARB;
  247. PFNGLBUFFERSUBDATAARBPROC qglBufferSubDataARB;
  248. PFNGLGETBUFFERSUBDATAARBPROC qglGetBufferSubDataARB;
  249. PFNGLMAPBUFFERARBPROC qglMapBufferARB;
  250. PFNGLUNMAPBUFFERARBPROC qglUnmapBufferARB;
  251. PFNGLGETBUFFERPARAMETERIVARBPROC qglGetBufferParameterivARB;
  252. PFNGLGETBUFFERPOINTERVARBPROC qglGetBufferPointervARB;
  253. // ARB_vertex_program / ARB_fragment_program
  254. PFNGLVERTEXATTRIBPOINTERARBPROC qglVertexAttribPointerARB;
  255. PFNGLENABLEVERTEXATTRIBARRAYARBPROC qglEnableVertexAttribArrayARB;
  256. PFNGLDISABLEVERTEXATTRIBARRAYARBPROC qglDisableVertexAttribArrayARB;
  257. PFNGLPROGRAMSTRINGARBPROC qglProgramStringARB;
  258. PFNGLBINDPROGRAMARBPROC qglBindProgramARB;
  259. PFNGLGENPROGRAMSARBPROC qglGenProgramsARB;
  260. PFNGLPROGRAMENVPARAMETER4FVARBPROC qglProgramEnvParameter4fvARB;
  261. PFNGLPROGRAMLOCALPARAMETER4FVARBPROC qglProgramLocalParameter4fvARB;
  262. // GL_EXT_depth_bounds_test
  263. PFNGLDEPTHBOUNDSEXTPROC qglDepthBoundsEXT;
  264. /*
  265. =================
  266. R_CheckExtension
  267. =================
  268. */
  269. bool R_CheckExtension( char *name ) {
  270. if ( !strstr( glConfig.extensions_string, name ) ) {
  271. common->Printf( "X..%s not found\n", name );
  272. return false;
  273. }
  274. common->Printf( "...using %s\n", name );
  275. return true;
  276. }
  277. /*
  278. ==================
  279. R_CheckPortableExtensions
  280. ==================
  281. */
  282. static void R_CheckPortableExtensions( void ) {
  283. glConfig.glVersion = atof( glConfig.version_string );
  284. // GL_ARB_multitexture
  285. glConfig.multitextureAvailable = R_CheckExtension( "GL_ARB_multitexture" );
  286. if ( glConfig.multitextureAvailable ) {
  287. qglMultiTexCoord2fARB = (void(APIENTRY *)(GLenum, GLfloat, GLfloat))GLimp_ExtensionPointer( "glMultiTexCoord2fARB" );
  288. qglMultiTexCoord2fvARB = (void(APIENTRY *)(GLenum, GLfloat *))GLimp_ExtensionPointer( "glMultiTexCoord2fvARB" );
  289. qglActiveTextureARB = (void(APIENTRY *)(GLenum))GLimp_ExtensionPointer( "glActiveTextureARB" );
  290. qglClientActiveTextureARB = (void(APIENTRY *)(GLenum))GLimp_ExtensionPointer( "glClientActiveTextureARB" );
  291. qglGetIntegerv( GL_MAX_TEXTURE_UNITS_ARB, (GLint *)&glConfig.maxTextureUnits );
  292. if ( glConfig.maxTextureUnits > MAX_MULTITEXTURE_UNITS ) {
  293. glConfig.maxTextureUnits = MAX_MULTITEXTURE_UNITS;
  294. }
  295. if ( glConfig.maxTextureUnits < 2 ) {
  296. glConfig.multitextureAvailable = false; // shouldn't ever happen
  297. }
  298. qglGetIntegerv( GL_MAX_TEXTURE_COORDS_ARB, (GLint *)&glConfig.maxTextureCoords );
  299. qglGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS_ARB, (GLint *)&glConfig.maxTextureImageUnits );
  300. }
  301. // GL_ARB_texture_env_combine
  302. glConfig.textureEnvCombineAvailable = R_CheckExtension( "GL_ARB_texture_env_combine" );
  303. // GL_ARB_texture_cube_map
  304. glConfig.cubeMapAvailable = R_CheckExtension( "GL_ARB_texture_cube_map" );
  305. // GL_ARB_texture_env_dot3
  306. glConfig.envDot3Available = R_CheckExtension( "GL_ARB_texture_env_dot3" );
  307. // GL_ARB_texture_env_add
  308. glConfig.textureEnvAddAvailable = R_CheckExtension( "GL_ARB_texture_env_add" );
  309. // GL_ARB_texture_non_power_of_two
  310. glConfig.textureNonPowerOfTwoAvailable = R_CheckExtension( "GL_ARB_texture_non_power_of_two" );
  311. // GL_ARB_texture_compression + GL_S3_s3tc
  312. // DRI drivers may have GL_ARB_texture_compression but no GL_EXT_texture_compression_s3tc
  313. if ( R_CheckExtension( "GL_ARB_texture_compression" ) && R_CheckExtension( "GL_EXT_texture_compression_s3tc" ) ) {
  314. glConfig.textureCompressionAvailable = true;
  315. qglCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)GLimp_ExtensionPointer( "glCompressedTexImage2DARB" );
  316. qglGetCompressedTexImageARB = (PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)GLimp_ExtensionPointer( "glGetCompressedTexImageARB" );
  317. } else {
  318. glConfig.textureCompressionAvailable = false;
  319. }
  320. // GL_EXT_texture_filter_anisotropic
  321. glConfig.anisotropicAvailable = R_CheckExtension( "GL_EXT_texture_filter_anisotropic" );
  322. if ( glConfig.anisotropicAvailable ) {
  323. qglGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glConfig.maxTextureAnisotropy );
  324. common->Printf( " maxTextureAnisotropy: %f\n", glConfig.maxTextureAnisotropy );
  325. } else {
  326. glConfig.maxTextureAnisotropy = 1;
  327. }
  328. // GL_EXT_texture_lod_bias
  329. // The actual extension is broken as specificed, storing the state in the texture unit instead
  330. // of the texture object. The behavior in GL 1.4 is the behavior we use.
  331. if ( glConfig.glVersion >= 1.4 || R_CheckExtension( "GL_EXT_texture_lod" ) ) {
  332. common->Printf( "...using %s\n", "GL_1.4_texture_lod_bias" );
  333. glConfig.textureLODBiasAvailable = true;
  334. } else {
  335. common->Printf( "X..%s not found\n", "GL_1.4_texture_lod_bias" );
  336. glConfig.textureLODBiasAvailable = false;
  337. }
  338. // GL_EXT_shared_texture_palette
  339. glConfig.sharedTexturePaletteAvailable = R_CheckExtension( "GL_EXT_shared_texture_palette" );
  340. if ( glConfig.sharedTexturePaletteAvailable ) {
  341. qglColorTableEXT = ( void ( APIENTRY * ) ( int, int, int, int, int, const void * ) ) GLimp_ExtensionPointer( "glColorTableEXT" );
  342. }
  343. // GL_EXT_texture3D (not currently used for anything)
  344. glConfig.texture3DAvailable = R_CheckExtension( "GL_EXT_texture3D" );
  345. if ( glConfig.texture3DAvailable ) {
  346. qglTexImage3D =
  347. (void (APIENTRY *)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *) )
  348. GLimp_ExtensionPointer( "glTexImage3D" );
  349. }
  350. // EXT_stencil_wrap
  351. // This isn't very important, but some pathological case might cause a clamp error and give a shadow bug.
  352. // Nvidia also believes that future hardware may be able to run faster with this enabled to avoid the
  353. // serialization of clamping.
  354. if ( R_CheckExtension( "GL_EXT_stencil_wrap" ) ) {
  355. tr.stencilIncr = GL_INCR_WRAP_EXT;
  356. tr.stencilDecr = GL_DECR_WRAP_EXT;
  357. } else {
  358. tr.stencilIncr = GL_INCR;
  359. tr.stencilDecr = GL_DECR;
  360. }
  361. // GL_NV_register_combiners
  362. glConfig.registerCombinersAvailable = R_CheckExtension( "GL_NV_register_combiners" );
  363. if ( glConfig.registerCombinersAvailable ) {
  364. qglCombinerParameterfvNV = (void (APIENTRY *)( GLenum pname, const GLfloat *params ))
  365. GLimp_ExtensionPointer( "glCombinerParameterfvNV" );
  366. qglCombinerParameterivNV = (void (APIENTRY *)( GLenum pname, const GLint *params ))
  367. GLimp_ExtensionPointer( "glCombinerParameterivNV" );
  368. qglCombinerParameterfNV = (void (APIENTRY *)( GLenum pname, const GLfloat param ))
  369. GLimp_ExtensionPointer( "glCombinerParameterfNV" );
  370. qglCombinerParameteriNV = (void (APIENTRY *)( GLenum pname, const GLint param ))
  371. GLimp_ExtensionPointer( "glCombinerParameteriNV" );
  372. qglCombinerInputNV = (void (APIENTRY *)( GLenum stage, GLenum portion, GLenum variable, GLenum input,
  373. GLenum mapping, GLenum componentUsage ))
  374. GLimp_ExtensionPointer( "glCombinerInputNV" );
  375. qglCombinerOutputNV = (void (APIENTRY *)( GLenum stage, GLenum portion, GLenum abOutput, GLenum cdOutput,
  376. GLenum sumOutput, GLenum scale, GLenum bias, GLboolean abDotProduct,
  377. GLboolean cdDotProduct, GLboolean muxSum ))
  378. GLimp_ExtensionPointer( "glCombinerOutputNV" );
  379. qglFinalCombinerInputNV = (void (APIENTRY *)( GLenum variable, GLenum input, GLenum mapping, GLenum componentUsage ))
  380. GLimp_ExtensionPointer( "glFinalCombinerInputNV" );
  381. }
  382. // GL_EXT_stencil_two_side
  383. glConfig.twoSidedStencilAvailable = R_CheckExtension( "GL_EXT_stencil_two_side" );
  384. if ( glConfig.twoSidedStencilAvailable ) {
  385. qglActiveStencilFaceEXT = (PFNGLACTIVESTENCILFACEEXTPROC)GLimp_ExtensionPointer( "glActiveStencilFaceEXT" );
  386. } else {
  387. glConfig.atiTwoSidedStencilAvailable = R_CheckExtension( "GL_ATI_separate_stencil" );
  388. if ( glConfig.atiTwoSidedStencilAvailable ) {
  389. qglStencilFuncSeparateATI = (PFNGLSTENCILFUNCSEPARATEATIPROC)GLimp_ExtensionPointer( "glStencilFuncSeparateATI" );
  390. qglStencilOpSeparateATI = (PFNGLSTENCILOPSEPARATEATIPROC)GLimp_ExtensionPointer( "glStencilOpSeparateATI" );
  391. }
  392. }
  393. // GL_ATI_fragment_shader
  394. glConfig.atiFragmentShaderAvailable = R_CheckExtension( "GL_ATI_fragment_shader" );
  395. if (! glConfig.atiFragmentShaderAvailable ) {
  396. // only on OSX: ATI_fragment_shader is faked through ATI_text_fragment_shader (macosx_glimp.cpp)
  397. glConfig.atiFragmentShaderAvailable = R_CheckExtension( "GL_ATI_text_fragment_shader" );
  398. }
  399. if ( glConfig.atiFragmentShaderAvailable ) {
  400. qglGenFragmentShadersATI = (PFNGLGENFRAGMENTSHADERSATIPROC)GLimp_ExtensionPointer( "glGenFragmentShadersATI" );
  401. qglBindFragmentShaderATI = (PFNGLBINDFRAGMENTSHADERATIPROC)GLimp_ExtensionPointer( "glBindFragmentShaderATI" );
  402. qglDeleteFragmentShaderATI = (PFNGLDELETEFRAGMENTSHADERATIPROC)GLimp_ExtensionPointer( "glDeleteFragmentShaderATI" );
  403. qglBeginFragmentShaderATI = (PFNGLBEGINFRAGMENTSHADERATIPROC)GLimp_ExtensionPointer( "glBeginFragmentShaderATI" );
  404. qglEndFragmentShaderATI = (PFNGLENDFRAGMENTSHADERATIPROC)GLimp_ExtensionPointer( "glEndFragmentShaderATI" );
  405. qglPassTexCoordATI = (PFNGLPASSTEXCOORDATIPROC)GLimp_ExtensionPointer( "glPassTexCoordATI" );
  406. qglSampleMapATI = (PFNGLSAMPLEMAPATIPROC)GLimp_ExtensionPointer( "glSampleMapATI" );
  407. qglColorFragmentOp1ATI = (PFNGLCOLORFRAGMENTOP1ATIPROC)GLimp_ExtensionPointer( "glColorFragmentOp1ATI" );
  408. qglColorFragmentOp2ATI = (PFNGLCOLORFRAGMENTOP2ATIPROC)GLimp_ExtensionPointer( "glColorFragmentOp2ATI" );
  409. qglColorFragmentOp3ATI = (PFNGLCOLORFRAGMENTOP3ATIPROC)GLimp_ExtensionPointer( "glColorFragmentOp3ATI" );
  410. qglAlphaFragmentOp1ATI = (PFNGLALPHAFRAGMENTOP1ATIPROC)GLimp_ExtensionPointer( "glAlphaFragmentOp1ATI" );
  411. qglAlphaFragmentOp2ATI = (PFNGLALPHAFRAGMENTOP2ATIPROC)GLimp_ExtensionPointer( "glAlphaFragmentOp2ATI" );
  412. qglAlphaFragmentOp3ATI = (PFNGLALPHAFRAGMENTOP3ATIPROC)GLimp_ExtensionPointer( "glAlphaFragmentOp3ATI" );
  413. qglSetFragmentShaderConstantATI = (PFNGLSETFRAGMENTSHADERCONSTANTATIPROC)GLimp_ExtensionPointer( "glSetFragmentShaderConstantATI" );
  414. }
  415. // ARB_vertex_buffer_object
  416. glConfig.ARBVertexBufferObjectAvailable = R_CheckExtension( "GL_ARB_vertex_buffer_object" );
  417. if(glConfig.ARBVertexBufferObjectAvailable) {
  418. qglBindBufferARB = (PFNGLBINDBUFFERARBPROC)GLimp_ExtensionPointer( "glBindBufferARB");
  419. qglDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)GLimp_ExtensionPointer( "glDeleteBuffersARB");
  420. qglGenBuffersARB = (PFNGLGENBUFFERSARBPROC)GLimp_ExtensionPointer( "glGenBuffersARB");
  421. qglIsBufferARB = (PFNGLISBUFFERARBPROC)GLimp_ExtensionPointer( "glIsBufferARB");
  422. qglBufferDataARB = (PFNGLBUFFERDATAARBPROC)GLimp_ExtensionPointer( "glBufferDataARB");
  423. qglBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)GLimp_ExtensionPointer( "glBufferSubDataARB");
  424. qglGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)GLimp_ExtensionPointer( "glGetBufferSubDataARB");
  425. qglMapBufferARB = (PFNGLMAPBUFFERARBPROC)GLimp_ExtensionPointer( "glMapBufferARB");
  426. qglUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)GLimp_ExtensionPointer( "glUnmapBufferARB");
  427. qglGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)GLimp_ExtensionPointer( "glGetBufferParameterivARB");
  428. qglGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)GLimp_ExtensionPointer( "glGetBufferPointervARB");
  429. }
  430. // ARB_vertex_program
  431. glConfig.ARBVertexProgramAvailable = R_CheckExtension( "GL_ARB_vertex_program" );
  432. if (glConfig.ARBVertexProgramAvailable) {
  433. qglVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC)GLimp_ExtensionPointer( "glVertexAttribPointerARB" );
  434. qglEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)GLimp_ExtensionPointer( "glEnableVertexAttribArrayARB" );
  435. qglDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)GLimp_ExtensionPointer( "glDisableVertexAttribArrayARB" );
  436. qglProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)GLimp_ExtensionPointer( "glProgramStringARB" );
  437. qglBindProgramARB = (PFNGLBINDPROGRAMARBPROC)GLimp_ExtensionPointer( "glBindProgramARB" );
  438. qglGenProgramsARB = (PFNGLGENPROGRAMSARBPROC)GLimp_ExtensionPointer( "glGenProgramsARB" );
  439. qglProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC)GLimp_ExtensionPointer( "glProgramEnvParameter4fvARB" );
  440. qglProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)GLimp_ExtensionPointer( "glProgramLocalParameter4fvARB" );
  441. }
  442. // ARB_fragment_program
  443. if ( r_inhibitFragmentProgram.GetBool() ) {
  444. glConfig.ARBFragmentProgramAvailable = false;
  445. } else {
  446. glConfig.ARBFragmentProgramAvailable = R_CheckExtension( "GL_ARB_fragment_program" );
  447. if (glConfig.ARBFragmentProgramAvailable) {
  448. // these are the same as ARB_vertex_program
  449. qglProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)GLimp_ExtensionPointer( "glProgramStringARB" );
  450. qglBindProgramARB = (PFNGLBINDPROGRAMARBPROC)GLimp_ExtensionPointer( "glBindProgramARB" );
  451. qglProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC)GLimp_ExtensionPointer( "glProgramEnvParameter4fvARB" );
  452. qglProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)GLimp_ExtensionPointer( "glProgramLocalParameter4fvARB" );
  453. }
  454. }
  455. // check for minimum set
  456. if ( !glConfig.multitextureAvailable || !glConfig.textureEnvCombineAvailable || !glConfig.cubeMapAvailable
  457. || !glConfig.envDot3Available ) {
  458. common->Error( common->GetLanguageDict()->GetString( "#str_06780" ) );
  459. }
  460. // GL_EXT_depth_bounds_test
  461. glConfig.depthBoundsTestAvailable = R_CheckExtension( "EXT_depth_bounds_test" );
  462. if ( glConfig.depthBoundsTestAvailable ) {
  463. qglDepthBoundsEXT = (PFNGLDEPTHBOUNDSEXTPROC)GLimp_ExtensionPointer( "glDepthBoundsEXT" );
  464. }
  465. }
  466. /*
  467. ====================
  468. R_GetModeInfo
  469. r_mode is normally a small non-negative integer that
  470. looks resolutions up in a table, but if it is set to -1,
  471. the values from r_customWidth, amd r_customHeight
  472. will be used instead.
  473. ====================
  474. */
  475. typedef struct vidmode_s {
  476. const char *description;
  477. int width, height;
  478. } vidmode_t;
  479. vidmode_t r_vidModes[] = {
  480. { "Mode 0: 640x480", 640, 480 },
  481. { "Mode 1: 800x600", 800, 600 },
  482. { "Mode 2: 856x480", 856, 480 },
  483. { "Mode 3: 960x720", 960, 720 },
  484. { "Mode 4: 1024x480", 1024, 480 },
  485. { "Mode 5: 1024x768", 1024, 768 },
  486. { "Mode 6: 1152x864", 1152, 864 },
  487. { "Mode 7: 1280x720", 1280, 720 },
  488. { "Mode 8: 1280x768", 1280, 768 },
  489. { "Mode 9: 1280x800", 1280, 800 },
  490. { "Mode 10: 1280x960", 1280, 960 },
  491. { "Mode 11: 1280x1024", 1280, 1024 },
  492. { "Mode 12: 1360x768", 1360, 768 },
  493. { "Mode 13: 1366x768", 1366, 768 },
  494. { "Mode 14: 1400x1050", 1400, 1050 },
  495. { "Mode 15: 1440x900", 1440, 900 },
  496. { "Mode 16: 1600x900", 1600, 900 },
  497. { "Mode 17: 1600x1200", 1600, 1200 },
  498. { "Mode 18: 1680x1050", 1680, 1050 },
  499. { "Mode 19: 1920x1080", 1920, 1080 },
  500. { "Mode 20: 1920x1200", 1920, 1200 },
  501. { "Mode 21: 1920x1440", 1920, 1440 },
  502. { "Mode 22: 2048x1536", 2048, 1536 },
  503. { "Mode 23: 2560x1440", 2560, 1440 },
  504. { "Mode 24: 2560x1600", 2560, 1600 },
  505. { "Mode 25: 2880x1800", 2880, 1800 },
  506. { "Mode 26: 3200x1080", 3200, 1080 },
  507. { "Mode 27: 3840x1080", 3840, 1080 },
  508. };
  509. static int s_numVidModes = ( sizeof( r_vidModes ) / sizeof( r_vidModes[0] ) );
  510. #if MACOS_X
  511. bool R_GetModeInfo( int *width, int *height, int mode ) {
  512. #else
  513. static bool R_GetModeInfo( int *width, int *height, int mode ) {
  514. #endif
  515. vidmode_t *vm;
  516. if ( mode < -1 ) {
  517. return false;
  518. }
  519. if ( mode >= s_numVidModes ) {
  520. return false;
  521. }
  522. if ( mode == -1 ) {
  523. *width = r_customWidth.GetInteger();
  524. *height = r_customHeight.GetInteger();
  525. return true;
  526. }
  527. vm = &r_vidModes[mode];
  528. if ( width ) {
  529. *width = vm->width;
  530. }
  531. if ( height ) {
  532. *height = vm->height;
  533. }
  534. return true;
  535. }
  536. /*
  537. ==================
  538. R_InitOpenGL
  539. This function is responsible for initializing a valid OpenGL subsystem
  540. for rendering. This is done by calling the system specific GLimp_Init,
  541. which gives us a working OGL subsystem, then setting all necessary openGL
  542. state, including images, vertex programs, and display lists.
  543. Changes to the vertex cache size or smp state require a vid_restart.
  544. If glConfig.isInitialized is false, no rendering can take place, but
  545. all renderSystem functions will still operate properly, notably the material
  546. and model information functions.
  547. ==================
  548. */
  549. void R_InitOpenGL( void ) {
  550. GLint temp;
  551. glimpParms_t parms;
  552. int i;
  553. common->Printf( "----- R_InitOpenGL -----\n" );
  554. if ( glConfig.isInitialized ) {
  555. common->FatalError( "R_InitOpenGL called while active" );
  556. }
  557. // in case we had an error while doing a tiled rendering
  558. tr.viewportOffset[0] = 0;
  559. tr.viewportOffset[1] = 0;
  560. //
  561. // initialize OS specific portions of the renderSystem
  562. //
  563. for ( i = 0 ; i < 2 ; i++ ) {
  564. // set the parameters we are trying
  565. R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, r_mode.GetInteger() );
  566. parms.width = glConfig.vidWidth;
  567. parms.height = glConfig.vidHeight;
  568. parms.fullScreen = r_fullscreen.GetBool();
  569. parms.displayHz = r_displayRefresh.GetInteger();
  570. parms.multiSamples = r_multiSamples.GetInteger();
  571. parms.stereo = false;
  572. if ( GLimp_Init( parms ) ) {
  573. // it worked
  574. break;
  575. }
  576. if ( i == 1 ) {
  577. common->FatalError( "Unable to initialize OpenGL" );
  578. }
  579. // if we failed, set everything back to "safe mode"
  580. // and try again
  581. r_mode.SetInteger( 3 );
  582. r_fullscreen.SetInteger( 1 );
  583. r_displayRefresh.SetInteger( 0 );
  584. r_multiSamples.SetInteger( 0 );
  585. }
  586. // input and sound systems need to be tied to the new window
  587. Sys_InitInput();
  588. soundSystem->InitHW();
  589. // get our config strings
  590. glConfig.vendor_string = (const char *)qglGetString(GL_VENDOR);
  591. glConfig.renderer_string = (const char *)qglGetString(GL_RENDERER);
  592. glConfig.version_string = (const char *)qglGetString(GL_VERSION);
  593. glConfig.extensions_string = (const char *)qglGetString(GL_EXTENSIONS);
  594. // OpenGL driver constants
  595. qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp );
  596. glConfig.maxTextureSize = temp;
  597. // stubbed or broken drivers may have reported 0...
  598. if ( glConfig.maxTextureSize <= 0 ) {
  599. glConfig.maxTextureSize = 256;
  600. }
  601. glConfig.isInitialized = true;
  602. // recheck all the extensions (FIXME: this might be dangerous)
  603. R_CheckPortableExtensions();
  604. // parse our vertex and fragment programs, possibly disably support for
  605. // one of the paths if there was an error
  606. R_NV10_Init();
  607. R_NV20_Init();
  608. R_R200_Init();
  609. R_ARB2_Init();
  610. cmdSystem->AddCommand( "reloadARBprograms", R_ReloadARBPrograms_f, CMD_FL_RENDERER, "reloads ARB programs" );
  611. R_ReloadARBPrograms_f( idCmdArgs() );
  612. // allocate the vertex array range or vertex objects
  613. vertexCache.Init();
  614. // select which renderSystem we are going to use
  615. r_renderer.SetModified();
  616. tr.SetBackEndRenderer();
  617. // allocate the frame data, which may be more if smp is enabled
  618. R_InitFrameData();
  619. // Reset our gamma
  620. R_SetColorMappings();
  621. #ifdef _WIN32
  622. static bool glCheck = false;
  623. if ( !glCheck && win32.osversion.dwMajorVersion == 6 ) {
  624. glCheck = true;
  625. if ( !idStr::Icmp( glConfig.vendor_string, "Microsoft" ) && idStr::FindText( glConfig.renderer_string, "OpenGL-D3D" ) != -1 ) {
  626. if ( cvarSystem->GetCVarBool( "r_fullscreen" ) ) {
  627. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "vid_restart partial windowed\n" );
  628. Sys_GrabMouseCursor( false );
  629. }
  630. int ret = MessageBox( NULL, "Please install OpenGL drivers from your graphics hardware vendor to run " GAME_NAME ".\nYour OpenGL functionality is limited.",
  631. "Insufficient OpenGL capabilities", MB_OKCANCEL | MB_ICONWARNING | MB_TASKMODAL );
  632. if ( ret == IDCANCEL ) {
  633. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "quit\n" );
  634. cmdSystem->ExecuteCommandBuffer();
  635. }
  636. if ( cvarSystem->GetCVarBool( "r_fullscreen" ) ) {
  637. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "vid_restart\n" );
  638. }
  639. }
  640. }
  641. #endif
  642. }
  643. /*
  644. ==================
  645. GL_CheckErrors
  646. ==================
  647. */
  648. void GL_CheckErrors( void ) {
  649. int err;
  650. char s[64];
  651. int i;
  652. // check for up to 10 errors pending
  653. for ( i = 0 ; i < 10 ; i++ ) {
  654. err = qglGetError();
  655. if ( err == GL_NO_ERROR ) {
  656. return;
  657. }
  658. switch( err ) {
  659. case GL_INVALID_ENUM:
  660. strcpy( s, "GL_INVALID_ENUM" );
  661. break;
  662. case GL_INVALID_VALUE:
  663. strcpy( s, "GL_INVALID_VALUE" );
  664. break;
  665. case GL_INVALID_OPERATION:
  666. strcpy( s, "GL_INVALID_OPERATION" );
  667. break;
  668. case GL_STACK_OVERFLOW:
  669. strcpy( s, "GL_STACK_OVERFLOW" );
  670. break;
  671. case GL_STACK_UNDERFLOW:
  672. strcpy( s, "GL_STACK_UNDERFLOW" );
  673. break;
  674. case GL_OUT_OF_MEMORY:
  675. strcpy( s, "GL_OUT_OF_MEMORY" );
  676. break;
  677. default:
  678. idStr::snPrintf( s, sizeof(s), "%i", err);
  679. break;
  680. }
  681. if ( !r_ignoreGLErrors.GetBool() ) {
  682. common->Printf( "GL_CheckErrors: %s\n", s );
  683. }
  684. }
  685. }
  686. /*
  687. =====================
  688. R_ReloadSurface_f
  689. Reload the material displayed by r_showSurfaceInfo
  690. =====================
  691. */
  692. static void R_ReloadSurface_f( const idCmdArgs &args ) {
  693. modelTrace_t mt;
  694. idVec3 start, end;
  695. // start far enough away that we don't hit the player model
  696. start = tr.primaryView->renderView.vieworg + tr.primaryView->renderView.viewaxis[0] * 16;
  697. end = start + tr.primaryView->renderView.viewaxis[0] * 1000.0f;
  698. if ( !tr.primaryWorld->Trace( mt, start, end, 0.0f, false ) ) {
  699. return;
  700. }
  701. common->Printf( "Reloading %s\n", mt.material->GetName() );
  702. // reload the decl
  703. mt.material->base->Reload();
  704. // reload any images used by the decl
  705. mt.material->ReloadImages( false );
  706. }
  707. /*
  708. ==============
  709. R_ListModes_f
  710. ==============
  711. */
  712. static void R_ListModes_f( const idCmdArgs &args ) {
  713. int i;
  714. common->Printf( "\n" );
  715. for ( i = 0; i < s_numVidModes; i++ ) {
  716. common->Printf( "%s\n", r_vidModes[i].description );
  717. }
  718. common->Printf( "\n" );
  719. }
  720. /*
  721. =============
  722. R_TestImage_f
  723. Display the given image centered on the screen.
  724. testimage <number>
  725. testimage <filename>
  726. =============
  727. */
  728. void R_TestImage_f( const idCmdArgs &args ) {
  729. int imageNum;
  730. if ( tr.testVideo ) {
  731. delete tr.testVideo;
  732. tr.testVideo = NULL;
  733. }
  734. tr.testImage = NULL;
  735. if ( args.Argc() != 2 ) {
  736. return;
  737. }
  738. if ( idStr::IsNumeric( args.Argv(1) ) ) {
  739. imageNum = atoi( args.Argv(1) );
  740. if ( imageNum >= 0 && imageNum < globalImages->images.Num() ) {
  741. tr.testImage = globalImages->images[imageNum];
  742. }
  743. } else {
  744. tr.testImage = globalImages->ImageFromFile( args.Argv( 1 ), TF_DEFAULT, false, TR_REPEAT, TD_DEFAULT );
  745. }
  746. }
  747. /*
  748. =============
  749. R_TestVideo_f
  750. Plays the cinematic file in a testImage
  751. =============
  752. */
  753. void R_TestVideo_f( const idCmdArgs &args ) {
  754. if ( tr.testVideo ) {
  755. delete tr.testVideo;
  756. tr.testVideo = NULL;
  757. }
  758. tr.testImage = NULL;
  759. if ( args.Argc() < 2 ) {
  760. return;
  761. }
  762. tr.testImage = globalImages->ImageFromFile( "_scratch", TF_DEFAULT, false, TR_REPEAT, TD_DEFAULT );
  763. tr.testVideo = idCinematic::Alloc();
  764. tr.testVideo->InitFromFile( args.Argv( 1 ), true );
  765. cinData_t cin;
  766. cin = tr.testVideo->ImageForTime( 0 );
  767. if ( !cin.image ) {
  768. delete tr.testVideo;
  769. tr.testVideo = NULL;
  770. tr.testImage = NULL;
  771. return;
  772. }
  773. common->Printf( "%i x %i images\n", cin.imageWidth, cin.imageHeight );
  774. int len = tr.testVideo->AnimationLength();
  775. common->Printf( "%5.1f seconds of video\n", len * 0.001 );
  776. tr.testVideoStartTime = tr.primaryRenderView.time * 0.001;
  777. // try to play the matching wav file
  778. idStr wavString = args.Argv( ( args.Argc() == 2 ) ? 1 : 2 );
  779. wavString.StripFileExtension();
  780. wavString = wavString + ".wav";
  781. session->sw->PlayShaderDirectly( wavString.c_str() );
  782. }
  783. static int R_QsortSurfaceAreas( const void *a, const void *b ) {
  784. const idMaterial *ea, *eb;
  785. int ac, bc;
  786. ea = *(idMaterial **)a;
  787. if ( !ea->EverReferenced() ) {
  788. ac = 0;
  789. } else {
  790. ac = ea->GetSurfaceArea();
  791. }
  792. eb = *(idMaterial **)b;
  793. if ( !eb->EverReferenced() ) {
  794. bc = 0;
  795. } else {
  796. bc = eb->GetSurfaceArea();
  797. }
  798. if ( ac < bc ) {
  799. return -1;
  800. }
  801. if ( ac > bc ) {
  802. return 1;
  803. }
  804. return idStr::Icmp( ea->GetName(), eb->GetName() );
  805. }
  806. /*
  807. ===================
  808. R_ReportSurfaceAreas_f
  809. Prints a list of the materials sorted by surface area
  810. ===================
  811. */
  812. void R_ReportSurfaceAreas_f( const idCmdArgs &args ) {
  813. int i, count;
  814. idMaterial **list;
  815. count = declManager->GetNumDecls( DECL_MATERIAL );
  816. list = (idMaterial **)_alloca( count * sizeof( *list ) );
  817. for ( i = 0 ; i < count ; i++ ) {
  818. list[i] = (idMaterial *)declManager->DeclByIndex( DECL_MATERIAL, i, false );
  819. }
  820. qsort( list, count, sizeof( list[0] ), R_QsortSurfaceAreas );
  821. // skip over ones with 0 area
  822. for ( i = 0 ; i < count ; i++ ) {
  823. if ( list[i]->GetSurfaceArea() > 0 ) {
  824. break;
  825. }
  826. }
  827. for ( ; i < count ; i++ ) {
  828. // report size in "editor blocks"
  829. int blocks = list[i]->GetSurfaceArea() / 4096.0;
  830. common->Printf( "%7i %s\n", blocks, list[i]->GetName() );
  831. }
  832. }
  833. /*
  834. ===================
  835. R_ReportImageDuplication_f
  836. Checks for images with the same hash value and does a better comparison
  837. ===================
  838. */
  839. void R_ReportImageDuplication_f( const idCmdArgs &args ) {
  840. int i, j;
  841. common->Printf( "Images with duplicated contents:\n" );
  842. int count = 0;
  843. for ( i = 0 ; i < globalImages->images.Num() ; i++ ) {
  844. idImage *image1 = globalImages->images[i];
  845. if ( image1->isPartialImage ) {
  846. // ignore background loading stubs
  847. continue;
  848. }
  849. if ( image1->generatorFunction ) {
  850. // ignore procedural images
  851. continue;
  852. }
  853. if ( image1->cubeFiles != CF_2D ) {
  854. // ignore cube maps
  855. continue;
  856. }
  857. if ( image1->defaulted ) {
  858. continue;
  859. }
  860. byte *data1;
  861. int w1, h1;
  862. R_LoadImageProgram( image1->imgName, &data1, &w1, &h1, NULL );
  863. for ( j = 0 ; j < i ; j++ ) {
  864. idImage *image2 = globalImages->images[j];
  865. if ( image2->isPartialImage ) {
  866. continue;
  867. }
  868. if ( image2->generatorFunction ) {
  869. continue;
  870. }
  871. if ( image2->cubeFiles != CF_2D ) {
  872. continue;
  873. }
  874. if ( image2->defaulted ) {
  875. continue;
  876. }
  877. if ( image1->imageHash != image2->imageHash ) {
  878. continue;
  879. }
  880. if ( image2->uploadWidth != image1->uploadWidth
  881. || image2->uploadHeight != image1->uploadHeight ) {
  882. continue;
  883. }
  884. if ( !idStr::Icmp( image1->imgName, image2->imgName ) ) {
  885. // ignore same image-with-different-parms
  886. continue;
  887. }
  888. byte *data2;
  889. int w2, h2;
  890. R_LoadImageProgram( image2->imgName, &data2, &w2, &h2, NULL );
  891. if ( w2 != w1 || h2 != h1 ) {
  892. R_StaticFree( data2 );
  893. continue;
  894. }
  895. if ( memcmp( data1, data2, w1*h1*4 ) ) {
  896. R_StaticFree( data2 );
  897. continue;
  898. }
  899. R_StaticFree( data2 );
  900. common->Printf( "%s == %s\n", image1->imgName.c_str(), image2->imgName.c_str() );
  901. session->UpdateScreen( true );
  902. count++;
  903. break;
  904. }
  905. R_StaticFree( data1 );
  906. }
  907. common->Printf( "%i / %i collisions\n", count, globalImages->images.Num() );
  908. }
  909. /*
  910. ==============================================================================
  911. THROUGHPUT BENCHMARKING
  912. ==============================================================================
  913. */
  914. /*
  915. ================
  916. R_RenderingFPS
  917. ================
  918. */
  919. static float R_RenderingFPS( const renderView_t *renderView ) {
  920. qglFinish();
  921. int start = Sys_Milliseconds();
  922. static const int SAMPLE_MSEC = 1000;
  923. int end;
  924. int count = 0;
  925. while( 1 ) {
  926. // render
  927. renderSystem->BeginFrame( glConfig.vidWidth, glConfig.vidHeight );
  928. tr.primaryWorld->RenderScene( renderView );
  929. renderSystem->EndFrame( NULL, NULL );
  930. qglFinish();
  931. count++;
  932. end = Sys_Milliseconds();
  933. if ( end - start > SAMPLE_MSEC ) {
  934. break;
  935. }
  936. }
  937. float fps = count * 1000.0 / ( end - start );
  938. return fps;
  939. }
  940. /*
  941. ================
  942. R_Benchmark_f
  943. ================
  944. */
  945. void R_Benchmark_f( const idCmdArgs &args ) {
  946. float fps, msec;
  947. renderView_t view;
  948. if ( !tr.primaryView ) {
  949. common->Printf( "No primaryView for benchmarking\n" );
  950. return;
  951. }
  952. view = tr.primaryRenderView;
  953. for ( int size = 100 ; size >= 10 ; size -= 10 ) {
  954. r_screenFraction.SetInteger( size );
  955. fps = R_RenderingFPS( &view );
  956. int kpix = glConfig.vidWidth * glConfig.vidHeight * ( size * 0.01 ) * ( size * 0.01 ) * 0.001;
  957. msec = 1000.0 / fps;
  958. common->Printf( "kpix: %4i msec:%5.1f fps:%5.1f\n", kpix, msec, fps );
  959. }
  960. // enable r_singleTriangle 1 while r_screenFraction is still at 10
  961. r_singleTriangle.SetBool( 1 );
  962. fps = R_RenderingFPS( &view );
  963. msec = 1000.0 / fps;
  964. common->Printf( "single tri msec:%5.1f fps:%5.1f\n", msec, fps );
  965. r_singleTriangle.SetBool( 0 );
  966. r_screenFraction.SetInteger( 100 );
  967. // enable r_skipRenderContext 1
  968. r_skipRenderContext.SetBool( true );
  969. fps = R_RenderingFPS( &view );
  970. msec = 1000.0 / fps;
  971. common->Printf( "no context msec:%5.1f fps:%5.1f\n", msec, fps );
  972. r_skipRenderContext.SetBool( false );
  973. }
  974. /*
  975. ==============================================================================
  976. SCREEN SHOTS
  977. ==============================================================================
  978. */
  979. /*
  980. ====================
  981. R_ReadTiledPixels
  982. Allows the rendering of an image larger than the actual window by
  983. tiling it into window-sized chunks and rendering each chunk separately
  984. If ref isn't specified, the full session UpdateScreen will be done.
  985. ====================
  986. */
  987. void R_ReadTiledPixels( int width, int height, byte *buffer, renderView_t *ref = NULL ) {
  988. // include extra space for OpenGL padding to word boundaries
  989. byte *temp = (byte *)R_StaticAlloc( (glConfig.vidWidth+3) * glConfig.vidHeight * 3 );
  990. int oldWidth = glConfig.vidWidth;
  991. int oldHeight = glConfig.vidHeight;
  992. tr.tiledViewport[0] = width;
  993. tr.tiledViewport[1] = height;
  994. // disable scissor, so we don't need to adjust all those rects
  995. r_useScissor.SetBool( false );
  996. for ( int xo = 0 ; xo < width ; xo += oldWidth ) {
  997. for ( int yo = 0 ; yo < height ; yo += oldHeight ) {
  998. tr.viewportOffset[0] = -xo;
  999. tr.viewportOffset[1] = -yo;
  1000. if ( ref ) {
  1001. tr.BeginFrame( oldWidth, oldHeight );
  1002. tr.primaryWorld->RenderScene( ref );
  1003. tr.EndFrame( NULL, NULL );
  1004. } else {
  1005. session->UpdateScreen();
  1006. }
  1007. int w = oldWidth;
  1008. if ( xo + w > width ) {
  1009. w = width - xo;
  1010. }
  1011. int h = oldHeight;
  1012. if ( yo + h > height ) {
  1013. h = height - yo;
  1014. }
  1015. qglReadBuffer( GL_FRONT );
  1016. qglReadPixels( 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, temp );
  1017. int row = ( w * 3 + 3 ) & ~3; // OpenGL pads to dword boundaries
  1018. for ( int y = 0 ; y < h ; y++ ) {
  1019. memcpy( buffer + ( ( yo + y )* width + xo ) * 3,
  1020. temp + y * row, w * 3 );
  1021. }
  1022. }
  1023. }
  1024. r_useScissor.SetBool( true );
  1025. tr.viewportOffset[0] = 0;
  1026. tr.viewportOffset[1] = 0;
  1027. tr.tiledViewport[0] = 0;
  1028. tr.tiledViewport[1] = 0;
  1029. R_StaticFree( temp );
  1030. glConfig.vidWidth = oldWidth;
  1031. glConfig.vidHeight = oldHeight;
  1032. }
  1033. /*
  1034. ==================
  1035. TakeScreenshot
  1036. Move to tr_imagefiles.c...
  1037. Will automatically tile render large screen shots if necessary
  1038. Downsample is the number of steps to mipmap the image before saving it
  1039. If ref == NULL, session->updateScreen will be used
  1040. ==================
  1041. */
  1042. void idRenderSystemLocal::TakeScreenshot( int width, int height, const char *fileName, int blends, renderView_t *ref ) {
  1043. byte *buffer;
  1044. int i, j, c, temp;
  1045. takingScreenshot = true;
  1046. int pix = width * height;
  1047. buffer = (byte *)R_StaticAlloc(pix*3 + 18);
  1048. memset (buffer, 0, 18);
  1049. if ( blends <= 1 ) {
  1050. R_ReadTiledPixels( width, height, buffer + 18, ref );
  1051. } else {
  1052. unsigned short *shortBuffer = (unsigned short *)R_StaticAlloc(pix*2*3);
  1053. memset (shortBuffer, 0, pix*2*3);
  1054. // enable anti-aliasing jitter
  1055. r_jitter.SetBool( true );
  1056. for ( i = 0 ; i < blends ; i++ ) {
  1057. R_ReadTiledPixels( width, height, buffer + 18, ref );
  1058. for ( j = 0 ; j < pix*3 ; j++ ) {
  1059. shortBuffer[j] += buffer[18+j];
  1060. }
  1061. }
  1062. // divide back to bytes
  1063. for ( i = 0 ; i < pix*3 ; i++ ) {
  1064. buffer[18+i] = shortBuffer[i] / blends;
  1065. }
  1066. R_StaticFree( shortBuffer );
  1067. r_jitter.SetBool( false );
  1068. }
  1069. // fill in the header (this is vertically flipped, which qglReadPixels emits)
  1070. buffer[2] = 2; // uncompressed type
  1071. buffer[12] = width & 255;
  1072. buffer[13] = width >> 8;
  1073. buffer[14] = height & 255;
  1074. buffer[15] = height >> 8;
  1075. buffer[16] = 24; // pixel size
  1076. // swap rgb to bgr
  1077. c = 18 + width * height * 3;
  1078. for (i=18 ; i<c ; i+=3) {
  1079. temp = buffer[i];
  1080. buffer[i] = buffer[i+2];
  1081. buffer[i+2] = temp;
  1082. }
  1083. // _D3XP adds viewnote screenie save to cdpath
  1084. if ( strstr( fileName, "viewnote" ) ) {
  1085. fileSystem->WriteFile( fileName, buffer, c, "fs_cdpath" );
  1086. } else {
  1087. fileSystem->WriteFile( fileName, buffer, c );
  1088. }
  1089. R_StaticFree( buffer );
  1090. takingScreenshot = false;
  1091. }
  1092. /*
  1093. ==================
  1094. R_ScreenshotFilename
  1095. Returns a filename with digits appended
  1096. if we have saved a previous screenshot, don't scan
  1097. from the beginning, because recording demo avis can involve
  1098. thousands of shots
  1099. ==================
  1100. */
  1101. void R_ScreenshotFilename( int &lastNumber, const char *base, idStr &fileName ) {
  1102. int a,b,c,d, e;
  1103. bool restrict = cvarSystem->GetCVarBool( "fs_restrict" );
  1104. cvarSystem->SetCVarBool( "fs_restrict", false );
  1105. lastNumber++;
  1106. if ( lastNumber > 99999 ) {
  1107. lastNumber = 99999;
  1108. }
  1109. for ( ; lastNumber < 99999 ; lastNumber++ ) {
  1110. int frac = lastNumber;
  1111. a = frac / 10000;
  1112. frac -= a*10000;
  1113. b = frac / 1000;
  1114. frac -= b*1000;
  1115. c = frac / 100;
  1116. frac -= c*100;
  1117. d = frac / 10;
  1118. frac -= d*10;
  1119. e = frac;
  1120. sprintf( fileName, "%s%i%i%i%i%i.tga", base, a, b, c, d, e );
  1121. if ( lastNumber == 99999 ) {
  1122. break;
  1123. }
  1124. int len = fileSystem->ReadFile( fileName, NULL, NULL );
  1125. if ( len <= 0 ) {
  1126. break;
  1127. }
  1128. // check again...
  1129. }
  1130. cvarSystem->SetCVarBool( "fs_restrict", restrict );
  1131. }
  1132. /*
  1133. ==================
  1134. R_BlendedScreenShot
  1135. screenshot
  1136. screenshot [filename]
  1137. screenshot [width] [height]
  1138. screenshot [width] [height] [samples]
  1139. ==================
  1140. */
  1141. #define MAX_BLENDS 256 // to keep the accumulation in shorts
  1142. void R_ScreenShot_f( const idCmdArgs &args ) {
  1143. static int lastNumber = 0;
  1144. idStr checkname;
  1145. int width = glConfig.vidWidth;
  1146. int height = glConfig.vidHeight;
  1147. int x = 0;
  1148. int y = 0;
  1149. int blends = 0;
  1150. switch ( args.Argc() ) {
  1151. case 1:
  1152. width = glConfig.vidWidth;
  1153. height = glConfig.vidHeight;
  1154. blends = 1;
  1155. R_ScreenshotFilename( lastNumber, "screenshots/shot", checkname );
  1156. break;
  1157. case 2:
  1158. width = glConfig.vidWidth;
  1159. height = glConfig.vidHeight;
  1160. blends = 1;
  1161. checkname = args.Argv( 1 );
  1162. break;
  1163. case 3:
  1164. width = atoi( args.Argv( 1 ) );
  1165. height = atoi( args.Argv( 2 ) );
  1166. blends = 1;
  1167. R_ScreenshotFilename( lastNumber, "screenshots/shot", checkname );
  1168. break;
  1169. case 4:
  1170. width = atoi( args.Argv( 1 ) );
  1171. height = atoi( args.Argv( 2 ) );
  1172. blends = atoi( args.Argv( 3 ) );
  1173. if ( blends < 1 ) {
  1174. blends = 1;
  1175. }
  1176. if ( blends > MAX_BLENDS ) {
  1177. blends = MAX_BLENDS;
  1178. }
  1179. R_ScreenshotFilename( lastNumber, "screenshots/shot", checkname );
  1180. break;
  1181. default:
  1182. common->Printf( "usage: screenshot\n screenshot <filename>\n screenshot <width> <height>\n screenshot <width> <height> <blends>\n" );
  1183. return;
  1184. }
  1185. // put the console away
  1186. console->Close();
  1187. tr.TakeScreenshot( width, height, checkname, blends, NULL );
  1188. common->Printf( "Wrote %s\n", checkname.c_str() );
  1189. }
  1190. /*
  1191. ===============
  1192. R_StencilShot
  1193. Save out a screenshot showing the stencil buffer expanded by 16x range
  1194. ===============
  1195. */
  1196. void R_StencilShot( void ) {
  1197. byte *buffer;
  1198. int i, c;
  1199. int width = tr.GetScreenWidth();
  1200. int height = tr.GetScreenHeight();
  1201. int pix = width * height;
  1202. c = pix * 3 + 18;
  1203. buffer = (byte *)Mem_Alloc(c);
  1204. memset (buffer, 0, 18);
  1205. byte *byteBuffer = (byte *)Mem_Alloc(pix);
  1206. qglReadPixels( 0, 0, width, height, GL_STENCIL_INDEX , GL_UNSIGNED_BYTE, byteBuffer );
  1207. for ( i = 0 ; i < pix ; i++ ) {
  1208. buffer[18+i*3] =
  1209. buffer[18+i*3+1] =
  1210. // buffer[18+i*3+2] = ( byteBuffer[i] & 15 ) * 16;
  1211. buffer[18+i*3+2] = byteBuffer[i];
  1212. }
  1213. // fill in the header (this is vertically flipped, which qglReadPixels emits)
  1214. buffer[2] = 2; // uncompressed type
  1215. buffer[12] = width & 255;
  1216. buffer[13] = width >> 8;
  1217. buffer[14] = height & 255;
  1218. buffer[15] = height >> 8;
  1219. buffer[16] = 24; // pixel size
  1220. fileSystem->WriteFile( "screenshots/stencilShot.tga", buffer, c, "fs_savepath" );
  1221. Mem_Free( buffer );
  1222. Mem_Free( byteBuffer );
  1223. }
  1224. /*
  1225. ==================
  1226. R_EnvShot_f
  1227. envshot <basename>
  1228. Saves out env/<basename>_ft.tga, etc
  1229. ==================
  1230. */
  1231. void R_EnvShot_f( const idCmdArgs &args ) {
  1232. idStr fullname;
  1233. const char *baseName;
  1234. int i;
  1235. idMat3 axis[6];
  1236. renderView_t ref;
  1237. viewDef_t primary;
  1238. int blends;
  1239. char *extensions[6] = { "_px.tga", "_nx.tga", "_py.tga", "_ny.tga",
  1240. "_pz.tga", "_nz.tga" };
  1241. int size;
  1242. if ( args.Argc() != 2 && args.Argc() != 3 && args.Argc() != 4 ) {
  1243. common->Printf( "USAGE: envshot <basename> [size] [blends]\n" );
  1244. return;
  1245. }
  1246. baseName = args.Argv( 1 );
  1247. blends = 1;
  1248. if ( args.Argc() == 4 ) {
  1249. size = atoi( args.Argv( 2 ) );
  1250. blends = atoi( args.Argv( 3 ) );
  1251. } else if ( args.Argc() == 3 ) {
  1252. size = atoi( args.Argv( 2 ) );
  1253. blends = 1;
  1254. } else {
  1255. size = 256;
  1256. blends = 1;
  1257. }
  1258. if ( !tr.primaryView ) {
  1259. common->Printf( "No primary view.\n" );
  1260. return;
  1261. }
  1262. primary = *tr.primaryView;
  1263. memset( &axis, 0, sizeof( axis ) );
  1264. axis[0][0][0] = 1;
  1265. axis[0][1][2] = 1;
  1266. axis[0][2][1] = 1;
  1267. axis[1][0][0] = -1;
  1268. axis[1][1][2] = -1;
  1269. axis[1][2][1] = 1;
  1270. axis[2][0][1] = 1;
  1271. axis[2][1][0] = -1;
  1272. axis[2][2][2] = -1;
  1273. axis[3][0][1] = -1;
  1274. axis[3][1][0] = -1;
  1275. axis[3][2][2] = 1;
  1276. axis[4][0][2] = 1;
  1277. axis[4][1][0] = -1;
  1278. axis[4][2][1] = 1;
  1279. axis[5][0][2] = -1;
  1280. axis[5][1][0] = 1;
  1281. axis[5][2][1] = 1;
  1282. for ( i = 0 ; i < 6 ; i++ ) {
  1283. ref = primary.renderView;
  1284. ref.x = ref.y = 0;
  1285. ref.fov_x = ref.fov_y = 90;
  1286. ref.width = glConfig.vidWidth;
  1287. ref.height = glConfig.vidHeight;
  1288. ref.viewaxis = axis[i];
  1289. sprintf( fullname, "env/%s%s", baseName, extensions[i] );
  1290. tr.TakeScreenshot( size, size, fullname, blends, &ref );
  1291. }
  1292. common->Printf( "Wrote %s, etc\n", fullname.c_str() );
  1293. }
  1294. //============================================================================
  1295. static idMat3 cubeAxis[6];
  1296. /*
  1297. ==================
  1298. R_SampleCubeMap
  1299. ==================
  1300. */
  1301. void R_SampleCubeMap( const idVec3 &dir, int size, byte *buffers[6], byte result[4] ) {
  1302. float adir[3];
  1303. int axis, x, y;
  1304. adir[0] = fabs(dir[0]);
  1305. adir[1] = fabs(dir[1]);
  1306. adir[2] = fabs(dir[2]);
  1307. if ( dir[0] >= adir[1] && dir[0] >= adir[2] ) {
  1308. axis = 0;
  1309. } else if ( -dir[0] >= adir[1] && -dir[0] >= adir[2] ) {
  1310. axis = 1;
  1311. } else if ( dir[1] >= adir[0] && dir[1] >= adir[2] ) {
  1312. axis = 2;
  1313. } else if ( -dir[1] >= adir[0] && -dir[1] >= adir[2] ) {
  1314. axis = 3;
  1315. } else if ( dir[2] >= adir[1] && dir[2] >= adir[2] ) {
  1316. axis = 4;
  1317. } else {
  1318. axis = 5;
  1319. }
  1320. float fx = (dir * cubeAxis[axis][1]) / (dir * cubeAxis[axis][0]);
  1321. float fy = (dir * cubeAxis[axis][2]) / (dir * cubeAxis[axis][0]);
  1322. fx = -fx;
  1323. fy = -fy;
  1324. x = size * 0.5 * (fx + 1);
  1325. y = size * 0.5 * (fy + 1);
  1326. if ( x < 0 ) {
  1327. x = 0;
  1328. } else if ( x >= size ) {
  1329. x = size-1;
  1330. }
  1331. if ( y < 0 ) {
  1332. y = 0;
  1333. } else if ( y >= size ) {
  1334. y = size-1;
  1335. }
  1336. result[0] = buffers[axis][(y*size+x)*4+0];
  1337. result[1] = buffers[axis][(y*size+x)*4+1];
  1338. result[2] = buffers[axis][(y*size+x)*4+2];
  1339. result[3] = buffers[axis][(y*size+x)*4+3];
  1340. }
  1341. /*
  1342. ==================
  1343. R_MakeAmbientMap_f
  1344. R_MakeAmbientMap_f <basename> [size]
  1345. Saves out env/<basename>_amb_ft.tga, etc
  1346. ==================
  1347. */
  1348. void R_MakeAmbientMap_f( const idCmdArgs &args ) {
  1349. idStr fullname;
  1350. const char *baseName;
  1351. int i;
  1352. renderView_t ref;
  1353. viewDef_t primary;
  1354. int downSample;
  1355. char *extensions[6] = { "_px.tga", "_nx.tga", "_py.tga", "_ny.tga",
  1356. "_pz.tga", "_nz.tga" };
  1357. int outSize;
  1358. byte *buffers[6];
  1359. int width, height;
  1360. if ( args.Argc() != 2 && args.Argc() != 3 ) {
  1361. common->Printf( "USAGE: ambientshot <basename> [size]\n" );
  1362. return;
  1363. }
  1364. baseName = args.Argv( 1 );
  1365. downSample = 0;
  1366. if ( args.Argc() == 3 ) {
  1367. outSize = atoi( args.Argv( 2 ) );
  1368. } else {
  1369. outSize = 32;
  1370. }
  1371. memset( &cubeAxis, 0, sizeof( cubeAxis ) );
  1372. cubeAxis[0][0][0] = 1;
  1373. cubeAxis[0][1][2] = 1;
  1374. cubeAxis[0][2][1] = 1;
  1375. cubeAxis[1][0][0] = -1;
  1376. cubeAxis[1][1][2] = -1;
  1377. cubeAxis[1][2][1] = 1;
  1378. cubeAxis[2][0][1] = 1;
  1379. cubeAxis[2][1][0] = -1;
  1380. cubeAxis[2][2][2] = -1;
  1381. cubeAxis[3][0][1] = -1;
  1382. cubeAxis[3][1][0] = -1;
  1383. cubeAxis[3][2][2] = 1;
  1384. cubeAxis[4][0][2] = 1;
  1385. cubeAxis[4][1][0] = -1;
  1386. cubeAxis[4][2][1] = 1;
  1387. cubeAxis[5][0][2] = -1;
  1388. cubeAxis[5][1][0] = 1;
  1389. cubeAxis[5][2][1] = 1;
  1390. // read all of the images
  1391. for ( i = 0 ; i < 6 ; i++ ) {
  1392. sprintf( fullname, "env/%s%s", baseName, extensions[i] );
  1393. common->Printf( "loading %s\n", fullname.c_str() );
  1394. session->UpdateScreen();
  1395. R_LoadImage( fullname, &buffers[i], &width, &height, NULL, true );
  1396. if ( !buffers[i] ) {
  1397. common->Printf( "failed.\n" );
  1398. for ( i-- ; i >= 0 ; i-- ) {
  1399. Mem_Free( buffers[i] );
  1400. }
  1401. return;
  1402. }
  1403. }
  1404. // resample with hemispherical blending
  1405. int samples = 1000;
  1406. byte *outBuffer = (byte *)_alloca( outSize * outSize * 4 );
  1407. for ( int map = 0 ; map < 2 ; map++ ) {
  1408. for ( i = 0 ; i < 6 ; i++ ) {
  1409. for ( int x = 0 ; x < outSize ; x++ ) {
  1410. for ( int y = 0 ; y < outSize ; y++ ) {
  1411. idVec3 dir;
  1412. float total[3];
  1413. dir = cubeAxis[i][0] + -( -1 + 2.0*x/(outSize-1) ) * cubeAxis[i][1] + -( -1 + 2.0*y/(outSize-1) ) * cubeAxis[i][2];
  1414. dir.Normalize();
  1415. total[0] = total[1] = total[2] = 0;
  1416. //samples = 1;
  1417. float limit = map ? 0.95 : 0.25; // small for specular, almost hemisphere for ambient
  1418. for ( int s = 0 ; s < samples ; s++ ) {
  1419. // pick a random direction vector that is inside the unit sphere but not behind dir,
  1420. // which is a robust way to evenly sample a hemisphere
  1421. idVec3 test;
  1422. while( 1 ) {
  1423. for ( int j = 0 ; j < 3 ; j++ ) {
  1424. test[j] = -1 + 2 * (rand()&0x7fff)/(float)0x7fff;
  1425. }
  1426. if ( test.Length() > 1.0 ) {
  1427. continue;
  1428. }
  1429. test.Normalize();
  1430. if ( test * dir > limit ) { // don't do a complete hemisphere
  1431. break;
  1432. }
  1433. }
  1434. byte result[4];
  1435. //test = dir;
  1436. R_SampleCubeMap( test, width, buffers, result );
  1437. total[0] += result[0];
  1438. total[1] += result[1];
  1439. total[2] += result[2];
  1440. }
  1441. outBuffer[(y*outSize+x)*4+0] = total[0] / samples;
  1442. outBuffer[(y*outSize+x)*4+1] = total[1] / samples;
  1443. outBuffer[(y*outSize+x)*4+2] = total[2] / samples;
  1444. outBuffer[(y*outSize+x)*4+3] = 255;
  1445. }
  1446. }
  1447. if ( map == 0 ) {
  1448. sprintf( fullname, "env/%s_amb%s", baseName, extensions[i] );
  1449. } else {
  1450. sprintf( fullname, "env/%s_spec%s", baseName, extensions[i] );
  1451. }
  1452. common->Printf( "writing %s\n", fullname.c_str() );
  1453. session->UpdateScreen();
  1454. R_WriteTGA( fullname, outBuffer, outSize, outSize );
  1455. }
  1456. }
  1457. for ( i = 0 ; i < 6 ; i++ ) {
  1458. if ( buffers[i] ) {
  1459. Mem_Free( buffers[i] );
  1460. }
  1461. }
  1462. }
  1463. //============================================================================
  1464. /*
  1465. ===============
  1466. R_SetColorMappings
  1467. ===============
  1468. */
  1469. void R_SetColorMappings( void ) {
  1470. int i, j;
  1471. float g, b;
  1472. int inf;
  1473. b = r_brightness.GetFloat();
  1474. g = r_gamma.GetFloat();
  1475. for ( i = 0; i < 256; i++ ) {
  1476. j = i * b;
  1477. if (j > 255) {
  1478. j = 255;
  1479. }
  1480. if ( g == 1 ) {
  1481. inf = (j<<8) | j;
  1482. } else {
  1483. inf = 0xffff * pow ( j/255.0f, 1.0f / g ) + 0.5f;
  1484. }
  1485. if (inf < 0) {
  1486. inf = 0;
  1487. }
  1488. if (inf > 0xffff) {
  1489. inf = 0xffff;
  1490. }
  1491. tr.gammaTable[i] = inf;
  1492. }
  1493. GLimp_SetGamma( tr.gammaTable, tr.gammaTable, tr.gammaTable );
  1494. }
  1495. /*
  1496. ================
  1497. GfxInfo_f
  1498. ================
  1499. */
  1500. void GfxInfo_f( const idCmdArgs &args ) {
  1501. const char *fsstrings[] =
  1502. {
  1503. "windowed",
  1504. "fullscreen"
  1505. };
  1506. common->Printf( "\nGL_VENDOR: %s\n", glConfig.vendor_string );
  1507. common->Printf( "GL_RENDERER: %s\n", glConfig.renderer_string );
  1508. common->Printf( "GL_VERSION: %s\n", glConfig.version_string );
  1509. common->Printf( "GL_EXTENSIONS: %s\n", glConfig.extensions_string );
  1510. if ( glConfig.wgl_extensions_string ) {
  1511. common->Printf( "WGL_EXTENSIONS: %s\n", glConfig.wgl_extensions_string );
  1512. }
  1513. common->Printf( "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize );
  1514. common->Printf( "GL_MAX_TEXTURE_UNITS_ARB: %d\n", glConfig.maxTextureUnits );
  1515. common->Printf( "GL_MAX_TEXTURE_COORDS_ARB: %d\n", glConfig.maxTextureCoords );
  1516. common->Printf( "GL_MAX_TEXTURE_IMAGE_UNITS_ARB: %d\n", glConfig.maxTextureImageUnits );
  1517. common->Printf( "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits );
  1518. common->Printf( "MODE: %d, %d x %d %s hz:", r_mode.GetInteger(), glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen.GetBool()] );
  1519. if ( glConfig.displayFrequency ) {
  1520. common->Printf( "%d\n", glConfig.displayFrequency );
  1521. } else {
  1522. common->Printf( "N/A\n" );
  1523. }
  1524. common->Printf( "CPU: %s\n", Sys_GetProcessorString() );
  1525. const char *active[2] = { "", " (ACTIVE)" };
  1526. common->Printf( "ARB path ENABLED%s\n", active[tr.backEndRenderer == BE_ARB] );
  1527. if ( glConfig.allowNV10Path ) {
  1528. common->Printf( "NV10 path ENABLED%s\n", active[tr.backEndRenderer == BE_NV10] );
  1529. } else {
  1530. common->Printf( "NV10 path disabled\n" );
  1531. }
  1532. if ( glConfig.allowNV20Path ) {
  1533. common->Printf( "NV20 path ENABLED%s\n", active[tr.backEndRenderer == BE_NV20] );
  1534. } else {
  1535. common->Printf( "NV20 path disabled\n" );
  1536. }
  1537. if ( glConfig.allowR200Path ) {
  1538. common->Printf( "R200 path ENABLED%s\n", active[tr.backEndRenderer == BE_R200] );
  1539. } else {
  1540. common->Printf( "R200 path disabled\n" );
  1541. }
  1542. if ( glConfig.allowARB2Path ) {
  1543. common->Printf( "ARB2 path ENABLED%s\n", active[tr.backEndRenderer == BE_ARB2] );
  1544. } else {
  1545. common->Printf( "ARB2 path disabled\n" );
  1546. }
  1547. //=============================
  1548. common->Printf( "-------\n" );
  1549. if ( r_finish.GetBool() ) {
  1550. common->Printf( "Forcing glFinish\n" );
  1551. } else {
  1552. common->Printf( "glFinish not forced\n" );
  1553. }
  1554. #if defined(_WIN32) && !defined(USE_SDL)
  1555. // WGL_EXT_swap_interval
  1556. typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
  1557. extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
  1558. if ( r_swapInterval.GetInteger() && wglSwapIntervalEXT ) {
  1559. common->Printf( "Forcing swapInterval %i\n", r_swapInterval.GetInteger() );
  1560. } else {
  1561. common->Printf( "swapInterval not forced\n" );
  1562. }
  1563. #endif
  1564. bool tss = glConfig.twoSidedStencilAvailable || glConfig.atiTwoSidedStencilAvailable;
  1565. if ( !r_useTwoSidedStencil.GetBool() && tss ) {
  1566. common->Printf( "Two sided stencil available but disabled\n" );
  1567. } else if ( !tss ) {
  1568. common->Printf( "Two sided stencil not available\n" );
  1569. } else if ( tss ) {
  1570. common->Printf( "Using two sided stencil\n" );
  1571. }
  1572. if ( vertexCache.IsFast() ) {
  1573. common->Printf( "Vertex cache is fast\n" );
  1574. } else {
  1575. common->Printf( "Vertex cache is SLOW\n" );
  1576. }
  1577. }
  1578. /*
  1579. =================
  1580. R_VidRestart_f
  1581. =================
  1582. */
  1583. void R_VidRestart_f( const idCmdArgs &args ) {
  1584. int err;
  1585. // if OpenGL isn't started, do nothing
  1586. if ( !glConfig.isInitialized ) {
  1587. return;
  1588. }
  1589. bool full = true;
  1590. bool forceWindow = false;
  1591. for ( int i = 1 ; i < args.Argc() ; i++ ) {
  1592. if ( idStr::Icmp( args.Argv( i ), "partial" ) == 0 ) {
  1593. full = false;
  1594. continue;
  1595. }
  1596. if ( idStr::Icmp( args.Argv( i ), "windowed" ) == 0 ) {
  1597. forceWindow = true;
  1598. continue;
  1599. }
  1600. }
  1601. // this could take a while, so give them the cursor back ASAP
  1602. Sys_GrabMouseCursor( false );
  1603. // dump ambient caches
  1604. renderModelManager->FreeModelVertexCaches();
  1605. // free any current world interaction surfaces and vertex caches
  1606. R_FreeDerivedData();
  1607. // make sure the defered frees are actually freed
  1608. R_ToggleSmpFrame();
  1609. R_ToggleSmpFrame();
  1610. // free the vertex caches so they will be regenerated again
  1611. vertexCache.PurgeAll();
  1612. // sound and input are tied to the window we are about to destroy
  1613. if ( full ) {
  1614. // free all of our texture numbers
  1615. soundSystem->ShutdownHW();
  1616. Sys_ShutdownInput();
  1617. globalImages->PurgeAllImages();
  1618. // free the context and close the window
  1619. GLimp_Shutdown();
  1620. glConfig.isInitialized = false;
  1621. // create the new context and vertex cache
  1622. bool latch = cvarSystem->GetCVarBool( "r_fullscreen" );
  1623. if ( forceWindow ) {
  1624. cvarSystem->SetCVarBool( "r_fullscreen", false );
  1625. }
  1626. R_InitOpenGL();
  1627. cvarSystem->SetCVarBool( "r_fullscreen", latch );
  1628. // regenerate all images
  1629. globalImages->ReloadAllImages();
  1630. } else {
  1631. glimpParms_t parms;
  1632. parms.width = glConfig.vidWidth;
  1633. parms.height = glConfig.vidHeight;
  1634. parms.fullScreen = ( forceWindow ) ? false : r_fullscreen.GetBool();
  1635. parms.displayHz = r_displayRefresh.GetInteger();
  1636. parms.multiSamples = r_multiSamples.GetInteger();
  1637. parms.stereo = false;
  1638. GLimp_SetScreenParms( parms );
  1639. }
  1640. // make sure the regeneration doesn't use anything no longer valid
  1641. tr.viewCount++;
  1642. tr.viewDef = NULL;
  1643. // regenerate all necessary interactions
  1644. R_RegenerateWorld_f( idCmdArgs() );
  1645. // check for problems
  1646. err = qglGetError();
  1647. if ( err != GL_NO_ERROR ) {
  1648. common->Printf( "glGetError() = 0x%x\n", err );
  1649. }
  1650. // start sound playing again
  1651. soundSystem->SetMute( false );
  1652. }
  1653. /*
  1654. =================
  1655. R_InitMaterials
  1656. =================
  1657. */
  1658. void R_InitMaterials( void ) {
  1659. tr.defaultMaterial = declManager->FindMaterial( "_default", false );
  1660. if ( !tr.defaultMaterial ) {
  1661. common->FatalError( "_default material not found" );
  1662. }
  1663. declManager->FindMaterial( "_default", false );
  1664. // needed by R_DeriveLightData
  1665. declManager->FindMaterial( "lights/defaultPointLight" );
  1666. declManager->FindMaterial( "lights/defaultProjectedLight" );
  1667. }
  1668. /*
  1669. =================
  1670. R_SizeUp_f
  1671. Keybinding command
  1672. =================
  1673. */
  1674. static void R_SizeUp_f( const idCmdArgs &args ) {
  1675. if ( r_screenFraction.GetInteger() + 10 > 100 ) {
  1676. r_screenFraction.SetInteger( 100 );
  1677. } else {
  1678. r_screenFraction.SetInteger( r_screenFraction.GetInteger() + 10 );
  1679. }
  1680. }
  1681. /*
  1682. =================
  1683. R_SizeDown_f
  1684. Keybinding command
  1685. =================
  1686. */
  1687. static void R_SizeDown_f( const idCmdArgs &args ) {
  1688. if ( r_screenFraction.GetInteger() - 10 < 10 ) {
  1689. r_screenFraction.SetInteger( 10 );
  1690. } else {
  1691. r_screenFraction.SetInteger( r_screenFraction.GetInteger() - 10 );
  1692. }
  1693. }
  1694. /*
  1695. ===============
  1696. TouchGui_f
  1697. this is called from the main thread
  1698. ===============
  1699. */
  1700. void R_TouchGui_f( const idCmdArgs &args ) {
  1701. const char *gui = args.Argv( 1 );
  1702. if ( !gui[0] ) {
  1703. common->Printf( "USAGE: touchGui <guiName>\n" );
  1704. return;
  1705. }
  1706. common->Printf( "touchGui %s\n", gui );
  1707. session->UpdateScreen();
  1708. uiManager->Touch( gui );
  1709. }
  1710. /*
  1711. =================
  1712. R_InitCvars
  1713. =================
  1714. */
  1715. void R_InitCvars( void ) {
  1716. // update latched cvars here
  1717. }
  1718. /*
  1719. =================
  1720. R_InitCommands
  1721. =================
  1722. */
  1723. void R_InitCommands( void ) {
  1724. cmdSystem->AddCommand( "MakeMegaTexture", idMegaTexture::MakeMegaTexture_f, CMD_FL_RENDERER|CMD_FL_CHEAT, "processes giant images" );
  1725. cmdSystem->AddCommand( "sizeUp", R_SizeUp_f, CMD_FL_RENDERER, "makes the rendered view larger" );
  1726. cmdSystem->AddCommand( "sizeDown", R_SizeDown_f, CMD_FL_RENDERER, "makes the rendered view smaller" );
  1727. cmdSystem->AddCommand( "reloadGuis", R_ReloadGuis_f, CMD_FL_RENDERER, "reloads guis" );
  1728. cmdSystem->AddCommand( "listGuis", R_ListGuis_f, CMD_FL_RENDERER, "lists guis" );
  1729. cmdSystem->AddCommand( "touchGui", R_TouchGui_f, CMD_FL_RENDERER, "touches a gui" );
  1730. cmdSystem->AddCommand( "screenshot", R_ScreenShot_f, CMD_FL_RENDERER, "takes a screenshot" );
  1731. cmdSystem->AddCommand( "envshot", R_EnvShot_f, CMD_FL_RENDERER, "takes an environment shot" );
  1732. cmdSystem->AddCommand( "makeAmbientMap", R_MakeAmbientMap_f, CMD_FL_RENDERER|CMD_FL_CHEAT, "makes an ambient map" );
  1733. cmdSystem->AddCommand( "benchmark", R_Benchmark_f, CMD_FL_RENDERER, "benchmark" );
  1734. cmdSystem->AddCommand( "gfxInfo", GfxInfo_f, CMD_FL_RENDERER, "show graphics info" );
  1735. cmdSystem->AddCommand( "modulateLights", R_ModulateLights_f, CMD_FL_RENDERER | CMD_FL_CHEAT, "modifies shader parms on all lights" );
  1736. cmdSystem->AddCommand( "testImage", R_TestImage_f, CMD_FL_RENDERER | CMD_FL_CHEAT, "displays the given image centered on screen", idCmdSystem::ArgCompletion_ImageName );
  1737. cmdSystem->AddCommand( "testVideo", R_TestVideo_f, CMD_FL_RENDERER | CMD_FL_CHEAT, "displays the given cinematic", idCmdSystem::ArgCompletion_VideoName );
  1738. cmdSystem->AddCommand( "reportSurfaceAreas", R_ReportSurfaceAreas_f, CMD_FL_RENDERER, "lists all used materials sorted by surface area" );
  1739. cmdSystem->AddCommand( "reportImageDuplication", R_ReportImageDuplication_f, CMD_FL_RENDERER, "checks all referenced images for duplications" );
  1740. cmdSystem->AddCommand( "regenerateWorld", R_RegenerateWorld_f, CMD_FL_RENDERER, "regenerates all interactions" );
  1741. cmdSystem->AddCommand( "showInteractionMemory", R_ShowInteractionMemory_f, CMD_FL_RENDERER, "shows memory used by interactions" );
  1742. cmdSystem->AddCommand( "showTriSurfMemory", R_ShowTriSurfMemory_f, CMD_FL_RENDERER, "shows memory used by triangle surfaces" );
  1743. cmdSystem->AddCommand( "vid_restart", R_VidRestart_f, CMD_FL_RENDERER, "restarts renderSystem" );
  1744. cmdSystem->AddCommand( "listRenderEntityDefs", R_ListRenderEntityDefs_f, CMD_FL_RENDERER, "lists the entity defs" );
  1745. cmdSystem->AddCommand( "listRenderLightDefs", R_ListRenderLightDefs_f, CMD_FL_RENDERER, "lists the light defs" );
  1746. cmdSystem->AddCommand( "listModes", R_ListModes_f, CMD_FL_RENDERER, "lists all video modes" );
  1747. cmdSystem->AddCommand( "reloadSurface", R_ReloadSurface_f, CMD_FL_RENDERER, "reloads the decl and images for selected surface" );
  1748. }
  1749. /*
  1750. ===============
  1751. idRenderSystemLocal::Clear
  1752. ===============
  1753. */
  1754. void idRenderSystemLocal::Clear( void ) {
  1755. registered = false;
  1756. frameCount = 0;
  1757. viewCount = 0;
  1758. staticAllocCount = 0;
  1759. frameShaderTime = 0.0f;
  1760. viewportOffset[0] = 0;
  1761. viewportOffset[1] = 0;
  1762. tiledViewport[0] = 0;
  1763. tiledViewport[1] = 0;
  1764. backEndRenderer = BE_BAD;
  1765. backEndRendererHasVertexPrograms = false;
  1766. backEndRendererMaxLight = 1.0f;
  1767. ambientLightVector.Zero();
  1768. sortOffset = 0;
  1769. worlds.Clear();
  1770. primaryWorld = NULL;
  1771. memset( &primaryRenderView, 0, sizeof( primaryRenderView ) );
  1772. primaryView = NULL;
  1773. defaultMaterial = NULL;
  1774. testImage = NULL;
  1775. ambientCubeImage = NULL;
  1776. viewDef = NULL;
  1777. memset( &pc, 0, sizeof( pc ) );
  1778. memset( &lockSurfacesCmd, 0, sizeof( lockSurfacesCmd ) );
  1779. memset( &identitySpace, 0, sizeof( identitySpace ) );
  1780. logFile = NULL;
  1781. stencilIncr = 0;
  1782. stencilDecr = 0;
  1783. memset( renderCrops, 0, sizeof( renderCrops ) );
  1784. currentRenderCrop = 0;
  1785. guiRecursionLevel = 0;
  1786. guiModel = NULL;
  1787. demoGuiModel = NULL;
  1788. memset( gammaTable, 0, sizeof( gammaTable ) );
  1789. takingScreenshot = false;
  1790. }
  1791. /*
  1792. ===============
  1793. idRenderSystemLocal::Init
  1794. ===============
  1795. */
  1796. void idRenderSystemLocal::Init( void ) {
  1797. common->Printf( "------- Initializing renderSystem --------\n" );
  1798. // clear all our internal state
  1799. viewCount = 1; // so cleared structures never match viewCount
  1800. // we used to memset tr, but now that it is a class, we can't, so
  1801. // there may be other state we need to reset
  1802. ambientLightVector[0] = 0.5f;
  1803. ambientLightVector[1] = 0.5f - 0.385f;
  1804. ambientLightVector[2] = 0.8925f;
  1805. ambientLightVector[3] = 1.0f;
  1806. memset( &backEnd, 0, sizeof( backEnd ) );
  1807. R_InitCvars();
  1808. R_InitCommands();
  1809. guiModel = new idGuiModel;
  1810. guiModel->Clear();
  1811. demoGuiModel = new idGuiModel;
  1812. demoGuiModel->Clear();
  1813. R_InitTriSurfData();
  1814. globalImages->Init();
  1815. idCinematic::InitCinematic( );
  1816. // build brightness translation tables
  1817. R_SetColorMappings();
  1818. R_InitMaterials();
  1819. renderModelManager->Init();
  1820. // set the identity space
  1821. identitySpace.modelMatrix[0*4+0] = 1.0f;
  1822. identitySpace.modelMatrix[1*4+1] = 1.0f;
  1823. identitySpace.modelMatrix[2*4+2] = 1.0f;
  1824. // determine which back end we will use
  1825. // ??? this is invalid here as there is not enough information to set it up correctly
  1826. SetBackEndRenderer();
  1827. common->Printf( "renderSystem initialized.\n" );
  1828. common->Printf( "--------------------------------------\n" );
  1829. }
  1830. /*
  1831. ===============
  1832. idRenderSystemLocal::Shutdown
  1833. ===============
  1834. */
  1835. void idRenderSystemLocal::Shutdown( void ) {
  1836. common->Printf( "idRenderSystem::Shutdown()\n" );
  1837. R_DoneFreeType( );
  1838. if ( glConfig.isInitialized ) {
  1839. globalImages->PurgeAllImages();
  1840. }
  1841. renderModelManager->Shutdown();
  1842. idCinematic::ShutdownCinematic( );
  1843. globalImages->Shutdown();
  1844. // close the r_logFile
  1845. if ( logFile ) {
  1846. fprintf( logFile, "*** CLOSING LOG ***\n" );
  1847. fclose( logFile );
  1848. logFile = 0;
  1849. }
  1850. // free frame memory
  1851. R_ShutdownFrameData();
  1852. // free the vertex cache, which should have nothing allocated now
  1853. vertexCache.Shutdown();
  1854. R_ShutdownTriSurfData();
  1855. RB_ShutdownDebugTools();
  1856. delete guiModel;
  1857. delete demoGuiModel;
  1858. Clear();
  1859. ShutdownOpenGL();
  1860. }
  1861. /*
  1862. ========================
  1863. idRenderSystemLocal::BeginLevelLoad
  1864. ========================
  1865. */
  1866. void idRenderSystemLocal::BeginLevelLoad( void ) {
  1867. renderModelManager->BeginLevelLoad();
  1868. globalImages->BeginLevelLoad();
  1869. }
  1870. /*
  1871. ========================
  1872. idRenderSystemLocal::EndLevelLoad
  1873. ========================
  1874. */
  1875. void idRenderSystemLocal::EndLevelLoad( void ) {
  1876. renderModelManager->EndLevelLoad();
  1877. globalImages->EndLevelLoad();
  1878. if ( r_forceLoadImages.GetBool() ) {
  1879. RB_ShowImages();
  1880. }
  1881. }
  1882. /*
  1883. ========================
  1884. idRenderSystemLocal::InitOpenGL
  1885. ========================
  1886. */
  1887. void idRenderSystemLocal::InitOpenGL( void ) {
  1888. // if OpenGL isn't started, start it now
  1889. if ( !glConfig.isInitialized ) {
  1890. int err;
  1891. R_InitOpenGL();
  1892. globalImages->ReloadAllImages();
  1893. err = qglGetError();
  1894. if ( err != GL_NO_ERROR ) {
  1895. common->Printf( "glGetError() = 0x%x\n", err );
  1896. }
  1897. }
  1898. }
  1899. /*
  1900. ========================
  1901. idRenderSystemLocal::ShutdownOpenGL
  1902. ========================
  1903. */
  1904. void idRenderSystemLocal::ShutdownOpenGL( void ) {
  1905. // free the context and close the window
  1906. R_ShutdownFrameData();
  1907. GLimp_Shutdown();
  1908. glConfig.isInitialized = false;
  1909. }
  1910. /*
  1911. ========================
  1912. idRenderSystemLocal::IsOpenGLRunning
  1913. ========================
  1914. */
  1915. bool idRenderSystemLocal::IsOpenGLRunning( void ) const {
  1916. if ( !glConfig.isInitialized ) {
  1917. return false;
  1918. }
  1919. return true;
  1920. }
  1921. /*
  1922. ========================
  1923. idRenderSystemLocal::IsFullScreen
  1924. ========================
  1925. */
  1926. bool idRenderSystemLocal::IsFullScreen( void ) const {
  1927. return glConfig.isFullscreen;
  1928. }
  1929. /*
  1930. ========================
  1931. idRenderSystemLocal::GetScreenWidth
  1932. ========================
  1933. */
  1934. int idRenderSystemLocal::GetScreenWidth( void ) const {
  1935. return glConfig.vidWidth;
  1936. }
  1937. /*
  1938. ========================
  1939. idRenderSystemLocal::GetScreenHeight
  1940. ========================
  1941. */
  1942. int idRenderSystemLocal::GetScreenHeight( void ) const {
  1943. return glConfig.vidHeight;
  1944. }
  1945. /*
  1946. ========================
  1947. idRenderSystemLocal::GetCardCaps
  1948. ========================
  1949. */
  1950. void idRenderSystemLocal::GetCardCaps( bool &oldCard, bool &nv10or20 ) {
  1951. nv10or20 = ( tr.backEndRenderer == BE_NV10 || tr.backEndRenderer == BE_NV20 );
  1952. oldCard = ( tr.backEndRenderer == BE_ARB || tr.backEndRenderer == BE_R200 || tr.backEndRenderer == BE_NV10 || tr.backEndRenderer == BE_NV20 );
  1953. }