123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- 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.
- ===========================================================================
- */
- #pragma hdrstop
- #include "../idlib/precompiled.h"
- #include "tr_local.h"
- #include "simplex.h" // line font definition
- idCVar r_showCenterOfProjection( "r_showCenterOfProjection", "0", CVAR_RENDERER | CVAR_BOOL, "Draw a cross to show the center of projection" );
- idCVar r_showLines( "r_showLines", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = draw alternate horizontal lines, 2 = draw alternate vertical lines" );
- #define MAX_DEBUG_LINES 16384
- typedef struct debugLine_s {
- idVec4 rgb;
- idVec3 start;
- idVec3 end;
- bool depthTest;
- int lifeTime;
- } debugLine_t;
- debugLine_t rb_debugLines[ MAX_DEBUG_LINES ];
- int rb_numDebugLines = 0;
- int rb_debugLineTime = 0;
- #define MAX_DEBUG_TEXT 512
- typedef struct debugText_s {
- idStr text;
- idVec3 origin;
- float scale;
- idVec4 color;
- idMat3 viewAxis;
- int align;
- int lifeTime;
- bool depthTest;
- } debugText_t;
- debugText_t rb_debugText[ MAX_DEBUG_TEXT ];
- int rb_numDebugText = 0;
- int rb_debugTextTime = 0;
- #define MAX_DEBUG_POLYGONS 8192
- typedef struct debugPolygon_s {
- idVec4 rgb;
- idWinding winding;
- bool depthTest;
- int lifeTime;
- } debugPolygon_t;
- debugPolygon_t rb_debugPolygons[ MAX_DEBUG_POLYGONS ];
- int rb_numDebugPolygons = 0;
- int rb_debugPolygonTime = 0;
- static void RB_DrawText( const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align );
- void RB_SetMVP( const idRenderMatrix & mvp );
- /*
- ================
- RB_DrawBounds
- ================
- */
- void RB_DrawBounds( const idBounds &bounds ) {
- if ( bounds.IsCleared() ) {
- return;
- }
- qglBegin( GL_LINE_LOOP );
- qglVertex3f( bounds[0][0], bounds[0][1], bounds[0][2] );
- qglVertex3f( bounds[0][0], bounds[1][1], bounds[0][2] );
- qglVertex3f( bounds[1][0], bounds[1][1], bounds[0][2] );
- qglVertex3f( bounds[1][0], bounds[0][1], bounds[0][2] );
- qglEnd();
- qglBegin( GL_LINE_LOOP );
- qglVertex3f( bounds[0][0], bounds[0][1], bounds[1][2] );
- qglVertex3f( bounds[0][0], bounds[1][1], bounds[1][2] );
- qglVertex3f( bounds[1][0], bounds[1][1], bounds[1][2] );
- qglVertex3f( bounds[1][0], bounds[0][1], bounds[1][2] );
- qglEnd();
- qglBegin( GL_LINES );
- qglVertex3f( bounds[0][0], bounds[0][1], bounds[0][2] );
- qglVertex3f( bounds[0][0], bounds[0][1], bounds[1][2] );
- qglVertex3f( bounds[0][0], bounds[1][1], bounds[0][2] );
- qglVertex3f( bounds[0][0], bounds[1][1], bounds[1][2] );
- qglVertex3f( bounds[1][0], bounds[0][1], bounds[0][2] );
- qglVertex3f( bounds[1][0], bounds[0][1], bounds[1][2] );
- qglVertex3f( bounds[1][0], bounds[1][1], bounds[0][2] );
- qglVertex3f( bounds[1][0], bounds[1][1], bounds[1][2] );
- qglEnd();
- }
- /*
- ================
- RB_SimpleSurfaceSetup
- ================
- */
- static void RB_SimpleSurfaceSetup( const drawSurf_t *drawSurf ) {
- // change the matrix if needed
- if ( drawSurf->space != backEnd.currentSpace ) {
- qglLoadMatrixf( drawSurf->space->modelViewMatrix );
- backEnd.currentSpace = drawSurf->space;
- }
- // change the scissor if needed
- if ( !backEnd.currentScissor.Equals( drawSurf->scissorRect ) && r_useScissor.GetBool() ) {
- GL_Scissor( backEnd.viewDef->viewport.x1 + drawSurf->scissorRect.x1,
- backEnd.viewDef->viewport.y1 + drawSurf->scissorRect.y1,
- drawSurf->scissorRect.x2 + 1 - drawSurf->scissorRect.x1,
- drawSurf->scissorRect.y2 + 1 - drawSurf->scissorRect.y1 );
- backEnd.currentScissor = drawSurf->scissorRect;
- }
- }
- /*
- ================
- RB_SimpleWorldSetup
- ================
- */
- static void RB_SimpleWorldSetup() {
- backEnd.currentSpace = &backEnd.viewDef->worldSpace;
- qglLoadMatrixf( backEnd.viewDef->worldSpace.modelViewMatrix );
- GL_Scissor( backEnd.viewDef->viewport.x1 + backEnd.viewDef->scissor.x1,
- backEnd.viewDef->viewport.y1 + backEnd.viewDef->scissor.y1,
- backEnd.viewDef->scissor.x2 + 1 - backEnd.viewDef->scissor.x1,
- backEnd.viewDef->scissor.y2 + 1 - backEnd.viewDef->scissor.y1 );
- backEnd.currentScissor = backEnd.viewDef->scissor;
- }
- /*
- =================
- RB_PolygonClear
- This will cover the entire screen with normal rasterization.
- Texturing is disabled, but the existing glColor, glDepthMask,
- glColorMask, and the enabled state of depth buffering and
- stenciling will matter.
- =================
- */
- void RB_PolygonClear() {
- qglPushMatrix();
- qglPushAttrib( GL_ALL_ATTRIB_BITS );
- qglLoadIdentity();
- qglDisable( GL_TEXTURE_2D );
- qglDisable( GL_DEPTH_TEST );
- qglDisable( GL_CULL_FACE );
- qglDisable( GL_SCISSOR_TEST );
- qglBegin( GL_POLYGON );
- qglVertex3f( -20, -20, -10 );
- qglVertex3f( 20, -20, -10 );
- qglVertex3f( 20, 20, -10 );
- qglVertex3f( -20, 20, -10 );
- qglEnd();
- qglPopAttrib();
- qglPopMatrix();
- }
- /*
- ====================
- RB_ShowDestinationAlpha
- ====================
- */
- void RB_ShowDestinationAlpha() {
- GL_State( GLS_SRCBLEND_DST_ALPHA | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS );
- GL_Color( 1, 1, 1 );
- RB_PolygonClear();
- }
- /*
- ===================
- RB_ScanStencilBuffer
- Debugging tool to see what values are in the stencil buffer
- ===================
- */
- void RB_ScanStencilBuffer() {
- int counts[256];
- int i;
- byte *stencilReadback;
- memset( counts, 0, sizeof( counts ) );
- stencilReadback = (byte *)R_StaticAlloc( renderSystem->GetWidth() * renderSystem->GetHeight(), TAG_RENDER_TOOLS );
- qglReadPixels( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight(), GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );
- for ( i = 0; i < renderSystem->GetWidth() * renderSystem->GetHeight(); i++ ) {
- counts[ stencilReadback[i] ]++;
- }
- R_StaticFree( stencilReadback );
- // print some stats (not supposed to do from back end in SMP...)
- common->Printf( "stencil values:\n" );
- for ( i = 0; i < 255; i++ ) {
- if ( counts[i] ) {
- common->Printf( "%i: %i\n", i, counts[i] );
- }
- }
- }
- /*
- ===================
- RB_CountStencilBuffer
- Print an overdraw count based on stencil index values
- ===================
- */
- static void RB_CountStencilBuffer() {
- int count;
- int i;
- byte *stencilReadback;
- stencilReadback = (byte *)R_StaticAlloc( renderSystem->GetWidth() * renderSystem->GetHeight(), TAG_RENDER_TOOLS );
- qglReadPixels( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight(), GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback );
- count = 0;
- for ( i = 0; i < renderSystem->GetWidth() * renderSystem->GetHeight(); i++ ) {
- count += stencilReadback[i];
- }
- R_StaticFree( stencilReadback );
- // print some stats (not supposed to do from back end in SMP...)
- common->Printf( "overdraw: %5.1f\n", (float)count/(renderSystem->GetWidth() * renderSystem->GetHeight()) );
- }
- /*
- ===================
- R_ColorByStencilBuffer
- Sets the screen colors based on the contents of the
- stencil buffer. Stencil of 0 = black, 1 = red, 2 = green,
- 3 = blue, ..., 7+ = white
- ===================
- */
- static void R_ColorByStencilBuffer() {
- int i;
- static float colors[8][3] = {
- {0,0,0},
- {1,0,0},
- {0,1,0},
- {0,0,1},
- {0,1,1},
- {1,0,1},
- {1,1,0},
- {1,1,1},
- };
- // clear color buffer to white (>6 passes)
- GL_Clear( true, false, false, 0, 1.0f, 1.0f, 1.0f, 1.0f );
- // now draw color for each stencil value
- qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
- for ( i = 0; i < 6; i++ ) {
- GL_Color( colors[i] );
- renderProgManager.BindShader_Color();
- qglStencilFunc( GL_EQUAL, i, 255 );
- RB_PolygonClear();
- }
- qglStencilFunc( GL_ALWAYS, 0, 255 );
- }
- //======================================================================
- /*
- ==================
- RB_ShowOverdraw
- ==================
- */
- void RB_ShowOverdraw() {
- const idMaterial * material;
- int i;
- drawSurf_t * * drawSurfs;
- const drawSurf_t * surf;
- int numDrawSurfs;
- viewLight_t * vLight;
- if ( r_showOverDraw.GetInteger() == 0 ) {
- return;
- }
- material = declManager->FindMaterial( "textures/common/overdrawtest", false );
- if ( material == NULL ) {
- return;
- }
- drawSurfs = backEnd.viewDef->drawSurfs;
- numDrawSurfs = backEnd.viewDef->numDrawSurfs;
- int interactions = 0;
- for ( vLight = backEnd.viewDef->viewLights; vLight; vLight = vLight->next ) {
- for ( surf = vLight->localInteractions; surf; surf = surf->nextOnLight ) {
- interactions++;
- }
- for ( surf = vLight->globalInteractions; surf; surf = surf->nextOnLight ) {
- interactions++;
- }
- }
- // FIXME: can't frame alloc from the renderer back-end
- drawSurf_t **newDrawSurfs = (drawSurf_t **)R_FrameAlloc( numDrawSurfs + interactions * sizeof( newDrawSurfs[0] ), FRAME_ALLOC_DRAW_SURFACE_POINTER );
- for ( i = 0; i < numDrawSurfs; i++ ) {
- surf = drawSurfs[i];
- if ( surf->material ) {
- const_cast<drawSurf_t *>(surf)->material = material;
- }
- newDrawSurfs[i] = const_cast<drawSurf_t *>(surf);
- }
- for ( vLight = backEnd.viewDef->viewLights; vLight; vLight = vLight->next ) {
- for ( surf = vLight->localInteractions; surf; surf = surf->nextOnLight ) {
- const_cast<drawSurf_t *>(surf)->material = material;
- newDrawSurfs[i++] = const_cast<drawSurf_t *>(surf);
- }
- for ( surf = vLight->globalInteractions; surf; surf = surf->nextOnLight ) {
- const_cast<drawSurf_t *>(surf)->material = material;
- newDrawSurfs[i++] = const_cast<drawSurf_t *>(surf);
- }
- vLight->localInteractions = NULL;
- vLight->globalInteractions = NULL;
- }
- switch( r_showOverDraw.GetInteger() ) {
- case 1: // geometry overdraw
- const_cast<viewDef_t *>(backEnd.viewDef)->drawSurfs = newDrawSurfs;
- const_cast<viewDef_t *>(backEnd.viewDef)->numDrawSurfs = numDrawSurfs;
- break;
- case 2: // light interaction overdraw
- const_cast<viewDef_t *>(backEnd.viewDef)->drawSurfs = &newDrawSurfs[numDrawSurfs];
- const_cast<viewDef_t *>(backEnd.viewDef)->numDrawSurfs = interactions;
- break;
- case 3: // geometry + light interaction overdraw
- const_cast<viewDef_t *>(backEnd.viewDef)->drawSurfs = newDrawSurfs;
- const_cast<viewDef_t *>(backEnd.viewDef)->numDrawSurfs += interactions;
- break;
- }
- }
- /*
- ===================
- RB_ShowIntensity
- Debugging tool to see how much dynamic range a scene is using.
- The greatest of the rgb values at each pixel will be used, with
- the resulting color shading from red at 0 to green at 128 to blue at 255
- ===================
- */
- static void RB_ShowIntensity() {
- byte *colorReadback;
- int i, j, c;
- if ( !r_showIntensity.GetBool() ) {
- return;
- }
- colorReadback = (byte *)R_StaticAlloc( renderSystem->GetWidth() * renderSystem->GetHeight() * 4, TAG_RENDER_TOOLS );
- qglReadPixels( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, colorReadback );
- c = renderSystem->GetWidth() * renderSystem->GetHeight() * 4;
- for ( i = 0; i < c; i+=4 ) {
- j = colorReadback[i];
- if ( colorReadback[i+1] > j ) {
- j = colorReadback[i+1];
- }
- if ( colorReadback[i+2] > j ) {
- j = colorReadback[i+2];
- }
- if ( j < 128 ) {
- colorReadback[i+0] = 2*(128-j);
- colorReadback[i+1] = 2*j;
- colorReadback[i+2] = 0;
- } else {
- colorReadback[i+0] = 0;
- colorReadback[i+1] = 2*(255-j);
- colorReadback[i+2] = 2*(j-128);
- }
- }
- // draw it back to the screen
- qglLoadIdentity();
- qglMatrixMode( GL_PROJECTION );
- GL_State( GLS_DEPTHFUNC_ALWAYS );
- qglPushMatrix();
- qglLoadIdentity();
- qglOrtho( 0, 1, 0, 1, -1, 1 );
- qglRasterPos2f( 0, 0 );
- qglPopMatrix();
- GL_Color( 1, 1, 1 );
- globalImages->BindNull();
- qglMatrixMode( GL_MODELVIEW );
- qglDrawPixels( renderSystem->GetWidth(), renderSystem->GetHeight(), GL_RGBA , GL_UNSIGNED_BYTE, colorReadback );
- R_StaticFree( colorReadback );
- }
- /*
- ===================
- RB_ShowDepthBuffer
- Draw the depth buffer as colors
- ===================
- */
- static void RB_ShowDepthBuffer() {
- void *depthReadback;
- if ( !r_showDepth.GetBool() ) {
- return;
- }
- qglPushMatrix();
- qglLoadIdentity();
- qglMatrixMode( GL_PROJECTION );
- qglPushMatrix();
- qglLoadIdentity();
- qglOrtho( 0, 1, 0, 1, -1, 1 );
- qglRasterPos2f( 0, 0 );
- qglPopMatrix();
- qglMatrixMode( GL_MODELVIEW );
- qglPopMatrix();
- GL_State( GLS_DEPTHFUNC_ALWAYS );
- GL_Color( 1, 1, 1 );
- globalImages->BindNull();
- depthReadback = R_StaticAlloc( renderSystem->GetWidth() * renderSystem->GetHeight()*4, TAG_RENDER_TOOLS );
- memset( depthReadback, 0, renderSystem->GetWidth() * renderSystem->GetHeight()*4 );
- qglReadPixels( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight(), GL_DEPTH_COMPONENT , GL_FLOAT, depthReadback );
- #if 0
- for ( i = 0; i < renderSystem->GetWidth() * renderSystem->GetHeight(); i++ ) {
- ((byte *)depthReadback)[i*4] =
- ((byte *)depthReadback)[i*4+1] =
- ((byte *)depthReadback)[i*4+2] = 255 * ((float *)depthReadback)[i];
- ((byte *)depthReadback)[i*4+3] = 1;
- }
- #endif
- qglDrawPixels( renderSystem->GetWidth(), renderSystem->GetHeight(), GL_RGBA , GL_UNSIGNED_BYTE, depthReadback );
- R_StaticFree( depthReadback );
- }
- /*
- =================
- RB_ShowLightCount
- This is a debugging tool that will draw each surface with a color
- based on how many lights are effecting it
- =================
- */
- static void RB_ShowLightCount() {
- int i;
- const drawSurf_t *surf;
- const viewLight_t *vLight;
- if ( !r_showLightCount.GetBool() ) {
- return;
- }
- RB_SimpleWorldSetup();
- GL_Clear( false, false, true, 0, 0.0f, 0.0f, 0.0f, 0.0f );
- // optionally count everything through walls
- if ( r_showLightCount.GetInteger() >= 2 ) {
- GL_State( GLS_DEPTHFUNC_EQUAL | GLS_STENCIL_OP_FAIL_KEEP | GLS_STENCIL_OP_ZFAIL_INCR | GLS_STENCIL_OP_PASS_INCR );
- } else {
- GL_State( GLS_DEPTHFUNC_EQUAL | GLS_STENCIL_OP_FAIL_KEEP | GLS_STENCIL_OP_ZFAIL_KEEP | GLS_STENCIL_OP_PASS_INCR );
- }
- globalImages->defaultImage->Bind();
- for ( vLight = backEnd.viewDef->viewLights; vLight; vLight = vLight->next ) {
- for ( i = 0; i < 2; i++ ) {
- for ( surf = i ? vLight->localInteractions: vLight->globalInteractions; surf; surf = (drawSurf_t *)surf->nextOnLight ) {
- RB_SimpleSurfaceSetup( surf );
- RB_DrawElementsWithCounters( surf );
- }
- }
- }
- // display the results
- R_ColorByStencilBuffer();
- if ( r_showLightCount.GetInteger() > 2 ) {
- RB_CountStencilBuffer();
- }
- }
- /*
- ===============
- RB_SetWeaponDepthHack
- ===============
- */
- static void RB_SetWeaponDepthHack() {
- }
- /*
- ===============
- RB_SetModelDepthHack
- ===============
- */
- static void RB_SetModelDepthHack( float depth ) {
- }
- /*
- ===============
- RB_EnterWeaponDepthHack
- ===============
- */
- static void RB_EnterWeaponDepthHack() {
- float matrix[16];
- memcpy( matrix, backEnd.viewDef->projectionMatrix, sizeof( matrix ) );
- const float modelDepthHack = 0.25f;
- matrix[2] *= modelDepthHack;
- matrix[6] *= modelDepthHack;
- matrix[10] *= modelDepthHack;
- matrix[14] *= modelDepthHack;
- qglMatrixMode( GL_PROJECTION );
- qglLoadMatrixf( matrix );
- qglMatrixMode( GL_MODELVIEW );
- }
- /*
- ===============
- RB_EnterModelDepthHack
- ===============
- */
- static void RB_EnterModelDepthHack( float depth ) {
- float matrix[16];
- memcpy( matrix, backEnd.viewDef->projectionMatrix, sizeof( matrix ) );
- matrix[14] -= depth;
- qglMatrixMode( GL_PROJECTION );
- qglLoadMatrixf( matrix );
- qglMatrixMode( GL_MODELVIEW );
- }
- /*
- ===============
- RB_LeaveDepthHack
- ===============
- */
- static void RB_LeaveDepthHack() {
- qglMatrixMode( GL_PROJECTION );
- qglLoadMatrixf( backEnd.viewDef->projectionMatrix );
- qglMatrixMode( GL_MODELVIEW );
- }
- /*
- =============
- RB_LoadMatrixWithBypass
- does a glLoadMatrixf after optionally applying the low-latency bypass matrix
- =============
- */
- static void RB_LoadMatrixWithBypass( const float m[16] ) {
- glLoadMatrixf( m );
- }
- /*
- ====================
- RB_RenderDrawSurfListWithFunction
- The triangle functions can check backEnd.currentSpace != surf->space
- to see if they need to perform any new matrix setup. The modelview
- matrix will already have been loaded, and backEnd.currentSpace will
- be updated after the triangle function completes.
- ====================
- */
- static void RB_RenderDrawSurfListWithFunction( drawSurf_t **drawSurfs, int numDrawSurfs, void (*triFunc_)( const drawSurf_t *) ) {
- backEnd.currentSpace = NULL;
- for ( int i = 0 ; i < numDrawSurfs ; i++ ) {
- const drawSurf_t * drawSurf = drawSurfs[i];
- if ( drawSurf == NULL ) {
- continue;
- }
- assert( drawSurf->space != NULL );
- if ( drawSurf->space != NULL ) { // is it ever NULL? Do we need to check?
- // Set these values ahead of time so we don't have to reconstruct the matrices on the consoles
- if ( drawSurf->space->weaponDepthHack ) {
- RB_SetWeaponDepthHack();
- }
- if ( drawSurf->space->modelDepthHack != 0.0f ) {
- RB_SetModelDepthHack( drawSurf->space->modelDepthHack );
- }
- // change the matrix if needed
- if ( drawSurf->space != backEnd.currentSpace ) {
- RB_LoadMatrixWithBypass( drawSurf->space->modelViewMatrix );
- }
- if ( drawSurf->space->weaponDepthHack ) {
- RB_EnterWeaponDepthHack();
- }
- if ( drawSurf->space->modelDepthHack != 0.0f ) {
- RB_EnterModelDepthHack( drawSurf->space->modelDepthHack );
- }
- }
- // change the scissor if needed
- if ( r_useScissor.GetBool() && !backEnd.currentScissor.Equals( drawSurf->scissorRect ) ) {
- backEnd.currentScissor = drawSurf->scissorRect;
- GL_Scissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1,
- backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
- backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
- backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
- }
- // render it
- triFunc_( drawSurf );
- if ( drawSurf->space != NULL && ( drawSurf->space->weaponDepthHack || drawSurf->space->modelDepthHack != 0.0f ) ) {
- RB_LeaveDepthHack();
- }
- backEnd.currentSpace = drawSurf->space;
- }
- }
- /*
- =================
- RB_ShowSilhouette
- Blacks out all edges, then adds color for each edge that a shadow
- plane extends from, allowing you to see doubled edges
- FIXME: not thread safe!
- =================
- */
- static void RB_ShowSilhouette() {
- int i;
- const drawSurf_t *surf;
- const viewLight_t *vLight;
- if ( !r_showSilhouette.GetBool() ) {
- return;
- }
- //
- // clear all triangle edges to black
- //
- globalImages->BindNull();
- qglDisable( GL_TEXTURE_2D );
- GL_Color( 0, 0, 0 );
- GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_POLYMODE_LINE );
- GL_Cull( CT_TWO_SIDED );
- RB_RenderDrawSurfListWithFunction( backEnd.viewDef->drawSurfs, backEnd.viewDef->numDrawSurfs,
- RB_DrawElementsWithCounters );
- //
- // now blend in edges that cast silhouettes
- //
- RB_SimpleWorldSetup();
- GL_Color( 0.5, 0, 0 );
- GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
- for ( vLight = backEnd.viewDef->viewLights; vLight; vLight = vLight->next ) {
- for ( i = 0; i < 2; i++ ) {
- for ( surf = i ? vLight->localShadows : vLight->globalShadows
- ; surf; surf = (drawSurf_t *)surf->nextOnLight ) {
- RB_SimpleSurfaceSetup( surf );
- const srfTriangles_t * tri = surf->frontEndGeo;
- idVertexBuffer vertexBuffer;
- if ( !vertexCache.GetVertexBuffer( tri->shadowCache, &vertexBuffer ) ) {
- continue;
- }
- qglBindBufferARB( GL_ARRAY_BUFFER_ARB, (GLuint)vertexBuffer.GetAPIObject() );
- int vertOffset = vertexBuffer.GetOffset();
- qglVertexPointer( 3, GL_FLOAT, sizeof( idShadowVert ), (void *)vertOffset );
- qglBegin( GL_LINES );
- for ( int j = 0; j < tri->numIndexes; j+=3 ) {
- int i1 = tri->indexes[j+0];
- int i2 = tri->indexes[j+1];
- int i3 = tri->indexes[j+2];
- if ( (i1 & 1) + (i2 & 1) + (i3 & 1) == 1 ) {
- if ( (i1 & 1) + (i2 & 1) == 0 ) {
- qglArrayElement( i1 );
- qglArrayElement( i2 );
- } else if ( (i1 & 1 ) + (i3 & 1) == 0 ) {
- qglArrayElement( i1 );
- qglArrayElement( i3 );
- }
- }
- }
- qglEnd();
- }
- }
- }
- GL_State( GLS_DEFAULT );
- GL_Color( 1,1,1 );
- GL_Cull( CT_FRONT_SIDED );
- }
- /*
- =====================
- RB_ShowTris
- Debugging tool
- =====================
- */
- static void RB_ShowTris( drawSurf_t **drawSurfs, int numDrawSurfs ) {
- modelTrace_t mt;
- idVec3 end;
- if ( r_showTris.GetInteger() == 0 ) {
- return;
- }
- float color[4] = { 1, 1, 1, 1 };
- GL_PolygonOffset( -1.0f, -2.0f );
-
- switch ( r_showTris.GetInteger() ) {
- case 1: // only draw visible ones
- GL_State( GLS_DEPTHMASK | GLS_ALPHAMASK | GLS_POLYMODE_LINE | GLS_POLYGON_OFFSET );
- break;
- case 2: // draw all front facing
- case 3: // draw all
- GL_State( GLS_DEPTHMASK | GLS_ALPHAMASK | GLS_POLYMODE_LINE | GLS_POLYGON_OFFSET | GLS_DEPTHFUNC_ALWAYS );
- break;
- case 4: // only draw visible ones with blended lines
- GL_State( GLS_DEPTHMASK | GLS_ALPHAMASK | GLS_POLYMODE_LINE | GLS_POLYGON_OFFSET | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
- color[3] = 0.4f;
- break;
- }
- if ( r_showTris.GetInteger() == 3 ) {
- GL_Cull( CT_TWO_SIDED );
- }
- GL_Color( color );
- renderProgManager.BindShader_Color();
- RB_RenderDrawSurfListWithFunction( drawSurfs, numDrawSurfs, RB_DrawElementsWithCounters );
- if ( r_showTris.GetInteger() == 3 ) {
- GL_Cull( CT_FRONT_SIDED );
- }
- }
- /*
- =====================
- RB_ShowSurfaceInfo
- Debugging tool
- =====================
- */
- static void RB_ShowSurfaceInfo( drawSurf_t **drawSurfs, int numDrawSurfs ) {
- modelTrace_t mt;
- idVec3 start, end;
-
- if ( !r_showSurfaceInfo.GetBool() ) {
- return;
- }
- // start far enough away that we don't hit the player model
- start = tr.primaryView->renderView.vieworg + tr.primaryView->renderView.viewaxis[0] * 16;
- end = start + tr.primaryView->renderView.viewaxis[0] * 1000.0f;
- if ( !tr.primaryWorld->Trace( mt, start, end, 0.0f, false ) ) {
- return;
- }
- globalImages->BindNull();
- qglDisable( GL_TEXTURE_2D );
- GL_Color( 1, 1, 1 );
- static float scale = -1;
- static float bias = -2;
- GL_PolygonOffset( scale, bias );
- GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_POLYMODE_LINE | GLS_POLYGON_OFFSET );
- idVec3 trans[3];
- float matrix[16];
- // transform the object verts into global space
- R_AxisToModelMatrix( mt.entity->axis, mt.entity->origin, matrix );
- tr.primaryWorld->DrawText( mt.entity->hModel->Name(), mt.point + tr.primaryView->renderView.viewaxis[2] * 12,
- 0.35f, colorRed, tr.primaryView->renderView.viewaxis );
- tr.primaryWorld->DrawText( mt.material->GetName(), mt.point,
- 0.35f, colorBlue, tr.primaryView->renderView.viewaxis );
- }
- /*
- =====================
- RB_ShowViewEntitys
- Debugging tool
- =====================
- */
- static void RB_ShowViewEntitys( viewEntity_t *vModels ) {
- if ( !r_showViewEntitys.GetBool() ) {
- return;
- }
- if ( r_showViewEntitys.GetInteger() >= 2 ) {
- common->Printf( "view entities: " );
- for ( const viewEntity_t * vModel = vModels; vModel; vModel = vModel->next ) {
- if ( vModel->entityDef->IsDirectlyVisible() ) {
- common->Printf( "<%i> ", vModel->entityDef->index );
- } else {
- common->Printf( "%i ", vModel->entityDef->index );
- }
- }
- common->Printf( "\n" );
- }
- globalImages->BindNull();
- renderProgManager.BindShader_Color();
- GL_Color( 1, 1, 1 );
- GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_POLYMODE_LINE );
- GL_Cull( CT_TWO_SIDED );
- for ( const viewEntity_t * vModel = vModels; vModel; vModel = vModel->next ) {
- idBounds b;
- qglLoadMatrixf( vModel->modelViewMatrix );
- const idRenderEntityLocal * edef = vModel->entityDef;
- if ( !edef ) {
- continue;
- }
- // draw the model bounds in white if directly visible,
- // or, blue if it is only-for-sahdow
- idVec4 color;
- if ( edef->IsDirectlyVisible() ) {
- color.Set( 1, 1, 1, 1 );
- } else {
- color.Set( 0, 0, 1, 1 );
- }
- GL_Color( color[0], color[1], color[2] );
- RB_DrawBounds( edef->localReferenceBounds );
- // transform the upper bounds corner into global space
- if ( r_showViewEntitys.GetInteger() >= 2 ) {
- idVec3 corner;
- R_LocalPointToGlobal( vModel->modelMatrix, edef->localReferenceBounds[1], corner );
- tr.primaryWorld->DrawText(
- va( "%i:%s", edef->index, edef->parms.hModel->Name() ),
- corner,
- 0.25f, color,
- tr.primaryView->renderView.viewaxis );
- }
- // draw the actual bounds in yellow if different
- if ( r_showViewEntitys.GetInteger() >= 3 ) {
- GL_Color( 1, 1, 0 );
- // FIXME: cannot instantiate a dynamic model from the renderer back-end
- idRenderModel *model = R_EntityDefDynamicModel( vModel->entityDef );
- if ( !model ) {
- continue; // particles won't instantiate without a current view
- }
- b = model->Bounds( &vModel->entityDef->parms );
- if ( b != vModel->entityDef->localReferenceBounds ) {
- RB_DrawBounds( b );
- }
- }
- }
- }
- /*
- =====================
- RB_ShowTexturePolarity
- Shade triangle red if they have a positive texture area
- green if they have a negative texture area, or blue if degenerate area
- =====================
- */
- static void RB_ShowTexturePolarity( drawSurf_t **drawSurfs, int numDrawSurfs ) {
- int i, j;
- drawSurf_t *drawSurf;
- const srfTriangles_t *tri;
- if ( !r_showTexturePolarity.GetBool() ) {
- return;
- }
- globalImages->BindNull();
- GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
- GL_Color( 1, 1, 1 );
- for ( i = 0; i < numDrawSurfs; i++ ) {
- drawSurf = drawSurfs[i];
- tri = drawSurf->frontEndGeo;
- if ( !tri->verts ) {
- continue;
- }
- RB_SimpleSurfaceSetup( drawSurf );
- qglBegin( GL_TRIANGLES );
- for ( j = 0; j < tri->numIndexes; j+=3 ) {
- idDrawVert *a, *b, *c;
- float d0[5], d1[5];
- float area;
- a = tri->verts + tri->indexes[j];
- b = tri->verts + tri->indexes[j+1];
- c = tri->verts + tri->indexes[j+2];
- const idVec2 aST = a->GetTexCoord();
- const idVec2 bST = b->GetTexCoord();
- const idVec2 cST = c->GetTexCoord();
- d0[3] = bST[0] - aST[0];
- d0[4] = bST[1] - aST[1];
- d1[3] = cST[0] - aST[0];
- d1[4] = cST[1] - aST[1];
- area = d0[3] * d1[4] - d0[4] * d1[3];
- if ( idMath::Fabs( area ) < 0.0001 ) {
- GL_Color( 0, 0, 1, 0.5 );
- } else if ( area < 0 ) {
- GL_Color( 1, 0, 0, 0.5 );
- } else {
- GL_Color( 0, 1, 0, 0.5 );
- }
- qglVertex3fv( a->xyz.ToFloatPtr() );
- qglVertex3fv( b->xyz.ToFloatPtr() );
- qglVertex3fv( c->xyz.ToFloatPtr() );
- }
- qglEnd();
- }
- GL_State( GLS_DEFAULT );
- }
- /*
- =====================
- RB_ShowUnsmoothedTangents
- Shade materials that are using unsmoothed tangents
- =====================
- */
- static void RB_ShowUnsmoothedTangents( drawSurf_t **drawSurfs, int numDrawSurfs ) {
- int i, j;
- drawSurf_t *drawSurf;
- const srfTriangles_t *tri;
- if ( !r_showUnsmoothedTangents.GetBool() ) {
- return;
- }
- globalImages->BindNull();
- GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
- GL_Color( 0, 1, 0, 0.5 );
- for ( i = 0; i < numDrawSurfs; i++ ) {
- drawSurf = drawSurfs[i];
- if ( !drawSurf->material->UseUnsmoothedTangents() ) {
- continue;
- }
- RB_SimpleSurfaceSetup( drawSurf );
- tri = drawSurf->frontEndGeo;
- qglBegin( GL_TRIANGLES );
- for ( j = 0; j < tri->numIndexes; j+=3 ) {
- idDrawVert *a, *b, *c;
- a = tri->verts + tri->indexes[j];
- b = tri->verts + tri->indexes[j+1];
- c = tri->verts + tri->indexes[j+2];
- qglVertex3fv( a->xyz.ToFloatPtr() );
- qglVertex3fv( b->xyz.ToFloatPtr() );
- qglVertex3fv( c->xyz.ToFloatPtr() );
- }
- qglEnd();
- }
- GL_State( GLS_DEFAULT );
- }
- /*
- =====================
- RB_ShowTangentSpace
- Shade a triangle by the RGB colors of its tangent space
- 1 = tangents[0]
- 2 = tangents[1]
- 3 = normal
- =====================
- */
- static void RB_ShowTangentSpace( drawSurf_t **drawSurfs, int numDrawSurfs ) {
- int i, j;
- drawSurf_t *drawSurf;
- const srfTriangles_t *tri;
- if ( !r_showTangentSpace.GetInteger() ) {
- return;
- }
- globalImages->BindNull();
- GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
- for ( i = 0; i < numDrawSurfs; i++ ) {
- drawSurf = drawSurfs[i];
- RB_SimpleSurfaceSetup( drawSurf );
- tri = drawSurf->frontEndGeo;
- if ( !tri->verts ) {
- continue;
- }
- qglBegin( GL_TRIANGLES );
- for ( j = 0; j < tri->numIndexes; j++ ) {
- const idDrawVert *v;
- v = &tri->verts[tri->indexes[j]];
- if ( r_showTangentSpace.GetInteger() == 1 ) {
- const idVec3 vertexTangent = v->GetTangent();
- GL_Color( 0.5 + 0.5 * vertexTangent[0], 0.5 + 0.5 * vertexTangent[1],
- 0.5 + 0.5 * vertexTangent[2], 0.5 );
- } else if ( r_showTangentSpace.GetInteger() == 2 ) {
- const idVec3 vertexBiTangent = v->GetBiTangent();
- GL_Color( 0.5 + 0.5 *vertexBiTangent[0], 0.5 + 0.5 * vertexBiTangent[1],
- 0.5 + 0.5 * vertexBiTangent[2], 0.5 );
- } else {
- const idVec3 vertexNormal = v->GetNormal();
- GL_Color( 0.5 + 0.5 * vertexNormal[0], 0.5 + 0.5 * vertexNormal[1],
- 0.5 + 0.5 * vertexNormal[2], 0.5 );
- }
- qglVertex3fv( v->xyz.ToFloatPtr() );
- }
- qglEnd();
- }
- GL_State( GLS_DEFAULT );
- }
- /*
- =====================
- RB_ShowVertexColor
- Draw each triangle with the solid vertex colors
- =====================
- */
- static void RB_ShowVertexColor( drawSurf_t **drawSurfs, int numDrawSurfs ) {
- int i, j;
- drawSurf_t *drawSurf;
- const srfTriangles_t *tri;
- if ( !r_showVertexColor.GetBool() ) {
- return;
- }
- globalImages->BindNull();
- GL_State( GLS_DEPTHFUNC_LESS );
- for ( i = 0; i < numDrawSurfs; i++ ) {
- drawSurf = drawSurfs[i];
- RB_SimpleSurfaceSetup( drawSurf );
- tri = drawSurf->frontEndGeo;
- if ( !tri->verts ) {
- continue;
- }
- qglBegin( GL_TRIANGLES );
- for ( j = 0; j < tri->numIndexes; j++ ) {
- const idDrawVert *v;
- v = &tri->verts[tri->indexes[j]];
- qglColor4ubv( v->color );
- qglVertex3fv( v->xyz.ToFloatPtr() );
- }
- qglEnd();
- }
- GL_State( GLS_DEFAULT );
- }
- /*
- =====================
- RB_ShowNormals
- Debugging tool
- =====================
- */
- static void RB_ShowNormals( drawSurf_t **drawSurfs, int numDrawSurfs ) {
- int i, j;
- drawSurf_t *drawSurf;
- idVec3 end;
- const srfTriangles_t *tri;
- float size;
- bool showNumbers;
- idVec3 pos;
- if ( r_showNormals.GetFloat() == 0.0f ) {
- return;
- }
- globalImages->BindNull();
- if ( !r_debugLineDepthTest.GetBool() ) {
- GL_State( GLS_POLYMODE_LINE | GLS_DEPTHFUNC_ALWAYS );
- } else {
- GL_State( GLS_POLYMODE_LINE );
- }
- size = r_showNormals.GetFloat();
- if ( size < 0.0f ) {
- size = -size;
- showNumbers = true;
- } else {
- showNumbers = false;
- }
- for ( i = 0; i < numDrawSurfs; i++ ) {
- drawSurf = drawSurfs[i];
- RB_SimpleSurfaceSetup( drawSurf );
- tri = drawSurf->frontEndGeo;
- if ( !tri->verts ) {
- continue;
- }
- qglBegin( GL_LINES );
- for ( j = 0; j < tri->numVerts; j++ ) {
- const idVec3 normal = tri->verts[j].GetNormal();
- const idVec3 tangent = tri->verts[j].GetTangent();
- const idVec3 bitangent = tri->verts[j].GetBiTangent();
- GL_Color( 0, 0, 1 );
- qglVertex3fv( tri->verts[j].xyz.ToFloatPtr() );
- VectorMA( tri->verts[j].xyz, size, normal, end );
- qglVertex3fv( end.ToFloatPtr() );
- GL_Color( 1, 0, 0 );
- qglVertex3fv( tri->verts[j].xyz.ToFloatPtr() );
- VectorMA( tri->verts[j].xyz, size, tangent, end );
- qglVertex3fv( end.ToFloatPtr() );
- GL_Color( 0, 1, 0 );
- qglVertex3fv( tri->verts[j].xyz.ToFloatPtr() );
- VectorMA( tri->verts[j].xyz, size, bitangent, end );
- qglVertex3fv( end.ToFloatPtr() );
- }
- qglEnd();
- }
- if ( showNumbers ) {
- RB_SimpleWorldSetup();
- for ( i = 0; i < numDrawSurfs; i++ ) {
- drawSurf = drawSurfs[i];
- tri = drawSurf->frontEndGeo;
- if ( !tri->verts ) {
- continue;
- }
-
- for ( j = 0; j < tri->numVerts; j++ ) {
- const idVec3 normal = tri->verts[j].GetNormal();
- const idVec3 tangent = tri->verts[j].GetTangent();
- R_LocalPointToGlobal( drawSurf->space->modelMatrix, tri->verts[j].xyz + tangent + normal * 0.2f, pos );
- RB_DrawText( va( "%d", j ), pos, 0.01f, colorWhite, backEnd.viewDef->renderView.viewaxis, 1 );
- }
- for ( j = 0; j < tri->numIndexes; j += 3 ) {
- const idVec3 normal = tri->verts[ tri->indexes[ j + 0 ] ].GetNormal();
- R_LocalPointToGlobal( drawSurf->space->modelMatrix, ( tri->verts[ tri->indexes[ j + 0 ] ].xyz + tri->verts[ tri->indexes[ j + 1 ] ].xyz + tri->verts[ tri->indexes[ j + 2 ] ].xyz ) * ( 1.0f / 3.0f ) + normal * 0.2f, pos );
- RB_DrawText( va( "%d", j / 3 ), pos, 0.01f, colorCyan, backEnd.viewDef->renderView.viewaxis, 1 );
- }
- }
- }
- }
- #if 0 // compiler warning
- /*
- =====================
- RB_ShowNormals
- Debugging tool
- =====================
- */
- static void RB_AltShowNormals( drawSurf_t **drawSurfs, int numDrawSurfs ) {
- if ( r_showNormals.GetFloat() == 0.0f ) {
- return;
- }
- globalImages->BindNull();
- GL_State( GLS_DEPTHFUNC_ALWAYS );
- for ( int i = 0; i < numDrawSurfs; i++ ) {
- drawSurf_t * drawSurf = drawSurfs[i];
- RB_SimpleSurfaceSetup( drawSurf );
- const srfTriangles_t * tri = drawSurf->geo;
- qglBegin( GL_LINES );
- for ( int j = 0; j < tri->numIndexes; j += 3 ) {
- const idDrawVert *v[3] = {
- &tri->verts[tri->indexes[j+0]],
- &tri->verts[tri->indexes[j+1]],
- &tri->verts[tri->indexes[j+2]]
- }
- const idPlane plane( v[0]->xyz, v[1]->xyz, v[2]->xyz );
- // make the midpoint slightly above the triangle
- const idVec3 mid = ( v[0]->xyz + v[1]->xyz + v[2]->xyz ) * ( 1.0f / 3.0f ) + 0.1f * plane.Normal();
- for ( int k = 0; k < 3; k++ ) {
- const idVec3 pos = ( mid + v[k]->xyz * 3.0f ) * 0.25f;
- idVec3 end;
- GL_Color( 0, 0, 1 );
- qglVertex3fv( pos.ToFloatPtr() );
- VectorMA( pos, r_showNormals.GetFloat(), v[k]->normal, end );
- qglVertex3fv( end.ToFloatPtr() );
- GL_Color( 1, 0, 0 );
- qglVertex3fv( pos.ToFloatPtr() );
- VectorMA( pos, r_showNormals.GetFloat(), v[k]->tangents[0], end );
- qglVertex3fv( end.ToFloatPtr() );
- GL_Color( 0, 1, 0 );
- qglVertex3fv( pos.ToFloatPtr() );
- VectorMA( pos, r_showNormals.GetFloat(), v[k]->tangents[1], end );
- qglVertex3fv( end.ToFloatPtr() );
- GL_Color( 1, 1, 1 );
- qglVertex3fv( pos.ToFloatPtr() );
- qglVertex3fv( v[k]->xyz.ToFloatPtr() );
- }
- }
- qglEnd();
- }
- }
- #endif
- /*
- =====================
- RB_ShowTextureVectors
- Draw texture vectors in the center of each triangle
- =====================
- */
- static void RB_ShowTextureVectors( drawSurf_t **drawSurfs, int numDrawSurfs ) {
- if ( r_showTextureVectors.GetFloat() == 0.0f ) {
- return;
- }
- GL_State( GLS_DEPTHFUNC_LESS );
- globalImages->BindNull();
- for ( int i = 0; i < numDrawSurfs; i++ ) {
- drawSurf_t * drawSurf = drawSurfs[i];
- const srfTriangles_t * tri = drawSurf->frontEndGeo;
- if ( tri->verts == NULL ) {
- continue;
- }
- RB_SimpleSurfaceSetup( drawSurf );
- // draw non-shared edges in yellow
- qglBegin( GL_LINES );
- for ( int j = 0; j < tri->numIndexes; j+= 3 ) {
- float d0[5], d1[5];
- idVec3 temp;
- idVec3 tangents[2];
- const idDrawVert *a = &tri->verts[tri->indexes[j+0]];
- const idDrawVert *b = &tri->verts[tri->indexes[j+1]];
- const idDrawVert *c = &tri->verts[tri->indexes[j+2]];
- const idPlane plane( a->xyz, b->xyz, c->xyz );
- // make the midpoint slightly above the triangle
- const idVec3 mid = ( a->xyz + b->xyz + c->xyz ) * ( 1.0f / 3.0f ) + 0.1f * plane.Normal();
- // calculate the texture vectors
- const idVec2 aST = a->GetTexCoord();
- const idVec2 bST = b->GetTexCoord();
- const idVec2 cST = c->GetTexCoord();
- d0[0] = b->xyz[0] - a->xyz[0];
- d0[1] = b->xyz[1] - a->xyz[1];
- d0[2] = b->xyz[2] - a->xyz[2];
- d0[3] = bST[0] - aST[0];
- d0[4] = bST[1] - aST[1];
- d1[0] = c->xyz[0] - a->xyz[0];
- d1[1] = c->xyz[1] - a->xyz[1];
- d1[2] = c->xyz[2] - a->xyz[2];
- d1[3] = cST[0] - aST[0];
- d1[4] = cST[1] - aST[1];
- const float area = d0[3] * d1[4] - d0[4] * d1[3];
- if ( area == 0 ) {
- continue;
- }
- const float inva = 1.0f / area;
- temp[0] = (d0[0] * d1[4] - d0[4] * d1[0]) * inva;
- temp[1] = (d0[1] * d1[4] - d0[4] * d1[1]) * inva;
- temp[2] = (d0[2] * d1[4] - d0[4] * d1[2]) * inva;
- temp.Normalize();
- tangents[0] = temp;
-
- temp[0] = (d0[3] * d1[0] - d0[0] * d1[3]) * inva;
- temp[1] = (d0[3] * d1[1] - d0[1] * d1[3]) * inva;
- temp[2] = (d0[3] * d1[2] - d0[2] * d1[3]) * inva;
- temp.Normalize();
- tangents[1] = temp;
- // draw the tangents
- tangents[0] = mid + tangents[0] * r_showTextureVectors.GetFloat();
- tangents[1] = mid + tangents[1] * r_showTextureVectors.GetFloat();
- GL_Color( 1, 0, 0 );
- qglVertex3fv( mid.ToFloatPtr() );
- qglVertex3fv( tangents[0].ToFloatPtr() );
- GL_Color( 0, 1, 0 );
- qglVertex3fv( mid.ToFloatPtr() );
- qglVertex3fv( tangents[1].ToFloatPtr() );
- }
- qglEnd();
- }
- }
- /*
- =====================
- RB_ShowDominantTris
- Draw lines from each vertex to the dominant triangle center
- =====================
- */
- static void RB_ShowDominantTris( drawSurf_t **drawSurfs, int numDrawSurfs ) {
- int i, j;
- drawSurf_t *drawSurf;
- const srfTriangles_t *tri;
- if ( !r_showDominantTri.GetBool() ) {
- return;
- }
- GL_State( GLS_DEPTHFUNC_LESS );
- GL_PolygonOffset( -1, -2 );
- qglEnable( GL_POLYGON_OFFSET_LINE );
- globalImages->BindNull();
- for ( i = 0; i < numDrawSurfs; i++ ) {
- drawSurf = drawSurfs[i];
- tri = drawSurf->frontEndGeo;
- if ( !tri->verts ) {
- continue;
- }
- if ( !tri->dominantTris ) {
- continue;
- }
- RB_SimpleSurfaceSetup( drawSurf );
- GL_Color( 1, 1, 0 );
- qglBegin( GL_LINES );
- for ( j = 0; j < tri->numVerts; j++ ) {
- const idDrawVert *a, *b, *c;
- idVec3 mid;
- // find the midpoint of the dominant tri
- a = &tri->verts[j];
- b = &tri->verts[tri->dominantTris[j].v2];
- c = &tri->verts[tri->dominantTris[j].v3];
- mid = ( a->xyz + b->xyz + c->xyz ) * ( 1.0f / 3.0f );
- qglVertex3fv( mid.ToFloatPtr() );
- qglVertex3fv( a->xyz.ToFloatPtr() );
- }
- qglEnd();
- }
- qglDisable( GL_POLYGON_OFFSET_LINE );
- }
- /*
- =====================
- RB_ShowEdges
- Debugging tool
- =====================
- */
- static void RB_ShowEdges( drawSurf_t **drawSurfs, int numDrawSurfs ) {
- int i, j, k, m, n, o;
- drawSurf_t *drawSurf;
- const srfTriangles_t *tri;
- const silEdge_t *edge;
- int danglePlane;
- if ( !r_showEdges.GetBool() ) {
- return;
- }
- globalImages->BindNull();
- GL_State( GLS_DEPTHFUNC_ALWAYS );
- for ( i = 0; i < numDrawSurfs; i++ ) {
- drawSurf = drawSurfs[i];
- tri = drawSurf->frontEndGeo;
- idDrawVert *ac = (idDrawVert *)tri->verts;
- if ( !ac ) {
- continue;
- }
- RB_SimpleSurfaceSetup( drawSurf );
- // draw non-shared edges in yellow
- GL_Color( 1, 1, 0 );
- qglBegin( GL_LINES );
- for ( j = 0; j < tri->numIndexes; j+= 3 ) {
- for ( k = 0; k < 3; k++ ) {
- int l, i1, i2;
- l = ( k == 2 ) ? 0 : k + 1;
- i1 = tri->indexes[j+k];
- i2 = tri->indexes[j+l];
- // if these are used backwards, the edge is shared
- for ( m = 0; m < tri->numIndexes; m += 3 ) {
- for ( n = 0; n < 3; n++ ) {
- o = ( n == 2 ) ? 0 : n + 1;
- if ( tri->indexes[m+n] == i2 && tri->indexes[m+o] == i1 ) {
- break;
- }
- }
- if ( n != 3 ) {
- break;
- }
- }
- // if we didn't find a backwards listing, draw it in yellow
- if ( m == tri->numIndexes ) {
- qglVertex3fv( ac[ i1 ].xyz.ToFloatPtr() );
- qglVertex3fv( ac[ i2 ].xyz.ToFloatPtr() );
- }
- }
- }
- qglEnd();
- // draw dangling sil edges in red
- if ( !tri->silEdges ) {
- continue;
- }
- // the plane number after all real planes
- // is the dangling edge
- danglePlane = tri->numIndexes / 3;
- GL_Color( 1, 0, 0 );
- qglBegin( GL_LINES );
- for ( j = 0; j < tri->numSilEdges; j++ ) {
- edge = tri->silEdges + j;
- if ( edge->p1 != danglePlane && edge->p2 != danglePlane ) {
- continue;
- }
- qglVertex3fv( ac[ edge->v1 ].xyz.ToFloatPtr() );
- qglVertex3fv( ac[ edge->v2 ].xyz.ToFloatPtr() );
- }
- qglEnd();
- }
- }
- /*
- ==============
- RB_ShowLights
- Visualize all light volumes used in the current scene
- r_showLights 1 : just print volumes numbers, highlighting ones covering the view
- r_showLights 2 : also draw planes of each volume
- r_showLights 3 : also draw edges of each volume
- ==============
- */
- static void RB_ShowLights() {
- if ( !r_showLights.GetInteger() ) {
- return;
- }
- GL_State( GLS_DEFAULT );
- // we use the 'vLight->invProjectMVPMatrix'
- qglMatrixMode( GL_PROJECTION );
- qglLoadIdentity();
- globalImages->BindNull();
- renderProgManager.BindShader_Color();
- GL_Cull( CT_TWO_SIDED );
- common->Printf( "volumes: " ); // FIXME: not in back end!
- int count = 0;
- for ( viewLight_t * vLight = backEnd.viewDef->viewLights; vLight != NULL; vLight = vLight->next ) {
- count++;
- // depth buffered planes
- if ( r_showLights.GetInteger() >= 2 ) {
- GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHMASK );
- GL_Color( 0.0f, 0.0f, 1.0f, 0.25f );
- idRenderMatrix invProjectMVPMatrix;
- idRenderMatrix::Multiply( backEnd.viewDef->worldSpace.mvp, vLight->inverseBaseLightProject, invProjectMVPMatrix );
- RB_SetMVP( invProjectMVPMatrix );
- RB_DrawElementsWithCounters( &backEnd.zeroOneCubeSurface );
- }
- // non-hidden lines
- if ( r_showLights.GetInteger() >= 3 ) {
- GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_POLYMODE_LINE | GLS_DEPTHMASK );
- GL_Color( 1.0f, 1.0f, 1.0f );
- idRenderMatrix invProjectMVPMatrix;
- idRenderMatrix::Multiply( backEnd.viewDef->worldSpace.mvp, vLight->inverseBaseLightProject, invProjectMVPMatrix );
- RB_SetMVP( invProjectMVPMatrix );
- RB_DrawElementsWithCounters( &backEnd.zeroOneCubeSurface );
- }
- common->Printf( "%i ", vLight->lightDef->index );
- }
- common->Printf( " = %i total\n", count );
- // set back the default projection matrix
- qglMatrixMode( GL_PROJECTION );
- qglLoadMatrixf( backEnd.viewDef->projectionMatrix );
- qglMatrixMode( GL_MODELVIEW );
- qglLoadIdentity();
- }
- /*
- =====================
- RB_ShowPortals
- Debugging tool, won't work correctly with SMP or when mirrors are present
- =====================
- */
- static void RB_ShowPortals() {
- if ( !r_showPortals.GetBool() ) {
- return;
- }
- // all portals are expressed in world coordinates
- RB_SimpleWorldSetup();
- globalImages->BindNull();
- renderProgManager.BindShader_Color();
- GL_State( GLS_DEPTHFUNC_ALWAYS );
- ((idRenderWorldLocal *)backEnd.viewDef->renderWorld)->ShowPortals();
- }
- /*
- ================
- RB_ClearDebugText
- ================
- */
- void RB_ClearDebugText( int time ) {
- int i;
- int num;
- debugText_t *text;
- rb_debugTextTime = time;
- if ( !time ) {
- // free up our strings
- text = rb_debugText;
- for ( i = 0; i < MAX_DEBUG_TEXT; i++, text++ ) {
- text->text.Clear();
- }
- rb_numDebugText = 0;
- return;
- }
- // copy any text that still needs to be drawn
- num = 0;
- text = rb_debugText;
- for ( i = 0; i < rb_numDebugText; i++, text++ ) {
- if ( text->lifeTime > time ) {
- if ( num != i ) {
- rb_debugText[ num ] = *text;
- }
- num++;
- }
- }
- rb_numDebugText = num;
- }
- /*
- ================
- RB_AddDebugText
- ================
- */
- void RB_AddDebugText( const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align, const int lifetime, const bool depthTest ) {
- debugText_t *debugText;
- if ( rb_numDebugText < MAX_DEBUG_TEXT ) {
- debugText = &rb_debugText[ rb_numDebugText++ ];
- debugText->text = text;
- debugText->origin = origin;
- debugText->scale = scale;
- debugText->color = color;
- debugText->viewAxis = viewAxis;
- debugText->align = align;
- debugText->lifeTime = rb_debugTextTime + lifetime;
- debugText->depthTest = depthTest;
- }
- }
- /*
- ================
- RB_DrawTextLength
- returns the length of the given text
- ================
- */
- float RB_DrawTextLength( const char *text, float scale, int len ) {
- int i, num, index, charIndex;
- float spacing, textLen = 0.0f;
- if ( text && *text ) {
- if ( !len ) {
- len = strlen(text);
- }
- for ( i = 0; i < len; i++ ) {
- charIndex = text[i] - 32;
- if ( charIndex < 0 || charIndex > NUM_SIMPLEX_CHARS ) {
- continue;
- }
- num = simplex[charIndex][0] * 2;
- spacing = simplex[charIndex][1];
- index = 2;
- while( index - 2 < num ) {
- if ( simplex[charIndex][index] < 0) {
- index++;
- continue;
- }
- index += 2;
- if ( simplex[charIndex][index] < 0) {
- index++;
- continue;
- }
- }
- textLen += spacing * scale;
- }
- }
- return textLen;
- }
- /*
- ================
- RB_DrawText
- oriented on the viewaxis
- align can be 0-left, 1-center (default), 2-right
- ================
- */
- static void RB_DrawText( const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align ) {
- renderProgManager.BindShader_Color();
- int i, j, len, num, index, charIndex, line;
- float textLen = 1.0f, spacing = 1.0f;
- idVec3 org, p1, p2;
- if ( text && *text ) {
- qglBegin( GL_LINES );
- qglColor3fv( color.ToFloatPtr() );
- if ( text[0] == '\n' ) {
- line = 1;
- } else {
- line = 0;
- }
- len = strlen( text );
- for ( i = 0; i < len; i++ ) {
- if ( i == 0 || text[i] == '\n' ) {
- org = origin - viewAxis[2] * ( line * 36.0f * scale );
- if ( align != 0 ) {
- for ( j = 1; i+j <= len; j++ ) {
- if ( i+j == len || text[i+j] == '\n' ) {
- textLen = RB_DrawTextLength( text+i, scale, j );
- break;
- }
- }
- if ( align == 2 ) {
- // right
- org += viewAxis[1] * textLen;
- } else {
- // center
- org += viewAxis[1] * ( textLen * 0.5f );
- }
- }
- line++;
- }
- charIndex = text[i] - 32;
- if ( charIndex < 0 || charIndex > NUM_SIMPLEX_CHARS ) {
- continue;
- }
- num = simplex[charIndex][0] * 2;
- spacing = simplex[charIndex][1];
- index = 2;
- while( index - 2 < num ) {
- if ( simplex[charIndex][index] < 0) {
- index++;
- continue;
- }
- p1 = org + scale * simplex[charIndex][index] * -viewAxis[1] + scale * simplex[charIndex][index+1] * viewAxis[2];
- index += 2;
- if ( simplex[charIndex][index] < 0) {
- index++;
- continue;
- }
- p2 = org + scale * simplex[charIndex][index] * -viewAxis[1] + scale * simplex[charIndex][index+1] * viewAxis[2];
- qglVertex3fv( p1.ToFloatPtr() );
- qglVertex3fv( p2.ToFloatPtr() );
- }
- org -= viewAxis[1] * ( spacing * scale );
- }
- qglEnd();
- }
- }
- /*
- ================
- RB_ShowDebugText
- ================
- */
- void RB_ShowDebugText() {
- int i;
- int width;
- debugText_t *text;
- if ( !rb_numDebugText ) {
- return;
- }
- // all lines are expressed in world coordinates
- RB_SimpleWorldSetup();
- globalImages->BindNull();
- width = r_debugLineWidth.GetInteger();
- if ( width < 1 ) {
- width = 1;
- } else if ( width > 10 ) {
- width = 10;
- }
- // draw lines
- qglLineWidth( width );
- if ( !r_debugLineDepthTest.GetBool() ) {
- GL_State( GLS_POLYMODE_LINE | GLS_DEPTHFUNC_ALWAYS );
- } else {
- GL_State( GLS_POLYMODE_LINE );
- }
- text = rb_debugText;
- for ( i = 0; i < rb_numDebugText; i++, text++ ) {
- if ( !text->depthTest ) {
- RB_DrawText( text->text, text->origin, text->scale, text->color, text->viewAxis, text->align );
- }
- }
- if ( !r_debugLineDepthTest.GetBool() ) {
- GL_State( GLS_POLYMODE_LINE );
- }
- text = rb_debugText;
- for ( i = 0; i < rb_numDebugText; i++, text++ ) {
- if ( text->depthTest ) {
- RB_DrawText( text->text, text->origin, text->scale, text->color, text->viewAxis, text->align );
- }
- }
- qglLineWidth( 1 );
- }
- /*
- ================
- RB_ClearDebugLines
- ================
- */
- void RB_ClearDebugLines( int time ) {
- int i;
- int num;
- debugLine_t *line;
- rb_debugLineTime = time;
- if ( !time ) {
- rb_numDebugLines = 0;
- return;
- }
- // copy any lines that still need to be drawn
- num = 0;
- line = rb_debugLines;
- for ( i = 0; i < rb_numDebugLines; i++, line++ ) {
- if ( line->lifeTime > time ) {
- if ( num != i ) {
- rb_debugLines[ num ] = *line;
- }
- num++;
- }
- }
- rb_numDebugLines = num;
- }
- /*
- ================
- RB_AddDebugLine
- ================
- */
- void RB_AddDebugLine( const idVec4 &color, const idVec3 &start, const idVec3 &end, const int lifeTime, const bool depthTest ) {
- debugLine_t *line;
- if ( rb_numDebugLines < MAX_DEBUG_LINES ) {
- line = &rb_debugLines[ rb_numDebugLines++ ];
- line->rgb = color;
- line->start = start;
- line->end = end;
- line->depthTest = depthTest;
- line->lifeTime = rb_debugLineTime + lifeTime;
- }
- }
- /*
- ================
- RB_ShowDebugLines
- ================
- */
- void RB_ShowDebugLines() {
- int i;
- int width;
- debugLine_t *line;
- if ( !rb_numDebugLines ) {
- return;
- }
- // all lines are expressed in world coordinates
- RB_SimpleWorldSetup();
- globalImages->BindNull();
- width = r_debugLineWidth.GetInteger();
- if ( width < 1 ) {
- width = 1;
- } else if ( width > 10 ) {
- width = 10;
- }
- // draw lines
- qglLineWidth( width );
- if ( !r_debugLineDepthTest.GetBool() ) {
- GL_State( GLS_POLYMODE_LINE | GLS_DEPTHFUNC_ALWAYS );
- } else {
- GL_State( GLS_POLYMODE_LINE );
- }
- qglBegin( GL_LINES );
- line = rb_debugLines;
- for ( i = 0; i < rb_numDebugLines; i++, line++ ) {
- if ( !line->depthTest ) {
- qglColor3fv( line->rgb.ToFloatPtr() );
- qglVertex3fv( line->start.ToFloatPtr() );
- qglVertex3fv( line->end.ToFloatPtr() );
- }
- }
- qglEnd();
- if ( !r_debugLineDepthTest.GetBool() ) {
- GL_State( GLS_POLYMODE_LINE );
- }
- qglBegin( GL_LINES );
- line = rb_debugLines;
- for ( i = 0; i < rb_numDebugLines; i++, line++ ) {
- if ( line->depthTest ) {
- qglColor4fv( line->rgb.ToFloatPtr() );
- qglVertex3fv( line->start.ToFloatPtr() );
- qglVertex3fv( line->end.ToFloatPtr() );
- }
- }
- qglEnd();
- qglLineWidth( 1 );
- GL_State( GLS_DEFAULT );
- }
- /*
- ================
- RB_ClearDebugPolygons
- ================
- */
- void RB_ClearDebugPolygons( int time ) {
- int i;
- int num;
- debugPolygon_t *poly;
- rb_debugPolygonTime = time;
- if ( !time ) {
- rb_numDebugPolygons = 0;
- return;
- }
- // copy any polygons that still need to be drawn
- num = 0;
- poly = rb_debugPolygons;
- for ( i = 0; i < rb_numDebugPolygons; i++, poly++ ) {
- if ( poly->lifeTime > time ) {
- if ( num != i ) {
- rb_debugPolygons[ num ] = *poly;
- }
- num++;
- }
- }
- rb_numDebugPolygons = num;
- }
- /*
- ================
- RB_AddDebugPolygon
- ================
- */
- void RB_AddDebugPolygon( const idVec4 &color, const idWinding &winding, const int lifeTime, const bool depthTest ) {
- debugPolygon_t *poly;
- if ( rb_numDebugPolygons < MAX_DEBUG_POLYGONS ) {
- poly = &rb_debugPolygons[ rb_numDebugPolygons++ ];
- poly->rgb = color;
- poly->winding = winding;
- poly->depthTest = depthTest;
- poly->lifeTime = rb_debugPolygonTime + lifeTime;
- }
- }
- /*
- ================
- RB_ShowDebugPolygons
- ================
- */
- void RB_ShowDebugPolygons() {
- int i, j;
- debugPolygon_t *poly;
- if ( !rb_numDebugPolygons ) {
- return;
- }
- // all lines are expressed in world coordinates
- RB_SimpleWorldSetup();
- globalImages->BindNull();
- qglDisable( GL_TEXTURE_2D );
- if ( r_debugPolygonFilled.GetBool() ) {
- GL_State( GLS_POLYGON_OFFSET | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHMASK );
- GL_PolygonOffset( -1, -2 );
- } else {
- GL_State( GLS_POLYGON_OFFSET | GLS_POLYMODE_LINE );
- GL_PolygonOffset( -1, -2 );
- }
- poly = rb_debugPolygons;
- for ( i = 0; i < rb_numDebugPolygons; i++, poly++ ) {
- // if ( !poly->depthTest ) {
- qglColor4fv( poly->rgb.ToFloatPtr() );
- qglBegin( GL_POLYGON );
- for ( j = 0; j < poly->winding.GetNumPoints(); j++) {
- qglVertex3fv( poly->winding[j].ToFloatPtr() );
- }
- qglEnd();
- // }
- }
- GL_State( GLS_DEFAULT );
- if ( r_debugPolygonFilled.GetBool() ) {
- qglDisable( GL_POLYGON_OFFSET_FILL );
- } else {
- qglDisable( GL_POLYGON_OFFSET_LINE );
- }
- GL_State( GLS_DEFAULT );
- }
- /*
- ================
- RB_ShowCenterOfProjection
- ================
- */
- void RB_ShowCenterOfProjection() {
- if ( !r_showCenterOfProjection.GetBool() ) {
- return;
- }
- const int w = backEnd.viewDef->scissor.GetWidth();
- const int h = backEnd.viewDef->scissor.GetHeight();
- qglClearColor( 1, 0, 0, 1 );
- for ( float f = 0.0f ; f <= 1.0f ; f += 0.125f ) {
- qglScissor( w * f - 1 , 0, 3, h );
- qglClear( GL_COLOR_BUFFER_BIT );
- qglScissor( 0, h * f - 1 , w, 3 );
- qglClear( GL_COLOR_BUFFER_BIT );
- }
- qglClearColor( 0, 1, 0, 1 );
- float f = 0.5f;
- qglScissor( w * f - 1 , 0, 3, h );
- qglClear( GL_COLOR_BUFFER_BIT );
- qglScissor( 0, h * f - 1 , w, 3 );
- qglClear( GL_COLOR_BUFFER_BIT );
- qglScissor( 0, 0, w, h );
- }
- /*
- ================
- RB_ShowLines
- Draw exact pixel lines to check pixel center sampling
- ================
- */
- void RB_ShowLines() {
- if ( !r_showLines.GetBool() ) {
- return;
- }
- glEnable( GL_SCISSOR_TEST );
- if ( backEnd.viewDef->renderView.viewEyeBuffer == 0 ) {
- glClearColor( 1, 0, 0, 1 );
- } else if ( backEnd.viewDef->renderView.viewEyeBuffer == 1 ) {
- glClearColor( 0, 1, 0, 1 );
- } else {
- glClearColor( 0, 0, 1, 1 );
- }
- const int start = ( r_showLines.GetInteger() > 2 ); // 1,3 = horizontal, 2,4 = vertical
- if ( r_showLines.GetInteger() == 1 || r_showLines.GetInteger() == 3 ) {
- for ( int i = start ; i < tr.GetHeight() ; i+=2 ) {
- glScissor( 0, i, tr.GetWidth(), 1 );
- glClear( GL_COLOR_BUFFER_BIT );
- }
- } else {
- for ( int i = start ; i < tr.GetWidth() ; i+=2 ) {
- glScissor( i, 0, 1, tr.GetHeight() );
- glClear( GL_COLOR_BUFFER_BIT );
- }
- }
- }
- /*
- ================
- RB_TestGamma
- ================
- */
- #define G_WIDTH 512
- #define G_HEIGHT 512
- #define BAR_HEIGHT 64
- void RB_TestGamma() {
- byte image[G_HEIGHT][G_WIDTH][4];
- int i, j;
- int c, comp;
- int v, dither;
- int mask, y;
- if ( r_testGamma.GetInteger() <= 0 ) {
- return;
- }
- v = r_testGamma.GetInteger();
- if ( v <= 1 || v >= 196 ) {
- v = 128;
- }
- memset( image, 0, sizeof( image ) );
- for ( mask = 0; mask < 8; mask++ ) {
- y = mask * BAR_HEIGHT;
- for ( c = 0; c < 4; c++ ) {
- v = c * 64 + 32;
- // solid color
- for ( i = 0; i < BAR_HEIGHT/2; i++ ) {
- for ( j = 0; j < G_WIDTH/4; j++ ) {
- for ( comp = 0; comp < 3; comp++ ) {
- if ( mask & ( 1 << comp ) ) {
- image[y+i][c*G_WIDTH/4+j][comp] = v;
- }
- }
- }
- // dithered color
- for ( j = 0; j < G_WIDTH/4; j++ ) {
- if ( ( i ^ j ) & 1 ) {
- dither = c * 64;
- } else {
- dither = c * 64 + 63;
- }
- for ( comp = 0; comp < 3; comp++ ) {
- if ( mask & ( 1 << comp ) ) {
- image[y+BAR_HEIGHT/2+i][c*G_WIDTH/4+j][comp] = dither;
- }
- }
- }
- }
- }
- }
- // draw geometrically increasing steps in the bottom row
- y = 0 * BAR_HEIGHT;
- float scale = 1;
- for ( c = 0; c < 4; c++ ) {
- v = (int)(64 * scale);
- if ( v < 0 ) {
- v = 0;
- } else if ( v > 255 ) {
- v = 255;
- }
- scale = scale * 1.5;
- for ( i = 0; i < BAR_HEIGHT; i++ ) {
- for ( j = 0; j < G_WIDTH/4; j++ ) {
- image[y+i][c*G_WIDTH/4+j][0] = v;
- image[y+i][c*G_WIDTH/4+j][1] = v;
- image[y+i][c*G_WIDTH/4+j][2] = v;
- }
- }
- }
- qglLoadIdentity();
- qglMatrixMode( GL_PROJECTION );
- GL_State( GLS_DEPTHFUNC_ALWAYS );
- GL_Color( 1, 1, 1 );
- qglPushMatrix();
- qglLoadIdentity();
- qglDisable( GL_TEXTURE_2D );
- qglOrtho( 0, 1, 0, 1, -1, 1 );
- qglRasterPos2f( 0.01f, 0.01f );
- qglDrawPixels( G_WIDTH, G_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, image );
- qglPopMatrix();
- qglEnable( GL_TEXTURE_2D );
- qglMatrixMode( GL_MODELVIEW );
- }
- /*
- ==================
- RB_TestGammaBias
- ==================
- */
- static void RB_TestGammaBias() {
- byte image[G_HEIGHT][G_WIDTH][4];
- if ( r_testGammaBias.GetInteger() <= 0 ) {
- return;
- }
- int y = 0;
- for ( int bias = -40; bias < 40; bias+=10, y += BAR_HEIGHT ) {
- float scale = 1;
- for ( int c = 0; c < 4; c++ ) {
- int v = (int)(64 * scale + bias);
- scale = scale * 1.5;
- if ( v < 0 ) {
- v = 0;
- } else if ( v > 255 ) {
- v = 255;
- }
- for ( int i = 0; i < BAR_HEIGHT; i++ ) {
- for ( int j = 0; j < G_WIDTH/4; j++ ) {
- image[y+i][c*G_WIDTH/4+j][0] = v;
- image[y+i][c*G_WIDTH/4+j][1] = v;
- image[y+i][c*G_WIDTH/4+j][2] = v;
- }
- }
- }
- }
- qglLoadIdentity();
- qglMatrixMode( GL_PROJECTION );
- GL_State( GLS_DEPTHFUNC_ALWAYS );
- GL_Color( 1, 1, 1 );
- qglPushMatrix();
- qglLoadIdentity();
- qglDisable( GL_TEXTURE_2D );
- qglOrtho( 0, 1, 0, 1, -1, 1 );
- qglRasterPos2f( 0.01f, 0.01f );
- qglDrawPixels( G_WIDTH, G_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, image );
- qglPopMatrix();
- qglEnable( GL_TEXTURE_2D );
- qglMatrixMode( GL_MODELVIEW );
- }
- /*
- ================
- RB_TestImage
- Display a single image over most of the screen
- ================
- */
- void RB_TestImage() {
- idImage *image = NULL;
- idImage *imageCr = NULL;
- idImage *imageCb = NULL;
- int max;
- float w, h;
- image = tr.testImage;
- if ( !image ) {
- return;
- }
- if ( tr.testVideo ) {
- cinData_t cin;
- cin = tr.testVideo->ImageForTime( backEnd.viewDef->renderView.time[1] - tr.testVideoStartTime );
- if ( cin.imageY != NULL ) {
- image = cin.imageY;
- imageCr = cin.imageCr;
- imageCb = cin.imageCb;
- } else {
- tr.testImage = NULL;
- return;
- }
- w = 0.25;
- h = 0.25;
- } else {
- max = image->GetUploadWidth() > image->GetUploadHeight() ? image->GetUploadWidth() : image->GetUploadHeight();
- w = 0.25 * image->GetUploadWidth() / max;
- h = 0.25 * image->GetUploadHeight() / max;
- w *= (float)renderSystem->GetHeight() / renderSystem->GetWidth();
- }
- // Set State
- GL_State( GLS_DEPTHFUNC_ALWAYS | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO );
- // Set Parms
- float texS[4] = { 1.0f, 0.0f, 0.0f, 0.0f };
- float texT[4] = { 0.0f, 1.0f, 0.0f, 0.0f };
- renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_S, texS );
- renderProgManager.SetRenderParm( RENDERPARM_TEXTUREMATRIX_T, texT );
- float texGenEnabled[4] = { 0, 0, 0, 0 };
- renderProgManager.SetRenderParm( RENDERPARM_TEXGEN_0_ENABLED, texGenEnabled );
- // not really necessary but just for clarity
- const float screenWidth = 1.0f;
- const float screenHeight = 1.0f;
- const float halfScreenWidth = screenWidth * 0.5f;
- const float halfScreenHeight = screenHeight * 0.5f;
- float scale[16] = { 0 };
- scale[0] = w; // scale
- scale[5] = h; // scale
- scale[12] = halfScreenWidth - ( halfScreenWidth * w ); // translate
- scale[13] = halfScreenHeight - ( halfScreenHeight * h ); // translate
- scale[10] = 1.0f;
- scale[15] = 1.0f;
- float ortho[16] = { 0 };
- ortho[0] = 2.0f / screenWidth;
- ortho[5] = -2.0f / screenHeight;
- ortho[10] = -2.0f;
- ortho[12] = -1.0f;
- ortho[13] = 1.0f;
- ortho[14] = -1.0f;
- ortho[15] = 1.0f;
- float finalOrtho[16];
- R_MatrixMultiply( scale, ortho, finalOrtho );
- float projMatrixTranspose[16];
- R_MatrixTranspose( finalOrtho, projMatrixTranspose );
- renderProgManager.SetRenderParms( RENDERPARM_MVPMATRIX_X, projMatrixTranspose, 4 );
- qglMatrixMode( GL_PROJECTION );
- qglLoadMatrixf( finalOrtho );
- qglMatrixMode( GL_MODELVIEW );
- qglLoadIdentity();
- // Set Color
- GL_Color( 1, 1, 1, 1 );
- // Bind the Texture
- if ( ( imageCr != NULL ) && ( imageCb != NULL ) ) {
- GL_SelectTexture( 0 );
- image->Bind();
- GL_SelectTexture( 1 );
- imageCr->Bind();
- GL_SelectTexture( 2 );
- imageCb->Bind();
- renderProgManager.BindShader_Bink();
- } else {
- GL_SelectTexture( 0 );
- image->Bind();
- // Set Shader
- renderProgManager.BindShader_Texture();
- }
-
- // Draw!
- RB_DrawElementsWithCounters( &backEnd.testImageSurface );
- }
- /*
- =================
- RB_DrawExpandedTriangles
- =================
- */
- void RB_DrawExpandedTriangles( const srfTriangles_t *tri, const float radius, const idVec3 &vieworg ) {
- int i, j, k;
- idVec3 dir[6], normal, point;
- for ( i = 0; i < tri->numIndexes; i += 3 ) {
- idVec3 p[3] = { tri->verts[ tri->indexes[ i + 0 ] ].xyz, tri->verts[ tri->indexes[ i + 1 ] ].xyz, tri->verts[ tri->indexes[ i + 2 ] ].xyz };
- dir[0] = p[0] - p[1];
- dir[1] = p[1] - p[2];
- dir[2] = p[2] - p[0];
- normal = dir[0].Cross( dir[1] );
- if ( normal * p[0] < normal * vieworg ) {
- continue;
- }
- dir[0] = normal.Cross( dir[0] );
- dir[1] = normal.Cross( dir[1] );
- dir[2] = normal.Cross( dir[2] );
- dir[0].Normalize();
- dir[1].Normalize();
- dir[2].Normalize();
- qglBegin( GL_LINE_LOOP );
- for ( j = 0; j < 3; j++ ) {
- k = ( j + 1 ) % 3;
- dir[4] = ( dir[j] + dir[k] ) * 0.5f;
- dir[4].Normalize();
- dir[3] = ( dir[j] + dir[4] ) * 0.5f;
- dir[3].Normalize();
- dir[5] = ( dir[4] + dir[k] ) * 0.5f;
- dir[5].Normalize();
- point = p[k] + dir[j] * radius;
- qglVertex3f( point[0], point[1], point[2] );
- point = p[k] + dir[3] * radius;
- qglVertex3f( point[0], point[1], point[2] );
- point = p[k] + dir[4] * radius;
- qglVertex3f( point[0], point[1], point[2] );
- point = p[k] + dir[5] * radius;
- qglVertex3f( point[0], point[1], point[2] );
- point = p[k] + dir[k] * radius;
- qglVertex3f( point[0], point[1], point[2] );
- }
- qglEnd();
- }
- }
- /*
- ================
- RB_ShowTrace
- Debug visualization
- FIXME: not thread safe!
- ================
- */
- void RB_ShowTrace( drawSurf_t **drawSurfs, int numDrawSurfs ) {
- int i;
- const srfTriangles_t *tri;
- const drawSurf_t *surf;
- idVec3 start, end;
- idVec3 localStart, localEnd;
- localTrace_t hit;
- float radius;
- if ( r_showTrace.GetInteger() == 0 ) {
- return;
- }
- if ( r_showTrace.GetInteger() == 2 ) {
- radius = 5.0f;
- } else {
- radius = 0.0f;
- }
- // determine the points of the trace
- start = backEnd.viewDef->renderView.vieworg;
- end = start + 4000 * backEnd.viewDef->renderView.viewaxis[0];
- // check and draw the surfaces
- globalImages->whiteImage->Bind();
- // find how many are ambient
- for ( i = 0; i < numDrawSurfs; i++ ) {
- surf = drawSurfs[i];
- tri = surf->frontEndGeo;
- if ( tri == NULL || tri->verts == NULL ) {
- continue;
- }
- // transform the points into local space
- R_GlobalPointToLocal( surf->space->modelMatrix, start, localStart );
- R_GlobalPointToLocal( surf->space->modelMatrix, end, localEnd );
- // check the bounding box
- if ( !tri->bounds.Expand( radius ).LineIntersection( localStart, localEnd ) ) {
- continue;
- }
- qglLoadMatrixf( surf->space->modelViewMatrix );
- // highlight the surface
- GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA );
- GL_Color( 1, 0, 0, 0.25 );
- RB_DrawElementsWithCounters( surf );
- // draw the bounding box
- GL_State( GLS_DEPTHFUNC_ALWAYS );
- GL_Color( 1, 1, 1, 1 );
- RB_DrawBounds( tri->bounds );
- if ( radius != 0.0f ) {
- // draw the expanded triangles
- GL_Color( 0.5f, 0.5f, 1.0f, 1.0f );
- RB_DrawExpandedTriangles( tri, radius, localStart );
- }
- // check the exact surfaces
- hit = R_LocalTrace( localStart, localEnd, radius, tri );
- if ( hit.fraction < 1.0 ) {
- GL_Color( 1, 1, 1, 1 );
- RB_DrawBounds( idBounds( hit.point ).Expand( 1 ) );
- }
- }
- }
- /*
- =================
- RB_RenderDebugTools
- =================
- */
- void RB_RenderDebugTools( drawSurf_t **drawSurfs, int numDrawSurfs ) {
- // don't do much if this was a 2D rendering
- if ( !backEnd.viewDef->viewEntitys ) {
- RB_TestImage();
- RB_ShowLines();
- return;
- }
- renderLog.OpenMainBlock( MRB_DRAW_DEBUG_TOOLS );
- RENDERLOG_PRINTF( "---------- RB_RenderDebugTools ----------\n" );
- GL_State( GLS_DEFAULT );
- GL_Scissor( backEnd.viewDef->viewport.x1 + backEnd.viewDef->scissor.x1,
- backEnd.viewDef->viewport.y1 + backEnd.viewDef->scissor.y1,
- backEnd.viewDef->scissor.x2 + 1 - backEnd.viewDef->scissor.x1,
- backEnd.viewDef->scissor.y2 + 1 - backEnd.viewDef->scissor.y1 );
- backEnd.currentScissor = backEnd.viewDef->scissor;
- RB_ShowLightCount();
- RB_ShowTexturePolarity( drawSurfs, numDrawSurfs );
- RB_ShowTangentSpace( drawSurfs, numDrawSurfs );
- RB_ShowVertexColor( drawSurfs, numDrawSurfs );
- RB_ShowTris( drawSurfs, numDrawSurfs );
- RB_ShowUnsmoothedTangents( drawSurfs, numDrawSurfs );
- RB_ShowSurfaceInfo( drawSurfs, numDrawSurfs );
- RB_ShowEdges( drawSurfs, numDrawSurfs );
- RB_ShowNormals( drawSurfs, numDrawSurfs );
- RB_ShowViewEntitys( backEnd.viewDef->viewEntitys );
- RB_ShowLights();
- RB_ShowTextureVectors( drawSurfs, numDrawSurfs );
- RB_ShowDominantTris( drawSurfs, numDrawSurfs );
- if ( r_testGamma.GetInteger() > 0 ) { // test here so stack check isn't so damn slow on debug builds
- RB_TestGamma();
- }
- if ( r_testGammaBias.GetInteger() > 0 ) {
- RB_TestGammaBias();
- }
- RB_TestImage();
- RB_ShowPortals();
- RB_ShowSilhouette();
- RB_ShowDepthBuffer();
- RB_ShowIntensity();
- RB_ShowCenterOfProjection();
- RB_ShowLines();
- RB_ShowDebugLines();
- RB_ShowDebugText();
- RB_ShowDebugPolygons();
- RB_ShowTrace( drawSurfs, numDrawSurfs );
- renderLog.CloseMainBlock();
- }
- /*
- =================
- RB_ShutdownDebugTools
- =================
- */
- void RB_ShutdownDebugTools() {
- for ( int i = 0; i < MAX_DEBUG_POLYGONS; i++ ) {
- rb_debugPolygons[i].winding.Clear();
- }
- }
|