2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 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.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../idlib/precompiled.h"
32 #include "Game_local.h"
34 // _D3XP : rename all gameLocal.time to gameLocal.slow.time for merge!
37 static int MakePowerOfTwo( int num ) {
39 for (pot = 1 ; pot < num ; pot<<=1) {
45 const int IMPULSE_DELAY = 150;
48 idPlayerView::idPlayerView
51 idPlayerView::idPlayerView() {
52 memset( screenBlobs, 0, sizeof( screenBlobs ) );
53 memset( &view, 0, sizeof( view ) );
55 dvMaterial = declManager->FindMaterial( "_scratch" );
56 tunnelMaterial = declManager->FindMaterial( "textures/decals/tunnel" );
57 armorMaterial = declManager->FindMaterial( "armorViewEffect" );
58 berserkMaterial = declManager->FindMaterial( "textures/decals/berserk" );
59 irGogglesMaterial = declManager->FindMaterial( "textures/decals/irblend" );
60 bloodSprayMaterial = declManager->FindMaterial( "textures/decals/bloodspray" );
61 bfgMaterial = declManager->FindMaterial( "textures/decals/bfgvision" );
62 lagoMaterial = declManager->FindMaterial( LAGO_MATERIAL, false );
67 lastDamageTime = 0.0f;
78 fxManager = new FullscreenFXManager;
79 fxManager->Initialize( this );
91 void idPlayerView::Save( idSaveGame *savefile ) const {
93 const screenBlob_t *blob;
95 blob = &screenBlobs[ 0 ];
96 for( i = 0; i < MAX_SCREEN_BLOBS; i++, blob++ ) {
97 savefile->WriteMaterial( blob->material );
98 savefile->WriteFloat( blob->x );
99 savefile->WriteFloat( blob->y );
100 savefile->WriteFloat( blob->w );
101 savefile->WriteFloat( blob->h );
102 savefile->WriteFloat( blob->s1 );
103 savefile->WriteFloat( blob->t1 );
104 savefile->WriteFloat( blob->s2 );
105 savefile->WriteFloat( blob->t2 );
106 savefile->WriteInt( blob->finishTime );
107 savefile->WriteInt( blob->startFadeTime );
108 savefile->WriteFloat( blob->driftAmount );
111 savefile->WriteInt( dvFinishTime );
112 savefile->WriteMaterial( dvMaterial );
113 savefile->WriteInt( kickFinishTime );
114 savefile->WriteAngles( kickAngles );
115 savefile->WriteBool( bfgVision );
117 savefile->WriteMaterial( tunnelMaterial );
118 savefile->WriteMaterial( armorMaterial );
119 savefile->WriteMaterial( berserkMaterial );
120 savefile->WriteMaterial( irGogglesMaterial );
121 savefile->WriteMaterial( bloodSprayMaterial );
122 savefile->WriteMaterial( bfgMaterial );
123 savefile->WriteFloat( lastDamageTime );
125 savefile->WriteVec4( fadeColor );
126 savefile->WriteVec4( fadeToColor );
127 savefile->WriteVec4( fadeFromColor );
128 savefile->WriteFloat( fadeRate );
129 savefile->WriteInt( fadeTime );
131 savefile->WriteAngles( shakeAng );
133 savefile->WriteObject( player );
134 savefile->WriteRenderView( view );
138 fxManager->Save( savefile );
145 idPlayerView::Restore
148 void idPlayerView::Restore( idRestoreGame *savefile ) {
152 blob = &screenBlobs[ 0 ];
153 for( i = 0; i < MAX_SCREEN_BLOBS; i++, blob++ ) {
154 savefile->ReadMaterial( blob->material );
155 savefile->ReadFloat( blob->x );
156 savefile->ReadFloat( blob->y );
157 savefile->ReadFloat( blob->w );
158 savefile->ReadFloat( blob->h );
159 savefile->ReadFloat( blob->s1 );
160 savefile->ReadFloat( blob->t1 );
161 savefile->ReadFloat( blob->s2 );
162 savefile->ReadFloat( blob->t2 );
163 savefile->ReadInt( blob->finishTime );
164 savefile->ReadInt( blob->startFadeTime );
165 savefile->ReadFloat( blob->driftAmount );
168 savefile->ReadInt( dvFinishTime );
169 savefile->ReadMaterial( dvMaterial );
170 savefile->ReadInt( kickFinishTime );
171 savefile->ReadAngles( kickAngles );
172 savefile->ReadBool( bfgVision );
174 savefile->ReadMaterial( tunnelMaterial );
175 savefile->ReadMaterial( armorMaterial );
176 savefile->ReadMaterial( berserkMaterial );
177 savefile->ReadMaterial( irGogglesMaterial );
178 savefile->ReadMaterial( bloodSprayMaterial );
179 savefile->ReadMaterial( bfgMaterial );
180 savefile->ReadFloat( lastDamageTime );
182 savefile->ReadVec4( fadeColor );
183 savefile->ReadVec4( fadeToColor );
184 savefile->ReadVec4( fadeFromColor );
185 savefile->ReadFloat( fadeRate );
186 savefile->ReadInt( fadeTime );
188 savefile->ReadAngles( shakeAng );
190 savefile->ReadObject( reinterpret_cast<idClass *&>( player ) );
191 savefile->ReadRenderView( view );
195 fxManager->Restore( savefile );
202 idPlayerView::SetPlayerEntity
205 void idPlayerView::SetPlayerEntity( idPlayer *playerEnt ) {
211 idPlayerView::ClearEffects
214 void idPlayerView::ClearEffects() {
215 lastDamageTime = MS2SEC( gameLocal.slow.time - 99999 );
217 dvFinishTime = ( gameLocal.fast.time - 99999 );
218 kickFinishTime = ( gameLocal.slow.time - 99999 );
220 for ( int i = 0 ; i < MAX_SCREEN_BLOBS ; i++ ) {
221 screenBlobs[i].finishTime = gameLocal.slow.time;
230 idPlayerView::GetScreenBlob
233 screenBlob_t *idPlayerView::GetScreenBlob() {
234 screenBlob_t *oldest = &screenBlobs[0];
236 for ( int i = 1 ; i < MAX_SCREEN_BLOBS ; i++ ) {
237 if ( screenBlobs[i].finishTime < oldest->finishTime ) {
238 oldest = &screenBlobs[i];
246 idPlayerView::DamageImpulse
248 LocalKickDir is the direction of force in the player's coordinate system,
249 which will determine the head kick direction
252 void idPlayerView::DamageImpulse( idVec3 localKickDir, const idDict *damageDef ) {
254 // double vision effect
256 if ( lastDamageTime > 0.0f && SEC2MS( lastDamageTime ) + IMPULSE_DELAY > gameLocal.slow.time ) {
257 // keep shotgun from obliterating the view
261 float dvTime = damageDef->GetFloat( "dv_time" );
263 if ( dvFinishTime < gameLocal.fast.time ) {
264 dvFinishTime = gameLocal.fast.time;
266 dvFinishTime += g_dvTime.GetFloat() * dvTime;
267 // don't let it add up too much in god mode
268 if ( dvFinishTime > gameLocal.fast.time + 5000 ) {
269 dvFinishTime = gameLocal.fast.time + 5000;
276 float kickTime = damageDef->GetFloat( "kick_time" );
278 kickFinishTime = gameLocal.slow.time + g_kickTime.GetFloat() * kickTime;
280 // forward / back kick will pitch view
281 kickAngles[0] = localKickDir[0];
283 // side kick will yaw view
284 kickAngles[1] = localKickDir[1]*0.5f;
286 // up / down kick will pitch view
287 kickAngles[0] += localKickDir[2];
289 // roll will come from side
290 kickAngles[2] = localKickDir[1];
292 float kickAmplitude = damageDef->GetFloat( "kick_amplitude" );
293 if ( kickAmplitude ) {
294 kickAngles *= kickAmplitude;
301 float blobTime = damageDef->GetFloat( "blob_time" );
303 screenBlob_t *blob = GetScreenBlob();
304 blob->startFadeTime = gameLocal.slow.time;
305 blob->finishTime = gameLocal.slow.time + blobTime * g_blobTime.GetFloat() * ((float)gameLocal.msec / USERCMD_MSEC);
307 const char *materialName = damageDef->GetString( "mtr_blob" );
308 blob->material = declManager->FindMaterial( materialName );
309 blob->x = damageDef->GetFloat( "blob_x" );
310 blob->x += ( gameLocal.random.RandomInt()&63 ) - 32;
311 blob->y = damageDef->GetFloat( "blob_y" );
312 blob->y += ( gameLocal.random.RandomInt()&63 ) - 32;
314 float scale = ( 256 + ( ( gameLocal.random.RandomInt()&63 ) - 32 ) ) / 256.0f;
315 blob->w = damageDef->GetFloat( "blob_width" ) * g_blobSize.GetFloat() * scale;
316 blob->h = damageDef->GetFloat( "blob_height" ) * g_blobSize.GetFloat() * scale;
324 // save lastDamageTime for tunnel vision accentuation
326 lastDamageTime = MS2SEC( gameLocal.slow.time );
332 idPlayerView::AddBloodSpray
334 If we need a more generic way to add blobs then we can do that
335 but having it localized here lets the material be pre-looked up etc.
338 void idPlayerView::AddBloodSpray( float duration ) {
340 if ( duration <= 0 || bloodSprayMaterial == NULL || g_skipViewEffects.GetBool() ) {
343 // visit this for chainsaw
344 screenBlob_t *blob = GetScreenBlob();
345 blob->startFadeTime = gameLocal.slow.time;
346 blob->finishTime = gameLocal.slow.time + ( duration * 1000 );
347 blob->material = bloodSprayMaterial;
348 blob->x = ( gameLocal.random.RandomInt() & 63 ) - 32;
349 blob->y = ( gameLocal.random.RandomInt() & 63 ) - 32;
350 blob->driftAmount = 0.5f + gameLocal.random.CRandomFloat() * 0.5;
351 float scale = ( 256 + ( ( gameLocal.random.RandomInt()&63 ) - 32 ) ) / 256.0f;
352 blob->w = 600 * g_blobSize.GetFloat() * scale;
353 blob->h = 480 * g_blobSize.GetFloat() * scale;
358 if ( blob->driftAmount < 0.6 ) {
361 } else if ( blob->driftAmount < 0.75 ) {
364 } else if ( blob->driftAmount < 0.85 ) {
379 idPlayerView::WeaponFireFeedback
381 Called when a weapon fires, generates head twitches, etc
384 void idPlayerView::WeaponFireFeedback( const idDict *weaponDef ) {
387 recoilTime = weaponDef->GetInt( "recoilTime" );
388 // don't shorten a damage kick in progress
389 if ( recoilTime && kickFinishTime < gameLocal.slow.time ) {
391 weaponDef->GetAngles( "recoilAngles", "5 0 0", angles );
393 int finish = gameLocal.slow.time + g_kickTime.GetFloat() * recoilTime;
394 kickFinishTime = finish;
401 idPlayerView::CalculateShake
404 void idPlayerView::CalculateShake() {
405 idVec3 origin, matrix;
407 float shakeVolume = gameSoundWorld->CurrentShakeAmplitudeForPosition( gameLocal.slow.time, player->firstPersonViewOrigin );
409 // shakeVolume should somehow be molded into an angle here
410 // it should be thought of as being in the range 0.0 -> 1.0, although
411 // since CurrentShakeAmplitudeForPosition() returns all the shake sounds
412 // the player can hear, it can go over 1.0 too.
414 shakeAng[0] = gameLocal.random.CRandomFloat() * shakeVolume;
415 shakeAng[1] = gameLocal.random.CRandomFloat() * shakeVolume;
416 shakeAng[2] = gameLocal.random.CRandomFloat() * shakeVolume;
421 idPlayerView::ShakeAxis
424 idMat3 idPlayerView::ShakeAxis() const {
425 return shakeAng.ToMat3();
430 idPlayerView::AngleOffset
432 kickVector, a world space direction that the attack should
435 idAngles idPlayerView::AngleOffset() const {
440 if ( gameLocal.slow.time < kickFinishTime ) {
441 float offset = kickFinishTime - gameLocal.slow.time;
443 ang = kickAngles * offset * offset * g_kickAmplitude.GetFloat();
445 for ( int i = 0 ; i < 3 ; i++ ) {
446 if ( ang[i] > 70.0f ) {
448 } else if ( ang[i] < -70.0f ) {
458 idPlayerView::SingleView
461 void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view ) {
468 // place the sound origin for the player
469 gameSoundWorld->PlaceListener( view->vieworg, view->viewaxis, player->entityNumber + 1, gameLocal.slow.time, hud ? hud->State().GetString( "location" ) : "Undefined" );
471 // if the objective system is up, don't do normal drawing
472 if ( player->objectiveSystemOpen ) {
473 player->objectiveSystem->Redraw( gameLocal.fast.time );
477 // hack the shake in at the very last moment, so it can't cause any consistency problems
478 renderView_t hackedView = *view;
479 hackedView.viewaxis = hackedView.viewaxis * ShakeAxis();
482 if ( gameLocal.portalSkyEnt.GetEntity() && gameLocal.IsPortalSkyAcive() && g_enablePortalSky.GetBool() ) {
483 renderView_t portalView = hackedView;
484 portalView.vieworg = gameLocal.portalSkyEnt.GetEntity()->GetPhysics()->GetOrigin();
486 // setup global fixup projection vars
488 int vidWidth, vidHeight;
491 renderSystem->GetGLSettings( vidWidth, vidHeight );
495 pot = MakePowerOfTwo( w );
496 shiftScale.x = (float)w / pot;
499 pot = MakePowerOfTwo( h );
500 shiftScale.y = (float)h / pot;
502 hackedView.shaderParms[4] = shiftScale.x;
503 hackedView.shaderParms[5] = shiftScale.y;
506 gameRenderWorld->RenderScene( &portalView );
507 renderSystem->CaptureRenderToImage( "_currentRender" );
509 hackedView.forceUpdate = true; // FIX: for smoke particles not drawing when portalSky present
513 fxManager->Process( &hackedView );
516 if ( player->spectating ) {
527 if ( !pm_thirdPerson.GetBool() && !g_skipViewEffects.GetBool() ) {
528 for ( int i = 0 ; i < MAX_SCREEN_BLOBS ; i++ ) {
529 screenBlob_t *blob = &screenBlobs[i];
530 if ( blob->finishTime <= gameLocal.slow.time ) {
534 blob->y += blob->driftAmount;
536 float fade = (float)( blob->finishTime - gameLocal.slow.time ) / ( blob->finishTime - blob->startFadeTime );
541 renderSystem->SetColor4( 1,1,1,fade );
542 renderSystem->DrawStretchPic( blob->x, blob->y, blob->w, blob->h,blob->s1, blob->t1, blob->s2, blob->t2, blob->material );
545 player->DrawHUD( hud );
547 // armor impulse feedback
548 float armorPulse = ( gameLocal.fast.time - player->lastArmorPulse ) / 250.0f;
550 if ( armorPulse > 0.0f && armorPulse < 1.0f ) {
551 renderSystem->SetColor4( 1, 1, 1, 1.0 - armorPulse );
552 renderSystem->DrawStretchPic( 0, 0, 640, 480, 0, 0, 1, 1, armorMaterial );
558 if ( g_testHealthVision.GetFloat() != 0.0f ) {
559 health = g_testHealthVision.GetFloat();
561 health = player->health;
563 float alpha = health / 100.0f;
564 if ( alpha < 0.0f ) {
567 if ( alpha > 1.0f ) {
571 if ( alpha < 1.0f ) {
572 renderSystem->SetColor4( ( player->health <= 0.0f ) ? MS2SEC( gameLocal.slow.time ) : lastDamageTime, 1.0f, 1.0f, ( player->health <= 0.0f ) ? 0.0f : alpha );
573 renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 1.0f, 1.0f, tunnelMaterial );
577 renderSystem->SetColor4( 1.0f, 1.0f, 1.0f, 1.0f );
578 renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 1.0f, 1.0f, bfgMaterial );
583 // test a single material drawn over everything
584 if ( g_testPostProcess.GetString()[0] ) {
585 const idMaterial *mtr = declManager->FindMaterial( g_testPostProcess.GetString(), false );
587 common->Printf( "Material not found.\n" );
588 g_testPostProcess.SetString( "" );
590 renderSystem->SetColor4( 1.0f, 1.0f, 1.0f, 1.0f );
591 renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 1.0f, 1.0f, mtr );
601 flashes the player view with the given color
604 void idPlayerView::Flash(idVec4 color, int time ) {
605 Fade(idVec4(0, 0, 0, 0), time);
606 fadeFromColor = colorWhite;
613 used for level transition fades
614 assumes: color.w is 0 or 1
617 void idPlayerView::Fade( idVec4 color, int time ) {
619 SetTimeState ts( player->timeGroup );
623 fadeFromColor.Set( 0.0f, 0.0f, 0.0f, 1.0f - color[ 3 ] );
625 fadeFromColor = fadeColor;
632 fadeColor = fadeToColor;
634 fadeRate = 1.0f / ( float )time;
637 if ( gameLocal.realClientTime == 0 && time == 0 ) {
640 fadeTime = gameLocal.realClientTime + time;
646 idPlayerView::ScreenFade
649 void idPlayerView::ScreenFade() {
658 SetTimeState ts( player->timeGroup );
661 msec = fadeTime - gameLocal.realClientTime;
664 fadeColor = fadeToColor;
665 if ( fadeColor[ 3 ] == 0.0f ) {
669 t = ( float )msec * fadeRate;
670 fadeColor = fadeFromColor * t + fadeToColor * ( 1.0f - t );
673 if ( fadeColor[ 3 ] != 0.0f ) {
674 renderSystem->SetColor4( fadeColor[ 0 ], fadeColor[ 1 ], fadeColor[ 2 ], fadeColor[ 3 ] );
675 renderSystem->DrawStretchPic( 0, 0, 640, 480, 0, 0, 1, 1, declManager->FindMaterial( "_white" ) );
681 idPlayerView::RenderPlayerView
684 void idPlayerView::RenderPlayerView( idUserInterface *hud ) {
685 const renderView_t *view = player->GetRenderView();
687 SingleView( hud, view );
690 if ( net_clientLagOMeter.GetBool() && lagoMaterial && gameLocal.isClient ) {
691 renderSystem->SetColor4( 1.0f, 1.0f, 1.0f, 1.0f );
692 renderSystem->DrawStretchPic( 10.0f, 380.0f, 64.0f, 64.0f, 0.0f, 0.0f, 1.0f, 1.0f, lagoMaterial );
699 idPlayerView::WarpVision
702 int idPlayerView::AddWarp( idVec3 worldOrigin, float centerx, float centery, float initialRadius, float durationMsec ) {
703 FullscreenFX_Warp *fx = (FullscreenFX_Warp*)( fxManager->FindFX( "warp" ) );
706 fx->EnableGrabber( true );
713 void idPlayerView::FreeWarp( int id ) {
714 FullscreenFX_Warp *fx = (FullscreenFX_Warp*)( fxManager->FindFX( "warp" ) );
717 fx->EnableGrabber( false );
733 state = FX_STATE_OFF;
740 FxFader::SetTriggerState
743 bool FxFader::SetTriggerState( bool active ) {
745 // handle on/off states
746 if ( active && state == FX_STATE_OFF ) {
747 state = FX_STATE_RAMPUP;
748 time = gameLocal.slow.time + msec;
750 else if ( !active && state == FX_STATE_ON ) {
751 state = FX_STATE_RAMPDOWN;
752 time = gameLocal.slow.time + msec;
755 // handle rampup/rampdown states
756 if ( state == FX_STATE_RAMPUP ) {
757 if ( gameLocal.slow.time >= time ) {
761 else if ( state == FX_STATE_RAMPDOWN ) {
762 if ( gameLocal.slow.time >= time ) {
763 state = FX_STATE_OFF;
769 case FX_STATE_ON: alpha = 1; break;
770 case FX_STATE_OFF: alpha = 0; break;
771 case FX_STATE_RAMPUP: alpha = 1 - (float)( time - gameLocal.slow.time ) / msec; break;
772 case FX_STATE_RAMPDOWN: alpha = (float)( time - gameLocal.slow.time ) / msec; break;
788 void FxFader::Save( idSaveGame *savefile ) {
789 savefile->WriteInt( time );
790 savefile->WriteInt( state );
791 savefile->WriteFloat( alpha );
792 savefile->WriteInt( msec );
800 void FxFader::Restore( idRestoreGame *savefile ) {
801 savefile->ReadInt( time );
802 savefile->ReadInt( state );
803 savefile->ReadFloat( alpha );
804 savefile->ReadInt( msec );
813 FullscreenFX_Helltime::Save
816 void FullscreenFX::Save( idSaveGame *savefile ) {
817 fader.Save( savefile );
822 FullscreenFX_Helltime::Restore
825 void FullscreenFX::Restore( idRestoreGame *savefile ) {
826 fader.Restore( savefile );
832 FullscreenFX_Helltime::Initialize
835 void FullscreenFX_Helltime::Initialize() {
836 acInitMaterials[0] = declManager->FindMaterial( "textures/smf/bloodorb1/ac_init" );
837 acInitMaterials[1] = declManager->FindMaterial( "textures/smf/bloodorb2/ac_init" );
838 acInitMaterials[2] = declManager->FindMaterial( "textures/smf/bloodorb3/ac_init" );
840 acCaptureMaterials[0] = declManager->FindMaterial( "textures/smf/bloodorb1/ac_capture" );
841 acCaptureMaterials[1] = declManager->FindMaterial( "textures/smf/bloodorb2/ac_capture" );
842 acCaptureMaterials[2] = declManager->FindMaterial( "textures/smf/bloodorb3/ac_capture" );
844 acDrawMaterials[0] = declManager->FindMaterial( "textures/smf/bloodorb1/ac_draw" );
845 acDrawMaterials[1] = declManager->FindMaterial( "textures/smf/bloodorb2/ac_draw" );
846 acDrawMaterials[2] = declManager->FindMaterial( "textures/smf/bloodorb3/ac_draw" );
848 crCaptureMaterials[0] = declManager->FindMaterial( "textures/smf/bloodorb1/cr_capture" );
849 crCaptureMaterials[1] = declManager->FindMaterial( "textures/smf/bloodorb2/cr_capture" );
850 crCaptureMaterials[2] = declManager->FindMaterial( "textures/smf/bloodorb3/cr_capture" );
852 crDrawMaterials[0] = declManager->FindMaterial( "textures/smf/bloodorb1/cr_draw" );
853 crDrawMaterials[1] = declManager->FindMaterial( "textures/smf/bloodorb2/cr_draw" );
854 crDrawMaterials[2] = declManager->FindMaterial( "textures/smf/bloodorb3/cr_draw" );
856 clearAccumBuffer = true;
861 FullscreenFX_Helltime::DetermineLevel
864 int FullscreenFX_Helltime::DetermineLevel() {
866 int testfx = g_testHelltimeFX.GetInteger();
868 // for testing purposes
869 if ( testfx >= 0 && testfx < 3 ) {
873 player = fxman->GetPlayer();
875 if ( player->PowerUpActive( INVULNERABILITY ) ) {
878 else if ( player->PowerUpActive( BERSERK ) ) {
881 else if ( player->PowerUpActive( HELLTIME ) ) {
890 FullscreenFX_Helltime::Active
893 bool FullscreenFX_Helltime::Active() {
895 if ( gameLocal.inCinematic || gameLocal.isMultiplayer ) {
899 if ( DetermineLevel() >= 0 ) {
903 // latch the clear flag
904 if ( fader.GetAlpha() == 0 ) {
905 clearAccumBuffer = true;
914 FullscreenFX_Helltime::AccumPass
917 void FullscreenFX_Helltime::AccumPass( const renderView_t *view ) {
919 int level = DetermineLevel();
922 if ( level < 0 || level > 2 ) {
926 shiftScale = fxman->GetShiftScale();
927 renderSystem->SetColor4( 1, 1, 1, 1 );
930 if ( clearAccumBuffer ) {
931 clearAccumBuffer = false;
932 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, acInitMaterials[level] );
935 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, acCaptureMaterials[level] );
936 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, shiftScale.y, shiftScale.x, 0, crCaptureMaterials[level] );
939 renderSystem->CaptureRenderToImage( "_accum" );
944 FullscreenFX_Helltime::HighQuality
947 void FullscreenFX_Helltime::HighQuality() {
949 int level = DetermineLevel();
952 if ( level < 0 || level > 2 ) {
956 shiftScale = fxman->GetShiftScale();
957 renderSystem->SetColor4( 1, 1, 1, 1 );
960 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, acDrawMaterials[level] );
961 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, shiftScale.y, shiftScale.x, 0, crDrawMaterials[level] );
966 FullscreenFX_Helltime::Restore
969 void FullscreenFX_Helltime::Restore( idRestoreGame *savefile ) {
970 FullscreenFX::Restore( savefile );
972 // latch the clear flag
973 clearAccumBuffer = true;
982 FullscreenFX_Multiplayer::Initialize
985 void FullscreenFX_Multiplayer::Initialize() {
986 acInitMaterials = declManager->FindMaterial( "textures/smf/multiplayer1/ac_init" );
987 acCaptureMaterials = declManager->FindMaterial( "textures/smf/multiplayer1/ac_capture" );
988 acDrawMaterials = declManager->FindMaterial( "textures/smf/multiplayer1/ac_draw" );
989 crCaptureMaterials = declManager->FindMaterial( "textures/smf/multiplayer1/cr_capture" );
990 crDrawMaterials = declManager->FindMaterial( "textures/smf/multiplayer1/cr_draw" );
991 clearAccumBuffer = true;
996 FullscreenFX_Multiplayer::DetermineLevel
999 int FullscreenFX_Multiplayer::DetermineLevel() {
1001 int testfx = g_testMultiplayerFX.GetInteger();
1003 // for testing purposes
1004 if ( testfx >= 0 && testfx < 3 ) {
1008 player = fxman->GetPlayer();
1010 if ( player->PowerUpActive( INVULNERABILITY ) ) {
1013 //else if ( player->PowerUpActive( HASTE ) ) {
1016 else if ( player->PowerUpActive( BERSERK ) ) {
1025 FullscreenFX_Multiplayer::Active
1028 bool FullscreenFX_Multiplayer::Active() {
1030 if ( !gameLocal.isMultiplayer && g_testMultiplayerFX.GetInteger() == -1 ) {
1034 if ( DetermineLevel() >= 0 ) {
1038 // latch the clear flag
1039 if ( fader.GetAlpha() == 0 ) {
1040 clearAccumBuffer = true;
1049 FullscreenFX_Multiplayer::AccumPass
1052 void FullscreenFX_Multiplayer::AccumPass( const renderView_t *view ) {
1054 int level = DetermineLevel();
1057 if ( level < 0 || level > 2 ) {
1061 shiftScale = fxman->GetShiftScale();
1062 renderSystem->SetColor4( 1, 1, 1, 1 );
1065 if ( clearAccumBuffer ) {
1066 clearAccumBuffer = false;
1067 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, acInitMaterials );
1070 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, acCaptureMaterials );
1071 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, shiftScale.y, shiftScale.x, 0, crCaptureMaterials );
1074 renderSystem->CaptureRenderToImage( "_accum" );
1079 FullscreenFX_Multiplayer::HighQuality
1082 void FullscreenFX_Multiplayer::HighQuality() {
1084 int level = DetermineLevel();
1087 if ( level < 0 || level > 2 ) {
1091 shiftScale = fxman->GetShiftScale();
1092 renderSystem->SetColor4( 1, 1, 1, 1 );
1095 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, acDrawMaterials );
1096 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, shiftScale.y, shiftScale.x, 0, crDrawMaterials );
1101 FullscreenFX_Multiplayer::Restore
1104 void FullscreenFX_Multiplayer::Restore( idRestoreGame *savefile ) {
1105 FullscreenFX::Restore( savefile );
1107 // latch the clear flag
1108 clearAccumBuffer = true;
1117 FullscreenFX_Warp::Initialize
1120 void FullscreenFX_Warp::Initialize() {
1121 material = declManager->FindMaterial( "textures/smf/warp" );
1122 grabberEnabled = false;
1128 FullscreenFX_Warp::Active
1131 bool FullscreenFX_Warp::Active() {
1132 if ( grabberEnabled ) {
1141 FullscreenFX_Warp::Save
1144 void FullscreenFX_Warp::Save( idSaveGame *savefile ) {
1145 FullscreenFX::Save( savefile );
1147 savefile->WriteBool( grabberEnabled );
1148 savefile->WriteInt( startWarpTime );
1153 FullscreenFX_Warp::Restore
1156 void FullscreenFX_Warp::Restore( idRestoreGame *savefile ) {
1157 FullscreenFX::Restore( savefile );
1159 savefile->ReadBool( grabberEnabled );
1160 savefile->ReadInt( startWarpTime );
1165 FullscreenFX_Warp::DrawWarp
1168 void FullscreenFX_Warp::DrawWarp( WarpPolygon_t wp, float interp ) {
1169 idVec4 mid1_uv, mid2_uv;
1171 idVec2 drawPts[6], shiftScale;
1172 WarpPolygon_t trans;
1175 shiftScale = fxman->GetShiftScale();
1177 // compute mid points
1178 mid1 = trans.outer1 * ( interp ) + trans.center * ( 1 - interp );
1179 mid2 = trans.outer2 * ( interp ) + trans.center * ( 1 - interp );
1180 mid1_uv = trans.outer1 * ( 0.5 ) + trans.center * ( 1 - 0.5 );
1181 mid2_uv = trans.outer2 * ( 0.5 ) + trans.center * ( 1 - 0.5 );
1183 // draw [outer1, mid2, mid1]
1184 drawPts[0].Set( trans.outer1.x, trans.outer1.y );
1185 drawPts[1].Set( mid2.x, mid2.y );
1186 drawPts[2].Set( mid1.x, mid1.y );
1187 drawPts[3].Set( trans.outer1.z, trans.outer1.w );
1188 drawPts[4].Set( mid2_uv.z, mid2_uv.w );
1189 drawPts[5].Set( mid1_uv.z, mid1_uv.w );
1190 for ( int j = 0; j < 3; j++ ) {
1191 drawPts[j+3].x *= shiftScale.x;
1192 drawPts[j+3].y *= shiftScale.y;
1194 renderSystem->DrawStretchTri( drawPts[0], drawPts[1], drawPts[2], drawPts[3], drawPts[4], drawPts[5], material );
1196 // draw [outer1, outer2, mid2]
1197 drawPts[0].Set( trans.outer1.x, trans.outer1.y );
1198 drawPts[1].Set( trans.outer2.x, trans.outer2.y );
1199 drawPts[2].Set( mid2.x, mid2.y );
1200 drawPts[3].Set( trans.outer1.z, trans.outer1.w );
1201 drawPts[4].Set( trans.outer2.z, trans.outer2.w );
1202 drawPts[5].Set( mid2_uv.z, mid2_uv.w );
1203 for ( int j = 0; j < 3; j++ ) {
1204 drawPts[j+3].x *= shiftScale.x;
1205 drawPts[j+3].y *= shiftScale.y;
1207 renderSystem->DrawStretchTri( drawPts[0], drawPts[1], drawPts[2], drawPts[3], drawPts[4], drawPts[5], material );
1209 // draw [mid1, mid2, center]
1210 drawPts[0].Set( mid1.x, mid1.y );
1211 drawPts[1].Set( mid2.x, mid2.y );
1212 drawPts[2].Set( trans.center.x, trans.center.y );
1213 drawPts[3].Set( mid1_uv.z, mid1_uv.w );
1214 drawPts[4].Set( mid2_uv.z, mid2_uv.w );
1215 drawPts[5].Set( trans.center.z, trans.center.w );
1216 for ( int j = 0; j < 3; j++ ) {
1217 drawPts[j+3].x *= shiftScale.x;
1218 drawPts[j+3].y *= shiftScale.y;
1220 renderSystem->DrawStretchTri( drawPts[0], drawPts[1], drawPts[2], drawPts[3], drawPts[4], drawPts[5], material );
1225 FullscreenFX_Warp::HighQuality
1228 void FullscreenFX_Warp::HighQuality() {
1229 float x1, y1, x2, y2, radius, interp;
1233 interp = ( idMath::Sin( (float)( gameLocal.slow.time - startWarpTime ) / 1000 ) + 1 ) / 2.f;
1234 interp = 0.7 * ( 1 - interp ) + 0.3 * ( interp );
1241 for ( float i = 0; i < 360; i += STEP ) {
1242 // compute the values
1243 x1 = idMath::Sin( DEG2RAD( i ) );
1244 y1 = idMath::Cos( DEG2RAD( i ) );
1246 x2 = idMath::Sin( DEG2RAD( i + STEP ) );
1247 y2 = idMath::Cos( DEG2RAD( i + STEP ) );
1252 p.outer1.x = center.x + x1 * radius;
1253 p.outer1.y = center.y + y1 * radius;
1254 p.outer1.z = p.outer1.x / 640.f;
1255 p.outer1.w = 1 - ( p.outer1.y / 480.f );
1257 p.outer2.x = center.x + x2 * radius;
1258 p.outer2.y = center.y + y2 * radius;
1259 p.outer2.z = p.outer2.x / 640.f;
1260 p.outer2.w = 1 - ( p.outer2.y / 480.f );
1262 p.center.x = center.x;
1263 p.center.y = center.y;
1264 p.center.z = p.center.x / 640.f;
1265 p.center.w = 1 - ( p.center.y / 480.f );
1268 DrawWarp( p, interp );
1278 FullscreenFX_EnviroSuit::Initialize
1281 void FullscreenFX_EnviroSuit::Initialize() {
1282 material = declManager->FindMaterial( "textures/smf/enviro_suit" );
1287 FullscreenFX_EnviroSuit::Active
1290 bool FullscreenFX_EnviroSuit::Active() {
1293 player = fxman->GetPlayer();
1295 if ( player->PowerUpActive( ENVIROSUIT ) ) {
1304 FullscreenFX_EnviroSuit::HighQuality
1307 void FullscreenFX_EnviroSuit::HighQuality() {
1308 renderSystem->SetColor4( 1, 1, 1, 1 );
1309 renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 1.0f, 1.0f, material );
1318 FullscreenFX_DoubleVision::Initialize
1321 void FullscreenFX_DoubleVision::Initialize() {
1322 material = declManager->FindMaterial( "textures/smf/doubleVision" );
1327 FullscreenFX_DoubleVision::Active
1330 bool FullscreenFX_DoubleVision::Active() {
1332 if ( gameLocal.fast.time < fxman->GetPlayerView()->dvFinishTime ) {
1341 FullscreenFX_DoubleVision::HighQuality
1344 void FullscreenFX_DoubleVision::HighQuality() {
1345 int offset = fxman->GetPlayerView()->dvFinishTime - gameLocal.fast.time;
1346 float scale = offset * g_dvAmplitude.GetFloat();
1350 // for testing purposes
1352 static int test = 0;
1358 scale = offset * g_dvAmplitude.GetFloat();
1361 player = fxman->GetPlayer();
1362 shiftScale = fxman->GetShiftScale();
1364 offset *= 2; // crutch up for higher res
1366 // set the scale and shift
1367 if ( scale > 0.5f ) {
1370 float shift = scale * sin( sqrtf( (float)offset ) * g_dvFrequency.GetFloat() );
1371 shift = fabs( shift );
1373 // carry red tint if in berserk mode
1374 idVec4 color(1, 1, 1, 1);
1375 if ( gameLocal.fast.time < player->inventory.powerupEndTime[ BERSERK ] ) {
1380 if ( !gameLocal.isMultiplayer && gameLocal.fast.time < player->inventory.powerupEndTime[ HELLTIME ] || gameLocal.fast.time < player->inventory.powerupEndTime[ INVULNERABILITY ]) {
1385 renderSystem->SetColor4( color.x, color.y, color.z, 1.0f );
1386 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, shift, shiftScale.y, shiftScale.x, 0, material );
1387 renderSystem->SetColor4( color.x, color.y, color.z, 0.5f );
1388 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, shiftScale.y, (1-shift) * shiftScale.x, 0, material );
1396 FullscreenFX_InfluenceVision::Initialize
1399 void FullscreenFX_InfluenceVision::Initialize() {
1405 FullscreenFX_InfluenceVision::Active
1408 bool FullscreenFX_InfluenceVision::Active() {
1411 player = fxman->GetPlayer();
1413 if ( player->GetInfluenceMaterial() || player->GetInfluenceEntity() ) {
1422 FullscreenFX_InfluenceVision::HighQuality
1425 void FullscreenFX_InfluenceVision::HighQuality() {
1426 float distance = 0.0f;
1431 shiftScale = fxman->GetShiftScale();
1432 player = fxman->GetPlayer();
1434 if ( player->GetInfluenceEntity() ) {
1435 distance = ( player->GetInfluenceEntity()->GetPhysics()->GetOrigin() - player->GetPhysics()->GetOrigin() ).Length();
1436 if ( player->GetInfluenceRadius() != 0.0f && distance < player->GetInfluenceRadius() ) {
1437 pct = distance / player->GetInfluenceRadius();
1438 pct = 1.0f - idMath::ClampFloat( 0.0f, 1.0f, pct );
1442 if ( player->GetInfluenceMaterial() ) {
1443 renderSystem->SetColor4( 1.0f, 1.0f, 1.0f, pct );
1444 renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 1.0f, 1.0f, player->GetInfluenceMaterial() );
1445 } else if ( player->GetInfluenceEntity() == NULL ) {
1448 // int offset = 25 + sinf( gameLocal.slow.time );
1449 // DoubleVision( hud, view, pct * offset );
1458 FullscreenFX_Bloom::Initialize
1461 void FullscreenFX_Bloom::Initialize() {
1462 drawMaterial = declManager->FindMaterial( "textures/smf/bloom2/draw" );
1463 initMaterial = declManager->FindMaterial( "textures/smf/bloom2/init" );
1464 currentMaterial = declManager->FindMaterial( "textures/smf/bloom2/currentMaterial" );
1466 currentIntensity = 0;
1467 targetIntensity = 0;
1472 FullscreenFX_Bloom::Active
1475 bool FullscreenFX_Bloom::Active() {
1478 player = fxman->GetPlayer();
1480 if ( player && player->bloomEnabled ) {
1489 FullscreenFX_Bloom::HighQuality
1492 void FullscreenFX_Bloom::HighQuality() {
1499 player = fxman->GetPlayer();
1500 shiftScale = fxman->GetShiftScale();
1501 renderSystem->SetColor4( 1, 1, 1, 1 );
1503 // if intensity value is different, start the blend
1504 targetIntensity = g_testBloomIntensity.GetFloat();
1506 if ( player && player->bloomEnabled ) {
1507 targetIntensity = player->bloomIntensity;
1510 delta = targetIntensity - currentIntensity;
1511 float step = 0.001f;
1513 if ( step < fabs( delta ) ) {
1518 currentIntensity += step;
1522 num = g_testBloomNumPasses.GetInteger();
1524 for ( int i = 0; i < num; i++ ) {
1525 float s1 = 0, t1 = 0, s2 = 1, t2 = 1;
1528 // do the center scale
1554 alpha = 1 - (float)i / ( num - 1 );
1557 renderSystem->SetColor4( alpha, alpha, alpha, 1 );
1558 renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, s1, t2, s2, t1, drawMaterial );
1560 shift += currentIntensity;
1566 FullscreenFX_Bloom::Save
1569 void FullscreenFX_Bloom::Save( idSaveGame *savefile ) {
1570 FullscreenFX::Save( savefile );
1571 savefile->WriteFloat( currentIntensity );
1572 savefile->WriteFloat( targetIntensity );
1577 FullscreenFX_Bloom::Restore
1580 void FullscreenFX_Bloom::Restore( idRestoreGame *savefile ) {
1581 FullscreenFX::Restore( savefile );
1582 savefile->ReadFloat( currentIntensity );
1583 savefile->ReadFloat( targetIntensity );
1593 FullscreenFXManager::FullscreenFXManager
1596 FullscreenFXManager::FullscreenFXManager() {
1597 highQualityMode = false;
1599 blendBackMaterial = NULL;
1600 shiftScale.Set( 0, 0 );
1605 FullscreenFXManager::~FullscreenFXManager
1608 FullscreenFXManager::~FullscreenFXManager() {
1614 FullscreenFXManager::FindFX
1617 FullscreenFX* FullscreenFXManager::FindFX( idStr name ) {
1618 for ( int i = 0; i < fx.Num(); i++ ) {
1619 if ( fx[i]->GetName() == name ) {
1629 FullscreenFXManager::CreateFX
1632 void FullscreenFXManager::CreateFX( idStr name, idStr fxtype, int fade ) {
1633 FullscreenFX *pfx = NULL;
1635 if ( fxtype == "helltime" ) {
1636 pfx = new FullscreenFX_Helltime;
1638 else if ( fxtype == "warp" ) {
1639 pfx = new FullscreenFX_Warp;
1641 else if ( fxtype == "envirosuit" ) {
1642 pfx = new FullscreenFX_EnviroSuit;
1644 else if ( fxtype == "doublevision" ) {
1645 pfx = new FullscreenFX_DoubleVision;
1647 else if ( fxtype == "multiplayer" ) {
1648 pfx = new FullscreenFX_Multiplayer;
1650 else if ( fxtype == "influencevision" ) {
1651 pfx = new FullscreenFX_InfluenceVision;
1653 else if ( fxtype == "bloom" ) {
1654 pfx = new FullscreenFX_Bloom;
1662 pfx->SetFXManager( this );
1663 pfx->SetName( name );
1664 pfx->SetFadeSpeed( fade );
1671 FullscreenFXManager::Initialize
1674 void FullscreenFXManager::Initialize( idPlayerView *pv ) {
1675 // set the playerview
1677 blendBackMaterial = declManager->FindMaterial( "textures/smf/blendBack" );
1680 CreateFX( "helltime", "helltime", 1000 );
1681 CreateFX( "warp", "warp", 0 );
1682 CreateFX( "envirosuit", "envirosuit", 500 );
1683 CreateFX( "doublevision", "doublevision", 0 );
1684 CreateFX( "multiplayer", "multiplayer", 1000 );
1685 CreateFX( "influencevision", "influencevision", 1000 );
1686 CreateFX( "bloom", "bloom", 0 );
1688 // pre-cache the texture grab so we dont hitch
1689 renderSystem->CropRenderSize( 512, 512, true );
1690 renderSystem->CaptureRenderToImage( "_accum" );
1691 renderSystem->UnCrop();
1693 renderSystem->CropRenderSize( 512, 256, true );
1694 renderSystem->CaptureRenderToImage( "_scratch" );
1695 renderSystem->UnCrop();
1697 renderSystem->CaptureRenderToImage( "_currentRender" );
1702 FullscreenFXManager::Blendback
1705 void FullscreenFXManager::Blendback( float alpha ) {
1707 if ( alpha < 1.f ) {
1708 renderSystem->SetColor4( 1, 1, 1, 1 - alpha );
1709 renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, shiftScale.y, shiftScale.x, 0.f, blendBackMaterial );
1715 FullscreenFXManager::Save
1718 void FullscreenFXManager::Save( idSaveGame *savefile ) {
1719 savefile->WriteBool( highQualityMode );
1720 savefile->WriteVec2( shiftScale );
1722 for ( int i = 0; i < fx.Num(); i++ ) {
1723 FullscreenFX *pfx = fx[i];
1724 pfx->Save( savefile );
1730 FullscreenFXManager::Restore
1733 void FullscreenFXManager::Restore( idRestoreGame *savefile ) {
1734 savefile->ReadBool( highQualityMode );
1735 savefile->ReadVec2( shiftScale );
1737 for ( int i = 0; i < fx.Num(); i++ ) {
1738 FullscreenFX *pfx = fx[i];
1739 pfx->Restore( savefile );
1745 FullscreenFXManager::CaptureCurrentRender
1748 void FullscreenFXManager::CaptureCurrentRender() {
1749 renderSystem->CaptureRenderToImage( "_currentRender" );
1754 FullscreenFXManager::Process
1757 void FullscreenFXManager::Process( const renderView_t *view ) {
1758 bool allpass = false;
1759 bool atLeastOneFX = false;
1761 if ( g_testFullscreenFX.GetInteger() == -2 ) {
1765 if ( g_lowresFullscreenFX.GetBool() ) {
1766 highQualityMode = false;
1769 highQualityMode = true;
1772 // compute the shift scale
1773 if ( highQualityMode ) {
1774 int vidWidth, vidHeight;
1775 renderSystem->GetGLSettings( vidWidth, vidHeight );
1779 pot = MakePowerOfTwo( w );
1780 shiftScale.x = (float)w / pot;
1783 pot = MakePowerOfTwo( h );
1784 shiftScale.y = (float)h / pot;
1787 // if we're in low-res mode, shrink view down
1790 renderSystem->CropRenderSize( 512, 512, true );
1793 // do the first render
1794 gameRenderWorld->RenderScene( view );
1797 for ( int i = 0; i < fx.Num(); i++ ) {
1798 FullscreenFX *pfx = fx[i];
1799 bool drawIt = false;
1801 // determine if we need to draw
1802 if ( pfx->Active() || g_testFullscreenFX.GetInteger() == i || allpass ) {
1803 drawIt = pfx->SetTriggerState( true );
1806 drawIt = pfx->SetTriggerState( false );
1809 // do the actual drawing
1811 atLeastOneFX = true;
1813 // we need to dump to _currentRender
1814 CaptureCurrentRender();
1816 // handle the accum pass if we have one
1817 if ( pfx->HasAccum() ) {
1819 // if we're in high quality mode, we need to crop the accum pass
1820 if ( highQualityMode ) {
1821 renderSystem->CropRenderSize( 512, 512, true );
1822 pfx->AccumPass( view );
1823 renderSystem->UnCrop();
1826 pfx->AccumPass( view );
1830 // do the high quality pass
1834 Blendback( pfx->GetFadeAlpha() );
1838 if ( !highQualityMode ) {
1839 // we need to dump to _currentRender
1840 CaptureCurrentRender();
1843 renderSystem->UnCrop();
1845 // draw the final full-screen image
1846 renderSystem->SetColor4( 1, 1, 1, 1 );
1847 renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 1, 1, 0.f, blendBackMaterial );