From 3b659054d8a11a8aa12f7125a11201c40651cec9 Mon Sep 17 00:00:00 2001 From: g-cont Date: Tue, 28 Dec 2010 00:00:00 +0300 Subject: [PATCH] 28 Dec 2010 --- backup.lst | 1 - change.log | 8 + common/bspfile.h | 2 +- engine/client/cl_game.c | 4 +- engine/client/cl_main.c | 3 + engine/client/cl_menu.c | 2 + engine/client/cl_scrn.c | 1 + engine/client/cl_video.c | 22 +- engine/client/cl_view.c | 23 +- engine/client/client.h | 1 + engine/client/gl_backend.c | 6 +- engine/client/gl_decals.c | 4 +- engine/client/gl_draw.c | 6 +- engine/client/gl_image.c | 4 +- engine/client/gl_local.h | 2 - engine/client/gl_rmain.c | 11 +- engine/client/gl_sprite.c | 8 +- engine/client/gl_studio.c | 28 + engine/client/gl_vidnt.c | 284 +- engine/client/sound/s_main.c | 2 - engine/client/sound/s_mix.c | 14 +- engine/client/Копия gl_vidnt.c | 1818 ++++++++++++ engine/common/cm_local.h | 2 +- engine/common/com_export.h | 1 + engine/common/common.h | 1 + engine/common/con_utils.c | 39 +- engine/common/console.c | 8 +- engine/common/host.c | 40 +- engine/common/input.c | 17 +- engine/common/keys.c | 2 +- engine/common/model.c | 25 +- engine/common/net_encode.c | 5 +- engine/server/server.h | 1 + engine/server/sv_game.c | 9 +- engine/server/sv_main.c | 2 + engine/server/sv_save.c | 2 +- launch/crclib.c | 1 + launch/cvar.c | 107 +- launch/imagelib/imagelib.h | 1 + launch/imagelib/img_utils.c | 10 + launch/imagelib/img_wad.c | 4 +- launch/system.c | 1 + mainui/basemenu.cpp | 21 +- mainui/basemenu.h | 1 + mainui/menu_advcontrols.cpp | 2 + mainui/menu_audio.cpp | 4 +- mainui/menu_configuration.cpp | 1 + mainui/menu_controls.cpp | 1 + mainui/menu_creategame.cpp | 1 + mainui/menu_customgame.cpp | 1 + mainui/menu_gameoptions.cpp | 1 + mainui/menu_langame.cpp | 1 + mainui/menu_loadgame.cpp | 1 + mainui/menu_main.cpp | 4 + mainui/menu_multiplayer.cpp | 2 + mainui/menu_newgame.cpp | 1 + mainui/menu_playdemo.cpp | 1 + mainui/menu_playersetup.cpp | 2 + mainui/menu_playrec.cpp | 2 + mainui/menu_recdemo.cpp | 1 + mainui/menu_savegame.cpp | 1 + mainui/menu_saveload.cpp | 2 + mainui/menu_video.cpp | 2 + mainui/menu_vidmodes.cpp | 22 +- mainui/menu_vidoptions.cpp | 2 + public/launch_api.h | 4 +- vid_gl/r_backend.c | 3225 --------------------- vid_gl/r_backend.h | 456 --- vid_gl/r_bloom.c | 524 ---- vid_gl/r_cull.c | 585 ---- vid_gl/r_decals.c | 1279 -------- vid_gl/r_draw.c | 704 ----- vid_gl/r_image.c | 3835 ------------------------ vid_gl/r_light.c | 1209 -------- vid_gl/r_local.h | 873 ------ vid_gl/r_main.c | 2570 ---------------- vid_gl/r_math.c | 226 -- vid_gl/r_math.h | 72 - vid_gl/r_mesh.c | 1443 --------- vid_gl/r_mesh.h | 114 - vid_gl/r_model.c | 2778 ------------------ vid_gl/r_model.h | 356 --- vid_gl/r_opengl.c | 713 ----- vid_gl/r_opengl.h | 1128 ------- vid_gl/r_poly.c | 456 --- vid_gl/r_program.c | 1139 -------- vid_gl/r_register.c | 1123 ------- vid_gl/r_shader.c | 4191 --------------------------- vid_gl/r_shader.h | 359 --- vid_gl/r_shadow.c | 476 --- vid_gl/r_shadow.h | 56 - vid_gl/r_sky.c | 652 ----- vid_gl/r_sprite.c | 891 ------ vid_gl/r_studio.c | 2694 ----------------- vid_gl/r_surf.c | 718 ----- vid_gl/render_api.h | 148 - vid_gl/vid_gl.dsp | 241 -- vid_gl/warpsin.h | 53 - 98 files changed, 2207 insertions(+), 35693 deletions(-) create mode 100644 engine/client/Копия gl_vidnt.c delete mode 100644 vid_gl/r_backend.c delete mode 100644 vid_gl/r_backend.h delete mode 100644 vid_gl/r_bloom.c delete mode 100644 vid_gl/r_cull.c delete mode 100644 vid_gl/r_decals.c delete mode 100644 vid_gl/r_draw.c delete mode 100644 vid_gl/r_image.c delete mode 100644 vid_gl/r_light.c delete mode 100644 vid_gl/r_local.h delete mode 100644 vid_gl/r_main.c delete mode 100644 vid_gl/r_math.c delete mode 100644 vid_gl/r_math.h delete mode 100644 vid_gl/r_mesh.c delete mode 100644 vid_gl/r_mesh.h delete mode 100644 vid_gl/r_model.c delete mode 100644 vid_gl/r_model.h delete mode 100644 vid_gl/r_opengl.c delete mode 100644 vid_gl/r_opengl.h delete mode 100644 vid_gl/r_poly.c delete mode 100644 vid_gl/r_program.c delete mode 100644 vid_gl/r_register.c delete mode 100644 vid_gl/r_shader.c delete mode 100644 vid_gl/r_shader.h delete mode 100644 vid_gl/r_shadow.c delete mode 100644 vid_gl/r_shadow.h delete mode 100644 vid_gl/r_sky.c delete mode 100644 vid_gl/r_sprite.c delete mode 100644 vid_gl/r_studio.c delete mode 100644 vid_gl/r_surf.c delete mode 100644 vid_gl/render_api.h delete mode 100644 vid_gl/vid_gl.dsp delete mode 100644 vid_gl/warpsin.h diff --git a/backup.lst b/backup.lst index 3c2de2d0..c6c1b11a 100644 --- a/backup.lst +++ b/backup.lst @@ -31,7 +31,6 @@ pm_shared\ public\ launch\ mainui\ -vid_gl\ utils\ utils\vgui\ utils\vgui\include\ diff --git a/change.log b/change.log index aa46f261..7067048d 100644 --- a/change.log +++ b/change.log @@ -1,3 +1,11 @@ +build ???? + +Render: fix decals serialization bug +Engine: fix movie plaback bug (black screen) +Engine: fix crash on loading encrypted client.dll +GameUI: now recalc resolution when vid_mode is changed +Sound: fix musicvolume bug + build 1418 Tools: move all tools into launch.dll diff --git a/common/bspfile.h b/common/bspfile.h index e797b54e..30325410 100644 --- a/common/bspfile.h +++ b/common/bspfile.h @@ -32,7 +32,7 @@ BRUSH MODELS #define SURF_DRAWTILED BIT( 5 ) // face without lighmap #define SURF_CONVEYOR BIT( 6 ) // scrolled texture #define SURF_UNDERWATER BIT( 7 ) // caustics -#define SURF_DONTWARP BIT( 8 ) +#define SURF_TRANSPARENT BIT( 8 ) // it's a transparent texture // lightstyle management #define LM_STYLES 4 // MAXLIGHTMAPS diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index a81229d3..d686fb68 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -1451,9 +1451,7 @@ pfnSPR_Draw */ static void pfnSPR_Draw( int frame, int x, int y, const wrect_t *prc ) { - GL_SetState( GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA ); - GL_TexEnv( GL_MODULATE ); - + GL_SetRenderMode( kRenderNormal ); SPR_DrawGeneric( frame, x, y, -1, -1, prc ); } diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index a59d4552..d2eae8d9 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -831,6 +831,8 @@ void CL_Crashed_f( void ) Host_WriteOpenGLConfig(); Host_WriteConfig(); // write config + // never write video.cfg here because reason to crash may be provoked + // with some renderer variables VID_RestoreGamma(); } @@ -1620,6 +1622,7 @@ void CL_Shutdown( void ) if( !cls.initialized ) return; Host_WriteOpenGLConfig (); + Host_WriteVideoConfig (); Host_WriteConfig (); IN_Shutdown (); diff --git a/engine/client/cl_menu.c b/engine/client/cl_menu.c index e39d61a5..4b87deb0 100644 --- a/engine/client/cl_menu.c +++ b/engine/client/cl_menu.c @@ -162,6 +162,8 @@ static void UI_DrawLogo( const char *filename, float x, float y, float width, fl redraw = true; } + GL_SetState( 0 ); + GL_TexEnv( GL_REPLACE ); R_DrawStretchRaw( x, y, width, height, menu.logo_xres, menu.logo_yres, cin_data, redraw ); } diff --git a/engine/client/cl_scrn.c b/engine/client/cl_scrn.c index feea30ed..6d013813 100644 --- a/engine/client/cl_scrn.c +++ b/engine/client/cl_scrn.c @@ -383,6 +383,7 @@ void SCR_VidInit( void ) menu.globals->scrWidth = scr_width->integer; menu.globals->scrHeight = scr_height->integer; + SCR_RebuildGammaTable(); VGui_Startup (); clgame.load_sequence++; // now all hud sprites are invalid diff --git a/engine/client/cl_video.c b/engine/client/cl_video.c index 7fbf37f6..76ebdb62 100644 --- a/engine/client/cl_video.c +++ b/engine/client/cl_video.c @@ -5,6 +5,7 @@ #include "common.h" #include "client.h" +#include "gl_local.h" #include // video for windows /* @@ -15,7 +16,6 @@ AVI PLAYING ================================================================= */ -convar_t *vid_gamma; static long xres, yres; static float video_duration; static float cin_time; @@ -133,13 +133,22 @@ SCR_RunCinematic */ void SCR_RunCinematic( void ) { + if( cls.state != ca_cinematic ) + return; + if( !AVI_IsActive( cin_state )) return; - if( vid_gamma->modified ) + if( UI_IsVisible( )) { - SCR_RebuildGammaTable(); - vid_gamma->modified = false; + // these can happens when user set +menu_ option to cmdline + AVI_CloseVideo( cin_state ); + cls.state = ca_disconnected; + Key_SetKeyDest( key_menu ); + S_StopStreaming(); + cls.movienum = -1; + cin_time = 0.0f; + return; } // advances cinematic time (ignores maxfps and host_framerate settings) @@ -170,7 +179,7 @@ qboolean SCR_DrawCinematic( void ) qboolean redraw = false; byte *frame = NULL; - if( cin_time <= 0.0f ) + if( !glw_state.initialized || cin_time <= 0.0f ) return false; if( cin_frame != last_frame ) @@ -275,9 +284,6 @@ SCR_InitCinematic void SCR_InitCinematic( void ) { AVIFileInit(); - - // used for movie gamma correction - vid_gamma = Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE, "gamma amount" ); cin_state = AVI_GetState( CIN_MAIN ); SCR_RebuildGammaTable(); diff --git a/engine/client/cl_view.c b/engine/client/cl_view.c index d2abe20a..68e9f6e3 100644 --- a/engine/client/cl_view.c +++ b/engine/client/cl_view.c @@ -87,26 +87,6 @@ void V_SetupRefDef( void ) } } -/* -=============== -V_ApplyRefDef - -apply pre-calculated values -=============== -*/ -void V_AddViewModel( void ) -{ - // add viewmodel only at firstperson pass when game not paused - if( cl.refdef.nextView || cl.refdef.paused || cl.thirdperson || cl.refdef.health <= 0 ) - return; - - // make sure what frame is valid and viewmodel is set - if( !cl.frame.valid || !clgame.viewent.model || cl.refdef.viewentity != ( cl.playernum + 1 )) - return; - - CL_AddVisibleEntity( &clgame.viewent, ET_NORMAL ); -} - /* =============== V_CalcRefDef @@ -119,7 +99,6 @@ void V_CalcRefDef( void ) do { clgame.dllFuncs.pfnCalcRefdef( &cl.refdef ); - V_AddViewModel(); R_RenderFrame( &cl.refdef, true ); cl.refdef.onlyClientDraw = false; } while( cl.refdef.nextView ); @@ -206,8 +185,8 @@ void V_PostRender( void ) CL_DrawDemoRecording(); R_ShowTextures(); CL_DrawHUD( CL_CHANGELEVEL ); - UI_UpdateMenu( host.realtime ); Con_DrawConsole(); + UI_UpdateMenu( host.realtime ); S_ExtraUpdate(); } diff --git a/engine/client/client.h b/engine/client/client.h index 0b0d4383..c126bebf 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -593,6 +593,7 @@ void CL_Download_f( void ); // void SCR_VidInit( void ); void SCR_EndLoadingPlaque( void ); +void SCR_RebuildGammaTable( void ); void SCR_RegisterShaders( void ); void SCR_MakeScreenShot( void ); void SCR_MakeLevelShot( void ); diff --git a/engine/client/gl_backend.c b/engine/client/gl_backend.c index 33a6a2b4..1c484af0 100644 --- a/engine/client/gl_backend.c +++ b/engine/client/gl_backend.c @@ -425,6 +425,10 @@ void GL_SetRenderMode( int mode ) { int state, texEnv; + // GoldSrc in 2D mode uses default mode as TransTexture + if( glState.in2DMode && mode == kRenderNormal ) + mode = kRenderTransTexture; + switch( mode ) { case kRenderNormal: @@ -434,7 +438,7 @@ void GL_SetRenderMode( int mode ) break; case kRenderTransColor: state = GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR|GLSTATE_DEPTHWRITE; - texEnv = GL_DECAL; + texEnv = GL_REPLACE; break; case kRenderTransAlpha: state = GLSTATE_AFUNC_GE128|GLSTATE_DEPTHWRITE; diff --git a/engine/client/gl_decals.c b/engine/client/gl_decals.c index 9ee2a98e..ff7333b3 100644 --- a/engine/client/gl_decals.c +++ b/engine/client/gl_decals.c @@ -658,7 +658,7 @@ static void R_DecalNodeSurfaces( model_t *model, mnode_t *node, decalinfo_t *dec for( i = 0; i < node->numsurfaces; i++, surf++ ) { // never apply decals on the water or sky surfaces - if( surf->flags & (SURF_DRAWTURB|SURF_DRAWSKY)) + if( surf->flags & (SURF_DRAWTURB|SURF_DRAWSKY|SURF_TRANSPARENT|SURF_CONVEYOR)) continue; R_DecalSurface( surf, decalinfo ); @@ -862,7 +862,7 @@ void DrawSurfaceDecals( msurface_t *fa ) oldState = glState.flags; oldTexEnv = glState.currentEnvModes[glState.activeTMU]; GL_SetState( GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_OFFSET_FILL ); - GL_TexEnv( GL_REPLACE ); + GL_TexEnv( GL_MODULATE ); // receive renderamt from bmodels for( p = fa->pdecals; p; p = p->pnext ) DrawSingleDecal( p, fa ); diff --git a/engine/client/gl_draw.c b/engine/client/gl_draw.c index 14eeebbb..68f17659 100644 --- a/engine/client/gl_draw.c +++ b/engine/client/gl_draw.c @@ -88,8 +88,8 @@ void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, c int width = 1, height = 1; // check the dimensions - while( width < cols ) width <<= 1; - while( height < rows ) height <<= 1; + width = NearestPOW( cols, true ); + height = NearestPOW( rows, false ); if( cols != width || rows != height ) { @@ -109,7 +109,7 @@ void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, c Host_Error( "R_DrawStretchRaw: size %i exceeds hardware limits\n", rows ); tex = R_GetTexture( tr.cinTexture ); - GL_Bind( 0, tr.cinTexture ); + GL_Bind( GL_TEXTURE0, tr.cinTexture ); if( cols == tex->width && rows == tex->height ) { diff --git a/engine/client/gl_image.c b/engine/client/gl_image.c index 41bdd27e..5ca1d54e 100644 --- a/engine/client/gl_image.c +++ b/engine/client/gl_image.c @@ -1159,10 +1159,10 @@ R_InitCinematicTexture */ static rgbdata_t *R_InitCinematicTexture( texFlags_t *flags ) { - r_image.width = r_image.height = 256; r_image.buffer = data2D; r_image.type = PF_RGBA_32; - r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA; + r_image.flags = IMAGE_HAS_COLOR; + r_image.width = r_image.height = 256; r_image.size = r_image.width * r_image.height * 4; *flags = TF_NOMIPMAP|TF_NOPICMIP|TF_UNCOMPRESSED|TF_CLAMP; diff --git a/engine/client/gl_local.h b/engine/client/gl_local.h index fbaf7a18..658cae7c 100644 --- a/engine/client/gl_local.h +++ b/engine/client/gl_local.h @@ -520,8 +520,6 @@ extern glwstate_t glw_state; extern convar_t *gl_allow_software; extern convar_t *gl_texture_anisotropy; extern convar_t *gl_extensions; -extern convar_t *gl_colorbits; -extern convar_t *gl_depthbits; extern convar_t *gl_stencilbits; extern convar_t *gl_texturebits; extern convar_t *gl_ignorehwgamma; diff --git a/engine/client/gl_rmain.c b/engine/client/gl_rmain.c index dc65276d..b4d5014e 100644 --- a/engine/client/gl_rmain.c +++ b/engine/client/gl_rmain.c @@ -368,11 +368,6 @@ static void R_Clear( int bitMask ) if( bits & GL_STENCIL_BUFFER_BIT ) pglClearStencil( 128 ); - if( bits & GL_COLOR_BUFFER_BIT ) - { - pglClearColor( 0.5f, 0.5f, 0.5f, 1.0f ); - } - pglClear( bits ); gldepthmin = 0.0f; @@ -742,6 +737,9 @@ void R_DrawEntitiesOnList( void ) CL_DrawParticles(); clgame.dllFuncs.pfnDrawTransparentTriangles (); + + // FIXME: allow to brush and sprite viewmodel ? + R_DrawViewModel(); } /* @@ -784,9 +782,8 @@ R_BeginFrame */ void R_BeginFrame( qboolean clearScene ) { - if( gl_clear->integer && clearScene ) + if( gl_clear->integer && clearScene && cls.state != ca_cinematic ) { - pglClearColor( 0.5f, 0.5f, 0.5f, 1.0f ); pglClear( GL_COLOR_BUFFER_BIT ); } diff --git a/engine/client/gl_sprite.c b/engine/client/gl_sprite.c index 6f3787da..52d22437 100644 --- a/engine/client/gl_sprite.c +++ b/engine/client/gl_sprite.c @@ -173,7 +173,7 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer ) pal = FS_LoadImage( "#normal.pal", src, 768 ); break; case SPR_INDEXALPHA: - pal = FS_LoadImage( "#decal.pal", src, 768 ); + pal = FS_LoadImage( "#indexalpha.pal", src, 768 ); break; case SPR_ALPHTEST: pal = FS_LoadImage( "#transparent.pal", src, 768 ); @@ -938,9 +938,6 @@ void R_DrawSpriteModel( cl_entity_t *e ) break; } - if( e->curstate.rendermode == kRenderGlow ) - pglDepthRange( gldepthmin, gldepthmin + 0.3f * ( gldepthmax - gldepthmin )); - if( psprite->facecull == SPR_CULL_NONE ) GL_Cull( GL_NONE ); @@ -969,9 +966,6 @@ void R_DrawSpriteModel( cl_entity_t *e ) } } - if( e->curstate.rendermode == kRenderGlow ) - pglDepthRange( gldepthmin, gldepthmax ); - if( psprite->facecull == SPR_CULL_NONE ) GL_Cull( GL_FRONT ); diff --git a/engine/client/gl_studio.c b/engine/client/gl_studio.c index 83314537..4b72b421 100644 --- a/engine/client/gl_studio.c +++ b/engine/client/gl_studio.c @@ -43,6 +43,7 @@ typedef struct studiolight_s convar_t *r_studio_lerping; convar_t *r_studio_lambert; +convar_t *r_drawviewmodel; convar_t *cl_himodels; char model_name[64]; static r_studio_interface_t *pStudioDraw; @@ -90,6 +91,7 @@ void R_StudioInit( void ) r_studio_lambert = Cvar_Get( "r_studio_lambert", "2", CVAR_ARCHIVE, "bonelighting lambert value" ); r_studio_lerping = Cvar_Get( "r_studio_lerping", "1", CVAR_ARCHIVE, "enables studio animation lerping" ); + r_drawviewmodel = Cvar_Get( "r_drawviewmodel", "1", 0, "draw firstperson weapon model" ); cl_himodels = Cvar_Get( "cl_himodels", "1", CVAR_ARCHIVE, "draw high-resolution player models in multiplayer" ); // recalc software X and Y alias scale (this stuff is used only by HL software renderer but who knews...) @@ -1994,6 +1996,7 @@ static void R_StudioSetupRenderer( int rendermode ) } g_iRenderMode = bound( 0, rendermode, kRenderTransInverse + 1 ); + pglShadeModel( GL_SMOOTH ); // enable gouraud shading } /* @@ -2016,6 +2019,7 @@ static void R_StudioRestoreRenderer( void ) GL_SetRenderMode( kRenderNormal ); pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); pglScalef( 1.0f, 1.0f, 1.0f ); + pglShadeModel( GL_FLAT ); } /* @@ -2567,6 +2571,30 @@ void R_RunViewmodelEvents( void ) RI.currentmodel = NULL; } +/* +================= +R_DrawViewModel +================= +*/ +void R_DrawViewModel( void ) +{ + if( RI.refdef.onlyClientDraw || r_drawviewmodel->integer == 0 ) + return; + + // ignore in thirdperson, camera view or client is died + if( cl.thirdperson || cl.refdef.health <= 0 || cl.refdef.viewentity != ( cl.playernum + 1 )) + return; + + RI.currententity = &clgame.viewent; + RI.currentmodel = RI.currententity->model; + if( !RI.currentmodel ) return; + + pStudioDraw->StudioDrawModel( STUDIO_RENDER ); + + RI.currententity = NULL; + RI.currentmodel = NULL; +} + /* ==================== R_StudioLoadTexture diff --git a/engine/client/gl_vidnt.c b/engine/client/gl_vidnt.c index e939ce6e..51c6b0c6 100644 --- a/engine/client/gl_vidnt.c +++ b/engine/client/gl_vidnt.c @@ -9,18 +9,16 @@ #include "cm_local.h" #include "input.h" -#define MAX_PFDS 256 #define VID_DEFAULTMODE "1" #define num_vidmodes ((int)(sizeof(vidmode) / sizeof(vidmode[0])) - 1) #define WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_SYSMENU|WS_CAPTION|WS_VISIBLE) #define WINDOW_EX_STYLE (0) #define GL_DRIVER_OPENGL "OpenGL32" +convar_t *renderinfo; convar_t *gl_allow_software; convar_t *gl_extensions; -convar_t *gl_colorbits; convar_t *gl_alphabits; -convar_t *gl_depthbits; convar_t *gl_stencilbits; convar_t *gl_texturebits; convar_t *gl_ignorehwgamma; @@ -39,6 +37,8 @@ convar_t *gl_finish; convar_t *gl_clear; convar_t *gl_test; +convar_t *r_xpos; +convar_t *r_ypos; convar_t *r_width; convar_t *r_height; convar_t *r_speeds; @@ -490,23 +490,18 @@ void GL_CheckExtension( const char *name, const dllfunc_t *funcs, const char *cv MsgDev( D_NOTE, "GL_CheckExtension: %s ", name ); - if( gl_extensions->integer == 0 && r_ext != GL_OPENGL_110 ) - { - MsgDev( D_NOTE, "- disabled\n" ); - GL_SetExtension( r_ext, 0 ); // update render info - return; - } - if( cvarname ) { // system config disable extensions - parm = Cvar_Get( cvarname, "1", CVAR_RENDERINFO, va( "enable or disable %s", name )); - GL_SetExtension( r_ext, parm->integer ); // update render info - if( parm->integer == 0 ) + parm = Cvar_Get( cvarname, "1", CVAR_GLCONFIG, va( "enable or disable %s", name )); + + if( parm->integer == 0 || ( gl_extensions->integer == 0 && r_ext != GL_OPENGL_110 )) { MsgDev( D_NOTE, "- disabled\n" ); + GL_SetExtension( r_ext, 0 ); return; // nothing to process at } + GL_SetExtension( r_ext, 1 ); } if(( name[2] == '_' || name[3] == '_' ) && !com.strstr( glConfig.extensions_string, name )) @@ -676,139 +671,57 @@ qboolean GL_DeleteContext( void ) VID_ChoosePFD ================= */ -static int VID_ChoosePFD( int colorBits, int alphaBits, int depthBits, int stencilBits ) +static int VID_ChoosePFD( PIXELFORMATDESCRIPTOR *pfd, int colorBits, int alphaBits, int depthBits, int stencilBits ) { - PIXELFORMATDESCRIPTOR PFDs[MAX_PFDS], *current, *selected; - uint flags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER; - int i, numPFDs, pixelFormat = 0; + int pixelFormat = 0; MsgDev( D_NOTE, "VID_ChoosePFD( color %i, alpha %i, depth %i, stencil %i )\n", colorBits, alphaBits, depthBits, stencilBits ); + // Fill out the PFD + pfd->nSize = sizeof (PIXELFORMATDESCRIPTOR); + pfd->nVersion = 1; + pfd->dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER; + pfd->iPixelType = PFD_TYPE_RGBA; + + pfd->cColorBits = colorBits; + pfd->cRedBits = 0; + pfd->cRedShift = 0; + pfd->cGreenBits = 0; + pfd->cGreenShift = 0; + pfd->cBlueBits = 0; + pfd->cBlueShift = 0; // wow! Blue Shift %) + + pfd->cAlphaBits = alphaBits; + pfd->cAlphaShift = 0; + + pfd->cAccumBits = 0; + pfd->cAccumRedBits = 0; + pfd->cAccumGreenBits = 0; + pfd->cAccumBlueBits = 0; + pfd->cAccumAlphaBits= 0; + + pfd->cDepthBits = depthBits; + pfd->cStencilBits = stencilBits; + + pfd->cAuxBuffers = 0; + pfd->iLayerType = PFD_MAIN_PLANE; + pfd->bReserved = 0; + + pfd->dwLayerMask = 0; + pfd->dwVisibleMask = 0; + pfd->dwDamageMask = 0; + // Count PFDs if( glw_state.minidriver ) - numPFDs = pwglDescribePixelFormat( glw_state.hDC, 0, 0, NULL ); - else numPFDs = DescribePixelFormat( glw_state.hDC, 0, 0, NULL ); - - if( numPFDs > MAX_PFDS ) - { - MsgDev( D_NOTE, "too many PFDs returned (%i > %i), reduce it\n", numPFDs, MAX_PFDS ); - numPFDs = MAX_PFDS; - } - else if( numPFDs < 1 ) - { - MsgDev( D_ERROR, "VID_ChoosePFD failed\n" ); - return 0; - } - - // run through all the PFDs, looking for the best match - for( i = 1, current = PFDs; i <= numPFDs; i++, current++ ) - { - if( glw_state.minidriver ) - pwglDescribePixelFormat( glw_state.hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), current ); - else DescribePixelFormat( glw_state.hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), current ); - - // check acceleration - if(( current->dwFlags & PFD_GENERIC_FORMAT ) && !gl_allow_software->integer ) - continue; - - // check flags - if(( current->dwFlags & flags ) != flags ) - continue; - - // check pixel type - if( current->iPixelType != PFD_TYPE_RGBA ) - continue; - - // check color bits - if( current->cColorBits < colorBits ) - continue; - - // check alpha bits - if( current->cAlphaBits < alphaBits ) - continue; - - // check depth bits - if( current->cDepthBits < depthBits ) - continue; - - // check stencil bits - if( current->cStencilBits < stencilBits ) - continue; - - // if we don't have a selected PFD yet, then use it - if( !pixelFormat ) - { - selected = current; - pixelFormat = i; - continue; - } - - if( colorBits != selected->cColorBits ) - { - if( colorBits == current->cColorBits || current->cColorBits > selected->cColorBits ) - { - selected = current; - pixelFormat = i; - continue; - } - } - - if( alphaBits != selected->cAlphaBits ) - { - if( alphaBits == current->cAlphaBits || current->cAlphaBits > selected->cAlphaBits ) - { - selected = current; - pixelFormat = i; - continue; - } - } - - if( depthBits != selected->cDepthBits ) - { - if( depthBits == current->cDepthBits || current->cDepthBits > selected->cDepthBits ) - { - selected = current; - pixelFormat = i; - continue; - } - } - - if( stencilBits != selected->cStencilBits ) - { - if( stencilBits == current->cStencilBits || current->cStencilBits > selected->cStencilBits ) - { - selected = current; - pixelFormat = i; - continue; - } - } - } + pixelFormat = pwglChoosePixelFormat( glw_state.hDC, pfd ); + else pixelFormat = ChoosePixelFormat( glw_state.hDC, pfd ); if( !pixelFormat ) { - MsgDev( D_ERROR, "VID_ChoosePFD: no hardware acceleration found\n" ); + MsgDev( D_ERROR, "VID_ChoosePFD failed\n" ); return 0; } - if( selected->dwFlags & PFD_GENERIC_FORMAT ) - { - if( selected->dwFlags & PFD_GENERIC_ACCELERATED ) - { - MsgDev( D_NOTE, "VID_ChoosePFD: usign Generic MCD acceleration\n" ); - glw_state.software = false; - } - else - { - MsgDev( D_NOTE, "VID_ChoosePFD: using software emulation\n" ); - glw_state.software = true; - } - } - else - { - MsgDev( D_NOTE, "VID_ChoosePFD: using hardware acceleration\n"); - glw_state.software = false; - } - return pixelFormat; } @@ -905,8 +818,8 @@ GL_SetPixelformat qboolean GL_SetPixelformat( void ) { PIXELFORMATDESCRIPTOR PFD; - int colorBits, alphaBits; - int depthBits, stencilBits; + int alphaBits; + int stencilBits; int pixelFormat; if( glw_state.minidriver ) @@ -920,21 +833,17 @@ qboolean GL_SetPixelformat( void ) return false; } - // set color/depth/stencil - colorBits = (gl_colorbits->integer) ? gl_colorbits->integer : 32; - depthBits = (gl_depthbits->integer) ? gl_depthbits->integer : 24; - alphaBits = (gl_alphabits->integer) ? gl_alphabits->integer : 8; - stencilBits = (gl_stencilbits->integer) ? gl_stencilbits->integer : 0; + // set alpha/stencil + alphaBits = bound( 0, gl_alphabits->integer, 8 ); + stencilBits = bound( 0, gl_stencilbits->integer, 8 ); // choose a pixel format - pixelFormat = VID_ChoosePFD( colorBits, alphaBits, depthBits, stencilBits ); + pixelFormat = VID_ChoosePFD( &PFD, 32, alphaBits, 24, stencilBits ); if( !pixelFormat ) { // try again with default color/depth/stencil - if( colorBits > 16 || depthBits > 16 || alphaBits > 0 || stencilBits > 0 ) - pixelFormat = VID_ChoosePFD( 16, 0, 16, 0 ); - else pixelFormat = VID_ChoosePFD( 32, 0, 24, 0 ); + pixelFormat = VID_ChoosePFD( &PFD, 32, 0, 24, 0 ); if( !pixelFormat ) { @@ -946,23 +855,47 @@ qboolean GL_SetPixelformat( void ) // set the pixel format if( glw_state.minidriver ) { - pwglDescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD ); - if( !pwglSetPixelFormat( glw_state.hDC, pixelFormat, &PFD )) { MsgDev( D_ERROR, "GL_SetPixelformat: failed\n" ); return false; } + + pwglDescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD ); } else { - DescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD ); - if( !SetPixelFormat( glw_state.hDC, pixelFormat, &PFD )) { MsgDev( D_ERROR, "GL_SetPixelformat: failed\n" ); return false; } + + DescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD ); + } + + if( PFD.dwFlags & PFD_GENERIC_FORMAT ) + { + if( PFD.dwFlags & PFD_GENERIC_ACCELERATED ) + { + MsgDev( D_NOTE, "VID_ChoosePFD: usign Generic MCD acceleration\n" ); + glw_state.software = false; + } + else if( gl_allow_software->integer ) + { + MsgDev( D_NOTE, "VID_ChoosePFD: using software emulation\n" ); + glw_state.software = true; + } + else + { + MsgDev( D_ERROR, "GL_SetPixelformat: no hardware acceleration found\n" ); + return false; + } + } + else + { + MsgDev( D_NOTE, "VID_ChoosePFD: using hardware acceleration\n"); + glw_state.software = false; } glConfig.color_bits = PFD.cColorBits; @@ -999,7 +932,6 @@ qboolean VID_CreateWindow( int width, int height, qboolean fullscreen ) { WNDCLASS wc; RECT rect; - convar_t *r_xpos, *r_ypos; int x = 0, y = 0, w, h; int stylebits = WINDOW_STYLE; int exstyle = WINDOW_EX_STYLE; @@ -1057,8 +989,6 @@ qboolean VID_CreateWindow( int width, int height, qboolean fullscreen ) if( !fullscreen ) { - r_xpos = Cvar_Get( "r_xpos", "130", CVAR_RENDERINFO, "window position by horizontal" ); - r_ypos = Cvar_Get( "r_ypos", "48", CVAR_RENDERINFO, "window position by vertical" ); x = r_xpos->integer; y = r_ypos->integer; @@ -1087,7 +1017,7 @@ qboolean VID_CreateWindow( int width, int height, qboolean fullscreen ) MsgDev( D_ERROR, "VID_CreateWindow: couldn't create '%s'\n", wndname ); return false; } - + ShowWindow( host.hWnd, SW_SHOW ); UpdateWindow( host.hWnd ); @@ -1181,6 +1111,9 @@ rserr_t R_ChangeDisplaySettings( int vid_mode, qboolean fullscreen ) if( vid_displayfrequency->integer > 0 ) { + if( vid_displayfrequency->integer < 60 ) Cvar_SetFloat( "vid_displayfrequency", 60 ); + if( vid_displayfrequency->integer > 100 ) Cvar_SetFloat( "vid_displayfrequency", 100 ); + dm.dmFields |= DM_DISPLAYFREQUENCY; dm.dmDisplayFrequency = vid_displayfrequency->integer; } @@ -1198,11 +1131,8 @@ rserr_t R_ChangeDisplaySettings( int vid_mode, qboolean fullscreen ) dm.dmPelsWidth = width * 2; dm.dmPelsHeight = height; dm.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT; - if( gl_depthbits->integer != 0 ) - { - dm.dmBitsPerPel = gl_depthbits->integer; - dm.dmFields |= DM_BITSPERPEL; - } + dm.dmBitsPerPel = 24; + dm.dmFields |= DM_BITSPERPEL; // our first CDS failed, so maybe we're running on some weird dual monitor system if( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL ) @@ -1245,8 +1175,6 @@ qboolean VID_SetMode( void ) qboolean fullscreen; fullscreen = vid_fullscreen->integer; - vid_fullscreen->modified = false; - vid_mode->modified = false; if(( err = R_ChangeDisplaySettings( vid_mode->integer, fullscreen )) == rserr_ok ) { @@ -1257,7 +1185,6 @@ qboolean VID_SetMode( void ) if( err == rserr_invalid_fullscreen ) { Cvar_SetFloat( "fullscreen", 0 ); - vid_fullscreen->modified = false; MsgDev( D_ERROR, "VID_SetMode: fullscreen unavailable in this mode\n" ); if(( err = R_ChangeDisplaySettings( vid_mode->integer, false )) == rserr_ok ) return true; @@ -1266,7 +1193,6 @@ qboolean VID_SetMode( void ) { Cvar_SetFloat( "vid_mode", glConfig.prev_mode ); MsgDev( D_ERROR, "VID_SetMode: invalid mode\n" ); - vid_mode->modified = false; } // try setting it back to something safe @@ -1288,7 +1214,7 @@ check vid modes and fullscreen */ void VID_CheckChanges( void ) { - if( vid_fullscreen->modified || vid_mode->modified ) + if( renderinfo->modified ) { if( !VID_SetMode()) { @@ -1297,8 +1223,7 @@ void VID_CheckChanges( void ) } else { - vid_fullscreen->modified = false; - vid_mode->modified = false; + renderinfo->modified = false; SCR_VidInit(); // tell the client.dll what vid_mode has changed } } @@ -1366,9 +1291,6 @@ static void GL_SetDefaults( void ) pglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); } - // enable gouraud shading - pglShadeModel( GL_SMOOTH ); - pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); pglPolygonOffset( -1, -2 ); @@ -1448,6 +1370,7 @@ void GL_InitCommands( void ) // system screen width and height (don't suppose for change from console at all) r_width = Cvar_Get( "width", "640", CVAR_READ_ONLY, "screen width" ); r_height = Cvar_Get( "height", "480", CVAR_READ_ONLY, "screen height" ); + renderinfo = Cvar_Get( "@renderinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only r_speeds = Cvar_Get( "r_speeds", "0", CVAR_ARCHIVE, "shows renderer speeds" ); r_fullbright = Cvar_Get( "r_fullbright", "0", CVAR_CHEAT, "disable lightmaps, get fullbright for entities" ); r_norefresh = Cvar_Get( "r_norefresh", "0", 0, "disable 3D rendering (use with caution)" ); @@ -1468,21 +1391,21 @@ void GL_InitCommands( void ) r_drawentities = Cvar_Get( "r_drawentities", "1", CVAR_CHEAT|CVAR_ARCHIVE, "render entities" ); r_lefthand = Cvar_Get( "hand", "0", CVAR_ARCHIVE, "viewmodel handedness" ); r_decals = Cvar_Get( "r_decals", "4096", CVAR_ARCHIVE, "sets the maximum number of decals" ); - - gl_picmip = Cvar_Get( "gl_picmip", "0", CVAR_RENDERINFO|CVAR_LATCH_VIDEO, "reduces resolution of textures by powers of 2" ); - gl_skymip = Cvar_Get( "gl_skymip", "0", CVAR_RENDERINFO|CVAR_LATCH_VIDEO, "reduces resolution of skybox textures by powers of 2" ); + r_xpos = Cvar_Get( "r_xpos", "130", CVAR_GLCONFIG, "window position by horizontal" ); + r_ypos = Cvar_Get( "r_ypos", "48", CVAR_GLCONFIG, "window position by vertical" ); + + gl_picmip = Cvar_Get( "gl_picmip", "0", CVAR_GLCONFIG, "reduces resolution of textures by powers of 2" ); + gl_skymip = Cvar_Get( "gl_skymip", "0", CVAR_GLCONFIG, "reduces resolution of skybox textures by powers of 2" ); gl_ignorehwgamma = Cvar_Get( "gl_ignorehwgamma", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "ignore hardware gamma (e.g. not support)" ); gl_allow_software = Cvar_Get( "gl_allow_software", "0", CVAR_ARCHIVE, "allow OpenGL software emulation" ); - gl_colorbits = Cvar_Get( "gl_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH_VIDEO, "pixelformat color bits (0 - auto)" ); - gl_alphabits = Cvar_Get( "gl_alphabits", "0", CVAR_ARCHIVE | CVAR_LATCH_VIDEO, "pixelformat alpha bits (0 - auto)" ); - gl_depthbits = Cvar_Get( "gl_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH_VIDEO, "pixelformat depth bits (0 - auto)" ); + gl_alphabits = Cvar_Get( "gl_alphabits", "8", CVAR_GLCONFIG, "pixelformat alpha bits (0 - auto)" ); gl_texturemode = Cvar_Get( "gl_texturemode", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE, "texture filter" ); - gl_texturebits = Cvar_Get( "gl_texturebits", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "set texture upload format (0 - auto)" ); - gl_round_down = Cvar_Get( "gl_round_down", "0", CVAR_RENDERINFO, "down size non-power of two textures" ); - gl_stencilbits = Cvar_Get( "gl_stencilbits", "8", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "pixelformat stencil bits (0 - auto)" ); + gl_texturebits = Cvar_Get( "gl_texturebits", "0", CVAR_GLCONFIG, "set texture upload format (0 - auto)" ); + gl_round_down = Cvar_Get( "gl_round_down", "0", CVAR_GLCONFIG, "down size non-power of two textures" ); + gl_stencilbits = Cvar_Get( "gl_stencilbits", "8", CVAR_GLCONFIG, "pixelformat stencil bits (0 - auto)" ); gl_check_errors = Cvar_Get( "gl_check_errors", "1", CVAR_ARCHIVE, "ignore video engine errors" ); gl_swapInterval = Cvar_Get( "gl_swapInterval", "0", CVAR_ARCHIVE, "time beetween frames (in msec)" ); - gl_extensions = Cvar_Get( "gl_extensions", "1", CVAR_RENDERINFO, "allow gl_extensions" ); + gl_extensions = Cvar_Get( "gl_extensions", "1", CVAR_GLCONFIG, "allow gl_extensions" ); gl_texture_anisotropy = Cvar_Get( "r_anisotropy", "2.0", CVAR_ARCHIVE, "textures anisotropic filter" ); gl_nobind = Cvar_Get( "gl_nobind", "0", 0, "replace all textures with '*notexture' (perfomance test)" ); gl_texture_lodbias = Cvar_Get( "gl_texture_lodbias", "0.0", CVAR_ARCHIVE, "LOD bias for mipmapped textures" ); @@ -1496,9 +1419,9 @@ void GL_InitCommands( void ) gl_swapInterval->modified = true; vid_gamma = Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE, "gamma amount" ); - vid_mode = Cvar_Get( "vid_mode", VID_DEFAULTMODE, CVAR_ARCHIVE, "display resolution mode" ); + vid_mode = Cvar_Get( "vid_mode", VID_DEFAULTMODE, CVAR_RENDERINFO, "display resolution mode" ); vid_fullscreen = Cvar_Get( "fullscreen", "0", CVAR_RENDERINFO, "set in 1 to enable fullscreen mode" ); - vid_displayfrequency = Cvar_Get ( "vid_displayfrequency", "0", CVAR_RENDERINFO|CVAR_LATCH_VIDEO, "fullscreen refresh rate" ); + vid_displayfrequency = Cvar_Get ( "vid_displayfrequency", "0", CVAR_RENDERINFO, "fullscreen refresh rate" ); Cmd_AddCommand( "r_info", R_RenderInfo_f, "display renderer info" ); Cmd_AddCommand( "texturelist", R_TextureList_f, "display loaded textures list" ); @@ -1696,6 +1619,7 @@ qboolean R_Init( void ) return false; } + renderinfo->modified = false; r_temppool = Mem_AllocPool( "Render Zone" ); GL_InitExtensions(); diff --git a/engine/client/sound/s_main.c b/engine/client/sound/s_main.c index 16479113..73329907 100644 --- a/engine/client/sound/s_main.c +++ b/engine/client/sound/s_main.c @@ -933,8 +933,6 @@ qboolean S_Init( void ) return false; } - Cmd_ExecuteString( "sndlatch\n" ); - s_volume = Cvar_Get( "volume", "0.7", CVAR_ARCHIVE, "sound volume" ); s_musicvolume = Cvar_Get( "musicvolume", "1.0", CVAR_ARCHIVE, "background music volume" ); s_mixahead = Cvar_Get( "_snd_mixahead", "0.1", CVAR_ARCHIVE, "how much sound to mix ahead of time" ); diff --git a/engine/client/sound/s_mix.c b/engine/client/sound/s_mix.c index 00e94f45..42e46f9c 100644 --- a/engine/client/sound/s_mix.c +++ b/engine/client/sound/s_mix.c @@ -838,16 +838,10 @@ void MIX_MixPaintbuffers( int ibuf1, int ibuf2, int ibuf3, int count, float fgai // mix front channels for( i = 0; i < count; i++ ) { - pbuf3[i].left = pbuf1[i].left + pbuf2[i].left; - pbuf3[i].right = pbuf1[i].right + pbuf2[i].right; - } - - if( gain == 256 ) return; - - for( i = 0; i < count; i++ ) - { - pbuf3[i].left = (pbuf3[i].left * gain) >> 8; - pbuf3[i].right = (pbuf3[i].right * gain) >> 8; + pbuf3[i].left = pbuf1[i].left; + pbuf3[i].right = pbuf1[i].right; + pbuf3[i].left += (pbuf2[i].left * gain) >> 8; + pbuf3[i].right += (pbuf2[i].right * gain) >> 8; } } diff --git a/engine/client/Копия gl_vidnt.c b/engine/client/Копия gl_vidnt.c new file mode 100644 index 00000000..8304499d --- /dev/null +++ b/engine/client/Копия gl_vidnt.c @@ -0,0 +1,1818 @@ +//======================================================================= +// Copyright XashXT Group 2010 +// gl_vidnt.c - NT GL vid component +//======================================================================= + +#include "common.h" +#include "client.h" +#include "gl_local.h" +#include "cm_local.h" +#include "input.h" + +#define MAX_PFDS 600 +#define VID_DEFAULTMODE "1" +#define num_vidmodes ((int)(sizeof(vidmode) / sizeof(vidmode[0])) - 1) +#define WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_SYSMENU|WS_CAPTION|WS_VISIBLE) +#define WINDOW_EX_STYLE (0) +#define GL_DRIVER_OPENGL "OpenGL32" + +convar_t *renderinfo; +convar_t *gl_allow_software; +convar_t *gl_extensions; +convar_t *gl_colorbits; +convar_t *gl_alphabits; +convar_t *gl_depthbits; +convar_t *gl_stencilbits; +convar_t *gl_texturebits; +convar_t *gl_ignorehwgamma; +convar_t *gl_texture_anisotropy; +convar_t *gl_compress_textures; +convar_t *gl_texture_lodbias; +convar_t *gl_showtextures; +convar_t *gl_swapInterval; +convar_t *gl_check_errors; +convar_t *gl_texturemode; +convar_t *gl_round_down; +convar_t *gl_picmip; +convar_t *gl_skymip; +convar_t *gl_nobind; +convar_t *gl_finish; +convar_t *gl_clear; +convar_t *gl_test; + +convar_t *r_xpos; +convar_t *r_ypos; +convar_t *r_width; +convar_t *r_height; +convar_t *r_speeds; +convar_t *r_fullbright; +convar_t *r_norefresh; +convar_t *r_lighting_modulate; +convar_t *r_lighting_ambient; +convar_t *r_lighting_direct; +convar_t *r_faceplanecull; +convar_t *r_drawentities; +convar_t *r_adjust_fov; +convar_t *r_lefthand; +convar_t *r_decals; +convar_t *r_novis; +convar_t *r_nocull; +convar_t *r_lockpvs; +convar_t *r_lockcull; +convar_t *r_wateralpha; +convar_t *r_dynamic; +convar_t *r_lightmap; +convar_t *r_shadows; +convar_t *r_fastsky; + +convar_t *vid_displayfrequency; +convar_t *vid_fullscreen; +convar_t *vid_gamma; +convar_t *vid_mode; + +byte *r_temppool; + +ref_globals_t tr; +glconfig_t glConfig; +glstate_t glState; +glwstate_t glw_state; + +typedef enum +{ + rserr_ok, + rserr_invalid_fullscreen, + rserr_invalid_mode, + rserr_unknown +} rserr_t; + +typedef struct vidmode_s +{ + const char *desc; + int width; + int height; + qboolean wideScreen; +} vidmode_t; + +vidmode_t vidmode[] = +{ +{ "Mode 0: 4x3", 640, 480, false }, +{ "Mode 1: 4x3", 800, 600, false }, +{ "Mode 2: 4x3", 960, 720, false }, +{ "Mode 3: 4x3", 1024, 768, false }, +{ "Mode 4: 4x3", 1152, 864, false }, +{ "Mode 5: 4x3", 1280, 800, false }, +{ "Mode 6: 4x3", 1280, 960, false }, +{ "Mode 7: 4x3", 1280, 1024, false }, +{ "Mode 8: 4x3", 1600, 1200, false }, +{ "Mode 9: 4x3", 2048, 1536, false }, +{ "Mode 10: 16x9", 856, 480, true }, +{ "Mode 11: 16x9", 1024, 576, true }, +{ "Mode 12: 16x9", 1280, 720, true }, +{ "Mode 13: 16x9", 1360, 768, true }, +{ "Mode 14: 16x9", 1440, 900, true }, +{ "Mode 15: 16x9", 1680, 1050, true }, +{ "Mode 16: 16x9", 1920, 1200, true }, +{ "Mode 17: 16x9", 2560, 1600, true }, +{ NULL, 0, 0, 0 }, +}; + +static dllfunc_t opengl_110funcs[] = +{ +{ "glClearColor" , (void **)&pglClearColor }, +{ "glClear" , (void **)&pglClear }, +{ "glAlphaFunc" , (void **)&pglAlphaFunc }, +{ "glBlendFunc" , (void **)&pglBlendFunc }, +{ "glCullFace" , (void **)&pglCullFace }, +{ "glDrawBuffer" , (void **)&pglDrawBuffer }, +{ "glReadBuffer" , (void **)&pglReadBuffer }, +{ "glEnable" , (void **)&pglEnable }, +{ "glDisable" , (void **)&pglDisable }, +{ "glEnableClientState" , (void **)&pglEnableClientState }, +{ "glDisableClientState" , (void **)&pglDisableClientState }, +{ "glGetBooleanv" , (void **)&pglGetBooleanv }, +{ "glGetDoublev" , (void **)&pglGetDoublev }, +{ "glGetFloatv" , (void **)&pglGetFloatv }, +{ "glGetIntegerv" , (void **)&pglGetIntegerv }, +{ "glGetError" , (void **)&pglGetError }, +{ "glGetString" , (void **)&pglGetString }, +{ "glFinish" , (void **)&pglFinish }, +{ "glFlush" , (void **)&pglFlush }, +{ "glClearDepth" , (void **)&pglClearDepth }, +{ "glDepthFunc" , (void **)&pglDepthFunc }, +{ "glDepthMask" , (void **)&pglDepthMask }, +{ "glDepthRange" , (void **)&pglDepthRange }, +{ "glFrontFace" , (void **)&pglFrontFace }, +{ "glDrawElements" , (void **)&pglDrawElements }, +{ "glColorMask" , (void **)&pglColorMask }, +{ "glIndexPointer" , (void **)&pglIndexPointer }, +{ "glVertexPointer" , (void **)&pglVertexPointer }, +{ "glNormalPointer" , (void **)&pglNormalPointer }, +{ "glColorPointer" , (void **)&pglColorPointer }, +{ "glTexCoordPointer" , (void **)&pglTexCoordPointer }, +{ "glArrayElement" , (void **)&pglArrayElement }, +{ "glColor3f" , (void **)&pglColor3f }, +{ "glColor3fv" , (void **)&pglColor3fv }, +{ "glColor4f" , (void **)&pglColor4f }, +{ "glColor4fv" , (void **)&pglColor4fv }, +{ "glColor3ub" , (void **)&pglColor3ub }, +{ "glColor4ub" , (void **)&pglColor4ub }, +{ "glColor4ubv" , (void **)&pglColor4ubv }, +{ "glTexCoord1f" , (void **)&pglTexCoord1f }, +{ "glTexCoord2f" , (void **)&pglTexCoord2f }, +{ "glTexCoord3f" , (void **)&pglTexCoord3f }, +{ "glTexCoord4f" , (void **)&pglTexCoord4f }, +{ "glTexGenf" , (void **)&pglTexGenf }, +{ "glTexGenfv" , (void **)&pglTexGenfv }, +{ "glTexGeni" , (void **)&pglTexGeni }, +{ "glVertex2f" , (void **)&pglVertex2f }, +{ "glVertex3f" , (void **)&pglVertex3f }, +{ "glVertex3fv" , (void **)&pglVertex3fv }, +{ "glNormal3f" , (void **)&pglNormal3f }, +{ "glNormal3fv" , (void **)&pglNormal3fv }, +{ "glBegin" , (void **)&pglBegin }, +{ "glEnd" , (void **)&pglEnd }, +{ "glLineWidth" , (void**)&pglLineWidth }, +{ "glPointSize" , (void**)&pglPointSize }, +{ "glMatrixMode" , (void **)&pglMatrixMode }, +{ "glOrtho" , (void **)&pglOrtho }, +{ "glRasterPos2f" , (void **) &pglRasterPos2f }, +{ "glFrustum" , (void **)&pglFrustum }, +{ "glViewport" , (void **)&pglViewport }, +{ "glPushMatrix" , (void **)&pglPushMatrix }, +{ "glPopMatrix" , (void **)&pglPopMatrix }, +{ "glLoadIdentity" , (void **)&pglLoadIdentity }, +{ "glLoadMatrixd" , (void **)&pglLoadMatrixd }, +{ "glLoadMatrixf" , (void **)&pglLoadMatrixf }, +{ "glMultMatrixd" , (void **)&pglMultMatrixd }, +{ "glMultMatrixf" , (void **)&pglMultMatrixf }, +{ "glRotated" , (void **)&pglRotated }, +{ "glRotatef" , (void **)&pglRotatef }, +{ "glScaled" , (void **)&pglScaled }, +{ "glScalef" , (void **)&pglScalef }, +{ "glTranslated" , (void **)&pglTranslated }, +{ "glTranslatef" , (void **)&pglTranslatef }, +{ "glReadPixels" , (void **)&pglReadPixels }, +{ "glDrawPixels" , (void **)&pglDrawPixels }, +{ "glStencilFunc" , (void **)&pglStencilFunc }, +{ "glStencilMask" , (void **)&pglStencilMask }, +{ "glStencilOp" , (void **)&pglStencilOp }, +{ "glClearStencil" , (void **)&pglClearStencil }, +{ "glTexEnvf" , (void **)&pglTexEnvf }, +{ "glTexEnvfv" , (void **)&pglTexEnvfv }, +{ "glTexEnvi" , (void **)&pglTexEnvi }, +{ "glTexParameterf" , (void **)&pglTexParameterf }, +{ "glTexParameterfv" , (void **)&pglTexParameterfv }, +{ "glTexParameteri" , (void **)&pglTexParameteri }, +{ "glHint" , (void **)&pglHint }, +{ "glPixelStoref" , (void **)&pglPixelStoref }, +{ "glPixelStorei" , (void **)&pglPixelStorei }, +{ "glGenTextures" , (void **)&pglGenTextures }, +{ "glDeleteTextures" , (void **)&pglDeleteTextures }, +{ "glBindTexture" , (void **)&pglBindTexture }, +{ "glTexImage1D" , (void **)&pglTexImage1D }, +{ "glTexImage2D" , (void **)&pglTexImage2D }, +{ "glTexSubImage1D" , (void **)&pglTexSubImage1D }, +{ "glTexSubImage2D" , (void **)&pglTexSubImage2D }, +{ "glCopyTexImage1D" , (void **)&pglCopyTexImage1D }, +{ "glCopyTexImage2D" , (void **)&pglCopyTexImage2D }, +{ "glCopyTexSubImage1D" , (void **)&pglCopyTexSubImage1D }, +{ "glCopyTexSubImage2D" , (void **)&pglCopyTexSubImage2D }, +{ "glScissor" , (void **)&pglScissor }, +{ "glGetTexEnviv" , (void **)&pglGetTexEnviv }, +{ "glPolygonOffset" , (void **)&pglPolygonOffset }, +{ "glPolygonMode" , (void **)&pglPolygonMode }, +{ "glPolygonStipple" , (void **)&pglPolygonStipple }, +{ "glClipPlane" , (void **)&pglClipPlane }, +{ "glGetClipPlane" , (void **)&pglGetClipPlane }, +{ "glShadeModel" , (void **)&pglShadeModel }, +{ "glFogfv" , (void **)&pglFogfv }, +{ "glFogf" , (void **)&pglFogf }, +{ "glFogi" , (void **)&pglFogi }, +{ NULL, NULL } +}; + +static dllfunc_t pointparametersfunc[] = +{ +{ "glPointParameterfEXT" , (void **)&pglPointParameterfEXT }, +{ "glPointParameterfvEXT" , (void **)&pglPointParameterfvEXT }, +{ NULL, NULL } +}; + +static dllfunc_t drawrangeelementsfuncs[] = +{ +{ "glDrawRangeElements" , (void **)&pglDrawRangeElements }, +{ NULL, NULL } +}; + +static dllfunc_t drawrangeelementsextfuncs[] = +{ +{ "glDrawRangeElementsEXT" , (void **)&pglDrawRangeElementsEXT }, +{ NULL, NULL } +}; + +static dllfunc_t sgis_multitexturefuncs[] = +{ +{ "glSelectTextureSGIS" , (void **)&pglSelectTextureSGIS }, +{ "glMTexCoord2fSGIS" , (void **)&pglMTexCoord2fSGIS }, +{ NULL, NULL } +}; + +static dllfunc_t multitexturefuncs[] = +{ +{ "glMultiTexCoord1fARB" , (void **)&pglMultiTexCoord1f }, +{ "glMultiTexCoord2fARB" , (void **)&pglMultiTexCoord2f }, +{ "glMultiTexCoord3fARB" , (void **)&pglMultiTexCoord3f }, +{ "glMultiTexCoord4fARB" , (void **)&pglMultiTexCoord4f }, +{ "glActiveTextureARB" , (void **)&pglActiveTextureARB }, +{ "glClientActiveTextureARB" , (void **)&pglClientActiveTexture }, +{ "glClientActiveTextureARB" , (void **)&pglClientActiveTextureARB }, +{ NULL, NULL } +}; + +static dllfunc_t compiledvertexarrayfuncs[] = +{ +{ "glLockArraysEXT" , (void **)&pglLockArraysEXT }, +{ "glUnlockArraysEXT" , (void **)&pglUnlockArraysEXT }, +{ "glDrawArrays" , (void **)&pglDrawArrays }, +{ NULL, NULL } +}; + +static dllfunc_t texture3dextfuncs[] = +{ +{ "glTexImage3DEXT" , (void **)&pglTexImage3D }, +{ "glTexSubImage3DEXT" , (void **)&pglTexSubImage3D }, +{ "glCopyTexSubImage3DEXT" , (void **)&pglCopyTexSubImage3D }, +{ NULL, NULL } +}; + +static dllfunc_t atiseparatestencilfuncs[] = +{ +{ "glStencilOpSeparateATI" , (void **)&pglStencilOpSeparate }, +{ "glStencilFuncSeparateATI" , (void **)&pglStencilFuncSeparate }, +{ NULL, NULL } +}; + +static dllfunc_t gl2separatestencilfuncs[] = +{ +{ "glStencilOpSeparate" , (void **)&pglStencilOpSeparate }, +{ "glStencilFuncSeparate" , (void **)&pglStencilFuncSeparate }, +{ NULL, NULL } +}; + +static dllfunc_t stenciltwosidefuncs[] = +{ +{ "glActiveStencilFaceEXT" , (void **)&pglActiveStencilFaceEXT }, +{ NULL, NULL } +}; + +static dllfunc_t blendequationfuncs[] = +{ +{ "glBlendEquationEXT" , (void **)&pglBlendEquationEXT }, +{ NULL, NULL } +}; + +static dllfunc_t shaderobjectsfuncs[] = +{ +{ "glDeleteObjectARB" , (void **)&pglDeleteObjectARB }, +{ "glGetHandleARB" , (void **)&pglGetHandleARB }, +{ "glDetachObjectARB" , (void **)&pglDetachObjectARB }, +{ "glCreateShaderObjectARB" , (void **)&pglCreateShaderObjectARB }, +{ "glShaderSourceARB" , (void **)&pglShaderSourceARB }, +{ "glCompileShaderARB" , (void **)&pglCompileShaderARB }, +{ "glCreateProgramObjectARB" , (void **)&pglCreateProgramObjectARB }, +{ "glAttachObjectARB" , (void **)&pglAttachObjectARB }, +{ "glLinkProgramARB" , (void **)&pglLinkProgramARB }, +{ "glUseProgramObjectARB" , (void **)&pglUseProgramObjectARB }, +{ "glValidateProgramARB" , (void **)&pglValidateProgramARB }, +{ "glUniform1fARB" , (void **)&pglUniform1fARB }, +{ "glUniform2fARB" , (void **)&pglUniform2fARB }, +{ "glUniform3fARB" , (void **)&pglUniform3fARB }, +{ "glUniform4fARB" , (void **)&pglUniform4fARB }, +{ "glUniform1iARB" , (void **)&pglUniform1iARB }, +{ "glUniform2iARB" , (void **)&pglUniform2iARB }, +{ "glUniform3iARB" , (void **)&pglUniform3iARB }, +{ "glUniform4iARB" , (void **)&pglUniform4iARB }, +{ "glUniform1fvARB" , (void **)&pglUniform1fvARB }, +{ "glUniform2fvARB" , (void **)&pglUniform2fvARB }, +{ "glUniform3fvARB" , (void **)&pglUniform3fvARB }, +{ "glUniform4fvARB" , (void **)&pglUniform4fvARB }, +{ "glUniform1ivARB" , (void **)&pglUniform1ivARB }, +{ "glUniform2ivARB" , (void **)&pglUniform2ivARB }, +{ "glUniform3ivARB" , (void **)&pglUniform3ivARB }, +{ "glUniform4ivARB" , (void **)&pglUniform4ivARB }, +{ "glUniformMatrix2fvARB" , (void **)&pglUniformMatrix2fvARB }, +{ "glUniformMatrix3fvARB" , (void **)&pglUniformMatrix3fvARB }, +{ "glUniformMatrix4fvARB" , (void **)&pglUniformMatrix4fvARB }, +{ "glGetObjectParameterfvARB" , (void **)&pglGetObjectParameterfvARB }, +{ "glGetObjectParameterivARB" , (void **)&pglGetObjectParameterivARB }, +{ "glGetInfoLogARB" , (void **)&pglGetInfoLogARB }, +{ "glGetAttachedObjectsARB" , (void **)&pglGetAttachedObjectsARB }, +{ "glGetUniformLocationARB" , (void **)&pglGetUniformLocationARB }, +{ "glGetActiveUniformARB" , (void **) &pglGetActiveUniformARB }, +{ "glGetUniformfvARB" , (void **)&pglGetUniformfvARB }, +{ "glGetUniformivARB" , (void **)&pglGetUniformivARB }, +{ "glGetShaderSourceARB" , (void **)&pglGetShaderSourceARB }, +{ "glVertexAttribPointerARB" , (void **)&pglVertexAttribPointerARB }, +{ "glEnableVertexAttribArrayARB" , (void **)&pglEnableVertexAttribArrayARB }, +{ "glDisableVertexAttribArrayARB" , (void **)&pglDisableVertexAttribArrayARB }, +{ "glBindAttribLocationARB" , (void **)&pglBindAttribLocationARB }, +{ "glGetActiveAttribARB" , (void **)&pglGetActiveAttribARB }, +{ "glGetAttribLocationARB" , (void **)&pglGetAttribLocationARB }, +{ NULL, NULL } +}; + +static dllfunc_t vertexshaderfuncs[] = +{ +{ "glVertexAttribPointerARB" , (void **)&pglVertexAttribPointerARB }, +{ "glEnableVertexAttribArrayARB" , (void **)&pglEnableVertexAttribArrayARB }, +{ "glDisableVertexAttribArrayARB" , (void **)&pglDisableVertexAttribArrayARB }, +{ "glBindAttribLocationARB" , (void **)&pglBindAttribLocationARB }, +{ "glGetActiveAttribARB" , (void **)&pglGetActiveAttribARB }, +{ "glGetAttribLocationARB" , (void **)&pglGetAttribLocationARB }, +{ NULL, NULL } +}; + +static dllfunc_t vbofuncs[] = +{ +{ "glBindBufferARB" , (void **)&pglBindBufferARB }, +{ "glDeleteBuffersARB" , (void **)&pglDeleteBuffersARB }, +{ "glGenBuffersARB" , (void **)&pglGenBuffersARB }, +{ "glIsBufferARB" , (void **)&pglIsBufferARB }, +{ "glMapBufferARB" , (void **)&pglMapBufferARB }, +{ "glUnmapBufferARB" , (void **)&pglUnmapBufferARB }, +{ "glBufferDataARB" , (void **)&pglBufferDataARB }, +{ "glBufferSubDataARB" , (void **)&pglBufferSubDataARB }, +{ NULL, NULL} +}; + +static dllfunc_t occlusionfunc[] = +{ +{ "glGenQueriesARB" , (void **)&pglGenQueriesARB }, +{ "glDeleteQueriesARB" , (void **)&pglDeleteQueriesARB }, +{ "glIsQueryARB" , (void **)&pglIsQueryARB }, +{ "glBeginQueryARB" , (void **)&pglBeginQueryARB }, +{ "glEndQueryARB" , (void **)&pglEndQueryARB }, +{ "glGetQueryivARB" , (void **)&pglGetQueryivARB }, +{ "glGetQueryObjectivARB" , (void **)&pglGetQueryObjectivARB }, +{ "glGetQueryObjectuivARB" , (void **)&pglGetQueryObjectuivARB }, +{ NULL, NULL } +}; + +static dllfunc_t texturecompressionfuncs[] = +{ +{ "glCompressedTexImage3DARB" , (void **)&pglCompressedTexImage3DARB }, +{ "glCompressedTexImage2DARB" , (void **)&pglCompressedTexImage2DARB }, +{ "glCompressedTexImage1DARB" , (void **)&pglCompressedTexImage1DARB }, +{ "glCompressedTexSubImage3DARB" , (void **)&pglCompressedTexSubImage3DARB }, +{ "glCompressedTexSubImage2DARB" , (void **)&pglCompressedTexSubImage2DARB }, +{ "glCompressedTexSubImage1DARB" , (void **)&pglCompressedTexSubImage1DARB }, +{ "glGetCompressedTexImageARB" , (void **)&pglGetCompressedTexImage }, +{ NULL, NULL } +}; + +static dllfunc_t wgl_funcs[] = +{ +{ "wglChoosePixelFormat" , (void **)&pwglChoosePixelFormat }, +{ "wglDescribePixelFormat" , (void **)&pwglDescribePixelFormat }, +{ "wglSetPixelFormat" , (void **)&pwglSetPixelFormat }, +{ "wglSwapBuffers" , (void **)&pwglSwapBuffers }, +{ "wglCreateContext" , (void **)&pwglCreateContext }, +{ "wglDeleteContext" , (void **)&pwglDeleteContext }, +{ "wglGetProcAddress" , (void **)&pwglGetProcAddress }, +{ "wglMakeCurrent" , (void **)&pwglMakeCurrent }, +{ "wglGetCurrentContext" , (void **)&pwglGetCurrentContext }, +{ "wglGetCurrentDC" , (void **)&pwglGetCurrentDC }, +{ NULL, NULL } +}; + +static dllfunc_t wglswapintervalfuncs[] = +{ +{ "wglSwapIntervalEXT" , (void **)&pwglSwapIntervalEXT }, +{ NULL, NULL } +}; + +static dllfunc_t wgl3DFXgammacontrolfuncs[] = +{ +{ "wglGetDeviceGammaRamp3DFX" , (void **)&pwglGetDeviceGammaRamp3DFX }, +{ "wglSetDeviceGammaRamp3DFX" , (void **)&pwglSetDeviceGammaRamp3DFX }, +{ NULL, NULL } +}; + +dll_info_t opengl_dll = { "opengl32.dll", wgl_funcs, NULL, NULL, NULL, true }; + +/* +================= +GL_SetExtension +================= +*/ +void GL_SetExtension( int r_ext, int enable ) +{ + if( r_ext >= 0 && r_ext < GL_EXTCOUNT ) + glConfig.extension[r_ext] = enable ? GL_TRUE : GL_FALSE; + else MsgDev( D_ERROR, "GL_SetExtension: invalid extension %d\n", r_ext ); +} + +/* +================= +GL_Support +================= +*/ +qboolean GL_Support( int r_ext ) +{ + if( r_ext >= 0 && r_ext < GL_EXTCOUNT ) + return glConfig.extension[r_ext] ? true : false; + MsgDev( D_ERROR, "GL_Support: invalid extension %d\n", r_ext ); + return false; +} + +/* +================= +GL_GetProcAddress +================= +*/ +void *GL_GetProcAddress( const char *name ) +{ + void *p = NULL; + + if( pwglGetProcAddress != NULL ) + p = (void *)pwglGetProcAddress( name ); + if( !p ) p = (void *)Sys_GetProcAddress( &opengl_dll, name ); + + return p; +} + +/* +================= +GL_CheckExtension +================= +*/ +void GL_CheckExtension( const char *name, const dllfunc_t *funcs, const char *cvarname, int r_ext ) +{ + const dllfunc_t *func; + convar_t *parm; + + MsgDev( D_NOTE, "GL_CheckExtension: %s ", name ); + + if( cvarname ) + { + // system config disable extensions + parm = Cvar_Get( cvarname, "1", CVAR_GLCONFIG, va( "enable or disable %s", name )); + + if( parm->integer == 0 || ( gl_extensions->integer == 0 && r_ext != GL_OPENGL_110 )) + { + MsgDev( D_NOTE, "- disabled\n" ); + GL_SetExtension( r_ext, 0 ); + return; // nothing to process at + } + GL_SetExtension( r_ext, 1 ); + } + + if(( name[2] == '_' || name[3] == '_' ) && !com.strstr( glConfig.extensions_string, name )) + { + GL_SetExtension( r_ext, false ); // update render info + MsgDev( D_NOTE, "- failed\n" ); + return; + } + + // clear exports + for( func = funcs; func && func->name; func++ ) + *func->func = NULL; + + GL_SetExtension( r_ext, true ); // predict extension state + for( func = funcs; func && func->name != NULL; func++ ) + { + // functions are cleared before all the extensions are evaluated + if(!(*func->func = (void *)GL_GetProcAddress( func->name ))) + GL_SetExtension( r_ext, false ); // one or more functions are invalid, extension will be disabled + } + + if( GL_Support( r_ext )) + MsgDev( D_NOTE, "- enabled\n" ); +} + +/* +=============== +GL_BuildGammaTable +=============== +*/ +void GL_BuildGammaTable( void ) +{ + int i, v; + double invGamma, div; + + invGamma = 1.0 / bound( 0.5, vid_gamma->value, 3.0 ); + div = (double) 1.0 / 255.5; + + Mem_Copy( glState.gammaRamp, glState.stateRamp, sizeof( glState.gammaRamp )); + + for( i = 0; i < 256; i++ ) + { + v = (int)(65535.0 * pow(((double)i + 0.5 ) * div, invGamma ) + 0.5 ); + glState.gammaRamp[i+0] = ((word)bound( 0, v, 65535 )); + glState.gammaRamp[i+256] = ((word)bound( 0, v, 65535 )); + glState.gammaRamp[i+512] = ((word)bound( 0, v, 65535 )); + } +} + +/* +=============== +GL_UpdateGammaRamp +=============== +*/ +void GL_UpdateGammaRamp( void ) +{ + if( gl_ignorehwgamma->integer ) return; + if( !glConfig.deviceSupportsGamma ) return; + + GL_BuildGammaTable(); + + if( pwglGetDeviceGammaRamp3DFX ) + pwglSetDeviceGammaRamp3DFX( glw_state.hDC, glState.gammaRamp ); + else SetDeviceGammaRamp( glw_state.hDC, glState.gammaRamp ); +} + +/* +=============== +GL_UpdateSwapInterval +=============== +*/ +void GL_UpdateSwapInterval( void ) +{ + if( gl_swapInterval->modified ) + { + gl_swapInterval->modified = false; + + if( pwglSwapIntervalEXT ) + pwglSwapIntervalEXT( gl_swapInterval->integer ); + } +} + +/* +=============== +GL_SetDefaultTexState +=============== +*/ +static void GL_SetDefaultTexState( void ) +{ + Mem_Set( glState.currentTextures, -1, MAX_TEXTURE_UNITS * sizeof( *glState.currentTextures )); + Mem_Set( glState.currentEnvModes, -1, MAX_TEXTURE_UNITS * sizeof( *glState.currentEnvModes )); + Mem_Set( glState.texIdentityMatrix, 0, MAX_TEXTURE_UNITS * sizeof( *glState.texIdentityMatrix )); + Mem_Set( glState.genSTEnabled, 0, MAX_TEXTURE_UNITS * sizeof( *glState.genSTEnabled )); + Mem_Set( glState.texCoordArrayMode, 0, MAX_TEXTURE_UNITS * sizeof( *glState.texCoordArrayMode )); +} + +/* +=============== +GL_SetDefaultState +=============== +*/ +static void GL_SetDefaultState( void ) +{ + Mem_Set( &glState, 0, sizeof( glState )); + GL_SetDefaultTexState (); + + glState.initializedMedia = false; +} + +/* +================= +GL_CreateContext +================= +*/ +qboolean GL_CreateContext( void ) +{ + if(!( glw_state.hGLRC = pwglCreateContext( glw_state.hDC ))) + return GL_DeleteContext(); + + if(!( pwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ))) + return GL_DeleteContext(); + + return true; +} + +/* +================= +GL_UpdateContext +================= +*/ +qboolean GL_UpdateContext( void ) +{ + if(!( pwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ))) + return GL_DeleteContext(); + + return true; +} + +/* +================= +GL_DeleteContext +================= +*/ +qboolean GL_DeleteContext( void ) +{ + if( pwglMakeCurrent ) + pwglMakeCurrent( NULL, NULL ); + + if( glw_state.hGLRC ) + { + if( pwglDeleteContext ) + pwglDeleteContext( glw_state.hGLRC ); + glw_state.hGLRC = NULL; + } + + if( glw_state.hDC ) + { + ReleaseDC( host.hWnd, glw_state.hDC ); + glw_state.hDC = NULL; + } + + return false; +} + +/* +================= +VID_ChoosePFD +================= +*/ +static int VID_ChoosePFD( int colorBits, int alphaBits, int depthBits, int stencilBits ) +{ + PIXELFORMATDESCRIPTOR PFD, PFDs[MAX_PFDS], *current, *selected; + uint flags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER; + int i, numPFDs, pixelFormat = 0; + + MsgDev( D_NOTE, "VID_ChoosePFD( color %i, alpha %i, depth %i, stencil %i )\n", colorBits, alphaBits, depthBits, stencilBits ); + + // Fill out the PFD + PFD.nSize = sizeof (PIXELFORMATDESCRIPTOR); + PFD.nVersion = 1; + PFD.dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER; + PFD.iPixelType = PFD_TYPE_RGBA; + + PFD.cColorBits = colorBits; + PFD.cRedBits = 0; + PFD.cRedShift = 0; + PFD.cGreenBits = 0; + PFD.cGreenShift = 0; + PFD.cBlueBits = 0; + PFD.cBlueShift = 0; // wow! Blue Shift %) + + PFD.cAlphaBits = alphaBits; + PFD.cAlphaShift = 0; + + PFD.cAccumBits = 0; + PFD.cAccumRedBits = 0; + PFD.cAccumGreenBits = 0; + PFD.cAccumBlueBits = 0; + PFD.cAccumAlphaBits= 0; + + PFD.cDepthBits = depthBits; + PFD.cStencilBits = stencilBits; + + PFD.cAuxBuffers = 0; + PFD.iLayerType = PFD_MAIN_PLANE; + PFD.bReserved = 0; + + PFD.dwLayerMask = 0; + PFD.dwVisibleMask = 0; + PFD.dwDamageMask = 0; + + // Count PFDs + if( glw_state.minidriver ) + numPFDs = pwglDescribePixelFormat( glw_state.hDC, 0, 0, NULL ); + else numPFDs = DescribePixelFormat( glw_state.hDC, 0, 0, NULL ); + + if( numPFDs > MAX_PFDS ) + { + MsgDev( D_NOTE, "too many PFDs returned (%i > %i), reduce it\n", numPFDs, MAX_PFDS ); + numPFDs = MAX_PFDS; + } + else if( numPFDs < 1 ) + { + MsgDev( D_ERROR, "VID_ChoosePFD failed\n" ); + return 0; + } + + // run through all the PFDs, looking for the best match + for( i = 1, current = PFDs; i <= numPFDs; i++, current++ ) + { + if( glw_state.minidriver ) + pwglDescribePixelFormat( glw_state.hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), current ); + else DescribePixelFormat( glw_state.hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), current ); + + // check acceleration + if(( current->dwFlags & PFD_GENERIC_FORMAT ) && !gl_allow_software->integer ) + continue; + + // check flags + if(( current->dwFlags & flags ) != flags ) + continue; + + // check pixel type + if( current->iPixelType != PFD_TYPE_RGBA ) + continue; + + // check color bits + if( current->cColorBits < colorBits ) + continue; + + // check alpha bits + if( current->cAlphaBits < alphaBits ) + continue; + + // check depth bits + if( current->cDepthBits < depthBits ) + continue; + + // check stencil bits + if( current->cStencilBits < stencilBits ) + continue; + + // if we don't have a selected PFD yet, then use it + if( !pixelFormat ) + { + selected = current; + pixelFormat = i; + continue; + } + + if( colorBits != selected->cColorBits ) + { + if( colorBits == current->cColorBits || current->cColorBits > selected->cColorBits ) + { + selected = current; + pixelFormat = i; + continue; + } + } + + if( alphaBits != selected->cAlphaBits ) + { + if( alphaBits == current->cAlphaBits || current->cAlphaBits > selected->cAlphaBits ) + { + selected = current; + pixelFormat = i; + continue; + } + } + + if( depthBits != selected->cDepthBits ) + { + if( depthBits == current->cDepthBits || current->cDepthBits > selected->cDepthBits ) + { + selected = current; + pixelFormat = i; + continue; + } + } + + if( stencilBits != selected->cStencilBits ) + { + if( stencilBits == current->cStencilBits || current->cStencilBits > selected->cStencilBits ) + { + selected = current; + pixelFormat = i; + continue; + } + } + } + + if( !pixelFormat ) + { + MsgDev( D_ERROR, "VID_ChoosePFD: no hardware acceleration found\n" ); + return 0; + } + + if( selected->dwFlags & PFD_GENERIC_FORMAT ) + { + if( selected->dwFlags & PFD_GENERIC_ACCELERATED ) + { + MsgDev( D_NOTE, "VID_ChoosePFD: usign Generic MCD acceleration\n" ); + glw_state.software = false; + } + else + { + MsgDev( D_NOTE, "VID_ChoosePFD: using software emulation\n" ); + glw_state.software = true; + } + } + else + { + MsgDev( D_NOTE, "VID_ChoosePFD: using hardware acceleration\n"); + glw_state.software = false; + } + + return pixelFormat; +} + +void VID_StartupGamma( void ) +{ + size_t gamma_size; + byte *savedGamma; + + // init gamma ramp + Mem_Set( glState.stateRamp, 0, sizeof( glState.stateRamp )); + + if( pwglGetDeviceGammaRamp3DFX ) + glConfig.deviceSupportsGamma = pwglGetDeviceGammaRamp3DFX( glw_state.hDC, glState.stateRamp ); + else glConfig.deviceSupportsGamma = GetDeviceGammaRamp( glw_state.hDC, glState.stateRamp ); + + // share this extension so engine can grab them + GL_SetExtension( GL_HARDWARE_GAMMA_CONTROL, glConfig.deviceSupportsGamma ); + + savedGamma = FS_LoadFile( "gamma.dat", &gamma_size ); + + if( !savedGamma || gamma_size != sizeof( glState.stateRamp )) + { + // saved gamma not found or corrupted file + FS_WriteFile( "gamma.dat", glState.stateRamp, sizeof( glState.stateRamp )); + MsgDev( D_NOTE, "VID_StartupGamma: gamma.dat initialized\n" ); + if( savedGamma ) Mem_Free( savedGamma ); + } + else + { + GL_BuildGammaTable(); + + // validate base gamma + if( !memcmp( savedGamma, glState.stateRamp, sizeof( glState.stateRamp ))) + { + // all ok, previous gamma is valid + MsgDev( D_NOTE, "VID_StartupGamma: validate screen gamma - ok\n" ); + } + else if( !memcmp( glState.gammaRamp, glState.stateRamp, sizeof( glState.stateRamp ))) + { + // screen gamma is equal to render gamma (probably previous instance crashed) + // run additional check to make sure for it + if( memcmp( savedGamma, glState.stateRamp, sizeof( glState.stateRamp ))) + { + // yes, current gamma it's totally wrong, restore it from gamma.dat + MsgDev( D_NOTE, "VID_StartupGamma: restore original gamma after crash\n" ); + Mem_Copy( glState.stateRamp, savedGamma, sizeof( glState.gammaRamp )); + } + else + { + // oops, savedGamma == glState.stateRamp == glState.gammaRamp + // probably r_gamma set as default + MsgDev( D_NOTE, "VID_StartupGamma: validate screen gamma - disabled\n" ); + } + } + else if( !memcmp( glState.gammaRamp, savedGamma, sizeof( glState.stateRamp ))) + { + // saved gamma is equal render gamma, probably gamma.dat wroted after crash + // run additional check to make sure it + if( memcmp( savedGamma, glState.stateRamp, sizeof( glState.stateRamp ))) + { + // yes, saved gamma it's totally wrong, get origianl gamma from screen + MsgDev( D_NOTE, "VID_StartupGamma: merge gamma.dat after crash\n" ); + FS_WriteFile( "gamma.dat", glState.stateRamp, sizeof( glState.stateRamp )); + } + else + { + // oops, savedGamma == glState.stateRamp == glState.gammaRamp + // probably r_gamma set as default + MsgDev( D_NOTE, "VID_StartupGamma: validate screen gamma - disabled\n" ); + } + } + else + { + // current gamma unset by other application, so we can restore it here + MsgDev( D_NOTE, "VID_StartupGamma: restore original gamma after crash\n" ); + Mem_Copy( glState.stateRamp, savedGamma, sizeof( glState.gammaRamp )); + } + Mem_Free( savedGamma ); + } + vid_gamma->modified = true; +} + +void VID_RestoreGamma( void ) +{ + if( !glw_state.hDC ) return; + SetDeviceGammaRamp( glw_state.hDC, glState.stateRamp ); +} + +/* +================= +GL_SetPixelformat +================= +*/ +qboolean GL_SetPixelformat( void ) +{ + PIXELFORMATDESCRIPTOR PFD; + int colorBits, alphaBits; + int depthBits, stencilBits; + int pixelFormat; + + if( glw_state.minidriver ) + { + if(( glw_state.hDC = pwglGetCurrentDC()) == NULL ) + return false; + } + else + { + if(( glw_state.hDC = GetDC( host.hWnd )) == NULL ) + return false; + } + + // set color/depth/stencil + colorBits = (gl_colorbits->integer) ? gl_colorbits->integer : 32; + depthBits = (gl_depthbits->integer) ? gl_depthbits->integer : 24; + alphaBits = (gl_alphabits->integer) ? gl_alphabits->integer : 8; + stencilBits = (gl_stencilbits->integer) ? gl_stencilbits->integer : 8; + + // choose a pixel format + pixelFormat = VID_ChoosePFD( colorBits, alphaBits, depthBits, stencilBits ); + + if( !pixelFormat ) + { + // try again with default color/depth/stencil + if( colorBits > 16 || depthBits > 16 || alphaBits > 0 || stencilBits > 0 ) + pixelFormat = VID_ChoosePFD( 16, 0, 16, 0 ); + else pixelFormat = VID_ChoosePFD( 32, 0, 24, 0 ); + + if( !pixelFormat ) + { + MsgDev( D_ERROR, "GL_SetPixelformat: failed to find an appropriate PIXELFORMAT\n" ); + return false; + } + } + + // set the pixel format + if( glw_state.minidriver ) + { + pwglDescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD ); + + if( !pwglSetPixelFormat( glw_state.hDC, pixelFormat, &PFD )) + { + MsgDev( D_ERROR, "GL_SetPixelformat: failed\n" ); + return false; + } + } + else + { + DescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD ); + + if( !SetPixelFormat( glw_state.hDC, pixelFormat, &PFD )) + { + MsgDev( D_ERROR, "GL_SetPixelformat: failed\n" ); + return false; + } + } + + glConfig.color_bits = PFD.cColorBits; + glConfig.alpha_bits = PFD.cAlphaBits; + glConfig.depth_bits = PFD.cDepthBits; + glConfig.stencil_bits = PFD.cStencilBits; + + if( PFD.cStencilBits != 0 ) + glState.stencilEnabled = true; + else glState.stencilEnabled = false; + + // print out PFD specifics + MsgDev( D_NOTE, "GL PFD: color( %d-bits ) alpha( %d-bits ) Z( %d-bit )\n", PFD.cColorBits, PFD.cAlphaBits, PFD.cDepthBits ); + + return true; +} + +void R_SaveVideoMode( int vid_mode ) +{ + int mode = bound( 0, vid_mode, num_vidmodes ); // check range + + glState.width = vidmode[mode].width; + glState.height = vidmode[mode].height; + glState.wideScreen = vidmode[mode].wideScreen; + + Cvar_FullSet( "width", va( "%i", vidmode[mode].width ), CVAR_READ_ONLY ); + Cvar_FullSet( "height", va( "%i", vidmode[mode].height ), CVAR_READ_ONLY ); + Cvar_SetFloat( "vid_mode", mode ); // merge if it out of bounds + + MsgDev( D_NOTE, "Set: %s [%dx%d]\n", vidmode[mode].desc, vidmode[mode].width, vidmode[mode].height ); +} + +qboolean VID_CreateWindow( int width, int height, qboolean fullscreen ) +{ + WNDCLASS wc; + RECT rect; + int x = 0, y = 0, w, h; + int stylebits = WINDOW_STYLE; + int exstyle = WINDOW_EX_STYLE; + static string wndname; + + com.snprintf( wndname, sizeof( wndname ), "%s", GI->title ); + + // register the frame class + wc.style = CS_OWNDC|CS_NOCLOSE; + wc.lpfnWndProc = (WNDPROC)IN_WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = host.hInst; + wc.hCursor = LoadCursor( NULL, IDC_ARROW ); + wc.hbrBackground = (void *)COLOR_3DSHADOW; + wc.lpszClassName = "Xash Window"; + wc.lpszMenuName = 0; + + // find the icon file in the filesystem + if( FS_FileExistsEx( "game.ico", true )) + { + char localPath[MAX_PATH]; + + com.snprintf( localPath, sizeof( localPath ), "%s/game.ico", GI->gamedir ); + wc.hIcon = LoadImage( NULL, localPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE|LR_DEFAULTSIZE ); + + if( !wc.hIcon ) + { + MsgDev( D_INFO, "Extract game.ico from pak if you want to see it.\n" ); + wc.hIcon = LoadIcon( host.hInst, MAKEINTRESOURCE( 101 )); + } + } + else wc.hIcon = LoadIcon( host.hInst, MAKEINTRESOURCE( 101 )); + + if( !RegisterClass( &wc )) + { + MsgDev( D_ERROR, "VID_CreateWindow: couldn't register window class %s\n" "Xash Window" ); + return false; + } + + if( fullscreen ) + { + stylebits = WS_POPUP|WS_VISIBLE; + exstyle = WS_EX_TOPMOST; + } + + rect.left = 0; + rect.top = 0; + rect.right = width; + rect.bottom = height; + + AdjustWindowRect( &rect, stylebits, FALSE ); + w = rect.right - rect.left; + h = rect.bottom - rect.top; + + if( !fullscreen ) + { + x = r_xpos->integer; + y = r_ypos->integer; + + // adjust window coordinates if necessary + // so that the window is completely on screen + if( x < 0 ) x = 0; + if( y < 0 ) y = 0; + + if( Cvar_VariableInteger( "vid_mode" ) != glConfig.prev_mode ) + { + // adjust window in the screen size + if(( x + w > glw_state.desktopWidth ) || ( y + h > glw_state.desktopHeight )) + { + x = ( glw_state.desktopWidth - w ) / 2; + y = ( glw_state.desktopHeight - h ) / 2; + } + } + } + + CreateWindowEx( exstyle, "Xash Window", wndname, stylebits, x, y, w, h, NULL, NULL, host.hInst, NULL ); + + // host.hWnd will be filled in IN_WndProc + + if( !host.hWnd ) + { + MsgDev( D_ERROR, "VID_CreateWindow: couldn't create '%s'\n", wndname ); + return false; + } + + ShowWindow( host.hWnd, SW_SHOW ); + UpdateWindow( host.hWnd ); + + // init all the gl stuff for the window + if( !GL_SetPixelformat( )) + { + ShowWindow( host.hWnd, SW_HIDE ); + DestroyWindow( host.hWnd ); + host.hWnd = NULL; + + UnregisterClass( "Xash Window", host.hInst ); + MsgDev( D_ERROR, "OpenGL driver not installed\n" ); + return false; + } + + if( !glw_state.initialized ) + { + if( !GL_CreateContext( )) + return false; + + VID_StartupGamma(); + } + else + { + if( !GL_UpdateContext( )) + return false; + } + + SetForegroundWindow( host.hWnd ); + SetFocus( host.hWnd ); + + return true; +} + +void VID_DestroyWindow( void ) +{ + if( pwglMakeCurrent ) + pwglMakeCurrent( NULL, NULL ); + + if( glw_state.hDC ) + { + ReleaseDC( host.hWnd, glw_state.hDC ); + glw_state.hDC = NULL; + } + + if( host.hWnd ) + { + DestroyWindow ( host.hWnd ); + host.hWnd = NULL; + } + + UnregisterClass( "Xash Window", host.hInst ); + + if( glState.fullScreen ) + { + ChangeDisplaySettings( 0, 0 ); + glState.fullScreen = false; + } +} + +rserr_t R_ChangeDisplaySettings( int vid_mode, qboolean fullscreen ) +{ + int width, height; + HDC hDC; + + R_SaveVideoMode( vid_mode ); + + width = r_width->integer; + height = r_height->integer; + + // check our desktop attributes + hDC = GetDC( GetDesktopWindow( )); + glw_state.desktopBitsPixel = GetDeviceCaps( hDC, BITSPIXEL ); + glw_state.desktopWidth = GetDeviceCaps( hDC, HORZRES ); + glw_state.desktopHeight = GetDeviceCaps( hDC, VERTRES ); + ReleaseDC( GetDesktopWindow(), hDC ); + + // destroy the existing window + if( host.hWnd ) VID_DestroyWindow(); + + // do a CDS if needed + if( fullscreen ) + { + DEVMODE dm; + + Mem_Set( &dm, 0, sizeof( dm )); + dm.dmSize = sizeof( dm ); + dm.dmPelsWidth = width; + dm.dmPelsHeight = height; + dm.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT; + + if( vid_displayfrequency->integer > 0 ) + { + dm.dmFields |= DM_DISPLAYFREQUENCY; + dm.dmDisplayFrequency = vid_displayfrequency->integer; + } + + if( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) == DISP_CHANGE_SUCCESSFUL ) + { + glState.fullScreen = true; + + if( !VID_CreateWindow( width, height, true )) + return rserr_invalid_mode; + return rserr_ok; + } + else + { + dm.dmPelsWidth = width * 2; + dm.dmPelsHeight = height; + dm.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT; + if( gl_depthbits->integer != 0 ) + { + dm.dmBitsPerPel = gl_depthbits->integer; + dm.dmFields |= DM_BITSPERPEL; + } + + // our first CDS failed, so maybe we're running on some weird dual monitor system + if( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL ) + { + ChangeDisplaySettings( 0, 0 ); + glState.fullScreen = false; + if( !VID_CreateWindow( width, height, false )) + return rserr_invalid_mode; + return rserr_invalid_fullscreen; + } + else + { + if( !VID_CreateWindow( width, height, true )) + return rserr_invalid_mode; + glState.fullScreen = true; + return rserr_ok; + } + } + } + else + { + ChangeDisplaySettings( 0, 0 ); + glState.fullScreen = false; + if( !VID_CreateWindow( width, height, false )) + return rserr_invalid_mode; + } + return rserr_ok; +} + +/* +================== +VID_SetMode + +Set the described video mode +================== +*/ +qboolean VID_SetMode( void ) +{ + rserr_t err; + qboolean fullscreen; + + fullscreen = vid_fullscreen->integer; + + if(( err = R_ChangeDisplaySettings( vid_mode->integer, fullscreen )) == rserr_ok ) + { + glConfig.prev_mode = vid_mode->integer; + } + else + { + if( err == rserr_invalid_fullscreen ) + { + Cvar_SetFloat( "fullscreen", 0 ); + MsgDev( D_ERROR, "VID_SetMode: fullscreen unavailable in this mode\n" ); + if(( err = R_ChangeDisplaySettings( vid_mode->integer, false )) == rserr_ok ) + return true; + } + else if( err == rserr_invalid_mode ) + { + Cvar_SetFloat( "vid_mode", glConfig.prev_mode ); + MsgDev( D_ERROR, "VID_SetMode: invalid mode\n" ); + } + + // try setting it back to something safe + if(( err = R_ChangeDisplaySettings( glConfig.prev_mode, false )) != rserr_ok ) + { + MsgDev( D_ERROR, "VID_SetMode: could not revert to safe mode\n" ); + return false; + } + } + return true; +} + +/* +================== +VID_CheckChanges + +check vid modes and fullscreen +================== +*/ +void VID_CheckChanges( void ) +{ + if( renderinfo->modified ) + { + if( !VID_SetMode()) + { + // can't initialize video subsystem + Sys_NewInstance( va("#%s", GI->gamefolder ), "fallback to dedicated mode\n" ); + } + else + { + renderinfo->modified = false; + SCR_VidInit(); // tell the client.dll what vid_mode has changed + } + } +} + +/* +================== +R_Init_OpenGL +================== +*/ +qboolean R_Init_OpenGL( void ) +{ + Sys_LoadLibrary( NULL, &opengl_dll ); // load opengl32.dll + if( !opengl_dll.link ) return false; + + glw_state.minidriver = false; // FIXME: allow 3dfx drivers too + + return VID_SetMode(); +} + +/* +================== +R_Free_OpenGL +================== +*/ +void R_Free_OpenGL( void ) +{ + VID_RestoreGamma (); + + VID_DestroyWindow (); + + Sys_FreeLibrary( &opengl_dll ); + + // now all extensions are disabled + Mem_Set( glConfig.extension, 0, sizeof( glConfig.extension[0] ) * GL_EXTCOUNT ); + glw_state.initialized = false; +} + +/* +=============== +GL_SetDefaults +=============== +*/ +static void GL_SetDefaults( void ) +{ + int i; + + pglFinish(); + + pglClearColor( 0.5f, 0.5f, 0.5f, 1.0f ); + + pglEnable( GL_DEPTH_TEST ); + pglDisable( GL_CULL_FACE ); + pglEnable( GL_SCISSOR_TEST ); + pglDepthFunc( GL_LEQUAL ); + pglDepthMask( GL_FALSE ); + + pglColor4f( 1, 1, 1, 1 ); + + if( glState.stencilEnabled ) + { + pglDisable( GL_STENCIL_TEST ); + pglStencilMask( ( GLuint ) ~0 ); + pglStencilFunc( GL_EQUAL, 128, 0xFF ); + pglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); + } + + // enable gouraud shading + pglShadeModel( GL_SMOOTH ); + + pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + pglPolygonOffset( -1, -2 ); + + // properly disable multitexturing at startup + for( i = glConfig.max_texture_units - 1; i > 0; i-- ) + { + GL_SelectTexture( i ); + GL_TexEnv( GL_MODULATE ); + pglDisable( GL_BLEND ); + pglDisable( GL_TEXTURE_2D ); + } + + GL_SelectTexture( 0 ); + pglDisable( GL_BLEND ); + pglDisable( GL_ALPHA_TEST ); + pglDisable( GL_POLYGON_OFFSET_FILL ); + pglEnable( GL_TEXTURE_2D ); + + GL_Cull( 0 ); + GL_FrontFace( 0 ); + + GL_SetState( GLSTATE_DEPTHWRITE ); + GL_TexEnv( GL_MODULATE ); + + R_SetTextureParameters(); + + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); +} + +/* +================= +R_RenderInfo_f +================= +*/ +void R_RenderInfo_f( void ) +{ + Msg( "\n" ); + Msg( "GL_VENDOR: %s\n", glConfig.vendor_string ); + Msg( "GL_RENDERER: %s\n", glConfig.renderer_string ); + Msg( "GL_VERSION: %s\n", glConfig.version_string ); + Msg( "GL_EXTENSIONS: %s\n", glConfig.extensions_string ); + + Msg( "GL_MAX_TEXTURE_SIZE: %i\n", glConfig.max_2d_texture_size ); + + if( GL_Support( GL_ARB_MULTITEXTURE )) + Msg( "GL_MAX_TEXTURE_UNITS_ARB: %i\n", glConfig.max_texture_units ); + if( GL_Support( GL_TEXTURECUBEMAP_EXT )) + Msg( "GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB: %i\n", glConfig.max_cubemap_size ); + if( GL_Support( GL_ANISOTROPY_EXT )) + Msg( "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: %.1f\n", glConfig.max_texture_anisotropy ); + if( glConfig.texRectangle ) + Msg( "GL_MAX_RECTANGLE_TEXTURE_SIZE_NV: %i\n", glConfig.max_2d_rectangle_size ); + + Msg( "\n" ); + Msg( "MODE: %i, %i x %i %s\n", vid_mode->integer, r_width->integer, r_height->integer ); + Msg( "GAMMA: %s\n", (glConfig.deviceSupportsGamma) ? "hardware" : "software" ); + Msg( "\n" ); + Msg( "PICMIP: %i\n", gl_picmip->integer ); + Msg( "SKYMIP: %i\n", gl_skymip->integer ); + Msg( "TEXTUREMODE: %s\n", gl_texturemode->string ); + Msg( "VERTICAL SYNC: %s\n", gl_swapInterval->integer ? "enabled" : "disabled" ); + Msg( "Color %d bits, Alpha %d bits, Depth %d bits, Stencil %d bits\n", glConfig.color_bits, + glConfig.alpha_bits, glConfig.depth_bits, glConfig.stencil_bits ); +} + +//======================================================================= + +void GL_InitCommands( void ) +{ + Cbuf_AddText( "vidlatch\n" ); + Cbuf_Execute(); + + // system screen width and height (don't suppose for change from console at all) + r_width = Cvar_Get( "width", "640", CVAR_READ_ONLY, "screen width" ); + r_height = Cvar_Get( "height", "480", CVAR_READ_ONLY, "screen height" ); + renderinfo = Cvar_Get( "@renderinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only + r_speeds = Cvar_Get( "r_speeds", "0", CVAR_ARCHIVE, "shows renderer speeds" ); + r_fullbright = Cvar_Get( "r_fullbright", "0", CVAR_CHEAT, "disable lightmaps, get fullbright for entities" ); + r_norefresh = Cvar_Get( "r_norefresh", "0", 0, "disable 3D rendering (use with caution)" ); + r_lighting_modulate = Cvar_Get( "r_lighting_modulate", "0.6", CVAR_ARCHIVE, "lightstyles modulate scale" ); + r_lighting_ambient = Cvar_Get( "r_lighting_ambient", "0.6", 0, "map ambient lighting scale" ); + r_lighting_direct = Cvar_Get( "r_lighting_direct", "1", 0, "map directed lighting scale" ); + r_adjust_fov = Cvar_Get( "r_adjust_fov", "1", CVAR_ARCHIVE, "making FOV adjustment for wide-screens" ); + r_novis = Cvar_Get( "r_novis", "0", 0, "ignore vis information (perfomance test)" ); + r_nocull = Cvar_Get( "r_nocull", "0", 0, "ignore frustrum culling (perfomance test)" ); + r_faceplanecull = Cvar_Get( "r_faceplanecull", "1", 0, "ignore face plane culling (perfomance test)" ); + r_lockpvs = Cvar_Get( "r_lockpvs", "0", CVAR_CHEAT, "lockpvs area at current point (pvs test)" ); + r_lockcull = Cvar_Get( "r_lockcull", "0", CVAR_CHEAT, "lock frustrum area at current point (cull test)" ); + r_wateralpha = Cvar_Get( "r_wateralpha", "1", CVAR_ARCHIVE, "world water transparency factor" ); + r_dynamic = Cvar_Get( "r_dynamic", "1", CVAR_ARCHIVE, "allow dynamic lighting (dlights, lightstyles)" ); + r_lightmap = Cvar_Get( "r_lightmap", "0", CVAR_CHEAT, "lightmap debugging tool" ); + r_shadows = Cvar_Get( "r_shadows", "0", CVAR_ARCHIVE, "enable model shadows" ); + r_fastsky = Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE, "enable algorhytm fo fast sky rendering (for old machines)" ); + r_drawentities = Cvar_Get( "r_drawentities", "1", CVAR_CHEAT|CVAR_ARCHIVE, "render entities" ); + r_lefthand = Cvar_Get( "hand", "0", CVAR_ARCHIVE, "viewmodel handedness" ); + r_decals = Cvar_Get( "r_decals", "4096", CVAR_ARCHIVE, "sets the maximum number of decals" ); + r_xpos = Cvar_Get( "r_xpos", "130", CVAR_GLCONFIG, "window position by horizontal" ); + r_ypos = Cvar_Get( "r_ypos", "48", CVAR_GLCONFIG, "window position by vertical" ); + + gl_picmip = Cvar_Get( "gl_picmip", "0", CVAR_GLCONFIG, "reduces resolution of textures by powers of 2" ); + gl_skymip = Cvar_Get( "gl_skymip", "0", CVAR_GLCONFIG, "reduces resolution of skybox textures by powers of 2" ); + gl_ignorehwgamma = Cvar_Get( "gl_ignorehwgamma", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "ignore hardware gamma (e.g. not support)" ); + gl_allow_software = Cvar_Get( "gl_allow_software", "0", CVAR_ARCHIVE, "allow OpenGL software emulation" ); + gl_colorbits = Cvar_Get( "gl_colorbits", "0", CVAR_RENDERINFO, "pixelformat color bits (0 - auto)" ); + gl_alphabits = Cvar_Get( "gl_alphabits", "0", CVAR_RENDERINFO, "pixelformat alpha bits (0 - auto)" ); + gl_depthbits = Cvar_Get( "gl_depthbits", "0", CVAR_RENDERINFO, "pixelformat depth bits (0 - auto)" ); + gl_texturemode = Cvar_Get( "gl_texturemode", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE, "texture filter" ); + gl_texturebits = Cvar_Get( "gl_texturebits", "0", CVAR_GLCONFIG, "set texture upload format (0 - auto)" ); + gl_round_down = Cvar_Get( "gl_round_down", "0", CVAR_GLCONFIG, "down size non-power of two textures" ); + gl_stencilbits = Cvar_Get( "gl_stencilbits", "0", CVAR_RENDERINFO, "pixelformat stencil bits (0 - auto)" ); + gl_check_errors = Cvar_Get( "gl_check_errors", "1", CVAR_ARCHIVE, "ignore video engine errors" ); + gl_swapInterval = Cvar_Get( "gl_swapInterval", "0", CVAR_ARCHIVE, "time beetween frames (in msec)" ); + gl_extensions = Cvar_Get( "gl_extensions", "1", CVAR_GLCONFIG, "allow gl_extensions" ); + gl_texture_anisotropy = Cvar_Get( "r_anisotropy", "2.0", CVAR_ARCHIVE, "textures anisotropic filter" ); + gl_nobind = Cvar_Get( "gl_nobind", "0", 0, "replace all textures with '*notexture' (perfomance test)" ); + gl_texture_lodbias = Cvar_Get( "gl_texture_lodbias", "0.0", CVAR_ARCHIVE, "LOD bias for mipmapped textures" ); + gl_compress_textures = Cvar_Get( "gl_compress_textures", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "compress textures to safe video memory" ); + gl_showtextures = Cvar_Get( "r_showtextures", "0", CVAR_CHEAT, "show all uploaded textures (type values from 1 to 9)" ); + gl_finish = Cvar_Get( "gl_finish", "0", CVAR_ARCHIVE, "use glFinish instead of glFlush" ); + gl_clear = Cvar_Get( "gl_clear", "0", CVAR_ARCHIVE, "clearing screen after each frame" ); + gl_test = Cvar_Get( "gl_test", "0", 0, "engine developer cvar for quick testing new features" ); + + // make sure r_swapinterval is checked after vid_restart + gl_swapInterval->modified = true; + + vid_gamma = Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE, "gamma amount" ); + vid_mode = Cvar_Get( "vid_mode", VID_DEFAULTMODE, CVAR_RENDERINFO, "display resolution mode" ); + vid_fullscreen = Cvar_Get( "fullscreen", "0", CVAR_RENDERINFO, "set in 1 to enable fullscreen mode" ); + vid_displayfrequency = Cvar_Get ( "vid_displayfrequency", "0", CVAR_RENDERINFO, "fullscreen refresh rate" ); + + Cmd_AddCommand( "r_info", R_RenderInfo_f, "display renderer info" ); + Cmd_AddCommand( "texturelist", R_TextureList_f, "display loaded textures list" ); +} + +void GL_RemoveCommands( void ) +{ + Cmd_RemoveCommand( "r_info"); + Cmd_RemoveCommand( "texturelist" ); +} + +void GL_InitExtensions( void ) +{ + int flags = 0; + + // initialize gl extensions + GL_CheckExtension( "OpenGL 1.1.0", opengl_110funcs, NULL, GL_OPENGL_110 ); + + // get our various GL strings + glConfig.vendor_string = pglGetString( GL_VENDOR ); + glConfig.renderer_string = pglGetString( GL_RENDERER ); + glConfig.version_string = pglGetString( GL_VERSION ); + glConfig.extensions_string = pglGetString( GL_EXTENSIONS ); + MsgDev( D_INFO, "Video: %s\n", glConfig.renderer_string ); + + GL_CheckExtension( "WGL_3DFX_gamma_control", wgl3DFXgammacontrolfuncs, NULL, GL_WGL_3DFX_GAMMA_CONTROL ); + GL_CheckExtension( "WGL_EXT_swap_control", wglswapintervalfuncs, NULL, GL_WGL_SWAPCONTROL ); + GL_CheckExtension( "glDrawRangeElements", drawrangeelementsfuncs, "gl_drawrangeelments", GL_DRAW_RANGEELEMENTS_EXT ); + + if( !GL_Support( GL_DRAW_RANGEELEMENTS_EXT )) + GL_CheckExtension( "GL_EXT_draw_range_elements", drawrangeelementsextfuncs, "gl_drawrangeelments", GL_DRAW_RANGEELEMENTS_EXT ); + + // multitexture + glConfig.max_texture_units = 1; + GL_CheckExtension( "GL_ARB_multitexture", multitexturefuncs, "gl_arb_multitexture", GL_ARB_MULTITEXTURE ); + + if( GL_Support( GL_ARB_MULTITEXTURE )) + { + pglGetIntegerv( GL_MAX_TEXTURE_UNITS_ARB, &glConfig.max_texture_units ); + GL_CheckExtension( "GL_ARB_texture_env_combine", NULL, "gl_texture_env_combine", GL_ENV_COMBINE_EXT ); + + if( !GL_Support( GL_ENV_COMBINE_EXT )) + GL_CheckExtension( "GL_EXT_texture_env_combine", NULL, "gl_texture_env_combine", GL_ENV_COMBINE_EXT ); + + if( GL_Support( GL_ENV_COMBINE_EXT )) + GL_CheckExtension( "GL_ARB_texture_env_dot3", NULL, "gl_texture_env_dot3", GL_DOT3_ARB_EXT ); + } + else + { + GL_CheckExtension( "GL_SGIS_multitexture", sgis_multitexturefuncs, "gl_sgis_multitexture", GL_ARB_MULTITEXTURE ); + if( GL_Support( GL_ARB_MULTITEXTURE )) glConfig.max_texture_units = 2; + } + + if( glConfig.max_texture_units == 1 ) + GL_SetExtension( GL_ARB_MULTITEXTURE, false ); + + // 3d texture support + GL_CheckExtension( "GL_EXT_texture3D", texture3dextfuncs, "gl_texture_3d", GL_TEXTURE_3D_EXT ); + + if( GL_Support( GL_TEXTURE_3D_EXT )) + { + pglGetIntegerv( GL_MAX_3D_TEXTURE_SIZE, &glConfig.max_3d_texture_size ); + + if( glConfig.max_3d_texture_size < 32 ) + { + GL_SetExtension( GL_TEXTURE_3D_EXT, false ); + MsgDev( D_ERROR, "GL_EXT_texture3D reported bogus GL_MAX_3D_TEXTURE_SIZE, disabled\n" ); + } + } + + GL_CheckExtension( "GL_SGIS_generate_mipmap", NULL, "gl_sgis_generate_mipmaps", GL_SGIS_MIPMAPS_EXT ); + + // hardware cubemaps + GL_CheckExtension( "GL_ARB_texture_cube_map", NULL, "gl_texture_cubemap", GL_TEXTURECUBEMAP_EXT ); + + if( GL_Support( GL_TEXTURECUBEMAP_EXT )) + pglGetIntegerv( GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, &glConfig.max_cubemap_size ); + + // point particles extension + GL_CheckExtension( "GL_EXT_point_parameters", pointparametersfunc, NULL, GL_EXT_POINTPARAMETERS ); + + GL_CheckExtension( "GL_ARB_texture_non_power_of_two", NULL, "gl_texture_npot", GL_ARB_TEXTURE_NPOT_EXT ); + GL_CheckExtension( "GL_ARB_texture_compression", texturecompressionfuncs, "gl_dds_hardware_support", GL_TEXTURE_COMPRESSION_EXT ); + GL_CheckExtension( "GL_EXT_compiled_vertex_array", compiledvertexarrayfuncs, "gl_cva_support", GL_CUSTOM_VERTEX_ARRAY_EXT ); + + if( !GL_Support( GL_CUSTOM_VERTEX_ARRAY_EXT )) + GL_CheckExtension( "GL_SGI_compiled_vertex_array", compiledvertexarrayfuncs, "gl_cva_support", GL_CUSTOM_VERTEX_ARRAY_EXT ); + + GL_CheckExtension( "GL_EXT_texture_edge_clamp", NULL, "gl_clamp_to_edge", GL_CLAMPTOEDGE_EXT ); + + if( !GL_Support( GL_CLAMPTOEDGE_EXT )) + GL_CheckExtension("GL_SGIS_texture_edge_clamp", NULL, "gl_clamp_to_edge", GL_CLAMPTOEDGE_EXT ); + + glConfig.max_texture_anisotropy = 0.0f; + GL_CheckExtension( "GL_EXT_texture_filter_anisotropic", NULL, "gl_ext_anisotropic_filter", GL_ANISOTROPY_EXT ); + + if( GL_Support( GL_ANISOTROPY_EXT )) + pglGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glConfig.max_texture_anisotropy ); + + GL_CheckExtension( "GL_EXT_texture_lod_bias", NULL, "gl_ext_texture_lodbias", GL_TEXTURE_LODBIAS ); + if( GL_Support( GL_TEXTURE_LODBIAS )) + pglGetFloatv( GL_MAX_TEXTURE_LOD_BIAS_EXT, &glConfig.max_texture_lodbias ); + + GL_CheckExtension( "GL_ARB_texture_border_clamp", NULL, "gl_ext_texborder_clamp", GL_CLAMP_TEXBORDER_EXT ); + + GL_CheckExtension( "GL_EXT_blend_minmax", blendequationfuncs, "gl_ext_customblend", GL_BLEND_MINMAX_EXT ); + GL_CheckExtension( "GL_EXT_blend_subtract", blendequationfuncs, "gl_ext_customblend", GL_BLEND_SUBTRACT_EXT ); + + GL_CheckExtension( "glStencilOpSeparate", gl2separatestencilfuncs, "gl_separate_stencil", GL_SEPARATESTENCIL_EXT ); + if( !GL_Support( GL_SEPARATESTENCIL_EXT )) + GL_CheckExtension("GL_ATI_separate_stencil", atiseparatestencilfuncs, "gl_separate_stencil", GL_SEPARATESTENCIL_EXT ); + + GL_CheckExtension( "GL_EXT_stencil_two_side", stenciltwosidefuncs, "gl_stenciltwoside", GL_STENCILTWOSIDE_EXT ); + GL_CheckExtension( "GL_ARB_vertex_buffer_object", vbofuncs, "gl_vertex_buffer_object", GL_ARB_VERTEX_BUFFER_OBJECT_EXT ); + + // we don't care if it's an extension or not, they are identical functions, so keep it simple in the rendering code + if( pglDrawRangeElementsEXT == NULL ) pglDrawRangeElementsEXT = pglDrawRangeElements; + + GL_CheckExtension( "GL_ARB_texture_env_add", NULL, "gl_texture_env_add", GL_TEXTURE_ENV_ADD_EXT ); + + // vp and fp shaders + GL_CheckExtension( "GL_ARB_shader_objects", shaderobjectsfuncs, "gl_shaderobjects", GL_SHADER_OBJECTS_EXT ); + GL_CheckExtension( "GL_ARB_shading_language_100", NULL, "gl_glslprogram", GL_SHADER_GLSL100_EXT ); + GL_CheckExtension( "GL_ARB_vertex_shader", vertexshaderfuncs, "gl_vertexshader", GL_VERTEX_SHADER_EXT ); + GL_CheckExtension( "GL_ARB_fragment_shader", NULL, "gl_pixelshader", GL_FRAGMENT_SHADER_EXT ); + + GL_CheckExtension( "GL_ARB_depth_texture", NULL, "gl_depthtexture", GL_DEPTH_TEXTURE ); + GL_CheckExtension( "GL_ARB_shadow", NULL, "gl_arb_shadow", GL_SHADOW_EXT ); + + // occlusion queries + GL_CheckExtension( "GL_ARB_occlusion_query", occlusionfunc, "gl_occlusion_queries", GL_OCCLUSION_QUERIES_EXT ); + + // rectangle textures support + if( com.strstr( glConfig.extensions_string, "GL_NV_texture_rectangle" )) + { + glConfig.texRectangle = GL_TEXTURE_RECTANGLE_NV; + pglGetIntegerv( GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, &glConfig.max_2d_rectangle_size ); + } + else if( com.strstr( glConfig.extensions_string, "GL_EXT_texture_rectangle" )) + { + glConfig.texRectangle = GL_TEXTURE_RECTANGLE_EXT; + pglGetIntegerv( GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT, &glConfig.max_2d_rectangle_size ); + } + else glConfig.texRectangle = glConfig.max_2d_rectangle_size = 0; // no rectangle + + glConfig.max_2d_texture_size = 0; + pglGetIntegerv( GL_MAX_TEXTURE_SIZE, &glConfig.max_2d_texture_size ); + if( glConfig.max_2d_texture_size <= 0 ) glConfig.max_2d_texture_size = 256; + + Cvar_Get( "gl_max_texture_size", "0", CVAR_INIT, "opengl texture max dims" ); + Cvar_Set( "gl_max_texture_size", va( "%i", glConfig.max_2d_texture_size )); + + // MCD has buffering issues + if(com.strstr( glConfig.renderer_string, "gdi" )) + Cvar_SetFloat( "gl_finish", 1 ); + + Cvar_Set( "gl_anisotropy", va( "%f", bound( 0, gl_texture_anisotropy->value, glConfig.max_texture_anisotropy ))); + + // software mipmap generator does wrong result with NPOT textures ... + if( !GL_Support( GL_SGIS_MIPMAPS_EXT )) + GL_SetExtension( GL_ARB_TEXTURE_NPOT_EXT, false ); + + flags |= IL_USE_LERPING|IL_ALLOW_OVERWRITE; + + Image_Init( NULL, flags ); + glw_state.initialized = true; + + tr.framecount = tr.visframecount = 1; +} + +/* +=============== +R_Init +=============== +*/ +qboolean R_Init( void ) +{ + if( glw_state.initialized ) + return true; + + // give initial openGL configuration + Cbuf_AddText( "exec opengl.cfg\n" ); + + GL_InitCommands(); + GL_SetDefaultState(); + + // create the window and set up the context + if( !R_Init_OpenGL( )) + { + GL_RemoveCommands(); + R_Free_OpenGL(); + + // can't initialize video subsystem + Sys_NewInstance( va("#%s", GI->gamefolder ), "fallback to dedicated mode\n" ); + return false; + } + + renderinfo->modified = false; + r_temppool = Mem_AllocPool( "Render Zone" ); + + GL_InitExtensions(); + GL_SetDefaults(); + R_InitMathlib(); + R_InitImages(); + R_SpriteInit(); + R_StudioInit(); + R_InitDecals(); + R_ClearScene(); + + // initialize screen + SCR_Init(); + + GL_CheckForErrors(); + + return true; +} + +/* +=============== +R_Shutdown +=============== +*/ +void R_Shutdown( void ) +{ + int i; + + if( !glw_state.initialized ) + return; + + // release SpriteTextures + for( i = 1; i < MAX_IMAGES; i++ ) + { + if( !clgame.sprites[i].name[0] ) continue; + Mod_UnloadSpriteModel( &clgame.sprites[i] ); + } + Mem_Set( clgame.sprites, 0, sizeof( clgame.sprites )); + + GL_RemoveCommands(); + R_ShutdownImages(); + R_ShutdownDecals(); + + Mem_FreePool( &r_temppool ); + + // shut down OS specific OpenGL stuff like contexts, etc. + R_Free_OpenGL(); +} + +/* +================= +GL_CheckForErrors +================= +*/ +void GL_CheckForErrors_( const char *filename, const int fileline ) +{ + int err; + char *str; + + if( !gl_check_errors->integer ) + return; + + if(( err = pglGetError( )) == GL_NO_ERROR ) + return; + + switch( err ) + { + case GL_STACK_OVERFLOW: + str = "GL_STACK_OVERFLOW"; + break; + case GL_STACK_UNDERFLOW: + str = "GL_STACK_UNDERFLOW"; + break; + case GL_INVALID_ENUM: + str = "GL_INVALID_ENUM"; + break; + case GL_INVALID_VALUE: + str = "GL_INVALID_VALUE"; + break; + case GL_INVALID_OPERATION: + str = "GL_INVALID_OPERATION"; + break; + case GL_OUT_OF_MEMORY: + str = "GL_OUT_OF_MEMORY"; + break; + default: + str = "UNKNOWN ERROR"; + break; + } + + Host_Error( "GL_CheckForErrors: %s (called at %s:%i)\n", str, filename, fileline ); +} \ No newline at end of file diff --git a/engine/common/cm_local.h b/engine/common/cm_local.h index 2b2cd436..c2f4db52 100644 --- a/engine/common/cm_local.h +++ b/engine/common/cm_local.h @@ -46,7 +46,7 @@ typedef struct typedef struct { int version; // map version - uint checksum; // map checksum + uint checksum; // current map checksum int load_sequence; // increace each map change vec3_t hull_sizes[4]; // actual hull sizes msurface_t **draw_surfaces; // used for sorting translucent surfaces diff --git a/engine/common/com_export.h b/engine/common/com_export.h index 34567ae3..6f412865 100644 --- a/engine/common/com_export.h +++ b/engine/common/com_export.h @@ -83,6 +83,7 @@ void Mod_UnloadStudioModel( struct model_s *mod ); void Mod_UnloadBrushModel( struct model_s *mod ); void GL_SetRenderMode( int mode ); void R_RunViewmodelEvents( void ); +void R_DrawViewModel( void ); int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame ); void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLight, float radius ); void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, vec3_t saxis ); diff --git a/engine/common/common.h b/engine/common/common.h index 90747eea..d4cce1ab 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -161,6 +161,7 @@ void Host_EndGame( const char *message, ... ); void Host_AbortCurrentFrame( void ); void Host_WriteServerConfig( const char *name ); void Host_WriteOpenGLConfig( void ); +void Host_WriteVideoConfig( void ); void Host_WriteConfig( void ); qboolean Host_IsLocalGame( void ); void Host_ShutdownServer( void ); diff --git a/engine/common/con_utils.c b/engine/common/con_utils.c index 8c09fa30..0a3d7bb7 100644 --- a/engine/common/con_utils.c +++ b/engine/common/con_utils.c @@ -796,6 +796,12 @@ static void Cmd_WriteServerCvar(const char *name, const char *string, const char } static void Cmd_WriteOpenGLCvar( const char *name, const char *string, const char *desc, void *f ) +{ + if( !desc || !*desc ) return; // ignore cvars without description (fantom variables) + FS_Printf( f, "setgl %s \"%s\"\n", name, string ); +} + +static void Cmd_WriteRenderCvar( const char *name, const char *string, const char *desc, void *f ) { if( !desc || !*desc ) return; // ignore cvars without description (fantom variables) FS_Printf( f, "setr %s \"%s\"\n", name, string ); @@ -821,7 +827,12 @@ void Cmd_WriteServerVariables( file_t *f ) void Cmd_WriteOpenGLVariables( file_t *f ) { - Cvar_LookupVars( CVAR_RENDERINFO, NULL, f, Cmd_WriteOpenGLCvar ); + Cvar_LookupVars( CVAR_GLCONFIG, NULL, f, Cmd_WriteOpenGLCvar ); +} + +void Cmd_WriteRenderVariables( file_t *f ) +{ + Cvar_LookupVars( CVAR_RENDERINFO, NULL, f, Cmd_WriteRenderCvar ); } /* @@ -892,7 +903,7 @@ void Host_WriteServerConfig( const char *name ) =============== Host_WriteOpenGLConfig -save renderinfo variables into opengl.cfg +save opengl variables into opengl.cfg =============== */ void Host_WriteOpenGLConfig( void ) @@ -912,6 +923,30 @@ void Host_WriteOpenGLConfig( void ) else MsgDev( D_ERROR, "can't update opengl.cfg.\n" ); } +/* +=============== +Host_WriteVideoConfig + +save render variables into video.cfg +=============== +*/ +void Host_WriteVideoConfig( void ) +{ + file_t *f; + + f = FS_Open( "video.cfg", "w" ); + if( f ) + { + FS_Printf( f, "//=======================================================================\n" ); + FS_Printf( f, "//\t\t\tCopyright XashXT Group %s \n", timestamp( TIME_YEAR_ONLY )); + FS_Printf( f, "//\t\tvideo.cfg - archive of renderer variables\n"); + FS_Printf( f, "//=======================================================================\n" ); + Cmd_WriteRenderVariables( f ); + FS_Close( f ); + } + else MsgDev( D_ERROR, "can't update video.cfg.\n" ); +} + void Key_EnumCmds_f( void ) { file_t *f; diff --git a/engine/common/console.c b/engine/common/console.c index 67c4c561..88a7683e 100644 --- a/engine/common/console.c +++ b/engine/common/console.c @@ -185,12 +185,12 @@ void Con_ToggleConsole_f( void ) if( cls.key_dest == key_console ) { UI_SetActiveMenu( false ); - cls.key_dest = key_game; + Key_SetKeyDest( key_game ); } else { UI_SetActiveMenu( false ); - cls.key_dest = key_console; + Key_SetKeyDest( key_console ); } } @@ -406,7 +406,7 @@ static int Con_DrawGenericChar( int x, int y, int number, rgba_t color ) static int Con_DrawCharacter( int x, int y, int number, rgba_t color ) { - GL_SetRenderMode( kRenderTransTexture ); + GL_SetRenderMode( kRenderNormal ); return Con_DrawGenericChar( x, y, number, color ); } @@ -1409,7 +1409,7 @@ void Con_DrawConsole( void ) if( cls.key_dest != key_menu && host.developer ) { Con_DrawSolidConsole( 1.0f ); - cls.key_dest = key_console; + Key_SetKeyDest( key_console ); } break; case ca_connected: diff --git a/engine/common/host.c b/engine/common/host.c index 7c3610bb..cf0a4822 100644 --- a/engine/common/host.c +++ b/engine/common/host.c @@ -18,8 +18,6 @@ convar_t *host_limitlocal; convar_t *host_cheats; convar_t *host_maxfps; convar_t *host_framerate; -qboolean sound_restart; -qboolean video_restart; // these cvars will be duplicated on each client across network int Host_ServerState( void ) @@ -118,30 +116,6 @@ void Host_SetServerState( int state ) Cvar_FullSet( "host_serverstate", va( "%i", state ), CVAR_INIT ); } -/* -================= -Host_VidRestart_f - -Restart the video subsystem -================= -*/ -void Host_VidRestart_f( void ) -{ - video_restart = true; -} - -/* -================= -Host_SndRestart_f - -Restart the audio subsystem -================= -*/ -void Host_SndRestart_f( void ) -{ - sound_restart = true; -} - /* ================= Host_ChangeGame_f @@ -611,18 +585,16 @@ void Host_Init( const int argc, const char **argv ) host_limitlocal = Cvar_Get( "host_limitlocal", "0", 0, "apply cl_cmdrate and rate to loopback connection" ); // content control - Cvar_Get( "violence_hgibs", "1", CVAR_INIT|CVAR_ARCHIVE, "content control disables human gibs" ); - Cvar_Get( "violence_agibs", "1", CVAR_INIT|CVAR_ARCHIVE, "content control disables alien gibs" ); - Cvar_Get( "violence_hblood", "1", CVAR_INIT|CVAR_ARCHIVE, "content control disables human blood" ); - Cvar_Get( "violence_ablood", "1", CVAR_INIT|CVAR_ARCHIVE, "content control disables alien blood" ); - - video_restart = true; // initalize renderer - sound_restart = true; // initialize sound engine + Cvar_Get( "violence_hgibs", "1", CVAR_ARCHIVE, "show human gib entities" ); + Cvar_Get( "violence_agibs", "1", CVAR_ARCHIVE, "show alien gib entities" ); + Cvar_Get( "violence_hblood", "1", CVAR_ARCHIVE, "draw human blood" ); + Cvar_Get( "violence_ablood", "1", CVAR_ARCHIVE, "draw alien blood" ); if( host.type != HOST_DEDICATED ) { // when we in developer-mode automatically turn cheats on if( host.developer > 1 ) Cvar_SetFloat( "sv_cheats", 1.0f ); + Cbuf_AddText( "exec video.cfg\n" ); } Mod_Init(); @@ -647,8 +619,6 @@ void Host_Init( const int argc, const char **argv ) else { Cmd_AddCommand( "minimize", Host_Minimize_f, "minimize main window to tray" ); - Cmd_AddCommand( "vid_restart", Host_VidRestart_f, "restarts video system" ); - Cmd_AddCommand( "snd_restart", Host_SndRestart_f, "restarts audio system" ); Cbuf_AddText( "exec config.cfg\n" ); } diff --git a/engine/common/input.c b/engine/common/input.c index c61f292c..30ec5497 100644 --- a/engine/common/input.c +++ b/engine/common/input.c @@ -32,10 +32,6 @@ RECT window_rect, real_rect; uint in_mouse_wheel; int wnd_caption; -convar_t *scr_xpos; // X coordinate of window position -convar_t *scr_ypos; // Y coordinate of window position -convar_t *scr_fullscreen; - static byte scan_to_key[128] = { 0,27,'1','2','3','4','5','6','7','8','9','0','-','=',K_BACKSPACE,9, @@ -188,7 +184,7 @@ void IN_ActivateMouse( void ) if( !in_mouseinitialized ) return; - if( cls.key_dest == key_menu && !scr_fullscreen->integer ) + if( cls.key_dest == key_menu && !Cvar_VariableInteger( "fullscreen" )) { // check for mouse leave-entering if( !in_mouse_suspended && !UI_MouseInRect( )) @@ -439,7 +435,7 @@ long IN_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam ) switch( uMsg ) { case WM_KILLFOCUS: - if( scr_fullscreen && scr_fullscreen->integer ) + if( Cvar_VariableInteger( "fullscreen" )) ShowWindow( host.hWnd, SW_SHOWMINNOACTIVE ); break; case WM_MOUSEWHEEL: @@ -457,9 +453,6 @@ long IN_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam ) break; case WM_CREATE: host.hWnd = hWnd; - scr_xpos = Cvar_Get( "r_xpos", "130", CVAR_RENDERINFO, "window position by horizontal" ); - scr_ypos = Cvar_Get( "r_ypos", "48", CVAR_RENDERINFO, "window position by vertical" ); - scr_fullscreen = Cvar_Get( "fullscreen", "0", CVAR_RENDERINFO|CVAR_LATCH_VIDEO, "toggle fullscreen" ); GetWindowRect( host.hWnd, &real_rect ); break; case WM_CLOSE: @@ -486,13 +479,13 @@ long IN_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam ) SetForegroundWindow( hWnd ); ShowWindow( hWnd, SW_RESTORE ); } - else if( scr_fullscreen->integer && host.state != HOST_RESTART ) + else if( Cvar_VariableInteger( "fullscreen" ) && host.state != HOST_RESTART ) { ShowWindow( hWnd, SW_MINIMIZE ); } break; case WM_MOVE: - if( !scr_fullscreen->integer ) + if( !Cvar_VariableInteger( "fullscreen" )) { RECT rect; int xPos, yPos, style; @@ -507,8 +500,6 @@ long IN_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam ) Cvar_SetFloat( "r_xpos", xPos + rect.left ); Cvar_SetFloat( "r_ypos", yPos + rect.top ); - scr_xpos->modified = false; - scr_ypos->modified = false; GetWindowRect( host.hWnd, &real_rect ); } break; diff --git a/engine/common/keys.c b/engine/common/keys.c index d6e19a87..e6871ffb 100644 --- a/engine/common/keys.c +++ b/engine/common/keys.c @@ -538,7 +538,7 @@ void Key_Event( int key, qboolean down ) case key_console: if( cls.state == ca_active ) { - cls.key_dest = key_game; + Key_SetKeyDest( key_game ); } else { diff --git a/engine/common/model.c b/engine/common/model.c index 34e08505..355d5f3d 100644 --- a/engine/common/model.c +++ b/engine/common/model.c @@ -857,6 +857,9 @@ static void Mod_LoadSurfaces( const dlump_t *l ) if( com.stristr( tex->name, "scroll" )) out->flags |= SURF_CONVEYOR; + if( tex->name[0] == '{' ) + out->flags |= SURF_TRANSPARENT; + if( out->texinfo->flags & TEX_SPECIAL ) out->flags |= SURF_DRAWTILED; } @@ -1605,13 +1608,13 @@ Mod_LoadModel Loads a model into the cache ================== */ -model_t *Mod_LoadModel( model_t *mod, qboolean isWorld ) +model_t *Mod_LoadModel( model_t *mod, qboolean crash ) { byte *buf; if( !mod ) { - if( isWorld ) Host_Error( "Mod_ForName: NULL model\n" ); + if( crash ) Host_Error( "Mod_ForName: NULL model\n" ); else MsgDev( D_ERROR, "Mod_ForName: NULL model\n" ); return NULL; } @@ -1623,16 +1626,12 @@ model_t *Mod_LoadModel( model_t *mod, qboolean isWorld ) buf = FS_LoadFile( mod->name, NULL ); if( !buf ) { - if( isWorld ) Host_Error( "Mod_ForName: %s couldn't load\n", mod->name ); + if( crash ) Host_Error( "Mod_ForName: %s couldn't load\n", mod->name ); else MsgDev( D_ERROR, "Mod_ForName: %s couldn't load\n", mod->name ); Mem_Set( mod, 0, sizeof( model_t )); return NULL; } - // if it's world - calc the map checksum - if( isWorld ) CRC32_MapFile( &world.checksum, mod->name ); - world.loading = isWorld; - MsgDev( D_NOTE, "Mod_LoadModel: %s\n", mod->name ); mod->needload = world.load_sequence; // register mod mod->type = mod_bad; @@ -1660,7 +1659,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean isWorld ) Mod_FreeModel( mod ); // check for loading problems - if( isWorld ) Host_Error( "Mod_ForName: %s unknown format\n", mod->name ); + if( crash ) Host_Error( "Mod_ForName: %s unknown format\n", mod->name ); else MsgDev( D_ERROR, "Mod_ForName: %s unknown format\n", mod->name ); return NULL; } @@ -1674,12 +1673,12 @@ Mod_ForName Loads in a model for the given name ================== */ -model_t *Mod_ForName( const char *name, qboolean world ) +model_t *Mod_ForName( const char *name, qboolean crash ) { model_t *mod; mod = Mod_FindName( name, true ); - return Mod_LoadModel( mod, world ); + return Mod_LoadModel( mod, crash ); } /* @@ -1720,10 +1719,14 @@ void Mod_LoadWorld( const char *name, uint *checksum ) world.load_sequence++; // now all models are invalid // load the newmap + world.loading = true; worldmodel = Mod_ForName( name, true ); com_models[1] = cm_models; // make link to world - if( checksum ) *checksum = world.checksum; + CRC32_MapFile( &world.checksum, worldmodel->name ); + world.loading = false; + if( checksum ) *checksum = world.checksum; + // calc Potentially Hearable Set and compress it Mod_CalcPHS(); } diff --git a/engine/common/net_encode.c b/engine/common/net_encode.c index f2a79b6e..8fcf8267 100644 --- a/engine/common/net_encode.c +++ b/engine/common/net_encode.c @@ -413,7 +413,7 @@ qboolean Delta_AddField( const char *pStructName, const char *pName, int flags, { if( !com.strcmp( pField->name, pName )) { - MsgDev( D_ERROR, "Delta_Add: %s->%s already existing\n", pStructName, pName ); + MsgDev( D_NOTE, "Delta_Add: %s->%s already existing\n", pStructName, pName ); return false; // field already exist } } @@ -743,6 +743,9 @@ void Delta_InitFields( void ) // adding some requrid fields fields that use may forget or don't know how to specified Delta_AddField( "event_t", "flags", DT_INTEGER, 8, 1.0f, 1.0f ); + Delta_AddField( "event_t", "velocity[0]", DT_SIGNED | DT_FLOAT, 16, 8.0f, 1.0f ); + Delta_AddField( "event_t", "velocity[1]", DT_SIGNED | DT_FLOAT, 16, 8.0f, 1.0f ); + Delta_AddField( "event_t", "velocity[2]", DT_SIGNED | DT_FLOAT, 16, 8.0f, 1.0f ); } void Delta_Init( void ) diff --git a/engine/server/server.h b/engine/server/server.h index a3f6b7da..9874f0f9 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -377,6 +377,7 @@ extern convar_t *sv_allow_upload; extern convar_t *sv_allow_download; extern convar_t *sv_send_resources; extern convar_t *sv_send_logos; +extern convar_t *sv_sendvelocity; extern convar_t *mp_consistency; extern convar_t *physinfo; extern sv_client_t *sv_client; diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index 2b33736f..affe73b9 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -1480,13 +1480,7 @@ int pfnDropToFloor( edict_t* e ) VectorCopy( e->v.origin, end ); end[2] -= 256; -#if 1 - if( e->v.solid == SOLID_TRIGGER || e->v.solid == SOLID_NOT ) - trace = SV_Move( e->v.origin, vec3_origin, vec3_origin, end, MOVE_NOMONSTERS, e ); - else trace = SV_Move( e->v.origin, e->v.mins, e->v.maxs, end, MOVE_NORMAL, e ); -#else trace = SV_Move( e->v.origin, e->v.mins, e->v.maxs, end, MOVE_NORMAL, e ); -#endif if( trace.allsolid ) return -1; @@ -3565,7 +3559,8 @@ void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex, // silently replace it with viewangles, client expected this VectorCopy( pInvoker->v.v_angle, args.angles ); } - VectorCopy( pInvoker->v.velocity, args.velocity ); + + if( sv_sendvelocity->integer ) VectorCopy( pInvoker->v.velocity, args.velocity ); args.ducking = (pInvoker->v.flags & FL_DUCKING) ? true : false; } diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 0c286bff..2d99c098 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -52,6 +52,7 @@ convar_t *sv_allow_upload; convar_t *sv_allow_download; convar_t *sv_send_resources; convar_t *sv_send_logos; +convar_t *sv_sendvelocity; convar_t *mp_consistency; convar_t *serverinfo; convar_t *physinfo; @@ -644,6 +645,7 @@ void SV_Init( void ) sv_allow_download = Cvar_Get( "sv_allow_download", "1", 0, "allow download missed resources to clients" ); sv_send_logos = Cvar_Get( "sv_send_logos", "1", 0, "send custom player decals to other clients" ); sv_send_resources = Cvar_Get( "sv_send_resources", "1", 0, "send generic resources that specified in 'mapname.res'" ); + sv_sendvelocity = Cvar_Get( "sv_sendvelocity", "1", CVAR_ARCHIVE, "force to send velocity for event_t structure across network" ); mp_consistency = Cvar_Get( "mp_consistency", "1", CVAR_SERVERNOTIFY, "enbale consistency check in multiplayer" ); clockwindow = Cvar_Get( "clockwindow", "0.5", 0, "timewindow to execute client moves" ); sv_novis = Cvar_Get( "sv_novis", "0", 0, "force to ignore server visibility" ); diff --git a/engine/server/sv_save.c b/engine/server/sv_save.c index ac53f4ae..1907233a 100644 --- a/engine/server/sv_save.c +++ b/engine/server/sv_save.c @@ -421,7 +421,7 @@ void ReapplyDecal( SAVERESTOREDATA *pSaveData, decallist_t *entry, qboolean adja edict_t *pEdict = pSaveData->pTable[entry->entityIndex].pent; if( pEdict != NULL ) modelIndex = pEdict->v.modelindex; - SV_CreateDecal( entry->position, decalIndex, entry->entityIndex, modelIndex, flags ); + SV_CreateDecal( entry->position, decalIndex, pEdict->serialnumber, modelIndex, flags ); } } diff --git a/launch/crclib.c b/launch/crclib.c index d2212374..43538807 100644 --- a/launch/crclib.c +++ b/launch/crclib.c @@ -227,6 +227,7 @@ qboolean CRC32_MapFile( dword *crcvalue, const char *filename ) int i, num_bytes, lumplen; qboolean blue_shift = false; + if( !crcvalue ) return false; f = FS_Open( filename, "rb", false ); if( !f ) return false; diff --git a/launch/cvar.c b/launch/cvar.c index 51fc7a37..7bd24b19 100644 --- a/launch/cvar.c +++ b/launch/cvar.c @@ -6,7 +6,7 @@ #include "launch.h" convar_t *cvar_vars; // head of list -convar_t *userinfo, *physinfo, *serverinfo; +convar_t *userinfo, *physinfo, *serverinfo, *renderinfo; /* ============ @@ -345,7 +345,7 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) if( !force ) { - if( var->flags & CVAR_READ_ONLY ) + if( var->flags & ( CVAR_READ_ONLY|CVAR_GLCONFIG )) { MsgDev( D_INFO, "%s is read only.\n", var_name ); return var; @@ -357,13 +357,7 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) return var; } - if( var->flags & CVAR_RENDERINFO ) - { - MsgDev( D_INFO, "%s is a renderer config variable.\n", var_name ); - return var; - } - - if( var->flags & ( CVAR_LATCH|CVAR_LATCH_VIDEO|CVAR_LATCH_AUDIO )) + if( var->flags & ( CVAR_LATCH|CVAR_LATCH_VIDEO )) { if( var->latched_string ) { @@ -387,11 +381,6 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) MsgDev( D_INFO, "%s will be changed upon restarting video.\n", var->name ); var->latched_string = copystring( value ); } - else if( var->flags & CVAR_LATCH_AUDIO ) - { - MsgDev( D_INFO, "%s will be changed upon restarting audio.\n", var->name ); - var->latched_string = copystring( value ); - } else { Mem_Free( var->string ); // free the old value string @@ -472,6 +461,8 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) if( var->flags & CVAR_SERVERINFO ) serverinfo->modified = true; // transmit at next oportunity + if( var->flags & CVAR_RENDERINFO ) + renderinfo->modified = true; // transmit at next oportunity // free the old value string Mem_Free( var->string ); @@ -550,6 +541,12 @@ void Cvar_FullSet( const char *var_name, const char *value, int flags ) serverinfo->modified = true; } + if( var->flags & CVAR_RENDERINFO ) + { + // transmit at next oportunity + renderinfo->modified = true; + } + Mem_Free( var->string ); // free the old value string var->string = copystring( value ); var->value = com.atof( var->string ); @@ -586,7 +583,7 @@ void Cvar_DirectSet( cvar_t *var, const char *value ) if( !value ) value = "0"; - if( var->flags & ( CVAR_READ_ONLY|CVAR_INIT|CVAR_RENDERINFO|CVAR_LATCH|CVAR_LATCH_VIDEO|CVAR_LATCH_AUDIO )) + if( var->flags & ( CVAR_READ_ONLY|CVAR_GLCONFIG|CVAR_INIT|CVAR_RENDERINFO|CVAR_LATCH|CVAR_LATCH_VIDEO )) { // Cvar_DirectSet cannot change these cvars at all return; @@ -650,6 +647,9 @@ void Cvar_DirectSet( cvar_t *var, const char *value ) if( var->flags & CVAR_SERVERINFO ) serverinfo->modified = true; // transmit at next oportunity + if( var->flags & CVAR_RENDERINFO ) + renderinfo->modified = true; // transmit at next oportunity + // free the old value string Mem_Free( var->string ); var->string = copystring( pszValue ); @@ -910,6 +910,23 @@ void Cvar_SetR_f( void ) Cvar_FullSet( Cmd_Argv( 1 ), Cmd_Argv( 2 ), CVAR_RENDERINFO ); } +/* +============ +Cvar_SetGL_f + +As Cvar_Set, but also flags it as glconfig +============ +*/ +void Cvar_SetGL_f( void ) +{ + if( Cmd_Argc() != 3 ) + { + Msg( "Usage: setgl \n" ); + return; + } + + Cvar_FullSet( Cmd_Argv( 1 ), Cmd_Argv( 2 ), CVAR_GLCONFIG ); +} /* ============ @@ -945,34 +962,34 @@ void Cvar_List_f( void ) if( match && !com.stricmpext( match, var->name )) continue; - if( var->flags & CVAR_SERVERINFO ) Msg( "SV " ); + if( var->flags & CVAR_SERVERINFO ) Msg( "SV " ); else Msg( " " ); - if( var->flags & CVAR_USERINFO ) Msg( "USER " ); + if( var->flags & CVAR_USERINFO ) Msg( "USER " ); else Msg( " " ); - if( var->flags & CVAR_PHYSICINFO ) Msg( "PHYS " ); + if( var->flags & CVAR_PHYSICINFO ) Msg( "PHYS " ); else Msg( " " ); - if( var->flags & CVAR_READ_ONLY ) Msg( "READ " ); + if( var->flags & CVAR_READ_ONLY ) Msg( "READ " ); else Msg( " " ); - if( var->flags & CVAR_INIT ) Msg( "INIT " ); + if( var->flags & CVAR_INIT ) Msg( "INIT " ); else Msg( " " ); - if( var->flags & CVAR_ARCHIVE ) Msg( "ARCH " ); + if( var->flags & CVAR_ARCHIVE ) Msg( "ARCH " ); else Msg( " " ); - if( var->flags & CVAR_LATCH ) Msg( "LATCH" ); + if( var->flags & CVAR_LATCH ) Msg( "LATCH " ); else Msg( " " ); - if( var->flags & CVAR_LATCH_VIDEO ) Msg( "VIDEO" ); + if( var->flags & CVAR_LATCH_VIDEO ) Msg( "VIDEO " ); else Msg( " " ); - if( var->flags & CVAR_LATCH_AUDIO ) Msg( "AUDIO" ); + if( var->flags & CVAR_GLCONFIG ) Msg( "OPENGL" ); else Msg( " " ); - if( var->flags & CVAR_CHEAT ) Msg( "CHEAT" ); + if( var->flags & CVAR_CHEAT ) Msg( "CHEAT " ); else Msg( " " ); Msg(" %s \"%s\"\n", var->name, var->string ); j++; @@ -1003,7 +1020,7 @@ void Cvar_Restart_f( void ) // don't mess with rom values, or some inter-module // communication will get broken (cl.active, etc) - if( var->flags & ( CVAR_READ_ONLY|CVAR_INIT|CVAR_RENDERINFO|CVAR_EXTDLL )) + if( var->flags & ( CVAR_READ_ONLY|CVAR_GLCONFIG|CVAR_INIT|CVAR_RENDERINFO|CVAR_EXTDLL )) { prev = &var->next; continue; @@ -1098,41 +1115,6 @@ void Cvar_LatchedVideo_f( void ) } } -/* -============ -Cvar_Latched_f - -Now all latched audio strings is valid -============ -*/ -void Cvar_LatchedAudio_f( void ) -{ - convar_t *var; - convar_t **prev; - - prev = &cvar_vars; - - while ( 1 ) - { - var = *prev; - if( !var ) break; - - if( var->flags & CVAR_EXTDLL ) - { - prev = &var->next; - continue; - } - - if( var->flags & CVAR_LATCH_AUDIO && var->latched_string ) - { - Cvar_FullSet( var->name, var->latched_string, var->flags ); - Mem_Free( var->latched_string ); - var->latched_string = NULL; - } - prev = &var->next; - } -} - /* ============ Cvar_Unlink_f @@ -1186,6 +1168,7 @@ void Cvar_Init( void ) userinfo = Cvar_Get( "@userinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only physinfo = Cvar_Get( "@physinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only serverinfo = Cvar_Get( "@serverinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only + renderinfo = Cvar_Get( "@renderinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only Cmd_AddCommand ("toggle", Cvar_Toggle_f, "toggles a console variable's values (use for more info)" ); Cmd_AddCommand ("set", Cvar_Set_f, "create or change the value of a console variable" ); @@ -1193,11 +1176,11 @@ void Cvar_Init( void ) Cmd_AddCommand ("setu", Cvar_SetU_f, "create or change the value of a userinfo variable" ); Cmd_AddCommand ("setp", Cvar_SetP_f, "create or change the value of a physicinfo variable" ); Cmd_AddCommand ("setr", Cvar_SetR_f, "create or change the value of a renderinfo variable" ); + Cmd_AddCommand ("setgl", Cvar_SetGL_f, "create or change the value of a opengl variable" ); Cmd_AddCommand ("seta", Cvar_SetA_f, "create or change the value of a console variable that will be saved to config.cfg" ); Cmd_AddCommand ("reset", Cvar_Reset_f, "reset any type variable to initial value" ); Cmd_AddCommand ("latch", Cvar_Latched_f, "apply latched values" ); Cmd_AddCommand ("vidlatch", Cvar_LatchedVideo_f, "apply latched values for video subsystem" ); - Cmd_AddCommand ("sndlatch", Cvar_LatchedAudio_f, "apply latched values for audio subsytem" ); Cmd_AddCommand ("cvarlist", Cvar_List_f, "display all console variables beginning with the specified prefix" ); Cmd_AddCommand ("unsetall", Cvar_Restart_f, "reset all console variables to their default values" ); Cmd_AddCommand ("@unlink", Cvar_Unlink_f, "unlink static cvars defined in gamedll" ); diff --git a/launch/imagelib/imagelib.h b/launch/imagelib/imagelib.h index 36e07554..e261c7d6 100644 --- a/launch/imagelib/imagelib.h +++ b/launch/imagelib/imagelib.h @@ -213,6 +213,7 @@ enum { LUMP_NORMAL = 0, LUMP_TRANSPARENT, + LUMP_INDEXALPHA, LUMP_DECAL, LUMP_QFONT, LUMP_EXTENDED // bmp images have extened palette with alpha-channel diff --git a/launch/imagelib/img_utils.c b/launch/imagelib/img_utils.c index f1cda80b..834424d4 100644 --- a/launch/imagelib/img_utils.c +++ b/launch/imagelib/img_utils.c @@ -438,6 +438,16 @@ void Image_SetPalette( const byte *pal, uint *d_table ) d_table[i] = *(uint *)rgba; } break; + case LUMP_INDEXALPHA: + for( i = 0; i < 256; i++ ) + { + rgba[0] = pal[i*3+0]; + rgba[1] = pal[i*3+1]; + rgba[2] = pal[i*3+2]; + rgba[3] = i; + d_table[i] = *(uint *)rgba; + } + break; case LUMP_TRANSPARENT: for( i = 0; i < 256; i++ ) { diff --git a/launch/imagelib/img_wad.c b/launch/imagelib/img_wad.c index 9edc2f53..1d077639 100644 --- a/launch/imagelib/img_wad.c +++ b/launch/imagelib/img_wad.c @@ -33,6 +33,8 @@ qboolean Image_LoadPAL( const char *name, const byte *buffer, size_t filesize ) rendermode = LUMP_TRANSPARENT; else if( com.stristr( name, "decal" )) rendermode = LUMP_DECAL; + else if( com.stristr( name, "indexalpha" )) + rendermode = LUMP_INDEXALPHA; else if( com.stristr( name, "qfont" )) rendermode = LUMP_QFONT; else if( com.stristr( name, "valve" )) @@ -224,7 +226,7 @@ qboolean Image_LoadSPR( const char *name, const byte *buffer, size_t filesize ) image.type = PF_INDEXED_32; // 32-bit palete // detect alpha-channel by palette type - if( image.d_rendermode == LUMP_DECAL || image.d_rendermode == LUMP_TRANSPARENT ) + if( image.d_rendermode == LUMP_INDEXALPHA || image.d_rendermode == LUMP_TRANSPARENT ) image.flags |= IMAGE_HAS_ALPHA; // make transparent color is black, blue color looks ugly diff --git a/launch/system.c b/launch/system.c index a19047a5..6cd5d437 100644 --- a/launch/system.c +++ b/launch/system.c @@ -491,6 +491,7 @@ void Sys_CreateInstance( void ) } Cmd_RemoveCommand( "setr" ); // remove potentially backdoor for change render settings + Cmd_RemoveCommand( "setgl" ); Sys.app_state = SYS_FRAME; // system is now active } diff --git a/mainui/basemenu.cpp b/mainui/basemenu.cpp index c4b5c472..88342b64 100644 --- a/mainui/basemenu.cpp +++ b/mainui/basemenu.cpp @@ -807,7 +807,16 @@ void UI_PopMenu( void ) uiStatic.menuActive = uiStatic.menuStack[uiStatic.menuDepth-1]; uiStatic.firstDraw = true; } - else UI_CloseMenu(); + else if ( CL_IsActive( )) + { + UI_CloseMenu(); + } + else + { + // never trying the close menu when client isn't connected + KEY_SetDest( KEY_MENU ); + UI_Main_Menu(); + } } // ===================================================================== @@ -1244,6 +1253,16 @@ int UI_VidInit( void ) // register ui font uiStatic.hFont = PIC_Load( "menufont", font_tga, sizeof( font_tga )); + // now recalc all the menus in stack + for( int i = 0; i < uiStatic.menuDepth; i++ ) + { + menuFramework_s *item = uiStatic.menuStack[i]; + + // do vid restart for all pushed elements + if( item && item->vidInitFunc ) + item->vidInitFunc(); + } + return 1; } diff --git a/mainui/basemenu.h b/mainui/basemenu.h index 48637f05..3ff0069c 100644 --- a/mainui/basemenu.h +++ b/mainui/basemenu.h @@ -130,6 +130,7 @@ typedef struct void (*drawFunc)( void ); const char *(*keyFunc)( int key, int down ); void (*activateFunc)( void ); + void (*vidInitFunc)( void ); } menuFramework_s; typedef struct diff --git a/mainui/menu_advcontrols.cpp b/mainui/menu_advcontrols.cpp index bd084623..ce898576 100644 --- a/mainui/menu_advcontrols.cpp +++ b/mainui/menu_advcontrols.cpp @@ -182,6 +182,8 @@ static void UI_AdvControls_Init( void ) { memset( &uiAdvControls, 0, sizeof( uiAdvControls_t )); + uiAdvControls.menu.vidInitFunc = UI_AdvControls_Init; + uiAdvControls.background.generic.id = ID_BACKGROUND; uiAdvControls.background.generic.type = QMTYPE_BITMAP; uiAdvControls.background.generic.flags = QMF_INACTIVE; diff --git a/mainui/menu_audio.cpp b/mainui/menu_audio.cpp index 8a382d4f..fd015e34 100644 --- a/mainui/menu_audio.cpp +++ b/mainui/menu_audio.cpp @@ -124,8 +124,6 @@ static void UI_Audio_SetConfig( void ) CVAR_SET_FLOAT( "musicvolume", uiAudio.musicVolume.curValue ); CVAR_SET_FLOAT( "s_lerping", uiAudio.lerping.enabled ); CVAR_SET_FLOAT( "dsp_off", uiAudio.noDSP.enabled ); - - CLIENT_COMMAND( TRUE, "snd_restart\n" ); } /* @@ -202,6 +200,8 @@ static void UI_Audio_Init( void ) { memset( &uiAudio, 0, sizeof( uiAudio_t )); + uiAudio.menu.vidInitFunc = UI_Audio_Init; + strcat( uiAudio.hintText, "Change Xash3D sound engine to get more compatibility\n" ); strcat( uiAudio.hintText, "or enable new features (EAX, Filters etc)" ); diff --git a/mainui/menu_configuration.cpp b/mainui/menu_configuration.cpp index 88ef7d15..decc6fdb 100644 --- a/mainui/menu_configuration.cpp +++ b/mainui/menu_configuration.cpp @@ -151,6 +151,7 @@ static void UI_Options_Init( void ) { memset( &uiOptions, 0, sizeof( uiOptions_t )); + uiOptions.menu.vidInitFunc = UI_Options_Init; uiOptions.menu.keyFunc = UI_Options_KeyFunc; uiOptions.background.generic.id = ID_BACKGROUND; diff --git a/mainui/menu_controls.cpp b/mainui/menu_controls.cpp index f6e600a0..97d0fef5 100644 --- a/mainui/menu_controls.cpp +++ b/mainui/menu_controls.cpp @@ -393,6 +393,7 @@ static void UI_Controls_Init( void ) { memset( &uiControls, 0, sizeof( uiControls_t )); + uiControls.menu.vidInitFunc = UI_Controls_Init; uiControls.menu.keyFunc = UI_Controls_KeyFunc; StringConcat( uiControls.hintText, "Action", CMD_LENGTH ); diff --git a/mainui/menu_creategame.cpp b/mainui/menu_creategame.cpp index c9abf827..a5eabbfe 100644 --- a/mainui/menu_creategame.cpp +++ b/mainui/menu_creategame.cpp @@ -261,6 +261,7 @@ static void UI_CreateGame_Init( void ) { memset( &uiCreateGame, 0, sizeof( uiCreateGame_t )); + uiCreateGame.menu.vidInitFunc = UI_CreateGame_Init; uiCreateGame.menu.keyFunc = UI_CreateGame_KeyFunc; StringConcat( uiCreateGame.hintText, "Map", MAPNAME_LENGTH ); diff --git a/mainui/menu_customgame.cpp b/mainui/menu_customgame.cpp index fe139c77..bf98c1dd 100644 --- a/mainui/menu_customgame.cpp +++ b/mainui/menu_customgame.cpp @@ -221,6 +221,7 @@ static void UI_CustomGame_Init( void ) { memset( &uiCustomGame, 0, sizeof( uiCustomGame_t )); + uiCustomGame.menu.vidInitFunc = UI_CustomGame_Init; uiCustomGame.menu.keyFunc = UI_CustomGame_KeyFunc; StringConcat( uiCustomGame.hintText, "Type", TYPE_LENGTH ); diff --git a/mainui/menu_gameoptions.cpp b/mainui/menu_gameoptions.cpp index 20b7b785..207dd9f9 100644 --- a/mainui/menu_gameoptions.cpp +++ b/mainui/menu_gameoptions.cpp @@ -179,6 +179,7 @@ static void UI_GameOptions_Init( void ) memset( &uiGameInitial, 0, sizeof( uiGameValues_t )); memset( &uiGameOptions, 0, sizeof( uiGameOptions_t )); + uiGameOptions.menu.vidInitFunc = UI_GameOptions_Init; uiGameOptions.menu.keyFunc = UI_GameOptions_KeyFunc; uiGameOptions.background.generic.id = ID_BACKGROUND; diff --git a/mainui/menu_langame.cpp b/mainui/menu_langame.cpp index de671d82..8a1238da 100644 --- a/mainui/menu_langame.cpp +++ b/mainui/menu_langame.cpp @@ -259,6 +259,7 @@ static void UI_LanGame_Init( void ) { memset( &uiLanGame, 0, sizeof( uiLanGame_t )); + uiLanGame.menu.vidInitFunc = UI_LanGame_Init; uiLanGame.menu.keyFunc = UI_LanGame_KeyFunc; StringConcat( uiLanGame.hintText, "Game", GAME_LENGTH ); diff --git a/mainui/menu_loadgame.cpp b/mainui/menu_loadgame.cpp index e5f80586..16513be8 100644 --- a/mainui/menu_loadgame.cpp +++ b/mainui/menu_loadgame.cpp @@ -292,6 +292,7 @@ static void UI_LoadGame_Init( void ) { memset( &uiLoadGame, 0, sizeof( uiLoadGame_t )); + uiLoadGame.menu.vidInitFunc = UI_LoadGame_Init; uiLoadGame.menu.keyFunc = UI_LoadGame_KeyFunc; StringConcat( uiLoadGame.hintText, "Time", TIME_LENGTH ); diff --git a/mainui/menu_main.cpp b/mainui/menu_main.cpp index 0f044462..0ac32754 100644 --- a/mainui/menu_main.cpp +++ b/mainui/menu_main.cpp @@ -322,6 +322,10 @@ static void UI_Main_Init( void ) { memset( &uiMain, 0, sizeof( uiMain_t )); + // precache .avi file and get logo width and height + PRECACHE_LOGO( "logo.avi" ); + + uiMain.menu.vidInitFunc = UI_Main_Init; uiMain.menu.keyFunc = UI_Main_KeyFunc; uiMain.menu.activateFunc = UI_Main_ActivateFunc; diff --git a/mainui/menu_multiplayer.cpp b/mainui/menu_multiplayer.cpp index 04d845f7..7abd50ad 100644 --- a/mainui/menu_multiplayer.cpp +++ b/mainui/menu_multiplayer.cpp @@ -93,6 +93,8 @@ static void UI_MultiPlayer_Init( void ) { memset( &uiMultiPlayer, 0, sizeof( uiMultiPlayer_t )); + uiMultiPlayer.menu.vidInitFunc = UI_MultiPlayer_Init; + uiMultiPlayer.background.generic.id = ID_BACKGROUND; uiMultiPlayer.background.generic.type = QMTYPE_BITMAP; uiMultiPlayer.background.generic.flags = QMF_INACTIVE; diff --git a/mainui/menu_newgame.cpp b/mainui/menu_newgame.cpp index d1cd8038..6db3d95b 100644 --- a/mainui/menu_newgame.cpp +++ b/mainui/menu_newgame.cpp @@ -178,6 +178,7 @@ static void UI_NewGame_Init( void ) { memset( &uiNewGame, 0, sizeof( uiNewGame_t )); + uiNewGame.menu.vidInitFunc = UI_NewGame_Init; uiNewGame.menu.keyFunc = UI_NewGame_KeyFunc; uiNewGame.background.generic.id = ID_BACKGROUND; diff --git a/mainui/menu_playdemo.cpp b/mainui/menu_playdemo.cpp index e359759d..cb6f3e37 100644 --- a/mainui/menu_playdemo.cpp +++ b/mainui/menu_playdemo.cpp @@ -296,6 +296,7 @@ static void UI_PlayDemo_Init( void ) { memset( &uiPlayDemo, 0, sizeof( uiPlayDemo_t )); + uiPlayDemo.menu.vidInitFunc = UI_PlayDemo_Init; uiPlayDemo.menu.keyFunc = UI_PlayDemo_KeyFunc; StringConcat( uiPlayDemo.hintText, "Title", TITLE_LENGTH ); diff --git a/mainui/menu_playersetup.cpp b/mainui/menu_playersetup.cpp index e1c6c752..f3076425 100644 --- a/mainui/menu_playersetup.cpp +++ b/mainui/menu_playersetup.cpp @@ -266,6 +266,8 @@ static void UI_PlayerSetup_Init( void ) { memset( &uiPlayerSetup, 0, sizeof( uiPlayerSetup_t )); + uiPlayerSetup.menu.vidInitFunc = UI_PlayerSetup_Init; + uiPlayerSetup.background.generic.id = ID_BACKGROUND; uiPlayerSetup.background.generic.type = QMTYPE_BITMAP; uiPlayerSetup.background.generic.flags = QMF_INACTIVE; diff --git a/mainui/menu_playrec.cpp b/mainui/menu_playrec.cpp index d4e77d06..94b154cf 100644 --- a/mainui/menu_playrec.cpp +++ b/mainui/menu_playrec.cpp @@ -85,6 +85,8 @@ static void UI_PlayRec_Init( void ) { memset( &uiPlayRec, 0, sizeof( uiPlayRec_t )); + uiPlayRec.menu.vidInitFunc = UI_PlayRec_Init; + strcat( uiPlayRec.hintText, "During play or record demo, you can quickly stop\n" ); strcat( uiPlayRec.hintText, "playing/recording demo by pressing " ); strcat( uiPlayRec.hintText, KEY_KeynumToString( KEY_GetKey( "stop" ))); diff --git a/mainui/menu_recdemo.cpp b/mainui/menu_recdemo.cpp index 88db3183..c57c8c9e 100644 --- a/mainui/menu_recdemo.cpp +++ b/mainui/menu_recdemo.cpp @@ -322,6 +322,7 @@ static void UI_RecDemo_Init( void ) { memset( &uiRecDemo, 0, sizeof( uiRecDemo_t )); + uiRecDemo.menu.vidInitFunc = UI_RecDemo_Init; uiRecDemo.menu.keyFunc = UI_RecDemo_KeyFunc; StringConcat( uiRecDemo.hintText, "Title", TITLE_LENGTH ); diff --git a/mainui/menu_savegame.cpp b/mainui/menu_savegame.cpp index 681cb6b1..46ab009c 100644 --- a/mainui/menu_savegame.cpp +++ b/mainui/menu_savegame.cpp @@ -314,6 +314,7 @@ static void UI_SaveGame_Init( void ) { memset( &uiSaveGame, 0, sizeof( uiSaveGame_t )); + uiSaveGame.menu.vidInitFunc = UI_SaveGame_Init; uiSaveGame.menu.keyFunc = UI_SaveGame_KeyFunc; StringConcat( uiSaveGame.hintText, "Time", TIME_LENGTH ); diff --git a/mainui/menu_saveload.cpp b/mainui/menu_saveload.cpp index 8d3ac0b1..9e1197ac 100644 --- a/mainui/menu_saveload.cpp +++ b/mainui/menu_saveload.cpp @@ -85,6 +85,8 @@ static void UI_SaveLoad_Init( void ) { memset( &uiSaveLoad, 0, sizeof( uiSaveLoad_t )); + uiSaveLoad.menu.vidInitFunc = UI_SaveLoad_Init; + strcat( uiSaveLoad.hintText, "During play, you can quickly save your game by pressing " ); strcat( uiSaveLoad.hintText, KEY_KeynumToString( KEY_GetKey( "savequick" ))); strcat( uiSaveLoad.hintText, ".\nLoad this game again by pressing " ); diff --git a/mainui/menu_video.cpp b/mainui/menu_video.cpp index d2e811d2..c3f51046 100644 --- a/mainui/menu_video.cpp +++ b/mainui/menu_video.cpp @@ -80,6 +80,8 @@ static void UI_Video_Init( void ) { memset( &uiVideo, 0, sizeof( uiVideo_t )); + uiVideo.menu.vidInitFunc = UI_Video_Init; + uiVideo.background.generic.id = ID_BACKGROUND; uiVideo.background.generic.type = QMTYPE_BITMAP; uiVideo.background.generic.flags = QMF_INACTIVE; diff --git a/mainui/menu_vidmodes.cpp b/mainui/menu_vidmodes.cpp index c21cc911..17ea2458 100644 --- a/mainui/menu_vidmodes.cpp +++ b/mainui/menu_vidmodes.cpp @@ -26,8 +26,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define ID_BACKGROUND 0 #define ID_BANNER 1 -#define ID_OK 2 -#define ID_CANCEL 3 +#define ID_APPLY 2 +#define ID_DONE 3 #define ID_RENDERLIBRARY 4 #define ID_VIDMODELIST 5 #define ID_FULLSCREEN 6 @@ -126,8 +126,6 @@ static void UI_VidOptions_SetConfig( void ) CVAR_SET_FLOAT( "vid_mode", uiVidModes.vidList.curItem ); CVAR_SET_FLOAT( "fullscreen", !uiVidModes.windowed.enabled ); CVAR_SET_FLOAT( "r_allow_software", uiVidModes.software.enabled ); - - CLIENT_COMMAND( TRUE, "vid_restart\n" ); } /* @@ -171,10 +169,10 @@ static void UI_VidModes_Callback( void *self, int event ) switch( item->id ) { - case ID_CANCEL: + case ID_DONE: UI_PopMenu(); break; - case ID_OK: + case ID_APPLY: UI_VidOptions_SetConfig (); break; } @@ -189,6 +187,8 @@ static void UI_VidModes_Init( void ) { memset( &uiVidModes, 0, sizeof( uiVidModes_t )); + uiVidModes.menu.vidInitFunc = UI_VidModes_Init; + strcat( uiVidModes.hintText, "Change Xash3D rendering engine\n" ); strcat( uiVidModes.hintText, "to get more compatibility and\n" ); strcat( uiVidModes.hintText, "optimize FPS.\n" ); @@ -213,21 +213,21 @@ static void UI_VidModes_Init( void ) uiVidModes.banner.generic.height = UI_BANNER_HEIGHT; uiVidModes.banner.pic = ART_BANNER; - uiVidModes.ok.generic.id = ID_OK; + uiVidModes.ok.generic.id = ID_APPLY; uiVidModes.ok.generic.type = QMTYPE_ACTION; uiVidModes.ok.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW; uiVidModes.ok.generic.x = 72; uiVidModes.ok.generic.y = 230; - uiVidModes.ok.generic.name = "Ok"; - uiVidModes.ok.generic.statusText = "Apply changes and return to the Main Menu"; + uiVidModes.ok.generic.name = "Apply"; + uiVidModes.ok.generic.statusText = "Apply changes"; uiVidModes.ok.generic.callback = UI_VidModes_Callback; - uiVidModes.cancel.generic.id = ID_CANCEL; + uiVidModes.cancel.generic.id = ID_DONE; uiVidModes.cancel.generic.type = QMTYPE_ACTION; uiVidModes.cancel.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW; uiVidModes.cancel.generic.x = 72; uiVidModes.cancel.generic.y = 280; - uiVidModes.cancel.generic.name = "Cancel"; + uiVidModes.cancel.generic.name = "Done"; uiVidModes.cancel.generic.statusText = "Return back to previous menu"; uiVidModes.cancel.generic.callback = UI_VidModes_Callback; diff --git a/mainui/menu_vidoptions.cpp b/mainui/menu_vidoptions.cpp index 20686164..23a82f81 100644 --- a/mainui/menu_vidoptions.cpp +++ b/mainui/menu_vidoptions.cpp @@ -142,6 +142,8 @@ static void UI_VidOptions_Init( void ) { memset( &uiVidOptions, 0, sizeof( uiVidOptions_t )); + uiVidOptions.menu.vidInitFunc = UI_VidOptions_Init; + uiVidOptions.background.generic.id = ID_BACKGROUND; uiVidOptions.background.generic.type = QMTYPE_BITMAP; uiVidOptions.background.generic.flags = QMF_INACTIVE; diff --git a/public/launch_api.h b/public/launch_api.h index ecbe0b5e..f51f6d0e 100644 --- a/public/launch_api.h +++ b/public/launch_api.h @@ -122,8 +122,8 @@ typedef enum CVAR_LATCH = BIT(14),// save changes until server restart CVAR_READ_ONLY = BIT(15),// display only, cannot be set by user at all CVAR_LATCH_VIDEO = BIT(16),// save changes until render restart - CVAR_LATCH_AUDIO = BIT(17),// save changes until vsound restart - CVAR_USER_CREATED = BIT(18),// created by a set command (dll's used) + CVAR_USER_CREATED = BIT(17),// created by a set command (dll's used) + CVAR_GLCONFIG = BIT(18),// set to cause it to be saved to opengl.cfg } cvar_flags_t; #include "cvardef.h" diff --git a/vid_gl/r_backend.c b/vid_gl/r_backend.c deleted file mode 100644 index fc29726c..00000000 --- a/vid_gl/r_backend.c +++ /dev/null @@ -1,3225 +0,0 @@ -/* -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "r_local.h" -#include "mathlib.h" -#include "matrix_lib.h" -#include "cl_entity.h" - -#define FTABLE_SIZE_POW 10 -#define FTABLE_SIZE ( 1<integer ) - r_identityLighting = (int)( 255.0f / pow( 2, max( 0, floor( r_overbrightbits->value )))); - else r_identityLighting = 255; - - // build lookup tables - for( i = 0; i < FTABLE_SIZE; i++ ) - { - t = (float)i / (float)FTABLE_SIZE; - - r_sintable[i] = sin( t * M_PI2 ); - - if( t < 0.25f ) r_triangletable[i] = t * 4.0f; - else if( t < 0.75f ) r_triangletable[i] = 2 - 4.0f * t; - else r_triangletable[i] = ( t - 0.75f ) * 4.0f - 1.0f; - - if( t < 0.5f ) r_squaretable[i] = 1.0f; - else r_squaretable[i] = -1.0f; - - r_sawtoothtable[i] = t; - r_inversesawtoothtable[i] = 1.0f - t; - } - - for( i = 0; i < 256; i++ ) - r_sintableByte[i] = sin((float)i / 255.0f * M_PI2 ); - - // init the noise table - for( i = 0; i < NOISE_SIZE; i++ ) - { - r_noisetable[i] = Com_RandomFloat( -1.0f, 1.0f ); - r_noiseperm[i] = Com_RandomLong( 0, 255 ); - } - - // init dynamic lights pass - Mem_Set( &r_dlightsPass, 0, sizeof( ref_stage_t )); - r_dlightsPass.flags = SHADERSTAGE_DLIGHT; - r_dlightsPass.glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_ONE; - - // init fog pass - Mem_Set( &r_fogPass, 0, sizeof( ref_stage_t )); - r_fogPass.tcgen = TCGEN_FOG; - r_fogPass.rgbGen.type = RGBGEN_FOG; - r_fogPass.alphaGen.type = ALPHAGEN_IDENTITY; - r_fogPass.flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_DECAL; - r_fogPass.glState = GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA; - - // the very first lightmap pass is reserved for GL_REPLACE or GL_MODULATE - Mem_Set( r_lightmapPasses, 0, sizeof( r_lightmapPasses )); - r_lightmapPasses[0].rgbGen.args = r_lightmapPassesArgs[0]; - - // the rest are GL_ADD - for( i = 1; i < MAX_TEXTURE_UNITS+1; i++ ) - { - r_lightmapPasses[i].flags = SHADERSTAGE_LIGHTMAP|SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_ADD; - r_lightmapPasses[i].glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE; - r_lightmapPasses[i].tcgen = TCGEN_LIGHTMAP; - r_lightmapPasses[i].alphaGen.type = ALPHAGEN_IDENTITY; - r_lightmapPasses[i].rgbGen.args = r_lightmapPassesArgs[i]; - } - - // init optional GLSL program passes - Mem_Set( r_GLSLpasses, 0, sizeof( r_GLSLpasses ) ); - r_GLSLpasses[0].flags = SHADERSTAGE_DLIGHT|SHADERSTAGE_BLEND_ADD; - r_GLSLpasses[0].glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE; - - r_GLSLpasses[1].flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE; - r_GLSLpasses[1].glState = GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR; - r_GLSLpasses[1].tcgen = TCGEN_BASE; - r_GLSLpasses[1].rgbGen.type = RGBGEN_IDENTITY; - r_GLSLpasses[1].alphaGen.type = ALPHAGEN_IDENTITY; - Mem_Copy( &r_GLSLpasses[2], &r_GLSLpasses[1], sizeof( ref_stage_t )); - - r_GLSLpasses[3].flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE; - r_GLSLpasses[3].glState = GLSTATE_DEPTHFUNC_EQ /*|GLSTATE_OFFSET_FILL*/|GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR; - r_GLSLpasses[3].tcgen = TCGEN_PROJECTION_SHADOW; - r_GLSLpasses[3].rgbGen.type = RGBGEN_IDENTITY; - r_GLSLpasses[3].alphaGen.type = ALPHAGEN_IDENTITY; - r_GLSLpasses[3].program = DEFAULT_GLSL_SHADOWMAP_PROGRAM; - r_GLSLpasses[3].program_type = PROGRAM_TYPE_SHADOWMAP; -} - -/* -============== -R_BackendShutdown -============== -*/ -void R_BackendShutdown( void ) -{ - R_ShutdownVertexBuffers (); -} - -/* -============== -R_FastSin -============== -*/ -float R_FastSin( float t ) -{ - return FTABLE_EVALUATE( r_sintable, t ); -} - -/* -============= -NormToLatLong -============= -*/ -void NormToLatLong( const vec3_t normal, byte latlong[2] ) -{ - // can't do atan2 (normal[1], normal[0]) - if( normal[0] == 0 && normal[1] == 0 ) - { - if( normal[2] > 0 ) - { - latlong[0] = 0; // acos ( 1 ) - latlong[1] = 0; - } - else - { - latlong[0] = 128; // acos ( -1 ) - latlong[1] = 0; - } - } - else - { - int angle; - - angle = (int)(com.acos( normal[2]) * 255.0 / M_PI2 ) & 255; - latlong[0] = angle; - angle = (int)(com.atan2( normal[1], normal[0] ) * 255.0 / M_PI2 ) & 255; - latlong[1] = angle; - } -} - -/* -============= -R_LatLongToNorm -============= -*/ -void R_LatLongToNorm( const byte latlong[2], vec3_t out ) -{ - float sin_a, sin_b, cos_a, cos_b; - - cos_a = r_sintableByte[(latlong[0] + 64) & 255]; - sin_a = r_sintableByte[latlong[0]]; - cos_b = r_sintableByte[(latlong[1] + 64) & 255]; - sin_b = r_sintableByte[latlong[1]]; - - VectorSet( out, cos_b * sin_a, sin_b * sin_a, cos_a ); -} - -/* -============== -ColorToBytes -============== -*/ -void ColorToBytes( const float *color, byte *colorBytes ) -{ - float max; - vec3_t sample; - - VectorCopy( color, sample ); - - // clamp with color normalization - max = VectorMax( sample ); - - if( max > 255 ) - VectorScale( sample, ( 255.0f / max ), sample ); - VectorCopy( sample, colorBytes ); -} - -/* -============== -R_TableForFunc -============== -*/ -static float *R_TableForFunc( uint func ) -{ - switch( func ) - { - case WAVEFORM_SIN: - return r_sintable; - case WAVEFORM_TRIANGLE: - return r_triangletable; - case WAVEFORM_SQUARE: - return r_squaretable; - case WAVEFORM_SAWTOOTH: - return r_sawtoothtable; - case WAVEFORM_INVERSESAWTOOTH: - return r_inversesawtoothtable; - case WAVEFORM_NOISE: - return r_sintable; // default to sintable - default: - return NULL; - } -} - -static float R_TableEvaluate( waveFunc_t func, float index ) -{ - float *table = R_TableForFunc( func.type ); - - if( table == NULL ) - { - if( func.type == WAVEFORM_TABLE ) - return R_LookupTable( func.tableIndex, index ); - return 1.0f; // assume error - } - return FTABLE_EVALUATE( table, index ); -} - -/* -============== -R_BackendGetNoiseValue -============== -*/ -float R_BackendGetNoiseValue( float x, float y, float z, float t ) -{ - int i; - int ix, iy, iz, it; - float fx, fy, fz, ft; - float front[4], back[4]; - float fvalue, bvalue, value[2], finalvalue; - - ix = ( int )floor( x ); - fx = x - ix; - iy = ( int )floor( y ); - fy = y - iy; - iz = ( int )floor( z ); - fz = z - iz; - it = ( int )floor( t ); - ft = t - it; - - for( i = 0; i < 2; i++ ) - { - front[0] = r_noisetable[NOISE_INDEX( ix, iy, iz, it + i )]; - front[1] = r_noisetable[NOISE_INDEX( ix+1, iy, iz, it + i )]; - front[2] = r_noisetable[NOISE_INDEX( ix, iy+1, iz, it + i )]; - front[3] = r_noisetable[NOISE_INDEX( ix+1, iy+1, iz, it + i )]; - - back[0] = r_noisetable[NOISE_INDEX( ix, iy, iz + 1, it + i )]; - back[1] = r_noisetable[NOISE_INDEX( ix+1, iy, iz + 1, it + i )]; - back[2] = r_noisetable[NOISE_INDEX( ix, iy+1, iz + 1, it + i )]; - back[3] = r_noisetable[NOISE_INDEX( ix+1, iy+1, iz + 1, it + i )]; - - fvalue = NOISE_LERP( NOISE_LERP( front[0], front[1], fx ), NOISE_LERP( front[2], front[3], fx ), fy ); - bvalue = NOISE_LERP( NOISE_LERP( back[0], back[1], fx ), NOISE_LERP( back[2], back[3], fx ), fy ); - value[i] = NOISE_LERP( fvalue, bvalue, fz ); - } - finalvalue = NOISE_LERP( value[0], value[1], ft ); - - return finalvalue; -} - -/* -============== -R_BackendResetCounters -============== -*/ -void R_BackendResetCounters( void ) -{ - Mem_Set( &r_backacc, 0, sizeof( r_backacc )); -} - -/* -============== -R_BackendStartFrame -============== -*/ -void R_BackendStartFrame( void ) -{ - r_speeds_msg[0] = '\0'; - R_BackendResetCounters(); -} - -/* -============== -R_BackendEndFrame -============== -*/ -void R_BackendEndFrame( void ) -{ - // unlock arrays if any - R_UnlockArrays(); - - // clean up texture units - R_CleanUpTextureUnits( 1 ); - - if( r_speeds->integer && RI.drawWorld ) - { - switch( r_speeds->integer ) - { - case 1: - default: - com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ), - "%4i wpoly %4i leafs %4i verts\n%4i tris %4i flushes %4i locks", - c_brush_polys, - c_world_leafs, - r_backacc.c_totalVerts, - r_backacc.c_totalTris, - r_backacc.c_totalFlushes, - r_backacc.c_totalKeptLocks - ); - break; - case 2: - com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ), - "lvs: %.8f node: %.8f\nfarclip: %6.f", - r_mark_leaves, - r_world_node, - RI.farClip - ); - break; - case 3: - com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ), - "polys\\ents: %.8f\\%.8f\nsort\\draw: %.8f\\%.8f", - r_add_polys, r_add_entities, - r_sort_meshes, r_draw_meshes - ); - break; - case 4: - if( r_debug_surface ) - { - com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ), - "%s", r_debug_surface->shader->name ); - - if( r_debug_surface->fog && r_debug_surface->fog->shader - && r_debug_surface->fog->shader != r_debug_surface->shader ) - { - com.strncat( r_speeds_msg, "\n", sizeof( r_speeds_msg ) ); - com.strncat( r_speeds_msg, r_debug_surface->fog->shader->name, sizeof( r_speeds_msg ) ); - } - } - else if( r_debug_hitbox ) - { - com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "%s", r_debug_hitbox ); - } - break; - case 5: - com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ), - "%.1f %.1f %.1f\n(%.1f,%.1f,%.1f)", - RI.refdef.vieworg[0], RI.refdef.vieworg[1], RI.refdef.vieworg[2], - RI.refdef.viewangles[0], RI.refdef.viewangles[1], RI.refdef.viewangles[2] - ); - break; - case 6: - com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ), "cl_numents %i", r_numEntities ); - break; - } - } -} - -/* -============== -R_LockArrays -============== -*/ -void R_LockArrays( int numverts ) -{ - if( r_arraysLocked ) return; - - R_UpdateVertexBuffer( tr.vertexBuffer, vertsArray, numverts * sizeof( vec4_t )); - pglVertexPointer( 3, GL_FLOAT, 16, tr.vertexBuffer->pointer ); - - if( r_features & MF_ENABLENORMALS ) - { - r_normalsEnabled = true; - R_UpdateVertexBuffer( tr.normalBuffer, normalsArray, numverts * sizeof( vec4_t )); - pglEnableClientState( GL_NORMAL_ARRAY ); - pglNormalPointer( GL_FLOAT, 16, tr.normalBuffer->pointer ); - } - - if( GL_Support( R_CUSTOM_VERTEX_ARRAY_EXT )) - pglLockArraysEXT( 0, numverts ); - - r_arraysLocked = true; -} - -/* -============== -R_UnlockArrays -============== -*/ -void R_UnlockArrays( void ) -{ - if( !r_arraysLocked ) - return; - - if(GL_Support( R_CUSTOM_VERTEX_ARRAY_EXT )) - pglUnlockArraysEXT(); - - if( r_normalsEnabled ) - { - r_normalsEnabled = false; - pglDisableClientState( GL_NORMAL_ARRAY ); - } - r_arraysLocked = false; -} - -/* -============== -R_ClearArrays -============== -*/ -void R_ClearArrays( void ) -{ - r_backacc.numVerts = 0; - r_backacc.numElems = 0; - r_backacc.numColors = 0; - - vertsArray = inVertsArray; - elemsArray = inElemsArray; - normalsArray = inNormalsArray; - sVectorsArray = inSVectorsArray; - tVectorsArray = inTVectorsArray; - coordsArray = inCoordsArray; - lightmapCoordsArray = inLightmapCoordsArray; -} - -/* -============== -R_FlushArrays -============== -*/ -void R_FlushArrays( void ) -{ - if( !r_backacc.numVerts || !r_backacc.numElems ) - return; - - if( r_backacc.numColors == 1 ) - { - pglColor4ubv( colorArray[0] ); - } - else if( r_backacc.numColors > 1 ) - { - pglEnableClientState( GL_COLOR_ARRAY ); - R_UpdateVertexBuffer( tr.colorsBuffer, colorArray, r_backacc.numVerts * sizeof( rgba_t )); - pglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tr.colorsBuffer->pointer ); - } - - if( r_drawelements->integer || glState.in2DMode || RI.drawWorld == false ) - { - if( GL_Support( R_DRAW_RANGEELEMENTS_EXT )) - pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); - else pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); - } - - if( r_backacc.numColors > 1 ) - pglDisableClientState( GL_COLOR_ARRAY ); - - r_backacc.c_totalTris += r_backacc.numElems / 3; - r_backacc.c_totalFlushes++; -} - -/* -============== -GL_DisableAllTexGens -============== -*/ -static _inline void GL_DisableAllTexGens( void ) -{ - GL_EnableTexGen( GL_S, 0 ); - GL_EnableTexGen( GL_T, 0 ); - GL_EnableTexGen( GL_R, 0 ); - GL_EnableTexGen( GL_Q, 0 ); -} - -/* -============== -R_CleanUpTextureUnits -============== -*/ -static void R_CleanUpTextureUnits( int last ) -{ - int i; - - for( i = glState.activeTMU; i > last - 1; i-- ) - { - GL_DisableAllTexGens(); - GL_SetTexCoordArrayMode( 0 ); - - pglDisable( GL_TEXTURE_2D ); - GL_SelectTexture( i - 1 ); - } -} - -/* -================ -R_DeformVertices -================ -*/ -void R_DeformVertices( void ) -{ - uint i, j, k; - double args[4], temp; - float deflect, *quad[4]; - const deform_t *deformv; - vec3_t tv, rot_centre; - - deformv = &r_currentShader->deforms[0]; - for( i = 0; i < r_currentShader->numDeforms; i++, deformv++ ) - { - switch( deformv->type ) - { - case DEFORM_NONE: - break; - case DEFORM_WAVE: - // Deflect vertex along its normal by wave amount - if( deformv->func.args[3] == 0 ) - { - temp = deformv->func.args[2]; - deflect = R_TableEvaluate( deformv->func, temp ) * deformv->func.args[1] + deformv->func.args[0]; - - for( j = 0; j < r_backacc.numVerts; j++ ) - VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] ); - } - else - { - args[0] = deformv->func.args[0]; - args[1] = deformv->func.args[1]; - args[2] = deformv->func.args[2] + deformv->func.args[3] * r_currentShaderTime; - args[3] = deformv->args[0]; - - if( args[1] == 0.0f ) - args[1] = RI.currententity->waveHeight; - - for( j = 0; j < r_backacc.numVerts; j++ ) - { - temp = args[2] + args[3] * ( inVertsArray[j][0] + inVertsArray[j][1] + inVertsArray[j][2] ); - deflect = R_TableEvaluate( deformv->func, temp ) * args[1] + args[0]; - VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] ); - } - } - break; - case DEFORM_NORMAL: - // without this * 0.1f deformation looks wrong, although q3a doesn't have it - args[0] = deformv->func.args[3] * r_currentShaderTime * 0.1f; - args[1] = deformv->func.args[1]; - - for( j = 0; j < r_backacc.numVerts; j++ ) - { - VectorScale( inVertsArray[j], 0.98f, tv ); - inNormalsArray[j][0] += args[1] *R_BackendGetNoiseValue( tv[0], tv[1], tv[2], args[0] ); - inNormalsArray[j][1] += args[1] *R_BackendGetNoiseValue( tv[0] + 100, tv[1], tv[2], args[0] ); - inNormalsArray[j][2] += args[1] *R_BackendGetNoiseValue( tv[0] + 200, tv[1], tv[2], args[0] ); - VectorNormalizeFast( inNormalsArray[j] ); - } - break; - case DEFORM_MOVE: - temp = deformv->func.args[2] + r_currentShaderTime * deformv->func.args[3]; - deflect = R_TableEvaluate( deformv->func, temp ) * deformv->func.args[1] + deformv->func.args[0]; - - for( j = 0; j < r_backacc.numVerts; j++ ) - VectorMA( inVertsArray[j], deflect, deformv->args, inVertsArray[j] ); - break; - case DEFORM_BULGE: - args[0] = deformv->args[0]; - args[1] = deformv->args[1]; - args[2] = r_currentShaderTime * deformv->args[2]; - - for( j = 0; j < r_backacc.numVerts; j++ ) - { - temp = ( coordsArray[j][0] * args[0] + args[2] ) / M_PI2; - deflect = R_FastSin( temp ) * args[1]; - VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] ); - } - break; - case DEFORM_AUTOSPRITE: - { - vec4_t *v; - vec2_t *st; - elem_t *elem; - float radius; - vec3_t point, v_centre, v_right, v_up; - - if( r_backacc.numVerts % 4 || r_backacc.numElems % 6 ) - break; - - if( RI.currententity && (RI.currentmodel != r_worldmodel) ) - { - Matrix3x3_Transform( RI.currententity->axis, RI.vright, v_right ); - Matrix3x3_Transform( RI.currententity->axis, RI.vup, v_up ); - } - else - { - VectorCopy( RI.vright, v_right ); - VectorCopy( RI.vup, v_up ); - } - - radius = RI.currententity ? RI.currententity->scale : 0.0f; - if( radius && radius != 1.0f ) - { - radius = 1.0f / radius; - VectorScale( v_right, radius, v_right ); - VectorScale( v_up, radius, v_up ); - } - - for( k = 0, v = inVertsArray, st = coordsArray, elem = elemsArray; k < r_backacc.numVerts; k += 4, v += 4, st += 4, elem += 6 ) - { - for( j = 0; j < 3; j++ ) - v_centre[j] = (v[0][j] + v[1][j] + v[2][j] + v[3][j]) * 0.25; - - VectorSubtract( v[0], v_centre, point ); - radius = VectorLength( point ) * 0.707106f; // 1.0f / sqrt(2) - - // very similar to R_PushSprite - VectorMA( v_centre, -radius, v_up, point ); - VectorMA( point, -radius, v_right, v[0] ); - VectorMA( point, radius, v_right, v[3] ); - - VectorMA( v_centre, radius, v_up, point ); - VectorMA( point, -radius, v_right, v[1] ); - VectorMA( point, radius, v_right, v[2] ); - - // reset texcoords - Vector2Set( st[0], 0, 1 ); - Vector2Set( st[1], 0, 0 ); - Vector2Set( st[2], 1, 0 ); - Vector2Set( st[3], 1, 1 ); - - // trifan elems - elem[0] = k; - elem[1] = k + 2 - 1; - elem[2] = k + 2; - - elem[3] = k; - elem[4] = k + 3 - 1; - elem[5] = k + 3; - } - } - break; - case DEFORM_AUTOSPRITE2: - if( r_backacc.numElems % 6 ) - break; - - for( k = 0; k < r_backacc.numElems; k += 6 ) - { - int long_axis = 0, short_axis = 0; - vec3_t axis, tmp; - float len[3]; - vec3_t m0[3], m1[3], m2[3], result[3]; - - quad[0] = (float *)(inVertsArray + elemsArray[k+0]); - quad[1] = (float *)(inVertsArray + elemsArray[k+1]); - quad[2] = (float *)(inVertsArray + elemsArray[k+2]); - - for( j = 2; j >= 0; j-- ) - { - quad[3] = (float *)(inVertsArray + elemsArray[k+3+j]); - - if( !VectorCompare( quad[3], quad[0] ) && !VectorCompare( quad[3], quad[1] ) && !VectorCompare( quad[3], quad[2] )) - { - break; - } - } - - // build a matrix were the longest axis of the billboard is the Y-Axis - VectorSubtract( quad[1], quad[0], m0[0] ); - VectorSubtract( quad[2], quad[0], m0[1] ); - VectorSubtract( quad[2], quad[1], m0[2] ); - len[0] = DotProduct( m0[0], m0[0] ); - len[1] = DotProduct( m0[1], m0[1] ); - len[2] = DotProduct( m0[2], m0[2] ); - - if(( len[2] > len[1] ) && ( len[2] > len[0] )) - { - if( len[1] > len[0] ) - { - long_axis = 1; - short_axis = 0; - } - else - { - long_axis = 0; - short_axis = 1; - } - } - else if(( len[1] > len[2] ) && ( len[1] > len[0] )) - { - if( len[2] > len[0] ) - { - long_axis = 2; - short_axis = 0; - } - else - { - long_axis = 0; - short_axis = 2; - } - } - else if(( len[0] > len[1] ) && ( len[0] > len[2] )) - { - if( len[2] > len[1] ) - { - long_axis = 2; - short_axis = 1; - } - else - { - long_axis = 1; - short_axis = 2; - } - } - - if( !len[long_axis] ) break; - len[long_axis] = rsqrt( len[long_axis] ); - VectorScale( m0[long_axis], len[long_axis], axis ); - - if( DotProduct( m0[long_axis], m0[short_axis] ) ) - { - VectorCopy( axis, m0[1] ); - if( axis[0] || axis[1] ) - VectorVectors( m0[1], m0[0], m0[2] ); - else VectorVectors( m0[1], m0[2], m0[0] ); - } - else - { - if( !len[short_axis] ) break; - len[short_axis] = rsqrt( len[short_axis] ); - VectorScale( m0[short_axis], len[short_axis], m0[0] ); - VectorCopy( axis, m0[1] ); - CrossProduct( m0[0], m0[1], m0[2] ); - } - - for( j = 0; j < 3; j++ ) - rot_centre[j] = ( quad[0][j] + quad[1][j] + quad[2][j] + quad[3][j] ) * 0.25; - - if( RI.currententity && ( RI.currentmodel != r_worldmodel )) - { - VectorAdd( RI.currententity->origin, rot_centre, tv ); - VectorSubtract( RI.viewOrigin, tv, tmp ); - Matrix3x3_Transform( RI.currententity->axis, tmp, tv ); - } - else - { - VectorCopy( rot_centre, tv ); - VectorSubtract( RI.viewOrigin, tv, tv ); - } - - // filter any longest-axis-parts off the camera-direction - deflect = -DotProduct( tv, axis ); - - VectorMA( tv, deflect, axis, m1[2] ); - VectorNormalizeFast( m1[2] ); - VectorCopy( axis, m1[1] ); - CrossProduct( m1[1], m1[2], m1[0] ); - - Matrix3x3_Transpose( m2, m1 ); - Matrix3x3_Concat( result, m2, m0 ); - - for( j = 0; j < 4; j++ ) - { - VectorSubtract( quad[j], rot_centre, tv ); - Matrix3x3_Transform( result, tv, quad[j] ); - VectorAdd( rot_centre, quad[j], quad[j] ); - } - } - break; - case DEFORM_PROJECTION_SHADOW: - R_DeformVPlanarShadow( r_backacc.numVerts, inVertsArray[0] ); - break; - case DEFORM_AUTOPARTICLE: - { - float scale; - vec3_t m0[3], m1[3], m2[3], result[3]; - - if( r_backacc.numElems % 6 ) - break; - - if( RI.currententity && ( RI.currentmodel != r_worldmodel )) - Matrix3x3_FromMatrix4x4( m1, RI.modelviewMatrix ); - else Matrix3x3_FromMatrix4x4( m1, RI.worldviewMatrix ); - - Matrix3x3_Transpose( m2, m1 ); - - for( k = 0; k < r_backacc.numElems; k += 6 ) - { - quad[0] = ( float * )( inVertsArray + elemsArray[k+0] ); - quad[1] = ( float * )( inVertsArray + elemsArray[k+1] ); - quad[2] = ( float * )( inVertsArray + elemsArray[k+2] ); - - for( j = 2; j >= 0; j-- ) - { - quad[3] = ( float * )( inVertsArray + elemsArray[k+3+j] ); - - if( !VectorCompare( quad[3], quad[0] ) && !VectorCompare( quad[3], quad[1] ) && !VectorCompare( quad[3], quad[2] )) - { - break; - } - } - - Matrix3x3_FromPoints( quad[0], quad[1], quad[2], m0 ); - Matrix3x3_Concat( result, m2, m0 ); - - // hack a scale up to keep particles from disappearing - scale = ( quad[0][0] - RI.viewOrigin[0] ) * RI.vpn[0] + ( quad[0][1] - RI.viewOrigin[1] ) * RI.vpn[1] + ( quad[0][2] - RI.viewOrigin[2] ) * RI.vpn[2]; - if( scale < 20 ) scale = 1.5; - else scale = 1.5 + scale * 0.006f; - - for( j = 0; j < 3; j++ ) - rot_centre[j] = ( quad[0][j] + quad[1][j] + quad[2][j] + quad[3][j] ) * 0.25; - - for( j = 0; j < 4; j++ ) - { - VectorSubtract( quad[j], rot_centre, tv ); - Matrix3x3_Transform( result, tv, quad[j] ); - VectorMA( rot_centre, scale, quad[j], quad[j] ); - } - } - } - break; - default: break; - } - } -} - -/* -============== -R_VertexTCBase -============== -*/ -static qboolean R_VertexTCBase( const ref_stage_t *pass, int unit, matrix4x4 matrix ) -{ - uint i; - float *outCoords; - qboolean identityMatrix = false; - - Matrix4x4_LoadIdentity( matrix ); - - switch( pass->tcgen ) - { - case TCGEN_BASE: - GL_DisableAllTexGens(); - - R_UpdateVertexBuffer( tr.tcoordBuffer[unit], coordsArray, r_backacc.numVerts * sizeof( vec2_t )); - pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer ); - return true; - case TCGEN_LIGHTMAP: - GL_DisableAllTexGens(); - - R_UpdateVertexBuffer( tr.tcoordBuffer[unit], lightmapCoordsArray, r_backacc.numVerts * sizeof( vec2_t )); - pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer ); - return true; - case TCGEN_ENVIRONMENT: - { - float depth, *n; - vec3_t projection, transform; - - if( glState.in2DMode ) - return true; - - if( !( RI.params & RP_SHADOWMAPVIEW )) - { - VectorSubtract( RI.viewOrigin, RI.currententity->origin, projection ); - Matrix3x3_Transform( RI.currententity->axis, projection, transform ); - - outCoords = tUnitCoordsArray[unit][0]; - for( i = 0, n = normalsArray[0]; i < r_backacc.numVerts; i++, outCoords += 2, n += 4 ) - { - VectorSubtract( transform, vertsArray[i], projection ); - VectorNormalizeFast( projection ); - - depth = DotProduct( n, projection ); depth += depth; - outCoords[0] = 0.5 + ( n[1] * depth - projection[1] ) * 0.5f; - outCoords[1] = 0.5 - ( n[2] * depth - projection[2] ) * 0.5f; - } - } - - GL_DisableAllTexGens(); - - R_UpdateVertexBuffer( tr.tcoordBuffer[unit], tUnitCoordsArray[unit], r_backacc.numVerts * sizeof( vec2_t )); - pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer ); - return true; - } - case TCGEN_VECTOR: - { - GLfloat genVector[2][4]; - - for( i = 0; i < 3; i++ ) - { - genVector[0][i] = pass->tcgenVec[i+0]; - genVector[1][i] = pass->tcgenVec[i+4]; - } - genVector[0][3] = genVector[1][3] = 0; - - Matrix4x4_SetOrigin2D( matrix, pass->tcgenVec[3], pass->tcgenVec[7] ); - - GL_SetTexCoordArrayMode( 0 ); - GL_EnableTexGen( GL_S, GL_OBJECT_LINEAR ); - GL_EnableTexGen( GL_T, GL_OBJECT_LINEAR ); - GL_EnableTexGen( GL_R, 0 ); - GL_EnableTexGen( GL_Q, 0 ); - pglTexGenfv( GL_S, GL_OBJECT_PLANE, genVector[0] ); - pglTexGenfv( GL_T, GL_OBJECT_PLANE, genVector[1] ); - return false; - } - case TCGEN_PROJECTION: - { - matrix4x4 m1, m2; - GLfloat genVector[4][4]; - - GL_SetTexCoordArrayMode( 0 ); - - // nonmoving objects using worldviewmatrix - if( VectorIsNull( RI.currententity->origin ) && Matrix3x3_Compare( RI.currententity->axis, matrix3x3_identity )) - Matrix4x4_Copy( matrix, RI.worldviewProjectionMatrix ); - else Matrix4x4_Concat( matrix, RI.projectionMatrix, RI.modelviewMatrix ); - - Matrix4x4_LoadIdentity( m1 ); - Matrix4x4_ConcatScale( m1, 0.5f ); - Matrix4x4_Concat( m2, m1, matrix ); - - Matrix4x4_LoadIdentity( m1 ); - Matrix4x4_ConcatTranslate( m1, 0.5f, 0.5f, 0.5f ); - Matrix4x4_Concat( matrix, m1, m2 ); - - for( i = 0; i < 4; i++ ) - { - genVector[0][i] = i == 0 ? 1 : 0; - genVector[1][i] = i == 1 ? 1 : 0; - genVector[2][i] = i == 2 ? 1 : 0; - genVector[3][i] = i == 3 ? 1 : 0; - } - - GL_EnableTexGen( GL_S, GL_OBJECT_LINEAR ); - GL_EnableTexGen( GL_T, GL_OBJECT_LINEAR ); - GL_EnableTexGen( GL_R, GL_OBJECT_LINEAR ); - GL_EnableTexGen( GL_Q, GL_OBJECT_LINEAR ); - - pglTexGenfv( GL_S, GL_OBJECT_PLANE, genVector[0] ); - pglTexGenfv( GL_T, GL_OBJECT_PLANE, genVector[1] ); - pglTexGenfv( GL_R, GL_OBJECT_PLANE, genVector[2] ); - pglTexGenfv( GL_Q, GL_OBJECT_PLANE, genVector[3] ); - return false; - } - case TCGEN_WARP: - outCoords = tUnitCoordsArray[unit][0]; - for( i = 0; r_currentShader->tessSize != 0.0f && i < r_backacc.numVerts; i++, outCoords += 2 ) - { - outCoords[0] = inCoordsArray[i][0] + r_warpsintable[((int)((inCoordsArray[i][1] * 8.0f + r_currentShaderTime) * (256.0/M_PI2))) & 255] * (1.0f / r_currentShader->tessSize ); - outCoords[1] = inCoordsArray[i][1] + r_warpsintable[((int)((inCoordsArray[i][0] * 8.0f + r_currentShaderTime) * (256.0/M_PI2))) & 255] * (1.0f / r_currentShader->tessSize ); - } - R_UpdateVertexBuffer( tr.tcoordBuffer[unit], tUnitCoordsArray[unit], r_backacc.numVerts * sizeof( vec2_t )); - pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer ); - return true; - case TCGEN_REFLECTION_CELLSHADE: - if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ) ) - { - vec3_t dir, vpn, vright, vup; - matrix4x4 m; - - R_LightDir( RI.currententity->lightingOrigin, dir, RI.currentmodel->radius * RI.currententity->scale ); - - // rotate direction - Matrix3x3_Transform( RI.currententity->axis, dir, vpn ); - VectorNormalizeLength( vpn ); - VectorVectors( vpn, vright, vup ); - - Matrix4x4_FromVectors( m, vpn, vright, vup, vec3_origin ); - Matrix4x4_Transpose( matrix, m ); - } - case TCGEN_REFLECTION: - GL_EnableTexGen( GL_S, GL_REFLECTION_MAP_ARB ); - GL_EnableTexGen( GL_T, GL_REFLECTION_MAP_ARB ); - GL_EnableTexGen( GL_R, GL_REFLECTION_MAP_ARB ); - GL_EnableTexGen( GL_Q, 0 ); - return true; - case TCGEN_NORMAL: - GL_EnableTexGen( GL_S, GL_NORMAL_MAP_ARB ); - GL_EnableTexGen( GL_T, GL_NORMAL_MAP_ARB ); - GL_EnableTexGen( GL_R, GL_NORMAL_MAP_ARB ); - GL_EnableTexGen( GL_Q, 0 ); - return true; - case TCGEN_FOG: - { - int fogPtype; - mplane_t *fogPlane; - ref_shader_t *fogShader; - vec3_t viewtofog; - float fogNormal[3], vpnNormal[3]; - float dist, vdist, fogDist, vpnDist; - - fogPlane = r_texFog->visibleplane; - fogShader = r_texFog->shader; - - matrix[0][0] = matrix[1][1] = 1.0 / (fogShader->fog_dist - fogShader->fog_clearDist); - Matrix4x4_SetOrigin2D( matrix, 0, 1.5f / (float)FOG_TEXTURE_HEIGHT ); - - // distance to fog - dist = RI.fog_dist_to_eye[r_texFog-r_worldbrushmodel->fogs]; - - if( r_currentShader->flags & SHADER_SKYPARMS ) - { - if( dist > 0 ) VectorMA( RI.viewOrigin, -dist, fogPlane->normal, viewtofog ); - else VectorCopy( RI.viewOrigin, viewtofog ); - } - else VectorCopy( RI.currententity->origin, viewtofog ); - - // some math tricks to take entity's rotation matrix into account - // for fog texture coordinates calculations: - // M is rotation matrix, v is vertex, t is transform vector - // n is plane's normal, d is plane's dist, r is view origin - // (M*v + t)*n - d = (M*n)*v - ((d - t*n)) - // (M*v + t - r)*n = (M*n)*v - ((r - t)*n) - fogNormal[0] = DotProduct( RI.currententity->axis[0], fogPlane->normal ) * RI.currententity->scale; - fogNormal[1] = DotProduct( RI.currententity->axis[1], fogPlane->normal ) * RI.currententity->scale; - fogNormal[2] = DotProduct( RI.currententity->axis[2], fogPlane->normal ) * RI.currententity->scale; - fogPtype = ( fogNormal[0] == 1.0 ? PLANE_X : ( fogNormal[1] == 1.0 ? PLANE_Y : ( fogNormal[2] == 1.0 ? PLANE_Z : PLANE_NONAXIAL ) ) ); - fogDist = ( fogPlane->dist - DotProduct( viewtofog, fogPlane->normal ) ); - - vpnNormal[0] = DotProduct( RI.currententity->axis[0], RI.vpn ) * RI.currententity->scale; - vpnNormal[1] = DotProduct( RI.currententity->axis[1], RI.vpn ) * RI.currententity->scale; - vpnNormal[2] = DotProduct( RI.currententity->axis[2], RI.vpn ) * RI.currententity->scale; - vpnDist = ( ( RI.viewOrigin[0] - viewtofog[0] ) * RI.vpn[0] + ( RI.viewOrigin[1] - viewtofog[1] ) * RI.vpn[1] + ( RI.viewOrigin[2] - viewtofog[2] ) * RI.vpn[2] ) + fogShader->fog_clearDist; - - outCoords = tUnitCoordsArray[unit][0]; - if( dist < 0 ) - { - // camera is inside the fog brush - for( i = 0; i < r_backacc.numVerts; i++, outCoords += 2 ) - { - outCoords[0] = DotProduct( vertsArray[i], vpnNormal ) - vpnDist; - if( fogPtype < 3 ) outCoords[1] = -( vertsArray[i][fogPtype] - fogDist ); - else outCoords[1] = -( DotProduct( vertsArray[i], fogNormal ) - fogDist ); - } - } - else - { - for( i = 0; i < r_backacc.numVerts; i++, outCoords += 2 ) - { - if( fogPtype < 3 ) vdist = vertsArray[i][fogPtype] - fogDist; - else vdist = DotProduct( vertsArray[i], fogNormal ) - fogDist; - outCoords[0] = ( ( vdist < 0 ) ? ( DotProduct( vertsArray[i], vpnNormal ) - vpnDist ) * vdist / ( vdist - dist ) : 0.0f ); - outCoords[1] = -vdist; - } - } - - GL_DisableAllTexGens(); - - R_UpdateVertexBuffer( tr.tcoordBuffer[unit], tUnitCoordsArray[unit], r_backacc.numVerts * sizeof( vec2_t )); - pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer ); - return false; - } - case TCGEN_SVECTORS: - GL_DisableAllTexGens(); - R_UpdateVertexBuffer( tr.tcoordBuffer[unit], sVectorsArray, r_backacc.numVerts * sizeof( vec4_t )); - pglTexCoordPointer( 4, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer ); - return true; - case TCGEN_PROJECTION_SHADOW: - GL_SetTexCoordArrayMode( 0 ); - GL_DisableAllTexGens(); - Matrix4x4_Concat( matrix, r_currentCastGroup->worldviewProjectionMatrix, RI.objectMatrix ); - break; - default: break; - } - return identityMatrix; -} - -/* -================ -R_ApplyTCMods -================ -*/ -static void R_ApplyTCMods( const ref_stage_t *pass, matrix4x4 result ) -{ - int i; - double t1, t2, sint, cost; - matrix4x4 m1, m2; - const tcMod_t *tcmod; - float flConveyorSpeed, flRate, flAngle; - waveFunc_t func; - - for( i = 0, tcmod = pass->tcMods; i < pass->numtcMods; i++, tcmod++ ) - { - switch( tcmod->type ) - { - case TCMOD_TRANSLATE: - Matrix4x4_Translate2D( result, tcmod->args[0], tcmod->args[1] ); - break; - case TCMOD_ROTATE: - cost = tcmod->args[0] * r_currentShaderTime; - sint = R_FastSin( cost ); - cost = R_FastSin( cost + 0.25 ); - Matrix4x4_Setup2D( m2, cost, sint, -sint, cost, 0.5f*(sint-cost+1), -0.5f*(sint+cost-1)); - Matrix4x4_Copy2D( m1, result ); - Matrix4x4_Concat2D( result, m2, m1 ); - break; - case TCMOD_SCALE: - Matrix4x4_Scale2D( result, tcmod->args[0], tcmod->args[1] ); - break; - case TCMOD_TURB: - t1 = ( 1.0f / 4.0f ); - t2 = tcmod->args[2] + r_currentShaderTime * tcmod->args[3]; - Matrix4x4_Scale2D( result, 1 + ( tcmod->args[1] * R_FastSin( t2 ) + tcmod->args[0] ) * t1, 1 + ( tcmod->args[1] * R_FastSin( t2 + 0.25 ) + tcmod->args[0] ) * t1 ); - break; - case TCMOD_STRETCH: - func.type = (uint)tcmod->args[0]; - func.tableIndex = (uint)tcmod->args[5]; - t2 = tcmod->args[3] + r_currentShaderTime * tcmod->args[4]; - t1 = R_TableEvaluate( func, t2 ) * tcmod->args[2] + tcmod->args[1]; - t1 = t1 ? 1.0f / t1 : 1.0f; - t2 = 0.5f - 0.5f * t1; - Matrix4x4_Stretch2D( result, t1, t2 ); - break; - case TCMOD_SCROLL: - t1 = tcmod->args[0] * r_currentShaderTime; - t2 = tcmod->args[1] * r_currentShaderTime; - if( pass->program_type != PROGRAM_TYPE_DISTORTION ) - { - // HACKHACK - t1 = t1 - floor( t1 ); - t2 = t2 - floor( t2 ); - } - Matrix4x4_Translate2D( result, t1, t2 ); - break; - case TCMOD_TRANSFORM: - Matrix4x4_Setup2D( m2, tcmod->args[0], tcmod->args[2], tcmod->args[3], tcmod->args[1], tcmod->args[4], tcmod->args[5] ); - Matrix4x4_Copy2D( m1, result ); - Matrix4x4_Concat2D( result, m1, m2 ); - break; - case TCMOD_CONVEYOR: - flConveyorSpeed = (RI.currententity->rendercolor[1]<<8|RI.currententity->rendercolor[2]) / 16.0f; - if( RI.currententity->rendercolor[0] ) flConveyorSpeed = -flConveyorSpeed; - flRate = abs( flConveyorSpeed ) / (float)pass->textures[0]->srcWidth; - flAngle = (flConveyorSpeed >= 0) ? 180 : 0; - - t1 = r_currentShaderTime * com.cos( flAngle * ( M_PI / 180.0f )) * flRate; - t2 = r_currentShaderTime * com.sin( flAngle * ( M_PI / 180.0f )) * flRate; - - // make sure that we are positive - if( t1 < 0.0f ) t1 += 1.0f + -floor( t1 ); - if( t2 < 0.0f ) t2 += 1.0f + -floor( t2 ); - - if( pass->program_type != PROGRAM_TYPE_DISTORTION ) - { - // HACKHACK - t1 = t1 - floor( t1 ); - t2 = t2 - floor( t2 ); - } - - Matrix4x4_Translate2D( result, t1, t2 ); - break; - default: break; - } - } -} - -/* -============== -R_ShaderpassTex -============== -*/ -static _inline texture_t *R_ShaderpassTex( const ref_stage_t *pass, int unit ) -{ - if( !glState.in2DMode && !triState.fActive ) - { - if( pass->flags & SHADERSTAGE_RENDERMODE && tr.iRenderMode == kRenderTransColor ) - return tr.whiteTexture; - } - - if( pass->flags & SHADERSTAGE_ANGLEDMAP ) - { - float yaw = RI.currententity->angles[1] - 45; // angled bias - int angleframe = (int)((RI.refdef.viewangles[1] - yaw) / 360 * 8 + 0.5 - 4) & 7; - if( !RI.currententity ) return pass->textures[0]; // assume error - return pass->textures[angleframe]; - } - - if( pass->flags & SHADERSTAGE_FRAMES && !(pass->flags & SHADERSTAGE_ANIMFREQUENCY)) - { - if( glState.in2DMode || triState.fActive ) - return pass->textures[bound( 0, glState.draw_frame, pass->num_textures - 1)]; - else if( RI.currententity && RI.currententity->model ) - { - switch( RI.currententity->model->type ) - { - case mod_brush: - case mod_world: - return pass->textures[bound( 0, (int)RI.currententity->frame, pass->num_textures - 1)]; - case mod_studio: - return pass->textures[bound( 0, (int)RI.currententity->skin, pass->num_textures - 1)]; - } - } - } - - if( pass->flags & SHADERSTAGE_ANIMFREQUENCY && pass->animFrequency[0] && pass->num_textures ) - { - int frame, numframes; - - if(( r_currentMeshBuffer->sortkey & 3 ) == MB_DECAL ) - { - decal_t *pDecal = R_DecalFromMeshbuf( r_currentMeshBuffer ); - - // play animation once and freeze at last frame - if( pDecal->flags & FDECAL_ANIMATED ) - { - numframes = pass->num_textures - 1; - - pDecal->currentFrame += pass->animFrequency[0] * ( r_currentShaderTime - pDecal->fadeStartTime ); - - // animation is finished ? - if( pDecal->currentFrame > numframes ) - { - // in case we compare current frame for right batching - pDecal->currentFrame = numframes; - pDecal->flags &= ~FDECAL_ANIMATED; - } - return pass->textures[bound( 0, (int)pDecal->currentFrame, pass->num_textures - 1 )]; - } - else if( pDecal->currentFrame != 0.0f ) - return pass->textures[bound( 0, (int)pDecal->currentFrame, pass->num_textures - 1 )]; - // fallback to default methods - } - - if( RI.currententity ) - { - if( RI.currententity->frame && pass->animFrequency[1] != 0.0f ) - { - numframes = bound( 1, pass->num_textures - pass->anim_offset, MAX_STAGE_TEXTURES - 1 ); - frame = (int)( pass->animFrequency[1] * r_currentShaderTime ) % numframes; - frame = bound( 0, frame + pass->anim_offset, pass->num_textures - 1 ); // bias - } - else - { - numframes = bound( 1, pass->anim_offset, MAX_STAGE_TEXTURES - 1 ); - frame = (int)( pass->animFrequency[0] * r_currentShaderTime ) % numframes; - } - } - else frame = (int)( pass->animFrequency[0] * r_currentShaderTime ) % pass->num_textures; - - ASSERT( pass->textures[frame] ); - - return pass->textures[frame]; - } - - if( pass->flags & SHADERSTAGE_LIGHTMAP ) - return tr.lightmapTextures[r_currentLightStyle->lightmapNum]; - if( pass->flags & SHADERSTAGE_PORTALMAP ) - return tr.portaltexture1; - return ( pass->textures[0] ? pass->textures[0] : tr.defaultTexture ); -} - -/* -================= -RB_SetShaderRenderMode - -UNDONE: not all cases are filled -================= -*/ -static void R_ShaderpassRenderMode( ref_stage_t *pass ) -{ - int mod_type = mod_bad; // mod_bad interpretate as orthogonal shader - - if(!( pass->flags & SHADERSTAGE_RENDERMODE )) - return; - - if( RI.currentmodel && !glState.in2DMode && !triState.fActive ) - mod_type = RI.currentmodel->type; - - switch( tr.iRenderMode ) - { - case kRenderNormal: - // restore real state - pass->glState = pass->prev.glState; - pass->flags = pass->prev.flags; - pass->rgbGen = pass->prev.rgbGen; - pass->alphaGen = pass->prev.alphaGen; - break; - case kRenderTransColor: - switch( mod_type ) - { - case mod_bad: - pass->glState = (GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR); - pass->flags = SHADERSTAGE_BLEND_DECAL; - pass->rgbGen.type = RGBGEN_VERTEX; - pass->alphaGen.type = ALPHAGEN_VERTEX; - break; - case mod_brush: - pass->glState = (GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_SRC_COLOR); - pass->flags = SHADERSTAGE_BLEND_MODULATE; - pass->rgbGen.type = RGBGEN_ENTITY; - pass->alphaGen.type = ALPHAGEN_ENTITY; - break; - case mod_studio: - case mod_sprite: - break; - } - break; - case kRenderTransTexture: - switch( mod_type ) - { - case mod_bad: - pass->glState = (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA); - pass->flags = SHADERSTAGE_BLEND_MODULATE; - pass->rgbGen.type = RGBGEN_VERTEX; - pass->alphaGen.type = ALPHAGEN_VERTEX; - break; - case mod_brush: - pass->glState = (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA); - pass->flags = SHADERSTAGE_BLEND_MODULATE; - pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING; - pass->alphaGen.type = ALPHAGEN_ENTITY; - break; - case mod_studio: - pass->glState = (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_DEPTHWRITE); - pass->flags = SHADERSTAGE_BLEND_MODULATE; - pass->rgbGen.type = RGBGEN_LIGHTING_DIFFUSE; - pass->alphaGen.type = ALPHAGEN_ENTITY; - break; - case mod_sprite: - pass->glState = (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_DEPTHWRITE); - pass->flags = SHADERSTAGE_BLEND_MODULATE; - pass->rgbGen.type = RGBGEN_VERTEX; - pass->alphaGen.type = ALPHAGEN_VERTEX; - break; - } - break; - case kRenderTransInverse: - switch( mod_type ) - { - case mod_bad: - pass->glState = (GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_DSTBLEND_SRC_ALPHA); - pass->flags = SHADERSTAGE_BLEND_MODULATE; - pass->rgbGen.type = RGBGEN_VERTEX; - pass->alphaGen.type = ALPHAGEN_VERTEX; - break; - case mod_brush: - pass->glState = (GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_DSTBLEND_SRC_ALPHA); - pass->flags = SHADERSTAGE_BLEND_MODULATE; - pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING; - pass->alphaGen.type = ALPHAGEN_ENTITY; - break; - case mod_studio: - pass->glState = (GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_DSTBLEND_SRC_ALPHA|GLSTATE_DEPTHWRITE); - pass->flags = SHADERSTAGE_BLEND_MODULATE; - pass->rgbGen.type = RGBGEN_LIGHTING_DIFFUSE; - pass->alphaGen.type = ALPHAGEN_ENTITY; - break; - case mod_sprite: - pass->glState = (GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_DSTBLEND_SRC_ALPHA|GLSTATE_DEPTHWRITE); - pass->flags = SHADERSTAGE_BLEND_MODULATE; - pass->rgbGen.type = RGBGEN_VERTEX; - pass->alphaGen.type = ALPHAGEN_VERTEX; - break; - } - break; - case kRenderGlow: - switch( mod_type ) - { - case mod_bad: - pass->glState = (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE); - pass->flags = SHADERSTAGE_BLEND_ADD; - pass->rgbGen.type = RGBGEN_VERTEX; - pass->alphaGen.type = ALPHAGEN_VERTEX; - break; - case mod_brush: - case mod_studio: - break; - case mod_sprite: - pass->glState = (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE); - pass->rgbGen.type = RGBGEN_VERTEX; - pass->alphaGen.type = ALPHAGEN_VERTEX; - break; - } - break; - case kRenderTransAlpha: - switch( mod_type ) - { - case mod_bad: - pass->glState = GLSTATE_AFUNC_GE128; - pass->rgbGen.type = RGBGEN_VERTEX; - pass->alphaGen.type = ALPHAGEN_VERTEX; - break; - case mod_brush: - pass->flags = SHADERSTAGE_BLEND_MODULATE; - pass->glState = GLSTATE_AFUNC_GE128|GLSTATE_DEPTHWRITE; - break; - case mod_studio: - break; - case mod_sprite: - pass->flags = SHADERSTAGE_BLEND_MODULATE; - pass->glState = GLSTATE_AFUNC_GE128; - pass->rgbGen.type = RGBGEN_VERTEX; - pass->alphaGen.type = ALPHAGEN_VERTEX; - break; - } - break; - case kRenderTransAdd: - switch( mod_type ) - { - case mod_bad: - pass->flags = SHADERSTAGE_BLEND_ADD; - pass->glState = (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE); - pass->rgbGen.type = RGBGEN_VERTEX; - pass->alphaGen.type = ALPHAGEN_VERTEX; - break; - case mod_brush: - pass->flags = SHADERSTAGE_BLEND_MODULATE; - pass->glState = (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE); - pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING; - pass->alphaGen.type = ALPHAGEN_ENTITY; - break; - case mod_studio: - pass->flags = SHADERSTAGE_BLEND_ADD; - pass->glState = (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE); - pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING; // models ignore color in 'add' mode - pass->alphaGen.type = ALPHAGEN_ENTITY; - break; - case mod_sprite: - pass->flags = SHADERSTAGE_BLEND_ADD; - pass->glState = (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE); - pass->rgbGen.type = RGBGEN_VERTEX; - pass->alphaGen.type = ALPHAGEN_VERTEX; - break; - } - break; - } - - // restore some flags - pass->flags |= SHADERSTAGE_RENDERMODE; - if( pass->prev.flags & SHADERSTAGE_ANIMFREQUENCY ) - pass->flags |= SHADERSTAGE_ANIMFREQUENCY; - if( pass->prev.flags & SHADERSTAGE_FRAMES ) - pass->flags |= SHADERSTAGE_FRAMES; - if( pass->prev.flags & SHADERSTAGE_ANGLEDMAP ) - pass->flags |= SHADERSTAGE_ANGLEDMAP; -} - -/* -================ -R_BindShaderpass -================ -*/ -static void R_BindShaderpass( const ref_stage_t *pass, texture_t *tex, int unit ) -{ - matrix4x4 m1, m2, result; - qboolean identityMatrix; - - if( !tex ) tex = R_ShaderpassTex( pass, unit ); - - GL_Bind( unit, tex ); - if( unit && !pass->program ) pglEnable( GL_TEXTURE_2D ); - GL_SetTexCoordArrayMode(( tex->flags & TF_CUBEMAP ? GL_TEXTURE_CUBE_MAP_ARB : GL_TEXTURE_COORD_ARRAY )); - - identityMatrix = R_VertexTCBase( pass, unit, result ); - - if( pass->numtcMods ) - { - identityMatrix = false; - R_ApplyTCMods( pass, result ); - } - - if( pass->tcgen == TCGEN_REFLECTION || pass->tcgen == TCGEN_REFLECTION_CELLSHADE ) - { - Matrix4x4_Transpose( m1, RI.modelviewMatrix ); - Matrix4x4_Copy( m2, result ); - Matrix4x4_Concat( result, m2, m1 ); - GL_LoadTexMatrix( result ); - return; - } - - if( identityMatrix ) - GL_LoadIdentityTexMatrix(); - else GL_LoadTexMatrix( result ); -} - -/* -================ -R_ModifyColor -================ -*/ -void R_ModifyColor( const ref_stage_t *pass ) -{ - float a; - double temp; - vec3_t t, v; - int i, c, bits; - byte *bArray, *inArray, rgba[4] = { 255, 255, 255, 255 }; - qboolean noArray, identityAlpha, entityAlpha; - const waveFunc_t *rgbgenfunc, *alphagenfunc; - - noArray = ( pass->flags & SHADERSTAGE_NOCOLORARRAY ) && !r_colorFog; - r_backacc.numColors = noArray ? 1 : r_backacc.numVerts; - bits = ( r_overbrightbits->integer > 0 ) && !( r_ignorehwgamma->integer ) ? r_overbrightbits->integer : 0; - - bArray = colorArray[0]; - inArray = inColorsArray[0]; - - if( pass->rgbGen.type == RGBGEN_IDENTITY_LIGHTING ) - { - entityAlpha = identityAlpha = false; - Mem_Set( bArray, r_identityLighting, sizeof( rgba_t ) * r_backacc.numColors ); - } - else if( pass->rgbGen.type == RGBGEN_EXACT_VERTEX ) - { - entityAlpha = identityAlpha = false; - Mem_Copy( bArray, inArray, sizeof( rgba_t ) * r_backacc.numColors ); - } - else - { - entityAlpha = false; - identityAlpha = true; - Mem_Set( bArray, 255, sizeof( rgba_t ) * r_backacc.numColors ); - - switch( pass->rgbGen.type ) - { - case RGBGEN_IDENTITY: - break; - case RGBGEN_CONST: - rgba[0] = R_FloatToByte( pass->rgbGen.args[0] ); - rgba[1] = R_FloatToByte( pass->rgbGen.args[1] ); - rgba[2] = R_FloatToByte( pass->rgbGen.args[2] ); - - for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 ) - *(int *)bArray = c; - break; - case RGBGEN_WAVE: - case RGBGEN_COLORWAVE: - rgbgenfunc = pass->rgbGen.func; - if( rgbgenfunc->type == WAVEFORM_NOISE ) - { - temp = R_BackendGetNoiseValue( 0, 0, 0, ( r_currentShaderTime + rgbgenfunc->args[2] ) * rgbgenfunc->args[3] ); - } - else - { - temp = r_currentShaderTime * rgbgenfunc->args[3] + rgbgenfunc->args[2]; - temp = R_TableEvaluate( *rgbgenfunc, temp ) * rgbgenfunc->args[1] + rgbgenfunc->args[0]; - } - - temp = bound( 0.0f, temp, 1.0f ); - a = bound( 0.0f, pass->rgbGen.args[0] * temp, 1.0f ); - rgba[0] = R_FloatToByte( a ); - a = bound( 0.0f, pass->rgbGen.args[1] * temp, 1.0f ); - rgba[1] = R_FloatToByte( a ); - a = bound( 0.0f, pass->rgbGen.args[2] * temp, 1.0f ); - rgba[2] = R_FloatToByte( a ); - - for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 ) - *(int *)bArray = c; - break; - case RGBGEN_ENTITY: - rgba[0] = RI.currententity->rendercolor[0]; - rgba[1] = RI.currententity->rendercolor[1]; - rgba[2] = RI.currententity->rendercolor[2]; - entityAlpha = true; - identityAlpha = ( RI.currententity->renderamt == 255 ); - - for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 ) - *(int *)bArray = c; - break; - case RGBGEN_ONE_MINUS_ENTITY: - rgba[0] = 255 - RI.currententity->rendercolor[0]; - rgba[1] = 255 - RI.currententity->rendercolor[1]; - rgba[2] = 255 - RI.currententity->rendercolor[2]; - - for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 ) - *(int *)bArray = c; - break; - case RGBGEN_VERTEX: - for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 ) - { - bArray[0] = inArray[0] >> bits; - bArray[1] = inArray[1] >> bits; - bArray[2] = inArray[2] >> bits; - } - break; - case RGBGEN_ONE_MINUS_VERTEX: - for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 ) - { - bArray[0] = 255 - ( inArray[0] >> bits ); - bArray[1] = 255 - ( inArray[1] >> bits ); - bArray[2] = 255 - ( inArray[2] >> bits ); - } - break; - case RGBGEN_LIGHTING_DIFFUSE: - if( RI.currententity ) - R_LightForEntity( RI.currententity, bArray ); - break; - case RGBGEN_LIGHTING_AMBIENT: - if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW )) - { - vec3_t ambient, lightingOrigin; - - if( RI.currententity ) - VectorCopy( RI.currententity->lightingOrigin, lightingOrigin ); - else if( triState.fActive ) - VectorCopy( triState.lightingOrigin, lightingOrigin ); - else VectorClear( lightingOrigin ); // FIXME: MB_POLY - - if( RI.currententity->flags & EF_FULLBRIGHT || r_fullbright->integer || !r_worldbrushmodel->lightdata ) - VectorSet( ambient, 1.0f, 1.0f, 1.0f ); - else R_LightForPoint( lightingOrigin, ambient ); - - rgba[0] = R_FloatToByte( ambient[0] ); - rgba[1] = R_FloatToByte( ambient[1] ); - rgba[2] = R_FloatToByte( ambient[2] ); - - for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 ) - *(int *)bArray = c; - } - break; - case RGBGEN_FOG: - for( i = 0, c = *(int *)r_texFog->shader->fog_color; i < r_backacc.numColors; i++, bArray += 4 ) - *(int *)bArray = c; - break; - case RGBGEN_CUSTOM: - c = (int)pass->rgbGen.args[0]; - for( i = 0, c = R_GetCustomColor( c ); i < r_backacc.numColors; i++, bArray += 4 ) - *(int *)bArray = c; - break; - case RGBGEN_ENVIRONMENT: - for( i = 0, c = *(int *)mapConfig.environmentColor; i < r_backacc.numColors; i++, bArray += 4 ) - *(int *)bArray = c; - break; - default: - break; - } - } - - bArray = colorArray[0]; - inArray = inColorsArray[0]; - - switch( pass->alphaGen.type ) - { - case ALPHAGEN_IDENTITY: - if( identityAlpha ) break; - for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) - bArray[3] = 255; - break; - case ALPHAGEN_CONST: - c = R_FloatToByte( pass->alphaGen.args[0] ); - for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) - bArray[3] = c; - break; - case ALPHAGEN_WAVE: - case ALPHAGEN_ALPHAWAVE: - alphagenfunc = pass->alphaGen.func; - if( alphagenfunc->type == WAVEFORM_NOISE ) - { - a = R_BackendGetNoiseValue( 0, 0, 0, ( r_currentShaderTime + alphagenfunc->args[2] ) * alphagenfunc->args[3] ); - } - else - { - a = alphagenfunc->args[2] + r_currentShaderTime * alphagenfunc->args[3]; - a = R_TableEvaluate( *alphagenfunc, a ); - } - - a = a * alphagenfunc->args[1] + alphagenfunc->args[0]; - c = a <= 0 ? 0 : R_FloatToByte( a ); - - for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) - bArray[3] = c; - break; - case ALPHAGEN_PORTAL: - VectorAdd( vertsArray[0], RI.currententity->origin, v ); - VectorSubtract( RI.viewOrigin, v, t ); - a = VectorLength( t ) * pass->alphaGen.args[0]; - a = bound( 0.0f, a, 1.0f ); - c = R_FloatToByte( a ); - - for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) - bArray[3] = c; - break; - case ALPHAGEN_VERTEX: - for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 ) - bArray[3] = inArray[3]; - break; - case ALPHAGEN_ONE_MINUS_VERTEX: - for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 ) - bArray[3] = 255 - inArray[3]; - break; - case ALPHAGEN_ENTITY: - if( entityAlpha ) break; - for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) - bArray[3] = RI.currententity->renderamt; - break; - case ALPHAGEN_ONE_MINUS_ENTITY: - rgba[3] = 255 - RI.currententity->renderamt; - for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) - bArray[3] = rgba[3]; - break; - case ALPHAGEN_SPECULAR: - VectorSubtract( RI.viewOrigin, RI.currententity->origin, t ); - if( !Matrix3x3_Compare( RI.currententity->axis, matrix3x3_identity )) - Matrix3x3_Transform( RI.currententity->axis, t, v ); - else VectorCopy( t, v ); - - for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) - { - VectorSubtract( v, vertsArray[i], t ); - c = VectorLength( t ); - a = DotProduct( t, normalsArray[i] ) / max( 0.1, c ); - a = pow( a, pass->alphaGen.args[0] ); - bArray[3] = a <= 0 ? 0 : R_FloatToByte( a ); - } - break; - case ALPHAGEN_DOT: - if( !Matrix3x3_Compare( RI.currententity->axis, matrix3x3_identity )) - Matrix3x3_Transform( RI.currententity->axis, RI.vpn, v ); - else VectorCopy( RI.vpn, v ); - - for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) - { - a = DotProduct( v, inNormalsArray[i] ); if( a < 0 ) a = -a; - bArray[3] = R_FloatToByte( bound( pass->alphaGen.args[0], a, pass->alphaGen.args[1] )); - } - break; - case ALPHAGEN_ONE_MINUS_DOT: - if( !Matrix3x3_Compare( RI.currententity->axis, matrix3x3_identity )) - Matrix3x3_Transform( RI.currententity->axis, RI.vpn, v ); - else VectorCopy( RI.vpn, v ); - - for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) - { - a = DotProduct( v, inNormalsArray[i] ); if( a < 0 ) a = -a; a = 1.0f - a; - bArray[3] = R_FloatToByte( bound( pass->alphaGen.args[0], a, pass->alphaGen.args[1] )); - } - break; - case ALPHAGEN_FADE: - for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) - { - VectorAdd( vertsArray[i], RI.currententity->origin, v ); - a = VectorDistance( v, RI.viewOrigin ); - - a = bound( pass->alphaGen.args[0], a, pass->alphaGen.args[1] ) - pass->alphaGen.args[0]; - a = a * pass->alphaGen.args[2]; - bArray[3] = R_FloatToByte( bound( 0.0, a, 1.0 )); - } - break; - case ALPHAGEN_ONE_MINUS_FADE: - for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) - { - VectorAdd( vertsArray[i], RI.currententity->origin, v ); - a = VectorDistance( v, RI.viewOrigin ); - - a = bound( pass->alphaGen.args[0], a, pass->alphaGen.args[1] ) - pass->alphaGen.args[0]; - a = a * pass->alphaGen.args[2]; - bArray[3] = R_FloatToByte( bound( 0.0, 1.0 - a, 1.0 )); - } - break; - default: - break; - } - - if( r_colorFog ) - { - float dist, vdist; - mplane_t *fogPlane; - vec3_t viewtofog; - float fogNormal[3], vpnNormal[3]; - float fogDist, vpnDist, fogShaderDistScale; - int fogptype; - qboolean alphaFog; - int blendsrc, blenddst; - - blendsrc = pass->glState & GLSTATE_SRCBLEND_MASK; - blenddst = pass->glState & GLSTATE_DSTBLEND_MASK; - if(( blendsrc != GLSTATE_SRCBLEND_SRC_ALPHA && blenddst != GLSTATE_DSTBLEND_SRC_ALPHA ) && ( blendsrc != GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA && blenddst != GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA )) - alphaFog = false; - else alphaFog = true; - - fogPlane = r_colorFog->visibleplane; - fogShaderDistScale = 1.0 / (r_colorFog->shader->fog_dist - r_colorFog->shader->fog_clearDist); - dist = RI.fog_dist_to_eye[r_colorFog-r_worldbrushmodel->fogs]; - - if( r_currentShader->flags & SHADER_SKYPARMS ) - { - if( dist > 0 ) - VectorScale( fogPlane->normal, -dist, viewtofog ); - else - VectorClear( viewtofog ); - } - else - { - VectorCopy( RI.currententity->origin, viewtofog ); - } - - vpnNormal[0] = DotProduct( RI.currententity->axis[0], RI.vpn ) * fogShaderDistScale * RI.currententity->scale; - vpnNormal[1] = DotProduct( RI.currententity->axis[1], RI.vpn ) * fogShaderDistScale * RI.currententity->scale; - vpnNormal[2] = DotProduct( RI.currententity->axis[2], RI.vpn ) * fogShaderDistScale * RI.currententity->scale; - vpnDist = (( ( RI.viewOrigin[0] - viewtofog[0] ) * RI.vpn[0] + ( RI.viewOrigin[1] - viewtofog[1] ) * RI.vpn[1] + ( RI.viewOrigin[2] - viewtofog[2] ) * RI.vpn[2] ) - + r_colorFog->shader->fog_clearDist) * fogShaderDistScale; - - bArray = colorArray[0]; - if( dist < 0 ) - { // camera is inside the fog - for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) - { - temp = DotProduct( vertsArray[i], vpnNormal ) - vpnDist; - c = ( 1.0f - bound( 0, temp, 1.0f ) ) * 0xFFFF; - - if( alphaFog ) - { - bArray[3] = ( bArray[3] * c ) >> 16; - } - else - { - bArray[0] = ( bArray[0] * c ) >> 16; - bArray[1] = ( bArray[1] * c ) >> 16; - bArray[2] = ( bArray[2] * c ) >> 16; - } - } - } - else - { - fogNormal[0] = DotProduct( RI.currententity->axis[0], fogPlane->normal ) * RI.currententity->scale; - fogNormal[1] = DotProduct( RI.currententity->axis[1], fogPlane->normal ) * RI.currententity->scale; - fogNormal[2] = DotProduct( RI.currententity->axis[2], fogPlane->normal ) * RI.currententity->scale; - fogptype = ( fogNormal[0] == 1.0 ? PLANE_X : ( fogNormal[1] == 1.0 ? PLANE_Y : ( fogNormal[2] == 1.0 ? PLANE_Z : PLANE_NONAXIAL ) ) ); - fogDist = fogPlane->dist - DotProduct( viewtofog, fogPlane->normal ); - - for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) - { - if( fogptype < 3 ) - vdist = vertsArray[i][fogptype] - fogDist; - else - vdist = DotProduct( vertsArray[i], fogNormal ) - fogDist; - - if( vdist < 0 ) - { - temp = ( DotProduct( vertsArray[i], vpnNormal ) - vpnDist ) * vdist / ( vdist - dist ); - c = ( 1.0f - bound( 0, temp, 1.0f ) ) * 0xFFFF; - - if( alphaFog ) - { - bArray[3] = ( bArray[3] * c ) >> 16; - } - else - { - bArray[0] = ( bArray[0] * c ) >> 16; - bArray[1] = ( bArray[1] * c ) >> 16; - bArray[2] = ( bArray[2] * c ) >> 16; - } - } - } - } - } -} - -/* -================ -R_ShaderpassBlendmode -================ -*/ -static int R_ShaderpassBlendmode( int passFlags ) -{ - if( passFlags & SHADERSTAGE_BLEND_REPLACE ) - return GL_REPLACE; - if( passFlags & SHADERSTAGE_BLEND_MODULATE ) - return GL_MODULATE; - if( passFlags & SHADERSTAGE_BLEND_ADD ) - return GL_ADD; - if( passFlags & SHADERSTAGE_BLEND_DECAL ) - return GL_DECAL; - return 0; -} - -/* -================ -R_SetShaderState -================ -*/ -static void R_SetShaderState( void ) -{ - int state; - - // Face culling - if( !gl_cull->integer || ( r_features & MF_NOCULL )) - GL_Cull( 0 ); - else if( r_currentShader->flags & SHADER_CULL_FRONT ) - GL_Cull( GL_FRONT ); - else if( r_currentShader->flags & SHADER_CULL_BACK ) - GL_Cull( GL_BACK ); - else GL_Cull( 0 ); - - state = 0; - if( r_currentShader->flags & SHADER_POLYGONOFFSET || RI.params & RP_SHADOWMAPVIEW ) - state |= GLSTATE_OFFSET_FILL; - if( r_currentShader->type == SHADER_FLARE ) - state |= GLSTATE_NO_DEPTH_TEST; - r_currentShaderState = state; -} - -/* -================ -R_RenderMeshGeneric -================ -*/ -void R_RenderMeshGeneric( void ) -{ - const ref_stage_t *pass = r_accumPasses[0]; - - R_BindShaderpass( pass, NULL, 0 ); - R_ModifyColor( pass ); - - if( pass->flags & SHADERSTAGE_BLEND_REPLACE ) - GL_TexEnv( GL_REPLACE ); - else - GL_TexEnv( GL_MODULATE ); - GL_SetState( r_currentShaderState | ( pass->glState & r_currentShaderPassMask )); - - R_FlushArrays(); -} - -/* -================ -R_RenderMeshMultitextured -================ -*/ -void R_RenderMeshMultitextured( void ) -{ - int i; - const ref_stage_t *pass = r_accumPasses[0]; - - R_BindShaderpass( pass, NULL, 0 ); - R_ModifyColor( pass ); - - GL_TexEnv( GL_MODULATE ); - GL_SetState( r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX ); - - for( i = 1; i < r_numAccumPasses; i++ ) - { - pass = r_accumPasses[i]; - R_BindShaderpass( pass, NULL, i ); - GL_TexEnv( R_ShaderpassBlendmode( pass->flags ) ); - } - - R_FlushArrays(); -} - -/* -================ -R_RenderMeshCombined -================ -*/ -void R_RenderMeshCombined( void ) -{ - int i; - const ref_stage_t *pass = r_accumPasses[0]; - - R_BindShaderpass( pass, NULL, 0 ); - R_ModifyColor( pass ); - - GL_TexEnv( GL_MODULATE ); - GL_SetState( r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX ); - - for( i = 1; i < r_numAccumPasses; i++ ) - { - pass = r_accumPasses[i]; - R_BindShaderpass( pass, NULL, i ); - - if( pass->flags & ( SHADERSTAGE_BLEND_REPLACE|SHADERSTAGE_BLEND_MODULATE )) - { - GL_TexEnv( GL_MODULATE ); - } - else if( pass->flags & SHADERSTAGE_BLEND_ADD ) - { - // these modes are best set with TexEnv, Combine4 would need much more setup - GL_TexEnv( GL_ADD ); - } - else if( pass->flags & SHADERSTAGE_BLEND_DECAL ) - { - // mimics Alpha-Blending in upper texture stage, but instead of multiplying the alpha-channel, they're added - // this way it can be possible to use GL_DECAL in both texture-units, while still looking good - // normal mutlitexturing would multiply the alpha-channel which looks ugly - GL_TexEnv( GL_COMBINE_ARB ); - pglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB ); - pglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD ); - - pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE ); - pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); - pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE ); - pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA ); - - pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB ); - pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); - pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB ); - pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA ); - - pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE ); - pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA ); - } - } - - R_FlushArrays(); -} - -/* -================ -R_RenderMeshGLSL_Material -================ -*/ -static void R_RenderMeshGLSL_Material( void ) -{ - int i, tcgen; - int state; - qboolean breakIntoPasses = false; - int program, object; - int programFeatures = 0; - texture_t *base, *normalmap, *glossmap, *decalmap; - matrix4x4 unused; - vec3_t lightDir = { 0.0f, 0.0f, 0.0f }; - vec4_t ambient = { 0.0f, 0.0f, 0.0f, 0.0f }, diffuse = { 0.0f, 0.0f, 0.0f, 0.0f }; - float offsetmappingScale; - ref_style_t *lightStyle; - ref_stage_t *pass = r_accumPasses[0]; - - // handy pointers - base = pass->textures[0]; - normalmap = pass->textures[1]; - glossmap = pass->textures[2]; - decalmap = pass->textures[3]; - - ASSERT( normalmap ); - - if( normalmap->samples == 4 ) - offsetmappingScale = r_offsetmapping_scale->value * r_currentShader->offsetmapping_scale; - else // no alpha in normalmap, don't bother with offset mapping - offsetmappingScale = 0; - - if( GL_Support( R_GLSL_BRANCHING )) - programFeatures |= PROGRAM_APPLY_BRANCHING; - if( GL_Support( R_GLSL_NO_HALF_TYPES )) - programFeatures |= PROGRAM_APPLY_NO_HALF_TYPES; - if( RI.params & RP_CLIPPLANE ) - programFeatures |= PROGRAM_APPLY_CLIPPING; - - if( r_currentMeshBuffer->infokey > 0 ) - { - // world surface - int srcAlpha = (pass->flags & SHADERSTAGE_BLEND_DECAL); - - // CHECKTHIS: this is right ? - srcAlpha |= (pass->glState & (GLSTATE_ALPHAFUNC|GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_DSTBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA)); - - if( !( r_offsetmapping->integer & 1 ) ) - offsetmappingScale = 0; - - if( r_lightmap->integer || ( r_currentDlightBits && !pass->textures[5] )) - { - if( !srcAlpha ) base = tr.whiteTexture; // white - else programFeatures |= PROGRAM_APPLY_BASETEX_ALPHA_ONLY; - } - - // we use multipass for dynamic lights, so bind the white texture - // instead of base in GLSL program and add another modulative pass (diffusemap) - if( !r_lightmap->integer && ( r_currentDlightBits && !pass->textures[5] )) - { - breakIntoPasses = true; - r_GLSLpasses[1] = *pass; - r_GLSLpasses[1].flags = ( pass->flags & SHADERSTAGE_NOCOLORARRAY )|SHADERSTAGE_BLEND_MODULATE; - r_GLSLpasses[1].glState = GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR|((pass->glState & GLSTATE_ALPHAFUNC) ? GLSTATE_DEPTHFUNC_EQ : 0); - - // decal - if( decalmap ) - { - r_GLSLpasses[1].rgbGen.type = RGBGEN_IDENTITY; - r_GLSLpasses[1].alphaGen.type = ALPHAGEN_IDENTITY; - - r_GLSLpasses[2] = *pass; - r_GLSLpasses[2].flags = ( pass->flags & SHADERSTAGE_NOCOLORARRAY )|SHADERSTAGE_BLEND_DECAL; - r_GLSLpasses[2].glState = GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA|((pass->glState & GLSTATE_ALPHAFUNC) ? GLSTATE_DEPTHFUNC_EQ : 0); - r_GLSLpasses[2].textures[0] = decalmap; - } - - if( offsetmappingScale <= 0 ) - { - r_GLSLpasses[1].program = r_GLSLpasses[2].program = NULL; - r_GLSLpasses[1].program_type = r_GLSLpasses[2].program_type = PROGRAM_TYPE_NONE; - } - else - { - r_GLSLpasses[1].textures[2] = r_GLSLpasses[2].textures[2] = NULL; // no specular - r_GLSLpasses[1].textures[3] = r_GLSLpasses[2].textures[3] = NULL; // no decal - r_GLSLpasses[1].textures[6] = r_GLSLpasses[6].textures[2] = ((texture_t *)1); // HACKHACK no ambient - } - } - } - else if(( r_currentMeshBuffer->sortkey & 3 ) == MB_POLY ) - { - // polys - if( !( r_offsetmapping->integer & 2 )) - offsetmappingScale = 0; - - R_BuildTangentVectors( r_backacc.numVerts, vertsArray, normalsArray, coordsArray, r_backacc.numElems/3, elemsArray, inSVectorsArray ); - } - else - { // models - if( !( r_offsetmapping->integer & 4 )) - offsetmappingScale = 0; - } - - tcgen = pass->tcgen; // store the original tcgen - - pass->tcgen = TCGEN_BASE; - R_BindShaderpass( pass, base, 0 ); - - if( !breakIntoPasses ) - { - // calculate the fragment color - R_ModifyColor( pass ); - } - else - { // rgbgen identity (255,255,255,255) - r_backacc.numColors = 1; - colorArray[0][0] = colorArray[0][1] = colorArray[0][2] = colorArray[0][3] = 255; - } - - // set shaderpass state (blending, depthwrite, etc) - state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX; - GL_SetState( state ); - - // don't waste time on processing GLSL programs with zero colormask - if( RI.params & RP_SHADOWMAPVIEW ) - { - pass->tcgen = tcgen; // restore original tcgen - R_FlushArrays(); - return; - } - - // we only send S-vectors to GPU and recalc T-vectors as cross product - // in vertex shader - pass->tcgen = TCGEN_SVECTORS; - GL_Bind( 1, normalmap ); // normalmap - GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY ); - R_VertexTCBase( pass, 1, unused ); - - if( glossmap && r_lighting_glossintensity->value ) - { - programFeatures |= PROGRAM_APPLY_SPECULAR; - GL_Bind( 2, glossmap ); // gloss - GL_SetTexCoordArrayMode( 0 ); - } - - if( decalmap && !breakIntoPasses ) - { - programFeatures |= PROGRAM_APPLY_DECAL; - GL_Bind( 3, decalmap ); // decal - GL_SetTexCoordArrayMode( 0 ); - } - - if( offsetmappingScale > 0 ) - programFeatures |= r_offsetmapping_reliefmapping->integer ? PROGRAM_APPLY_RELIEFMAPPING : PROGRAM_APPLY_OFFSETMAPPING; - - if( r_currentMeshBuffer->infokey > 0 ) - { - // world surface - lightStyle = r_currentLightStyle; - - // bind lightmap textures and set program's features for lightstyles - if( lightStyle && lightStyle->lightmapNum >= 0 ) - { - pass->tcgen = TCGEN_LIGHTMAP; - - for( i = 0; i < LM_STYLES && lightStyle->lightmapStyles[i] != 255; i++ ) - { - programFeatures |= ( PROGRAM_APPLY_LIGHTSTYLE0 << i ); - - GL_Bind( i+4, tr.lightmapTextures[lightStyle->lightmapNum] ); // lightmap - GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY ); - R_VertexTCBase( pass, i+4, unused ); - } - - if( i == 1 ) - { - // PROGRAM_APPLY_FB_LIGHTMAP indicates that there's no need to renormalize - // the lighting vector for specular (saves 3 adds, 3 muls and 1 normalize per pixel) - if( r_lightStyles[lightStyle->lightmapStyles[0]].white == 3 ) - programFeatures |= PROGRAM_APPLY_FB_LIGHTMAP; - } - } - - if( !pass->textures[6] && !VectorCompare( mapConfig.ambient, vec3_origin )) - { - VectorCopy( mapConfig.ambient, ambient ); - programFeatures |= PROGRAM_APPLY_AMBIENT_COMPENSATION; - } - } - else - { - vec3_t temp; - - lightStyle = NULL; - programFeatures |= PROGRAM_APPLY_DIRECTIONAL_LIGHT; - - if(( r_currentMeshBuffer->sortkey & 3 ) == MB_POLY ) - { - VectorCopy( r_polys[-r_currentMeshBuffer->infokey-1].normal, lightDir ); - Vector4Set( ambient, 0, 0, 0, 0 ); - Vector4Set( diffuse, 1, 1, 1, 1 ); - } - else if( RI.currententity ) - { - if( RI.currententity->flags & EF_FULLBRIGHT ) - { - Vector4Set( ambient, 1, 1, 1, 1 ); - Vector4Set( diffuse, 1, 1, 1, 1 ); - } - else - { - float radius = RI.currententity->model ? RI.currententity->model->radius * RI.currententity->scale : 0; - - // get weighted incoming direction of world and dynamic lights - R_LightForOrigin( RI.currententity->lightingOrigin, temp, ambient, diffuse, radius ); - - if( RI.currententity->flags & EF_MINLIGHT ) - { - for( i = 0; i < 3; i++ ) - { - if( ambient[i] > 0.01f ) - break; - } - - if( i == 3 ) VectorSet( ambient, 0.01f, 0.01f, 0.01f ); - } - - // rotate direction - Matrix3x3_Transform( RI.currententity->axis, temp, lightDir ); - } - } - } - - pass->tcgen = tcgen; // restore original tcgen - - program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures ); - object = R_GetProgramObject( program ); - if( object ) - { - pglUseProgramObjectARB( object ); - - // update uniforms - R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, lightDir, ambient, diffuse, - lightStyle, true, 0, 0, 0, offsetmappingScale ); - - R_FlushArrays(); - - pglUseProgramObjectARB( 0 ); - } - - if( breakIntoPasses ) - { - uint oDB = r_currentDlightBits; // HACK HACK HACK - ref_style_t *oSL = r_currentLightStyle; - - R_AccumulatePass( &r_GLSLpasses[0] ); // dynamic lighting pass - - if( offsetmappingScale ) - { - r_currentLightStyle = NULL; - r_currentDlightBits = 0; - } - - R_AccumulatePass( &r_GLSLpasses[1] ); // modulate (diffusemap) - - if( decalmap ) - R_AccumulatePass( &r_GLSLpasses[2] ); // alpha-blended decal texture - - if( offsetmappingScale ) - { - r_currentLightStyle = oSL; - r_currentDlightBits = oDB; - } - } -} - -/* -================ -R_RenderMeshGLSL_Distortion -================ -*/ -static void R_RenderMeshGLSL_Distortion( void ) -{ - int state, tcgen; - int program, object; - int programFeatures = 0; - matrix4x4 unused; - ref_stage_t *pass = r_accumPasses[0]; - texture_t *portaltexture1, *portaltexture2; - qboolean frontPlane; - - if( !( RI.params & ( RP_PORTALCAPTURED|RP_PORTALCAPTURED2 ))) - return; - - if( GL_Support( R_GLSL_BRANCHING )) - programFeatures |= PROGRAM_APPLY_BRANCHING; - if( GL_Support( R_GLSL_NO_HALF_TYPES )) - programFeatures |= PROGRAM_APPLY_NO_HALF_TYPES; - if( RI.params & RP_CLIPPLANE ) - programFeatures |= PROGRAM_APPLY_CLIPPING; - - portaltexture1 = ( RI.params & RP_PORTALCAPTURED ) ? tr.portaltexture1 : tr.blackTexture; - portaltexture2 = ( RI.params & RP_PORTALCAPTURED2 ) ? tr.portaltexture2 : tr.blackTexture; - - frontPlane = (PlaneDiff( RI.viewOrigin, &RI.portalPlane ) > 0 ? true : false); - - tcgen = pass->tcgen; // store the original tcgen - - R_BindShaderpass( pass, pass->textures[0], 0 ); // dudvmap - - // calculate the fragment color - R_ModifyColor( pass ); - - if( frontPlane ) - { - if( pass->alphaGen.type != ALPHAGEN_IDENTITY ) - programFeatures |= PROGRAM_APPLY_DISTORTION_ALPHA; - } - - // set shaderpass state (blending, depthwrite, etc) - state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX; - GL_SetState( state ); - - if( pass->textures[1] /* && ( RI.params & RP_PORTALCAPTURED )*/ ) - { - // eyeDot - programFeatures |= PROGRAM_APPLY_EYEDOT; - - pass->tcgen = TCGEN_SVECTORS; - GL_Bind( 1, pass->textures[1] ); // normalmap - GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY ); - R_VertexTCBase( pass, 1, unused ); - } - - GL_Bind( 2, portaltexture1 ); // reflection - GL_Bind( 3, portaltexture2 ); // refraction - - pass->tcgen = tcgen; // restore original tcgen - - // update uniforms - program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures ); - object = R_GetProgramObject( program ); - if( object ) - { - pglUseProgramObjectARB( object ); - - R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, vec3_origin, NULL, NULL, NULL, - frontPlane, tr.portaltexture1->width, tr.portaltexture1->height, 0, 0 ); - - R_FlushArrays(); - - pglUseProgramObjectARB( 0 ); - } -} - -/* -================ -R_RenderMeshGLSL_Shadowmap -================ -*/ -static void R_RenderMeshGLSL_Shadowmap( void ) -{ - int i; - int state; - int program, object; - int programFeatures = GL_Support( R_GLSL_BRANCHING ) ? PROGRAM_APPLY_BRANCHING : 0; - ref_stage_t *pass = r_accumPasses[0]; - - if( r_shadows_pcf->integer == 2 ) - programFeatures |= PROGRAM_APPLY_PCF2x2; - else if( r_shadows_pcf->integer == 3 ) - programFeatures |= PROGRAM_APPLY_PCF3x3; - - // update uniforms - program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures ); - object = R_GetProgramObject( program ); - if( !object ) - return; - - for( i = 0, r_currentCastGroup = r_shadowGroups; i < r_numShadowGroups; i++, r_currentCastGroup++ ) - { - if( !( r_currentShadowBits & r_currentCastGroup->bit ) ) - continue; - - R_BindShaderpass( pass, r_currentCastGroup->depthTexture, 0 ); - - pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB ); - pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL ); - - // calculate the fragment color - R_ModifyColor( pass ); - - // set shaderpass state (blending, depthwrite, etc) - state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX; - GL_SetState( state ); - - pglUseProgramObjectARB( object ); - - R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, vec3_origin, NULL, NULL, NULL, true, - r_currentCastGroup->depthTexture->width, r_currentCastGroup->depthTexture->height, - r_currentCastGroup->projDist, 0 ); - - R_FlushArrays(); - - pglUseProgramObjectARB( 0 ); - - pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE ); - } -} - -/* -================ -R_RenderMeshGLSLProgrammed -================ -*/ -static void R_RenderMeshGLSLProgrammed( void ) -{ - const ref_stage_t *pass = ( ref_stage_t * )r_accumPasses[0]; - - switch( pass->program_type ) - { - case PROGRAM_TYPE_MATERIAL: - R_RenderMeshGLSL_Material(); - break; - case PROGRAM_TYPE_DISTORTION: - R_RenderMeshGLSL_Distortion(); - break; - case PROGRAM_TYPE_SHADOWMAP: - R_RenderMeshGLSL_Shadowmap(); - break; - default: - MsgDev( D_WARN, "Unknown GLSL program type %i\n", pass->program_type ); - break; - } -} - -/* -================ -R_RenderAccumulatedPasses -================ -*/ -static void R_RenderAccumulatedPasses( void ) -{ - const ref_stage_t *pass = r_accumPasses[0]; - - R_CleanUpTextureUnits( r_numAccumPasses ); - - if( pass->program ) - { - r_numAccumPasses = 0; - R_RenderMeshGLSLProgrammed(); - return; - } - if( pass->flags & SHADERSTAGE_DLIGHT ) - { - r_numAccumPasses = 0; - R_AddDynamicLights( r_currentDlightBits, r_currentShaderState | ( pass->glState & r_currentShaderPassMask )); - return; - } - if( pass->flags & SHADERSTAGE_STENCILSHADOW ) - { - r_numAccumPasses = 0; - R_PlanarShadowPass( r_currentShaderState | ( pass->glState & r_currentShaderPassMask )); - return; - } - - if( r_numAccumPasses == 1 ) - R_RenderMeshGeneric(); - else if( GL_Support( R_ENV_COMBINE_EXT )) - R_RenderMeshCombined(); - else R_RenderMeshMultitextured(); - - r_numAccumPasses = 0; -} - -/* -================ -R_AccumulatePass -================ -*/ -static void R_AccumulatePass( ref_stage_t *pass ) -{ - qboolean accumulate, renderNow; - const ref_stage_t *prevPass; - - // for depth texture we render light's view to, ignore passes that do not write into depth buffer - if( ( RI.params & RP_SHADOWMAPVIEW ) && !( pass->glState & GLSTATE_DEPTHWRITE )) - return; - - R_ShaderpassRenderMode( pass ); - - // see if there are any free texture units - renderNow = ( pass->flags & ( SHADERSTAGE_DLIGHT|SHADERSTAGE_STENCILSHADOW )) || pass->program; - accumulate = ( r_numAccumPasses < glConfig.max_texture_units ) && !renderNow; - - if( accumulate ) - { - if( !r_numAccumPasses ) - { - r_accumPasses[r_numAccumPasses++] = pass; - return; - } - - // ok, we've got several passes, diff against the previous - prevPass = r_accumPasses[r_numAccumPasses-1]; - - // see if depthfuncs and colors are good - if( - (( prevPass->glState ^ pass->glState ) & GLSTATE_DEPTHFUNC_EQ ) || - ( pass->glState & GLSTATE_ALPHAFUNC ) || - ( pass->rgbGen.type != RGBGEN_IDENTITY ) || - ( pass->alphaGen.type != ALPHAGEN_IDENTITY ) || - ( ( prevPass->glState & GLSTATE_ALPHAFUNC ) && !( pass->glState & GLSTATE_DEPTHFUNC_EQ )) - ) - accumulate = false; - - // see if blendmodes are good - if( accumulate ) - { - int mode, prevMode; - - mode = R_ShaderpassBlendmode( pass->flags ); - if( mode ) - { - prevMode = R_ShaderpassBlendmode( prevPass->flags ); - - if( GL_Support( R_ENV_COMBINE_EXT )) - { - if( prevMode == GL_REPLACE ) - accumulate = ( mode == GL_ADD ) ? GL_Support( R_TEXTURE_ENV_ADD_EXT ) : true; - else if( prevMode == GL_ADD ) - accumulate = ( mode == GL_ADD ) && GL_Support( R_TEXTURE_ENV_ADD_EXT ); - else if( prevMode == GL_MODULATE ) - accumulate = ( mode == GL_MODULATE || mode == GL_REPLACE ); - else - accumulate = false; - } - else /* if( GL_Support( R_ARB_MULTITEXTURE ))*/ - { - if( prevMode == GL_REPLACE ) - accumulate = ( mode == GL_ADD ) ? GL_Support( R_TEXTURE_ENV_ADD_EXT ) : ( mode != GL_DECAL ); - else if( prevMode == GL_ADD ) - accumulate = ( mode == GL_ADD ) && GL_Support( R_TEXTURE_ENV_ADD_EXT ); - else if( prevMode == GL_MODULATE ) - accumulate = ( mode == GL_MODULATE || mode == GL_REPLACE ); - else - accumulate = false; - } - } - else - { - accumulate = false; - } - } - } - - // no, failed to accumulate - if( !accumulate ) - { - if( r_numAccumPasses ) - R_RenderAccumulatedPasses(); - } - - r_accumPasses[r_numAccumPasses++] = pass; - if( renderNow ) - R_RenderAccumulatedPasses(); -} - -/* -================ -R_SetupLightmapMode -================ -*/ -void R_SetupLightmapMode( void ) -{ - r_lightmapPasses[0].tcgen = TCGEN_LIGHTMAP; - r_lightmapPasses[0].rgbGen.type = RGBGEN_IDENTITY; - r_lightmapPasses[0].alphaGen.type = ALPHAGEN_IDENTITY; - r_lightmapPasses[0].flags &= ~SHADERSTAGE_BLENDMODE; - r_lightmapPasses[0].glState &= ~( GLSTATE_ALPHAFUNC|GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK|GLSTATE_DEPTHFUNC_EQ ); - r_lightmapPasses[0].flags |= SHADERSTAGE_LIGHTMAP|SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE; -// r_lightmapPasses[0].glState |= GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ZERO; - if( r_lightmap->integer ) r_lightmapPasses[0].glState |= GLSTATE_DEPTHWRITE; -} - -/* -================ -R_NeedLightmapPass -================ -*/ -qboolean R_NeedLightmapPass( msurface_t *surf ) -{ - if( r_fullbright->integer ) - return false; - - // no valid lightmaps - if( !r_currentLightStyle || r_currentLightStyle->lightmapNum < 0 || r_currentLightStyle->lightmapStyles[0] == 255 ) - return false; - - if( r_currentShader->flags & SHADER_RENDERMODE ) - { - switch( tr.iRenderMode ) - { - case kRenderGlow: - case kRenderTransAdd: - case kRenderTransColor: - case kRenderTransTexture: - return false; // no lightmaps in 'add' mode - } - } - return true; -} - -/* -================ -R_RenderMeshBuffer -================ -*/ -void R_RenderMeshBuffer( const meshbuffer_t *mb ) -{ - msurface_t *surf; - ref_stage_t *pass; - mfog_t *fog; - int i, j, type; - - if( !r_backacc.numVerts || !r_backacc.numElems ) - { - R_ClearArrays(); - return; - } - - ASSERT( mb ); - - type = mb->sortkey & 3; - r_currentLightStyle = NULL; - r_currentMeshBuffer = mb; - surf = NULL; - - // trying to extract lightstyle for mesh - switch( type ) - { - case MB_MODEL: - if( RI.currentmodel ) - { - switch( RI.currentmodel->type ) - { - case mod_world: - case mod_brush: - surf = mb->infokey > 0 ? &r_worldbrushmodel->surfaces[mb->infokey-1] : NULL; - if( surf ) r_currentLightStyle = &tr.superLightStyles[surf->superLightStyle]; - break; - } - } - break; - case MB_DECAL: - j = ((mb->sortkey>>10) & (MAX_SUPER_STYLES - 1)); - r_currentLightStyle = &tr.superLightStyles[j - 1]; - surf = R_DecalFromMeshbuf( mb )->psurf; - break; - } - - MB_NUM2SHADER( mb->shaderkey, r_currentShader ); - - if( glState.in2DMode ) r_currentShaderTime = Sys_DoubleTime(); - else r_currentShaderTime = (double)RI.refdef.time; - - if( !r_triangleOutlines ) - R_SetShaderState(); - - if( r_currentShader->numDeforms ) - R_DeformVertices(); - - if( r_features & MF_KEEPLOCK ) - r_backacc.c_totalKeptLocks++; - else - R_UnlockArrays(); - - if( r_triangleOutlines ) - { - R_LockArrays( r_backacc.numVerts ); - - if( RI.params & RP_TRISOUTLINES ) - R_DrawTriangles(); - if( RI.params & RP_SHOWNORMALS ) - R_DrawNormals(); - - R_ClearArrays(); - return; - } - - // extract the fog volume number from sortkey - if( !r_worldmodel ) fog = NULL; - else MB_NUM2FOG( mb->sortkey, fog ); - - if( fog && !fog->shader ) fog = NULL; - - // can we fog the geometry with alpha texture? - r_texFog = ( fog && ( ( r_currentShader->sort <= SORT_ALPHATEST && - ( r_currentShader->flags & (SHADER_DEPTHWRITE|SHADER_SKYPARMS))) || r_currentShader->fog_dist ) ) ? fog : NULL; - - // check if the fog volume is present but we can't use alpha texture - r_colorFog = ( fog && !r_texFog ) ? fog : NULL; - - if( r_currentShader->type == SHADER_FLARE ) - r_currentDlightBits = 0; - else r_currentDlightBits = surf ? mb->dlightbits : 0; - r_currentShadowBits = mb->shadowbits & RI.shadowBits; - - R_LockArrays( r_backacc.numVerts ); - - // accumulate passes for dynamic merging - for( i = 0, pass = r_currentShader->stages; i < r_currentShader->num_stages; i++, pass++ ) - { - if( !pass->program ) - { - if( pass->flags & SHADERSTAGE_LIGHTMAP ) - { - int j, k, l, u; - - // no valid lightmaps, goodbye - if( !R_NeedLightmapPass( surf )) continue; - - // try to apply lightstyles - if(( !( pass->glState & (GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK)) || ( pass->flags & SHADERSTAGE_BLEND_MODULATE )) && ( pass->rgbGen.type == RGBGEN_IDENTITY ) && ( pass->alphaGen.type == ALPHAGEN_IDENTITY )) - { - vec3_t colorSum, color; - - // the first pass is always GL_MODULATE or GL_REPLACE - // other passes are GL_ADD - r_lightmapPasses[0] = *pass; - - if( r_lightmapPasses[0].rgbGen.args == NULL ) - { - // in cause we crash on breaklight.bsp - r_lightmapPasses[0].rgbGen.args = r_lightmapPassesArgs[0]; - } - - for( j = 0, l = 0, u = 0; j < LM_STYLES && r_currentLightStyle->lightmapStyles[j] != 255; j++ ) - { - VectorCopy( r_lightStyles[r_currentLightStyle->lightmapStyles[j]].rgb, colorSum ); - VectorClear( color ); - - for( ; ; l++ ) - { - for( k = 0; k < 3; k++ ) - { - colorSum[k] -= color[k]; - color[k] = bound( 0, colorSum[k], 1 ); - } - - if( l ) - { - if( !color[0] && !color[1] && !color[2] ) - break; - if( l == MAX_TEXTURE_UNITS+1 ) - r_lightmapPasses[0] = r_lightmapPasses[1]; - u = l % ( MAX_TEXTURE_UNITS+1 ); - } - - if( VectorCompare( color, colorWhite ) ) - { - r_lightmapPasses[u].rgbGen.type = RGBGEN_IDENTITY; - } - else - { - if( !l ) - { - r_lightmapPasses[0].flags &= ~SHADERSTAGE_BLENDMODE; - r_lightmapPasses[0].flags |= SHADERSTAGE_BLEND_MODULATE; - } - r_lightmapPasses[u].rgbGen.type = RGBGEN_CONST; - VectorCopy( color, r_lightmapPasses[u].rgbGen.args ); - } - - if( r_lightmap->integer && !l ) - R_SetupLightmapMode(); - R_AccumulatePass( &r_lightmapPasses[u] ); - } - } - } - else - { - if( r_lightmap->integer ) - { - R_SetupLightmapMode(); - pass = r_lightmapPasses; - } - R_AccumulatePass( pass ); - } - continue; - } - else if( r_lightmap->integer && ( r_currentShader->flags & SHADER_HASLIGHTMAP )) - continue; - if(( pass->flags & SHADERSTAGE_PORTALMAP ) && !( RI.params & RP_PORTALCAPTURED )) - continue; - if(( pass->flags & SHADERSTAGE_DETAIL ) && !r_detailtextures->integer ) - continue; - if(( pass->flags & SHADERSTAGE_DLIGHT ) && !r_currentDlightBits ) - continue; - } - R_AccumulatePass( pass ); - } - - // accumulate dynamic lights pass and fog pass if any - if( r_currentDlightBits && !( r_currentShader->flags & SHADER_NO_MODULATIVE_DLIGHTS )) - { - if( !r_lightmap->integer || !( r_currentShader->flags & SHADER_HASLIGHTMAP )) - R_AccumulatePass( &r_dlightsPass ); - } - - if( r_currentShadowBits && ( r_currentShader->sort >= SORT_OPAQUE ) && ( r_currentShader->sort <= SORT_ALPHATEST )) - R_AccumulatePass( &r_GLSLpasses[3] ); - - if( r_texFog && r_texFog->shader ) - { - r_fogPass.textures[0] = tr.fogTexture; - if( !r_currentShader->num_stages || r_currentShader->fog_dist || ( r_currentShader->flags & SHADER_SKYPARMS ) ) - r_fogPass.glState &= ~GLSTATE_DEPTHFUNC_EQ; - else r_fogPass.glState |= GLSTATE_DEPTHFUNC_EQ; - R_AccumulatePass( &r_fogPass ); - } - - // flush any remaining passes - if( r_numAccumPasses ) - R_RenderAccumulatedPasses(); - - R_ClearArrays(); - - pglMatrixMode( GL_MODELVIEW ); -} - -/* -================ -R_BackendCleanUpTextureUnits -================ -*/ -void R_BackendCleanUpTextureUnits( void ) -{ - R_CleanUpTextureUnits( 1 ); - - GL_LoadIdentityTexMatrix(); - pglMatrixMode( GL_MODELVIEW ); - - GL_DisableAllTexGens(); - GL_SetTexCoordArrayMode( 0 ); -} - -/* -================ -R_BackendSetPassMask -================ -*/ -void R_BackendSetPassMask( int mask ) -{ - r_currentShaderPassMask = mask; -} - -/* -================ -R_BackendResetPassMask -================ -*/ -void R_BackendResetPassMask( void ) -{ - r_currentShaderPassMask = GLSTATE_MASK; -} - -/* -================ -R_BackendBeginTriangleOutlines -================ -*/ -void R_BackendBeginTriangleOutlines( void ) -{ - r_triangleOutlines = true; - pglColor4fv( colorWhite ); - - GL_Cull( 0 ); - GL_SetState( GLSTATE_NO_DEPTH_TEST ); - pglDisable( GL_TEXTURE_2D ); - pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); -} - -/* -================ -R_BackendEndTriangleOutlines -================ -*/ -void R_BackendEndTriangleOutlines( void ) -{ - r_triangleOutlines = false; - pglColor4fv( colorWhite ); - GL_SetState( 0 ); - pglEnable( GL_TEXTURE_2D ); - pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); -} - -/* -================ -R_SetColorForOutlines -================ -*/ -static _inline void R_SetColorForOutlines( void ) -{ - ref_entity_t *ent; - int modtype = mod_bad; - int type = r_currentMeshBuffer->sortkey & 3; - - MB_NUM2ENTITY( r_currentMeshBuffer->sortkey, ent ); - - if( ent && ent->model ) - modtype = ent->model->type; - - switch( type ) - { - case MB_MODEL: - if( triState.fActive ) - { - pglColor4fv( colorMagenta ); - } - else - { - switch( modtype ) - { - case mod_bad: - case mod_world: - pglColor4fv( colorWhite ); - break; - case mod_brush: - pglColor4fv( colorYellow ); - break; - case mod_studio: - pglColor4fv( colorRed ); - break; - case mod_sprite: - pglColor4fv( colorBlue ); - break; - } - } - break; - case MB_POLY: - case MB_DECAL: - pglColor4fv( colorGreen ); - break; - } -} - -/* -================ -R_DrawTriangles -================ -*/ -static void R_DrawTriangles( void ) -{ - // ignore triapi triangles for 'debug_surface' mode - if( triState.fActive && !gl_wireframe->integer && r_speeds->integer == 4 ) - return; - - if( gl_wireframe->integer == 2 ) - R_SetColorForOutlines(); - - if( GL_Support( R_DRAW_RANGEELEMENTS_EXT )) - pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); - else pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); -} - -/* -================ -R_DrawNormals -================ -*/ -static void R_DrawNormals( void ) -{ - uint i; - - if( r_shownormals->integer == 2 ) - R_SetColorForOutlines(); - - pglBegin( GL_LINES ); - for( i = 0; i < r_backacc.numVerts; i++ ) - { - pglVertex3fv( vertsArray[i] ); - pglVertex3f( vertsArray[i][0] + normalsArray[i][0], vertsArray[i][1] + normalsArray[i][1], vertsArray[i][2] + normalsArray[i][2] ); - } - pglEnd(); -} - -/* -==================== -R_DrawEntitiesDebug - -==================== -*/ -void R_DrawEntitiesDebug( void ) -{ - int i; - - if(( RI.drawWorld == false ) || ( r_drawentities->integer < 2 )) - return; - - pglDisable( GL_TEXTURE_2D ); - GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA ); - pglDepthRange( 0, 0 ); - - for( i = 1; i < r_numEntities; i++ ) - { - RI.previousentity = RI.currententity; - RI.currententity = &r_entities[i]; - - if( !RI.currententity->model ) - continue; - - if( RP_LOCALCLIENT( RI.currententity )) - { - // ignore localcient in firstperson mode - if( !RI.thirdPerson && !( RI.params & ( RP_MIRRORVIEW|RP_SHADOWMAPVIEW ))) - continue; - } - - if( RP_FOLLOWENTITY( RI.currententity ) && RP_LOCALCLIENT( RI.currententity->parent ) && !RI.thirdPerson ) - { - // ignore entities that linked to localcient - if(!( RI.params & ( RP_MIRRORVIEW|RP_SHADOWMAPVIEW ))) - continue; - } - - if( RI.currententity->ent_type == ET_VIEWENTITY ) - { - if( RI.params & RP_NONVIEWERREF ) - continue; - } -#if 0 - // this stuff doesn't working corretly with mirrors. disabled - if( RI.currententity->m_nCachedFrameCount != r_framecount ) - continue; // culled -#endif - switch( RI.currententity->model->type ) - { - case mod_brush: - R_BmodelDrawDebug(); - break; - case mod_studio: - R_StudioDrawDebug(); - break; - case mod_sprite: - R_SpriteDrawDebug(); - break; - } - } - - pglDepthRange( gldepthmin, gldepthmax ); - pglEnable( GL_TEXTURE_2D ); -} - -static void R_DrawLine( int color, int numpoints, const float *points ) -{ - int i = numpoints - 1; - vec3_t p0, p1; - - VectorSet( p0, points[i*3+0], points[i*3+1], points[i*3+2] ); - - for( i = 0; i < numpoints; i++ ) - { - VectorSet( p1, points[i*3+0], points[i*3+1], points[i*3+2] ); - - switch( color ) - { - case 1: - pglColor4fv( colorRed ); - break; - case 2: - pglColor4fv( colorGreen ); - break; - case 4: - pglColor4fv( colorBlue ); - break; - default: - pglColor4fv( colorWhite ); - break; - } - - pglVertex3fv( p0 ); - pglVertex3fv( p1 ); - - VectorCopy( p1, p0 ); - } -} - -/* -================ -R_DrawPhysDebug -================ -*/ -void R_DrawPhysDebug( void ) -{ - if( r_physbdebug->integer ) - { - // physic debug - pglDisable( GL_TEXTURE_2D ); - GL_SetState( GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA ); - - GL_LoadMatrix( RI.worldviewMatrix ); - pglBegin( GL_LINES ); - ri.ShowCollision( R_DrawLine ); - - pglEnd(); - pglEnable( GL_TEXTURE_2D ); - } -} \ No newline at end of file diff --git a/vid_gl/r_backend.h b/vid_gl/r_backend.h deleted file mode 100644 index caf025db..00000000 --- a/vid_gl/r_backend.h +++ /dev/null @@ -1,456 +0,0 @@ -/* -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#ifndef __R_BACKEND_H__ -#define __R_BACKEND_H__ - -#define MAX_LIGHTMAPS 128 -#define MAX_SUPER_STYLES 1024 // unique lightstyle combiantions -#define MAX_TEXTURES 4096 -#define MAX_ARRAY_VERTS 12288 -#define MAX_ARRAY_ELEMENTS MAX_ARRAY_VERTS * 6 -#define MAX_ARRAY_TRIANGLES MAX_ARRAY_ELEMENTS / 3 -#define MAX_ARRAY_NEIGHBORS MAX_ARRAY_TRIANGLES * 3 - -enum -{ - VBO_VERTS, - VBO_NORMALS, - VBO_COLORS, - VBO_TC0, - VBO_ENDMARKER -}; - -#define MAX_SHADOWGROUPS 32 -#define MAX_VERTEX_BUFFER_OBJECTS VBO_ENDMARKER+MAX_TEXTURE_UNITS-1 - -extern ALIGN( 16 ) vec4_t inVertsArray[MAX_ARRAY_VERTS]; -extern ALIGN( 16 ) vec4_t inNormalsArray[MAX_ARRAY_VERTS]; -extern vec4_t inSVectorsArray[MAX_ARRAY_VERTS]; -extern vec4_t inTVectorsArray[MAX_ARRAY_VERTS]; -extern elem_t inElemsArray[MAX_ARRAY_ELEMENTS]; -extern vec2_t inCoordsArray[MAX_ARRAY_VERTS]; -extern vec2_t inLightmapCoordsArray[MAX_ARRAY_VERTS]; -extern rgba_t inColorsArray[MAX_ARRAY_VERTS]; - -extern elem_t *elemsArray; -extern vec4_t *vertsArray; -extern vec4_t *normalsArray; -extern vec4_t *sVectorsArray; -extern vec4_t *tVectorsArray; -extern vec2_t *coordsArray; -extern vec2_t *lightmapCoordsArray; -extern rgba_t colorArray[MAX_ARRAY_VERTS]; -extern int r_features; - -//=================================================================== -typedef struct vbo_buffer_s -{ - byte *pointer; - int size; - uint usage; - uint bufNum; -} vbo_buffer_t; - -typedef struct -{ - int features; - int lightmapNum; - float stOffset[2]; - int lightmapStyles[LM_STYLES]; -} ref_style_t; - -typedef struct -{ - uint numVerts; - uint numElems; - uint numColors; - - uint c_totalVerts; - uint c_totalTris; - uint c_totalFlushes; - uint c_totalKeptLocks; -} ref_backacc_t; - -typedef struct -{ - // renderer global variables - int registration_sequence; - int iRenderMode; - - // vbo stuff - int numVertexBufferObjects; - vbo_buffer_t vertexBufferObjects[MAX_VERTEX_BUFFER_OBJECTS]; - vbo_buffer_t *vertexBuffer; - vbo_buffer_t *normalBuffer; - vbo_buffer_t *colorsBuffer; - vbo_buffer_t *tcoordBuffer[MAX_TEXTURE_UNITS]; - - // OpenGL matrix states - qboolean modelviewIdentity; - - // super lightstyles - ref_style_t superLightStyles[MAX_SUPER_STYLES]; - int numSuperLightStyles; - - // builtin textures - texture_t *cinTexture; // cinematic texture - texture_t *portaltexture1; // portal view - texture_t *portaltexture2; // refraction image for distortions - texture_t *defaultTexture; // use for bad textures - texture_t *particleTexture; // little dot for particles - texture_t *whiteTexture; - texture_t *blackTexture; - texture_t *blankbumpTexture; - texture_t *dlightTexture; - texture_t *dspotlightTexture; - texture_t *normalizeTexture; // cubemap - texture_t *fogTexture; - texture_t *skyTexture; - texture_t *coronaTexture; - texture_t *shadowmapTextures[MAX_SHADOWGROUPS]; - texture_t *lightmapTextures[MAX_LIGHTMAPS]; - - // utility shaders - ref_shader_t *defaultShader; // generic black texture - ref_shader_t *fillShader; // generic white texture - ref_shader_t *currentSkyShader; // ponter to sky shader for current map -} ref_globals_t; - -extern ref_globals_t tr; -extern ref_backacc_t r_backacc; - -//=================================================================== - -void R_BackendInit( void ); -void R_BackendShutdown( void ); -void R_BackendStartFrame( void ); -void R_BackendEndFrame( void ); -void R_BackendResetCounters( void ); - -void R_BackendBeginTriangleOutlines( void ); -void R_BackendEndTriangleOutlines( void ); - -void R_BackendCleanUpTextureUnits( void ); - -void R_BackendSetPassMask( int mask ); -void R_BackendResetPassMask( void ); - -void R_DrawEntitiesDebug( void ); -void R_DrawPhysDebug( void ); - -void R_InitVertexBuffers( void ); -void R_ShutdownVertexBuffers( void ); -vbo_buffer_t *R_AllocVertexBuffer( size_t size, GLuint usage ); -void R_UpdateVertexBuffer( vbo_buffer_t *vertexBuffer, const void *data, size_t size ); - -void R_LockArrays( int numverts ); -void R_UnlockArrays( void ); -void R_UnlockArrays( void ); -void R_FlushArrays( void ); -void R_FlushArraysMtex( void ); -void R_ClearArrays( void ); - -static _inline void R_PushElems( elem_t *elems, int count, int features ) -{ - elem_t *currentElem; - - // this is a fast path for non-batched geometry, use carefully - // used on pics, sprites, .dpm, .md3 and .md2 models - if( features & MF_NONBATCHED ) - { - // simply change elemsArray to point at elems - r_backacc.numElems = count; - elemsArray = currentElem = elems; - } - else - { - currentElem = elemsArray + r_backacc.numElems; - r_backacc.numElems += count; - - // the following code assumes that R_PushElems is fed with triangles... - for(; count > 0; count -= 3, elems += 3, currentElem += 3 ) - { - currentElem[0] = r_backacc.numVerts + elems[0]; - currentElem[1] = r_backacc.numVerts + elems[1]; - currentElem[2] = r_backacc.numVerts + elems[2]; - } - } -} - -static _inline void R_PushTrifanElems( int numverts ) -{ - elem_t *currentElem; - int count; - - currentElem = elemsArray + r_backacc.numElems; - r_backacc.numElems += numverts + numverts + numverts - 6; - - for( count = 2; count < numverts; count++, currentElem += 3 ) - { - currentElem[0] = r_backacc.numVerts; - currentElem[1] = r_backacc.numVerts + count - 1; - currentElem[2] = r_backacc.numVerts + count; - } -} - -static _inline void R_PushMesh( const mesh_t *mesh, int features ) -{ - int numverts; - - if( !mesh || !( mesh->elems || ( features & MF_TRIFAN )) || !mesh->vertexArray ) - return; - - r_features = features; - - if( features & MF_TRIFAN ) R_PushTrifanElems( mesh->numVerts ); - else R_PushElems( mesh->elems, mesh->numElems, features ); - - numverts = mesh->numVerts; - - if( features & MF_NONBATCHED ) - { - if( features & MF_DEFORMVS ) - { - if( mesh->vertexArray != inVertsArray ) - Mem_Copy( inVertsArray, mesh->vertexArray, numverts * sizeof( vec4_t ) ); - - if( ( features & MF_NORMALS ) && mesh->normalsArray && ( mesh->normalsArray != inNormalsArray ) ) - Mem_Copy( inNormalsArray, mesh->normalsArray, numverts * sizeof( vec4_t ) ); - } - else - { - vertsArray = mesh->vertexArray; - - if( ( features & MF_NORMALS ) && mesh->normalsArray ) - normalsArray = mesh->normalsArray; - } - - if(( features & MF_STCOORDS ) && mesh->stCoordArray ) - coordsArray = mesh->stCoordArray; - - if(( features & MF_LMCOORDS ) && mesh->lmCoordArray ) - lightmapCoordsArray = mesh->lmCoordArray; - - if(( features & MF_SVECTORS ) && mesh->sVectorsArray ) - sVectorsArray = mesh->sVectorsArray; - - if(( features & MF_TVECTORS ) && mesh->tVectorsArray ) - tVectorsArray = mesh->tVectorsArray; - } - else - { - if( mesh->vertexArray != inVertsArray ) - Mem_Copy( inVertsArray[r_backacc.numVerts], mesh->vertexArray, numverts * sizeof( vec4_t )); - - if(( features & MF_NORMALS ) && mesh->normalsArray && (mesh->normalsArray != inNormalsArray )) - Mem_Copy( inNormalsArray[r_backacc.numVerts], mesh->normalsArray, numverts * sizeof( vec4_t )); - - if(( features & MF_STCOORDS ) && mesh->stCoordArray && ( mesh->stCoordArray != inCoordsArray )) - Mem_Copy( inCoordsArray[r_backacc.numVerts], mesh->stCoordArray, numverts * sizeof( vec2_t )); - - if(( features & MF_LMCOORDS ) && mesh->lmCoordArray && ( mesh->lmCoordArray != inLightmapCoordsArray )) - Mem_Copy( inLightmapCoordsArray[r_backacc.numVerts], mesh->lmCoordArray, numverts * sizeof( vec2_t )); - - if(( features & MF_SVECTORS ) && mesh->sVectorsArray && (mesh->sVectorsArray != inSVectorsArray )) - Mem_Copy( inSVectorsArray[r_backacc.numVerts], mesh->sVectorsArray, numverts * sizeof( vec4_t )); - - if(( features & MF_TVECTORS ) && mesh->tVectorsArray && (mesh->tVectorsArray != inTVectorsArray )) - Mem_Copy( inTVectorsArray[r_backacc.numVerts], mesh->tVectorsArray, numverts * sizeof( vec4_t )); - } - - if(( features & MF_COLORS ) && mesh->colorsArray ) - Mem_Copy( inColorsArray[r_backacc.numVerts], mesh->colorsArray, numverts * sizeof( rgba_t )); - - r_backacc.numVerts += numverts; - r_backacc.c_totalVerts += numverts; -} - -static _inline qboolean R_MeshOverflow( const mesh_t *mesh ) -{ - if( !mesh ) return false; - return ( r_backacc.numVerts + mesh->numVerts > MAX_ARRAY_VERTS || r_backacc.numElems + mesh->numElems > MAX_ARRAY_ELEMENTS ); -} - -static _inline qboolean R_MeshOverflow2( const mesh_t *mesh1, const mesh_t *mesh2 ) -{ - return ( r_backacc.numVerts + mesh1->numVerts + mesh2->numVerts > MAX_ARRAY_VERTS || - r_backacc.numElems + mesh1->numElems + mesh2->numElems > MAX_ARRAY_ELEMENTS ); -} - -static _inline qboolean R_InvalidMesh( const mesh_t *mesh ) -{ - return ( !mesh->numVerts || !mesh->numElems || mesh->numVerts > MAX_ARRAY_VERTS || mesh->numElems > MAX_ARRAY_ELEMENTS ); -} - -void R_RenderMeshBuffer( const meshbuffer_t *mb ); - -/* -======================================================================= - - GL STATE MACHINE - -======================================================================= -*/ -// render supported extensions -// this part are shared with engine.dll -#define R_OPENGL_110 0 // base -#define R_WGL_SWAPCONTROL 1 -#define R_HARDWARE_GAMMA_CONTROL 2 -#define R_ARB_VERTEX_BUFFER_OBJECT_EXT 3 -#define R_ENV_COMBINE_EXT 4 -#define R_ARB_MULTITEXTURE 5 -#define R_TEXTURECUBEMAP_EXT 6 -#define R_DOT3_ARB_EXT 7 -#define R_ANISOTROPY_EXT 8 -#define R_TEXTURE_LODBIAS 9 -#define R_OCCLUSION_QUERIES_EXT 10 -#define R_TEXTURE_COMPRESSION_EXT 11 -#define R_SHADER_GLSL100_EXT 12 - -// this part are private for render.dll -#define R_WGL_3DFX_GAMMA_CONTROL 13 -#define R_SGIS_MIPMAPS_EXT 14 -#define R_DRAW_RANGEELEMENTS_EXT 15 -#define R_LOCKARRAYS_EXT 16 -#define R_TEXTURE_3D_EXT 17 -#define R_CLAMPTOEDGE_EXT 18 -#define R_BLEND_MINMAX_EXT 19 -#define R_STENCILTWOSIDE_EXT 20 -#define R_BLEND_SUBTRACT_EXT 21 -#define R_SHADER_OBJECTS_EXT 22 -#define R_VERTEX_SHADER_EXT 23 // glsl vertex program -#define R_FRAGMENT_SHADER_EXT 24 // glsl fragment program -#define R_EXT_POINTPARAMETERS 25 -#define R_SEPARATESTENCIL_EXT 26 -#define R_ARB_TEXTURE_NPOT_EXT 27 -#define R_CUSTOM_VERTEX_ARRAY_EXT 28 -#define R_TEXTURE_ENV_ADD_EXT 29 -#define R_CLAMP_TEXBORDER_EXT 30 -#define R_DEPTH_TEXTURE 31 -#define R_SHADOW_EXT 32 -#define R_GLSL_NO_HALF_TYPES 33 // fake extension -#define R_GLSL_BRANCHING 34 // fake extension -#define R_EXTCOUNT 35 - -typedef struct -{ - const char *renderer_string; // ptrs to OpenGL32.dll, use with caution - const char *vendor_string; - const char *version_string; - - // list of supported extensions - const char *extensions_string; - byte extension[R_EXTCOUNT]; - - int max_texture_units; - GLint max_2d_texture_size; - GLint max_2d_rectangle_size; - GLint max_3d_texture_size; - GLint max_cubemap_texture_size; - GLint texRectangle; - - GLfloat max_texture_anisotropy; - GLfloat max_texture_lodbias; - - int color_bits; - int depth_bits; - int stencil_bits; - - qboolean allowCDS; - qboolean deviceSupportsGamma; - int prev_mode; -} glconfig_t; - -typedef struct -{ - int flags; - - word gammaRamp[768]; // current gamma ramp - word stateRamp[768]; // original gamma ramp - - int width, height; - qboolean fullScreen; - qboolean wideScreen; - - qboolean initializedMedia; - - int activeTMU; - GLuint currentTextures[MAX_TEXTURE_UNITS]; - GLenum currentEnvModes[MAX_TEXTURE_UNITS]; - GLqbooleanean texIdentityMatrix[MAX_TEXTURE_UNITS]; - GLint genSTEnabled[MAX_TEXTURE_UNITS]; // 0 - disabled, OR 1 - S, OR 2 - T, OR 4 - R - GLint texCoordArrayMode[MAX_TEXTURE_UNITS]; // 0 - disabled, 1 - enabled, 2 - cubemap - - rgba_t draw_color; - int draw_rendermode; // rendermode for drawing - int draw_frame; // will be reset after each drawing - - int faceCull; - int frontFace; - - qboolean stencilEnabled; - qboolean in2DMode; -} glstate_t; - -typedef struct -{ - qboolean fActive; // drawing in progress - int currentRenderMode; - shader_t currentShader; - int vertexState; - int drawMode; - rgba_t color; - vec3_t lightingOrigin; - vec3_t mins, maxs; // for compute lightbounds - - // linear fog stuff - vec4_t fogColor; - float fogStartDist; - float fogEndDist; - qboolean fogEnabled; - - int features; - int numVertex; - int numColor; - int numIndex; - - qboolean noCulling; - qboolean checkFlush; - qboolean hasNormals; -} tristate_t; - -extern glconfig_t glConfig; -extern glstate_t glState; -extern tristate_t triState; - -// r_register.c -void GL_InitBackend( void ); -qboolean GL_Support( int r_ext ); -void GL_InitExtensions( void ); -void GL_ShutdownBackend( void ); -void GL_UpdateSwapInterval( void ); -void GL_UpdateGammaRamp( void ); -void GL_SetExtension( int r_ext, int enable ); -void GL_BuildGammaTable( void ); - -qboolean R_Init_OpenGL( void ); -void R_Free_OpenGL( void ); - -#endif /*__R_BACKEND_H__*/ diff --git a/vid_gl/r_bloom.c b/vid_gl/r_bloom.c deleted file mode 100644 index 05707090..00000000 --- a/vid_gl/r_bloom.c +++ /dev/null @@ -1,524 +0,0 @@ -/* -Copyright (C) Forest Hale -Copyright (C) 2006-2007 German Garcia - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// r_bloom.c: 2D lighting post process effect - -#include "r_local.h" - -/* -============================================================================== - -LIGHT BLOOMS - -============================================================================== -*/ - -static float Diamond8x[8][8] = -{ - { 0.0f, 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, 0.0f, }, - { 0.0f, 0.0f, 0.2f, 0.3f, 0.3f, 0.2f, 0.0f, 0.0f, }, - { 0.0f, 0.2f, 0.4f, 0.6f, 0.6f, 0.4f, 0.2f, 0.0f, }, - { 0.1f, 0.3f, 0.6f, 0.9f, 0.9f, 0.6f, 0.3f, 0.1f, }, - { 0.1f, 0.3f, 0.6f, 0.9f, 0.9f, 0.6f, 0.3f, 0.1f, }, - { 0.0f, 0.2f, 0.4f, 0.6f, 0.6f, 0.4f, 0.2f, 0.0f, }, - { 0.0f, 0.0f, 0.2f, 0.3f, 0.3f, 0.2f, 0.0f, 0.0f, }, - { 0.0f, 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, 0.0f } -}; - -static float Diamond6x[6][6] = -{ - { 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, }, - { 0.0f, 0.3f, 0.5f, 0.5f, 0.3f, 0.0f, }, - { 0.1f, 0.5f, 0.9f, 0.9f, 0.5f, 0.1f, }, - { 0.1f, 0.5f, 0.9f, 0.9f, 0.5f, 0.1f, }, - { 0.0f, 0.3f, 0.5f, 0.5f, 0.3f, 0.0f, }, - { 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f } -}; - -static float Diamond4x[4][4] = -{ - { 0.3f, 0.4f, 0.4f, 0.3f, }, - { 0.4f, 0.9f, 0.9f, 0.4f, }, - { 0.4f, 0.9f, 0.9f, 0.4f, }, - { 0.3f, 0.4f, 0.4f, 0.3f } -}; - -static int BLOOM_SIZE; - -static texture_t *r_bloomscreentexture; -static texture_t *r_bloomeffecttexture; -static texture_t *r_bloombackuptexture; -static texture_t *r_bloomdownsamplingtexture; - -static int r_screendownsamplingtexture_size; -static int screen_texture_width, screen_texture_height; -static int r_screenbackuptexture_width, r_screenbackuptexture_height; - -// current refdef size: -static int curView_x; -static int curView_y; -static int curView_width; -static int curView_height; - -// texture coordinates of screen data inside screentexture -static float screenTex_tcw; -static float screenTex_tch; - -static int sample_width; -static int sample_height; - -// texture coordinates of adjusted textures -static float sampleText_tcw; -static float sampleText_tch; - -/* -================= -R_Bloom_InitBackUpTexture -================= -*/ -static void R_Bloom_InitBackUpTexture( int width, int height ) -{ - rgbdata_t r_bloom; - - Mem_Set( &r_bloom, 0, sizeof( rgbdata_t )); - r_screenbackuptexture_width = width; - r_screenbackuptexture_height = height; - - r_bloom.width = width; - r_bloom.height = height; - r_bloom.type = PF_RGBA_32; - r_bloom.size = width * height * 4; - r_bloom.flags = 0; - r_bloom.palette = NULL; - r_bloom.buffer = Mem_Alloc( r_temppool, width * height * 4 ); - - r_bloombackuptexture = R_LoadTexture( "***r_bloombackuptexture***", &r_bloom, 3, TF_STATIC|TF_UNCOMPRESSED|TF_NOPICMIP|TF_CLAMP|TF_NOMIPMAP ); - Mem_Free( r_bloom.buffer ); -} - -/* -================= -R_Bloom_InitEffectTexture -================= -*/ -static void R_Bloom_InitEffectTexture( void ) -{ - int limit; - rgbdata_t r_bloomfx; - - Mem_Set( &r_bloomfx, 0, sizeof( rgbdata_t )); - - if( r_bloom_sample_size->integer < 32 ) - Cvar_Set( "r_bloom_sample_size", "32" ); - - // make sure bloom size doesn't have stupid values - limit = min( r_bloom_sample_size->integer, min( screen_texture_width, screen_texture_height ) ); - - if( GL_Support( R_ARB_TEXTURE_NPOT_EXT )) - BLOOM_SIZE = limit; - else // make sure bloom size is a power of 2 - for( BLOOM_SIZE = 32; (BLOOM_SIZE<<1) <= limit; BLOOM_SIZE <<= 1 ); - - if( BLOOM_SIZE != r_bloom_sample_size->integer ) - Cvar_Set( "r_bloom_sample_size", va( "%i", BLOOM_SIZE ) ); - - r_bloomfx.width = BLOOM_SIZE; - r_bloomfx.height = BLOOM_SIZE; - r_bloomfx.size = BLOOM_SIZE * BLOOM_SIZE * 4; - r_bloomfx.type = PF_RGBA_32; - r_bloomfx.flags = 0; - r_bloomfx.palette = NULL; - r_bloomfx.buffer = Mem_Alloc( r_temppool, BLOOM_SIZE * BLOOM_SIZE * 4 ); - - r_bloomeffecttexture = R_LoadTexture( "***r_bloomeffecttexture***", &r_bloomfx, 3, TF_STATIC|TF_UNCOMPRESSED|TF_NOPICMIP|TF_CLAMP|TF_NOMIPMAP ); - Mem_Free( r_bloomfx.buffer ); -} - -/* -================= -R_Bloom_InitTextures -================= -*/ -static void R_Bloom_InitTextures( void ) -{ - int size; - rgbdata_t r_bloomscr, r_downsample; - - Mem_Set( &r_bloomscr, 0, sizeof( rgbdata_t )); - Mem_Set( &r_downsample, 0, sizeof( rgbdata_t )); - - if( GL_Support( R_ARB_TEXTURE_NPOT_EXT )) - { - screen_texture_width = glState.width; - screen_texture_height = glState.height; - } - else - { - // find closer power of 2 to screen size - for (screen_texture_width = 1;screen_texture_width < glState.width;screen_texture_width <<= 1); - for (screen_texture_height = 1;screen_texture_height < glState.height;screen_texture_height <<= 1); - } - - // disable blooms if we can't handle a texture of that size - if( screen_texture_width > glConfig.max_2d_texture_size || screen_texture_height > glConfig.max_2d_texture_size ) - { - screen_texture_width = screen_texture_height = 0; - Cvar_Set( "r_bloom_intensity", "0" ); - MsgDev( D_WARN, "'R_InitBloomScreenTexture' too high resolution for light bloom, effect disabled\n" ); - return; - } - - // init the screen texture - size = screen_texture_width * screen_texture_height * 4; - - r_bloomscr.width = screen_texture_width; - r_bloomscr.height = screen_texture_height; - r_bloomscr.type = PF_RGBA_32; - r_bloomscr.flags = 0; - r_bloomscr.palette = NULL; - r_bloomscr.size = size; - r_bloomscr.buffer = Mem_Alloc( r_temppool, size ); - Mem_Set( r_bloomscr.buffer, 255, size ); - - r_bloomscreentexture = R_LoadTexture( "***r_bloomscreentexture***", &r_bloomscr, 3, TF_STATIC|TF_UNCOMPRESSED|TF_NOPICMIP|TF_CLAMP|TF_NOMIPMAP ); - Mem_Free( r_bloomscr.buffer ); - - // validate bloom size and init the bloom effect texture - R_Bloom_InitEffectTexture(); - - // if screensize is more than 2x the bloom effect texture, set up for stepped downsampling - r_bloomdownsamplingtexture = NULL; - r_screendownsamplingtexture_size = 0; - - if(( glState.width > (BLOOM_SIZE * 2) || glState.height > (BLOOM_SIZE * 2)) && !r_bloom_fast_sample->integer ) - { - r_screendownsamplingtexture_size = (int)( BLOOM_SIZE * 2 ); - r_downsample.width = r_screendownsamplingtexture_size; - r_downsample.height = r_screendownsamplingtexture_size; - r_downsample.type = PF_RGBA_32; - r_downsample.size = r_screendownsamplingtexture_size * r_screendownsamplingtexture_size * 4; - r_downsample.flags = 0; - r_downsample.palette = NULL; - r_downsample.buffer = Mem_Alloc( r_temppool, r_downsample.size ); - - r_bloomdownsamplingtexture = R_LoadTexture( "***r_bloomdownsamplingtexture***", &r_downsample, 3, TF_STATIC|TF_NOPICMIP|TF_UNCOMPRESSED|TF_CLAMP|TF_NOMIPMAP ); - Mem_Free( r_downsample.buffer ); - } - - // init the screen backup texture - if( r_screendownsamplingtexture_size ) - R_Bloom_InitBackUpTexture( r_screendownsamplingtexture_size, r_screendownsamplingtexture_size ); - else R_Bloom_InitBackUpTexture( BLOOM_SIZE, BLOOM_SIZE ); -} - -/* -================= -R_InitBloomTextures -================= -*/ -void R_InitBloomTextures( void ) -{ - BLOOM_SIZE = 0; - if( !r_bloom_intensity->integer ) - return; - R_Bloom_InitTextures(); -} - -/* -================= -R_Bloom_SamplePass -================= -*/ -static _inline void R_Bloom_SamplePass( int xpos, int ypos ) -{ - pglBegin( GL_QUADS ); - pglTexCoord2f( 0, sampleText_tch ); - pglVertex2f( xpos, ypos ); - pglTexCoord2f( 0, 0 ); - pglVertex2f( xpos, ypos+sample_height ); - pglTexCoord2f( sampleText_tcw, 0 ); - pglVertex2f( xpos+sample_width, ypos+sample_height ); - pglTexCoord2f( sampleText_tcw, sampleText_tch ); - pglVertex2f( xpos+sample_width, ypos ); - pglEnd(); -} - -/* -================= -R_Bloom_Quad -================= -*/ -static _inline void R_Bloom_Quad( int x, int y, int w, int h, float texwidth, float texheight ) -{ - pglBegin( GL_QUADS ); - pglTexCoord2f( 0, texheight ); - pglVertex2f( x, glState.height-h-y ); - pglTexCoord2f( 0, 0 ); - pglVertex2f( x, glState.height-y ); - pglTexCoord2f( texwidth, 0 ); - pglVertex2f( x+w, glState.height-y ); - pglTexCoord2f( texwidth, texheight ); - pglVertex2f( x+w, glState.height-h ); - pglEnd(); -} - -/* -================= -R_Bloom_DrawEffect -================= -*/ -static void R_Bloom_DrawEffect( void ) -{ - GL_Bind( 0, r_bloomeffecttexture ); - GL_TexEnv( GL_MODULATE ); - GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE ); - pglColor4f( r_bloom_alpha->value, r_bloom_alpha->value, r_bloom_alpha->value, 1.0f ); - - pglBegin( GL_QUADS ); - pglTexCoord2f( 0, sampleText_tch ); - pglVertex2f( curView_x, curView_y ); - pglTexCoord2f( 0, 0 ); - pglVertex2f( curView_x, curView_y+curView_height ); - pglTexCoord2f( sampleText_tcw, 0 ); - pglVertex2f( curView_x+curView_width, curView_y+curView_height ); - pglTexCoord2f( sampleText_tcw, sampleText_tch ); - pglVertex2f( curView_x+curView_width, curView_y ); - pglEnd(); -} - -/* -================= -R_Bloom_GeneratexDiamonds -================= -*/ -static void R_Bloom_GeneratexDiamonds( void ) -{ - int i, j, k; - float intensity, scale, *diamond; - - // set up sample size workspace - pglScissor( 0, 0, sample_width, sample_height ); - pglViewport( 0, 0, sample_width, sample_height ); - pglMatrixMode( GL_PROJECTION ); - pglLoadIdentity(); - pglOrtho( 0, sample_width, sample_height, 0, -10, 100 ); - pglMatrixMode( GL_MODELVIEW ); - pglLoadIdentity(); - - // copy small scene into r_bloomeffecttexture - GL_Bind( 0, r_bloomeffecttexture ); - pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height ); - - // start modifying the small scene corner - pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); - - // darkening passes - if( r_bloom_darken->integer ) - { - GL_TexEnv( GL_MODULATE ); - GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_ZERO ); - - for( i = 0; i < r_bloom_darken->integer; i++ ) - R_Bloom_SamplePass( 0, 0 ); - pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height ); - } - - // bluring passes - GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE_MINUS_SRC_COLOR ); - - if( r_bloom_diamond_size->integer > 7 || r_bloom_diamond_size->integer <= 3 ) - { - if( r_bloom_diamond_size->integer != 8 ) - Cvar_Set( "r_bloom_diamond_size", "8" ); - } - else if( r_bloom_diamond_size->integer > 5 ) - { - if( r_bloom_diamond_size->integer != 6 ) - Cvar_Set( "r_bloom_diamond_size", "6" ); - } - else if( r_bloom_diamond_size->integer > 3 ) - { - if( r_bloom_diamond_size->integer != 4 ) - Cvar_Set( "r_bloom_diamond_size", "4" ); - } - - switch( r_bloom_diamond_size->integer ) - { - case 4: - k = 2; - diamond = &Diamond4x[0][0]; - scale = r_bloom_intensity->value * 0.8f; - break; - case 6: - k = 3; - diamond = &Diamond6x[0][0]; - scale = r_bloom_intensity->value * 0.5f; - break; - default: - k = 4; - diamond = &Diamond8x[0][0]; - scale = r_bloom_intensity->value * 0.3f; - break; - } - - for( i = 0; i < r_bloom_diamond_size->integer; i++ ) - { - for( j = 0; j < r_bloom_diamond_size->integer; j++, diamond++ ) - { - intensity = *diamond * scale; - if( intensity < 0.01f ) - continue; - - pglColor4f( intensity, intensity, intensity, 1.0 ); - R_Bloom_SamplePass( i - k, j - k ); - } - } - - pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height ); - - // restore full screen workspace - pglScissor( 0, 0, glState.width, glState.height ); - pglViewport( 0, 0, glState.width, glState.height ); - pglMatrixMode( GL_PROJECTION ); - pglLoadIdentity(); - pglOrtho( 0, glState.width, glState.height, 0, -10, 100 ); - pglMatrixMode( GL_MODELVIEW ); - pglLoadIdentity(); -} - -/* -================= -R_Bloom_DownsampleView -================= -*/ -static void R_Bloom_DownsampleView( void ) -{ - pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); - - if( r_screendownsamplingtexture_size ) - { - // stepped downsample - int midsample_width = ( r_screendownsamplingtexture_size * sampleText_tcw ); - int midsample_height = ( r_screendownsamplingtexture_size * sampleText_tch ); - - // copy the screen and draw resized - GL_Bind( 0, r_bloomscreentexture ); - pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, curView_x, glState.height - ( curView_y + curView_height ), curView_width, curView_height ); - R_Bloom_Quad( 0, 0, midsample_width, midsample_height, screenTex_tcw, screenTex_tch ); - - // now copy into downsampling (mid-sized) texture - GL_Bind( 0, r_bloomdownsamplingtexture ); - pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, midsample_width, midsample_height ); - - // now draw again in bloom size - pglColor4f( 0.5f, 0.5f, 0.5f, 1.0f ); - R_Bloom_Quad( 0, 0, sample_width, sample_height, sampleText_tcw, sampleText_tch ); - - // now blend the big screen texture into the bloom generation space (hoping it adds some blur) - GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE ); - - GL_Bind( 0, r_bloomscreentexture ); - R_Bloom_Quad( 0, 0, sample_width, sample_height, screenTex_tcw, screenTex_tch ); - pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); - } - else - { - // downsample simple - GL_Bind( 0, r_bloomscreentexture ); - pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, curView_x, glState.height - ( curView_y + curView_height ), curView_width, curView_height ); - R_Bloom_Quad( 0, 0, sample_width, sample_height, screenTex_tcw, screenTex_tch ); - } -} - -/* -================= -R_BloomBlend -================= -*/ -void R_BloomBlend( const ref_params_t *fd ) -{ - if( !r_bloom_intensity->integer ) - return; - - if( !BLOOM_SIZE ) - R_Bloom_InitTextures(); - - if( screen_texture_width < BLOOM_SIZE || screen_texture_height < BLOOM_SIZE ) - return; - - // set up full screen workspace - pglScissor( 0, 0, glState.width, glState.height ); - pglViewport( 0, 0, glState.width, glState.height ); - pglMatrixMode( GL_PROJECTION ); - pglLoadIdentity(); - pglOrtho( 0, glState.width, glState.height, 0, -10, 100 ); - pglMatrixMode( GL_MODELVIEW ); - pglLoadIdentity(); - - GL_Cull( 0 ); - GL_SetState( GLSTATE_NO_DEPTH_TEST ); - - pglColor4f( 1, 1, 1, 1 ); - - // set up current sizes - curView_x = fd->viewport[0]; - curView_y = fd->viewport[1]; - curView_width = fd->viewport[2]; - curView_height = fd->viewport[3]; - - screenTex_tcw = ( (float)curView_width / (float)screen_texture_width ); - screenTex_tch = ( (float)curView_height / (float)screen_texture_height ); - if( curView_height > curView_width ) - { - sampleText_tcw = ( (float)curView_width / (float)curView_height ); - sampleText_tch = 1.0f; - } - else - { - sampleText_tcw = 1.0f; - sampleText_tch = ( (float)curView_height / (float)curView_width ); - } - - sample_width = ( BLOOM_SIZE * sampleText_tcw ); - sample_height = ( BLOOM_SIZE * sampleText_tch ); - - // copy the screen space we'll use to work into the backup texture - GL_Bind( 0, r_bloombackuptexture ); - pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, r_screenbackuptexture_width, r_screenbackuptexture_height ); - - // create the bloom image - R_Bloom_DownsampleView(); - R_Bloom_GeneratexDiamonds(); - - // restore the screen-backup to the screen - GL_SetState( GLSTATE_NO_DEPTH_TEST ); - GL_Bind( 0, r_bloombackuptexture ); - - pglColor4f( 1, 1, 1, 1 ); - - R_Bloom_Quad( 0, 0, r_screenbackuptexture_width, r_screenbackuptexture_height, 1.0f, 1.0f ); - - pglScissor( RI.scissor[0], RI.scissor[1], RI.scissor[2], RI.scissor[3] ); - - R_Bloom_DrawEffect(); - - pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] ); -} diff --git a/vid_gl/r_cull.c b/vid_gl/r_cull.c deleted file mode 100644 index 4d8cc952..00000000 --- a/vid_gl/r_cull.c +++ /dev/null @@ -1,585 +0,0 @@ -/* -Copyright (C) 2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "r_local.h" -#include "mathlib.h" -#include "cl_entity.h" - -/* -============================================================= - -FRUSTUM AND PVS CULLING - -============================================================= -*/ - -/* -================= -R_CullBox - -Returns true if the box is completely outside the frustum -================= -*/ -qboolean R_CullBox( const vec3_t mins, const vec3_t maxs, const uint clipflags ) -{ - uint i, bit; - const mplane_t *p; - - if( r_nocull->integer ) - return false; - - for( i = sizeof( RI.frustum )/sizeof( RI.frustum[0] ), bit = 1, p = RI.frustum; i > 0; i--, bit<<=1, p++ ) - { - if( !( clipflags & bit )) - continue; - - switch( p->signbits ) - { - case 0: - if( p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist ) - return true; - break; - case 1: - if( p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist ) - return true; - break; - case 2: - if( p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist ) - return true; - break; - case 3: - if( p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist ) - return true; - break; - case 4: - if( p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist ) - return true; - break; - case 5: - if( p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist ) - return true; - break; - case 6: - if( p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist ) - return true; - break; - case 7: - if( p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist ) - return true; - break; - default: - return false; - } - } - - return false; -} - -/* -================= -R_CullSphere - -Returns true if the sphere is completely outside the frustum -================= -*/ -qboolean R_CullSphere( const vec3_t centre, const float radius, const uint clipflags ) -{ - uint i, bit; - const mplane_t *p; - - if( r_nocull->integer ) - return false; - - for( i = sizeof( RI.frustum ) / sizeof( RI.frustum[0] ), bit = 1, p = RI.frustum; i > 0; i--, bit <<= 1, p++ ) - { - if(!( clipflags & bit )) continue; - if( DotProduct( centre, p->normal ) - p->dist <= -radius ) - return true; - } - return false; -} - -/* -=================== -R_VisCullBox -=================== -*/ -qboolean R_VisCullBox( const vec3_t mins, const vec3_t maxs ) -{ - int s, stackdepth = 0; - vec3_t extmins, extmaxs; - mnode_t *node, *localstack[2048]; - - if( !r_worldmodel || ( RI.drawWorld == false )) - return false; - if( r_novis->integer ) - return false; - - for( s = 0; s < 3; s++ ) - { - extmins[s] = mins[s] - 4; - extmaxs[s] = maxs[s] + 4; - } - - for( node = r_worldbrushmodel->nodes; node; ) - { - if( node->pvsframe != r_pvsframecount ) - { - if( !stackdepth ) - return true; - node = localstack[--stackdepth]; - continue; - } - - if( !node->plane ) - return false; - - s = BOX_ON_PLANE_SIDE( extmins, extmaxs, node->plane ) - 1; - - if( s < 2 ) - { - node = node->children[s]; - continue; - } - - // go down both sides - if( stackdepth < sizeof( localstack )/sizeof( mnode_t * ) ) - localstack[stackdepth++] = node->children[0]; - node = node->children[1]; - } - - return true; -} - -/* -=================== -R_VisCullSphere -=================== -*/ -qboolean R_VisCullSphere( const vec3_t origin, float radius ) -{ - float dist; - int stackdepth = 0; - mnode_t *node, *localstack[2048]; - - if( !r_worldmodel || ( RI.drawWorld == false )) - return false; - if( r_novis->integer ) - return false; - - radius += 4; - for( node = r_worldbrushmodel->nodes;; ) - { - if( node->pvsframe != r_pvsframecount ) - { - if( !stackdepth ) - return true; - node = localstack[--stackdepth]; - continue; - } - - if( !node->plane ) - return false; - - dist = PlaneDiff( origin, node->plane ); - if( dist > radius ) - { - node = node->children[0]; - continue; - } - else if( dist < -radius ) - { - node = node->children[1]; - continue; - } - - // go down both sides - if( stackdepth < sizeof( localstack )/sizeof( mnode_t * ) ) - localstack[stackdepth++] = node->children[0]; - node = node->children[1]; - } - - return true; -} - -/* -============= -R_CullModel -============= -*/ -int R_CullModel( ref_entity_t *e, vec3_t mins, vec3_t maxs, float radius ) -{ - if( e->ent_type == ET_VIEWENTITY ) - { - if( RI.params & RP_NONVIEWERREF ) - return 1; - return 0; - } - - // don't reflect this entity in mirrors - if( e->flags & EF_NOREFLECT && RI.params & RP_MIRRORVIEW ) - return 1; - - // draw only in mirrors - if( e->flags & EF_REFLECTONLY && !( RI.params & RP_MIRRORVIEW )) - return 1; - - if( RP_LOCALCLIENT( e ) && !RI.thirdPerson ) - { - if(!( RI.params & ( RP_MIRRORVIEW|RP_SHADOWMAPVIEW ))) - return 1; - } - - if( RP_FOLLOWENTITY( e ) && RP_LOCALCLIENT( e->parent ) && !RI.thirdPerson ) - { - if(!( RI.params & ( RP_MIRRORVIEW|RP_SHADOWMAPVIEW ))) - return 1; - } - - if( R_CullSphere( e->origin, radius, RI.clipFlags )) - return 1; - - if( RI.rdflags & ( RDF_PORTALINVIEW|RDF_SKYPORTALINVIEW ) || ( RI.params & RP_SKYPORTALVIEW )) - { - if( R_VisCullSphere( e->origin, radius )) - return 2; - } - - return 0; -} - - -/* -============================================================= - -OCCLUSION QUERIES - -============================================================= -*/ - -// occlusion queries for entities -#define BEGIN_OQ_ENTITIES 0 -#define MAX_OQ_ENTITIES MAX_ENTITIES -#define END_OQ_ENTITIES ( BEGIN_OQ_ENTITIES+MAX_OQ_ENTITIES ) - -// occlusion queries for planar shadows -#define BEGIN_OQ_PLANARSHADOWS END_OQ_ENTITIES -#define MAX_OQ_PLANARSHADOWS MAX_ENTITIES -#define END_OQ_PLANARSHADOWS ( BEGIN_OQ_PLANARSHADOWS+MAX_OQ_PLANARSHADOWS ) - -// occlusion queries for shadowgroups -#define BEGIN_OQ_SHADOWGROUPS END_OQ_PLANARSHADOWS -#define MAX_OQ_SHADOWGROUPS MAX_SHADOWGROUPS -#define END_OQ_SHADOWGROUPS ( BEGIN_OQ_SHADOWGROUPS+MAX_OQ_SHADOWGROUPS ) - -// custom occlusion queries (portals, mirrors, etc) -#define BEGIN_OQ_CUSTOM END_OQ_SHADOWGROUPS -#define MAX_OQ_CUSTOM MAX_SURF_QUERIES -#define END_OQ_CUSTOM ( BEGIN_OQ_CUSTOM+MAX_OQ_CUSTOM ) - -#define MAX_OQ_TOTAL ( MAX_OQ_ENTITIES+MAX_OQ_PLANARSHADOWS+MAX_OQ_SHADOWGROUPS+MAX_OQ_CUSTOM ) - -static byte r_queriesBits[MAX_OQ_TOTAL/8]; -static GLuint r_occlusionQueries[MAX_OQ_TOTAL]; - -static meshbuffer_t r_occluderMB; -static ref_shader_t *r_occlusionShader; -static qboolean r_occludersQueued; -static ref_entity_t *r_occlusionEntity; - -static void R_RenderOccludingSurfaces( void ); - -/* -=============== -R_InitOcclusionQueries -=============== -*/ -void R_InitOcclusionQueries( void ) -{ - meshbuffer_t *meshbuf = &r_occluderMB; - - if( !r_occlusionShader ) - r_occlusionShader = R_LoadShader( "***r_occlusion***", SHADER_OPAQUE_OCCLUDER, false, 0, SHADER_INVALID ); - - if( !GL_Support( R_OCCLUSION_QUERIES_EXT )) - return; - - pglGenQueriesARB( MAX_OQ_TOTAL, r_occlusionQueries ); - - meshbuf->sortkey = MB_ENTITY2NUM( r_worldent ) | MB_MODEL; - meshbuf->shaderkey = r_occlusionShader->sortkey; -} - -/* -=============== -R_BeginOcclusionPass -=============== -*/ -void R_BeginOcclusionPass( void ) -{ - ASSERT( OCCLUSION_QUERIES_ENABLED( RI )); - - r_occludersQueued = false; - r_occlusionEntity = r_worldent; - memset( r_queriesBits, 0, sizeof( r_queriesBits ) ); - - R_LoadIdentity(); - - R_BackendResetPassMask(); - - R_ClearSurfOcclusionQueryKeys(); - - pglShadeModel( GL_FLAT ); - pglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); - pglDisable( GL_TEXTURE_2D ); -} - -/* -=============== -R_EndOcclusionPass -=============== -*/ -void R_EndOcclusionPass( void ) -{ - ASSERT( OCCLUSION_QUERIES_ENABLED( RI )); - - R_RenderOccludingSurfaces(); - - R_SurfIssueOcclusionQueries(); - - R_BackendResetPassMask(); - - R_BackendResetCounters(); - - if( r_occlusion_queries_finish->integer ) - pglFinish(); - else - pglFlush(); - - pglShadeModel( GL_SMOOTH ); - pglEnable( GL_TEXTURE_2D ); - pglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); -} - -/* -=============== -R_RenderOccludingSurfaces -=============== -*/ -static void R_RenderOccludingSurfaces( void ) -{ - if( !r_occludersQueued ) - return; - - r_occludersQueued = false; - R_RotateForEntity( r_occlusionEntity ); - R_BackendResetPassMask(); - R_RenderMeshBuffer( &r_occluderMB ); -} - -/* -=============== -R_OcclusionShader -=============== -*/ -ref_shader_t *R_OcclusionShader( void ) -{ - return r_occlusionShader; -} - -/* -=============== -R_AddOccludingSurface -=============== -*/ -void R_AddOccludingSurface( msurface_t *surf, ref_shader_t *shader ) -{ - int diff = shader->flags ^ r_occlusionShader->flags; - - if( R_MeshOverflow( surf->mesh ) || ( diff & ( SHADER_CULL_FRONT|SHADER_CULL_BACK ) ) || r_occlusionEntity != RI.currententity ) - { - R_RenderOccludingSurfaces(); - - r_occlusionShader->flags ^= diff; - r_occlusionEntity = RI.currententity; - } - r_occludersQueued = true; - - R_PushMesh( surf->mesh, 0 ); -} - -/* -=============== -R_GetOcclusionQueryNum -=============== -*/ -int R_GetOcclusionQueryNum( int type, int key ) -{ - switch( type ) - { - case OQ_ENTITY: - return ( r_occlusion_queries->integer & 1 ) ? BEGIN_OQ_ENTITIES + ( key%MAX_OQ_ENTITIES ) : -1; - case OQ_PLANARSHADOW: - return ( r_occlusion_queries->integer & 1 ) ? BEGIN_OQ_PLANARSHADOWS + ( key%MAX_OQ_PLANARSHADOWS ) : -1; - case OQ_SHADOWGROUP: - return ( r_occlusion_queries->integer & 2 ) ? BEGIN_OQ_SHADOWGROUPS + ( key%MAX_OQ_SHADOWGROUPS ) : -1; - case OQ_CUSTOM: - return BEGIN_OQ_CUSTOM + ( key%MAX_OQ_CUSTOM ); - } - - return -1; -} - -/* -=============== -R_IssueOcclusionQuery -=============== -*/ -int R_IssueOcclusionQuery( int query, ref_entity_t *e, vec3_t mins, vec3_t maxs ) -{ - vec3_t bbox[8]; - static vec4_t verts[8]; - static mesh_t mesh; - static elem_t indices[] = - { - 0, 1, 2, 1, 2, 3, // top - 7, 5, 6, 5, 6, 4, // bottom - 4, 0, 6, 0, 6, 2, // front - 3, 7, 1, 7, 1, 5, // back - 0, 1, 4, 1, 4, 5, // left - 7, 6, 3, 6, 3, 2, // right - }; - - int i; - - if( query < 0 ) return -1; - - if( r_queriesBits[query>>3] & ( 1<<( query & 7 ))) - return -1; - - r_queriesBits[query>>3] |= ( 1<<( query & 7 )); - - R_RenderOccludingSurfaces(); - - mesh.numVerts = 8; - mesh.vertexArray = verts; - mesh.numElems = 36; - mesh.elems = indices; - r_occlusionShader->flags &= ~( SHADER_CULL_BACK|SHADER_CULL_FRONT ); - - pglBeginQueryARB( GL_SAMPLES_PASSED_ARB, r_occlusionQueries[query] ); - - R_TransformEntityBBox( e, mins, maxs, bbox, false ); - - for( i = 0; i < 8; i++ ) - Vector4Set( verts[i], bbox[i][0], bbox[i][1], bbox[i][2], 1.0f ); - - R_RotateForEntity( e ); - R_BackendSetPassMask( GLSTATE_MASK & ~GLSTATE_DEPTHWRITE ); - R_PushMesh( &mesh, MF_NONBATCHED|MF_NOCULL ); - R_RenderMeshBuffer( &r_occluderMB ); - - pglEndQueryARB( GL_SAMPLES_PASSED_ARB ); - - return query; -} - -/* -=============== -R_OcclusionQueryIssued -=============== -*/ -qboolean R_OcclusionQueryIssued( int query ) -{ - ASSERT( query >= 0 && query < MAX_OQ_TOTAL ); - - return r_queriesBits[query>>3] & ( 1<<( query & 7 )); -} - -/* -=============== -R_GetOcclusionQueryResult -=============== -*/ -unsigned int R_GetOcclusionQueryResult( int query, qboolean wait ) -{ - GLint available; - GLuint sampleCount; - - if( query < 0 ) - return 1; - if( !R_OcclusionQueryIssued( query ) ) - return 1; - - query = r_occlusionQueries[query]; - - pglGetQueryObjectivARB( query, GL_QUERY_RESULT_AVAILABLE_ARB, &available ); - if( !available && wait ) - { - int n = 0; - do - { - n++; - pglGetQueryObjectivARB( query, GL_QUERY_RESULT_AVAILABLE_ARB, &available ); - } while( !available && ( n < 10000 ) ); - } - - if( !available ) - return 0; - - pglGetQueryObjectuivARB( query, GL_QUERY_RESULT_ARB, &sampleCount ); - - return sampleCount; -} - -/* -=============== -R_GetOcclusionQueryResultBool -=============== -*/ -qboolean R_GetOcclusionQueryResultBool( int type, int key, qboolean wait ) -{ - int query = R_GetOcclusionQueryNum( type, key ); - - if( query >= 0 && R_OcclusionQueryIssued( query ) ) - { - if( R_GetOcclusionQueryResult( query, wait ) ) - return true; - return false; - } - - return true; -} - -/* -=============== -R_ShutdownOcclusionQueries -=============== -*/ -void R_ShutdownOcclusionQueries( void ) -{ - r_occlusionShader = NULL; - - if( !GL_Support( R_OCCLUSION_QUERIES_EXT )) - return; - - pglDeleteQueriesARB( MAX_OQ_TOTAL, r_occlusionQueries ); - r_occludersQueued = false; -} diff --git a/vid_gl/r_decals.c b/vid_gl/r_decals.c deleted file mode 100644 index 4341fd1e..00000000 --- a/vid_gl/r_decals.c +++ /dev/null @@ -1,1279 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2010 -// r_decals.c - render decals on brushmodels -//======================================================================= - -#include "r_local.h" -#include "mathlib.h" -#include "matrix_lib.h" -#include "cl_entity.h" -#include "bspfile.h" -#include "const.h" - -#define DECAL_DISTANCE 4 // too big values produce more clipped polygons -#define MAX_DECALCLIPVERT 32 // produced vertexes of fragmented decal -#define DECAL_CACHEENTRY 256 // MUST BE POWER OF 2 or code below needs to change! - -// empirically determined constants for minimizing overalpping decals -#define MAX_OVERLAP_DECALS 4 -#define DECAL_OVERLAP_DIST 8 - -typedef struct -{ - vec3_t m_vPos; - vec2_t m_tCoords; // these are the texcoords for the decal itself - vec2_t m_LMCoords; // lightmap texcoords for the decal. -} decalvert_t; - -// FIXME: move this out to the r_math.c ? -typedef struct -{ - qboolean (*pfnInside)( decalvert_t *pVert ); - float (*pfnClip)( decalvert_t *one, decalvert_t *two ); -} decal_clip_t; - -static qboolean Top_Inside( decalvert_t *pVert ){ return pVert->m_tCoords[1] < 1.0f; } -static float Top_Clip( decalvert_t *one, decalvert_t *two ){ return ( 1.0f - one->m_tCoords[1] ) / ( two->m_tCoords[1] - one->m_tCoords[1] ); } -static qboolean Left_Inside( decalvert_t *pVert ){ return pVert->m_tCoords[0] > 0.0f; } -static float Left_Clip( decalvert_t *one, decalvert_t *two ){ return one->m_tCoords[0] / ( one->m_tCoords[0] - two->m_tCoords[0] ); } -static qboolean Right_Inside( decalvert_t *pVert ){ return pVert->m_tCoords[0] < 1.0f; } -static float Right_Clip( decalvert_t *one, decalvert_t *two ){ return ( 1.0f - one->m_tCoords[0] ) / ( two->m_tCoords[0] - one->m_tCoords[0] ); } -static qboolean Bottom_Inside( decalvert_t *pVert ){ return pVert->m_tCoords[1] > 0.0f; } -static float Bottom_Clip( decalvert_t *one, decalvert_t *two ){ return one->m_tCoords[1] / ( one->m_tCoords[1] - two->m_tCoords[1] ); } - -// clippanes -static decal_clip_t PlaneTop = { Top_Inside, Top_Clip }; -static decal_clip_t PlaneLeft = { Left_Inside, Left_Clip }; -static decal_clip_t PlaneRight = { Right_Inside, Right_Clip }; -static decal_clip_t PlaneBottom = { Bottom_Inside, Bottom_Clip }; - -static void Intersect( decal_clip_t clipFunc, decalvert_t *one, decalvert_t *two, decalvert_t *out ) -{ - float t = clipFunc.pfnClip( one, two ); - - VectorLerp( one->m_vPos, t, two->m_vPos, out->m_vPos ); - Vector2Lerp( one->m_LMCoords, t, two->m_LMCoords, out->m_LMCoords ); - Vector2Lerp( one->m_tCoords, t, two->m_tCoords, out->m_tCoords ); -} - -// This structure contains the information used to create new decals -typedef struct -{ - vec3_t m_Position; // world coordinates of the decal center - vec3_t m_BasePosition; // untransformed world pos for right serialize - vec3_t m_SAxis; // the s axis for the decal in world coordinates - ref_model_t* m_pModel; // the model the decal is going to be applied in - ref_shader_t *m_pShader; // The decal material - int m_Size; // Size of the decal (in world coords) - int m_Flags; - int m_Entity; // Entity the decal is applied to. - float m_scale; - float m_flFadeTime; - float m_flFadeDuration; - int m_decalWidth; - int m_decalHeight; - rgba_t m_Color; - vec3_t m_Basis[3]; -} decalinfo_t; - -static decalvert_t g_DecalClipVerts[MAX_DECALCLIPVERT]; -static decalvert_t g_DecalClipVerts2[MAX_DECALCLIPVERT]; -static byte *r_decalPool; // pool of decal meshes - -static decal_t gDecalPool[MAX_RENDER_DECALS]; -static int gDecalCount; - -void R_ClearDecals( void ) -{ - Mem_EmptyPool( r_decalPool ); - Mem_Set( gDecalPool, 0, sizeof( gDecalPool )); - gDecalCount = 0; -} - -// Init the decal pool -void R_InitDecals( void ) -{ - r_decalPool = Mem_AllocPool( "Decals Mesh Pool" ); - R_ClearDecals (); -} - -void R_ShutdownDecals( void ) -{ - Mem_FreePool( &r_decalPool ); -} - -// unlink pdecal from any surface it's attached to -static void R_DecalUnlink( decal_t *pdecal ) -{ - decal_t *tmp; - - if( pdecal->psurf ) - { - if( pdecal->psurf->pdecals == pdecal ) - { - pdecal->psurf->pdecals = pdecal->pnext; - } - else - { - tmp = pdecal->psurf->pdecals; - if( !tmp ) Host_Error( "D_DecalUnlink: bad decal list\n" ); - - while( tmp->pnext ) - { - if( tmp->pnext == pdecal ) - { - tmp->pnext = pdecal->pnext; - break; - } - tmp = tmp->pnext; - } - } - } - - if( pdecal->mesh ) - Mem_Free( pdecal->mesh ); - - pdecal->psurf = NULL; - pdecal->mesh = NULL; -} - - -// Just reuse next decal in list -// A decal that spans multiple surfaces will use multiple decal_t pool entries, as each surface needs -// it's own. -static decal_t *R_DecalAlloc( decal_t *pdecal ) -{ - int limit = MAX_RENDER_DECALS; - - if( r_decals->integer < limit ) - limit = r_decals->integer; - - if( !limit ) return NULL; - - if( !pdecal ) - { - int count = 0; - - // check for the odd possiblity of infinte loop - do - { - gDecalCount++; - if( gDecalCount >= limit ) - gDecalCount = 0; - pdecal = gDecalPool + gDecalCount; // reuse next decal - count++; - } while(( pdecal->flags & FDECAL_PERMANENT ) && count < limit ); - } - - // If decal is already linked to a surface, unlink it. - R_DecalUnlink( pdecal ); - - return pdecal; -} - -//----------------------------------------------------------------------------- -// find decal image and grab size from it -//----------------------------------------------------------------------------- -static void R_GetDecalDimensions( ref_shader_t *shader, int *width, int *height ) -{ - ref_stage_t *pass; - int i; - - if( !shader ) return; - - for( i = 0; i < shader->num_stages; i++ ) - { - pass = &shader->stages[i]; - if( pass->flags & SHADERSTAGE_LIGHTMAP ) - continue; // skip lightmap - if( pass->num_textures ) - { - if( width ) *width = pass->textures[0]->srcWidth; - if( height ) *height = pass->textures[0]->srcHeight; - return; - } - } - - // nothing found ? - if( width ) *width = 1; // to avoid divide by zero - if( height ) *height = 1; -} - -//----------------------------------------------------------------------------- -// compute the decal basis based on surface normal, and preferred saxis -//----------------------------------------------------------------------------- -void R_DecalComputeBasis( msurface_t *surf, vec3_t pSAxis, vec3_t textureSpaceBasis[3] ) -{ - vec3_t surfaceNormal; - - // setup normal - if( surf->flags & SURF_PLANEBACK ) - VectorNegate( surf->plane->normal, surfaceNormal ); - else VectorCopy( surf->plane->normal, surfaceNormal ); - - if( pSAxis ) - { - // T = S cross N - CrossProduct( pSAxis, textureSpaceBasis[2], textureSpaceBasis[1] ); - - // Name sure they aren't parallel or antiparallel - // In that case, fall back to the normal algorithm. - if( DotProduct( textureSpaceBasis[1], textureSpaceBasis[1] ) > 1e-6 ) - { - // S = N cross T - CrossProduct( textureSpaceBasis[2], textureSpaceBasis[1], textureSpaceBasis[0] ); - - VectorNormalizeFast( textureSpaceBasis[0] ); - VectorNormalizeFast( textureSpaceBasis[1] ); - return; - } - // Fall through to the standard algorithm for parallel or antiparallel - } - - // original Half-Life algorithm: get textureBasis from linked surface - VectorCopy( surf->texinfo->vecs[0], textureSpaceBasis[0] ); - VectorCopy( surf->texinfo->vecs[1], textureSpaceBasis[1] ); - VectorCopy( surfaceNormal, textureSpaceBasis[2] ); - - VectorNormalizeFast( textureSpaceBasis[0] ); - VectorNormalizeFast( textureSpaceBasis[1] ); -} - -void R_SetupDecalTextureSpaceBasis( decal_t *pDecal, msurface_t *surf, ref_shader_t *pShader, vec3_t textureSpaceBasis[3], float decalWorldScale[2] ) -{ - float *sAxis = NULL; - int width, height; - - if( pDecal->flags & FDECAL_USESAXIS ) - sAxis = pDecal->saxis; - - // Compute the non-scaled decal basis - R_DecalComputeBasis( surf, sAxis, textureSpaceBasis ); - R_GetDecalDimensions( pShader, &width, &height ); - - // world width of decal = ptexture->width / pDecal->scale - // world height of decal = ptexture->height / pDecal->scale - // scale is inverse, scales world space to decal u/v space [0,1] - // OPTIMIZE: Get rid of these divides - decalWorldScale[0] = pDecal->scale / width; - decalWorldScale[1] = pDecal->scale / height; - - VectorScale( textureSpaceBasis[0], decalWorldScale[0], textureSpaceBasis[0] ); - VectorScale( textureSpaceBasis[1], decalWorldScale[1], textureSpaceBasis[1] ); -} - -// Build the initial list of vertices from the surface verts into the global array, 'verts'. -void R_SetupDecalVertsForMSurface( decal_t *pDecal, msurface_t *surf, vec3_t textureSpaceBasis[3], decalvert_t *pVerts ) -{ - int j; - - for( j = 0; j < surf->mesh->numVerts; j++ ) - { - VectorCopy( surf->mesh->vertexArray[j], pVerts[j].m_vPos ); // copy model space coordinates - pVerts[j].m_tCoords[0] = DotProduct( pVerts[j].m_vPos, textureSpaceBasis[0] ) - pDecal->dx + 0.5f; - pVerts[j].m_tCoords[1] = DotProduct( pVerts[j].m_vPos, textureSpaceBasis[1] ) - pDecal->dy + 0.5f; - pVerts[j].m_LMCoords[0] = pVerts[j].m_LMCoords[1] = 0.0f; - } -} - -// Figure out where the decal maps onto the surface. -void R_SetupDecalClip( decalvert_t *pOutVerts, decal_t *pDecal, msurface_t *surf, ref_shader_t *pMaterial, vec3_t textureSpaceBasis[3], float decalWorldScale[2] ) -{ -// if ( pOutVerts == NULL ) -// pOutVerts = &g_DecalClipVerts[0]; - - R_SetupDecalTextureSpaceBasis( pDecal, surf, pMaterial, textureSpaceBasis, decalWorldScale ); - - // Generate texture coordinates for each vertex in decal s,t space - // probably should pre-generate this, store it and use it for decal-decal collisions - // as in R_DecalsIntersect() - pDecal->dx = DotProduct( pDecal->position, textureSpaceBasis[0] ); - pDecal->dy = DotProduct( pDecal->position, textureSpaceBasis[1] ); -} - -static int SHClip( decalvert_t *g_DecalClipVerts, int vertCount, decalvert_t *out, decal_clip_t clipFunc ) -{ - int j, outCount; - decalvert_t *s, *p; - - outCount = 0; - - s = &g_DecalClipVerts[vertCount - 1]; - - for( j = 0; j < vertCount; j++ ) - { - p = &g_DecalClipVerts[j]; - - if( clipFunc.pfnInside( p )) - { - if( clipFunc.pfnInside( s )) - { - Mem_Copy( out, p, sizeof( *out )); - outCount++; - out++; - } - else - { - Intersect( clipFunc, s, p, out ); - out++; - outCount++; - - Mem_Copy( out, p, sizeof( *out )); - outCount++; - out++; - } - } - else - { - if( clipFunc.pfnInside( s )) - { - Intersect( clipFunc, p, s, out ); - out++; - outCount++; - } - } - s = p; - } - return outCount; -} - -decalvert_t *R_DoDecalSHClip( decalvert_t *pInVerts, decalvert_t *pOutVerts, decal_t *pDecal, int nStartVerts, int *pVertCount ) -{ - int outCount; - - if( pOutVerts == NULL ) - pOutVerts = &g_DecalClipVerts[0]; - - // clip the polygon to the decal texture space - outCount = SHClip( pInVerts, nStartVerts, &g_DecalClipVerts2[0], PlaneTop ); - outCount = SHClip( &g_DecalClipVerts2[0], outCount, &g_DecalClipVerts[0], PlaneLeft ); - outCount = SHClip( &g_DecalClipVerts[0], outCount, &g_DecalClipVerts2[0], PlaneRight ); - outCount = SHClip( &g_DecalClipVerts2[0], outCount, pOutVerts, PlaneBottom ); - - if( outCount ) - { - if( pDecal->flags & FDECAL_CLIPTEST ) - { - pDecal->flags &= ~FDECAL_CLIPTEST; // we're doing the test - - // If there are exactly 4 verts and they are all 0,1 tex coords, then we've got an unclipped decal - // A more precise test would be to calculate the texture area and make sure it's one, but this - // should work as well. - if( outCount == 4 ) - { - int j, clipped = 0; - decalvert_t *v = pOutVerts; - - for( j = 0; j < outCount && !clipped; j++, v++ ) - { - float s, t; - s = v->m_tCoords[0]; - t = v->m_tCoords[1]; - - if (( s != 0.0f && s != 1.0f ) || ( t != 0.0f && t != 1.0f )) - clipped = 1; - } - - // We didn't need to clip this decal, it's a quad covering - // the full texture space, optimize subsequent frames. - if( !clipped ) pDecal->flags |= FDECAL_NOCLIP; - } - } - } - - *pVertCount = outCount; - return pOutVerts; -} - -//----------------------------------------------------------------------------- -// Generate clipped vertex list for decal pdecal projected onto polygon psurf -//----------------------------------------------------------------------------- -decalvert_t *R_DecalVertsClip( decalvert_t *pOutVerts, decal_t *pDecal, msurface_t *surf, ref_shader_t *pShader, int *pVertCount ) -{ - float decalWorldScale[2]; - vec3_t textureSpaceBasis[3]; - - // figure out where the decal maps onto the surface. - R_SetupDecalClip( pOutVerts, pDecal, surf, pShader, textureSpaceBasis, decalWorldScale ); - - // build the initial list of vertices from the surface verts. - R_SetupDecalVertsForMSurface( pDecal, surf, textureSpaceBasis, g_DecalClipVerts ); - - return R_DoDecalSHClip( g_DecalClipVerts, pOutVerts, pDecal, surf->mesh->numVerts, pVertCount ); -} - -// Generate lighting coordinates at each vertex for decal vertices v[] on surface psurf -static void R_DecalVertsLight( decalvert_t *v, msurface_t *surf, int vertCount ) -{ - float s, t; - mtexinfo_t *tex; - int j; - - tex = surf->texinfo; - - for ( j = 0; j < vertCount; j++, v++ ) - { - // lightmap texture coordinates - s = DotProduct( v->m_vPos, tex->vecs[0] ) + tex->vecs[0][3] - surf->textureMins[0]; - s += surf->lmS * LM_SAMPLE_SIZE; - s += LM_SAMPLE_SIZE >> 1; - s /= LIGHTMAP_TEXTURE_WIDTH * LM_SAMPLE_SIZE; - - t = DotProduct( v->m_vPos, tex->vecs[1] ) + tex->vecs[1][3] - surf->textureMins[1]; - t += surf->lmT * LM_SAMPLE_SIZE; - t += LM_SAMPLE_SIZE >> 1; - t /= LIGHTMAP_TEXTURE_HEIGHT * LM_SAMPLE_SIZE; - - v->m_LMCoords[0] = s; - v->m_LMCoords[1] = t; - } -} - -static decalvert_t* R_DecalVertsNoclip( decal_t *pdecal, msurface_t *surf, ref_shader_t *pShader ) -{ - decalvert_t *vlist; - int outCount; - - // use the old code for now, and just cache them - vlist = R_DecalVertsClip( NULL, pdecal, surf, pShader, &outCount ); - - R_DecalVertsLight( vlist, surf, 4 ); - - return vlist; -} - -//----------------------------------------------------------------------------- -// Purpose: Check for intersecting decals on this surface -// Input : *psurf - -// *pcount - -// x - -// y - -// Output : static decal_t -//----------------------------------------------------------------------------- -// UNDONE: This probably doesn't work quite right any more -// we should base overlap on the new decal basis matrix -// decal basis is constant per plane, perhaps we should store it (unscaled) in the shared plane struct -// BRJ: Note, decal basis is not constant when decals need to specify an s direction -// but that certainly isn't the majority case -static decal_t *R_DecalIntersect( decalinfo_t *decalinfo, msurface_t *surf, int *pcount ) -{ - ref_shader_t *pShader; - decal_t *plast, *pDecal; - vec3_t decalExtents[2]; - float lastArea = 2; - int mapSize[2]; - - plast = NULL; - *pcount = 0; - - // (Same as R_SetupDecalClip). - pShader = decalinfo->m_pShader; - - // precalculate the extents of decalinfo's decal in world space. - R_GetDecalDimensions( pShader, &mapSize[0], &mapSize[1] ); - VectorScale( decalinfo->m_Basis[0], ((mapSize[0] / decalinfo->m_scale) * 0.5f), decalExtents[0] ); - VectorScale( decalinfo->m_Basis[1], ((mapSize[1] / decalinfo->m_scale) * 0.5f), decalExtents[1] ); - - pDecal = surf->pdecals; - - while( pDecal ) - { - pShader = pDecal->shader; - - // Don't steal bigger decals and replace them with smaller decals - // Don't steal permanent decals - if(!( pDecal->flags & FDECAL_PERMANENT )) - { - vec3_t testBasis[3]; - vec3_t testPosition[2]; - float testWorldScale[2]; - vec2_t vDecalMin, vDecalMax; - vec2_t vUnionMin, vUnionMax; - - R_SetupDecalTextureSpaceBasis( pDecal, surf, pShader, testBasis, testWorldScale ); - - VectorSubtract( decalinfo->m_Position, decalExtents[0], testPosition[0] ); - VectorSubtract( decalinfo->m_Position, decalExtents[1], testPosition[1] ); - - // Here, we project the min and max extents of the decal that got passed in into - // this decal's (pDecal's) [0,0,1,1] clip space, just like we would if we were - // clipping a triangle into pDecal's clip space. - Vector2Set( vDecalMin, DotProduct( testPosition[0], testBasis[0] ) - pDecal->dx + 0.5f, - DotProduct( testPosition[1], testBasis[1] ) - pDecal->dy + 0.5f ); - - VectorAdd( decalinfo->m_Position, decalExtents[0], testPosition[0] ); - VectorAdd( decalinfo->m_Position, decalExtents[1], testPosition[1] ); - - Vector2Set( vDecalMax, - DotProduct( testPosition[0], testBasis[0] ) - pDecal->dx + 0.5f, - DotProduct( testPosition[1], testBasis[1] ) - pDecal->dy + 0.5f ); - - // Now figure out the part of the projection that intersects pDecal's - // clip box [0,0,1,1]. - Vector2Set( vUnionMin, max( vDecalMin[0], 0 ), max( vDecalMin[1], 0 )); - Vector2Set( vUnionMax, min( vDecalMax[0], 1 ), min( vDecalMax[1], 1 )); - - if( vUnionMin[0] < 1 && vUnionMin[1] < 1 && vUnionMax[0] > 0 && vUnionMax[1] > 0 ) - { - // Figure out how much of this intersects the (0,0) - (1,1) bbox. - float flArea = (vUnionMax[0] - vUnionMin[1]) * (vUnionMax[1] - vUnionMin[1]); - - if( flArea > 0.6f ) - { - *pcount += 1; - - if( !plast || flArea <= lastArea ) - { - plast = pDecal; - lastArea = flArea; - } - } - } - } - pDecal = pDecal->pnext; - } - return plast; -} - -// Add the decal to the surface's list of decals. -static void R_AddDecalToSurface( decal_t *pdecal, msurface_t *surf, decalinfo_t *decalinfo ) -{ - decal_t *pold; - - pdecal->pnext = NULL; - pold = surf->pdecals; - - if( pold ) - { - while( pold->pnext ) - pold = pold->pnext; - pold->pnext = pdecal; - } - else - { - surf->pdecals = pdecal; - } - - // tag surface - pdecal->psurf = surf; - - // at this point decal are linked with surface - // and will be culled, drawing and sorting - // together with surface -} - -static void R_DecalCreate( decalinfo_t *decalinfo, msurface_t *surf, float x, float y ) -{ - decal_t *pdecal, *pold; - int count, vertCount; - - if( !surf ) - { - MsgDev( D_ERROR, "psurface NULL in R_DecalCreate!\n" ); - return; - } - - pold = R_DecalIntersect( decalinfo, surf, &count ); - if( count < MAX_OVERLAP_DECALS ) pold = NULL; - - pdecal = R_DecalAlloc( pold ); - pdecal->flags = decalinfo->m_Flags; - - Vector4Copy( decalinfo->m_Color, pdecal->color ); - VectorCopy( decalinfo->m_Position, pdecal->position ); - VectorCopy( decalinfo->m_BasePosition, pdecal->worldPos ); - - if( pdecal->flags & FDECAL_USESAXIS ) - VectorCopy( decalinfo->m_SAxis, pdecal->saxis ); - - pdecal->dx = x; - pdecal->dy = y; - pdecal->shader = decalinfo->m_pShader; - ASSERT( pdecal->shader ); - - // set scaling - pdecal->scale = decalinfo->m_scale; - pdecal->entityIndex = decalinfo->m_Entity; - pdecal->fadeStartTime = RI.refdef.time; - - // Get dynamic information from the material (fade start, fade time) - if( decalinfo->m_flFadeDuration != 0.0f ) - { - pdecal->flags |= FDECAL_DYNAMIC; - pdecal->fadeDuration = decalinfo->m_flFadeDuration; - pdecal->fadeStartTime += decalinfo->m_flFadeTime; - } - else if( decalinfo->m_Flags & FDECAL_ANIMATED ) - { - pdecal->currentFrame = 0.0f; - } - - // check to see if the decal actually intersects the surface - // if not, then remove the decal - R_DecalVertsClip( NULL, pdecal, surf, decalinfo->m_pShader, &vertCount ); - - if( !vertCount ) - { - R_DecalUnlink( pdecal ); - return; - } - - // add to the surface's list - R_AddDecalToSurface( pdecal, surf, decalinfo ); -} - -void R_DecalSurface( msurface_t *surf, decalinfo_t *decalinfo ) -{ - // get the texture associated with this surface - mtexinfo_t *tex = surf->texinfo; - vec4_t textureU, textureV; - float *sAxis = NULL; - float s, t, w, h; - - Vector4Copy( tex->vecs[0], textureU ); - Vector4Copy( tex->vecs[1], textureV ); - - // project decal center into the texture space of the surface - s = DotProduct( decalinfo->m_Position, textureU ) + textureU[3] - surf->textureMins[0]; - t = DotProduct( decalinfo->m_Position, textureV ) + textureV[3] - surf->textureMins[1]; - - // Determine the decal basis (measured in world space) - // Note that the decal basis vectors 0 and 1 will always lie in the same - // plane as the texture space basis vectorstextureVecsTexelsPerWorldUnits. - - if( decalinfo->m_Flags & FDECAL_USESAXIS ) - sAxis = decalinfo->m_SAxis; - - R_DecalComputeBasis( surf, sAxis, decalinfo->m_Basis ); - - // Compute an effective width and height (axis aligned) in the parent texture space - // How does this work? decalBasis[0] represents the u-direction (width) - // of the decal measured in world space, decalBasis[1] represents the - // v-direction (height) measured in world space. - // textureVecsTexelsPerWorldUnits[0] represents the u direction of - // the surface's texture space measured in world space (with the appropriate - // scale factor folded in), and textureVecsTexelsPerWorldUnits[1] - // represents the texture space v direction. We want to find the dimensions (w,h) - // of a square measured in texture space, axis aligned to that coordinate system. - // All we need to do is to find the components of the decal edge vectors - // (decalWidth * decalBasis[0], decalHeight * decalBasis[1]) - // in texture coordinates: - - w = fabs( decalinfo->m_decalWidth * DotProduct( textureU, decalinfo->m_Basis[0] )) + - fabs( decalinfo->m_decalHeight * DotProduct( textureU, decalinfo->m_Basis[1] )); - - h = fabs( decalinfo->m_decalWidth * DotProduct( textureV, decalinfo->m_Basis[0] )) + - fabs( decalinfo->m_decalHeight * DotProduct( textureV, decalinfo->m_Basis[1] )); - - // move s,t to upper left corner - s -= ( w * 0.5f ); - t -= ( h * 0.5f ); - - // Is this rect within the surface? -- tex width & height are unsigned - if( s <= -w || t <= -h || s > (surf->extents[0] + w) || t > (surf->extents[1] + h)) - { - return; // nope - } - - // stamp it - R_DecalCreate( decalinfo, surf, s, t ); -} - -//----------------------------------------------------------------------------- -// iterate over all surfaces on a node, looking for surfaces to decal -//----------------------------------------------------------------------------- -static void R_DecalNodeSurfaces( mnode_t* node, decalinfo_t *decalinfo ) -{ - // iterate over all surfaces in the node - msurface_t *surf; - int i; - - for( i = 0, surf = node->firstface; i < node->numfaces; i++, surf++ ) - { - // never apply decals on the water or sky surfaces - if( surf->flags & (SURF_DRAWTURB|SURF_DRAWSKY)) - continue; - - R_DecalSurface( surf, decalinfo ); - } -} - -//----------------------------------------------------------------------------- -// Recursive routine to find surface to apply a decal to. World coordinates of -// the decal are passed in r_recalpos like the rest of the engine. This should -// be called through R_DecalShoot() -//----------------------------------------------------------------------------- -static void R_DecalNode( mnode_t *node, decalinfo_t *decalinfo ) -{ - mplane_t *splitplane; - float dist; - - ASSERT( node ); - - if( !node->plane ) - { - // hit a leaf - return; - } - - splitplane = node->plane; - dist = DotProduct( decalinfo->m_Position, splitplane->normal ) - splitplane->dist; - - // This is arbitrarily set to 10 right now. In an ideal world we'd have the - // exact surface but we don't so, this tells me which planes are "sort of - // close" to the gunshot -- the gunshot is actually 4 units in front of the - // wall (see dlls\weapons.cpp). We also need to check to see if the decal - // actually intersects the texture space of the surface, as this method tags - // parallel surfaces in the same node always. - // JAY: This still tags faces that aren't correct at edges because we don't - // have a surface normal - if( dist > decalinfo->m_Size ) - { - R_DecalNode( node->children[0], decalinfo ); - } - else if( dist < -decalinfo->m_Size ) - { - R_DecalNode( node->children[1], decalinfo ); - } - else - { - if( dist < DECAL_DISTANCE && dist > -DECAL_DISTANCE ) - R_DecalNodeSurfaces( node, decalinfo ); - - R_DecalNode( node->children[0], decalinfo ); - R_DecalNode( node->children[1], decalinfo ); - } -} - -// Shoots a decal onto the surface of the BSP. position is the center of the decal in world coords -static void R_DecalShoot_( ref_shader_t *shader, int entity, ref_model_t *model, vec3_t pos, vec3_t saxis, int flags, rgba_t color, float fadeTime, float fadeDuration ) -{ - decalinfo_t decalInfo; - mbrushmodel_t *bmodel; - mnode_t *pnodes; - int i, width, height; - - if( !shader || shader->type != SHADER_DECAL ) - { - MsgDev( D_ERROR, "Decals has invalid shader!\n" ); - return; - } - - if( !model || ( model->type != mod_brush && model->type != mod_world )) - { - MsgDev( D_ERROR, "Decals must hit mod_brush or mod_world!\n" ); - return; - } - - decalInfo.m_pModel = model; - - VectorCopy( pos, decalInfo.m_BasePosition ); - - if( model->type == mod_brush ) - { - cl_entity_t *ent = ri.GetClientEdict( entity ); - vec3_t pos_l; - - if( ent ) - { - // transform decal position in local bmodel space - if( !VectorIsNull( ent->angles )) - { - matrix4x4 matrix, imatrix; - float *org = ent->origin; - float *ang = ent->angles; - - Matrix4x4_CreateFromEntity( matrix, org[0], org[1], org[2], ang[PITCH], ang[YAW], ang[ROLL], 1.0f ); - Matrix4x4_Invert_Simple( imatrix, matrix ); - - Matrix4x4_VectorTransform( imatrix, pos, pos_l ); - } - else - { - VectorSubtract( pos, ent->origin, pos_l ); - } - VectorCopy( pos_l, decalInfo.m_Position ); - } - else - { - // give untransformed pos - VectorCopy( pos, decalInfo.m_Position ); - } - } - else - { - // pass position in global - VectorCopy( pos, decalInfo.m_Position ); - } - - // deal with the s axis if one was passed in - if( saxis ) - { - flags |= FDECAL_USESAXIS; - VectorCopy( saxis, decalInfo.m_SAxis ); - } - - // check for animated decal - for( i = 0; i < shader->num_stages; i++ ) - { - if( shader->stages[i].flags & ( SHADERSTAGE_ANIMFREQUENCY|SHADERSTAGE_FRAMES )) - { - flags |= FDECAL_ANIMATED; - break; - } - } - - // more state used by R_DecalNode() - decalInfo.m_pShader = shader; - - decalInfo.m_flFadeTime = fadeTime; - decalInfo.m_flFadeDuration = fadeDuration; - - // don't optimize custom decals - if(!( flags & FDECAL_CUSTOM )) - flags |= FDECAL_CLIPTEST; - - decalInfo.m_Flags = flags; - decalInfo.m_Entity = entity; - - R_GetDecalDimensions( shader, &width, &height ); - decalInfo.m_Size = width >> 1; - if(( height >> 1 ) > decalInfo.m_Size ) - decalInfo.m_Size = height >> 1; - - // FIXME: grab scale from shader ? - decalInfo.m_scale = 1.0f; - - // compute the decal dimensions in world space - decalInfo.m_decalWidth = width / decalInfo.m_scale; - decalInfo.m_decalHeight = height / decalInfo.m_scale; - if( color ) Vector4Copy( color, decalInfo.m_Color ); - - bmodel = (mbrushmodel_t *)decalInfo.m_pModel->extradata; - pnodes = bmodel->firstmodelnode; - - R_DecalNode( pnodes, &decalInfo ); -} - -qboolean R_DecalShoot( shader_t texture, int entityIndex, int modelIndex, vec3_t pos, vec3_t saxis, int flags, rgba_t color, float fadeTime, float fadeDuration ) -{ - ref_shader_t *shader; - ref_model_t *model; - - // setup shader - if( texture < 0 || texture >= MAX_SHADERS || !( shader = &r_shaders[texture] )) - return false; - - // setup model - if( modelIndex <= 0 || modelIndex >= MAX_MODELS ) - model = r_worldmodel; - else model = cl_models[modelIndex]; - - R_DecalShoot_( shader, entityIndex, model, pos, saxis, flags, color, fadeTime, fadeDuration ); - - return true; -} - -void R_AddSurfaceDecals( msurface_t *surf ) -{ - decal_t *plist; - meshbuffer_t *mb; - - ASSERT( surf ); - - plist = surf->pdecals; - - while( plist ) - { - // Store off the next pointer, DecalUpdateAndDrawSingle could unlink - decal_t *pnext = plist->pnext; - int decalNum = -((signed int)(plist - gDecalPool) + 1); - - // add decals into list - mb = R_AddMeshToList( MB_DECAL, surf->fog, plist->shader, decalNum ); - if( mb ) - { - mb->sortkey |= (( surf->superLightStyle+1 ) << 10 ); - mb->placeTime = (uint)plist->fadeStartTime * 1000; // FIXME: doesn't work - } - plist = pnext; - } -} - -//----------------------------------------------------------------------------- -// Updates all decals, returns true if the decal should be retired -//----------------------------------------------------------------------------- -qboolean DecalUpdate( decal_t *pDecal ) -{ - // retire the decal if it's time has come - if( pDecal->fadeDuration > 0.0f ) - { - return ( RI.refdef.time >= pDecal->fadeStartTime + pDecal->fadeDuration ); - } - return false; -} - -// Build the vertex list for a decal on a surface and clip it to the surface. -// This is a template so it can work on world surfaces and dynamic displacement -// triangles the same way. -decalvert_t *R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, ref_shader_t *pShader, int *outCount ) -{ - decalvert_t *v; - - if( pDecal->flags & FDECAL_NOCLIP ) - { - v = R_DecalVertsNoclip( pDecal, surf, pShader ); - *outCount = 4; - } - else - { - v = R_DecalVertsClip( NULL, pDecal, surf, pShader, outCount ); - if( outCount ) R_DecalVertsLight( v, surf, *outCount ); - } - return v; -} - -/* -==================== -R_BuildMeshForDecal - -creates mesh for decal on first rendering -==================== -*/ -mesh_t *R_BuildMeshForDecal( decal_t *pDecal ) -{ - decalvert_t *v; - uint index, bufSize; - qboolean createSTverts = false; - int i, numVerts, numElems; - byte *buffer; - vec3_t normal; - mesh_t *mesh; - - if( pDecal->mesh ) - { - // already have mesh - return pDecal->mesh; - } - - // first rendering? create mesh for it - v = R_DecalSetupVerts( pDecal, pDecal->psurf, pDecal->shader, &numVerts ); - - // degenerate polygon - if( !numVerts ) return NULL; - - // allocate mesh - numElems = (numVerts - 2) * 3; - - if( mapConfig.deluxeMappingEnabled || ( pDecal->shader->flags & SHADER_PORTAL_CAPTURE2 )) - createSTverts = true; - - // mesh + ( align vertex, align normal, (st + lmst) + elem * numElems) * numVerts; - bufSize = sizeof( mesh_t ) + numVerts * ( sizeof( vec4_t ) + sizeof( vec4_t ) + sizeof( vec4_t )) + numElems * sizeof( elem_t ); - if( createSTverts ) bufSize += numVerts * sizeof( vec4_t ); - - buffer = Mem_Alloc( r_decalPool, bufSize ); - - mesh = (mesh_t *)buffer; - buffer += sizeof( mesh_t ); - mesh->numVerts = numVerts; - mesh->numElems = numElems; - - // setup pointers - mesh->vertexArray = (vec4_t *)buffer; - buffer += numVerts * sizeof( vec4_t ); - mesh->normalsArray = (vec4_t *)buffer; - buffer += numVerts * sizeof( vec4_t ); - mesh->stCoordArray = (vec2_t *)buffer; - buffer += numVerts * sizeof( vec2_t ); - mesh->lmCoordArray = (vec2_t *)buffer; - buffer += numVerts * sizeof( vec2_t ); - mesh->elems = (elem_t *)buffer; - buffer += numElems * sizeof( elem_t ); - - // create indices - for( i = 0, index = 2; i < mesh->numElems; i += 3, index++ ) - { - mesh->elems[i+0] = 0; - mesh->elems[i+1] = index - 1; - mesh->elems[i+2] = index; - } - - // setup normal - if( pDecal->psurf->flags & SURF_PLANEBACK ) - VectorNegate( pDecal->psurf->plane->normal, normal ); - else VectorCopy( pDecal->psurf->plane->normal, normal ); - - VectorNormalize( normal ); - - // create vertices - mesh->numVerts = numVerts; - - for( i = 0; i < numVerts; i++, v++ ) - { - VectorCopy( v->m_vPos, mesh->vertexArray[i] ); - VectorCopy( normal, mesh->normalsArray[i] ); - Vector2Copy( v->m_tCoords, mesh->stCoordArray[i] ); - Vector2Copy( v->m_LMCoords, mesh->lmCoordArray[i] ); - } - - if( createSTverts ) - { - mesh->sVectorsArray = (vec4_t *)buffer; - buffer += numVerts * sizeof( vec4_t ); - R_BuildTangentVectors( mesh->numVerts, mesh->vertexArray, mesh->normalsArray, mesh->stCoordArray, mesh->numElems / 3, mesh->elems, mesh->sVectorsArray ); - } - - return mesh; -} - -decal_t *R_DecalFromMeshbuf( const meshbuffer_t *mb ) -{ - decal_t *pDecal; - - pDecal = &gDecalPool[-mb->infokey-1]; - - // in case we compare two meshes for batching - if( !pDecal->mesh ) - pDecal->mesh = R_BuildMeshForDecal( pDecal ); - - return pDecal; -} - -/* -================= -R_PushDecal -================= -*/ -void R_PushDecal( const meshbuffer_t *mb ) -{ - decal_t *pDecal; - ref_shader_t *shader; - qboolean retire = false; - int features; - - MB_NUM2SHADER( mb->shaderkey, shader ); - pDecal = &gDecalPool[-mb->infokey-1]; - - // update dynamic decals - if( pDecal->flags & FDECAL_DYNAMIC ) - retire = DecalUpdate( pDecal ); - - if( !pDecal->mesh ) - { - // first draw? create mesh for it - pDecal->mesh = R_BuildMeshForDecal( pDecal ); - } - - if( !pDecal->mesh || retire ) - { - // invalid or expired decal, unlink it - R_DecalUnlink( pDecal ); - return; - } - - features = shader->features; - - // Deal with fading out... (should this be done in the shader?) - // Note that we do it with per-vertex color even though the translucency - // is constant so as to not change any rendering state (like the constant - // alpha value) - if( pDecal->flags & FDECAL_DYNAMIC ) - { - float fadeval; - rgba_t color; - - Vector4Copy( pDecal->color, color ); - - // negative fadeDuration value means to fade in - if( pDecal->fadeDuration < 0 ) - { - fadeval = -( RI.refdef.time - pDecal->fadeStartTime ) / pDecal->fadeDuration; - } - else - { - fadeval = 1.0f - ( RI.refdef.time - pDecal->fadeStartTime ) / pDecal->fadeDuration; - } - color[3] = bound( 0, (byte)(fadeval * 255), 255 ); - - // FIXME: apply custom color to decal - } - - R_PushMesh( pDecal->mesh, features ); -} - -/* -============================================================= - - DECALS SERIALIZATION - -============================================================= -*/ -static qboolean R_DecalUnProject( decal_t *pdecal, decallist_t *entry ) -{ - cl_entity_t *ent; - - if( !pdecal || !( pdecal->psurf )) - return false; - - ent = ri.GetClientEdict( pdecal->entityIndex ); - - if( ent ) - { - // transform decal position back into world space - if( !VectorIsNull( ent->angles )) - { - matrix4x4 matrix; - float *org = ent->origin; - float *ang = ent->angles; - - Matrix4x4_CreateFromEntity( matrix, org[0], org[1], org[2], ang[PITCH], ang[YAW], ang[ROLL], 1.0f ); - Matrix4x4_VectorTransform( matrix, pdecal->position, entry->position ); - } - else - { - VectorAdd( pdecal->position, ent->origin, entry->position ); - } - } - else - { - // give untransformed pos - VectorCopy( pdecal->position, entry->position ); - } - - - // NOTE: return original decal position for world or bmodel -// VectorCopy( pdecal->worldPos, entry->position ); - entry->entityIndex = pdecal->entityIndex; - - // Grab surface plane equation - if( pdecal->psurf->flags & SURF_PLANEBACK ) - VectorNegate( pdecal->psurf->plane->normal, entry->impactPlaneNormal ); - else VectorCopy( pdecal->psurf->plane->normal, entry->impactPlaneNormal ); - - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *pList - -// count - -// Output : static int -//----------------------------------------------------------------------------- -static int DecalListAdd( decallist_t *pList, int count ) -{ - vec3_t tmp; - decallist_t *pdecal; - int i; - - pdecal = pList + count; - - for( i = 0; i < count; i++ ) - { - if( !com.strcmp( pdecal->name, pList[i].name ) && pdecal->entityIndex == pList[i].entityIndex ) - { - VectorSubtract( pdecal->position, pList[i].position, tmp ); // Merge - if( VectorLength( tmp ) < 2 ) - { - // UNDONE: Tune this '2' constant - return count; - } - } - } - - // this is a new decal - return count + 1; -} - -static int DecalDepthCompare( const void *a, const void *b ) -{ - const decallist_t *elem1, *elem2; - - elem1 = (const decallist_t *)a; - elem2 = (const decallist_t *)b; - - if( elem1->depth > elem2->depth ) - return -1; - if( elem1->depth < elem2->depth ) - return 1; - - return 0; -} - -//----------------------------------------------------------------------------- -// Purpose: Called by CSaveRestore::SaveClientState -// Input : *pList - -// Output : int -//----------------------------------------------------------------------------- -int R_CreateDecalList( decallist_t *pList, qboolean changelevel ) -{ - int total = 0; - int i, depth; - - if( r_worldmodel && RI.drawWorld ) - { - for( i = 0; i < MAX_RENDER_DECALS; i++ ) - { - decal_t *decal = &gDecalPool[i]; - decal_t *pdecals; - - // decal is in use and is not a custom decal - if( decal->psurf == NULL || ( decal->flags & FDECAL_CUSTOM )) - continue; - - // another transition - ignore moved decals - // also permanent decals can't moving across transition - if( changelevel && decal->flags & ( FDECAL_DONTSAVE|FDECAL_PERMANENT )) - continue; - - // compute depth - depth = 0; - pdecals = decal->psurf->pdecals; - - while( pdecals && pdecals != decal ) - { - depth++; - pdecals = pdecals->pnext; - } - - pList[total].depth = depth; - pList[total].flags = decal->flags; - - R_DecalUnProject( decal, &pList[total] ); - com.strncpy( pList[total].name, decal->shader->name, sizeof( pList[total].name )); - - // check to see if the decal should be added - total = DecalListAdd( pList, total ); - } - } - - // sort the decals lowest depth first, so they can be re-applied in order - qsort( pList, total, sizeof( decallist_t ), DecalDepthCompare ); - - return total; -} - -/* -=============== -R_DecalRemoveAll - -remove all decals with specified shader -=============== -*/ -void R_DecalRemoveAll( shader_t handle ) -{ - decal_t *pdecal; - ref_shader_t *shader; - int i; - - if( handle < 0 || handle > MAX_SHADERS || !( shader = &r_shaders[handle] )) - return; - - for( i = 0; i < gDecalCount; i++ ) - { - pdecal = &gDecalPool[i]; - - if( pdecal->shader == shader ) - R_DecalUnlink( pdecal ); - } -} \ No newline at end of file diff --git a/vid_gl/r_draw.c b/vid_gl/r_draw.c deleted file mode 100644 index a2c1d566..00000000 --- a/vid_gl/r_draw.c +++ /dev/null @@ -1,704 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2007 -// r_draw.c - draw 2d pictures -//======================================================================= - -#include "r_local.h" -#include "mathlib.h" -#include "matrix_lib.h" -#include "triangleapi.h" - -#define MAX_TRIVERTS 2048 -#define MAX_TRIELEMS MAX_TRIVERTS * 6 -#define MAX_TRIANGLES MAX_TRIELEMS / 3 - -static vec4_t tri_vertex[MAX_TRIVERTS]; -static vec4_t tri_normal[MAX_TRIVERTS]; -static vec2_t tri_coords[MAX_TRIVERTS]; -static rgba_t tri_colors[MAX_TRIVERTS]; -static elem_t tri_elems[MAX_TRIELEMS]; -static mesh_t tri_mesh; -meshbuffer_t tri_mbuffer; -tristate_t triState; - -static vec4_t pic_xyz[4] = { {0,0,0,1}, {0,0,0,1}, {0,0,0,1}, {0,0,0,1} }; -static vec2_t pic_st[4]; -static rgba_t pic_colors[4]; -static mesh_t pic_mesh = { 4, 6, pic_xyz, pic_xyz, NULL, NULL, pic_st, NULL, pic_colors, NULL, NULL }; -meshbuffer_t pic_mbuffer; - -/* -=============== -R_DrawSetColor -=============== -*/ -void R_DrawSetColor( const rgba_t color ) -{ - if( color ) Vector4Copy( color, glState.draw_color ); - else Vector4Set( glState.draw_color, 255, 255, 255, 255 ); -} - -/* -=============== -R_DrawStretchPic -=============== -*/ -void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, shader_t handle ) -{ - int bcolor; - ref_shader_t *shader; - static int oldframe; - - if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle])) - return; - - // lower-left - Vector2Set( pic_xyz[0], x, y ); - Vector2Set( pic_st[0], s1, t1 ); - Vector4Copy( glState.draw_color, pic_colors[0] ); - bcolor = *(int *)pic_colors[0]; - - // lower-right - Vector2Set( pic_xyz[1], x+w, y ); - Vector2Set( pic_st[1], s2, t1 ); - *(int *)pic_colors[1] = bcolor; - - // upper-right - Vector2Set( pic_xyz[2], x+w, y+h ); - Vector2Set( pic_st[2], s2, t2 ); - *(int *)pic_colors[2] = bcolor; - - // upper-left - Vector2Set( pic_xyz[3], x, y+h ); - Vector2Set( pic_st[3], s1, t2 ); - *(int *)pic_colors[3] = bcolor; - - if( pic_mbuffer.shaderkey != (int)shader->sortkey || -pic_mbuffer.infokey-1+4 > MAX_ARRAY_VERTS ) - { - if( pic_mbuffer.shaderkey ) - { - pic_mbuffer.infokey = -1; - R_RenderMeshBuffer( &pic_mbuffer ); - } - } - - tr.iRenderMode = glState.draw_rendermode; - pic_mbuffer.shaderkey = shader->sortkey; - pic_mbuffer.infokey -= 4; - - R_PushMesh( &pic_mesh, MF_TRIFAN|shader->features | ( r_shownormals->integer ? MF_NORMALS : 0 )); - - if( oldframe != glState.draw_frame ) - { - if( pic_mbuffer.shaderkey != shader->sortkey ) - { - // will be rendering on next call - oldframe = glState.draw_frame; - return; - } - if( pic_mbuffer.shaderkey ) - { - pic_mbuffer.infokey = -1; - R_RenderMeshBuffer( &pic_mbuffer ); - } - oldframe = glState.draw_frame; - } -} -/* -================= -R_ResampleRaw -================= -*/ -static byte *R_ResampleRaw( const byte *source, int inWidth, int inHeight, int outWidth, int outHeight ) -{ - uint frac, fracStep; - uint *in = (uint *)source; - uint p1[0x1000], p2[0x1000]; - byte *pix1, *pix2, *pix3, *pix4; - uint *inRow1, *inRow2, *out; - static byte *resampled = NULL; - int i, x, y; - - // clean frames doesn't contain raw buffer - if( !source ) return NULL; - - resampled = Mem_Realloc( r_temppool, resampled, outWidth * outHeight * 4 ); - out = (uint *)resampled; - - fracStep = inWidth * 0x10000 / outWidth; - - frac = fracStep >> 2; - for( i = 0; i < outWidth; i++ ) - { - p1[i] = 4 * (frac >> 16); - frac += fracStep; - } - - frac = (fracStep >> 2) * 3; - for( i = 0; i < outWidth; i++ ) - { - p2[i] = 4 * (frac >> 16); - frac += fracStep; - } - - for( y = 0; y < outHeight; y++, out += outWidth ) - { - inRow1 = in + inWidth * (int)(((float)y + 0.25) * inHeight/outHeight); - inRow2 = in + inWidth * (int)(((float)y + 0.75) * inHeight/outHeight); - - for( x = 0; x < outWidth; x++ ) - { - pix1 = (byte *)inRow1 + p1[x]; - pix2 = (byte *)inRow1 + p2[x]; - pix3 = (byte *)inRow2 + p1[x]; - pix4 = (byte *)inRow2 + p2[x]; - - ((byte *)(out+x))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2; - ((byte *)(out+x))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2; - ((byte *)(out+x))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2; - ((byte *)(out+x))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3]) >> 2; - } - } - return resampled; -} - -/* -============= -R_DrawStretchRaw -============= -*/ -void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty ) -{ - byte *raw; - - if( !GL_Support( R_ARB_TEXTURE_NPOT_EXT )) - { - int width = 1, height = 1; - - // check the dimensions - while( width < cols ) width <<= 1; - while( height < rows ) height <<= 1; - - if( cols != width || rows != height ) - { - raw = R_ResampleRaw( data, cols, rows, width, height ); - cols = width; - rows = height; - } - } - else - { - raw = (byte *)data; - } - - if( cols > glConfig.max_2d_texture_size ) - Host_Error( "R_DrawStretchRaw: size exceeds hardware limits (%i > %i)\n", cols, glConfig.max_2d_texture_size ); - if( rows > glConfig.max_2d_texture_size ) - Host_Error( "R_DrawStretchRaw: size exceeds hardware limits (%i > %i)\n", rows, glConfig.max_2d_texture_size ); - - // draw logo may be called between two draw pic calls. - // so we need flush it here - if( pic_mbuffer.infokey != -1 ) - { - R_RenderMeshBuffer( &pic_mbuffer ); - pic_mbuffer.infokey = -1; - } - - GL_Bind( 0, tr.cinTexture ); - - if( cols == tr.cinTexture->width && rows == tr.cinTexture->height ) - { - if( dirty ) pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_BGRA, GL_UNSIGNED_BYTE, raw ); - } - else - { - tr.cinTexture->width = cols; - tr.cinTexture->height = rows; - if( dirty ) pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, raw ); - } - - R_CheckForErrors(); - - pglBegin( GL_QUADS ); - pglTexCoord2f( 0, 0 ); - pglVertex2f( x, y ); - pglTexCoord2f( 1, 0 ); - pglVertex2f( x + w, y ); - pglTexCoord2f( 1, 1 ); - pglVertex2f( x + w, y + h ); - pglTexCoord2f( 0, 1 ); - pglVertex2f( x, y + h ); - pglEnd(); -} - -void R_DrawGetParms( int *w, int *h, int *f, int frame, shader_t handle ) -{ - ref_shader_t *shader; - int cur = 0; - - if( !w && !h && !f ) return; - - // assume error - if( w ) *w = 0; - if( h ) *h = 0; - if( f ) *f = 1; - - if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle])) - return; - - if( !shader->num_stages || !shader->stages[0].textures[0] ) - return; - - if( shader->stages[0].textures[0] && shader->stages[0].num_textures && frame > 0 ) - cur = bound( 0, frame, shader->stages[0].num_textures ); - - if( w ) *w = (int)shader->stages[0].textures[cur]->srcWidth; - if( h ) *h = (int)shader->stages[0].textures[cur]->srcHeight; - if( f ) *f = (int)shader->stages[0].num_textures; -} - -void R_DrawSetParms( shader_t handle, int rendermode, int frame ) -{ - ref_shader_t *shader; - - if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle]) || !shader->num_stages ) - return; - - if( glState.draw_rendermode != rendermode ) - { - if( pic_mbuffer.shaderkey ) - { - pic_mbuffer.infokey = -1; - R_RenderMeshBuffer( &pic_mbuffer ); - } - } - - if( triState.currentRenderMode != rendermode ) - { - if( pic_mbuffer.shaderkey ) - { - pic_mbuffer.infokey = -1; - R_RenderMeshBuffer( &pic_mbuffer ); - } - } - - glState.draw_rendermode = rendermode; - - if( !shader->stages[0].num_textures ) - return; - - // change frame if need - if( shader->stages[0].flags & SHADERSTAGE_FRAMES ) - { - // make sure what frame inbound - glState.draw_frame = bound( 0, frame, shader->stages[0].num_textures - 1 ); - } -} - -/* -============================================================= - - TRIAPI IMPLEMENTATION - -============================================================= -*/ -static void Tri_ClearBounds( void ) -{ - // clear bounds that uses for polygon lighting - VectorClear( triState.lightingOrigin ); - ClearBounds( triState.mins, triState.maxs ); -} - -static void Tri_DrawPolygon( void ) -{ - ref_shader_t *shader; - static int i, oldframe; - - shader = &r_shaders[triState.currentShader]; - - tri_mesh.numVerts = triState.numVertex; - tri_mesh.numElems = triState.numIndex; - - if( triState.hasNormals ) - tri_mesh.normalsArray = tri_normal; - else tri_mesh.normalsArray = NULL; // no normals - - if( triState.numColor == 1 ) - { - // global color for all vertexes - for( i = 0; i < triState.numVertex - 1; i++ ) - Vector4Copy( tri_colors[0], tri_colors[i+1] ); - } - - // compute lightingOrigin - VectorAverage( triState.mins, triState.maxs, triState.lightingOrigin ); - - tri_mesh.vertexArray = tri_vertex; - tri_mesh.stCoordArray = tri_coords; - tri_mesh.colorsArray = tri_colors; - tri_mesh.elems = tri_elems; - - if( tri_mbuffer.shaderkey != (int)shader->sortkey || -tri_mbuffer.infokey-1+256 > MAX_ARRAY_VERTS ) - { - if( tri_mbuffer.shaderkey ) - { - tri_mbuffer.infokey = -1; - R_RenderMeshBuffer( &tri_mbuffer ); - Tri_ClearBounds(); - } - } - - tr.iRenderMode = triState.currentRenderMode; - tri_mbuffer.shaderkey = shader->sortkey; - tri_mbuffer.infokey -= triState.numVertex; - - triState.features = shader->features; - triState.features |= MF_COLORS; - if( r_shownormals->integer || triState.hasNormals ) - triState.features |= MF_NORMALS; - - if( triState.noCulling ) - triState.features |= MF_NOCULL; - - R_PushMesh( &tri_mesh, triState.features ); - - if( oldframe != glState.draw_frame ) - { - if( tri_mbuffer.shaderkey != shader->sortkey ) - { - // will be rendering on next call - oldframe = glState.draw_frame; - return; - } - if( tri_mbuffer.shaderkey ) - { - tri_mbuffer.infokey = -1; - R_RenderMeshBuffer( &tri_mbuffer ); - Tri_ClearBounds(); - } - oldframe = glState.draw_frame; - } - triState.numVertex = triState.numIndex = triState.numColor = 0; -} - -static void Tri_CheckOverflow( int numIndices, int numVertices ) -{ - if( numIndices > MAX_TRIELEMS ) - Host_Error( "Tri_Overflow: %i > MAX_TRIELEMS\n", numIndices ); - if( numVertices > MAX_TRIVERTS ) - Host_Error( "Tri_Overflow: %i > MAX_TRIVERTS\n", numVertices ); - - if( triState.numIndex + numIndices <= MAX_TRIELEMS && triState.numVertex + numVertices <= MAX_TRIVERTS ) - return; - - Tri_DrawPolygon(); -} - -void Tri_Fog( float flFogColor[3], float flStart, float flEnd, int bOn ) -{ - // ignore fog calls from TriApi callbacks - // to avoid strange artefacts and other issues - if( triState.fActive ) return; - - // change fog params - triState.fogColor[0] = bound( 0.0f, flFogColor[0], 1.0f ); - triState.fogColor[1] = bound( 0.0f, flFogColor[1], 1.0f ); - triState.fogColor[2] = bound( 0.0f, flFogColor[2], 1.0f ); - triState.fogColor[3] = 1.0f; - triState.fogStartDist = min( flStart, flEnd ); - triState.fogEndDist = max( flStart, flEnd ); - triState.fogEnabled = bOn; -} - -void Tri_CullFace( int mode ) -{ - if( mode == TRI_FRONT ) - triState.noCulling = false; - else if( mode == TRI_NONE ) - triState.noCulling = true; -} - -void Tri_RenderMode( const int mode ) -{ - if( triState.currentRenderMode != mode ) - { - if( tri_mbuffer.shaderkey ) - { - tri_mbuffer.infokey = -1; - R_RenderMeshBuffer( &tri_mbuffer ); - Tri_ClearBounds(); - } - } - triState.currentRenderMode = mode; -} - -void Tri_Vertex3f( const float x, const float y, const float z ) -{ - uint oldIndex = triState.numIndex; - - switch( triState.drawMode ) - { - case TRI_LINES: - tri_elems[triState.numIndex++] = triState.numVertex; - if( triState.vertexState++ == 1 ) - { - Tri_Vertex3f( x + 1, y + 1, z + 1 ); - triState.vertexState = 0; - triState.checkFlush = true; // flush for long sequences of quads. - } - break; - case TRI_TRIANGLES: - tri_elems[triState.numIndex++] = triState.numVertex; - if( triState.vertexState++ == 2 ) - { - triState.vertexState = 0; - triState.checkFlush = true; // flush for long sequences of triangles. - } - break; - case TRI_QUADS: - if( triState.vertexState++ < 3 ) - { - tri_elems[triState.numIndex++] = triState.numVertex; - } - else - { - // we've already done triangle (0, 1, 2), now draw (2, 3, 0) - tri_elems[triState.numIndex++] = triState.numVertex - 1; - tri_elems[triState.numIndex++] = triState.numVertex; - tri_elems[triState.numIndex++] = triState.numVertex - 3; - triState.vertexState = 0; - triState.checkFlush = true; // flush for long sequences of quads. - } - break; - case TRI_TRIANGLE_STRIP: - if( triState.numVertex + triState.vertexState > MAX_TRIVERTS ) - { - // This is a strip that's too big for us to buffer. - // (We can't just flush the buffer because we have to keep - // track of the last two vertices. - Host_Error( "Tri_Vertex3f: overflow: %i > MAX_TRIVERTS\n", triState.numVertex + triState.vertexState ); - } - if( triState.numIndex > MAX_TRIELEMS ) - { - // This is a strip that's too big for us to buffer. - // (We can't just flush the buffer because we have to keep - // track of the last two vertices. - Host_Error( "Tri_Vertex3f: overflow: %i > MAX_TRIELEMS\n", triState.numIndex ); - } - if( triState.vertexState++ < 3 ) - { - tri_elems[triState.numIndex++] = triState.numVertex; - } - else - { - // flip triangles between clockwise and counter clockwise - if( triState.vertexState & 1 ) - { - // draw triangle [n-2 n-1 n] - tri_elems[triState.numIndex++] = triState.numVertex - 2; - tri_elems[triState.numIndex++] = triState.numVertex - 1; - tri_elems[triState.numIndex++] = triState.numVertex; - } - else - { - // draw triangle [n-1 n-2 n] - tri_elems[triState.numIndex++] = triState.numVertex - 1; - tri_elems[triState.numIndex++] = triState.numVertex - 2; - tri_elems[triState.numIndex++] = triState.numVertex; - } - } - break; - case TRI_POLYGON: - case TRI_TRIANGLE_FAN: // same as polygon - if( triState.numVertex + triState.vertexState > MAX_TRIVERTS ) - { - // This is a polygon or fan that's too big for us to buffer. - // (We can't just flush the buffer because we have to keep - // track of the starting vertex. - Host_Error( "Tri_Vertex3f: overflow: %i > MAX_TRIVERTS\n", triState.numVertex + triState.vertexState ); - } - if( triState.vertexState++ < 3 ) - { - tri_elems[triState.numIndex++] = triState.numVertex; - } - else - { - // draw triangle [0 n-1 n] - tri_elems[triState.numIndex++] = triState.numVertex - ( triState.vertexState - 1 ); - tri_elems[triState.numIndex++] = triState.numVertex - 1; - tri_elems[triState.numIndex++] = triState.numVertex; - } - break; - default: - Host_Error( "Tri_SetVertex: unknown mode: %i\n", triState.drawMode ); - break; - } - - // copy current vertex - tri_vertex[triState.numVertex][0] = x; - tri_vertex[triState.numVertex][1] = y; - tri_vertex[triState.numVertex][2] = z; - tri_vertex[triState.numVertex][3] = 1; - - // for compute lighting origin - AddPointToBounds( tri_vertex[triState.numVertex], triState.mins, triState.maxs ); - - triState.numVertex++; - - // flush buffer if needed - if( triState.checkFlush ) - Tri_CheckOverflow( triState.numIndex - oldIndex, triState.vertexState ); -} - -void Tri_Color4ub( const byte r, const byte g, const byte b, const byte a ) -{ - tri_colors[triState.numVertex][0] = r; - tri_colors[triState.numVertex][1] = g; - tri_colors[triState.numVertex][2] = b; - tri_colors[triState.numVertex][3] = a; - triState.numColor++; -} - -void Tri_Normal3f( const float x, const float y, const float z ) -{ - triState.hasNormals = true; // curstate has normals - tri_normal[triState.numVertex][0] = x; - tri_normal[triState.numVertex][1] = y; - tri_normal[triState.numVertex][2] = z; - tri_normal[triState.numVertex][3] = 1; -} - -void Tri_TexCoord2f( const float u, const float v ) -{ - tri_coords[triState.numVertex][0] = u; - tri_coords[triState.numVertex][1] = v; -} - -void Tri_Bind( shader_t handle, int frame ) -{ - ref_shader_t *shader; - - if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle])) - { - MsgDev( D_ERROR, "TriBind: bad shader %i\n", handle ); - return; - } - - if( !shader->num_stages || !shader->stages[0].textures[0] ) - { - MsgDev( D_ERROR, "TriBind: bad shader %i\n", handle ); - return; - } - - triState.currentShader = handle; - - // FIXME: scan stages while( frame < stage->num_textures ) ? - if( shader->stages[0].textures[0] && shader->stages[0].num_textures && frame > 0 ) - glState.draw_frame = bound( 0, frame, shader->stages[0].num_textures ); -} - -void Tri_Begin( int mode ) -{ - triState.drawMode = mode; - triState.vertexState = 0; - triState.checkFlush = false; - triState.hasNormals = false; -} - -void Tri_End( void ) -{ - if( triState.numIndex ) - Tri_DrawPolygon(); -} - -void Tri_RenderCallback( int fTrans ) -{ - if( !RI.drawWorld ) return; - - triState.fActive = true; - - if( fTrans ) GL_SetState( GLSTATE_NO_DEPTH_TEST ); - R_LoadIdentity (); - Tri_ClearBounds (); - - pglColor4f( 1, 1, 1, 1 ); - - RI.currententity = RI.previousentity = NULL; - RI.currentmodel = NULL; - - tri_mbuffer.infokey = -1; - tri_mbuffer.shaderkey = 0; - triState.numColor = 0; - - ri.DrawTriangles( fTrans ); - - // fulsh remaining tris - if( tri_mbuffer.infokey != -1 ) - { - R_RenderMeshBuffer( &tri_mbuffer ); - tri_mbuffer.infokey = -1; - } - - triState.fActive = false; -} - -/* -=============== -R_Set2DMode -=============== -*/ -void R_Set2DMode( qboolean enable ) -{ - if( enable ) - { - if( glState.in2DMode ) - return; - - // set 2D virtual screen size - pglScissor( 0, 0, glState.width, glState.height ); - pglViewport( 0, 0, glState.width, glState.height ); - pglMatrixMode( GL_PROJECTION ); - pglLoadIdentity(); - pglOrtho( 0, glState.width, glState.height, 0, -99999, 99999 ); - pglMatrixMode( GL_MODELVIEW ); - pglLoadIdentity(); - - GL_Cull( 0 ); - GL_SetState( GLSTATE_NO_DEPTH_TEST ); - - pglColor4f( 1, 1, 1, 1 ); - - glState.in2DMode = true; - RI.currententity = RI.previousentity = NULL; - RI.currentmodel = NULL; - - pic_mbuffer.infokey = -1; - pic_mbuffer.shaderkey = 0; - - // reset TriApi state too in case we want use it in 2d mode - Tri_ClearBounds (); - - tri_mbuffer.infokey = -1; - tri_mbuffer.shaderkey = 0; - triState.numColor = 0; - triState.fActive = true; - } - else - { - if( pic_mbuffer.infokey != -1 ) - { - R_RenderMeshBuffer( &pic_mbuffer ); - pic_mbuffer.infokey = -1; - } - - // fulsh remaining tris - if( tri_mbuffer.infokey != -1 ) - { - R_RenderMeshBuffer( &tri_mbuffer ); - tri_mbuffer.infokey = -1; - } - - triState.fActive = false; - glState.in2DMode = false; - } -} \ No newline at end of file diff --git a/vid_gl/r_image.c b/vid_gl/r_image.c deleted file mode 100644 index 72e0145e..00000000 --- a/vid_gl/r_image.c +++ /dev/null @@ -1,3835 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2008 -// r_image.c - texture manager -//======================================================================= - -#include "r_local.h" -#include "mathlib.h" -#include "matrix_lib.h" -#include "const.h" - -#define TEXTURES_HASH_SIZE 64 - -static rgbdata_t *R_LoadImage( script_t *script, const char *name, const byte *buf, size_t size, int *samples, texFlags_t *flags ); -static int r_textureMinFilter = GL_LINEAR_MIPMAP_LINEAR; -static int r_textureMagFilter = GL_LINEAR; -static int r_textureDepthFilter = GL_LINEAR; - -// internal tables -static vec3_t r_luminanceTable[256]; // RGB to luminance -static byte r_glowTable[256][3]; // auto LUMA table -static byte r_gammaTable[256]; // adjust screenshot gamma - -static texture_t r_textures[MAX_TEXTURES]; -static texture_t *r_texturesHashTable[TEXTURES_HASH_SIZE]; -static int r_numTextures; -static byte *r_imagepool; // immediate buffers -static byte *r_texpool; // texture_t permanent chain -static byte data2D[256*256*4]; -static rgbdata_t r_image; // generic pixelbuffer used for internal textures - -typedef struct envmap_s -{ - vec3_t angles; - int flags; -} envmap_t; - -const envmap_t r_skyBoxInfo[6] = -{ -{{ 0, 270, 180}, IMAGE_FLIP_X }, -{{ 0, 90, 180}, IMAGE_FLIP_X }, -{{ -90, 0, 180}, IMAGE_FLIP_X }, -{{ 90, 0, 180}, IMAGE_FLIP_X }, -{{ 0, 0, 180}, IMAGE_FLIP_X }, -{{ 0, 180, 180}, IMAGE_FLIP_X }, -}; - -const envmap_t r_envMapInfo[6] = -{ -{{ 0, 0, 90}, 0 }, -{{ 0, 180, -90}, 0 }, -{{ 0, 90, 0}, 0 }, -{{ 0, 270, 180}, 0 }, -{{-90, 180, -90}, 0 }, -{{ 90, 180, 90}, 0 } -}; - -static struct -{ - string name; - pixformat_t format; - int width; - int height; - int bpp; - int SizeOfFile; - int numSides; - GLuint glFormat; - GLuint glType; - GLuint glTarget; - GLuint glSamples; - GLuint texTarget; - texType_t texType; - - uint tflags; // TF_ flags - uint flags; // IMAGE_ flags - byte *pal; - byte *source; - byte *scaled; -} image_desc; - -void GL_SelectTexture( GLenum texture ) -{ - if( !GL_Support( R_ARB_MULTITEXTURE )) - return; - if( glState.activeTMU == texture ) - return; - - glState.activeTMU = texture; - - if( pglActiveTextureARB ) - { - pglActiveTextureARB( texture + GL_TEXTURE0_ARB ); - pglClientActiveTextureARB( texture + GL_TEXTURE0_ARB ); - } - else if( pglSelectTextureSGIS ) - { - pglSelectTextureSGIS( texture + GL_TEXTURE0_SGIS ); - } -} - -void GL_TexEnv( GLenum mode ) -{ - if( glState.currentEnvModes[glState.activeTMU] == mode ) - return; - - glState.currentEnvModes[glState.activeTMU] = mode; - pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode ); -} - -void GL_Bind( GLenum tmu, texture_t *texture ) -{ - GL_SelectTexture( tmu ); - - if( r_nobind->integer ) texture = tr.defaultTexture; // performance evaluation option - if( glState.currentTextures[tmu] == texture->texnum ) - return; - - glState.currentTextures[tmu] = texture->texnum; - pglBindTexture( texture->target, texture->texnum ); -} - -void GL_LoadTexMatrix( const matrix4x4 m ) -{ - pglMatrixMode( GL_TEXTURE ); - GL_LoadMatrix( m ); - glState.texIdentityMatrix[glState.activeTMU] = false; -} - -void GL_LoadMatrix( const matrix4x4 source ) -{ - GLfloat dest[16]; - - Matrix4x4_ToArrayFloatGL( source, dest ); - pglLoadMatrixf( dest ); -} - -void GL_LoadIdentityTexMatrix( void ) -{ - if( glState.texIdentityMatrix[glState.activeTMU] ) - return; - - pglMatrixMode( GL_TEXTURE ); - pglLoadIdentity(); - glState.texIdentityMatrix[glState.activeTMU] = true; -} - -void GL_EnableTexGen( int coord, int mode ) -{ - int tmu = glState.activeTMU; - int bit, gen; - - switch( coord ) - { - case GL_S: - bit = 1; - gen = GL_TEXTURE_GEN_S; - break; - case GL_T: - bit = 2; - gen = GL_TEXTURE_GEN_T; - break; - case GL_R: - bit = 4; - gen = GL_TEXTURE_GEN_R; - break; - case GL_Q: - bit = 8; - gen = GL_TEXTURE_GEN_Q; - break; - default: return; - } - - if( mode ) - { - if(!( glState.genSTEnabled[tmu] & bit )) - { - pglEnable( gen ); - glState.genSTEnabled[tmu] |= bit; - } - pglTexGeni( coord, GL_TEXTURE_GEN_MODE, mode ); - } - else - { - if( glState.genSTEnabled[tmu] & bit ) - { - pglDisable( gen ); - glState.genSTEnabled[tmu] &= ~bit; - } - } -} - -void GL_SetTexCoordArrayMode( int mode ) -{ - int tmu = glState.activeTMU; - int bit, cmode = glState.texCoordArrayMode[tmu]; - - if( mode == GL_TEXTURE_COORD_ARRAY ) - bit = 1; - else if( mode == GL_TEXTURE_CUBE_MAP_ARB ) - bit = 2; - else bit = 0; - - if( cmode != bit ) - { - if( cmode == 1 ) pglDisableClientState( GL_TEXTURE_COORD_ARRAY ); - else if( cmode == 2 ) pglDisable( GL_TEXTURE_CUBE_MAP_ARB ); - - if( bit == 1 ) pglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - else if( bit == 2 ) pglEnable( GL_TEXTURE_CUBE_MAP_ARB ); - - glState.texCoordArrayMode[tmu] = bit; - } -} - -/* -================= -R_SetTextureParameters -================= -*/ -void R_SetTextureParameters( void ) -{ - texture_t *texture; - int i; - - if( !com.stricmp( gl_texturemode->string, "GL_NEAREST" )) - { - r_textureMinFilter = GL_NEAREST; - r_textureMagFilter = GL_NEAREST; - } - else if( !com.stricmp( gl_texturemode->string, "GL_LINEAR" )) - { - r_textureMinFilter = GL_LINEAR; - r_textureMagFilter = GL_LINEAR; - } - else if( !com.stricmp( gl_texturemode->string, "GL_NEAREST_MIPMAP_NEAREST" )) - { - r_textureMinFilter = GL_NEAREST_MIPMAP_NEAREST; - r_textureMagFilter = GL_NEAREST; - } - else if( !com.stricmp( gl_texturemode->string, "GL_LINEAR_MIPMAP_NEAREST" )) - { - r_textureMinFilter = GL_LINEAR_MIPMAP_NEAREST; - r_textureMagFilter = GL_LINEAR; - } - else if( !com.stricmp( gl_texturemode->string, "GL_NEAREST_MIPMAP_LINEAR" )) - { - r_textureMinFilter = GL_NEAREST_MIPMAP_LINEAR; - r_textureMagFilter = GL_NEAREST; - } - else if( !com.stricmp( gl_texturemode->string, "GL_LINEAR_MIPMAP_LINEAR" )) - { - r_textureMinFilter = GL_LINEAR_MIPMAP_LINEAR; - r_textureMagFilter = GL_LINEAR; - } - else - { - MsgDev( D_ERROR, "gl_texturemode invalid mode %s, defaulting to GL_LINEAR_MIPMAP_LINEAR\n", gl_texturemode->string ); - Cvar_Set( "gl_texturemode", "GL_LINEAR_MIPMAP_LINEAR" ); - r_textureMinFilter = GL_LINEAR_MIPMAP_LINEAR; - r_textureMagFilter = GL_LINEAR; - } - - gl_texturemode->modified = false; - - if( GL_Support( R_ANISOTROPY_EXT )) - { - if( gl_texture_anisotropy->value > glConfig.max_texture_anisotropy ) - Cvar_SetFloat( "r_anisotropy", glConfig.max_texture_anisotropy ); - else if( gl_texture_anisotropy->value < 1.0f ) - Cvar_SetFloat( "r_anisotropy", 1.0f ); - } - gl_texture_anisotropy->modified = false; - - if( GL_Support( R_TEXTURE_LODBIAS )) - { - if( gl_texture_lodbias->value > glConfig.max_texture_lodbias ) - Cvar_SetFloat( "r_texture_lodbias", glConfig.max_texture_lodbias ); - else if( gl_texture_lodbias->value < -glConfig.max_texture_lodbias ) - Cvar_SetFloat( "r_texture_lodbias", -glConfig.max_texture_lodbias ); - } - gl_texture_lodbias->modified = false; - - // change all the existing mipmapped texture objects - for( i = 0, texture = r_textures; i < r_numTextures; i++, texture++ ) - { - if( !texture->texnum ) continue; // free slot - GL_Bind( GL_TEXTURE0, texture ); - - // set texture filter - if( texture->flags & TF_DEPTHMAP ) - { - // set texture filter - pglTexParameteri( texture->target, GL_TEXTURE_MIN_FILTER, r_textureDepthFilter ); - pglTexParameteri( texture->target, GL_TEXTURE_MAG_FILTER, r_textureDepthFilter ); - - // set texture anisotropy if available - if( GL_Support( R_ANISOTROPY_EXT )) - pglTexParameterf( texture->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f ); - } - else if( texture->flags & TF_NOMIPMAP ) - { - if( texture->flags & TF_NEAREST ) - { - pglTexParameteri( texture->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); - pglTexParameteri( texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); - } - else - { - pglTexParameteri( texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - pglTexParameteri( texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - } - } - else - { - if( texture->flags & TF_NEAREST ) - { - pglTexParameteri( texture->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST ); - pglTexParameteri( texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); - } - else - { - pglTexParameteri( texture->target, GL_TEXTURE_MIN_FILTER, r_textureMinFilter ); - pglTexParameteri( texture->target, GL_TEXTURE_MAG_FILTER, r_textureMagFilter ); - } - - // set texture anisotropy if available - if( GL_Support( R_ANISOTROPY_EXT )) - pglTexParameterf( texture->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_anisotropy->value ); - - // set texture LOD bias if available - if( GL_Support( R_TEXTURE_LODBIAS )) - pglTexParameterf( texture->target, GL_TEXTURE_LOD_BIAS_EXT, gl_texture_lodbias->value ); - } - } -} - -/* -=============== -R_TextureList_f -=============== -*/ -void R_TextureList_f( void ) -{ - texture_t *image; - int i, texCount, bytes = 0; - - Msg( "\n" ); - Msg(" -w-- -h-- -size- -fmt- type -filter -wrap-- -name--------\n" ); - - for( i = texCount = 0, image = r_textures; i < r_numTextures; i++, image++ ) - { - if( !image->texnum ) continue; - - bytes += image->size; - texCount++; - - Msg( "%4i: ", i ); - Msg( "%4i %4i ", image->width, image->height ); - Msg( "%5ik ", image->size >> 10 ); - - switch( image->format ) - { - case GL_COMPRESSED_RGBA_ARB: - Msg( "CRGBA " ); - break; - case GL_COMPRESSED_RGB_ARB: - Msg( "CRGB " ); - break; - case GL_COMPRESSED_LUMINANCE_ALPHA_ARB: - Msg( "CLA " ); - break; - case GL_COMPRESSED_LUMINANCE_ARB: - Msg( "CL " ); - break; - case GL_COMPRESSED_ALPHA_ARB: - Msg( "CA " ); - break; - case GL_COMPRESSED_INTENSITY_ARB: - Msg( "CI " ); - break; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - Msg( "DXT1 " ); - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - Msg( "DXT3 " ); - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - Msg( "DXT5 " ); - break; - case GL_RGBA: - Msg( "RGBA " ); - break; - case GL_RGBA8: - Msg( "RGBA8 " ); - break; - case GL_RGBA4: - Msg( "RGBA4 " ); - break; - case GL_RGB: - Msg( "RGB " ); - break; - case GL_RGB8: - Msg( "RGB8 " ); - break; - case GL_RGB5: - Msg( "RGB5 " ); - break; - case GL_LUMINANCE8_ALPHA8: - Msg( "L8A8 " ); - break; - case GL_LUMINANCE8: - Msg( "L8 " ); - break; - case GL_ALPHA8: - Msg( "A8 " ); - break; - case GL_INTENSITY8: - Msg( "I8 " ); - break; - default: - Msg( "????? " ); - break; - } - - switch( image->target ) - { - case GL_TEXTURE_2D: - Msg( " 2D " ); - break; - case GL_TEXTURE_3D: - Msg( " 3D " ); - break; - case GL_TEXTURE_CUBE_MAP_ARB: - Msg( "CUBE " ); - break; - default: - Msg( "???? " ); - break; - } - - if( image->flags & TF_NOMIPMAP ) - Msg( "linear " ); - else Msg( "default" ); - - if( image->flags & TF_CLAMP ) - Msg( " clamp " ); - else Msg( " repeat " ); - Msg( " %s\n", image->name ); - } - - Msg( "---------------------------------------------------------\n" ); - Msg( "%i total textures\n", texCount ); - Msg( "%s total memory used\n", memprint( bytes )); - Msg( "\n" ); -} - -/* -======================================================================= - -TEXTURE INITIALIZATION AND LOADING - -======================================================================= -*/ - -/* -=============== -R_GetImageSize - -calculate buffer size for current miplevel -=============== -*/ -uint R_GetImageSize( int block, int width, int height, int depth, int bpp, int rgbcount ) -{ - uint BlockSize = 0; - - if( block == 0 ) BlockSize = width * height * depth * bpp; - else if( block > 0 ) BlockSize = ((width + 3)/4) * ((height + 3)/4) * depth * block; - else if( block < 0 && rgbcount > 0 ) BlockSize = width * height * depth * rgbcount; - else BlockSize = width * height * depth * abs( block ); - - return BlockSize; -} - -int R_GetSamples( int flags ) -{ - if( flags & IMAGE_HAS_COLOR ) - return (flags & IMAGE_HAS_ALPHA) ? 4 : 3; - return (flags & IMAGE_HAS_ALPHA) ? 2 : 1; -} - -int R_SetSamples( int s1, int s2 ) -{ - int samples; - - if( s1 == 1 ) samples = s2; - else if( s1 == 2 ) - { - if( s2 == 3 || s2 == 4 ) - samples = 4; - else samples = 2; - } - else if( s1 == 3 ) - { - if( s2 == 2 || s2 == 4 ) - samples = 4; - else samples = 3; - } - else samples = s1; - - return samples; -} - -/* -=============== -R_TextureFormat -=============== -*/ -static void R_TextureFormat( texture_t *tex, qboolean compress ) -{ - // set texture format - if( tex->flags & TF_DEPTHMAP ) - { - tex->format = GL_DEPTH_COMPONENT; - tex->flags &= ~TF_INTENSITY; - tex->flags &= ~TF_ALPHA; - } - else if( compress ) - { - switch( tex->samples ) - { - case 1: tex->format = GL_COMPRESSED_LUMINANCE_ARB; break; - case 2: tex->format = GL_COMPRESSED_LUMINANCE_ALPHA_ARB; break; - case 3: tex->format = GL_COMPRESSED_RGB_ARB; break; - case 4: tex->format = GL_COMPRESSED_RGBA_ARB; break; - } - - if( tex->flags & TF_INTENSITY ) - tex->format = GL_COMPRESSED_INTENSITY_ARB; - if( tex->flags & TF_ALPHA ) - tex->format = GL_COMPRESSED_ALPHA_ARB; - tex->flags &= ~TF_INTENSITY; - tex->flags &= ~TF_ALPHA; - } - else - { - int bits = r_texturebits->integer; - - switch( tex->samples ) - { - case 1: tex->format = GL_LUMINANCE8; break; - case 2: tex->format = GL_LUMINANCE8_ALPHA8; break; - case 3: - switch( bits ) - { - case 16: tex->format = GL_RGB5; break; - case 32: tex->format = GL_RGB8; break; - default: tex->format = GL_RGB; break; - } - break; - case 4: - switch( bits ) - { - case 16: tex->format = GL_RGBA4; break; - case 32: tex->format = GL_RGBA8; break; - default: tex->format = GL_RGBA; break; - } - break; - } - - if( tex->flags & TF_INTENSITY ) - tex->format = GL_INTENSITY8; - if( tex->flags & TF_ALPHA ) - tex->format = GL_ALPHA8; - tex->flags &= ~TF_INTENSITY; - tex->flags &= ~TF_ALPHA; - } -} - -void R_RoundImageDimensions( int *width, int *height, qboolean force ) -{ - int scaledWidth, scaledHeight; - - scaledWidth = *width; - scaledHeight = *height; - - if( force || !GL_Support( R_ARB_TEXTURE_NPOT_EXT )) - { - // find nearest power of two, rounding down if desired - scaledWidth = NearestPOW( scaledWidth, gl_round_down->integer ); - scaledHeight = NearestPOW( scaledHeight, gl_round_down->integer ); - } - - if( image_desc.tflags & TF_SKYSIDE ) - { - // let people sample down the sky textures for speed - scaledWidth >>= r_skymip->integer; - scaledHeight >>= r_skymip->integer; - } - else if(!( image_desc.tflags & TF_NOPICMIP )) - { - // let people sample down the world textures for speed - scaledWidth >>= r_picmip->integer; - scaledHeight >>= r_picmip->integer; - } - - if( image_desc.tflags & TF_CUBEMAP ) - { - while( scaledWidth > glConfig.max_cubemap_texture_size || scaledHeight > glConfig.max_cubemap_texture_size ) - { - scaledWidth >>= 1; - scaledHeight >>= 1; - } - } - else - { - while( scaledWidth > glConfig.max_2d_texture_size || scaledHeight > glConfig.max_2d_texture_size ) - { - scaledWidth >>= 1; - scaledHeight >>= 1; - } - } - - if( scaledWidth < 1 ) scaledWidth = 1; - if( scaledHeight < 1 ) scaledHeight = 1; - - *width = scaledWidth; - *height = scaledHeight; -} - -/* -================= -R_BuildMipMap - -Operates in place, quartering the size of the texture -================= -*/ -static void R_BuildMipMap( byte *in, int width, int height, qboolean isNormalMap ) -{ - byte *out = in; - vec3_t normal; - int x, y; - - width <<= 2; - height >>= 1; - - if( isNormalMap ) - { - for( y = 0; y < height; y++, in += width ) - { - for( x = 0; x < width; x += 8, in += 8, out += 4 ) - { - normal[0] = (in[0] * (1.0/127) - 1.0) + (in[4] * (1.0/127) - 1.0) + (in[width+0] * (1.0/127) - 1.0) + (in[width+4] * (1.0/127) - 1.0); - normal[1] = (in[1] * (1.0/127) - 1.0) + (in[5] * (1.0/127) - 1.0) + (in[width+1] * (1.0/127) - 1.0) + (in[width+5] * (1.0/127) - 1.0); - normal[2] = (in[2] * (1.0/127) - 1.0) + (in[6] * (1.0/127) - 1.0) + (in[width+2] * (1.0/127) - 1.0) + (in[width+6] * (1.0/127) - 1.0); - - if( !VectorNormalizeLength( normal )) VectorSet( normal, 0.0, 0.0, 1.0 ); - - out[0] = (byte)(128 + 127 * normal[0]); - out[1] = (byte)(128 + 127 * normal[1]); - out[2] = (byte)(128 + 127 * normal[2]); - out[3] = 255; - } - } - } - else - { - for( y = 0; y < height; y++, in += width ) - { - for( x = 0; x < width; x += 8, in += 8, out += 4 ) - { - out[0] = (in[0] + in[4] + in[width+0] + in[width+4]) >> 2; - out[1] = (in[1] + in[5] + in[width+1] + in[width+5]) >> 2; - out[2] = (in[2] + in[6] + in[width+2] + in[width+6]) >> 2; - out[3] = (in[3] + in[7] + in[width+3] + in[width+7]) >> 2; - } - } - } -} - -/* -================= -R_ResampleTexture -================= -*/ -static void R_ResampleTexture( const byte *source, int inWidth, int inHeight, int outWidth, int outHeight, qboolean isNormalMap ) -{ - uint frac, fracStep; - uint *in = (uint *)source; - uint p1[0x1000], p2[0x1000]; - byte *pix1, *pix2, *pix3, *pix4; - uint *out = (uint *)image_desc.scaled; - uint *inRow1, *inRow2; - vec3_t normal; - int i, x, y; - - fracStep = inWidth * 0x10000 / outWidth; - - frac = fracStep >> 2; - for( i = 0; i < outWidth; i++ ) - { - p1[i] = 4 * (frac >> 16); - frac += fracStep; - } - - frac = (fracStep >> 2) * 3; - for( i = 0; i < outWidth; i++ ) - { - p2[i] = 4 * (frac >> 16); - frac += fracStep; - } - - if( isNormalMap ) - { - for( y = 0; y < outHeight; y++, out += outWidth ) - { - inRow1 = in + inWidth * (int)(((float)y + 0.25) * inHeight/outHeight); - inRow2 = in + inWidth * (int)(((float)y + 0.75) * inHeight/outHeight); - - for( x = 0; x < outWidth; x++ ) - { - pix1 = (byte *)inRow1 + p1[x]; - pix2 = (byte *)inRow1 + p2[x]; - pix3 = (byte *)inRow2 + p1[x]; - pix4 = (byte *)inRow2 + p2[x]; - - normal[0] = (pix1[0] * (1.0/127) - 1.0) + (pix2[0] * (1.0/127) - 1.0) + (pix3[0] * (1.0/127) - 1.0) + (pix4[0] * (1.0/127) - 1.0); - normal[1] = (pix1[1] * (1.0/127) - 1.0) + (pix2[1] * (1.0/127) - 1.0) + (pix3[1] * (1.0/127) - 1.0) + (pix4[1] * (1.0/127) - 1.0); - normal[2] = (pix1[2] * (1.0/127) - 1.0) + (pix2[2] * (1.0/127) - 1.0) + (pix3[2] * (1.0/127) - 1.0) + (pix4[2] * (1.0/127) - 1.0); - - if( !VectorNormalizeLength( normal )) VectorSet( normal, 0.0, 0.0, 1.0 ); - - ((byte *)(out+x))[0] = (byte)(128 + 127 * normal[0]); - ((byte *)(out+x))[1] = (byte)(128 + 127 * normal[1]); - ((byte *)(out+x))[2] = (byte)(128 + 127 * normal[2]); - ((byte *)(out+x))[3] = 255; - } - } - } - else - { - for( y = 0; y < outHeight; y++, out += outWidth ) - { - inRow1 = in + inWidth * (int)(((float)y + 0.25) * inHeight/outHeight); - inRow2 = in + inWidth * (int)(((float)y + 0.75) * inHeight/outHeight); - - for( x = 0; x < outWidth; x++ ) - { - pix1 = (byte *)inRow1 + p1[x]; - pix2 = (byte *)inRow1 + p2[x]; - pix3 = (byte *)inRow2 + p1[x]; - pix4 = (byte *)inRow2 + p2[x]; - - ((byte *)(out+x))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2; - ((byte *)(out+x))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2; - ((byte *)(out+x))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2; - ((byte *)(out+x))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3]) >> 2; - } - } - } -} - -/* -=============== -R_GetPixelFormat - -filled additional info -=============== -*/ -qboolean R_GetPixelFormat( const char *name, rgbdata_t *pic, uint tex_flags ) -{ - int w, h, s; - size_t totalsize = 0; - - if( !pic ) return false; // pass images with NULL buffer (e.g. shadowmaps, portalmaps ) - Mem_EmptyPool( r_imagepool ); // flush buffers - Mem_Set( &image_desc, 0, sizeof( image_desc )); - - image_desc.bpp = PFDesc( pic->type )->bpp; - image_desc.glFormat = PFDesc( pic->type )->glFormat; - image_desc.format = pic->type; - image_desc.numSides = 1; - - image_desc.texTarget = image_desc.glTarget = GL_TEXTURE_2D; - image_desc.width = w = pic->width; - image_desc.height = h = pic->height; - image_desc.flags = pic->flags; - image_desc.tflags = tex_flags; - image_desc.glSamples = R_GetSamples( image_desc.flags ); - - // now correct buffer size - totalsize = w * h * image_desc.bpp; - - if( image_desc.tflags & TF_DEPTHMAP ) - { - image_desc.glFormat = GL_DEPTH_COMPONENT; - } - else if( image_desc.tflags & TF_CUBEMAP ) - { - if( GL_Support( R_TEXTURECUBEMAP_EXT )) - { - if( pic->flags & IMAGE_CUBEMAP ) - { - image_desc.numSides = 6; - image_desc.glTarget = GL_TEXTURE_CUBE_MAP_ARB; - image_desc.texTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; - } - else - { - MsgDev( D_WARN, "R_GetPixelFormat: %s it's not a cubemap image\n", name ); - image_desc.tflags &= ~TF_CUBEMAP; - } - } - else - { - MsgDev( D_WARN, "R_GetPixelFormat: cubemaps isn't supported, %s ignored\n", name ); - image_desc.tflags &= ~TF_CUBEMAP; - } - } - - image_desc.pal = pic->palette; - - // check for permanent images - if( image_desc.tflags & TF_NOPICMIP ) - image_desc.tflags |= TF_STATIC; - - // restore temp dimensions - w = image_desc.width; - h = image_desc.height; - s = w * h; - - // apply texture type (R_ShowTextures uses it) - if( image_desc.tflags & TF_LIGHTMAP ) - image_desc.texType = TEX_LIGHTMAP; - else if( image_desc.tflags & (TF_NOPICMIP|TF_NOMIPMAP)) - image_desc.texType = TEX_NOMIP; - else if( image_desc.tflags & TF_SKYSIDE ) - image_desc.texType = TEX_SKYBOX; - else if( image_desc.flags & IMAGE_HAS_ALPHA ) - image_desc.texType = TEX_ALPHA; - else image_desc.texType = TEX_GENERIC; - - // calc immediate buffers - R_RoundImageDimensions( &w, &h, false ); - - image_desc.source = Mem_Alloc( r_imagepool, s * 4 ); // source buffer - image_desc.scaled = Mem_Alloc( r_imagepool, w * h * 4 ); // scaled buffer - totalsize *= image_desc.numSides; - - if( totalsize != pic->size ) // sanity check - { - MsgDev( D_ERROR, "R_GetPixelFormat: %s has invalid size (%i should be %i)\n", name, pic->size, totalsize ); - return false; - } - if( s&3 ) - { - // will be resample, just tell me for debug targets - MsgDev( D_NOTE, "R_GetPixelFormat: %s s&3 [%d x %d]\n", name, image_desc.width, image_desc.height ); - } - return true; -} - -/* -=============== -R_SetPixelFormat - -prepare image to upload in video memory -=============== -*/ -void R_SetPixelFormat( int width, int height ) -{ - image_desc.bpp = PFDesc( image_desc.format )->bpp; - - if( image_desc.tflags & TF_DEPTHMAP ) - image_desc.glFormat = GL_DEPTH_COMPONENT; - else image_desc.glFormat = PFDesc( image_desc.format )->glFormat; - - image_desc.width = width; - image_desc.height = height; - image_desc.SizeOfFile = width * height * image_desc.bpp; -} - -rgbdata_t *R_ForceImageToRGBA( rgbdata_t *pic ) -{ - // no need additional check - image lib make it self - Image_Process( &pic, 0, 0, IMAGE_FORCE_RGBA ); - return pic; -} - -/* -======================================================================= - - IMAGE PROGRAM FUNCTIONS - -======================================================================= -*/ -/* -================= -R_AddImages - -Adds the given images together -================= -*/ -static rgbdata_t *R_AddImages( rgbdata_t *in1, rgbdata_t *in2 ) -{ - rgbdata_t *out; - int width, height; - int r, g, b, a; - int x, y; - - // make sure what we processing RGBA images - in1 = R_ForceImageToRGBA( in1 ); - in2 = R_ForceImageToRGBA( in2 ); - width = in1->width, height = in1->height; - out = in1; - - for( y = 0; y < height; y++ ) - { - for( x = 0; x < width; x++ ) - { - r = in1->buffer[4*(y*width+x)+0] + in2->buffer[4*(y*width+x)+0]; - g = in1->buffer[4*(y*width+x)+1] + in2->buffer[4*(y*width+x)+1]; - b = in1->buffer[4*(y*width+x)+2] + in2->buffer[4*(y*width+x)+2]; - a = in1->buffer[4*(y*width+x)+3] + in2->buffer[4*(y*width+x)+3]; - out->buffer[4*(y*width+x)+0] = bound( 0, r, 255 ); - out->buffer[4*(y*width+x)+1] = bound( 0, g, 255 ); - out->buffer[4*(y*width+x)+2] = bound( 0, b, 255 ); - out->buffer[4*(y*width+x)+3] = bound( 0, a, 255 ); - } - } - FS_FreeImage( in2 ); - - return out; -} - -/* -================= -R_MultiplyImages - -Multiplies the given images -================= -*/ -static rgbdata_t *R_MultiplyImages( rgbdata_t *in1, rgbdata_t *in2 ) -{ - rgbdata_t *out; - int width, height; - int r, g, b, a; - int x, y; - - // make sure what we processing RGBA images - in1 = R_ForceImageToRGBA( in1 ); - in2 = R_ForceImageToRGBA( in2 ); - width = in1->width, height = in1->height; - out = in1; - - for( y = 0; y < height; y++ ) - { - for( x = 0; x < width; x++ ) - { - r = in1->buffer[4*(y*width+x)+0] * (in2->buffer[4*(y*width+x)+0] * (1.0/255)); - g = in1->buffer[4*(y*width+x)+1] * (in2->buffer[4*(y*width+x)+1] * (1.0/255)); - b = in1->buffer[4*(y*width+x)+2] * (in2->buffer[4*(y*width+x)+2] * (1.0/255)); - a = in1->buffer[4*(y*width+x)+3] * (in2->buffer[4*(y*width+x)+3] * (1.0/255)); - out->buffer[4*(y*width+x)+0] = bound( 0, r, 255 ); - out->buffer[4*(y*width+x)+1] = bound( 0, g, 255 ); - out->buffer[4*(y*width+x)+2] = bound( 0, b, 255 ); - out->buffer[4*(y*width+x)+3] = bound( 0, a, 255 ); - } - } - FS_FreeImage( in2 ); - - return out; -} - -/* -================= -R_BiasImage - -Biases the given image -================= -*/ -static rgbdata_t *R_BiasImage( rgbdata_t *in, const vec4_t bias ) -{ - rgbdata_t *out; - int width, height; - int r, g, b, a; - int x, y; - - // make sure what we processing RGBA image - in = R_ForceImageToRGBA( in ); - width = in->width, height = in->height; - out = in; - - for( y = 0; y < height; y++ ) - { - for( x = 0; x < width; x++ ) - { - r = in->buffer[4*(y*width+x)+0] + (255 * bias[0]); - g = in->buffer[4*(y*width+x)+1] + (255 * bias[1]); - b = in->buffer[4*(y*width+x)+2] + (255 * bias[2]); - a = in->buffer[4*(y*width+x)+3] + (255 * bias[3]); - out->buffer[4*(y*width+x)+0] = bound( 0, r, 255 ); - out->buffer[4*(y*width+x)+1] = bound( 0, g, 255 ); - out->buffer[4*(y*width+x)+2] = bound( 0, b, 255 ); - out->buffer[4*(y*width+x)+3] = bound( 0, a, 255 ); - } - } - return out; -} - -/* -================= -R_ScaleImage - -Scales the given image -================= -*/ -static rgbdata_t *R_ScaleImage( rgbdata_t *in, const vec4_t scale ) -{ - rgbdata_t *out; - int width, height; - int r, g, b, a; - int x, y; - - // make sure what we processing RGBA image - in = R_ForceImageToRGBA( in ); - width = in->width, height = in->height; - out = in; - - for( y = 0; y < height; y++ ) - { - for( x = 0; x < width; x++ ) - { - r = in->buffer[4*(y*width+x)+0] * scale[0]; - g = in->buffer[4*(y*width+x)+1] * scale[1]; - b = in->buffer[4*(y*width+x)+2] * scale[2]; - a = in->buffer[4*(y*width+x)+3] * scale[3]; - out->buffer[4*(y*width+x)+0] = bound( 0, r, 255 ); - out->buffer[4*(y*width+x)+1] = bound( 0, g, 255 ); - out->buffer[4*(y*width+x)+2] = bound( 0, b, 255 ); - out->buffer[4*(y*width+x)+3] = bound( 0, a, 255 ); - } - } - return out; -} - -/* -================= -R_InvertColor - -Inverts the color channels of the given image -================= -*/ -static rgbdata_t *R_InvertColor( rgbdata_t *in ) -{ - rgbdata_t *out; - int width, height; - int x, y; - - // make sure what we processing RGBA image - in = R_ForceImageToRGBA( in ); - width = in->width, height = in->height; - out = in; - - for( y = 0; y < height; y++ ) - { - for( x = 0; x < width; x++ ) - { - out->buffer[4*(y*width+x)+0] = 255 - in->buffer[4*(y*width+x)+0]; - out->buffer[4*(y*width+x)+1] = 255 - in->buffer[4*(y*width+x)+1]; - out->buffer[4*(y*width+x)+2] = 255 - in->buffer[4*(y*width+x)+2]; - } - } - return out; -} - -/* -================= -R_InvertAlpha - -Inverts the alpha channel of the given image -================= -*/ -static rgbdata_t *R_InvertAlpha( rgbdata_t *in ) -{ - rgbdata_t *out; - int width, height; - int x, y; - - // make sure what we processing RGBA image - in = R_ForceImageToRGBA( in ); - width = in->width, height = in->height; - out = in; - - for( y = 0; y < height; y++ ) - { - for( x = 0; x < width; x++ ) - out->buffer[4*(y*width+x)+3] = 255 - in->buffer[4*(y*width+x)+3]; - } - return out; -} - -/* -================= -R_MakeIntensity - -Converts the given image to intensity -================= -*/ -static rgbdata_t *R_MakeIntensity( rgbdata_t *in ) -{ - rgbdata_t *out; - int width, height; - byte intensity; - float r, g, b; - int x, y; - - // make sure what we processing RGBA image - in = R_ForceImageToRGBA( in ); - width = in->width, height = in->height; - out = in; - - for( y = 0; y < height; y++ ) - { - for( x = 0; x < width; x++ ) - { - r = r_luminanceTable[in->buffer[4*(y*width+x)+0]][0]; - g = r_luminanceTable[in->buffer[4*(y*width+x)+1]][1]; - b = r_luminanceTable[in->buffer[4*(y*width+x)+2]][2]; - - intensity = (byte)(r + g + b); - - out->buffer[4*(y*width+x)+0] = intensity; - out->buffer[4*(y*width+x)+1] = intensity; - out->buffer[4*(y*width+x)+2] = intensity; - out->buffer[4*(y*width+x)+3] = intensity; - } - } - return out; -} - -/* -================= -R_MakeLuminance - -Converts the given image to luminance -================= -*/ -static rgbdata_t *R_MakeLuminance( rgbdata_t *in ) -{ - rgbdata_t *out; - int width, height; - byte luminance; - float r, g, b; - int x, y; - - // make sure what we processing RGBA image - in = R_ForceImageToRGBA( in ); - width = in->width, height = in->height; - out = in; - - for( y = 0; y < height; y++ ) - { - for( x = 0; x < width; x++ ) - { - r = r_luminanceTable[in->buffer[4*(y*width+x)+0]][0]; - g = r_luminanceTable[in->buffer[4*(y*width+x)+1]][1]; - b = r_luminanceTable[in->buffer[4*(y*width+x)+2]][2]; - - luminance = (byte)(r + g + b); - - out->buffer[4*(y*width+x)+0] = luminance; - out->buffer[4*(y*width+x)+1] = luminance; - out->buffer[4*(y*width+x)+2] = luminance; - out->buffer[4*(y*width+x)+3] = in->buffer[4*(y*width+x)+3]; // copy alpha as is - } - } - return out; -} - -/* -================= -R_MakeGlow - -Converts the given image to glow (LUMA) -================= -*/ -static rgbdata_t *R_MakeGlow( rgbdata_t *in ) -{ - rgbdata_t *out; - int width, height; - byte r, g, b; - int x, y; - - // make sure what we processing RGBA image - in = R_ForceImageToRGBA( in ); - width = in->width, height = in->height; - out = in; - - for( y = 0; y < height; y++ ) - { - for( x = 0; x < width; x++ ) - { - r = r_glowTable[in->buffer[4*(y*width+x)+0]][0]; - g = r_glowTable[in->buffer[4*(y*width+x)+1]][1]; - b = r_glowTable[in->buffer[4*(y*width+x)+2]][2]; - - out->buffer[4*(y*width+x)+0] = r; - out->buffer[4*(y*width+x)+1] = g; - out->buffer[4*(y*width+x)+2] = b; - out->buffer[4*(y*width+x)+3] = 255; // kill alpha if any - } - } - return out; -} - -static rgbdata_t *R_MakeImageBlock( rgbdata_t *in , int block[4] ) -{ - byte *fin, *out; - int i, x, y, xl, yl, xh, yh, w, h; - int linedelta; - - // make sure what we processing RGBA image - in = R_ForceImageToRGBA( in ); - - xl = block[0]; - yl = block[1]; - w = block[2]; - h = block[3]; - xh = xl + w; - yh = yl + h; - - image_desc.source = Mem_Realloc( r_temppool, image_desc.source, w * h * 4 ); - out = image_desc.source; - - fin = in->buffer + (yl * in->width + xl) * 4; - linedelta = (in->width - w) * 4; - - // cut block from source - for( y = yl; y < yh; y++ ) - { - for( x = xl; x < xh; x++ ) - for( i = 0; i < 4; i++ ) - *out++ = *fin++; - fin += linedelta; - } - - // copy result back - in->buffer = Mem_Realloc( r_temppool, in->buffer, w * h * 4 ); - Mem_Copy( in->buffer, image_desc.source, w * h * 4 ); - in->size = w * h * 4; - in->height = h; - in->width = w; - - return in; -} - -/* -================= -R_MakeAlpha - -Converts the given image to alpha -================= -*/ -static rgbdata_t *R_MakeAlpha( rgbdata_t *in ) -{ - rgbdata_t *out; - int width, height; - byte alpha; - float r, g, b; - int x, y; - - // make sure what we processing RGBA image - in = R_ForceImageToRGBA( in ); - width = in->width, height = in->height; - out = in; - - for( y = 0; y < height; y++ ) - { - for( x = 0; x < width; x++ ) - { - r = r_luminanceTable[in->buffer[4*(y*width+x)+0]][0]; - g = r_luminanceTable[in->buffer[4*(y*width+x)+1]][1]; - b = r_luminanceTable[in->buffer[4*(y*width+x)+2]][2]; - - alpha = (byte)(r + g + b); - - out->buffer[4*(y*width+x)+0] = 255; - out->buffer[4*(y*width+x)+1] = 255; - out->buffer[4*(y*width+x)+2] = 255; - out->buffer[4*(y*width+x)+3] = alpha; - } - } - return out; -} - -/* -================= -R_HeightMap - -Converts the given height map to a normal map -================= -*/ -static rgbdata_t *R_HeightMap( rgbdata_t *in, float bumpScale ) -{ - byte *out; - int width, height; - vec3_t normal; - float r, g, b; - float c, cx, cy; - int x, y; - - // make sure what we processing RGBA image - in = R_ForceImageToRGBA( in ); - width = in->width, height = in->height; - out = image_desc.source = Mem_Realloc( r_temppool, image_desc.source, width * height * 4 ); - - if( !bumpScale ) bumpScale = 1.0f; - bumpScale *= max( 0, r_lighting_bumpscale->value ); - - for( y = 0; y < height; y++ ) - { - for( x = 0; x < width; x++ ) - { - r = r_luminanceTable[in->buffer[4*(y*width+x)+0]][0]; - g = r_luminanceTable[in->buffer[4*(y*width+x)+1]][1]; - b = r_luminanceTable[in->buffer[4*(y*width+x)+2]][2]; - - c = (r + g + b) * (1.0/255); - - r = r_luminanceTable[in->buffer[4*(y*width+((x+1)%width))+0]][0]; - g = r_luminanceTable[in->buffer[4*(y*width+((x+1)%width))+1]][1]; - b = r_luminanceTable[in->buffer[4*(y*width+((x+1)%width))+2]][2]; - - cx = (r + g + b) * (1.0/255); - - r = r_luminanceTable[in->buffer[4*(((y+1)%height)*width+x)+0]][0]; - g = r_luminanceTable[in->buffer[4*(((y+1)%height)*width+x)+1]][1]; - b = r_luminanceTable[in->buffer[4*(((y+1)%height)*width+x)+2]][2]; - - cy = (r + g + b) * (1.0/255); - - normal[0] = (c - cx) * bumpScale; - normal[1] = (c - cy) * bumpScale; - normal[2] = 1.0; - - if(!VectorNormalizeLength( normal )) VectorSet( normal, 0.0f, 0.0f, 1.0f ); - out[4*(y*width+x)+0] = (byte)(128 + 127 * normal[0]); - out[4*(y*width+x)+1] = (byte)(128 + 127 * normal[1]); - out[4*(y*width+x)+2] = (byte)(128 + 127 * normal[2]); - out[4*(y*width+x)+3] = 255; - } - } - - // copy result back - Mem_Copy( in->buffer, out, width * height * 4 ); - - return in; -} - -/* -================= -R_AddNormals - -Adds the given normal maps together -================= -*/ -static rgbdata_t *R_AddNormals( rgbdata_t *in1, rgbdata_t *in2 ) -{ - byte *out; - int width, height; - vec3_t normal; - int x, y; - - // make sure what we processing RGBA images - in1 = R_ForceImageToRGBA( in1 ); - in2 = R_ForceImageToRGBA( in2 ); - width = in1->width, height = in1->height; - out = image_desc.source; - - for( y = 0; y < height; y++ ) - { - for( x = 0; x < width; x++ ) - { - normal[0] = (in1->buffer[4*(y*width+x)+0] * (1.0/127) - 1.0) + (in2->buffer[4*(y*width+x)+0] * (1.0/127) - 1.0); - normal[1] = (in1->buffer[4*(y*width+x)+1] * (1.0/127) - 1.0) + (in2->buffer[4*(y*width+x)+1] * (1.0/127) - 1.0); - normal[2] = (in1->buffer[4*(y*width+x)+2] * (1.0/127) - 1.0) + (in2->buffer[4*(y*width+x)+2] * (1.0/127) - 1.0); - - if(!VectorNormalizeLength( normal )) VectorSet( normal, 0.0f, 0.0f, 1.0f ); - - out[4*(y*width+x)+0] = (byte)(128 + 127 * normal[0]); - out[4*(y*width+x)+1] = (byte)(128 + 127 * normal[1]); - out[4*(y*width+x)+2] = (byte)(128 + 127 * normal[2]); - out[4*(y*width+x)+3] = 255; - } - } - - // copy result back - Mem_Copy( in1->buffer, out, width * height * 4 ); - FS_FreeImage( in2 ); - - return in1; -} - -/* -================= -R_SmoothNormals - -Smoothes the given normal map -================= -*/ -static rgbdata_t *R_SmoothNormals( rgbdata_t *in ) -{ - byte *out; - int width, height; - uint frac, fracStep; - uint p1[0x1000], p2[0x1000]; - byte *pix1, *pix2, *pix3, *pix4; - uint *inRow1, *inRow2; - vec3_t normal; - int i, x, y; - - // make sure what we processing RGBA image - in = R_ForceImageToRGBA( in ); - width = in->width, height = in->height; - out = image_desc.source; - - fracStep = 0x10000; - frac = fracStep>>2; - for( i = 0; i < width; i++ ) - { - p1[i] = 4 * (frac>>16); - frac += fracStep; - } - - frac = (fracStep>>2) * 3; - for( i = 0; i < width; i++ ) - { - p2[i] = 4 * (frac>>16); - frac += fracStep; - } - - for( y = 0; y < height; y++ ) - { - inRow1 = (uint *)in->buffer + width * (int)((float)y + 0.25); - inRow2 = (uint *)in->buffer + width * (int)((float)y + 0.75); - - for( x = 0; x < width; x++ ) - { - pix1 = (byte *)inRow1 + p1[x]; - pix2 = (byte *)inRow1 + p2[x]; - pix3 = (byte *)inRow2 + p1[x]; - pix4 = (byte *)inRow2 + p2[x]; - - normal[0] = (pix1[0] * (1.0/127) - 1.0) + (pix2[0] * (1.0/127) - 1.0) + (pix3[0] * (1.0/127) - 1.0) + (pix4[0] * (1.0/127) - 1.0); - normal[1] = (pix1[1] * (1.0/127) - 1.0) + (pix2[1] * (1.0/127) - 1.0) + (pix3[1] * (1.0/127) - 1.0) + (pix4[1] * (1.0/127) - 1.0); - normal[2] = (pix1[2] * (1.0/127) - 1.0) + (pix2[2] * (1.0/127) - 1.0) + (pix3[2] * (1.0/127) - 1.0) + (pix4[2] * (1.0/127) - 1.0); - - if( !VectorNormalizeLength( normal )) VectorSet( normal, 0.0f, 0.0f, 1.0f ); - out[4*(y*width+x)+0] = (byte)(128 + 127 * normal[0]); - out[4*(y*width+x)+1] = (byte)(128 + 127 * normal[1]); - out[4*(y*width+x)+2] = (byte)(128 + 127 * normal[2]); - out[4*(y*width+x)+3] = 255; - } - } - - // copy result back - Mem_Copy( in->buffer, out, width * height * 4 ); - - return in; -} - -/* -================ -R_IncludeDepthmap - -Write depthmap into alpha-channel the given normal map -================ -*/ -static rgbdata_t *R_IncludeDepthmap( rgbdata_t *in1, rgbdata_t *in2 ) -{ - int i; - byte *pic1, *pic2; - - // make sure what we processing RGBA images - in1 = R_ForceImageToRGBA( in1 ); - in2 = R_ForceImageToRGBA( in2 ); - - pic1 = in1->buffer; - pic2 = in2->buffer; - - for( i = (in1->width * in1->height) - 1; i > 0; i--, pic1 += 4, pic2 += 4 ) - { - if( in2->flags & IMAGE_HAS_COLOR ) - pic1[3] = ((int)pic2[0] + (int)pic2[1] + (int)pic2[2]) / 3; - else if( in2->flags & IMAGE_HAS_ALPHA ) - pic1[3] = pic2[3]; - else pic1[3] = pic2[0]; - } - - FS_FreeImage( in2 ); - in1->flags |= (IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA); - - return in1; -} - -/* -================ -R_ClearPixels - -clear specified area: color or alpha -================ -*/ -static rgbdata_t *R_ClearPixels( rgbdata_t *in, qboolean clearAlpha ) -{ - int i; - byte *pic; - - // make sure what we processing RGBA images - in = R_ForceImageToRGBA( in ); - pic = in->buffer; - - if( clearAlpha ) - { - for( i = 0; i < in->width * in->height && in->flags & IMAGE_HAS_ALPHA; i++ ) - pic[(i<<2)+3] = 0xFF; - } - else - { - // clear color or greyscale image otherwise - for( i = 0; i < in->width * in->height; i++ ) - pic[(i<<2)+0] = pic[(i<<2)+1] = pic[(i<<2)+2] = 0xFF; - } - return in; -} - - -/* -================= -R_ParseAdd -================= -*/ -static rgbdata_t *R_ParseAdd( script_t *script, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic1, *pic2; - int samples1, samples2; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp(token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'add'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'add'\n" ); - return NULL; - } - - pic1 = R_LoadImage( script, token.string, NULL, 0, &samples1, flags ); - if( !pic1 ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "," )) - { - MsgDev( D_WARN, "expected ',', found '%s' instead for 'add'\n", token.string ); - FS_FreeImage( pic1 ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'add'\n" ); - FS_FreeImage( pic1 ); - return NULL; - } - - pic2 = R_LoadImage( script, token.string, NULL, 0, &samples2, flags ); - if( !pic2 ) - { - FS_FreeImage( pic1 ); - return NULL; - } - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'add'\n", token.string ); - FS_FreeImage( pic1 ); - FS_FreeImage( pic2 ); - return NULL; - } - - if( pic1->width != pic2->width || pic1->height != pic2->height ) - { - MsgDev( D_WARN, "images for 'add' have mismatched dimensions [%ix%i] != [%ix%i]\n", - pic1->width, pic1->height, pic2->width, pic2->height ); - - FS_FreeImage( pic1 ); - FS_FreeImage( pic2 ); - return NULL; - } - - *samples = R_SetSamples( samples1, samples2 ); - if( *samples != 1 ) - { - *flags &= ~TF_INTENSITY; - *flags &= ~TF_ALPHA; - } - return R_AddImages( pic1, pic2 ); -} - -/* -================= -R_ParseMultiply -================= -*/ -static rgbdata_t *R_ParseMultiply( script_t *script, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic1, *pic2; - int samples1, samples2; - - Com_ReadToken( script, 0, &token ); - - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'multiply'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'multiply'\n" ); - return NULL; - } - - pic1 = R_LoadImage( script, token.string, NULL, 0, &samples1, flags ); - if( !pic1 ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "," )) - { - MsgDev( D_WARN, "expected ',', found '%s' instead for 'multiply'\n", token.string ); - FS_FreeImage( pic1 ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'multiply'\n" ); - FS_FreeImage( pic1 ); - return NULL; - } - - pic2 = R_LoadImage( script, token.string, NULL, 0, &samples2, flags ); - if( !pic2 ) - { - FS_FreeImage( pic1 ); - return NULL; - } - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'multiply'\n", token.string ); - - FS_FreeImage( pic1 ); - FS_FreeImage( pic2 ); - return NULL; - } - - if( pic1->width != pic2->width || pic1->height != pic2->height ) - { - MsgDev( D_WARN, "images for 'multiply' have mismatched dimensions [%ix%i] != [%ix%i]\n", - pic1->width, pic1->height, pic2->width, pic2->height ); - - FS_FreeImage( pic1 ); - FS_FreeImage( pic2 ); - return NULL; - } - - *samples = R_SetSamples( samples1, samples2 ); - - if( *samples != 1 ) - { - *flags &= ~TF_INTENSITY; - *flags &= ~TF_ALPHA; - } - return R_MultiplyImages( pic1, pic2 ); -} - -/* -================= -R_ParseBias -================= -*/ -static rgbdata_t *R_ParseBias( script_t *script, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - vec4_t bias; - int i; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'bias'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'bias'\n" ); - return NULL; - } - - pic = R_LoadImage( script, token.string, NULL, 0, samples, flags ); - if( !pic ) return NULL; - - for( i = 0; i < 4; i++ ) - { - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "," )) - { - MsgDev( D_WARN, "expected ',', found '%s' instead for 'bias'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - - if( !Com_ReadFloat( script, 0, &bias[i] )) - { - MsgDev( D_WARN, "missing parameters for 'bias'\n" ); - FS_FreeImage( pic ); - return NULL; - } - } - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'bias'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - - if( *samples < 3 ) *samples += 2; - *flags &= ~TF_INTENSITY; - *flags &= ~TF_ALPHA; - - return R_BiasImage( pic, bias ); -} - -/* -================= -R_ParseScale -================= -*/ -static rgbdata_t *R_ParseScale( script_t *script, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - vec4_t scale; - int i; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'scale'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &token )) - { - MsgDev( D_WARN, "missing parameters for 'scale'\n" ); - return NULL; - } - - pic = R_LoadImage( script, token.string, NULL, 0, samples, flags ); - if( !pic ) return NULL; - - for( i = 0; i < 4; i++ ) - { - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "," )) - { - MsgDev( D_WARN, "expected ',', found '%s' instead for 'scale'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - - if( !Com_ReadFloat( script, 0, &scale[i] )) - { - MsgDev( D_WARN, "missing parameters for 'scale'\n" ); - FS_FreeImage( pic ); - return NULL; - } - } - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'scale'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - - if( *samples < 3 ) *samples += 2; - *flags &= ~TF_INTENSITY; - *flags &= ~TF_ALPHA; - - return R_ScaleImage( pic, scale ); -} - -/* -================= -R_ParseInvertColor -================= -*/ -static rgbdata_t *R_ParseInvertColor( script_t *script, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'invertColor'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'invertColor'\n" ); - return NULL; - } - - pic = R_LoadImage( script, token.string, NULL, 0, samples, flags ); - if( !pic ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'invertColor'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - return R_InvertColor( pic ); -} - -/* -================= -R_ParseInvertAlpha -================= -*/ -static rgbdata_t *R_ParseInvertAlpha( script_t *script, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'invertAlpha'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'invertAlpha'\n" ); - return NULL; - } - - pic = R_LoadImage( script, token.string, NULL, 0, samples, flags ); - if( !pic ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'invertAlpha'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - return R_InvertAlpha( pic ); -} - -/* -================= -R_ParseMakeIntensity -================= -*/ -static rgbdata_t *R_ParseMakeIntensity( script_t *script, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'makeIntensity'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'makeIntensity'\n" ); - return NULL; - } - - pic = R_LoadImage( script, token.string, NULL, 0, samples, flags ); - if( !pic ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'makeIntensity'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - - *samples = 1; - *flags |= TF_INTENSITY; - *flags &= ~TF_ALPHA; - *flags &= ~TF_NORMALMAP; - - return R_MakeIntensity( pic ); -} - -/* -================= -R_ParseMakeLuminance -================= -*/ -static rgbdata_t *R_ParseMakeLuminance( script_t *script, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'makeLuminance'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'makeLuminance'\n" ); - return NULL; - } - - pic = R_LoadImage( script, token.string, NULL, 0, samples, flags ); - if( !pic ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'makeLuminance'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - - *samples = (pic->flags & IMAGE_HAS_ALPHA) ? 2 : 1; - *flags &= ~TF_INTENSITY; - *flags &= ~TF_ALPHA; - *flags &= ~TF_NORMALMAP; - - return R_MakeLuminance( pic ); -} - -/* -================= -R_ParseMakeAlpha -================= -*/ -static rgbdata_t *R_ParseMakeAlpha( script_t *script, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'makeAlpha'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'makeAlpha'\n" ); - return NULL; - } - - pic = R_LoadImage( script, token.string, NULL, 0, samples, flags ); - if( !pic ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'makeAlpha'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - - *samples = 1; - *flags &= ~TF_INTENSITY; - *flags |= TF_ALPHA; - *flags &= ~TF_NORMALMAP; - - return R_MakeAlpha( pic ); -} - -/* -================= -R_ParseMakeGlow -================= -*/ -static rgbdata_t *R_ParseMakeGlow( script_t *script, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'makeGlow'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &token )) - { - MsgDev( D_WARN, "missing parameters for 'makeGlow'\n" ); - return NULL; - } - - pic = R_LoadImage( script, token.string, NULL, 0, samples, flags ); - if( !pic ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'makeGlow'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - - *samples = 3; - - return R_MakeGlow( pic ); -} - -static rgbdata_t *R_ParseStudioSkin( script_t *script, const byte *buf, size_t size, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - string model_path; - string modelT_path; - string skinname; - studiohdr_t hdr; - file_t *f; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'Studio'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &token )) - { - MsgDev( D_WARN, "missing parameters for 'Studio'\n" ); - return NULL; - } - - // NOTE: studio skin show as 'models/props/flame1.mdl/flame2a.bmp' - FS_ExtractFilePath( token.string, model_path ); - FS_StripExtension( model_path ); - com.snprintf( modelT_path, MAX_STRING, "%sT.mdl", model_path ); - FS_DefaultExtension( model_path, ".mdl" ); - FS_FileBase( token.string, skinname ); - - if( buf && size ) - { - // load it in - pic = R_LoadImage( script, va( "#%s.mdl", skinname ), buf, size, samples, flags ); - if( !pic ) return NULL; - goto studio_done; - } - FS_DefaultExtension( skinname, ".bmp" ); - f = FS_Open( model_path, "rb" ); - if( !f ) - { - MsgDev( D_WARN, "'Studio' can't find studiomodel %s\n", model_path ); - return NULL; - } - if( FS_Read( f, &hdr, sizeof( hdr )) != sizeof( hdr )) - { - MsgDev( D_WARN, "'Studio' %s probably corrupted\n", model_path ); - FS_Close( f ); - return NULL; - } - - if( hdr.numtextures == 0 ) - { - // textures are keep seperate - FS_Close( f ); - f = FS_Open( modelT_path, "rb" ); - if( !f ) - { - MsgDev( D_WARN, "'Studio' can't find studiotextures %s\n", modelT_path ); - return NULL; - } - if( FS_Read( f, &hdr, sizeof( hdr )) != sizeof( hdr )) - { - MsgDev( D_WARN, "'Studio' %s probably corrupted\n", modelT_path ); - FS_Close( f ); - return NULL; - } - } - - if( hdr.textureindex > 0 && hdr.numtextures <= MAXSTUDIOSKINS ) - { - // all ok, can load model into memory - mstudiotexture_t *ptexture, *tex; - size_t mdl_size, tex_size; - byte *pin; - int i; - - FS_Seek( f, 0, SEEK_END ); - mdl_size = FS_Tell( f ); - FS_Seek( f, 0, SEEK_SET ); - - pin = Mem_Alloc( r_imagepool, mdl_size ); - if( FS_Read( f, pin, mdl_size ) != mdl_size ) - { - MsgDev( D_WARN, "'Studio' %s probably corrupted\n", model_path ); - Mem_Free( pin ); - FS_Close( f ); - return NULL; - } - ptexture = (mstudiotexture_t *)(pin + hdr.textureindex); - - // find specified texture - for( i = 0; i < hdr.numtextures; i++ ) - { - if( !com.stricmp( ptexture[i].name, skinname )) - break; // found - } - if( i == hdr.numtextures ) - { - MsgDev( D_WARN, "'Studio' %s doesn't have skin %s\n", model_path, skinname ); - Mem_Free( pin ); - FS_Close( f ); - return NULL; - } - tex = ptexture + i; - - // NOTE: replace index with pointer to start of imagebuffer, ImageLib expected it - tex->index = (int)pin + tex->index; - tex_size = sizeof( mstudiotexture_t ) + tex->width * tex->height + 768; - - // load studio texture and bind it - FS_FileBase( skinname, skinname ); - - // load it in - pic = R_LoadImage( script, va( "#%s.mdl", tex->name ), (byte *)tex, tex_size, samples, flags ); - - // shutdown operations - Mem_Free( pin ); - FS_Close( f ); - - if( !pic ) return NULL; - } - else - { - MsgDev( D_WARN, "'Studio' %s has invalid skin count\n", model_path ); - FS_Close( f ); - return NULL; - } - -studio_done: - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'Studio'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - return pic; -} - -static rgbdata_t *R_ParseSpriteFrame( script_t *script, const byte *buf, size_t size, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'Sprite'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &token )) - { - MsgDev( D_WARN, "missing parameters for 'Sprite'\n" ); - return NULL; - } - - pic = R_LoadImage( script, va( "#%s.spr", token.string ), buf, size, samples, flags ); - if( !pic ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'Sprite'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - return pic; -} - -static rgbdata_t *R_ParseAliasSkin( script_t *script, const byte *buf, size_t size, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'Alias'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &token )) - { - MsgDev( D_WARN, "missing parameters for 'Alias'\n" ); - return NULL; - } - - pic = R_LoadImage( script, va( "#%s.mdl", token.string ), buf, size, samples, flags ); - if( !pic ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'Alias'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - return pic; -} - -/* -================= -R_ParseScrapBlock -================= -*/ -static rgbdata_t *R_ParseScrapBlock( script_t *script, int *samples, texFlags_t *flags ) -{ - int i, block[4]; - token_t token; - rgbdata_t *pic; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'scrapBlock'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &token )) - { - MsgDev( D_WARN, "missing parameters for 'scrapBlock'\n" ); - return NULL; - } - - pic = R_LoadImage( script, token.string, NULL, 0, samples, flags ); - if( !pic ) return NULL; - - for( i = 0; i < 4; i++ ) - { - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "," )) - { - MsgDev( D_WARN, "expected ',', found '%s' instead for 'rect'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - - if( !Com_ReadLong( script, 0, &block[i] )) - { - MsgDev( D_WARN, "missing parameters for 'block'\n" ); - FS_FreeImage( pic ); - return NULL; - } - if( block[i] < 0 ) - { - MsgDev( D_WARN, "invalid argument %i for 'block'\n", i+1 ); - FS_FreeImage( pic ); - return NULL; - } - if((i+1) & 1 && block[i] > pic->width ) - { - MsgDev( D_WARN, "invalid argument %i for 'block'\n", i+1 ); - FS_FreeImage( pic ); - return NULL; - } - if((i+1) & 2 && block[i] > pic->height ) - { - MsgDev( D_WARN, "invalid argument %i for 'block'\n", i+1 ); - FS_FreeImage( pic ); - return NULL; - } - } - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'bias'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - if((block[0] + block[2] > pic->width) || (block[1] + block[3] > pic->height)) - { - MsgDev( D_WARN, "'ScrapBlock' image size out of bounds\n" ); - FS_FreeImage( pic ); - return NULL; - } - - return R_MakeImageBlock( pic, block ); -} - -/* -================= -R_ParseHeightMap -================= -*/ -static rgbdata_t *R_ParseHeightMap( script_t *script, const byte *buf, size_t size, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - float scale; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'heightMap'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'heightMap'\n" ); - return NULL; - } - - pic = R_LoadImage( script, token.string, buf, size, samples, flags ); - if( !pic ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "," )) - { - MsgDev( D_WARN, "expected ',', found '%s' instead for 'heightMap'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - - if( !Com_ReadFloat( script, 0, &scale )) - { - MsgDev( D_WARN, "missing parameters for 'heightMap'\n" ); - FS_FreeImage( pic ); - return NULL; - } - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'heightMap'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - - *samples = 3; - *flags &= ~TF_INTENSITY; - *flags &= ~TF_ALPHA; - *flags |= TF_NORMALMAP; - - return R_HeightMap( pic, scale ); -} - -/* -================= -R_ParseAddNormals -================= -*/ -static rgbdata_t *R_ParseAddNormals( script_t *script, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic1, *pic2; - int samples1, samples2; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'addNormals'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'addNormals'\n" ); - return NULL; - } - - pic1 = R_LoadImage( script, token.string, NULL, 0, &samples1, flags ); - if( !pic1 ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "," )) - { - MsgDev( D_WARN, "expected ',', found '%s' instead for 'addNormals'\n", token.string ); - FS_FreeImage( pic1 ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'addNormals'\n" ); - FS_FreeImage( pic1 ); - return NULL; - } - - pic2 = R_LoadImage( script, token.string, NULL, 0, &samples2, flags ); - if( !pic2 ) - { - FS_FreeImage( pic1 ); - return NULL; - } - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'addNormals'\n", token.string ); - FS_FreeImage( pic1 ); - FS_FreeImage( pic2 ); - return NULL; - } - - if( pic1->width != pic2->width || pic1->height != pic2->height ) - { - MsgDev( D_WARN, "images for 'addNormals' have mismatched dimensions [%ix%i] != [%ix%i]\n", - pic1->width, pic1->height, pic2->width, pic2->height ); - FS_FreeImage( pic1 ); - FS_FreeImage( pic2 ); - return NULL; - } - - *samples = 3; - *flags &= ~TF_INTENSITY; - *flags &= ~TF_ALPHA; - *flags |= TF_NORMALMAP; - - return R_AddNormals( pic1, pic2 ); -} - -/* -================= -R_ParseSmoothNormals -================= -*/ -static rgbdata_t *R_ParseSmoothNormals( script_t *script, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'smoothNormals'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'smoothNormals'\n" ); - return NULL; - } - - pic = R_LoadImage( script, token.string, NULL, 0, samples, flags ); - if( !pic ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'smoothNormals'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - - *samples = 3; - *flags &= ~TF_INTENSITY; - *flags &= ~TF_ALPHA; - *flags |= TF_NORMALMAP; - - return R_SmoothNormals( pic ); -} - -/* -================= -R_ParseDepthmap -================= -*/ -static rgbdata_t *R_ParseDepthmap( script_t *script, const byte *buf, size_t size, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic1, *pic2; - int samples1, samples2; - - Com_ReadToken( script, 0, &token ); - - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'mergeDepthmap'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'mergeDepthmap'\n" ); - return NULL; - } - - pic1 = R_LoadImage( script, token.string, buf, size, &samples1, flags ); - if( !pic1 ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "," )) - { - MsgDev( D_WARN, "expected ',', found '%s' instead for 'mergeDepthmap'\n", token.string ); - FS_FreeImage( pic1 ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'mergeDepthmap'\n" ); - FS_FreeImage( pic1 ); - return NULL; - } - - *samples = 3; - pic2 = R_LoadImage( script, token.string, buf, size, &samples2, flags ); - if( !pic2 ) return pic1; // don't free normalmap - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'mergeDepthmap'\n", token.string ); - - FS_FreeImage( pic1 ); - FS_FreeImage( pic2 ); - return NULL; - } - - if( pic1->width != pic2->width || pic1->height != pic2->height ) - { - MsgDev( D_WARN, "images for 'mergeDepthmap' have mismatched dimensions [%ix%i] != [%ix%i]\n", - pic1->width, pic1->height, pic2->width, pic2->height ); - - FS_FreeImage( pic2 ); - return pic1; // don't free normalmap - } - - *samples = 4; - *flags &= ~TF_INTENSITY; - - return R_IncludeDepthmap( pic1, pic2 ); -} - -/* -================= -R_ParseClearPixels -================= -*/ -static rgbdata_t *R_ParseClearPixels( script_t *script, int *samples, texFlags_t *flags ) -{ - token_t token; - rgbdata_t *pic; - qboolean clearAlpha; - - Com_ReadToken( script, 0, &token ); - if( com.stricmp( token.string, "(" )) - { - MsgDev( D_WARN, "expected '(', found '%s' instead for 'clearPixels'\n", token.string ); - return NULL; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) - { - MsgDev( D_WARN, "missing parameters for 'clearPixels'\n" ); - return NULL; - } - - pic = R_LoadImage( script, token.string, NULL, 0, samples, flags ); - if( !pic ) return NULL; - - Com_ReadToken( script, 0, &token ); - if( !com.stricmp( token.string, "alpha" )) - { - Com_ReadToken( script, 0, &token ); - clearAlpha = true; - } - else if( !com.stricmp( token.string, "color" )) - { - Com_ReadToken( script, 0, &token ); - clearAlpha = false; - } - else if( !com.stricmp( token.string, ")" )) - { - Com_SaveToken( script, &token ); - clearAlpha = false; // clear color as default - } - else Com_ReadToken( script, 0, &token ); // skip unknown token - - if( com.stricmp( token.string, ")" )) - { - MsgDev( D_WARN, "expected ')', found '%s' instead for 'clearPixels'\n", token.string ); - FS_FreeImage( pic ); - return NULL; - } - - *samples = clearAlpha ? 3 : 1; - if( clearAlpha ) *flags &= ~TF_ALPHA; - *flags &= ~TF_INTENSITY; - - return R_ClearPixels( pic, clearAlpha ); -} - -/* -================= -R_LoadImage -================= -*/ -static rgbdata_t *R_LoadImage( script_t *script, const char *name, const byte *buf, size_t size, int *samples, texFlags_t *flags ) -{ - if( !com.stricmp( name, "add" )) - return R_ParseAdd( script, samples, flags ); - else if( !com.stricmp( name, "multiply" )) - return R_ParseMultiply( script, samples, flags ); - else if( !com.stricmp( name, "bias" )) - return R_ParseBias( script, samples, flags ); - else if( !com.stricmp( name, "scale")) - return R_ParseScale( script, samples, flags ); - else if( !com.stricmp( name, "invertColor" )) - return R_ParseInvertColor( script, samples, flags ); - else if( !com.stricmp( name, "invertAlpha" )) - return R_ParseInvertAlpha( script, samples, flags ); - else if( !com.stricmp( name, "makeIntensity" )) - return R_ParseMakeIntensity( script, samples, flags ); - else if( !com.stricmp( name, "makeLuminance" )) - return R_ParseMakeLuminance( script, samples, flags); - else if( !com.stricmp( name, "makeAlpha" )) - return R_ParseMakeAlpha( script, samples, flags ); - else if( !com.stricmp( name, "makeGlow" )) - return R_ParseMakeGlow( script, samples, flags ); - else if( !com.stricmp( name, "heightMap" )) - return R_ParseHeightMap( script, buf, size, samples, flags ); - else if( !com.stricmp( name, "ScrapBlock" )) - return R_ParseScrapBlock( script, samples, flags ); - else if( !com.stricmp( name, "addNormals" )) - return R_ParseAddNormals( script, samples, flags ); - else if( !com.stricmp( name, "smoothNormals" )) - return R_ParseSmoothNormals( script, samples, flags ); - else if( !com.stricmp( name, "mergeDepthmap" )) - return R_ParseDepthmap( script, buf, size, samples, flags ); - else if( !com.stricmp( name, "clearPixels" )) - return R_ParseClearPixels( script, samples, flags ); - else if( !com.stricmp( name, "Studio" )) - return R_ParseStudioSkin( script, buf, size, samples, flags ); - else if( !com.stricmp( name, "Alias" )) - return R_ParseAliasSkin( script, buf, size, samples, flags ); - else if( !com.stricmp( name, "Sprite" )) - return R_ParseSpriteFrame( script, buf, size, samples, flags ); - else - { - // loading form disk - rgbdata_t *image = FS_LoadImage( name, buf, size ); - if( image ) *samples = R_GetSamples( image->flags ); - return image; - } - return NULL; -} - -/* -=============== -GL_GenerateMipmaps - -sgis generate mipmap -=============== -*/ -void GL_GenerateMipmaps( byte *buffer, texture_t *tex, int side ) -{ - int mipLevel; - int mipWidth, mipHeight; - - // not needs - if( tex->flags & TF_NOMIPMAP ) - return; - - if( GL_Support( R_SGIS_MIPMAPS_EXT )) - { - pglHint( GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST ); - pglTexParameteri( image_desc.glTarget, GL_GENERATE_MIPMAP_SGIS, GL_TRUE ); - if( pglGetError()) MsgDev( D_WARN, "GL_GenerateMipmaps: %s can't create mip levels\n", tex->name ); - else return; // falltrough to software mipmap generating - } - - if( image_desc.format != PF_RGBA_32 ) - { - // g-cont. because i'm don't know how to generate miplevels for GL_FLOAT or GL_SHORT_REV_1_bla_bla - // ok, please show me videocard which don't supported GL_GENERATE_MIPMAP_SGIS ... - MsgDev( D_ERROR, "GL_GenerateMipmaps: failed on %s\n", PFDesc( image_desc.format )->name ); - return; - } - - mipLevel = 0; - mipWidth = tex->width; - mipHeight = tex->height; - - // software mipmap generator - while( mipWidth > 1 || mipHeight > 1 ) - { - // build the mipmap - R_BuildMipMap( buffer, mipWidth, mipHeight, ( tex->flags & TF_NORMALMAP )); - - mipWidth = (mipWidth+1)>>1; - mipHeight = (mipHeight+1)>>1; - mipLevel++; - - pglTexImage2D( image_desc.texTarget + side, mipLevel, tex->format, mipWidth, mipHeight, 0, image_desc.glFormat, GL_UNSIGNED_BYTE, buffer ); - } -} - -void GL_TexFilter( texture_t *tex ) -{ - // set texture filter - if( tex->flags & TF_DEPTHMAP ) - { - pglTexParameteri( tex->target, GL_TEXTURE_MIN_FILTER, r_textureDepthFilter ); - pglTexParameteri( tex->target, GL_TEXTURE_MAG_FILTER, r_textureDepthFilter ); - - if( GL_Support( R_ANISOTROPY_EXT )) - pglTexParameterf( tex->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f ); - } - else if( tex->flags & TF_NOMIPMAP ) - { - if( tex->flags & TF_NEAREST ) - { - pglTexParameteri( tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); - pglTexParameteri( tex->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); - } - else - { - pglTexParameteri( tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - pglTexParameteri( tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - } - } - else - { - if( tex->flags & TF_NEAREST ) - { - pglTexParameteri( tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST ); - pglTexParameteri( tex->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); - } - else - { - pglTexParameteri( tex->target, GL_TEXTURE_MIN_FILTER, r_textureMinFilter ); - pglTexParameteri( tex->target, GL_TEXTURE_MAG_FILTER, r_textureMagFilter ); - } - // set texture anisotropy if available - if( GL_Support( R_ANISOTROPY_EXT )) - pglTexParameterf( tex->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_anisotropy->value ); - - // set texture LOD bias if available - if( GL_Support( R_TEXTURE_LODBIAS )) - pglTexParameterf( tex->target, GL_TEXTURE_LOD_BIAS_EXT, gl_texture_lodbias->value ); - } - - // set texture wrap - if( tex->flags & TF_CLAMP ) - { - if(GL_Support( R_CLAMPTOEDGE_EXT )) - { - pglTexParameteri( tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - pglTexParameteri( tex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - if( tex->target == GL_TEXTURE_3D ) - pglTexParameteri( tex->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE ); - } - else - { - pglTexParameteri( tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP ); - pglTexParameteri( tex->target, GL_TEXTURE_WRAP_T, GL_CLAMP ); - if( tex->target == GL_TEXTURE_3D ) - pglTexParameteri( tex->target, GL_TEXTURE_WRAP_R, GL_CLAMP ); - } - } - else - { - pglTexParameteri( tex->target, GL_TEXTURE_WRAP_S, GL_REPEAT ); - pglTexParameteri( tex->target, GL_TEXTURE_WRAP_T, GL_REPEAT ); - if( tex->target == GL_TEXTURE_3D ) - pglTexParameteri( tex->target, GL_TEXTURE_WRAP_R, GL_REPEAT ); - } -} - -static void R_UploadTexture( rgbdata_t *pic, texture_t *tex ) -{ - uint i, offset = 0; - qboolean compress; - byte *buf, *data; - const byte *bufend; - - tex->width = tex->srcWidth; - tex->height = tex->srcHeight; - R_RoundImageDimensions( &tex->width, &tex->height, false ); - - // check if it should be compressed - if( !gl_compress_textures->integer || ( tex->flags & TF_UNCOMPRESSED )) - compress = false; - else compress = GL_Support( R_TEXTURE_COMPRESSION_EXT ); - - R_TextureFormat( tex, compress ); - - pglGenTextures( 1, &tex->texnum ); - GL_Bind( GL_TEXTURE0, tex ); - - buf = pic->buffer; - bufend = pic->buffer + pic->size; - - // uploading texture into video memory - for( offset = i = 0; i < image_desc.numSides; i++ ) - { - R_SetPixelFormat( tex->width, tex->height ); - offset = image_desc.SizeOfFile; // member side offset - tex->size += offset; - - if( buf >= bufend ) Host_Error( "R_UploadTexture: %s image buffer overflow\n", tex->name ); - - // copy or resample the texture - if( tex->width == tex->srcWidth && tex->height == tex->srcHeight ) - { - data = buf; - } - else - { - R_ResampleTexture( buf, tex->srcWidth, tex->srcHeight, tex->width, tex->height, (tex->flags & TF_NORMALMAP)); - data = image_desc.scaled; - } - - if( GL_Support( R_SGIS_MIPMAPS_EXT )) GL_GenerateMipmaps( data, tex, i ); - pglTexImage2D( image_desc.texTarget + i, 0, tex->format, tex->width, tex->height, 0, image_desc.glFormat, GL_UNSIGNED_BYTE, data ); - if( !GL_Support( R_SGIS_MIPMAPS_EXT )) GL_GenerateMipmaps( data, tex, i ); - - R_CheckForErrors(); - - if( image_desc.numSides > 1 ) - buf += offset; - } -} - -/* -================= -R_LoadTexture -================= -*/ -texture_t *R_LoadTexture( const char *name, rgbdata_t *pic, int samples, texFlags_t flags ) -{ - texture_t *texture; - uint i, hash; - - if( r_numTextures == MAX_TEXTURES ) - Host_Error( "R_LoadTexture: MAX_TEXTURES limit exceeds\n" ); - - // find a free texture_t slot - for( i = 0, texture = r_textures; i < r_numTextures; i++, texture++ ) - if( !texture->texnum ) break; - - if( i == r_numTextures ) - { - if( r_numTextures == MAX_TEXTURES ) - { - MsgDev( D_ERROR, "R_LoadTexture: gl textures is out\n" ); - return tr.defaultTexture; - } - r_numTextures++; - } - - texture = &r_textures[i]; - - // fill it in - com.strncpy( texture->name, name, sizeof( texture->name )); - texture->srcWidth = pic->width; - texture->srcHeight = pic->height; - texture->srcFlags = pic->flags; - texture->touchFrame = tr.registration_sequence; - if( samples <= 0 ) - texture->samples = R_GetSamples( pic->flags ); - else texture->samples = samples; - - // setup image_desc - R_GetPixelFormat( name, pic, flags ); - texture->flags = image_desc.tflags; - texture->target = image_desc.glTarget; - texture->texType = image_desc.texType; - - R_UploadTexture( pic, texture ); - GL_TexFilter( texture ); // update texture filter, wrap etc - - // add to hash table - hash = Com_HashKey( texture->name, TEXTURES_HASH_SIZE ); - texture->nextHash = r_texturesHashTable[hash]; - r_texturesHashTable[hash] = texture; - - return texture; -} - -/* -================= -R_FindTexture -================= -*/ -texture_t *R_FindTexture( const char *name, const byte *buf, size_t size, texFlags_t flags ) -{ - texture_t *texture; - script_t *script; - rgbdata_t *image; - token_t token; - int samples; - uint hash; - - if( !name || !name[0] ) return NULL; - if( com.strlen( name ) >= MAX_STRING ) - Host_Error( "R_FindTexture: texture name exceeds %i symbols\n", MAX_STRING ); - - // see if already loaded - hash = Com_HashKey( name, TEXTURES_HASH_SIZE ); - - for( texture = r_texturesHashTable[hash]; texture; texture = texture->nextHash ) - { - if( texture->flags & TF_CUBEMAP ) - continue; - - if( !com.stricmp( texture->name, name )) - { - if( texture->flags & TF_STATIC ) - return texture; - - if( texture->flags != flags ) - MsgDev( D_WARN, "reused texture '%s' with mixed flags parameter (%p should be %p)\n", name, texture->flags, flags ); - - // prolonge registration - texture->touchFrame = tr.registration_sequence; - return texture; - } - } - - // NOTE: texname may contains some commands over textures - script = Com_OpenScript( "texturedef", name, com.strlen( name )); - if( !script ) return NULL; - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &token )) - { - Com_CloseScript( script ); - return NULL; - } - - image = R_LoadImage( script, token.string, buf, size, &samples, &flags ); - Com_CloseScript( script ); - - // load the texture - if( image ) - { - texture = R_LoadTexture( name, image, samples, flags ); - FS_FreeImage( image ); - return texture; - } - - // not found or invalid - return NULL; -} - -/* -================ -R_FreeImage -================ -*/ -void R_FreeImage( texture_t *image ) -{ - uint hash; - texture_t *cur; - texture_t **prev; - - ASSERT( image ); - - // remove from hash table - hash = Com_HashKey( image->name, TEXTURES_HASH_SIZE ); - prev = &r_texturesHashTable[hash]; - - while( 1 ) - { - cur = *prev; - if( !cur ) break; - - if( cur == image ) - { - *prev = cur->nextHash; - break; - } - prev = &cur->nextHash; - } - - pglDeleteTextures( 1, &image->texnum ); - Mem_Set( image, 0, sizeof( *image )); -} - - -/* -============================================================================== - -SCREEN SHOTS - -============================================================================== -*/ -/* -================ -VID_ImageAdjustGamma -================ -*/ -void VID_ImageAdjustGamma( byte *in, uint width, uint height ) -{ - int i, c = width * height; - float g = 1.0f / bound( 0.5f, r_gamma->value, 3.0f ); - byte *p = in; - - // screenshots gamma - for( i = 0; i < 256; i++ ) - { - if ( g == 1 ) r_gammaTable[i] = i; - else r_gammaTable[i] = bound( 0, 255 * pow((i + 0.5)/255.5f, g ) + 0.5, 255); - } - for( i = 0; i < c; i++, p += 3 ) - { - p[0] = r_gammaTable[p[0]]; - p[1] = r_gammaTable[p[1]]; - p[2] = r_gammaTable[p[2]]; - } -} - -qboolean VID_ScreenShot( const char *filename, int shot_type ) -{ - rgbdata_t *r_shot; - uint flags = IMAGE_FLIP_Y; - int width = 0, height = 0; - qboolean result; - - r_shot = Mem_Alloc( r_temppool, sizeof( rgbdata_t )); - r_shot->width = glState.width; - r_shot->height = glState.height; - r_shot->flags = IMAGE_HAS_COLOR; - r_shot->type = PF_RGB_24; - r_shot->size = r_shot->width * r_shot->height * PFDesc( r_shot->type )->bpp; - r_shot->palette = NULL; - r_shot->buffer = Mem_Alloc( r_temppool, glState.width * glState.height * 3 ); - - // get screen frame - pglReadPixels( 0, 0, glState.width, glState.height, GL_RGB, GL_UNSIGNED_BYTE, r_shot->buffer ); - - switch( shot_type ) - { - case VID_SCREENSHOT: - VID_ImageAdjustGamma( r_shot->buffer, r_shot->width, r_shot->height ); // adjust brightness - break; - case VID_LEVELSHOT: - flags |= IMAGE_RESAMPLE; - height = 384; - width = 512; - break; - case VID_MINISHOT: - flags |= IMAGE_RESAMPLE; - height = 200; - width = 320; - break; - } - - Image_Process( &r_shot, width, height, flags ); - - // write image - result = FS_SaveImage( filename, r_shot ); - FS_FreeImage( r_shot ); - - return result; -} - -/* -================= -VID_CubemapShot -================= -*/ -qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot ) -{ - rgbdata_t *r_shot, *r_side; - byte *temp = NULL; - byte *buffer = NULL; - string basename; - int i = 1, flags, result; - - if( !RI.drawWorld || !r_worldmodel ) - return false; - - // make sure the specified size is valid - while( i < size ) i<<=1; - - if( i != size ) return false; - if( size > glState.width || size > glState.height ) - return false; - - // setup refdef - RI.params |= RP_ENVVIEW; // do not render non-bmodel entities - - // alloc space - temp = Mem_Alloc( r_temppool, size * size * 3 ); - buffer = Mem_Alloc( r_temppool, size * size * 3 * 6 ); - r_shot = Mem_Alloc( r_temppool, sizeof( rgbdata_t )); - r_side = Mem_Alloc( r_temppool, sizeof( rgbdata_t )); - - // use client vieworg - if( !vieworg ) vieworg = r_lastRefdef.vieworg; - - for( i = 0; i < 6; i++ ) - { - if( skyshot ) - { - R_DrawCubemapView( vieworg, r_skyBoxInfo[i].angles, size ); - flags = r_skyBoxInfo[i].flags; - } - else - { - R_DrawCubemapView( vieworg, r_envMapInfo[i].angles, size ); - flags = r_envMapInfo[i].flags; - } - - pglReadPixels( 0, glState.height - size, size, size, GL_RGB, GL_UNSIGNED_BYTE, temp ); - r_side->flags = IMAGE_HAS_COLOR; - r_side->width = r_side->height = size; - r_side->type = PF_RGB_24; - r_side->size = r_side->width * r_side->height * 3; - r_side->buffer = temp; - - if( flags ) Image_Process( &r_side, 0, 0, flags ); - Mem_Copy( buffer + (size * size * 3 * i), r_side->buffer, size * size * 3 ); - } - - RI.params &= ~RP_ENVVIEW; - - r_shot->flags = IMAGE_HAS_COLOR; - r_shot->flags |= (skyshot) ? IMAGE_SKYBOX : IMAGE_CUBEMAP; - r_shot->width = size; - r_shot->height = size; - r_shot->type = PF_RGB_24; - r_shot->size = r_shot->width * r_shot->height * 3 * 6; - r_shot->palette = NULL; - r_shot->buffer = buffer; - - // make sure what we have right extension - com.strncpy( basename, base, MAX_STRING ); - FS_StripExtension( basename ); - FS_DefaultExtension( basename, va( ".%s", SI->envshot_ext )); - - // write image as dds packet - result = FS_SaveImage( basename, r_shot ); - FS_FreeImage( r_shot ); - FS_FreeImage( r_side ); - - return result; -} -//======================================================= - -/* -================== -R_InitNoTexture -================== -*/ -static rgbdata_t *R_InitNoTexture( int *flags, int *samples ) -{ - int x, y; - - // also use this for bad textures, but without alpha - r_image.width = r_image.height = 16; - r_image.buffer = data2D; - r_image.flags = IMAGE_HAS_COLOR; - r_image.type = PF_RGBA_32; - r_image.size = r_image.width * r_image.height * 4; - - *flags = 0; - *samples = 3; - - // default texture -#if 1 - // emo-texture from quake1 - for( y = 0; y < 16; y++ ) - { - for( x = 0; x < 16; x++ ) - { - if(( y < 8 ) ^ ( x < 8 )) - ((uint *)&data2D)[y*16+x] = 0xFFFF00FF; - else ((uint *)&data2D)[y*16+x] = 0xFF000000; - } - } -#else - // notexture from quake3 - for( y = 0; y < 16; y++ ) - { - for( x = 0; x < 16; x++ ) - { - if( x == 0 || x == 15 || y == 0 || y == 15 ) - ((uint *)&data2D)[y*16+x] = 0xFFFFFFFF; - else ((uint *)&data2D)[y*16+x] = 0xFF000000; - } - } -#endif - return &r_image; -} - -/* -================== -R_InitDynamicLightTexture -================== -*/ -static rgbdata_t *R_InitDynamicLightTexture( int *flags, int *samples ) -{ - vec3_t v = { 0, 0, 0 }; - int x, y, size, size2, halfsize; - float intensity; - - // dynamic light texture - size = 128; - - r_image.width = r_image.height = size; - r_image.buffer = data2D; - r_image.flags = IMAGE_HAS_COLOR; - r_image.type = PF_RGBA_32; - r_image.size = r_image.width * r_image.height * 4; - - halfsize = size / 2; - intensity = halfsize * halfsize; - size2 = size * size; - - *flags = TF_NOPICMIP|TF_NOMIPMAP|TF_CLAMP|TF_UNCOMPRESSED; - *samples = 3; - - for( x = 0; x < size; x++ ) - { - for( y = 0; y < size; y++ ) - { - float result; - - if( x == size - 1 || x == 0 || y == size - 1 || y == 0 ) - result = 255; - else - { - float xf = ((float)x - 64 ) / 64.0f; - float yf = ((float)y - 64 ) / 64.0f; - result = ((xf * xf) + (yf * yf)) * 255; - if( result > 255 ) result = 255; - } - data2D[(x*size+y)*4+0] = (byte)255 - result; - data2D[(x*size+y)*4+1] = (byte)255 - result; - data2D[(x*size+y)*4+2] = (byte)255 - result; - } - } - - return &r_image; -} - -/* -================== -R_InitSpotLightTexture -================== -*/ -static rgbdata_t *R_InitSpotLightTexture( int *flags, int *samples ) -{ - *flags = TF_NOPICMIP|TF_NOMIPMAP|TF_CLAMP|TF_UNCOMPRESSED; - *samples = 0; - - return NULL; // UNDONE: test only -} - -/* -================== -R_InitNormalizeCubemap -================== -*/ -static rgbdata_t *R_InitNormalizeCubemap( int *flags, int *samples ) -{ - int i, x, y, size = 32; - byte *dataCM = data2D; - float s, t; - vec3_t normal; - - if( !GL_Support( R_TEXTURECUBEMAP_EXT )) - return NULL; - - // normal cube map texture - for( i = 0; i < 6; i++ ) - { - for( y = 0; y < size; y++ ) - { - for( x = 0; x < size; x++ ) - { - s = (((float)x + 0.5f) * (2.0f / size )) - 1.0f; - t = (((float)y + 0.5f) * (2.0f / size )) - 1.0f; - - switch( i ) - { - case 0: VectorSet( normal, 1.0f, -t, -s ); break; - case 1: VectorSet( normal, -1.0f, -t, s ); break; - case 2: VectorSet( normal, s, 1.0f, t ); break; - case 3: VectorSet( normal, s, -1.0f, -t ); break; - case 4: VectorSet( normal, s, -t, 1.0f ); break; - case 5: VectorSet( normal, -s, -t, -1.0f); break; - } - - VectorNormalize( normal ); - - dataCM[4*(y*size+x)+0] = (byte)(128 + 127 * normal[0]); - dataCM[4*(y*size+x)+1] = (byte)(128 + 127 * normal[1]); - dataCM[4*(y*size+x)+2] = (byte)(128 + 127 * normal[2]); - dataCM[4*(y*size+x)+3] = 255; - } - } - dataCM += (size*size*4); // move pointer - } - - *flags = (TF_STATIC|TF_NOPICMIP|TF_NOMIPMAP|TF_UNCOMPRESSED|TF_CUBEMAP|TF_CLAMP); - *samples = 3; - - r_image.width = r_image.height = size; - r_image.size = r_image.width * r_image.height * 4 * 6; - r_image.flags |= (IMAGE_CUBEMAP|IMAGE_HAS_COLOR); // yes it's cubemap - r_image.buffer = data2D; - r_image.type = PF_RGBA_32; - - return &r_image; -} - -/* -================== -R_InitSolidColorTexture -================== -*/ -static rgbdata_t *R_InitSolidColorTexture( int *flags, int *samples, int color ) -{ - // solid color texture - r_image.width = r_image.height = 1; - r_image.buffer = data2D; - r_image.flags = IMAGE_HAS_COLOR; - r_image.type = PF_RGB_24; - r_image.size = r_image.width * r_image.height * 3; - - *flags = TF_NOPICMIP|TF_UNCOMPRESSED; - *samples = 3; - - data2D[0] = data2D[1] = data2D[2] = color; - return &r_image; -} - -/* -================== -R_InitParticleTexture -================== -*/ -static rgbdata_t *R_InitParticleTexture( int *flags, int *samples ) -{ - int x, y; - int dx2, dy, d; - - // particle texture - r_image.width = r_image.height = 16; - r_image.buffer = data2D; - r_image.flags = (IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA); - r_image.type = PF_RGBA_32; - r_image.size = r_image.width * r_image.height * 4; - - *flags = TF_NOPICMIP|TF_NOMIPMAP; - *samples = 4; - - for( x = 0; x < 16; x++ ) - { - dx2 = x - 8; - dx2 = dx2 * dx2; - - for( y = 0; y < 16; y++ ) - { - dy = y - 8; - d = 255 - 35 * com.sqrt( dx2 + dy * dy ); - data2D[( y*16 + x ) * 4 + 3] = bound( 0, d, 255 ); - } - } - return &r_image; -} - -/* -================== -R_InitWhiteTexture -================== -*/ -static rgbdata_t *R_InitWhiteTexture( int *flags, int *samples ) -{ - return R_InitSolidColorTexture( flags, samples, 255 ); -} - -/* -================== -R_InitBlackTexture -================== -*/ -static rgbdata_t *R_InitBlackTexture( int *flags, int *samples ) -{ - return R_InitSolidColorTexture( flags, samples, 0 ); -} - -/* -================== -R_InitBlankBumpTexture -================== -*/ -static rgbdata_t *R_InitBlankBumpTexture( int *flags, int *samples ) -{ - rgbdata_t *pic = R_InitSolidColorTexture( flags, samples, 128 ); - -/* - pic->buffer[2] = 128; // normal X - pic->buffer[1] = 128; // normal Y -*/ - pic->buffer[0] = 255; // normal Z - pic->buffer[3] = 128; // height - - return pic; -} - -/* -================== -R_InitSkyTexture -================== -*/ -static rgbdata_t *R_InitSkyTexture( int *flags, int *samples ) -{ - int i; - - // skybox texture - for( i = 0; i < 256; i++ ) - ((uint *)&data2D)[i] = 0xFFFFDEB5; - - *flags = TF_NOPICMIP|TF_UNCOMPRESSED; - *samples = 3; - - r_image.buffer = data2D; - r_image.width = r_image.height = 16; - r_image.size = r_image.width * r_image.height * 4; - r_image.flags = IMAGE_HAS_COLOR; - r_image.type = PF_RGBA_32; - - return &r_image; -} - -/* -================== -R_InitFogTexture -================== -*/ -static rgbdata_t *R_InitFogTexture( int *flags, int *samples ) -{ - int x, y; - double tw = 1.0f / ( (float)FOG_TEXTURE_WIDTH - 1.0f ); - double th = 1.0f / ( (float)FOG_TEXTURE_HEIGHT - 1.0f ); - double tx, ty, t; - - // fog texture - r_image.width = FOG_TEXTURE_WIDTH; - r_image.height = FOG_TEXTURE_HEIGHT; - r_image.buffer = data2D; - r_image.flags = IMAGE_HAS_COLOR; - r_image.type = PF_RGBA_32; - r_image.size = r_image.width * r_image.height * 4; - - *flags = TF_NOMIPMAP|TF_CLAMP; - *samples = 4; - - for( y = 0, ty = 0.0f; y < FOG_TEXTURE_HEIGHT; y++, ty += th ) - { - for( x = 0, tx = 0.0f; x < FOG_TEXTURE_WIDTH; x++, tx += tw ) - { - t = com.sqrt( tx ) * 255.0; - data2D[( x+y*FOG_TEXTURE_WIDTH )*4+3] = (byte)( min( t, 255.0 )); - } - data2D[y*4+3] = 0; - } - return &r_image; -} - -/* -================== -R_InitCoronaTexture -================== -*/ -static rgbdata_t *R_InitCoronaTexture( int *flags, int *samples ) -{ - int x, y, a; - float dx, dy; - - // light corona texture - r_image.width = r_image.height = 32; - r_image.buffer = data2D; - r_image.flags = IMAGE_HAS_COLOR; - r_image.type = PF_RGBA_32; - r_image.size = r_image.width * r_image.height * 4; - - *flags = TF_NOMIPMAP|TF_NOPICMIP|TF_UNCOMPRESSED|TF_CLAMP; - *samples = 4; - - for( y = 0; y < 32; y++ ) - { - dy = ( y - 15.5f ) * ( 1.0f / 16.0f ); - for( x = 0; x < 32; x++ ) - { - dx = ( x - 15.5f ) * ( 1.0f / 16.0f ); - a = (int)((( 1.0f / ( dx * dx + dy * dy + 0.2f )) - ( 1.0f / ( 1.0f + 0.2 ))) * 32.0f / ( 1.0f / ( 1.0f + 0.2 ))); - a = bound( 0, a, 255 ); - data2D[( y*32+x )*4+0] = data2D[( y*32+x )*4+1] = data2D[( y*32+x )*4+2] = a; - } - } - return &r_image; -} - -/* -================== -R_InitScreenTexture -================== -*/ -static void R_InitScreenTexture( texture_t **ptr, const char *name, int id, int screenWidth, int screenHeight, int size, int flags, int samples ) -{ - int limit; - int width, height; - rgbdata_t r_screen; - - Mem_Set( &r_screen, 0, sizeof( rgbdata_t )); - limit = glConfig.max_2d_texture_size; - if( size ) limit = min( limit, size ); - - limit = min( limit, min( screenWidth, screenHeight )); - for( size = 2; size <= limit; size <<= 1 ); - width = height = size >> 1; - - if( !(*ptr) || (*ptr)->width != width || (*ptr)->height != height ) - { - byte *data = NULL; - - if( !*ptr ) - { - string uploadName; - - com.snprintf( uploadName, sizeof( uploadName ), "***%s%i***", name, id ); - - r_screen.width = width; - r_screen.height = height; - r_screen.type = PF_RGB_24; - r_screen.buffer = data; - r_screen.size = width * height * samples; - *ptr = R_LoadTexture( uploadName, &r_screen, samples, flags ); - return; - } - - GL_Bind( 0, *ptr ); - (*ptr)->width = width; - (*ptr)->height = height; - R_RoundImageDimensions(&((*ptr)->width), &((*ptr)->height), true ); - pglTexImage2D( GL_TEXTURE_2D, 0, (*ptr)->format, (*ptr)->width, (*ptr)->height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL ); - GL_TexFilter( *ptr ); - } -} - -/* -================== -R_InitPortalTexture -================== -*/ -void R_InitPortalTexture( texture_t **texture, int id, int screenWidth, int screenHeight ) -{ - R_InitScreenTexture( texture, "r_portaltexture", id, screenWidth, screenHeight, r_portalmaps_maxtexsize->integer, TF_PORTALMAP, 3 ); -} - -/* -================== -R_InitShadowmapTexture -================== -*/ -void R_InitShadowmapTexture( texture_t **texture, int id, int screenWidth, int screenHeight ) -{ - R_InitScreenTexture( texture, "r_shadowmap", id, screenWidth, screenHeight, r_shadows_maxtexsize->integer, TF_SHADOWMAP, 1 ); -} - -/* -================== -R_InitCinematicTexture -================== -*/ -static rgbdata_t *R_InitCinematicTexture( int *flags, int *samples ) -{ - // light corona texture - r_image.width = r_image.height = 256; - r_image.buffer = data2D; - r_image.flags = IMAGE_HAS_COLOR; - r_image.type = PF_RGBA_32; - r_image.size = r_image.width * r_image.height * 4; - - *flags = TF_STATIC|TF_NOMIPMAP|TF_NOPICMIP|TF_UNCOMPRESSED|TF_CLAMP; - *samples = 4; - - return &r_image; -} - -/* -================== -R_InitBuiltinTextures -================== -*/ -static void R_InitBuiltinTextures( void ) -{ - rgbdata_t *pic; - int flags, samples; - texture_t *image; - - const struct - { - char *name; - texture_t **image; - rgbdata_t *( *init )( int *flags, int *samples ); - } - textures[] = - { - { "*default", &tr.defaultTexture, R_InitNoTexture }, - { "*fog", &tr.fogTexture, R_InitFogTexture }, - { "*sky", &tr.skyTexture, R_InitSkyTexture }, - { "*white", &tr.whiteTexture, R_InitWhiteTexture }, - { "*black", &tr.blackTexture, R_InitBlackTexture }, - { "*blankbump", &tr.blankbumpTexture, R_InitBlankBumpTexture }, - { "*dlight", &tr.dlightTexture, R_InitDynamicLightTexture }, -// { "*dspotlight", &tr.dspotlightTexture, R_InitSpotLightTexture }, - { "*normalize", &tr.normalizeTexture, R_InitNormalizeCubemap }, - { "*particle", &tr.particleTexture, R_InitParticleTexture }, - { "*corona", &tr.coronaTexture, R_InitCoronaTexture }, - { "*cintexture", &tr.cinTexture, R_InitCinematicTexture }, - { NULL, NULL, NULL } - }; - size_t i, num_builtin_textures = sizeof( textures ) / sizeof( textures[0] ) - 1; - - for( i = 0; i < num_builtin_textures; i++ ) - { - Mem_Set( &r_image, 0, sizeof( rgbdata_t )); - Mem_Set( data2D, 0xFF, sizeof( data2D )); - - pic = textures[i].init( &flags, &samples ); - if( pic == NULL ) continue; - image = R_LoadTexture( textures[i].name, pic, samples, flags ); - - if( textures[i].image ) - *( textures[i].image ) = image; - } - tr.portaltexture1 = NULL; - tr.portaltexture2 = NULL; -} - -/* -=============== -R_ShowTextures - -Draw all the images to the screen, on top of whatever -was there. This is used to test for texture thrashing. -=============== -*/ -void R_ShowTextures( void ) -{ - texture_t *image; - float x, y, w, h; - int i, j, base_w, base_h; - - if( !r_showtextures->integer ) - return; - - if( !glState.in2DMode ) - { - R_Set2DMode( true ); - } - - pglClear( GL_COLOR_BUFFER_BIT ); - pglFinish(); - - if( r_showtextures->integer == TEX_LIGHTMAP ) - { - // draw lightmaps as big images - base_w = 5; - base_h = 4; - } - else - { - base_w = 16; - base_h = 12; - } - - for( i = j = 0, image = r_textures; i < r_numTextures; i++, image++ ) - { - if( !image->texnum ) continue; - - if( image->texType != r_showtextures->integer ) - continue; - - w = glState.width / base_w; - h = glState.height / base_h; - x = j % base_w * w; - y = j / base_w * h; - - pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); - GL_Bind( GL_TEXTURE0, image ); - R_CheckForErrors(); - pglBegin( GL_QUADS ); - pglTexCoord2f( 0, 0 ); - pglVertex2f( x, y ); - pglTexCoord2f( 1, 0 ); - pglVertex2f( x + w, y ); - pglTexCoord2f( 1, 1 ); - pglVertex2f( x + w, y + h ); - pglTexCoord2f( 0, 1 ); - pglVertex2f( x, y + h ); - pglEnd(); - j++; - } - pglFinish(); - - R_CheckForErrors (); -} - -//======================================================= - -/* -=============== -R_InitImages -=============== -*/ -void R_InitImages( void ) -{ - int i; - float f; - - r_texpool = Mem_AllocPool( "Texture Manager Pool" ); - r_imagepool = Mem_AllocPool( "Immediate TexturePool" ); // for scaling and resampling - - r_numTextures = 0; - tr.registration_sequence = 1; - Mem_Set( r_textures, 0, sizeof( r_textures )); - Mem_Set( r_texturesHashTable, 0, sizeof( r_texturesHashTable )); - - // build the auto-luma table - for( i = 0; i < 256; i++ ) - { - // 224 is a Q1 luma threshold - r_glowTable[i][0] = i > 224 ? i : 0; - r_glowTable[i][1] = i > 224 ? i : 0; - r_glowTable[i][2] = i > 224 ? i : 0; - } - - // build luminance table - for( i = 0; i < 256; i++ ) - { - f = (float)i; - r_luminanceTable[i][0] = f * 0.299; - r_luminanceTable[i][1] = f * 0.587; - r_luminanceTable[i][2] = f * 0.114; - } - - // set texture parameters - R_SetTextureParameters(); - - R_InitBuiltinTextures(); - R_InitBloomTextures(); -} - -/* -=============== -R_ShutdownImages -=============== -*/ -void R_ShutdownImages( void ) -{ - int i; - texture_t *image; - - if( !glw_state.initialized ) return; - - for( i = MAX_TEXTURE_UNITS - 1; i >= 0; i-- ) - { - if( i >= glConfig.max_texture_units ) - continue; - - GL_SelectTexture( i ); - pglBindTexture( GL_TEXTURE_2D, 0 ); - pglBindTexture( GL_TEXTURE_CUBE_MAP_ARB, 0 ); - } - - for( i = 0, image = r_textures; i < r_numTextures; i++, image++ ) - { - if( !image->texnum ) continue; - R_FreeImage( image ); - } - - Mem_Set( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures )); - Mem_Set( tr.shadowmapTextures, 0, sizeof( tr.shadowmapTextures )); - Mem_Set( r_texturesHashTable, 0, sizeof( r_texturesHashTable )); - Mem_Set( r_textures, 0, sizeof( r_textures )); - - r_numTextures = 0; - tr.portaltexture1 = NULL; - tr.portaltexture2 = NULL; -} \ No newline at end of file diff --git a/vid_gl/r_light.c b/vid_gl/r_light.c deleted file mode 100644 index 5e94e68d..00000000 --- a/vid_gl/r_light.c +++ /dev/null @@ -1,1209 +0,0 @@ -/* -Copyright (C) 1997-2001 Id Software, Inc. -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// r_light.c - -#include "r_local.h" -#include "mathlib.h" -#include "matrix_lib.h" -#include "pm_movevars.h" -#include "bspfile.h" - -/* -============================================================================= - - DYNAMIC LIGHTS - -============================================================================= -*/ -/* -============= -R_SurfPotentiallyLit -============= -*/ -qboolean R_SurfPotentiallyLit( msurface_t *surf ) -{ - ref_shader_t *shader; - - if( surf->flags & ( SURF_DRAWSKY|SURF_DRAWTURB )) - return false; - - if( !surf->samples ) - return false; - - shader = surf->shader; - if( shader->flags & SHADER_SKYPARMS || shader->type == SHADER_FLARE || !shader->num_stages ) - return false; - - return true; -} - -/* -============= -R_LightBounds -============= -*/ -void R_LightBounds( const vec3_t origin, float intensity, vec3_t mins, vec3_t maxs ) -{ - VectorSet( mins, origin[0] - intensity, origin[1] - intensity, origin[2] - intensity ); - VectorSet( maxs, origin[0] + intensity, origin[1] + intensity, origin[2] + intensity ); -} - -/* -============= -R_AddSurfDlighbits -============= -*/ -uint R_AddSurfDlighbits( msurface_t *surf, uint dlightbits ) -{ - uint k, bit; - ref_dlight_t *lt; - float dist; - - for( k = 0, bit = 1, lt = r_dlights; k < r_numDlights; k++, bit <<= 1, lt++ ) - { - if( dlightbits & bit ) - { - if( surf->plane->type < 3 ) dist = lt->origin[surf->plane->type] - surf->plane->dist; - else dist = DotProduct( lt->origin, surf->plane->normal ) - surf->plane->dist; - - dist = PlaneDiff( lt->origin, surf->plane ); - if( dist <= -lt->intensity || dist >= lt->intensity ) - dlightbits &= ~bit; // how lucky... - } - } - return dlightbits; -} - -/* -================= -R_AddDynamicLights -================= -*/ -void R_AddDynamicLights( uint dlightbits, int state ) -{ - uint i, j, numTempElems; - qboolean cullAway; - const ref_dlight_t *light; - const ref_shader_t *shader; - vec3_t tvec, dlorigin, normal; - elem_t tempElemsArray[MAX_ARRAY_ELEMENTS]; - float inverseIntensity, *v1, *v2, *v3, dist; - GLfloat xyzFallof[4][4] = {{ 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 0 }}; - matrix4x4 m; - - r_backacc.numColors = 0; - Matrix4x4_BuildLightIdentity( m ); - - // we multitexture or texture3D support for dynamic lights - if( !GL_Support( R_TEXTURE_3D_EXT ) && !GL_Support( R_ARB_MULTITEXTURE )) - return; - - for( i = 0; i < ( GL_Support( R_TEXTURE_3D_EXT ) ? 1 : 2 ); i++ ) - { - GL_SelectTexture( i ); - GL_TexEnv( GL_MODULATE ); - GL_SetState( state | ( i ? 0 : GLSTATE_BLEND_MTEX )); - GL_SetTexCoordArrayMode( 0 ); - GL_EnableTexGen( GL_S, GL_OBJECT_LINEAR ); - GL_EnableTexGen( GL_T, GL_OBJECT_LINEAR ); - GL_EnableTexGen( GL_R, 0 ); - GL_EnableTexGen( GL_Q, 0 ); - } - - if( GL_Support( R_TEXTURE_3D_EXT )) - { - GL_EnableTexGen( GL_R, GL_OBJECT_LINEAR ); - pglDisable( GL_TEXTURE_2D ); - pglEnable( GL_TEXTURE_3D ); - } - else - { - pglEnable( GL_TEXTURE_2D ); - } - - for( i = 0, light = r_dlights; i < r_numDlights; i++, light++ ) - { - if( light->flags & DLIGHT_ONLYENTS ) - continue; - - if(!( dlightbits & ( 1<origin, RI.currententity->origin, dlorigin ); - if( !Matrix3x3_Compare( RI.currententity->axis, matrix3x3_identity )) - { - VectorCopy( dlorigin, tvec ); - Matrix3x3_Transform( RI.currententity->axis, tvec, dlorigin ); - } - - shader = light->shader; - if( shader && ( shader->flags & SHADER_CULL_BACK )) - cullAway = true; - else cullAway = false; - - numTempElems = 0; - if( cullAway ) - { - for( j = 0; j < r_backacc.numElems; j += 3 ) - { - v1 = (float *)(vertsArray + elemsArray[j+0]); - v2 = (float *)(vertsArray + elemsArray[j+1]); - v3 = (float *)(vertsArray + elemsArray[j+2]); - - normal[0] = ( v1[1] - v2[1] ) * ( v3[2] - v2[2] ) - ( v1[2] - v2[2] ) * ( v3[1] - v2[1] ); - normal[1] = ( v1[2] - v2[2] ) * ( v3[0] - v2[0] ) - ( v1[0] - v2[0] ) * ( v3[2] - v2[2] ); - normal[2] = ( v1[0] - v2[0] ) * ( v3[1] - v2[1] ) - ( v1[1] - v2[1] ) * ( v3[0] - v2[0] ); - dist = (dlorigin[0] - v1[0]) * normal[0] + (dlorigin[1] - v1[1]) * normal[1] + (dlorigin[2] - v1[2]) * normal[2]; - - if( dist <= 0 || dist * rsqrt( DotProduct( normal, normal )) >= light->intensity ) - continue; - - tempElemsArray[numTempElems++] = elemsArray[j+0]; - tempElemsArray[numTempElems++] = elemsArray[j+1]; - tempElemsArray[numTempElems++] = elemsArray[j+2]; - } - if( !numTempElems ) continue; - } - - inverseIntensity = 1.0f / light->intensity; - - GL_Bind( 0, tr.dlightTexture ); - GL_LoadTexMatrix( m ); - pglColor4f( light->color[0], light->color[1], light->color[2], 255 ); - - xyzFallof[0][0] = inverseIntensity; - xyzFallof[0][3] = -dlorigin[0] * inverseIntensity; - pglTexGenfv( GL_S, GL_OBJECT_PLANE, xyzFallof[0] ); - - xyzFallof[1][1] = inverseIntensity; - xyzFallof[1][3] = -dlorigin[1] * inverseIntensity; - pglTexGenfv( GL_T, GL_OBJECT_PLANE, xyzFallof[1] ); - - xyzFallof[2][2] = inverseIntensity; - xyzFallof[2][3] = -dlorigin[2] * inverseIntensity; - - if( GL_Support( R_TEXTURE_3D_EXT )) - { - pglTexGenfv( GL_R, GL_OBJECT_PLANE, xyzFallof[2] ); - } - else - { - GL_Bind( 1, tr.dlightTexture ); - GL_LoadTexMatrix( m ); - - pglTexGenfv( GL_S, GL_OBJECT_PLANE, xyzFallof[2] ); - pglTexGenfv( GL_T, GL_OBJECT_PLANE, xyzFallof[3] ); - } - - if( numTempElems ) - { - if( GL_Support( R_DRAW_RANGEELEMENTS_EXT )) - pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, numTempElems, GL_UNSIGNED_INT, tempElemsArray ); - else pglDrawElements( GL_TRIANGLES, numTempElems, GL_UNSIGNED_INT, tempElemsArray ); - } - else - { - if( GL_Support( R_DRAW_RANGEELEMENTS_EXT )) - pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); - else pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); - } - } - - if( GL_Support( R_TEXTURE_3D_EXT )) - { - GL_EnableTexGen( GL_R, 0 ); - pglDisable( GL_TEXTURE_3D ); - pglEnable( GL_TEXTURE_2D ); - } - else - { - pglDisable( GL_TEXTURE_2D ); - GL_SelectTexture( 0 ); - } -} - -//=================================================================== - -static ref_shader_t *r_coronaShader; - -/* -================= -R_InitCoronas -================= -*/ -void R_InitCoronas( void ) -{ - r_coronaShader = R_LoadShader( "*corona", SHADER_FLARE, true, TF_NOMIPMAP|TF_NOPICMIP|TF_UNCOMPRESSED|TF_CLAMP, SHADER_INVALID ); -} - -/* -================= -R_DrawCoronas -================= -*/ -void R_DrawCoronas( void ) -{ - uint i; - float dist; - ref_dlight_t *light; - meshbuffer_t *mb; - pmtrace_t tr; - - if( r_dynamiclight->integer != 2 ) - return; - - for( i = 0, light = r_dlights; i < r_numDlights; i++, light++ ) - { - dist = RI.vpn[0] * ( light->origin[0] - RI.viewOrigin[0] ) + - RI.vpn[1] * ( light->origin[1] - RI.viewOrigin[1] ) + - RI.vpn[2] * ( light->origin[2] - RI.viewOrigin[2] ); - - if( dist < 24.0f ) continue; - dist -= light->intensity; - - R_TraceLine( &tr, light->origin, RI.viewOrigin, FTRACE_IGNORE_GLASS ); - if( tr.fraction != 1.0f ) - continue; - - mb = R_AddMeshToList( MB_CORONA, NULL, r_coronaShader, -((signed int)i + 1 )); - if( mb ) mb->shaderkey |= ( bound( 1, 0x4000 - (uint)dist, 0x4000 - 1 ) << 12 ); - } -} - -//=================================================================== -/* -================= -R_ReadLightGrid -================= -*/ -static void R_ReadLightGrid( const vec3_t origin, vec3_t lightDir ) -{ - vec3_t vf1, vf2, tdir; - int vi[3], elem[4]; - float scale[8]; - int i, k, s; - - if( !r_worldbrushmodel->lightgrid ) - { - // pre-defined light vector - VectorSet( lightDir, RI.refdef.movevars->skyvec_x, RI.refdef.movevars->skyvec_y, RI.refdef.movevars->skyvec_z ); - return; - } - - for( i = 0; i < 3; i++ ) - { - vf1[i] = (origin[i] - r_worldbrushmodel->gridMins[i]) / r_worldbrushmodel->gridSize[i]; - vi[i] = (int)vf1[i]; - vf1[i] = vf1[i] - floor( vf1[i] ); - vf2[i] = 1.0f - vf1[i]; - } - - elem[0] = vi[2] * r_worldbrushmodel->gridBounds[3] + vi[1] * r_worldbrushmodel->gridBounds[0] + vi[0]; - elem[1] = elem[0] + r_worldbrushmodel->gridBounds[0]; - elem[2] = elem[0] + r_worldbrushmodel->gridBounds[3]; - elem[3] = elem[2] + r_worldbrushmodel->gridBounds[0]; - - for( i = 0; i < 4; i++ ) - { - if( elem[i] < 0 || elem[i] >= r_worldbrushmodel->numgridpoints - 1 ) - { - VectorSet( lightDir, 1.0f, 0.0f, -1.0f ); - return; - } - } - - scale[0] = vf2[0] * vf2[1] * vf2[2]; - scale[1] = vf1[0] * vf2[1] * vf2[2]; - scale[2] = vf2[0] * vf1[1] * vf2[2]; - scale[3] = vf1[0] * vf1[1] * vf2[2]; - scale[4] = vf2[0] * vf2[1] * vf1[2]; - scale[5] = vf1[0] * vf2[1] * vf1[2]; - scale[6] = vf2[0] * vf1[1] * vf1[2]; - scale[7] = vf1[0] * vf1[1] * vf1[2]; - - VectorClear( lightDir ); - - for( i = 0; i < 4; i++ ) - { - R_LatLongToNorm( r_worldbrushmodel->lightgrid[elem[i]+0].direction, tdir ); - VectorScale( tdir, scale[i*2+0], tdir ); - - for( k = 0; k < LM_STYLES && ( s = r_worldbrushmodel->lightgrid[elem[i]+0].styles[k] ) != 255; k++ ) - { - lightDir[0] += r_lightStyles[s].rgb[0] * tdir[0]; - lightDir[1] += r_lightStyles[s].rgb[1] * tdir[1]; - lightDir[2] += r_lightStyles[s].rgb[2] * tdir[2]; - } - - R_LatLongToNorm( r_worldbrushmodel->lightgrid[elem[i]+1].direction, tdir ); - VectorScale( tdir, scale[i*2+1], tdir ); - - for( k = 0; k < LM_STYLES && ( s = r_worldbrushmodel->lightgrid[elem[i]+1].styles[k] ) != 255; k++ ) - { - lightDir[0] += r_lightStyles[s].rgb[0] * tdir[0]; - lightDir[1] += r_lightStyles[s].rgb[1] * tdir[1]; - lightDir[2] += r_lightStyles[s].rgb[2] * tdir[2]; - } - } -} - -/* -======================================================================= - - AMBIENT & DIFFUSE LIGHTING - -======================================================================= -*/ - -static vec3_t r_pointColor; -static vec3_t r_lightColors[MAX_ARRAY_VERTS]; - -/* -================= -R_RecursiveLightPoint -================= -*/ -static qboolean R_RecursiveLightPoint( mnode_t *node, const vec3_t start, const vec3_t end ) -{ - int side; - mplane_t *plane; - msurface_t *surf; - mtexinfo_t *tex; - vec3_t mid, scale; - float front, back, frac; - int i, map, size, s, t; - byte *lm; - - // didn't hit anything - if( !node->plane ) return false; - - // calculate mid point - plane = node->plane; - if( plane->type < 3 ) - { - front = start[plane->type] - plane->dist; - back = end[plane->type] - plane->dist; - } - else - { - front = DotProduct( start, plane->normal ) - plane->dist; - back = DotProduct( end, plane->normal ) - plane->dist; - } - - side = front < 0; - if(( back < 0 ) == side ) - return R_RecursiveLightPoint( node->children[side], start, end ); - - frac = front / ( front - back ); - - VectorLerp( start, frac, end, mid ); - - // co down front side - if( R_RecursiveLightPoint( node->children[side], start, mid )) - return true; // hit something - - if(( back < 0 ) == side ) - return false;// didn't hit anything - - // check for impact on this node - surf = node->firstface; - - for( i = 0; i < node->numfaces; i++, surf++ ) - { - tex = surf->texinfo; - - if( surf->flags & SURF_DRAWTILED ) - continue; // no lightmaps - - s = DotProduct( mid, tex->vecs[0] ) + tex->vecs[0][3] - surf->textureMins[0]; - t = DotProduct( mid, tex->vecs[1] ) + tex->vecs[1][3] - surf->textureMins[1]; - - if(( s < 0 || s > surf->extents[0] ) || ( t < 0 || t > surf->extents[1] )) - continue; - - s >>= 4; - t >>= 4; - - if( !surf->samples ) - return true; - - VectorClear( r_pointColor ); - - lm = surf->samples + 3 * (t * surf->lmWidth + s); - size = surf->lmWidth * surf->lmHeight * 3; - - for( map = 0; map < surf->numstyles; map++ ) - { - VectorScale( r_lightStyles[surf->styles[map]].rgb, r_lighting_modulate->value * (1.0 / 255), scale ); - - r_pointColor[0] += lm[0] * scale[0]; - r_pointColor[1] += lm[1] * scale[1]; - r_pointColor[2] += lm[2] * scale[2]; - - lm += size; // skip to next lightmap - } - - return true; - } - - // go down back side - return R_RecursiveLightPoint( node->children[!side], mid, end ); -} - -/* -================= -R_LightForPoint -================= -*/ -void R_LightForPoint( const vec3_t point, vec3_t ambientLight ) -{ - ref_dlight_t *dl; - vec3_t end, dir; - float dist, add; - int lnum; - - // set to full bright if no light data - if( !r_worldbrushmodel || !r_worldbrushmodel->lightdata ) - { - VectorSet( ambientLight, 1.0f, 1.0f, 1.0f ); - return; - } - - // Get lighting at this point - VectorSet( end, point[0], point[1], point[2] - 8192 ); - VectorSet( r_pointColor, 1.0f, 1.0f, 1.0f ); - - R_RecursiveLightPoint( r_worldbrushmodel->nodes, point, end ); - - VectorCopy( r_pointColor, ambientLight ); - - // add dynamic lights - if( r_dynamiclight->integer ) - { - for( lnum = 0, dl = r_dlights; lnum < r_numDlights; lnum++, dl++ ) - { - VectorSubtract( dl->origin, point, dir ); - dist = VectorLength( dir ); - - if( !dist || dist > dl->intensity ) - continue; - - add = ( dl->intensity - dist ) * ( 1.0f / 255 ); - VectorMA( ambientLight, add, dl->color, ambientLight ); - } - } -} - -/* -================= -R_LightDir -================= -*/ -void R_LightDir( const vec3_t origin, vec3_t lightDir, float radius ) -{ - ref_dlight_t *dl; - vec3_t dir; - float dist; - int lnum; - - // get light direction from light grid - R_ReadLightGrid( origin, lightDir ); - - // add dynamic lights - if( radius > 0.0f && r_dynamiclight->integer && r_numDlights ) - { - for( lnum = 0, dl = r_dlights; lnum < r_numDlights; lnum++, dl++ ) - { - if( !BoundsAndSphereIntersect( dl->mins, dl->maxs, origin, radius )) - continue; - - VectorSubtract( dl->origin, origin, dir ); - dist = VectorLength( dir ); - - if( !dist || dist > dl->intensity + radius ) - continue; - VectorAdd( lightDir, dir, lightDir ); - } - } -} - -/* -=============== -R_LightForOrigin -=============== -*/ -void R_LightForOrigin( const vec3_t origin, vec3_t dir, vec4_t ambient, vec4_t diffuse, float radius ) -{ - int i, j; - int k, s; - float dot, t[8]; - vec3_t vf, vf2, tdir; - int vi[3], elem[4]; - vec3_t ambientLocal, diffuseLocal; - vec_t *gridSize, *gridMins; - int *gridBounds; - mgridlight_t *lightgrid; - - if( !r_worldmodel || !r_worldbrushmodel->lightgrid || !r_worldbrushmodel->numgridpoints ) - { - // get fullbright - VectorSet( ambientLocal, 255, 255, 255 ); - VectorSet( diffuseLocal, 255, 255, 255 ); - VectorSet( dir, 0.5f, 0.2f, -1.0f ); - goto dynamic; - } - else - { - VectorSet( ambientLocal, 0, 0, 0 ); - VectorSet( diffuseLocal, 0, 0, 0 ); - } - - lightgrid = r_worldbrushmodel->lightgrid; - gridSize = r_worldbrushmodel->gridSize; - gridMins = r_worldbrushmodel->gridMins; - gridBounds = r_worldbrushmodel->gridBounds; - - for( i = 0; i < 3; i++ ) - { - vf[i] = ( origin[i] - gridMins[i] ) / gridSize[i]; - vi[i] = (int)vf[i]; - vf[i] = vf[i] - floor( vf[i] ); - vf2[i] = 1.0f - vf[i]; - } - - elem[0] = vi[2] * gridBounds[3] + vi[1] * gridBounds[0] + vi[0]; - elem[1] = elem[0] + gridBounds[0]; - elem[2] = elem[0] + gridBounds[3]; - elem[3] = elem[2] + gridBounds[0]; - - for( i = 0; i < 4; i++ ) - { - if( elem[i] < 0 || elem[i] >= ( r_worldbrushmodel->numgridpoints - 1 )) - { - VectorSet( dir, 0.5f, 0.2f, -1.0f ); - goto dynamic; - } - } - - t[0] = vf2[0] * vf2[1] * vf2[2]; - t[1] = vf[0] * vf2[1] * vf2[2]; - t[2] = vf2[0] * vf[1] * vf2[2]; - t[3] = vf[0] * vf[1] * vf2[2]; - t[4] = vf2[0] * vf2[1] * vf[2]; - t[5] = vf[0] * vf2[1] * vf[2]; - t[6] = vf2[0] * vf[1] * vf[2]; - t[7] = vf[0] * vf[1] * vf[2]; - - VectorClear( dir ); - - for( i = 0; i < 4; i++ ) - { - R_LatLongToNorm( lightgrid[elem[i]].direction, tdir ); - VectorScale( tdir, t[i*2+0], tdir ); - for( k = 0; k < LM_STYLES && ( s = lightgrid[elem[i]].styles[k] ) != 255; k++ ) - { - dir[0] += r_lightStyles[s].rgb[0] * tdir[0]; - dir[1] += r_lightStyles[s].rgb[1] * tdir[1]; - dir[2] += r_lightStyles[s].rgb[2] * tdir[2]; - } - - R_LatLongToNorm( lightgrid[elem[i] + 1].direction, tdir ); - VectorScale( tdir, t[i*2+1], tdir ); - for( k = 0; k < LM_STYLES && ( s = lightgrid[elem[i] + 1].styles[k] ) != 255; k++ ) - { - dir[0] += r_lightStyles[s].rgb[0] * tdir[0]; - dir[1] += r_lightStyles[s].rgb[1] * tdir[1]; - dir[2] += r_lightStyles[s].rgb[2] * tdir[2]; - } - } - - for( j = 0; j < 3; j++ ) - { - if( ambient ) - { - for( i = 0; i < 4; i++ ) - { - for( k = 0; k < LM_STYLES; k++ ) - { - if( ( s = lightgrid[elem[i]].styles[k] ) != 255 ) - ambientLocal[j] += t[i*2] * lightgrid[elem[i]].ambient[k][j] * r_lightStyles[s].rgb[j]; - if( ( s = lightgrid[elem[i] + 1].styles[k] ) != 255 ) - ambientLocal[j] += t[i*2+1] * lightgrid[elem[i] + 1].ambient[k][j] * r_lightStyles[s].rgb[j]; - } - } - } - if( diffuse || radius ) - { - for( i = 0; i < 4; i++ ) - { - for( k = 0; k < LM_STYLES; k++ ) - { - if( ( s = lightgrid[elem[i]].styles[k] ) != 255 ) - diffuseLocal[j] += t[i*2] * lightgrid[elem[i]].diffuse[k][j] * r_lightStyles[s].rgb[j]; - if( ( s = lightgrid[elem[i] + 1].styles[k] ) != 255 ) - diffuseLocal[j] += t[i*2+1] * lightgrid[elem[i] + 1].diffuse[k][j] * r_lightStyles[s].rgb[j]; - } - } - } - } - -dynamic: - // add dynamic lights - if( radius && r_dynamiclight->integer && r_numDlights ) - { - uint lnum; - ref_dlight_t *dl; - float dist, dist2, add; - vec3_t direction; - qboolean anyDlights = false; - - for( lnum = 0, dl = r_dlights; lnum < r_numDlights; lnum++, dl++ ) - { - if( !BoundsAndSphereIntersect( dl->mins, dl->maxs, origin, radius ) ) - continue; - - VectorSubtract( dl->origin, origin, direction ); - dist = VectorLength( direction ); - - if( !dist || dist > dl->intensity + radius ) - continue; - - if( !anyDlights ) - { - VectorNormalizeFast( dir ); - anyDlights = true; - } - - add = 1.0f - (dist / (dl->intensity + radius)); - dist2 = add * 0.5f / dist; - for( i = 0; i < 3; i++ ) - { - dot = dl->color[i] * add; - diffuseLocal[i] += dot; - ambientLocal[i] += dot * 0.05; - dir[i] += direction[i] * dist2; - } - } - } - - VectorNormalizeFast( dir ); - - if( ambient ) - { - dot = bound( 0.0f, r_lighting_ambientscale->value, 1.0f ) * ( 1.0f / 255.0f ); - for( i = 0; i < 3; i++ ) - { - ambient[i] = ambientLocal[i] * dot; - ambient[i] = bound( 0, ambient[i], 1 ); - } - ambient[3] = 1.0f; - } - - if( diffuse ) - { - dot = bound( 0.0f, r_lighting_directedscale->value, 1.0f ) * ( 1.0f / 255.0f ); - for( i = 0; i < 3; i++ ) - { - diffuse[i] = diffuseLocal[i] * dot; - diffuse[i] = bound( 0, diffuse[i], 1 ); - } - diffuse[3] = 1.0f; - } -} -/* -================= -R_LightForEntity -================= -*/ -void R_LightForEntity( ref_entity_t *e, byte *bArray ) -{ - ref_dlight_t *dl; - vec3_t end, dir; - float add, dot, dist, intensity, radius; - vec3_t ambientLight, directedLight, lightDir; - float *cArray; - int i, l; - - if(( e->flags & EF_FULLBRIGHT ) || r_fullbright->integer ) - return; - - // never gets diffuse lighting for world brushes - if( !e->model || ( e->model->type == mod_brush ) || ( e->model->type == mod_world )) - return; - - // get lighting at this point - VectorSet( end, e->lightingOrigin[0], e->lightingOrigin[1], e->lightingOrigin[2] - 8192 ); - VectorSet( r_pointColor, 1.0f, 1.0f, 1.0f ); - - R_RecursiveLightPoint( r_worldbrushmodel->nodes, e->lightingOrigin, end ); - - VectorScale( r_pointColor, r_lighting_ambientscale->value, ambientLight ); - VectorScale( r_pointColor, r_lighting_directedscale->value, directedLight ); - - R_ReadLightGrid( e->lightingOrigin, lightDir ); - - // always have some light - if( e->flags & EF_MINLIGHT ) - { - for( i = 0; i < 3; i++ ) - { - if( ambientLight[i] > 0.01f ) - break; - } - - if( i == 3 ) VectorSet( ambientLight, 0.01f, 0.01f, 0.01f ); - } - - // compute lighting at each vertex - - // rotate direction - Matrix3x3_Transform( e->axis, lightDir, dir ); - VectorNormalizeFast( dir ); - - for( i = 0; i < r_backacc.numColors; i++ ) - { - dot = DotProduct( normalsArray[i], dir ); - if( dot <= 0.0f ) VectorCopy( ambientLight, r_lightColors[i] ); - else VectorMA( ambientLight, dot, directedLight, r_lightColors[i] ); - } - - // add dynamic lights - if( r_dynamiclight->integer ) - { - if( e->rtype == RT_MODEL ) - radius = e->model->radius; - else radius = e->radius; - - for( l = 0, dl = r_dlights; l < r_numDlights; l++, dl++ ) - { - VectorSubtract( dl->origin, e->lightingOrigin, dir ); - dist = VectorLength( dir ); - - if( !dist || dist > dl->intensity + radius ) - continue; - - Matrix3x3_Transform( e->axis, dir, lightDir ); - intensity = dl->intensity * 8; - - // compute lighting at each vertex - for( i = 0; i < r_backacc.numColors; i++ ) - { - VectorSubtract( lightDir, vertsArray[i], dir ); - add = DotProduct( normalsArray[i], dir ); - if( add <= 0.0f ) continue; - - dot = DotProduct( dir, dir ); - add *= ( intensity / dot ) * rsqrt( dot ); - VectorMA( r_lightColors[i], add, dl->color, r_lightColors[i] ); - } - } - } - - cArray = r_lightColors[0]; - - for( i = 0; i < r_backacc.numColors; i++, bArray += 4, cArray += 3 ) - { - bArray[0] = R_FloatToByte( cArray[0] ); - bArray[1] = R_FloatToByte( cArray[1] ); - bArray[2] = R_FloatToByte( cArray[2] ); - } -} - -/* -======================================================================= - - LIGHT SAMPLING - -======================================================================= -*/ -static vec3_t r_blockLights[LIGHTMAP_TEXTURE_WIDTH*LIGHTMAP_TEXTURE_HEIGHT]; - -/* -================= -R_SetCacheState -================= -*/ -static void R_SetCacheState( msurface_t *surf ) -{ - int map; - - for( map = 0; map < surf->numstyles; map++ ) - surf->cached[map] = r_lightStyles[surf->styles[map]].white; -} - -/* -================= -R_BuildLightmap - -combine and scale multiple lightmaps into the -floating format in r_blockLights -================= -*/ -static void R_BuildLightmap( msurface_t *surf, byte *dest, int stride ) -{ - int i, map, size, s, t; - byte *lm; - vec3_t scale; - float *bl, max; - - lm = surf->samples; - size = surf->lmWidth * surf->lmHeight; - - if( !lm ) - { - // set to full bright if no light data - for( i = 0, bl = r_blockLights[0]; i < size; i++, bl += 3 ) - { - bl[0] = 255; - bl[1] = 255; - bl[2] = 255; - } - } - else - { - // add all the lightmaps - VectorScale( r_lightStyles[surf->styles[0]].rgb, r_lighting_modulate->value, scale ); - - for( i = 0, bl = r_blockLights[0]; i < size; i++, bl += 3, lm += 3 ) - { - bl[0] = lm[0] * scale[0]; - bl[1] = lm[1] * scale[1]; - bl[2] = lm[2] * scale[2]; - } - - if( surf->numstyles > 1 ) - { - for( map = 1; map < surf->numstyles; map++ ) - { - VectorScale( r_lightStyles[surf->styles[map]].rgb, r_lighting_modulate->value, scale ); - - for( i = 0, bl = r_blockLights[0]; i < size; i++, bl += 3, lm += 3 ) - { - bl[0] += lm[0] * scale[0]; - bl[1] += lm[1] * scale[1]; - bl[2] += lm[2] * scale[2]; - } - } - } - } - - // put into texture format - stride -= (surf->lmWidth << 2); - bl = r_blockLights[0]; - - for( t = 0; t < surf->lmHeight; t++ ) - { - for( s = 0; s < surf->lmWidth; s++ ) - { - // catch negative lights - if( bl[0] < 0.0f ) bl[0] = 0.0f; - if( bl[1] < 0.0f ) bl[1] = 0.0f; - if( bl[2] < 0.0f ) bl[2] = 0.0f; - - // Determine the brightest of the three color components - max = VectorMax( bl ); - - // rescale all the color components if the intensity of the - // greatest channel exceeds 255 - if( max > 255.0f ) - { - max = 255.0f / max; - - dest[0] = bl[0] * max; - dest[1] = bl[1] * max; - dest[2] = bl[2] * max; - dest[3] = 255; - } - else - { - dest[0] = bl[0]; - dest[1] = bl[1]; - dest[2] = bl[2]; - dest[3] = 255; - } - - bl += 3; - dest += 4; - } - dest += stride; - } -} - -/* -======================================================================= - - LIGHTSTYLE HANDLING - -======================================================================= -*/ -/* -======================= -R_AddSuperLightStyle -======================= -*/ -int R_AddSuperLightStyle( const int lightmapNum, const byte *lightmapStyles ) -{ - int i, j; - ref_style_t *sls; - - for( i = 0, sls = tr.superLightStyles; i < tr.numSuperLightStyles; i++, sls++ ) - { - if( sls->lightmapNum != lightmapNum ) - continue; - - for( j = 0; j < LM_STYLES; j++ ) - { - if( sls->lightmapStyles[j] != lightmapStyles[j] ) - break; - } - if( j == LM_STYLES ) - return i; - } - - if( tr.numSuperLightStyles == MAX_SUPER_STYLES ) - Host_Error( "R_AddSuperLightStyle: MAX_SUPERSTYLES limit exceeded\n" ); - - // create new style - sls->features = 0; - sls->lightmapNum = lightmapNum; - - for( j = 0; j < LM_STYLES; j++ ) - { - sls->lightmapStyles[j] = lightmapStyles[j]; - - if( j ) - { - if( lightmapStyles[j] != 255 ) - sls->features |= ( MF_LMCOORDS << j ); - } - } - return tr.numSuperLightStyles++; -} - -/* -======================================================================= - - LIGHTMAP ALLOCATION - -======================================================================= -*/ -typedef struct -{ - int currentNum; - int allocated[LIGHTMAP_TEXTURE_WIDTH]; - byte buffer[LIGHTMAP_TEXTURE_WIDTH*LIGHTMAP_TEXTURE_HEIGHT*4]; -} lmState_t; - -static lmState_t r_lmState; - -/* -================= - R_UploadLightmap -================= -*/ -static void R_UploadLightmap( void ) -{ - string lmName; - rgbdata_t r_image; - texture_t *image; - - if( r_lmState.currentNum == MAX_LIGHTMAPS - 1 ) - Host_Error( "R_UploadLightmap: MAX_LIGHTMAPS limit exceeded\n" ); - - com.snprintf( lmName, sizeof( lmName ), "*lightmap%i", r_lmState.currentNum ); - - Mem_Set( &r_image, 0, sizeof( r_image )); - - r_image.width = LIGHTMAP_TEXTURE_WIDTH; - r_image.height = LIGHTMAP_TEXTURE_HEIGHT; - r_image.type = PF_RGBA_32; - r_image.size = r_image.width * r_image.height * 4; - r_image.flags = IMAGE_HAS_COLOR; // FIXME: detecting grayscale lightmaps for quake1 - r_image.buffer = r_lmState.buffer; - - image = R_LoadTexture( lmName, &r_image, 0, TF_LIGHTMAP|TF_NOPICMIP|TF_UNCOMPRESSED|TF_CLAMP|TF_NOMIPMAP ); - tr.lightmapTextures[r_lmState.currentNum++] = image; - - // reset - Mem_Set( r_lmState.allocated, 0, sizeof( r_lmState.allocated )); - Mem_Set( r_lmState.buffer, 255, sizeof( r_lmState.buffer )); -} - -/* -================= -R_AllocLightmapBlock -================= -*/ -static byte *R_AllocLightmapBlock( int width, int height, int *s, int *t ) -{ - int i, j; - int best1, best2; - - best1 = LIGHTMAP_TEXTURE_HEIGHT; - - for( i = 0; i < LIGHTMAP_TEXTURE_WIDTH - width; i++ ) - { - best2 = 0; - - for( j = 0; j < width; j++ ) - { - if( r_lmState.allocated[i+j] >= best1 ) - break; - if( r_lmState.allocated[i+j] > best2 ) - best2 = r_lmState.allocated[i+j]; - } - - if( j == width ) - { - // this is a valid spot - *s = i; - *t = best1 = best2; - } - } - - if( best1 + height > LIGHTMAP_TEXTURE_HEIGHT ) - return NULL; - - for( i = 0; i < width; i++ ) - r_lmState.allocated[*s + i] = best1 + height; - - return r_lmState.buffer + (( *t * LIGHTMAP_TEXTURE_WIDTH + *s ) * 4 ); -} - -/* -================= -R_BeginBuildingLightmaps -================= -*/ -void R_BeginBuildingLightmaps( void ) -{ - int i; - - // setup the base lightstyles so the lightmaps won't have to be - // regenerated the first time they're seen - for( i = 0; i < MAX_LIGHTSTYLES; i++ ) - { - r_lightStyles[i].white = 3; - r_lightStyles[i].rgb[0] = 1; - r_lightStyles[i].rgb[1] = 1; - r_lightStyles[i].rgb[2] = 1; - } - - // release old lightmaps - for( i = 0; i < r_lmState.currentNum; i++ ) - { - if( !tr.lightmapTextures[i] ) continue; - R_FreeImage( tr.lightmapTextures[i] ); - } - - r_lmState.currentNum = -1; - tr.numSuperLightStyles = 0; - - Mem_Set( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures )); - Mem_Set( r_lmState.allocated, 0, sizeof( r_lmState.allocated )); - Mem_Set( r_lmState.buffer, 255, sizeof( r_lmState.buffer )); -} - -/* -================= -R_EndBuildingLightmaps -================= -*/ -void R_EndBuildingLightmaps( void ) -{ - if( r_lmState.currentNum == -1 ) - return; - - R_UploadLightmap(); -} - -/* -================= -R_BuildSurfaceLightmap -================= -*/ -void R_BuildSurfaceLightmap( msurface_t *surf ) -{ - byte *base; - - if( !R_SurfPotentiallyLit( surf )) - { - surf->lmNum = -1; - return; // no lightmaps - } - - base = R_AllocLightmapBlock( surf->lmWidth, surf->lmHeight, &surf->lmS, &surf->lmT ); - - if( !base ) - { - if( r_lmState.currentNum != -1 ) R_UploadLightmap(); - - base = R_AllocLightmapBlock( surf->lmWidth, surf->lmHeight, &surf->lmS, &surf->lmT ); - if( !base ) Host_Error( "AllocBlock: full\n" ); - } - - if( r_lmState.currentNum == -1 ) - r_lmState.currentNum = 0; - - surf->lmNum = r_lmState.currentNum; - - R_SetCacheState( surf ); - R_BuildLightmap( surf, base, LIGHTMAP_TEXTURE_WIDTH * 4 ); -} - -/* -================= -R_UpdateSurfaceLightmap -================= -*/ -void R_UpdateSurfaceLightmap( msurface_t *surf ) -{ - int map; - - ASSERT( surf ); - - // is this surface allowed to have a lightmap? - if( !R_SurfPotentiallyLit( surf )) - return; - - // dynamic this frame or dynamic previously - if( r_dynamiclight->integer ) - { - for( map = 0; map < surf->numstyles; map++ ) - { - if( r_lightStyles[surf->styles[map]].white != surf->cached[map] ) - goto update_lightmap; - } - } - - // no need to update - return; - -update_lightmap: - R_SetCacheState( surf ); - R_BuildLightmap( surf, r_lmState.buffer, surf->lmWidth * 4 ); - - GL_Bind( 0, tr.lightmapTextures[surf->lmNum] ); - - pglTexSubImage2D( GL_TEXTURE_2D, 0, surf->lmS, surf->lmT, surf->lmWidth, surf->lmHeight, - GL_RGBA, GL_UNSIGNED_BYTE, r_lmState.buffer ); -} \ No newline at end of file diff --git a/vid_gl/r_local.h b/vid_gl/r_local.h deleted file mode 100644 index 46948dc0..00000000 --- a/vid_gl/r_local.h +++ /dev/null @@ -1,873 +0,0 @@ -/* -Copyright (C) 1997-2001 Id Software, Inc. -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#ifndef __R_LOCAL_H__ -#define __R_LOCAL_H__ - -#include -#include "launch_api.h" -#include "engine_api.h" -#include "render_api.h" -#include "pmtrace.h" -#include "entity_types.h" - -#if defined( _MSC_VER ) && ( _MSC_VER >= 1400 ) -# define ALIGN(x) __declspec(align(16)) -#else -# define ALIGN(x) -#endif - -#include "r_opengl.h" - -extern stdlib_api_t com; // engine toolbox -extern render_imp_t ri; -extern byte *r_temppool; -#define Host_Error com.error - -typedef unsigned int elem_t; -typedef enum { RT_NONE, RT_MODEL, RT_PORTALSURFACE, NUM_RTYPES } refEntityType_t; - -/* -skins will be outline flood filled and mip mapped -pics and sprites with alpha will be outline flood filled -pic won't be mip mapped - -model skin -sprite frame -wall texture -pic -*/ -typedef enum -{ - TEX_UNKNOWN = 0, // not passed with R_GetPixelFormat, ignore it - TEX_SYSTEM, // generated by engine - TEX_NOMIP, // hud pics, menu etc - TEX_GENERIC, // models, sprites etc - TEX_LIGHTMAP, // lightmap textures - TEX_ALPHA, // with alpha-channel - TEX_SKYBOX, // skybox textures -} texType_t; - -typedef enum -{ - TF_STATIC = BIT(0), // don't free until Shader_FreeUnused() - TF_NOPICMIP = BIT(1), // ignore r_picmip resample rules - TF_UNCOMPRESSED = BIT(2), // don't compress texture in video memory - TF_CUBEMAP = BIT(3), // it's cubemap texture - TF_NORMALMAP = BIT(4), // needs to be merged with depthmap - TF_DEPTHMAP = BIT(5), // custom texture filter used - TF_INTENSITY = BIT(6), - TF_ALPHA = BIT(7), - TF_SKYSIDE = BIT(8), - TF_CLAMP = BIT(9), - TF_NOMIPMAP = BIT(10), - TF_NEAREST = BIT(11), // disable texfilter - TF_LIGHTMAP = BIT(12), // no resample etc -} texFlags_t; - -#define TF_PORTALMAP ( TF_NOMIPMAP|TF_UNCOMPRESSED|TF_NOPICMIP|TF_CLAMP ) -#define TF_SHADOWMAP ( TF_NOMIPMAP|TF_UNCOMPRESSED|TF_NOPICMIP|TF_CLAMP|TF_DEPTHMAP ) - -typedef struct texture_s -{ - string name; // game path, including extension - int srcWidth; // source dims, used for mipmap loading - int srcHeight; - int srcFlags; // rgbdata flags - - int width; // upload width\height - int height; - - texType_t texType; // just for debug - texFlags_t flags; - size_t size; // upload size for debug targets - - GLint format; // PFDesc[type].glType - GLuint target; // glTarget - GLuint texnum; // gl texture binding - GLint samples; // gl samples - - int touchFrame; // 0 = free - struct texture_s *nextHash; -} texture_t; - -enum -{ - TEXTURE_UNIT0, - TEXTURE_UNIT1, - TEXTURE_UNIT2, - TEXTURE_UNIT3, - TEXTURE_UNIT4, - TEXTURE_UNIT5, - TEXTURE_UNIT6, - TEXTURE_UNIT7, - MAX_TEXTURE_UNITS -}; - -#define FOG_TEXTURE_WIDTH 256 -#define FOG_TEXTURE_HEIGHT 32 - -#define LIGHTMAP_TEXTURE_WIDTH 256 -#define LIGHTMAP_TEXTURE_HEIGHT 256 - -#define VID_DEFAULTMODE "3" - -#define SHADOW_PLANAR 1 -#define SHADOW_MAPPING 2 -#define LM_STYLES 4 // MAXLIGHTMAPS - -#define MAX_ENTITIES 2048 // per one frame -#define MAX_POLY_VERTS 3000 -#define MAX_POLYS 2048 - -typedef struct mplane_s -{ - vec3_t normal; - float dist; - short type; // for fast side tests - short signbits; // signx + (signy<<1) + (signz<<1) -} mplane_t; - -//=================================================================== - -#include "r_math.h" -#include "r_mesh.h" -#include "r_shader.h" -#include "r_backend.h" -#include "r_shadow.h" -#include "r_model.h" - -#define BACKFACE_EPSILON 0.01 - -#define Z_NEAR 4 - -#define SIDE_FRONT 0 -#define SIDE_BACK 1 -#define SIDE_ON 2 - -// renderer flags -#define RDF_PORTALINVIEW BIT( 0 ) // draw portal pass -#define RDF_SKYPORTALINVIEW BIT( 1 ) // draw skyportal instead of regular sky - -#define RP_NONE 0x0 -#define RP_MIRRORVIEW 0x1 // lock pvs at vieworg -#define RP_PORTALVIEW 0x2 -#define RP_ENVVIEW 0x4 -#define RP_NOSKY 0x8 -#define RP_SKYPORTALVIEW 0x10 -#define RP_PORTALCAPTURED 0x20 -#define RP_PORTALCAPTURED2 0x40 -#define RP_OLDVIEWLEAF 0x80 -#define RP_SHADOWMAPVIEW 0x100 -#define RP_FLIPFRONTFACE 0x200 -#define RP_WORLDSURFVISIBLE 0x400 -#define RP_CLIPPLANE 0x800 -#define RP_TRISOUTLINES 0x1000 -#define RP_SHOWNORMALS 0x2000 - -#define RP_NONVIEWERREF ( RP_PORTALVIEW|RP_MIRRORVIEW|RP_ENVVIEW|RP_SKYPORTALVIEW|RP_SHADOWMAPVIEW ) -#define RP_LOCALCLIENT(e) (ri.GetLocalPlayer() && ((e)->index == ri.GetLocalPlayer()->index && e->lerp->player )) -#define RP_FOLLOWENTITY(e) (((e)->movetype == MOVETYPE_FOLLOW && (e)->parent)) -#define MOD_ALLOWBUMP() (r_lighting_models_followdeluxe->integer ? mapConfig.deluxeMappingEnabled : GL_Support( R_SHADER_GLSL100_EXT )) - -//==================================================== -typedef struct -{ - vec3_t origin; - vec3_t color; // dlight color - float intensity; // cdlight->radius - vec3_t mins, maxs; - ref_shader_t *shader; - int flags; // misc flags -} ref_dlight_t; - -typedef struct -{ - vec3_t rgb; // 0.0 - 2.0 - float white; // highest of RGB -} lightstyle_t; - -// FIXME: compress this as much as possible -typedef struct ref_entity_s -{ - uint ent_type; // entity type - uint m_nCachedFrameCount;// keep current render frame - int index; // viewmodel has entindex -1 - refEntityType_t rtype; - qboolean doOcclusionTest; // check this entity for occlusion - - struct ref_model_s *model; // opaque type outside refresh - struct ref_entity_s *parent; // link to parent entity (FOLLOW or weaponmodel) - struct cl_entity_s *lerp; // pointer to client entity - - float framerate; // custom framerate - float frame; - - int body; - int skin; - - int movetype; // entity moving type - float scale; - - byte *mempool; // studio mempool - void *extradata; // studiomodel bones, etc - - // misc - rgb_t rendercolor; // hl1 rendercolor - byte renderamt; // hl1 alphavalues - int rendermode; // hl1 rendermode - int renderfx; // server will be translate hl1 values into flags - int colormap; // q1 and hl1 model colormap (can applied for sprites) - int flags; // q1 effect flags, EF_LIGHT, EF_DIMLIGHT etc - - // client gait sequence (local stuff) - int gaitsequence; // client->sequence + yaw - - // most recent data - vec3_t axis[3]; - vec3_t angles; - vec3_t movedir; // forward vector that computed on a server - vec3_t origin, origin2; - vec3_t lightingOrigin; - float waveHeight; - - // RT_SPRITE stuff - struct ref_shader_s *customShader; // client drawing stuff - float radius; // used as RT_SPRITE's radius -} ref_entity_t; - -typedef struct skyportal_s -{ - float fov; - float scale; - vec3_t vieworg; - vec3_t viewangles; -} skyportal_t; - -typedef struct -{ - int params; // rendering parameters - int rdflags; // actual rendering flags - - ref_params_t refdef; - int scissor[4]; - int viewport[4]; - float lerpFrac; // lerpfraction - qboolean drawWorld; // ignore world for drawing PlayerModel - qboolean thirdPerson; // thirdperson camera is enabled - - meshlist_t *meshlist; // meshes to be rendered - meshbuffer_t **surfmbuffers; // pointers to meshbuffers of world surfaces - - uint shadowBits; - shadowGroup_t *shadowGroup; - - ref_entity_t *currententity; - ref_model_t *currentmodel; - ref_entity_t *previousentity; - - // - // view origin - // - vec3_t viewOrigin; - vec3_t viewAxis[3]; - vec_t *vup, *vpn, *vright; - mplane_t frustum[6]; - float farClip; - uint clipFlags; - vec3_t visMins, visMaxs; - - matrix4x4 objectMatrix; - matrix4x4 worldviewMatrix; - matrix4x4 modelviewMatrix; // worldviewMatrix * objectMatrix - - matrix4x4 projectionMatrix; - matrix4x4 worldviewProjectionMatrix; // worldviewMatrix * projectionMatrix - - float skyMins[2][6]; - float skyMaxs[2][6]; - - skyportal_t skyportal; // skyportal params - - float fog_dist_to_eye[256]; // MAX_MAP_FOGS - - vec3_t pvsOrigin; - mplane_t clipPlane; - mplane_t portalPlane; -} refinst_t; - -//==================================================== -extern int r_pvsframecount; -extern int r_framecount; -extern int r_framecount2; -extern int c_brush_polys, c_world_leafs; - -extern double r_mark_leaves, r_world_node; -extern double r_add_polys, r_add_entities; -extern double r_sort_meshes, r_draw_meshes; - -extern msurface_t *r_debug_surface; -extern const char *r_debug_hitbox; - -extern int gl_filter_min, gl_filter_max; - -#define MAX_RSPEEDSMSGSIZE 1024 -extern char r_speeds_msg[MAX_RSPEEDSMSGSIZE]; - -extern ref_model_t *cl_models[MAX_MODELS]; - -extern float gldepthmin, gldepthmax; - -// -// screen size info -// -extern uint r_numEntities; -extern ref_entity_t r_entities[MAX_ENTITIES]; - -extern uint r_numDlights; -extern ref_dlight_t r_dlights[MAX_DLIGHTS]; - -extern uint r_numPolys; -extern poly_t r_polys[MAX_POLYS]; - -extern lightstyle_t r_lightStyles[MAX_LIGHTSTYLES]; - -extern ref_params_t r_lastRefdef; - -extern mleaf_t *r_viewleaf, *r_oldviewleaf; -extern mleaf_t *r_viewleaf2, *r_oldviewleaf2; - -extern float r_farclip_min, r_farclip_bias; - -extern ref_entity_t *r_worldent; -extern ref_model_t *r_worldmodel; -extern mbrushmodel_t *r_worldbrushmodel; - -extern convar_t *r_colorbits; -extern convar_t *r_depthbits; -extern convar_t *r_stencilbits; -extern convar_t *r_norefresh; -extern convar_t *r_drawentities; -extern convar_t *r_drawworld; -extern convar_t *r_speeds; -extern convar_t *r_drawelements; -extern convar_t *r_fullbright; -extern convar_t *r_lightmap; -extern convar_t *r_novis; -extern convar_t *r_nocull; -extern convar_t *r_ignorehwgamma; -extern convar_t *r_overbrightbits; -extern convar_t *r_vertexbuffers; -extern convar_t *r_lefthand; -extern convar_t *r_physbdebug; -extern convar_t *r_check_errors; -extern convar_t *r_allow_software; -extern convar_t *r_frontbuffer; -extern convar_t *r_adjust_fov; -extern convar_t *r_width; -extern convar_t *r_height; - -extern convar_t *r_flares; -extern convar_t *r_flaresize; -extern convar_t *r_flarefade; -extern convar_t *r_spriteflares; -extern convar_t *r_cullflares; - -extern convar_t *r_dynamiclight; -extern convar_t *r_coronascale; -extern convar_t *r_detailtextures; -extern convar_t *r_subdivisions; -extern convar_t *r_faceplanecull; -extern convar_t *gl_wireframe; -extern convar_t *r_shownormals; -extern convar_t *r_showtextures; -extern convar_t *r_draworder; - -extern convar_t *r_fastsky; -extern convar_t *r_portalonly; -extern convar_t *r_portalmaps; -extern convar_t *r_portalmaps_maxtexsize; - -extern convar_t *r_lighting_bumpscale; -extern convar_t *r_lighting_deluxemapping; -extern convar_t *r_lighting_diffuse2heightmap; -extern convar_t *r_lighting_specular; -extern convar_t *r_lighting_glossintensity; -extern convar_t *r_lighting_glossexponent; -extern convar_t *r_lighting_models_followdeluxe; -extern convar_t *r_lighting_ambientscale; -extern convar_t *r_lighting_directedscale; -extern convar_t *r_lighting_modulate; - -extern convar_t *r_offsetmapping; -extern convar_t *r_offsetmapping_scale; -extern convar_t *r_offsetmapping_reliefmapping; - -extern convar_t *r_occlusion_queries; -extern convar_t *r_occlusion_queries_finish; - -extern convar_t *r_shadows; -extern convar_t *r_shadows_alpha; -extern convar_t *r_shadows_nudge; -extern convar_t *r_shadows_projection_distance; -extern convar_t *r_shadows_maxtexsize; -extern convar_t *r_shadows_pcf; -extern convar_t *r_shadows_self_shadow; - -extern convar_t *r_bloom_alpha; -extern convar_t *r_bloom_diamond_size; -extern convar_t *r_bloom_intensity; -extern convar_t *r_bloom_darken; -extern convar_t *r_bloom_sample_size; -extern convar_t *r_bloom_fast_sample; - -extern convar_t *r_himodels; -extern convar_t *r_environment_color; -extern convar_t *r_gamma; -extern convar_t *r_texturebits; -extern convar_t *gl_texturemode; -extern convar_t *gl_texture_anisotropy; -extern convar_t *gl_texture_lodbias; -extern convar_t *gl_round_down; -extern convar_t *gl_compress_textures; -extern convar_t *r_decals; -extern convar_t *r_mode; -extern convar_t *r_nobind; -extern convar_t *r_picmip; -extern convar_t *r_skymip; -extern convar_t *gl_clear; -extern convar_t *r_lockpvs; -extern convar_t *r_swapInterval; - -extern convar_t *gl_finish; -extern convar_t *gl_delayfinish; -extern convar_t *gl_cull; -extern convar_t *gl_extensions; - -extern convar_t *vid_fullscreen; -extern convar_t *vid_multiscreen_head; -extern convar_t *vid_displayfrequency; - -//==================================================================== - -static _inline byte R_FloatToByte( float x ) -{ - union { - float f; - unsigned int i; - } f2i; - - // shift float to have 8bit fraction at base of number - f2i.f = x + 32768.0f; - f2i.i &= 0x7FFFFF; - - // then read as integer and kill float bits... - return ( byte )min( f2i.i, 255 ); -} - -float R_FastSin( float t ); -void R_LatLongToNorm( const byte latlong[2], vec3_t out ); -void NormToLatLong( const vec3_t normal, byte latlong[2] ); -void ColorToBytes( const float *color, byte *colorBytes ); - -//==================================================================== - -// -// r_bloom.c -// -void R_InitBloomTextures( void ); -void R_BloomBlend( const ref_params_t *fd ); - -// -// r_cull.c -// -enum -{ - OQ_NONE = -1, - OQ_ENTITY, - OQ_PLANARSHADOW, - OQ_SHADOWGROUP, - OQ_CUSTOM -}; - -#define OCCLUSION_QUERIES_CVAR_HACK( RI ) ( !(r_occlusion_queries->integer == 2 && r_shadows->integer != SHADOW_MAPPING) \ - || ((RI).rdflags & RDF_PORTALINVIEW) ) -#define OCCLUSION_QUERIES_ENABLED( RI ) ( GL_Support( R_OCCLUSION_QUERIES_EXT ) && r_occlusion_queries->integer && r_drawentities->integer \ - && !((RI).params & RP_NONVIEWERREF) && ((RI).drawWorld) \ - && OCCLUSION_QUERIES_CVAR_HACK( RI ) ) -#define OCCLUSION_OPAQUE_SHADER( s ) (((s)->sort == SORT_OPAQUE ) && ((s)->flags & SHADER_DEPTHWRITE ) && !(s)->numDeforms ) -#define OCCLUSION_TEST_ENTITY( e ) (((e)->doOcclusionTest ) || ((e)->ent_type == ET_VIEWENTITY )) - -void R_InitOcclusionQueries( void ); -void R_BeginOcclusionPass( void ); -ref_shader_t *R_OcclusionShader( void ); -void R_AddOccludingSurface( msurface_t *surf, ref_shader_t *shader ); -int R_GetOcclusionQueryNum( int type, int key ); -int R_IssueOcclusionQuery( int query, ref_entity_t *e, vec3_t mins, vec3_t maxs ); -qboolean R_OcclusionQueryIssued( int query ); -uint R_GetOcclusionQueryResult( int query, qboolean wait ); -qboolean R_GetOcclusionQueryResultBool( int type, int key, qboolean wait ); -void R_EndOcclusionPass( void ); -void R_ShutdownOcclusionQueries( void ); - -// -// r_draw.c -// -void R_Set2DMode( qboolean enable ); -void R_DrawSetColor( const void *data ); -void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, shader_t shadernum ); -void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean redraw ); -void R_DrawSetParms( shader_t handle, int rendermode, int frame ); -void R_DrawGetParms( int *w, int *h, int *f, int frame, shader_t shader ); -void Tri_RenderMode( const int mode ); -void Tri_Normal3f( const float x, const float y, const float z ); -void Tri_Vertex3f( const float x, const float y, const float z ); -void Tri_Color4ub( const byte r, const byte g, const byte b, const byte a ); -void Tri_Fog( float flFogColor[3], float flStart, float flEnd, int bOn ); -void Tri_TexCoord2f( const float u, const float v ); -void Tri_Bind( shader_t shader, int frame ); -void Tri_RenderCallback( int fTrans ); -void Tri_CullFace( int mode ); -void Tri_Begin( int mode ); -void Tri_End( void ); - -// -// r_image.c -// -void GL_SelectTexture( GLenum tmu ); -void GL_Bind( GLenum tmu, texture_t *tex ); -void GL_TexEnv( GLenum mode ); -void GL_LoadMatrix( const matrix4x4 source ); -void GL_LoadTexMatrix( const matrix4x4 m ); -void GL_LoadIdentityTexMatrix( void ); -void GL_EnableTexGen( int coord, int mode ); -void GL_SetTexCoordArrayMode( int mode ); -void GL_TexFilter( texture_t *tex ); - -void R_InitImages( void ); -void R_ShutdownImages( void ); -void R_InitPortalTexture( texture_t **texture, int id, int screenWidth, int screenHeight ); -void R_InitShadowmapTexture( texture_t **texture, int id, int screenWidth, int screenHeight ); -void R_FreeImage( texture_t *image ); - -void R_TextureList_f( void ); -void R_SetTextureParameters( void ); -void R_ShowTextures( void ); - -texture_t *R_LoadTexture( const char *name, rgbdata_t *pic, int samples, texFlags_t flags ); -texture_t *R_FindTexture( const char *name, const byte *buf, size_t size, texFlags_t flags ); - -qboolean VID_ScreenShot( const char *filename, int shot_type ); -qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot ); - -// -// r_light.c -// -void R_BeginBuildingLightmaps( void ); -void R_BuildSurfaceLightmap( msurface_t *surf ); -void R_EndBuildingLightmaps( void ); - -void R_UpdateSurfaceLightmap( msurface_t *surf ); -void R_LightBounds( const vec3_t origin, float intensity, vec3_t mins, vec3_t maxs ); -qboolean R_SurfPotentiallyLit( msurface_t *surf ); -uint R_AddSurfDlighbits( msurface_t *surf, uint dlightbits ); -void R_AddDynamicLights( uint dlightbits, int state ); -void R_LightForEntity( ref_entity_t *e, byte *bArray ); -void R_LightForOrigin( const vec3_t origin, vec3_t dir, vec4_t ambient, vec4_t diffuse, float radius ); -void R_LightForPoint( const vec3_t point, vec3_t ambientLight ); -void R_LightDir( const vec3_t origin, vec3_t lightDir, float radius ); -int R_AddSuperLightStyle( const int lightmapNum, const byte *lightmapStyles ); -void R_BuildLightGrid( mbrushmodel_t *world ); -void R_InitCoronas( void ); -void R_DrawCoronas( void ); - -// -// r_main.c -// -void GL_Cull( int cull ); -void GL_SetState( int state ); -void GL_FrontFace( int front ); -void R_BeginFrame( qboolean clearScene ); -void R_EndFrame( void ); -void R_RenderScene( const ref_params_t *fd, qboolean drawWorld ); -void R_RenderView( const ref_params_t *fd ); -void R_ClearScene( void ); - -qboolean R_CullBox( const vec3_t mins, const vec3_t maxs, const uint clipflags ); -qboolean R_CullSphere( const vec3_t centre, const float radius, const uint clipflags ); -qboolean R_VisCullBox( const vec3_t mins, const vec3_t maxs ); -qboolean R_VisCullSphere( const vec3_t origin, float radius ); -int R_CullModel( ref_entity_t *e, vec3_t mins, vec3_t maxs, float radius ); - -mfog_t *R_FogForSphere( const vec3_t centre, const float radius ); -qboolean R_CompletelyFogged( mfog_t *fog, vec3_t origin, float radius ); - -void R_LoadIdentity( void ); -void R_RotateForEntity( ref_entity_t *e ); -void R_TranslateForEntity( ref_entity_t *e ); -qboolean R_TransformToScreen_Vec3( const vec3_t in, vec3_t out ); -void R_TransformVectorToScreen( const ref_params_t *rd, const vec3_t in, vec2_t out ); -void R_TransformEntityBBox( ref_entity_t *e, vec3_t mins, vec3_t maxs, vec3_t bbox[8], qboolean local ); - -qboolean R_SpriteOverflow( void ); -qboolean R_PushSpritePoly( const meshbuffer_t *mb ); -qboolean R_PushSprite( const meshbuffer_t *mb, int type, float right, float left, float up, float down ); - -#define NUM_CUSTOMCOLORS 16 -void R_InitCustomColors( void ); -void R_SetCustomColor( int num, int r, int g, int b ); -int R_GetCustomColor( int num ); - -msurface_t *R_TraceLine( pmtrace_t *tr, const vec3_t start, const vec3_t end, int flags ); - -// -// r_mesh.c -// - -extern meshlist_t r_worldlist, r_shadowlist; - -void R_InitMeshLists( void ); -void R_FreeMeshLists( void ); -void R_ClearMeshList( meshlist_t *meshlist ); -int R_ReAllocMeshList( meshbuffer_t **mb, int minMeshes, int maxMeshes ); -meshbuffer_t *R_AddMeshToList( int type, mfog_t *fog, ref_shader_t *shader, int infokey ); -void R_AddModelMeshToList( unsigned int modhandle, mfog_t *fog, ref_shader_t *shader, int meshnum ); -void R_AllocMeshbufPointers( refinst_t *RI ); - -void R_SortMeshes( void ); -void R_DrawMeshes( void ); -void R_DrawTriangleOutlines( qboolean showTris, qboolean showNormals ); -void R_DrawPortals( void ); - -void R_DrawCubemapView( const vec3_t origin, const vec3_t angles, int size ); -void R_DrawSkyPortal( skyportal_t *skyportal, vec3_t mins, vec3_t maxs ); - -void R_BuildTangentVectors( int numVertexes, vec4_t *xyzArray, vec4_t *normalsArray, vec2_t *stArray, int numTris, elem_t *elems, vec4_t *sVectorsArray ); - -// -// r_program.c -// -#define DEFAULT_GLSL_PROGRAM "*r_defaultProgram" -#define DEFAULT_GLSL_DISTORTION_PROGRAM "*r_defaultDistortionProgram" -#define DEFAULT_GLSL_SHADOWMAP_PROGRAM "*r_defaultShadowmapProgram" - -enum -{ - PROGRAM_TYPE_NONE, - PROGRAM_TYPE_MATERIAL, - PROGRAM_TYPE_DISTORTION, - PROGRAM_TYPE_SHADOWMAP, -}; - -enum -{ - PROGRAM_APPLY_LIGHTSTYLE0 = 1 << 0, - PROGRAM_APPLY_LIGHTSTYLE1 = 1 << 1, - PROGRAM_APPLY_LIGHTSTYLE2 = 1 << 2, - PROGRAM_APPLY_LIGHTSTYLE3 = 1 << 3, - PROGRAM_APPLY_SPECULAR = 1 << 4, - PROGRAM_APPLY_DIRECTIONAL_LIGHT = 1 << 5, - PROGRAM_APPLY_FB_LIGHTMAP = 1 << 6, - PROGRAM_APPLY_OFFSETMAPPING = 1 << 7, - PROGRAM_APPLY_RELIEFMAPPING = 1 << 8, - PROGRAM_APPLY_AMBIENT_COMPENSATION = 1 << 9, - PROGRAM_APPLY_DECAL = 1 << 10, - PROGRAM_APPLY_BASETEX_ALPHA_ONLY = 1 << 11, - - PROGRAM_APPLY_EYEDOT = 1 << 12, - PROGRAM_APPLY_DISTORTION_ALPHA = 1 << 13, - - PROGRAM_APPLY_PCF2x2 = 1 << 14, - PROGRAM_APPLY_PCF3x3 = 1 << 15, - - PROGRAM_APPLY_BRANCHING = 1 << 16, - PROGRAM_APPLY_CLIPPING = 1 << 17, - PROGRAM_APPLY_NO_HALF_TYPES = 1 << 18 -}; - -void R_InitGLSLPrograms( void ); -int R_FindGLSLProgram( const char *name ); -int R_RegisterGLSLProgram( const char *name, const char *string, unsigned int features ); -int R_GetProgramObject( int elem ); -void R_UpdateProgramUniforms( int elem, vec3_t eyeOrigin, vec3_t lightOrigin, vec3_t lightDir, - vec4_t ambient, vec4_t diffuse, ref_style_t *lightStyle, qboolean frontPlane, int TexWidth, int TexHeight, - float projDistance, float offsetmappingScale ); - -void R_ShutdownGLSLPrograms( void ); -void R_ProgramList_f( void ); -void R_ProgramDump_f( void ); - -// -// r_decals.c -// - -void R_InitDecals( void ); -void R_ClearDecals( void ); -void R_ShutdownDecals( void ); -qboolean R_DecalShoot( shader_t texture, int entity, int modelIndex, vec3_t pos, vec3_t saxis, int flags, rgba_t color, float fadeTime, float fadeDuration ); -decal_t *R_DecalFromMeshbuf( const meshbuffer_t *mb ); -int R_CreateDecalList( decallist_t *pList, qboolean changelevel ); -void R_AddSurfaceDecals( msurface_t *surf ); -void R_PushDecal( const meshbuffer_t *mb ); -void R_DecalRemoveAll( shader_t shader ); - -// -// r_poly.c -// -void R_PushPoly( const meshbuffer_t *mb ); -void R_AddPolysToList( void ); -msurface_t *R_TransformedTraceLine( pmtrace_t *tr, const vec3_t start, const vec3_t end, ref_entity_t *test, int flags ); - -// -// r_sprite.c -// - -void R_SpriteInit( void ); -mspriteframe_t *R_GetSpriteFrame( ref_model_t *pModel, int frame, float yawAngle ); -ref_shader_t *CL_LoadSprite( const char *szSpriteName ); -void R_DrawSpriteModel( const meshbuffer_t *mb ); -qboolean R_SpriteOccluded( ref_entity_t *e ); -qboolean R_CullSpriteModel( ref_entity_t *e ); -void R_SpriteDrawDebug( void ); - -// -// r_studio.c -// - -void R_AddStudioModelToList( ref_entity_t *e ); -void R_DrawStudioModel( const meshbuffer_t *mb ); -void R_StudioModelBBox( ref_entity_t *e, vec3_t mins, vec3_t maxs ); -qboolean R_CullStudioModel( ref_entity_t *e ); -void R_StudioRunEvents( ref_entity_t *e ); -void R_StudioDrawHitbox( ref_entity_t *e, int iHitbox ); -void R_StudioDrawDebug( void ); -void R_StudioInit( void ); -qboolean R_StudioTrace( ref_entity_t *e, const vec3_t start, const vec3_t end, pmtrace_t *tr ); -void R_StudioAllocExtradata( struct cl_entity_s *in, ref_entity_t *e ); -void R_StudioFreeAllExtradata( void ); -void R_StudioShutdown( void ); - -// -// -// r_register.c -// -void R_NewMap( void ); -qboolean R_Init( qboolean full ); -void R_Shutdown( qboolean full ); - -// -// r_opengl.c -// -void R_RestoreGamma( void ); -void R_CheckForErrors_( const char *filename, const int fileline ); -#define R_CheckForErrors() R_CheckForErrors_( __FILE__, __LINE__ ) - -// -// r_surf.c -// -#define MAX_SURF_QUERIES 0x1E0 - -void R_MarkLeaves( void ); -void R_DrawWorld( void ); -void R_BmodelDrawDebug( void ); -qboolean R_SurfPotentiallyVisible( msurface_t *surf ); -qboolean R_CullBrushModel( ref_entity_t *e ); -void R_AddBrushModelToList( ref_entity_t *e ); - -void R_ClearSurfOcclusionQueryKeys( void ); -int R_SurfOcclusionQueryKey( ref_entity_t *e, msurface_t *surf ); -void R_SurfIssueOcclusionQueries( void ); - -// -// r_sky.c -// -skydome_t *R_CreateSkydome( byte *mempool, float skyheight, ref_shader_t **farboxShaders, ref_shader_t **nearboxShaders ); -void R_FreeSkydome( skydome_t *skydome ); -void R_ClearSkyBox( void ); -void R_DrawSky( ref_shader_t *shader ); -qboolean R_AddSkySurface( msurface_t *fa ); -void R_SetupSky( const char *name ); -void R_FreeSky( void ); - -//==================================================================== - -enum -{ - GLSTATE_NONE = 0, - - // - // glBlendFunc args - // - GLSTATE_SRCBLEND_ZERO = 1, - GLSTATE_SRCBLEND_ONE = 2, - GLSTATE_SRCBLEND_DST_COLOR = 1|2, - GLSTATE_SRCBLEND_ONE_MINUS_DST_COLOR = 4, - GLSTATE_SRCBLEND_SRC_ALPHA = 1|4, - GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA = 2|4, - GLSTATE_SRCBLEND_DST_ALPHA = 1|2|4, - GLSTATE_SRCBLEND_ONE_MINUS_DST_ALPHA = 8, - - GLSTATE_DSTBLEND_ZERO = 16, - GLSTATE_DSTBLEND_ONE = 32, - GLSTATE_DSTBLEND_SRC_COLOR = 16|32, - GLSTATE_DSTBLEND_ONE_MINUS_SRC_COLOR = 64, - GLSTATE_DSTBLEND_SRC_ALPHA = 16|64, - GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA = 32|64, - GLSTATE_DSTBLEND_DST_ALPHA = 16|32|64, - GLSTATE_DSTBLEND_ONE_MINUS_DST_ALPHA = 128, - - GLSTATE_BLEND_MTEX = 0x100, - - GLSTATE_AFUNC_GT0 = 0x200, - GLSTATE_AFUNC_LT128 = 0x400, - GLSTATE_AFUNC_GE128 = 0x800, - - GLSTATE_DEPTHWRITE = 0x1000, - GLSTATE_DEPTHFUNC_EQ = 0x2000, - - GLSTATE_OFFSET_FILL = 0x4000, - GLSTATE_NO_DEPTH_TEST = 0x8000, - - GLSTATE_MARK_END = 0x10000 // SHADERPASS_MARK_BEGIN -}; - -#define GLSTATE_MASK ( GLSTATE_MARK_END-1 ) - -// #define SHADERPASS_SRCBLEND_MASK (((GLSTATE_SRCBLEND_DST_ALPHA)<<1)-GLSTATE_SRCBLEND_ZERO) -#define GLSTATE_SRCBLEND_MASK 0xF - -// #define SHADERPASS_DSTBLEND_MASK (((GLSTATE_DSTBLEND_DST_ALPHA)<<1)-GLSTATE_DSTBLEND_ZERO) -#define GLSTATE_DSTBLEND_MASK 0xF0 - -#define GLSTATE_BLENDFUNC ( GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK ) -#define GLSTATE_ALPHAFUNC ( GLSTATE_AFUNC_GT0|GLSTATE_AFUNC_LT128|GLSTATE_AFUNC_GE128 ) - -typedef struct -{ - float ambient[3]; - rgba_t environmentColor; - - qboolean deluxeMappingEnabled; // true if deluxeMaps is true and r_lighting_deluxemaps->integer != 0 -} mapconfig_t; - -extern mapconfig_t mapConfig; -extern refinst_t RI, prevRI; - -#endif /*__R_LOCAL_H__*/ diff --git a/vid_gl/r_main.c b/vid_gl/r_main.c deleted file mode 100644 index 15438a7a..00000000 --- a/vid_gl/r_main.c +++ /dev/null @@ -1,2570 +0,0 @@ -/* -Copyright (C) 1997-2001 Id Software, Inc. -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// r_main.c - -#include // sscanf -#include "r_local.h" -#include "cl_entity.h" -#include "mathlib.h" -#include "matrix_lib.h" -#include "pm_movevars.h" - -render_imp_t ri; -stdlib_api_t com; - -ref_model_t *r_worldmodel; -mbrushmodel_t *r_worldbrushmodel; - -float gldepthmin, gldepthmax; - -mapconfig_t mapConfig; - -refinst_t RI, prevRI; -ref_params_t r_lastRefdef; - -static int r_numnullentities; -static ref_entity_t *r_nullentities[MAX_ENTITIES]; -ref_model_t *cl_models[MAX_MODELS]; // client replacement modeltable -static int r_numbmodelentities; -static ref_entity_t *r_bmodelentities[MAX_MODELS]; - -static byte r_entVisBits[MAX_EDICTS/8]; - -int r_pvsframecount; // bumped when going to a new PVS -int r_framecount; // used for dlight push checking -int r_framecount2; // used bonestransform checking - -int c_brush_polys, c_world_leafs; - -double r_mark_leaves, r_world_node; -double r_add_polys, r_add_entities; -double r_sort_meshes, r_draw_meshes; - -msurface_t *r_debug_surface; -const char *r_debug_hitbox; - -char r_speeds_msg[MAX_RSPEEDSMSGSIZE]; - -uint r_numEntities; -ref_entity_t r_entities[MAX_ENTITIES]; -ref_entity_t *r_worldent = &r_entities[0]; - -uint r_numDlights; -ref_dlight_t r_dlights[MAX_DLIGHTS]; - -uint r_numPolys; -poly_t r_polys[MAX_POLYS]; - -lightstyle_t r_lightStyles[MAX_LIGHTSTYLES]; - -mleaf_t *r_viewleaf, *r_oldviewleaf; -mleaf_t *r_viewleaf2, *r_oldviewleaf2; - -float r_farclip_min, r_farclip_bias = 64.0f; - -/* -================= -GL_Cull -================= -*/ -void GL_Cull( int cull ) -{ - if( glState.faceCull == cull ) - return; - - if( !cull ) - { - pglDisable( GL_CULL_FACE ); - glState.faceCull = 0; - return; - } - - if( !glState.faceCull ) - pglEnable( GL_CULL_FACE ); - pglCullFace( cull ); - glState.faceCull = cull; -} - -/* -================= -GL_SetState -================= -*/ -void GL_SetState( int state ) -{ - int diff; - - if( glState.in2DMode ) - state |= GLSTATE_NO_DEPTH_TEST; - if( state & GLSTATE_NO_DEPTH_TEST ) - state &= ~( GLSTATE_DEPTHWRITE|GLSTATE_DEPTHFUNC_EQ ); - - diff = glState.flags ^ state; - if( !diff ) - return; - - if( diff & ( GLSTATE_BLEND_MTEX|GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK ) ) - { - if( state & ( GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK ) ) - { - int blendsrc, blenddst; - - switch( state & GLSTATE_SRCBLEND_MASK ) - { - case GLSTATE_SRCBLEND_ZERO: - blendsrc = GL_ZERO; - break; - case GLSTATE_SRCBLEND_DST_COLOR: - blendsrc = GL_DST_COLOR; - break; - case GLSTATE_SRCBLEND_ONE_MINUS_DST_COLOR: - blendsrc = GL_ONE_MINUS_DST_COLOR; - break; - case GLSTATE_SRCBLEND_SRC_ALPHA: - blendsrc = GL_SRC_ALPHA; - break; - case GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA: - blendsrc = GL_ONE_MINUS_SRC_ALPHA; - break; - case GLSTATE_SRCBLEND_DST_ALPHA: - blendsrc = GL_DST_ALPHA; - break; - case GLSTATE_SRCBLEND_ONE_MINUS_DST_ALPHA: - blendsrc = GL_ONE_MINUS_DST_ALPHA; - break; - default: - case GLSTATE_SRCBLEND_ONE: - blendsrc = GL_ONE; - break; - } - - switch( state & GLSTATE_DSTBLEND_MASK ) - { - case GLSTATE_DSTBLEND_ONE: - blenddst = GL_ONE; - break; - case GLSTATE_DSTBLEND_SRC_COLOR: - blenddst = GL_SRC_COLOR; - break; - case GLSTATE_DSTBLEND_ONE_MINUS_SRC_COLOR: - blenddst = GL_ONE_MINUS_SRC_COLOR; - break; - case GLSTATE_DSTBLEND_SRC_ALPHA: - blenddst = GL_SRC_ALPHA; - break; - case GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA: - blenddst = GL_ONE_MINUS_SRC_ALPHA; - break; - case GLSTATE_DSTBLEND_DST_ALPHA: - blenddst = GL_DST_ALPHA; - break; - case GLSTATE_DSTBLEND_ONE_MINUS_DST_ALPHA: - blenddst = GL_ONE_MINUS_DST_ALPHA; - break; - default: - case GLSTATE_DSTBLEND_ZERO: - blenddst = GL_ZERO; - break; - } - - if( state & GLSTATE_BLEND_MTEX ) - { - if( glState.currentEnvModes[glState.activeTMU] != GL_REPLACE ) - pglEnable( GL_BLEND ); - else - pglDisable( GL_BLEND ); - } - else - { - pglEnable( GL_BLEND ); - } - - pglBlendFunc( blendsrc, blenddst ); - } - else - { - pglDisable( GL_BLEND ); - } - } - - if( diff & GLSTATE_ALPHAFUNC ) - { - if( state & GLSTATE_ALPHAFUNC ) - { - if( !( glState.flags & GLSTATE_ALPHAFUNC ) ) - pglEnable( GL_ALPHA_TEST ); - - if( state & GLSTATE_AFUNC_GT0 ) - pglAlphaFunc( GL_GREATER, 0 ); - else if( state & GLSTATE_AFUNC_LT128 ) - pglAlphaFunc( GL_LESS, 0.5f ); - else - pglAlphaFunc( GL_GEQUAL, 0.5f ); - } - else - { - pglDisable( GL_ALPHA_TEST ); - } - } - - if( diff & GLSTATE_DEPTHFUNC_EQ ) - { - if( state & GLSTATE_DEPTHFUNC_EQ ) - pglDepthFunc( GL_EQUAL ); - else - pglDepthFunc( GL_LEQUAL ); - } - - if( diff & GLSTATE_DEPTHWRITE ) - { - if( state & GLSTATE_DEPTHWRITE ) - pglDepthMask( GL_TRUE ); - else - pglDepthMask( GL_FALSE ); - } - - if( diff & GLSTATE_NO_DEPTH_TEST ) - { - if( state & GLSTATE_NO_DEPTH_TEST ) - pglDisable( GL_DEPTH_TEST ); - else - pglEnable( GL_DEPTH_TEST ); - } - - if( diff & GLSTATE_OFFSET_FILL ) - { - if( state & GLSTATE_OFFSET_FILL ) - pglEnable( GL_POLYGON_OFFSET_FILL ); - else - pglDisable( GL_POLYGON_OFFSET_FILL ); - } - - glState.flags = state; -} - -/* -================= -GL_FrontFace -================= -*/ -void GL_FrontFace( int front ) -{ - pglFrontFace( front ? GL_CW : GL_CCW ); - glState.frontFace = front; -} - -/* -============= -R_TransformEntityBBox -============= -*/ -void R_TransformEntityBBox( ref_entity_t *e, vec3_t mins, vec3_t maxs, vec3_t bbox[8], qboolean local ) -{ - int i; - vec3_t axis[3], tmp; - - if( e == r_worldent ) local = false; - if( local ) Matrix3x3_Transpose( axis, e->axis ); // switch row-column order - - // rotate local bounding box and compute the full bounding box - for( i = 0; i < 8; i++ ) - { - vec_t *corner = bbox[i]; - - corner[0] = (( i & 1 ) ? mins[0] : maxs[0] ); - corner[1] = (( i & 2 ) ? mins[1] : maxs[1] ); - corner[2] = (( i & 4 ) ? mins[2] : maxs[2] ); - - if( local ) - { - Matrix3x3_Transform( axis, corner, tmp ); - VectorAdd( tmp, e->origin, corner ); - } - } -} - -/* -============= -R_LoadIdentity -============= -*/ -void R_LoadIdentity( void ) -{ - if( tr.modelviewIdentity ) return; - - Matrix4x4_LoadIdentity( RI.objectMatrix ); - Matrix4x4_Copy( RI.modelviewMatrix, RI.worldviewMatrix ); - GL_LoadMatrix( RI.modelviewMatrix ); - tr.modelviewIdentity = true; -} - -/* -============= -R_RotateForEntity -============= -*/ -void R_RotateForEntity( ref_entity_t *e ) -{ - if( e == r_worldent ) - { - R_LoadIdentity(); - return; - } - - Matrix4x4_FromMatrix3x3( RI.objectMatrix, e->axis, e->scale ); - if( e->movetype == MOVETYPE_FOLLOW && e->parent && !VectorIsNull( e->origin2 )) - Matrix4x4_SetOrigin( RI.objectMatrix, e->origin2[0], e->origin2[1], e->origin2[2] ); - else Matrix4x4_SetOrigin( RI.objectMatrix, e->origin[0], e->origin[1], e->origin[2] ); - Matrix4x4_ConcatTransforms( RI.modelviewMatrix, RI.worldviewMatrix, RI.objectMatrix ); - GL_LoadMatrix( RI.modelviewMatrix ); - tr.modelviewIdentity = false; -} - -/* -============= -R_TranslateForEntity -============= -*/ -void R_TranslateForEntity( ref_entity_t *e ) -{ - if( e == r_worldent ) - { - R_LoadIdentity(); - return; - } - - Matrix4x4_LoadIdentity( RI.objectMatrix ); - - if( e->movetype == MOVETYPE_FOLLOW && e->parent && !VectorIsNull( e->origin2 )) - Matrix4x4_SetOrigin( RI.objectMatrix, e->origin2[0], e->origin2[1], e->origin2[2] ); - else Matrix4x4_SetOrigin( RI.objectMatrix, e->origin[0], e->origin[1], e->origin[2] ); - Matrix4x4_ConcatScale( RI.objectMatrix, e->scale ); - Matrix4x4_ConcatTransforms( RI.modelviewMatrix, RI.worldviewMatrix, RI.objectMatrix ); - GL_LoadMatrix( RI.modelviewMatrix ); - tr.modelviewIdentity = false; -} - -/* -============= -R_FogForSphere -============= -*/ -mfog_t *R_FogForSphere( const vec3_t centre, const float radius ) -{ - int i, j; - mfog_t *fog; - mplane_t *plane; - - if( !r_worldmodel || !RI.drawWorld || !r_worldbrushmodel->numfogs ) - return NULL; - if( RI.params & RP_SHADOWMAPVIEW ) - return NULL; - if( r_worldbrushmodel->globalfog ) - return r_worldbrushmodel->globalfog; - - fog = r_worldbrushmodel->fogs; - for( i = 0; i < r_worldbrushmodel->numfogs; i++, fog++ ) - { - if( !fog->shader ) - continue; - - plane = fog->planes; - for( j = 0; j < fog->numplanes; j++, plane++ ) - { - // if completely in front of face, no intersection - if( PlaneDiff( centre, plane ) > radius ) - break; - } - - if( j == fog->numplanes ) - return fog; - } - - return NULL; -} - -/* -============= -R_CompletelyFogged -============= -*/ -qboolean R_CompletelyFogged( mfog_t *fog, vec3_t origin, float radius ) -{ - // note that fog->distanceToEye < 0 is always true if - // globalfog is not NULL and we're inside the world boundaries - if( fog && fog->shader && RI.fog_dist_to_eye[fog-r_worldbrushmodel->fogs] < 0 ) - { - float vpnDist = (( RI.viewOrigin[0] - origin[0] ) * RI.vpn[0] + ( RI.viewOrigin[1] - origin[1] ) * RI.vpn[1] + ( RI.viewOrigin[2] - origin[2] ) * RI.vpn[2] ); - return (( vpnDist + radius ) / fog->shader->fog_dist ) < -1; - } - return false; -} - -/* -============================================================= - -CUSTOM COLORS - -============================================================= -*/ - -static rgba_t r_customColors[NUM_CUSTOMCOLORS]; - -/* -================= -R_InitCustomColors -================= -*/ -void R_InitCustomColors( void ) -{ - Mem_Set( r_customColors, 255, sizeof( r_customColors )); -} - -/* -================= -R_SetCustomColor -================= -*/ -void R_SetCustomColor( int num, int r, int g, int b ) -{ - if( num < 0 || num >= NUM_CUSTOMCOLORS ) - return; - Vector4Set( r_customColors[num], (byte)r, (byte)g, (byte)b, 255 ); -} -/* -================= -R_GetCustomColor -================= -*/ -int R_GetCustomColor( int num ) -{ - if( num < 0 || num >= NUM_CUSTOMCOLORS ) - return 0xFFFFFFFF; // white color - return *(int *)r_customColors[num]; -} - -/* -============================================================= - -SPRITE MODELS AND FLARES - -============================================================= -*/ - -static vec4_t spr_xyz[4] = { {0,0,0,1}, {0,0,0,1}, {0,0,0,1}, {0,0,0,1} }; -static vec2_t spr_st[4] = { {1, 0}, {1, 1}, {0,1}, {0, 0} }; -static rgba_t spr_color[4]; -static mesh_t spr_mesh = { 4, 6, spr_xyz, spr_xyz, NULL, NULL, spr_st, NULL, spr_color, NULL, NULL }; - -/* -================= -R_PushSprite -================= -*/ -qboolean R_PushSprite( const meshbuffer_t *mb, int type, float right, float left, float up, float down ) -{ - int i, features; - vec3_t v_forward, v_right, v_up; - ref_entity_t *e = RI.currententity; - float angle, sr, cr; - ref_shader_t *shader; - vec3_t point, origin; - - // don't touch entity origin in case we doesn't have updates - VectorCopy( e->origin, origin ); - - switch( type ) - { - case SPR_ORIENTED: - VectorCopy( e->axis[0], v_forward ); - VectorCopy( e->axis[1], v_right ); - VectorCopy( e->axis[2], v_up ); - VectorScale( v_forward, 0.01f, v_forward ); // to avoid z-fighting - VectorSubtract( origin, v_forward, origin ); - break; - case SPR_FACING_UPRIGHT: - VectorSet( v_right, origin[1] - RI.viewOrigin[1], -(origin[0] - RI.viewOrigin[0]), 0 ); - VectorSet( v_up, 0, 0, 1 ); - VectorNormalize( v_right ); - break; - case SPR_FWD_PARALLEL_UPRIGHT: - VectorSet( v_right, RI.vpn[1], -RI.vpn[0], 0 ); - VectorSet( v_up, 0, 0, 1 ); - break; - case SPR_FWD_PARALLEL_ORIENTED: - angle = e->angles[ROLL] * (M_PI * 2.0f/360.0f); - sr = com.sin( angle ); - cr = com.cos( angle ); - for( i = 0; i < 3; i++ ) - { - v_right[i] = (RI.vright[i] * cr + RI.vup[i] * sr); - v_up[i] = RI.vright[i] * -sr + RI.vup[i] * cr; - } - break; - case SPR_FWD_PARALLEL: // normal sprite - default: - if( e->customShader ) - angle = e->angles[PITCH]; - else angle = e->angles[ROLL]; // for support rotating muzzleflashes - - if( angle != 0.0f ) - { - RotatePointAroundVector( v_right, RI.vpn, RI.vright, angle ); - CrossProduct( RI.vpn, v_right, v_up ); - } - else - { - VectorCopy( RI.vright, v_right ); - VectorCopy( RI.vup, v_up ); - } - break; - } - - VectorScale( v_up, down, point ); - VectorMA( point, -left, v_right, spr_xyz[0] ); - VectorMA( point, -right, v_right, spr_xyz[3] ); - - VectorScale( v_up, up, point ); - VectorMA( point, -left, v_right, spr_xyz[1] ); - VectorMA( point, -right, v_right, spr_xyz[2] ); - - MB_NUM2SHADER( mb->shaderkey, shader ); - - // the code below is disgusting, but some q3a shaders use 'rgbgen vertex' - // and 'alphagen vertex' for effects instead of 'rgbgen entity' and 'alphagen entity' - if( shader->features & MF_COLORS ) - { - for( i = 0; i < 4; i++ ) - Vector4Set( spr_color[i], e->rendercolor[0], e->rendercolor[1], e->rendercolor[2], e->renderamt ); - } - - features = MF_NOCULL | MF_TRIFAN | shader->features; - if( r_shownormals->integer ) - features |= MF_NORMALS; - - if( shader->flags & SHADER_ENTITY_MERGABLE ) - { - for( i = 0; i < 4; i++ ) - VectorAdd( spr_xyz[i], origin, spr_xyz[i] ); - R_PushMesh( &spr_mesh, features ); - return false; - } - - R_PushMesh( &spr_mesh, MF_NONBATCHED | features ); - return true; -} - -/* -================= -R_PushFlareSurf -================= -*/ -static void R_PushFlareSurf( const meshbuffer_t *mb ) -{ - int i; - vec4_t color; - vec3_t origin, point, v; - float radius = r_flaresize->value, colorscale, depth; - float up = radius, down = -radius, left = -radius, right = radius; - mbrushmodel_t *bmodel = ( mbrushmodel_t * )RI.currentmodel->extradata; - msurface_t *surf = &bmodel->surfaces[mb->infokey - 1]; - ref_shader_t *shader; - - if( !r_flares->integer ) return; - - if( RI.currentmodel != r_worldmodel ) - { - Matrix3x3_Transform( RI.currententity->axis, surf->origin, origin ); - VectorAdd( origin, RI.currententity->origin, origin ); - } - else VectorCopy( surf->origin, origin ); - R_TransformToScreen_Vec3( origin, v ); - - if( v[0] < RI.refdef.viewport[0] || v[0] > RI.refdef.viewport[0] + RI.refdef.viewport[2] ) - return; - if( v[1] < RI.refdef.viewport[1] || v[1] > RI.refdef.viewport[1] + RI.refdef.viewport[3] ) - return; - - pglReadPixels((int)( v[0] ), (int)( v[1] ), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth ); - if( depth + 1e-4 < v[2] ) return; // occluded - - VectorCopy( origin, origin ); - - VectorMA( origin, down, RI.vup, point ); - VectorMA( point, -left, RI.vright, spr_xyz[0] ); - VectorMA( point, -right, RI.vright, spr_xyz[3] ); - - VectorMA( origin, up, RI.vup, point ); - VectorMA( point, -left, RI.vright, spr_xyz[1] ); - VectorMA( point, -right, RI.vright, spr_xyz[2] ); - - colorscale = 255.0 / r_flarefade->value; - Vector4Set( color, surf->color[0] * colorscale, surf->color[1] * colorscale, surf->color[2] * colorscale, 255 ); - for( i = 0; i < 4; i++ ) - color[i] = bound( 0, color[i], 255 ); - - for( i = 0; i < 4; i++ ) - Vector4Copy( color, spr_color[i] ); - - MB_NUM2SHADER( mb->shaderkey, shader ); - - R_PushMesh( &spr_mesh, MF_NOCULL | MF_TRIFAN | shader->features ); -} - -/* -================= -R_PushCorona -================= -*/ -static void R_PushCorona( const meshbuffer_t *mb ) -{ - vec4_t color; - vec3_t origin, point; - ref_dlight_t *light = r_dlights + ( -mb->infokey - 1 ); - float radius = light->intensity, colorscale; - float up = radius, down = -radius, left = -radius, right = radius; - ref_shader_t *shader; - int i; - - VectorCopy( light->origin, origin ); - - VectorMA( origin, down, RI.vup, point ); - VectorMA( point, -left, RI.vright, spr_xyz[0] ); - VectorMA( point, -right, RI.vright, spr_xyz[3] ); - - VectorMA( origin, up, RI.vup, point ); - VectorMA( point, -left, RI.vright, spr_xyz[1] ); - VectorMA( point, -right, RI.vright, spr_xyz[2] ); - - colorscale = 255.0 * bound( 0, r_coronascale->value, 1.0 ); - Vector4Set( color, light->color[0] * colorscale, light->color[1] * colorscale, light->color[2] * colorscale, 255 ); - for( i = 0; i < 4; i++ ) - color[i] = bound( 0, color[i], 255 ); - - for( i = 0; i < 4; i++ ) - Vector4Copy( color, spr_color[i] ); - - MB_NUM2SHADER( mb->shaderkey, shader ); - - R_PushMesh( &spr_mesh, MF_NOCULL | MF_TRIFAN | shader->features ); -} - -/* -================= -R_PushSpritePoly -================= -*/ -qboolean R_PushSpritePoly( const meshbuffer_t *mb ) -{ - ref_entity_t *e = RI.currententity; - - if( ( mb->sortkey & 3 ) == MB_CORONA ) - { - R_PushCorona( mb ); - return false; - } - if( mb->infokey > 0 ) - { - R_PushFlareSurf( mb ); - return false; - } - return R_PushSprite( mb, -1, -e->radius, e->radius, e->radius, -e->radius ); -} - - - -/* -================= -R_AddSpriteModelToList -================= -*/ -static void R_AddSpriteModelToList( ref_entity_t *e ) -{ - mspriteframe_t *frame; - msprite_t *psprite; - ref_model_t *model = e->model; - ref_shader_t *shader; - float dist; - meshbuffer_t *mb; - - if(!( psprite = (( msprite_t* )model->extradata ))) - return; - - dist = (e->origin[0] - RI.viewOrigin[0]) * RI.vpn[0] + (e->origin[1] - RI.viewOrigin[1]) * RI.vpn[1] + (e->origin[2] - RI.viewOrigin[2]) * RI.vpn[2]; - if( dist < 0 ) return; // cull it because we don't want to sort unneeded things - - if( R_SpriteOccluded( e )) return; - - frame = R_GetSpriteFrame( e->model, e->lerp->curstate.frame, e->angles[YAW] ); - if( e->customShader ) shader = e->customShader; - else shader = &r_shaders[frame->shader]; - - if( RI.rdflags & (RDF_PORTALINVIEW|RDF_SKYPORTALINVIEW) || ( RI.params & RP_SKYPORTALVIEW )) - { - if( R_VisCullSphere( e->origin, frame->radius )) - return; - } - - mb = R_AddMeshToList( MB_MODEL, R_FogForSphere( e->origin, frame->radius ), shader, -1 ); - if( mb ) mb->shaderkey |= ( bound( 1, 0x4000 - (uint)dist, 0x4000 - 1 )<<12 ); -} - -/* -================= -R_SpriteOverflow -================= -*/ -qboolean R_SpriteOverflow( void ) -{ - return R_MeshOverflow( &spr_mesh ); -} - -//================================================================================== -/* -=============== -R_ApplySoftwareGamma -=============== -*/ -static void R_ApplySoftwareGamma( void ) -{ - double f, div; - - // apply software gamma - if( !r_ignorehwgamma->integer ) - return; - - pglMatrixMode( GL_PROJECTION ); - pglLoadIdentity(); - pglOrtho( 0, 1, 1, 0, -99999, 99999 ); - - pglMatrixMode( GL_MODELVIEW ); - pglLoadIdentity(); - - GL_Cull( 0 ); - GL_SetState( GLSTATE_NO_DEPTH_TEST | GLSTATE_SRCBLEND_DST_COLOR | GLSTATE_DSTBLEND_ONE ); - - pglDisable( GL_TEXTURE_2D ); - - if( r_overbrightbits->integer > 0 ) - div = 0.5 * (double)( 1 << r_overbrightbits->integer ); - else - div = 0.5; - f = div + r_gamma->value; - f = bound( 0.1f, f, 5.0f ); - - pglBegin( GL_TRIANGLES ); - - while( f >= 1.01f ) - { - if( f >= 2 ) - pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); - else - pglColor4f( f - 1.0f, f - 1.0f, f - 1.0f, 1.0f ); - - pglVertex2f( -5, -5 ); - pglVertex2f( 10, -5 ); - pglVertex2f( -5, 10 ); - f *= 0.5; - } - - pglEnd(); - - pglEnable( GL_TEXTURE_2D ); - - pglColor4f( 1, 1, 1, 1 ); -} - -//============================================================================= -/* -=============== -R_SetupFrustum -=============== -*/ -static void R_SetupFrustum( void ) -{ - int i; - vec3_t farPoint; - - // 0 - left - // 1 - right - // 2 - down - // 3 - up - // 4 - farclip - - // rotate RI.vpn right by FOV_X/2 degrees - RotatePointAroundVector( RI.frustum[0].normal, RI.vup, RI.vpn, -( 90-RI.refdef.fov_x / 2 ) ); - // rotate RI.vpn left by FOV_X/2 degrees - RotatePointAroundVector( RI.frustum[1].normal, RI.vup, RI.vpn, 90-RI.refdef.fov_x / 2 ); - // rotate RI.vpn up by FOV_X/2 degrees - RotatePointAroundVector( RI.frustum[2].normal, RI.vright, RI.vpn, 90-RI.refdef.fov_y / 2 ); - // rotate RI.vpn down by FOV_X/2 degrees - RotatePointAroundVector( RI.frustum[3].normal, RI.vright, RI.vpn, -( 90 - RI.refdef.fov_y / 2 ) ); - // negate forward vector - VectorNegate( RI.vpn, RI.frustum[4].normal ); - - for( i = 0; i < 4; i++ ) - { - RI.frustum[i].type = PLANE_NONAXIAL; - RI.frustum[i].dist = DotProduct( RI.viewOrigin, RI.frustum[i].normal ); - RI.frustum[i].signbits = SignbitsForPlane( RI.frustum[i].normal ); - } - - VectorMA( RI.viewOrigin, RI.farClip, RI.vpn, farPoint ); - RI.frustum[i].type = PLANE_NONAXIAL; - RI.frustum[i].dist = DotProduct( farPoint, RI.frustum[i].normal ); - RI.frustum[i].signbits = SignbitsForPlane( RI.frustum[i].normal ); -} - -/* -=============== -R_FarClip -=============== -*/ -static float R_FarClip( void ) -{ - float farclip_dist; - - if( r_worldmodel && RI.drawWorld ) - { - int i; - float dist; - vec3_t tmp; - - farclip_dist = 0; - for( i = 0; i < 8; i++ ) - { - tmp[0] = ( ( i & 1 ) ? RI.visMins[0] : RI.visMaxs[0] ); - tmp[1] = ( ( i & 2 ) ? RI.visMins[1] : RI.visMaxs[1] ); - tmp[2] = ( ( i & 4 ) ? RI.visMins[2] : RI.visMaxs[2] ); - - dist = VectorDistance2( tmp, RI.viewOrigin ); - farclip_dist = max( farclip_dist, dist ); - } - - farclip_dist = com.sqrt( farclip_dist ); - farclip_dist = max( RI.refdef.movevars->zmax, farclip_dist ); - - if( r_worldbrushmodel->globalfog ) - { - float fogdist = r_worldbrushmodel->globalfog->shader->fog_dist; - if( farclip_dist > fogdist ) - farclip_dist = fogdist; - else - RI.clipFlags &= ~16; - } - } - else - { - farclip_dist = 2048; - } - - return max( r_farclip_min, farclip_dist ) + r_farclip_bias; -} - -/* -============= -R_SetupProjectionMatrix -============= -*/ -static void R_SetupProjectionMatrix( const ref_params_t *rd, matrix4x4 m ) -{ - GLdouble xMin, xMax, yMin, yMax, zNear, zFar; - - if( !RI.drawWorld ) RI.farClip = 2048; - else RI.farClip = R_FarClip(); - - zNear = Z_NEAR; - zFar = RI.farClip; - - yMax = zNear *tan( rd->fov_y *M_PI / 360.0 ); - yMin = -yMax; - - xMax = zNear *tan( rd->fov_x *M_PI / 360.0 ); - xMin = -xMax; - - Matrix4x4_CreateProjection( m, xMax, xMin, yMax, yMin, zNear, zFar ); -} - -/* -============= -R_SetupModelviewMatrix -============= -*/ -void R_SetupModelviewMatrix( const ref_params_t *rd, matrix4x4 m ) -{ -#if 0 - Matrix4x4_LoadIdentity( m ); - Matrix4x4_ConcatRotate( m, -90, 1, 0, 0 ); - Matrix4x4_ConcatRotate( m, 90, 0, 0, 1 ); -#else - Matrix4x4_CreateModelview( m ); -#endif - Matrix4x4_ConcatRotate( m, -rd->viewangles[2], 1, 0, 0 ); - Matrix4x4_ConcatRotate( m, -rd->viewangles[0], 0, 1, 0 ); - Matrix4x4_ConcatRotate( m, -rd->viewangles[1], 0, 0, 1 ); - Matrix4x4_ConcatTranslate( m, -rd->vieworg[0], -rd->vieworg[1], -rd->vieworg[2] ); -} - -/* -=============== -R_SetupFrame -=============== -*/ -static void R_SetupFrame( void ) -{ - // build the transformation matrix for the given view angles - VectorCopy( RI.refdef.vieworg, RI.viewOrigin ); - AngleVectors( RI.refdef.viewangles, RI.viewAxis[0], RI.viewAxis[1], RI.viewAxis[2] ); - RI.vpn = RI.viewAxis[0]; - RI.vright = RI.viewAxis[1]; - RI.vup = RI.viewAxis[2]; - - // ambient lighting - if( r_worldmodel && RI.drawWorld ) - { - mapConfig.environmentColor[0] = RI.refdef.movevars->skycolor_r; - mapConfig.environmentColor[1] = RI.refdef.movevars->skycolor_g; - mapConfig.environmentColor[2] = RI.refdef.movevars->skycolor_b; - mapConfig.environmentColor[3] = 255; - } - - if( RI.params & RP_SHADOWMAPVIEW ) - return; - - r_framecount++; - - // current viewleaf - if( RI.drawWorld ) - { - mleaf_t *leaf; - vec3_t tmp; - - VectorCopy( r_worldmodel->mins, RI.visMins ); - VectorCopy( r_worldmodel->maxs, RI.visMaxs ); - - if(!( RI.params & RP_OLDVIEWLEAF )) - { - r_oldviewleaf = r_viewleaf; - r_oldviewleaf2 = r_viewleaf2; - leaf = Mod_PointInLeaf( RI.pvsOrigin, r_worldmodel ); - r_viewleaf2 = r_viewleaf = leaf; - - // check above and below so crossing solid water doesn't draw wrong - if( leaf->contents == CONTENTS_EMPTY ) - { - // look down a bit - VectorCopy( RI.pvsOrigin, tmp ); - tmp[2] -= 16; - leaf = Mod_PointInLeaf( tmp, r_worldmodel ); - if(( leaf->contents != CONTENTS_SOLID ) && ( leaf != r_viewleaf2 )) - r_viewleaf2 = leaf; - } - else - { - // look up a bit - VectorCopy( RI.pvsOrigin, tmp ); - tmp[2] += 16; - leaf = Mod_PointInLeaf( tmp, r_worldmodel ); - if(( leaf->contents != CONTENTS_SOLID ) && ( leaf != r_viewleaf2 )) - r_viewleaf2 = leaf; - } - } - } -} - -/* -=============== -R_SetupViewMatrices -=============== -*/ -static void R_SetupViewMatrices( void ) -{ - R_SetupModelviewMatrix( &RI.refdef, RI.worldviewMatrix ); - if( RI.params & RP_SHADOWMAPVIEW ) - { - int i; - float x1, x2, y1, y2; - int ix1, ix2, iy1, iy2; - int sizex = RI.refdef.viewport[2], sizey = RI.refdef.viewport[3]; - int diffx, diffy; - shadowGroup_t *group = RI.shadowGroup; - - R_SetupProjectionMatrix( &RI.refdef, RI.projectionMatrix ); - Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix ); - - // compute optimal fov to increase depth precision (so that shadow group objects are - // as close to the nearplane as possible) - // note that it's suboptimal to use bbox calculated in worldspace (FIXME) - x1 = y1 = 999999; - x2 = y2 = -999999; - for( i = 0; i < 8; i++ ) - { - vec3_t v, tmp; - - // compute and rotate a full bounding box - tmp[0] = ( ( i & 1 ) ? group->mins[0] : group->maxs[0] ); - tmp[1] = ( ( i & 2 ) ? group->mins[1] : group->maxs[1] ); - tmp[2] = ( ( i & 4 ) ? group->mins[2] : group->maxs[2] ); - - // transform to screen - R_TransformToScreen_Vec3( tmp, v ); - x1 = min( x1, v[0] ); y1 = min( y1, v[1] ); - x2 = max( x2, v[0] ); y2 = max( y2, v[1] ); - } - - // give it 1 pixel gap on both sides - ix1 = x1 - 1.0f; ix2 = x2 + 1.0f; - iy1 = y1 - 1.0f; iy2 = y2 + 1.0f; - - diffx = sizex - min( ix1, sizex - ix2 ) * 2; - diffy = sizey - min( iy1, sizey - iy2 ) * 2; - - // adjust fov - RI.refdef.fov_x = 2 * RAD2DEG( atan( (float)diffx / (float)sizex )); - RI.refdef.fov_y = 2 * RAD2DEG( atan( (float)diffy / (float)sizey )); - } - R_SetupProjectionMatrix( &RI.refdef, RI.projectionMatrix ); - if( RI.params & RP_MIRRORVIEW ) RI.projectionMatrix[0][0] = -RI.projectionMatrix[0][0]; - Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix ); -} - -/* -============= -R_Clear -============= -*/ -static void R_Clear( int bitMask ) -{ - int bits; - - bits = GL_DEPTH_BUFFER_BIT; - - if( RI.drawWorld && r_fastsky->integer ) - bits |= GL_COLOR_BUFFER_BIT; - if( glState.stencilEnabled && ( r_shadows->integer >= SHADOW_PLANAR ) ) - bits |= GL_STENCIL_BUFFER_BIT; - - bits &= bitMask; - - if( bits & GL_STENCIL_BUFFER_BIT ) - pglClearStencil( 128 ); - - if( bits & GL_COLOR_BUFFER_BIT ) - { - byte *color = ( r_worldmodel && RI.drawWorld && r_worldbrushmodel->globalfog ) ? - r_worldbrushmodel->globalfog->shader->fog_color : mapConfig.environmentColor; - pglClearColor( (float)color[0]*( 1.0/255.0 ), (float)color[1]*( 1.0/255.0 ), (float)color[2]*( 1.0/255.0 ), 1 ); - } - - pglClear( bits ); - - gldepthmin = 0; - gldepthmax = 1; - pglDepthRange( gldepthmin, gldepthmax ); -} - -/* -============= -R_SetupGL -============= -*/ -static void R_SetupGL( void ) -{ - pglScissor( RI.scissor[0], RI.scissor[1], RI.scissor[2], RI.scissor[3] ); - pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] ); - - pglMatrixMode( GL_PROJECTION ); - GL_LoadMatrix( RI.projectionMatrix ); - - pglMatrixMode( GL_MODELVIEW ); - GL_LoadMatrix( RI.worldviewMatrix ); - - if( RI.params & RP_CLIPPLANE ) - { - GLdouble clip[4]; - mplane_t *p = &RI.clipPlane; - - clip[0] = p->normal[0]; - clip[1] = p->normal[1]; - clip[2] = p->normal[2]; - clip[3] = -p->dist; - - pglClipPlane( GL_CLIP_PLANE0, clip ); - pglEnable( GL_CLIP_PLANE0 ); - } - - if( RI.params & RP_FLIPFRONTFACE ) - GL_FrontFace( !glState.frontFace ); - - if( RI.params & RP_SHADOWMAPVIEW ) - { - pglShadeModel( GL_FLAT ); - pglColorMask( 0, 0, 0, 0 ); - pglPolygonOffset( 1, 4 ); - if( prevRI.params & RP_CLIPPLANE ) - pglDisable( GL_CLIP_PLANE0 ); - } - - GL_Cull( GL_FRONT ); - GL_SetState( GLSTATE_DEPTHWRITE ); -} - -/* -============= -R_EndGL -============= -*/ -static void R_EndGL( void ) -{ - if( RI.params & RP_SHADOWMAPVIEW ) - { - pglPolygonOffset( -1, -2 ); - pglColorMask( 1, 1, 1, 1 ); - pglShadeModel( GL_SMOOTH ); - if( prevRI.params & RP_CLIPPLANE ) - pglEnable( GL_CLIP_PLANE0 ); - } - - if( RI.params & RP_FLIPFRONTFACE ) - GL_FrontFace( !glState.frontFace ); - - if( RI.params & RP_CLIPPLANE ) - pglDisable( GL_CLIP_PLANE0 ); -} - - -/* -============= -R_CategorizeEntities -============= -*/ -static void R_CategorizeEntities( void ) -{ - uint i, j; - cl_entity_t *world; - - r_numnullentities = 0; - r_numbmodelentities = 0; - - if( !r_drawentities->integer ) - return; - - // apply global waveheight to world entity - world = ri.GetClientEdict( 0 ); - if( world ) r_worldent->waveHeight = world->curstate.scale * 16.0f; - - for( i = 1; i < r_numEntities; i++ ) - { - RI.previousentity = RI.currententity; - RI.currententity = &r_entities[i]; - - if( RI.currententity->rtype != RT_MODEL ) - continue; - - RI.currentmodel = RI.currententity->model; - if( !RI.currentmodel ) - { - r_nullentities[r_numnullentities++] = RI.currententity; - continue; - } - - // setup entity parents - if( RI.currententity->movetype == MOVETYPE_FOLLOW && !RI.currententity->parent ) - { - cl_entity_t *pEntity = RI.currententity->lerp; - - if( pEntity && pEntity->curstate.aiment > 0 ) - { - for( j = 1; j < r_numEntities; j++ ) - { - if( r_entities[j].index == pEntity->curstate.aiment ) - { - RI.currententity->parent = r_entities + j; - break; - } - } - } - } - - switch( RI.currentmodel->type ) - { - case mod_brush: - case mod_world: - r_bmodelentities[r_numbmodelentities++] = RI.currententity; - break; - case mod_studio: - if(!( RI.currententity->flags & EF_NOSHADOW )) - R_AddShadowCaster( RI.currententity ); // build groups and mark shadow casters - break; - case mod_sprite: - break; - default: - Host_Error( "%s: bad modeltype\n", RI.currentmodel->name ); - break; - } - } -} - -/* -============= -R_CullEntities -============= -*/ -static void R_CullEntities( void ) -{ - uint i; - ref_entity_t *e; - qboolean culled; - - Mem_Set( r_entVisBits, 0, sizeof( r_entVisBits )); - if( !r_drawentities->integer ) - return; - - for( i = 1; i < r_numEntities; i++ ) - { - RI.previousentity = RI.currententity; - RI.currententity = e = &r_entities[i]; - culled = true; - - switch( e->rtype ) - { - case RT_MODEL: - if( !e->model ) break; - switch( e->model->type ) - { - case mod_world: - case mod_brush: - culled = R_CullBrushModel( e ); - break; - case mod_studio: - culled = R_CullStudioModel( e ); - break; - case mod_sprite: - culled = R_CullSpriteModel( e ); - break; - default: break; - } - break; - case RT_NONE: - default: break; - } - - if( !culled ) r_entVisBits[i>>3] |= ( 1<<( i&7 )); - } -} - -/* -============= -R_DrawNullModel -============= -*/ -static void R_DrawNullModel( void ) -{ - pglBegin( GL_LINES ); - - pglColor4f( 1, 0, 0, 0.5 ); - pglVertex3fv( RI.currententity->origin ); - pglVertex3f( RI.currententity->origin[0] + RI.currententity->axis[0][0] * 15, - RI.currententity->origin[1] + RI.currententity->axis[0][1] * 15, - RI.currententity->origin[2] + RI.currententity->axis[0][2] * 15 ); - - pglColor4f( 0, 1, 0, 0.5 ); - pglVertex3fv( RI.currententity->origin ); - pglVertex3f( RI.currententity->origin[0] - RI.currententity->axis[1][0] * 15, - RI.currententity->origin[1] - RI.currententity->axis[1][1] * 15, - RI.currententity->origin[2] - RI.currententity->axis[1][2] * 15 ); - - pglColor4f( 0, 0, 1, 0.5 ); - pglVertex3fv( RI.currententity->origin ); - pglVertex3f( RI.currententity->origin[0] + RI.currententity->axis[2][0] * 15, - RI.currententity->origin[1] + RI.currententity->axis[2][1] * 15, - RI.currententity->origin[2] + RI.currententity->axis[2][2] * 15 ); - - pglEnd(); -} - -/* -============= -R_DrawBmodelEntities -============= -*/ -static void R_DrawBmodelEntities( void ) -{ - int i, j; - - for( i = 0; i < r_numbmodelentities; i++ ) - { - RI.previousentity = RI.currententity; - RI.currententity = r_bmodelentities[i]; - j = RI.currententity - r_entities; - - if( r_entVisBits[j>>3] & ( 1<<( j & 7 ))) - R_AddBrushModelToList( RI.currententity ); - } -} - -/* -============= -R_DrawRegularEntities -============= -*/ -static void R_DrawRegularEntities( void ) -{ - uint i; - ref_entity_t *e; - qboolean shadowmap = (( RI.params & RP_SHADOWMAPVIEW ) != 0 ); - - for( i = 1; i < r_numEntities; i++ ) - { - RI.previousentity = RI.currententity; - RI.currententity = e = &r_entities[i]; - - if( shadowmap ) - { - if( e->flags & EF_NOSHADOW ) - continue; - if( r_entShadowBits[i] & RI.shadowGroup->bit ) - goto add; // shadow caster - } - if(!( r_entVisBits[i>>3] & ( 1<<( i & 7 )))) - continue; -add: - switch( e->rtype ) - { - case RT_MODEL: - RI.currentmodel = e->model; - switch( RI.currentmodel->type ) - { - case mod_studio: - R_AddStudioModelToList( e ); - break; - case mod_sprite: - if( !shadowmap ) - R_AddSpriteModelToList( e ); - break; - default: break; - } - break; - case RT_NONE: - default: break; - } - } -} - -/* -============= -R_DrawNullEntities -============= -*/ -static void R_DrawNullEntities( void ) -{ - int i; - - if( !r_numnullentities ) - return; - - pglDisable( GL_TEXTURE_2D ); - GL_SetState( GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA ); - - // draw non-transparent first - for( i = 0; i < r_numnullentities; i++ ) - { - RI.previousentity = RI.currententity; - RI.currententity = r_nullentities[i]; - - if( RI.params & RP_MIRRORVIEW ) - { - if( RI.currententity->ent_type == ET_VIEWENTITY ) - continue; - } - else - { - if( RP_LOCALCLIENT( RI.currententity )) - continue; - } - R_DrawNullModel(); - } - - pglEnable( GL_TEXTURE_2D ); -} - -/* -============= -R_DrawEntities -============= -*/ -static void R_DrawEntities( void ) -{ - qboolean shadowmap = (( RI.params & RP_SHADOWMAPVIEW ) != 0 ); - - if( r_drawentities->integer <= 0 ) - return; - - if( !shadowmap ) - { - R_CullEntities(); // mark visible entities in r_entVisBits - R_CullShadowmapGroups(); - } - - // we don't mark bmodel entities in RP_SHADOWMAPVIEW, only individual surfaces - R_DrawBmodelEntities(); - - if( OCCLUSION_QUERIES_ENABLED( RI )) - { - R_EndOcclusionPass(); - } - - if( RI.params & RP_ENVVIEW ) - return; - - if( !shadowmap ) R_DrawShadowmaps(); // render to depth textures, mark shadowed entities and surfaces - else if(!( RI.params & RP_WORLDSURFVISIBLE ) || ( prevRI.shadowBits & RI.shadowGroup->bit )) - return; // we're supposed to cast shadows but there are no visible surfaces for this light, so stop - // or we've already drawn and captured textures for this group - - R_DrawRegularEntities(); -} - - -/* -=============== -R_RenderDebugSurface -=============== -*/ -void R_RenderDebugSurface( void ) -{ - pmtrace_t tr; - vec3_t forward; - vec3_t start, end; - - if( RI.params & RP_NONVIEWERREF || !RI.drawWorld ) - return; - - r_debug_surface = NULL; - r_debug_hitbox = NULL; - - if( r_speeds->integer != 4 ) - return; - - VectorCopy( RI.vpn, forward ); - VectorCopy( RI.viewOrigin, start ); - VectorMA( start, 4096, forward, end ); - - r_debug_surface = R_TraceLine( &tr, start, end, 0 ); - - if( tr.hitgroup >= 0 && tr.ent != -1 && r_drawentities->integer != 3 ) - { - pglDisable( GL_TEXTURE_2D ); - GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA ); - pglDepthRange( 0, 0 ); - - RI.previousentity = NULL; - RI.currententity = &r_entities[tr.ent]; - - R_StudioDrawHitbox( RI.currententity, tr.hitgroup ); - - pglDepthRange( gldepthmin, gldepthmax ); - pglEnable( GL_TEXTURE_2D ); - } - else if( r_debug_surface && r_debug_surface->mesh && !gl_wireframe->integer ) - { - RI.previousentity = NULL; - RI.currententity = &r_entities[tr.ent]; - - R_ClearMeshList( RI.meshlist ); - R_AddMeshToList( MB_MODEL, NULL, r_debug_surface->shader, r_debug_surface - r_worldbrushmodel->surfaces + 1 ); - R_DrawTriangleOutlines( true, false ); - } -} - -/* -================ -R_RenderView - -RI.refdef must be set before the first call -================ -*/ -void R_RenderView( const ref_params_t *fd ) -{ - double starttime; - qboolean shadowMap = RI.params & RP_SHADOWMAPVIEW ? true : false; - - RI.refdef = *fd; - - R_ClearMeshList( RI.meshlist ); - - if( !r_worldmodel && RI.drawWorld ) - Host_Error( "R_RenderView: NULL worldmodel\n" ); - - R_SetupFrame(); - - r_framecount2++; - - // we know the farclip so adjust fov before setting up the frustum - if( shadowMap ) - { - R_SetupViewMatrices(); - } - else if( OCCLUSION_QUERIES_ENABLED( RI )) - { - R_SetupViewMatrices(); - - R_SetupGL(); - - R_Clear( ~( GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT )); - - R_BeginOcclusionPass(); - } - - R_SetupFrustum(); - - if( r_speeds->integer ) - starttime = Sys_DoubleTime(); - - R_MarkLeaves(); - - if( r_speeds->integer ) - r_mark_leaves += ( Sys_DoubleTime() - starttime ); - - R_DrawWorld(); - - // we know the the farclip at this point after determining visible world leafs - if( !shadowMap ) - { - R_SetupViewMatrices(); - - R_DrawCoronas(); - - if( r_speeds->integer ) - starttime = Sys_DoubleTime(); - - R_AddPolysToList(); - - if( r_speeds->integer ) - r_add_polys += ( Sys_DoubleTime() - starttime ); - } - - if( r_speeds->integer ) - starttime = Sys_DoubleTime(); - - R_DrawEntities(); - - if( r_speeds->integer ) - r_add_entities += ( Sys_DoubleTime() - starttime ); - - if( shadowMap ) - { - if(!( RI.params & RP_WORLDSURFVISIBLE )) - return; // we didn't cast shadows on anything, so stop - - if( prevRI.shadowBits & RI.shadowGroup->bit ) - return; // already drawn - } - - if( r_speeds->integer ) - starttime = Sys_DoubleTime(); - - R_SortMeshes(); - - if( r_speeds->integer ) - r_sort_meshes += ( Sys_DoubleTime() - starttime ); - - R_DrawPortals(); - - if( r_portalonly->integer && !( RI.params & ( RP_MIRRORVIEW|RP_PORTALVIEW ))) - return; - - R_SetupGL(); - - R_Clear( shadowMap ? ~( GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT ) : ~0 ); - - if( r_speeds->integer ) - starttime = Sys_DoubleTime(); - - R_DrawMeshes(); - - if( r_speeds->integer ) - r_draw_meshes += ( Sys_DoubleTime() - starttime ); - - R_BackendCleanUpTextureUnits(); - - R_DrawTriangleOutlines( gl_wireframe->integer ? true : false, r_shownormals->integer ? true : false ); - - R_RenderDebugSurface (); - - R_DrawEntitiesDebug (); - - R_DrawPhysDebug (); - - R_DrawNullEntities(); - - R_EndGL(); -} - -//======================================================================= -/* -=============== -R_BeginFrame -=============== -*/ -void R_BeginFrame( qboolean clearScene ) -{ - if( gl_finish->integer && gl_delayfinish->integer ) - { - // flush any remaining 2D bits -// R_Set2DMode( false ); - - // apply software gamma -// R_ApplySoftwareGamma (); - - pglFinish(); - - R_CheckForErrors (); - - // Swap the buffers - if( !r_frontbuffer->integer ) - { - if( !pwglSwapBuffers( glw_state.hDC )) - Sys_Break( "R_EndFrame() - SwapBuffers() failed!\n" ); - } - } - - if( r_colorbits->modified ) - { - r_colorbits->modified = false; - } - - if( r_environment_color->modified ) - { - VectorClear( mapConfig.environmentColor ); - mapConfig.environmentColor[3] = 255; - - if( r_environment_color->string[0] ) - { - int r, g, b; - - if( sscanf( r_environment_color->string, "%i %i %i", &r, &g, &b ) == 3 ) - { - mapConfig.environmentColor[0] = bound( 0, r, 255 ); - mapConfig.environmentColor[1] = bound( 0, g, 255 ); - mapConfig.environmentColor[2] = bound( 0, b, 255 ); - } - else - { - Cvar_Set( "r_environment_color", "" ); - } - } - r_environment_color->modified = false; - } - - if( gl_clear->integer && clearScene ) - { - rgba_t color; - - Vector4Copy( mapConfig.environmentColor, color ); - pglClearColor( color[0]*( 1.0/255.0 ), color[1]*( 1.0/255.0 ), color[2]*( 1.0/255.0 ), 1 ); - pglClear( GL_COLOR_BUFFER_BIT ); - } - - // update gamma - if( r_gamma->modified ) - { - r_gamma->modified = false; - GL_UpdateGammaRamp(); - } - - // go into 2D mode - R_Set2DMode( true ); - - // draw buffer stuff - if( r_frontbuffer->modified ) - { - r_frontbuffer->modified = false; - - if( r_frontbuffer->integer ) - pglDrawBuffer( GL_FRONT ); - else pglDrawBuffer( GL_BACK ); - } - - // texturemode stuff - // update texture parameters - if( gl_texturemode->modified || gl_texture_anisotropy->modified || gl_texture_lodbias ->modified ) - R_SetTextureParameters(); - - // swapinterval stuff - GL_UpdateSwapInterval(); -} - - -/* -==================== -R_ClearScene -==================== -*/ -void R_ClearScene( void ) -{ - r_numEntities = 1; // worldmodel - r_numDlights = 0; - r_numPolys = 0; - RI.previousentity = NULL; - RI.currententity = r_worldent; - RI.currentmodel = r_worldmodel; -} - -/* -===================== -R_AddPolyToScene -===================== -*/ -qboolean R_AddPolyToScene( const poly_t *poly ) -{ - if(( r_numPolys < MAX_POLYS ) && poly && poly->numverts ) - { - poly_t *dp = &r_polys[r_numPolys]; - ref_shader_t *shader; - - *dp = *poly; - if( dp->numverts > MAX_POLY_VERTS ) - dp->numverts = MAX_POLY_VERTS; - - if( poly->shadernum < 0 || poly->shadernum > MAX_SHADERS ) - return false; - - if( !(shader = &r_shaders[poly->shadernum] )) - return false; - - dp->shader = shader; - r_numPolys++; - - return true; - } - return false; -} - -/* -===================== -R_AddLightStyleToScene -===================== -*/ -void R_AddLightStyleToScene( int style, float r, float g, float b ) -{ - lightstyle_t *ls; - - if( !r_worldmodel || !r_worldbrushmodel->lightdata ) - return; // don't apply lightstyles when no lighting info - - if( style < 0 || style >= MAX_LIGHTSTYLES ) - Host_Error( "R_SetLightStyle: bad light style %i\n", style ); - - ls = &r_lightStyles[style]; - ls->rgb[0] = max( 0, r ); - ls->rgb[1] = max( 0, g ); - ls->rgb[2] = max( 0, b ); - ls->white = ls->rgb[0] + ls->rgb[1] + ls->rgb[2]; -} - -/* -=============== -R_RenderScene -=============== -*/ -void R_RenderScene( const ref_params_t *fd, qboolean drawWorld ) -{ - // flush any remaining 2D bits - R_Set2DMode( false ); - - if( r_norefresh->integer ) - return; - - R_BackendStartFrame(); - - if( drawWorld ) - { - r_lastRefdef = *fd; - } - - c_brush_polys = 0; - c_world_leafs = 0; - - r_mark_leaves = r_add_polys = r_add_entities = r_sort_meshes = r_draw_meshes = r_world_node = 0; - - RI.params = RP_NONE; - RI.refdef = *fd; - RI.farClip = 0; - RI.rdflags = 0; - RI.clipFlags = 15; - RI.drawWorld = drawWorld; - RI.lerpFrac = ri.GetLerpFrac(); - RI.thirdPerson = ri.IsThirdPerson(); - - if( r_worldmodel && RI.drawWorld && r_worldbrushmodel->globalfog ) - { - RI.farClip = r_worldbrushmodel->globalfog->shader->fog_dist; - RI.farClip = max( r_farclip_min, RI.farClip ) + r_farclip_bias; - RI.clipFlags |= 16; - } - - RI.meshlist = &r_worldlist; - RI.shadowBits = 0; - RI.shadowGroup = NULL; - - // adjust field of view for widescreen - if( glState.wideScreen && r_adjust_fov->integer ) - AdjustFov( &RI.refdef.fov_x, &RI.refdef.fov_y, glState.width, glState.height, false ); - - Vector4Set( RI.scissor, fd->viewport[0], glState.height - fd->viewport[3] - fd->viewport[1], fd->viewport[2], fd->viewport[3] ); - Vector4Set( RI.viewport, fd->viewport[0], glState.height - fd->viewport[3] - fd->viewport[1], fd->viewport[2], fd->viewport[3] ); - VectorCopy( fd->vieworg, RI.pvsOrigin ); - - if( gl_finish->integer && !gl_delayfinish->integer && drawWorld ) - pglFinish(); - - R_ClearShadowmaps(); - - R_CategorizeEntities(); - - R_RenderView( fd ); - - R_BloomBlend( fd ); - - R_BackendEndFrame(); - - R_Set2DMode( true ); - - R_ShowTextures(); -} - -/* -=============== -R_EndFrame -=============== -*/ -void R_EndFrame( void ) -{ - // flush any remaining 2D bits - R_Set2DMode( false ); - - // cleanup texture units - R_BackendCleanUpTextureUnits(); - - // apply software gamma - R_ApplySoftwareGamma(); - - if( gl_finish->integer && gl_delayfinish->integer ) - { - pglFlush(); - return; - } - - R_CheckForErrors (); - - // Swap the buffers - if( !r_frontbuffer->integer ) - { - if( !pwglSwapBuffers( glw_state.hDC )) - Sys_Break( "R_EndFrame() - SwapBuffers() failed!\n" ); - } -} - -/* -=============== -R_SpeedsMessage -=============== -*/ -static qboolean R_SpeedsMessage( char *out, size_t size ) -{ - if( r_speeds->integer <= 0 ) return false; - if( !out || !size ) return false; - - com.strncpy( out, r_speeds_msg, size ); - return true; -} - -//================================================================================== -int R_ComputeFxBlend( ref_entity_t *e ) -{ - int blend = 0, renderAmt; - cl_entity_t *m_pEntity = e->lerp; - float offset, dist; - vec3_t tmp; - - offset = ((int)e->index ) * 363.0f; // Use ent index to de-sync these fx - - if( e->ent_type == ET_TEMPENTITY ) - { - renderAmt = e->renderamt; - } - else if( m_pEntity ) - { - renderAmt = m_pEntity->curstate.renderamt; - } - else renderAmt = 255; - - switch( e->renderfx ) - { - case kRenderFxPulseSlowWide: - blend = renderAmt + 0x40 * com.sin( RI.refdef.time * 2 + offset ); - break; - case kRenderFxPulseFastWide: - blend = renderAmt + 0x40 * com.sin( RI.refdef.time * 8 + offset ); - break; - case kRenderFxPulseSlow: - blend = renderAmt + 0x10 * com.sin( RI.refdef.time * 2 + offset ); - break; - case kRenderFxPulseFast: - blend = renderAmt + 0x10 * com.sin( RI.refdef.time * 8 + offset ); - break; - // JAY: HACK for now -- not time based - case kRenderFxFadeSlow: - if( renderAmt > 0 ) - renderAmt -= 1; - else renderAmt = 0; - blend = renderAmt; - break; - case kRenderFxFadeFast: - if( renderAmt > 3 ) - renderAmt -= 4; - else renderAmt = 0; - blend = renderAmt; - break; - case kRenderFxSolidSlow: - if( renderAmt < 255 ) - renderAmt += 1; - else renderAmt = 255; - blend = renderAmt; - break; - case kRenderFxSolidFast: - if( renderAmt < 252 ) - renderAmt += 4; - else renderAmt = 255; - blend = renderAmt; - break; - case kRenderFxStrobeSlow: - blend = 20 * com.sin( RI.refdef.time * 4 + offset ); - if( blend < 0 ) blend = 0; - else blend = renderAmt; - break; - case kRenderFxStrobeFast: - blend = 20 * com.sin( RI.refdef.time * 16 + offset ); - if( blend < 0 ) blend = 0; - else blend = renderAmt; - break; - case kRenderFxStrobeFaster: - blend = 20 * com.sin( RI.refdef.time * 36 + offset ); - if( blend < 0 ) blend = 0; - else blend = renderAmt; - break; - case kRenderFxFlickerSlow: - blend = 20 * (com.sin( RI.refdef.time * 2 ) + com.sin( RI.refdef.time * 17 + offset )); - if( blend < 0 ) blend = 0; - else blend = renderAmt; - break; - case kRenderFxFlickerFast: - blend = 20 * (com.sin( RI.refdef.time * 16 ) + com.sin( RI.refdef.time * 23 + offset )); - if( blend < 0 ) blend = 0; - else blend = renderAmt; - break; - case kRenderFxHologram: - case kRenderFxDistort: - VectorCopy( e->origin, tmp ); - VectorSubtract( tmp, RI.refdef.vieworg, tmp ); - dist = DotProduct( tmp, RI.refdef.forward ); - - // Turn off distance fade - if( e->renderfx == kRenderFxDistort ) - dist = 1; - - if( dist <= 0 ) - { - blend = 0; - } - else - { - renderAmt = 180; - if( dist <= 100 ) blend = renderAmt; - else blend = (int) ((1.0f - ( dist - 100 ) * ( 1.0f / 400.0f )) * renderAmt ); - blend += Com_RandomLong( -32, 31 ); - } - break; - case kRenderFxNone: - case kRenderFxClampMinScale: - default: - if( e->rendermode == kRenderNormal ) - blend = 255; - else blend = renderAmt; - break; - } - - // store value back into client entity, some effects requires this - if( m_pEntity ) - { - // FIXME: this value can be owerwritten on a next client frame - // find another safety place - m_pEntity->curstate.renderamt = renderAmt; - - // NOTE: never pass sprites with rendercolor '0 0 0' it's a stupid Valve Hammer Editor bug - if(( !e->rendercolor[0] && !e->rendercolor[1] && !e->rendercolor[2] )) - VectorSet( e->rendercolor, 255, 255, 255 ); - } - blend = bound( 0, blend, 255 ); - - return blend; -} - -/* -============= -R_TransformToScreen_Vec3 -============= -*/ -qboolean R_TransformToScreen_Vec3( const vec3_t in, vec3_t out ) -{ - vec4_t temp, temp2; - - temp[0] = in[0]; - temp[1] = in[1]; - temp[2] = in[2]; - temp[3] = 1.0f; - - Matrix4x4_ConcatVector( RI.worldviewProjectionMatrix, temp, temp2 ); - if( !temp2[3] ) return true; // Z-clipped - - out[0] = (temp2[0] / temp2[3] + 1.0f) * 0.5f * RI.refdef.viewport[2]; - out[1] = (temp2[1] / temp2[3] + 1.0f) * 0.5f * RI.refdef.viewport[3]; - out[2] = (temp2[2] / temp2[3] + 1.0f) * 0.5f; - - return false; -} - -/* -============= -R_TransformVectorToScreen -============= -*/ -void R_TransformVectorToScreen( const ref_params_t *rd, const vec3_t in, vec2_t out ) -{ - matrix4x4 p, m; - vec4_t temp, temp2; - - if( !rd || !in || !out ) - return; - - temp[0] = in[0]; - temp[1] = in[1]; - temp[2] = in[2]; - temp[3] = 1.0f; - - R_SetupProjectionMatrix( rd, p ); - R_SetupModelviewMatrix( rd, m ); - - Matrix4x4_ConcatVector( m, temp, temp2 ); - Matrix4x4_ConcatVector( p, temp2, temp ); - - if( !temp[3] ) return; - - out[0] = rd->viewport[0] + ( temp[0] / temp[3] + 1.0f ) * rd->viewport[2] * 0.5f; - out[1] = rd->viewport[1] + ( temp[1] / temp[3] + 1.0f ) * rd->viewport[3] * 0.5f; -} - -/* -============= -R_ScreenTransform - -transform world position into screen -============= -*/ -qboolean R_ScreenTransform( const vec3_t point, vec3_t pClip ) -{ - matrix4x4 worldToScreen; - qboolean behind; - float w; - - Matrix4x4_Copy( worldToScreen, RI.worldviewProjectionMatrix ); - pClip[0] = worldToScreen[0][0] * point[0] + worldToScreen[0][1] * point[1] + worldToScreen[0][2] * point[2] + worldToScreen[0][3]; - pClip[1] = worldToScreen[1][0] * point[0] + worldToScreen[1][1] * point[1] + worldToScreen[1][2] * point[2] + worldToScreen[1][3]; -// z = worldToScreen[2][0] * point[0] + worldToScreen[2][1] * point[1] + worldToScreen[2][2] * point[2] + worldToScreen[2][3]; - w = worldToScreen[3][0] * point[0] + worldToScreen[3][1] * point[1] + worldToScreen[3][2] * point[2] + worldToScreen[3][3]; - - // Just so we have something valid here - pClip[2] = 0.0f; - - if( w < 0.001f ) - { - behind = true; - pClip[0] *= 100000; - pClip[1] *= 100000; - } - else - { - float invw = 1.0f / w; - behind = false; - pClip[0] *= invw; - pClip[1] *= invw; - } - return behind; -} -static void R_ScreenToWorld( const float *screen, float *world ) -{ - // FIXME: implement -} - -static qboolean R_WorldToScreen( const float *world, float *screen ) -{ - return R_ScreenTransform( world, screen ); -} -//================================================================================== - -/* -============= -R_TraceLine -============= -*/ -msurface_t *R_TraceLine( pmtrace_t *tr, const vec3_t start, const vec3_t end, int flags ) -{ - int i; - msurface_t *surf; - ref_entity_t *e; - - // trace against world - surf = R_TransformedTraceLine( tr, start, end, r_worldent, flags ); - - // trace against bmodels - for( i = 1; i < r_numEntities; i++ ) - { - pmtrace_t t2; - msurface_t *s2; - - e = &r_entities[i]; - - // don't trace localclient - if( RP_LOCALCLIENT( e ) && !RI.thirdPerson ) - continue; - - if( !e->model || ( e->model->type != mod_brush && e->model->type != mod_studio )) - continue; - - if( flags & FTRACE_SIMPLEBOX && e->model->type == mod_studio ) - continue; - - s2 = R_TransformedTraceLine( &t2, start, end, e, flags ); - if( t2.fraction < tr->fraction ) - { - *tr = t2; // closer impact point - surf = s2; - } - } - return surf; -} - -qboolean R_UploadModel( const char *name, int index ) -{ - ref_model_t *mod; - - // this array used by AddEntityToScene - mod = R_RegisterModel( name ); - cl_models[index] = mod; - - return (mod != NULL); -} - -shader_t Mod_RegisterShader( const char *name, int shaderType ) -{ - ref_shader_t *src; - - if( !glState.initializedMedia ) - return 0; - - switch( shaderType ) - { - case SHADER_NOMIP: - src = R_LoadShader( name, shaderType, false, TF_CLAMP|TF_NOMIPMAP|TF_NOPICMIP, SHADER_INVALID ); - break; - case SHADER_DECAL: - case SHADER_GENERIC: - src = R_LoadShader( name, shaderType, false, 0, SHADER_INVALID ); - break; - case SHADER_SPRITE: - src = CL_LoadSprite( name ); // hud sprites - break; - case SHADER_SKY: - R_SetupSky( name ); - src = tr.currentSkyShader; - break; - default: - MsgDev( D_WARN, "Mod_RegisterShader: invalid shader type (%i)\n", shaderType ); - return 0; - } - return src - r_shaders; -} - -shader_t Mod_RegisterShaderInt( const char *name, const byte *image_buf, size_t image_size ) -{ - texture_t *tex = R_FindTexture( va( "#%s", name ), image_buf, image_size, TF_CLAMP|TF_NOMIPMAP|TF_NOPICMIP ); - ref_shader_t *src; - - if( !tex ) - { - // no reason to duplicate default shader - MsgDev( D_ERROR, "Mod_RegisterShader: couldn't load %s\n", name ); - return tr.defaultShader - r_shaders; - } - - R_ShaderAddStageTexture( tex ); // set shader texture - src = R_LoadShader( name, SHADER_NOMIP, 0, 0, SHADER_INVALID ); - - return src - r_shaders; -} - -byte *Mod_GetCurrentVis( void ) -{ - return Mod_LeafPVS( r_viewleaf, r_worldmodel ); -} - -qboolean Mod_CullBox( const vec3_t mins, const vec3_t maxs ) -{ - return R_CullBox( mins, maxs, RI.clipFlags ); -} - -shader_t R_GetSpriteTexture( int spriteIndex, int spriteFrame ) -{ - ref_model_t *pSpriteModel; - mspriteframe_t *pSpriteFrame; - - if( spriteIndex <= 0 || spriteIndex >= MAX_MODELS ) - return tr.defaultShader->shadernum; // assume error - - pSpriteModel = cl_models[spriteIndex]; - - if( !pSpriteModel || pSpriteModel->type != mod_sprite ) - { - MsgDev( D_ERROR, "R_GetSpriteTexture: invalid Sprite %d\n", spriteIndex ); - return tr.defaultShader->shadernum; - } - - // okay, at this point we have valid sprite model - pSpriteFrame = R_GetSpriteFrame( pSpriteModel, spriteFrame, 0.0f ); - - return pSpriteFrame->shader; -} - -void R_SetSkyPortal( const vec3_t vieworg, const vec3_t viewangles, float scale, float fov ) -{ - VectorCopy( vieworg, RI.skyportal.vieworg ); - VectorCopy( viewangles, RI.skyportal.viewangles ); - RI.skyportal.fov = max( 1.0f, fov ); // to avoid division by zero - RI.skyportal.scale = scale; - RI.rdflags |= RDF_SKYPORTALINVIEW; // enable sky portal -} - -qboolean R_AddLightStyle( int stylenum, vec3_t color ) -{ - if( stylenum < 0 || stylenum > MAX_LIGHTSTYLES ) - return false; // invalid lightstyle - - R_AddLightStyleToScene( stylenum, color[0], color[1], color[2] ); - return true; -} - -qboolean R_AddGenericEntity( cl_entity_t *pRefEntity, ref_entity_t *refent ) -{ - // check model - if( !refent->model ) return false; - - refent->rtype = RT_MODEL; - - // get pointer to lerping frame data - refent->lerp = pRefEntity; - - // setup light origin - VectorCopy( pRefEntity->origin, refent->lightingOrigin ); - refent->lightingOrigin[2] += 1; - - switch( refent->model->type ) - { - case mod_world: - case mod_brush: - if( !refent->model->extradata ) - return false; - if( pRefEntity->curstate.skin ) - refent->waveHeight = refent->scale * 16.0f; - refent->scale = 1.0f; // ignore scale for brush models - refent->frame = pRefEntity->curstate.frame; // brush properly animating - break; - case mod_studio: - case mod_sprite: - if( !refent->model->extradata ) - return false; - if( refent->scale == 0.0f ) // fixup null scale - refent->scale = 1.0f; - refent->frame = 0.0f; // keep clear to prevent randomly change skins :-) - break; - case mod_bad: // let the render drawing null model - break; - } - - VectorCopy( pRefEntity->angles, refent->angles ); - VectorCopy( pRefEntity->origin, refent->origin ); - - Matrix3x3_FromAngles( refent->angles, refent->axis ); - VectorClear( refent->origin2 ); - - if( refent->ent_type == ET_PLAYER ) - { - refent->gaitsequence = pRefEntity->curstate.gaitsequence; - refent->doOcclusionTest = true; - refent->lightingOrigin[2] += refent->model->maxs[2] - 2; // drop shadow to floor - } - else refent->gaitsequence = 0; - VectorClear( refent->movedir ); - - if( refent->ent_type == ET_VIEWENTITY ) - { - if( r_lefthand->integer == 1 ) - VectorNegate( refent->axis[1], refent->axis[1] ); - } - - if( refent->model->type == mod_studio ) - { - R_StudioAllocExtradata( pRefEntity, refent ); - } - else - { - // entity has changed model, so no reason to keep this data - if( refent->extradata ) Mem_EmptyPool( refent->mempool ); - refent->extradata = NULL; - } - return true; -} - -qboolean R_AddPortalEntity( cl_entity_t *pRefEntity, ref_entity_t *refent ) -{ - refent->rtype = RT_PORTALSURFACE; - - VectorClear( refent->angles ); - VectorCopy( pRefEntity->curstate.vuser2, refent->movedir ); // FIXME: movedir - VectorCopy( pRefEntity->origin, refent->origin ); - VectorCopy( pRefEntity->curstate.vuser1, refent->origin2 ); // FIXME: oldorigin - - if( !VectorCompare( pRefEntity->curstate.origin, pRefEntity->curstate.vuser1 )) - RI.rdflags |= RDF_PORTALINVIEW; - - // calculate angles - Matrix3x3_FromAngles( refent->angles, refent->axis ); - return true; -} - -qboolean R_AddEntityToScene( cl_entity_t *pRefEntity, int entityType, shader_t customShader ) -{ - ref_entity_t *refent; - ref_shader_t *shader; - qboolean result = false; - - if( !pRefEntity || pRefEntity->curstate.modelindex <= 0 || pRefEntity->curstate.modelindex >= MAX_MODELS ) - return false; // if set to invisible, skip - if( r_numEntities >= MAX_ENTITIES ) - { - MsgDev( D_ERROR, "R_AddEntityToScene: too many visible entities\n" ); - return false; - } - refent = &r_entities[r_numEntities]; - - if( pRefEntity->curstate.rendermode != kRenderNormal && pRefEntity->curstate.renderamt <= 0.0f ) - return true; // done - - // ignore env_sprite flares if supposed - if( !r_spriteflares->integer && pRefEntity->curstate.rendermode == kRenderGlow ) - { - if( cl_models[pRefEntity->curstate.modelindex]->type == mod_sprite && !pRefEntity->curstate.renderfx ) - return true; // only sprite flares with variable size supposed to be ignored - // because we don't want ignore laserspot and other like things - } - - // copy state to render - refent->index = pRefEntity->index; - refent->ent_type = entityType; - refent->rendermode = pRefEntity->curstate.rendermode; - refent->rendercolor[0] = pRefEntity->curstate.rendercolor.r; - refent->rendercolor[1] = pRefEntity->curstate.rendercolor.g; - refent->rendercolor[2] = pRefEntity->curstate.rendercolor.b; - refent->body = pRefEntity->curstate.body; - refent->skin = pRefEntity->curstate.skin; - refent->scale = pRefEntity->curstate.scale; - refent->colormap = pRefEntity->curstate.colormap; - refent->flags = pRefEntity->curstate.effects; - refent->renderfx = pRefEntity->curstate.renderfx; - refent->renderamt = pRefEntity->curstate.renderamt; - refent->model = cl_models[pRefEntity->curstate.modelindex]; - refent->movetype = pRefEntity->curstate.movetype; - refent->framerate = pRefEntity->curstate.framerate; - refent->doOcclusionTest = false; - refent->parent = NULL; - refent->lerp = NULL; - - if( pRefEntity->curstate.rendermode == kRenderGlow && !pRefEntity->curstate.renderfx ) - refent->doOcclusionTest = true; - - // setup custom shader - if( customShader >= 0 && customShader < MAX_SHADERS && (shader = &r_shaders[customShader])) - refent->customShader = shader; - else refent->customShader = NULL; - - refent->rtype = RT_MODEL; - - // setup rtype - switch( entityType ) - { - case ET_PORTAL: - result = R_AddPortalEntity( pRefEntity, refent ); - break; - default: - result = R_AddGenericEntity( pRefEntity, refent ); - break; - } - - if( result ) r_numEntities++; - - refent->renderamt = R_ComputeFxBlend( refent ); - - if( entityType == ET_VIEWENTITY ) - { - // run events here to prevent - // de-synchronize muzzleflashes movement - R_StudioRunEvents( refent ); - } - - // never adding child entity without parent - // only studio models can have attached childrens - if( result && refent->model->type == mod_studio && pRefEntity->curstate.weaponmodel && (refent->renderfx != kRenderFxDeadPlayer)) - { - cl_entity_t FollowEntity = *pRefEntity; - - // create attached entity - FollowEntity.curstate.modelindex = pRefEntity->curstate.weaponmodel; - FollowEntity.curstate.movetype = MOVETYPE_FOLLOW; - FollowEntity.curstate.weaponmodel = 0; - - if( R_AddEntityToScene( &FollowEntity, ET_NORMAL, customShader )) - r_entities[r_numEntities-1].parent = refent; // set parent - } - return result; -} - -qboolean R_AddDynamicLight( vec3_t pos, color24 color, float radius, int flags ) -{ - ref_dlight_t *dl; - - if(( r_numDlights >= MAX_DLIGHTS ) || ( radius == 0.0f )) - return false; - - dl = &r_dlights[r_numDlights++]; - - VectorCopy( pos, dl->origin ); - dl->color[0] = color.r * ( 1.0f / 255.0f ); - dl->color[1] = color.g * ( 1.0f / 255.0f ); - dl->color[2] = color.b * ( 1.0f / 255.0f ); - dl->intensity = radius * 0.5f; - dl->flags = flags; - dl->shader = NULL; - - R_LightBounds( dl->origin, dl->intensity, dl->mins, dl->maxs ); - - return true; -} - -// main DLL entry point -BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) -{ - return TRUE; -} - -/* -@@@@@@@@@@@@@@@@@@@@@ -CreateAPI - -@@@@@@@@@@@@@@@@@@@@@ -*/ -render_exp_t EXPORT *CreateAPI(stdlib_api_t *input, render_imp_t *engfuncs ) -{ - static render_exp_t re; - - com = *input; - // Sys_LoadLibrary can create fake instance, to check - // api version and api size, but second argument will be 0 - // and always make exception, run simply check for avoid it - if( engfuncs ) ri = *engfuncs; - - // generic functions - re.api_size = sizeof( render_exp_t ); - re.com_size = sizeof( stdlib_api_t ); - - re.Init = R_Init; - re.Shutdown = R_Shutdown; - - re.BeginRegistration = R_BeginRegistration; - re.RegisterModel = R_UploadModel; - re.RegisterShader = Mod_RegisterShader; - re.RegisterShaderInt = Mod_RegisterShaderInt; - re.EndRegistration = R_EndRegistration; - re.FreeShader = Mod_FreeShader; - - re.AddLightStyle = R_AddLightStyle; - re.AddRefEntity = R_AddEntityToScene; - re.AddDLight = R_AddDynamicLight; - re.AddPolygon = R_AddPolyToScene; - re.DecalShoot = R_DecalShoot; - re.ClearScene = R_ClearScene; - - re.BeginFrame = R_BeginFrame; - re.RenderFrame = R_RenderScene; - re.EndFrame = R_EndFrame; - - re.RenderMode = Tri_RenderMode; - re.TexCoord2f = Tri_TexCoord2f; - re.Normal3f = Tri_Normal3f; - re.Vertex3f = Tri_Vertex3f; - re.Color4ub = Tri_Color4ub; - re.CullFace = Tri_CullFace; - re.Begin = Tri_Begin; - re.Bind = Tri_Bind; - re.End = Tri_End; - re.Fog = Tri_Fog; - - re.SetColor = R_DrawSetColor; - re.GetParms = R_DrawGetParms; - re.SetParms = R_DrawSetParms; - re.ScrShot = VID_ScreenShot; - re.EnvShot = VID_CubemapShot; - re.SetSkyPortal = R_SetSkyPortal; - re.LightForPoint = R_LightForPoint; - re.DrawStretchRaw = R_DrawStretchRaw; - re.DrawStretchPic = R_DrawStretchPic; - re.GetSpriteTexture = R_GetSpriteTexture; - re.ScreenToWorld = R_ScreenToWorld; - re.WorldToScreen = R_WorldToScreen; - re.RSpeedsMessage = R_SpeedsMessage; - re.CreateDecalList = R_CreateDecalList; - re.DecalRemoveAll = R_DecalRemoveAll; - re.CullBox = Mod_CullBox; - re.GetCurrentVis = Mod_GetCurrentVis; - re.RestoreGamma = R_RestoreGamma; - - return &re; -} \ No newline at end of file diff --git a/vid_gl/r_math.c b/vid_gl/r_math.c deleted file mode 100644 index 4c4725e3..00000000 --- a/vid_gl/r_math.c +++ /dev/null @@ -1,226 +0,0 @@ -/* -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// r_math.c - -#include "r_local.h" -#include "r_math.h" -#include "mathlib.h" - -/* -==================== -CalcFov -==================== -*/ -float CalcFov( float fov_x, float width, float height ) -{ - float x, half_fov_y; - - if( fov_x < 1 || fov_x > 170 ) - { - MsgDev( D_ERROR, "CalcFov: bad fov %g!\n", fov_x ); - fov_x = 90; - } - - x = width / tan( DEG2RAD( fov_x ) * 0.5f ); - half_fov_y = atan( height / x ); - return RAD2DEG( half_fov_y ) * 2; -} - -/* -==================== -AdjustFov -==================== -*/ -void AdjustFov( float *fov_x, float *fov_y, float width, float height, qboolean lock_x ) -{ - float x, y; - - if( width * 3 == 4 * height || width * 4 == height * 5 ) - { - // 4:3 or 5:4 ratio - return; - } - - if( lock_x ) - { - *fov_y = 2 * atan((width * 3) / (height * 4) * tan (*fov_y * M_PI / 360.0 * 0.5) ) * 360 / M_PI; - return; - } - - y = CalcFov( *fov_x, 640, 480 ); - x = *fov_x; - - *fov_x = CalcFov( y, height, width ); - if( *fov_x < x ) *fov_x = x; - else *fov_y = y; -} - -/* -================= -CategorizePlane - -A slightly more complex version of SignbitsForPlane and PlaneTypeForNormal, -which also tries to fix possible floating point glitches (like -0.00000 cases) -================= -*/ -void CategorizePlane( mplane_t *plane ) -{ - int i; - - plane->signbits = 0; - plane->type = PLANE_NONAXIAL; - - for( i = 0; i < 3; i++ ) - { - if( plane->normal[i] < 0 ) - { - plane->signbits |= 1<normal[i] == -1.0f ) - { - plane->signbits = (1<normal[0] = plane->normal[1] = plane->normal[2] = 0; - plane->normal[i] = -1.0f; - break; - } - } - else if( plane->normal[i] == 1.0f ) - { - plane->type = i; - plane->signbits = 0; - plane->normal[0] = plane->normal[1] = plane->normal[2] = 0; - plane->normal[i] = 1.0f; - break; - } - } -} - -/* -================== -BoxOnPlaneSide - -Returns 1, 2, or 1 + 2 -================== -*/ -int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p ) -{ - float dist1, dist2; - int sides = 0; - - // general case - switch( p->signbits ) - { - case 0: - dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; - dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; - break; - case 1: - dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; - dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; - break; - case 2: - dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; - dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; - break; - case 3: - dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; - dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; - break; - case 4: - dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; - dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; - break; - case 5: - dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; - dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; - break; - case 6: - dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; - dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; - break; - case 7: - dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; - dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; - break; - default: - // shut up compiler - dist1 = dist2 = 0; - break; - } - - if( dist1 >= p->dist ) - sides = 1; - if( dist2 < p->dist ) - sides |= 2; - - return sides; -} - -/* -==================== -RotatePointAroundVector -==================== -*/ -void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ) -{ - float t0, t1; - float angle, c, s; - vec3_t vr, vu, vf; - - angle = DEG2RAD( degrees ); - com.sincos( angle, &s, &c ); - VectorCopy( dir, vf ); - VectorVectors( vf, vr, vu ); - - t0 = vr[0] * c + vu[0] * -s; - t1 = vr[0] * s + vu[0] * c; - dst[0] = (t0 * vr[0] + t1 * vu[0] + vf[0] * vf[0]) * point[0] - + (t0 * vr[1] + t1 * vu[1] + vf[0] * vf[1]) * point[1] - + (t0 * vr[2] + t1 * vu[2] + vf[0] * vf[2]) * point[2]; - - t0 = vr[1] * c + vu[1] * -s; - t1 = vr[1] * s + vu[1] * c; - dst[1] = (t0 * vr[0] + t1 * vu[0] + vf[1] * vf[0]) * point[0] - + (t0 * vr[1] + t1 * vu[1] + vf[1] * vf[1]) * point[1] - + (t0 * vr[2] + t1 * vu[2] + vf[1] * vf[2]) * point[2]; - - t0 = vr[2] * c + vu[2] * -s; - t1 = vr[2] * s + vu[2] * c; - dst[2] = (t0 * vr[0] + t1 * vu[0] + vf[2] * vf[0]) * point[0] - + (t0 * vr[1] + t1 * vu[1] + vf[2] * vf[1]) * point[1] - + (t0 * vr[2] + t1 * vu[2] + vf[2] * vf[2]) * point[2]; -} - - -/* -================= -PlaneFromPoints -================= -*/ -void PlaneFromPoints( vec3_t verts[3], mplane_t *plane ) -{ - vec3_t v1, v2; - - VectorSubtract( verts[1], verts[0], v1 ); - VectorSubtract( verts[2], verts[0], v2 ); - CrossProduct( v2, v1, plane->normal ); - VectorNormalize( plane->normal ); - plane->dist = DotProduct( verts[0], plane->normal ); -} \ No newline at end of file diff --git a/vid_gl/r_math.h b/vid_gl/r_math.h deleted file mode 100644 index 338130ac..00000000 --- a/vid_gl/r_math.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ -#ifndef __R_MATH_H__ -#define __R_MATH_H__ - -// r_math.h -float CalcFov( float fov_x, float width, float height ); -int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p ); -void AdjustFov( float *fov_x, float *fov_y, float width, float height, qboolean lock_x ); -void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ); -void PlaneFromPoints( vec3_t verts[3], mplane_t *plane ); -void CategorizePlane( mplane_t *plane ); - -#define BOX_ON_PLANE_SIDE( emins, emaxs, p ) \ - ((( p )->type < 3 ) ? \ - ( \ - ((p)->dist <= (emins)[(p)->type]) ? \ - 1 \ - : \ - ( \ - ((p)->dist >= (emaxs)[(p)->type]) ? \ - 2 \ - : \ - 3 \ - ) \ - ) \ - : \ - BoxOnPlaneSide(( emins ), ( emaxs ), ( p ))) - - -/* -=============== -ColorNormalize -=============== -*/ -_inline float ColorNormalize( const float *in, vec3_t out ) -{ - float f = max( max( in[0], in[1] ), in[2] ); - - if( f > 1.0f ) - { - f = 1.0f / f; - out[0] = in[0] * f; - out[1] = in[1] * f; - out[2] = in[2] * f; - } - else - { - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - } - return f; -} - -#endif /*__R_MATH_H__*/ diff --git a/vid_gl/r_mesh.c b/vid_gl/r_mesh.c deleted file mode 100644 index 849b270e..00000000 --- a/vid_gl/r_mesh.c +++ /dev/null @@ -1,1443 +0,0 @@ -/* -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// r_mesh.c: transformation and sorting - -#include "r_local.h" -#include "mathlib.h" -#include "matrix_lib.h" - -#define QSORT_MAX_STACKDEPTH 2048 - -static byte *r_meshlistmempool; - -meshlist_t r_worldlist, r_shadowlist; -static meshlist_t r_portallist, r_skyportallist; - -static meshbuffer_t **r_portalSurfMbuffers; -static meshbuffer_t **r_skyPortalSurfMbuffers; - -static void R_QSortMeshBuffers( meshbuffer_t *meshes, int Li, int Ri ); -static void R_ISortMeshBuffers( meshbuffer_t *meshes, int num_meshes ); - -static qboolean R_AddPortalSurface( const meshbuffer_t *mb ); -static qboolean R_DrawPortalSurface( void ); - -#define R_MBCopy( in, out ) \ - ( \ - ( out ).sortkey = ( in ).sortkey, \ - ( out ).infokey = ( in ).infokey, \ - ( out ).modhandle = ( in ).modhandle, \ - ( out ).shaderkey = ( in ).shaderkey, \ - ( out ).shadowbits = ( in ).shadowbits \ - ) - -#define R_MBCmp( mb1, mb2 ) \ - ( \ - ( mb1 ).shaderkey > ( mb2 ).shaderkey ? true : \ - ( mb1 ).shaderkey < ( mb2 ).shaderkey ? false : \ - ( mb1 ).sortkey > ( mb2 ).sortkey ? true : \ - ( mb1 ).sortkey < ( mb2 ).sortkey ? false : \ - ( mb1 ).modhandle > ( mb2 ).modhandle ? true : \ - ( mb1 ).modhandle < ( mb2 ).modhandle ? false : \ - ( mb1 ).shadowbits > ( mb2 ).shadowbits \ - ) - -/* -================ -R_QSortMeshBuffers - -Quicksort -================ -*/ -static void R_QSortMeshBuffers( meshbuffer_t *meshes, int Li, int Ri ) -{ - int li, ri, stackdepth = 0, total = Ri + 1; - meshbuffer_t median, tempbuf; - int lstack[QSORT_MAX_STACKDEPTH], rstack[QSORT_MAX_STACKDEPTH]; - -mark0: - if( Ri - Li > 8 ) - { - li = Li; - ri = Ri; - - R_MBCopy( meshes[( Li+Ri ) >> 1], median ); - - if( R_MBCmp( meshes[Li], median ) ) - { - if( R_MBCmp( meshes[Ri], meshes[Li] ) ) - R_MBCopy( meshes[Li], median ); - } - else if( R_MBCmp( median, meshes[Ri] )) - { - R_MBCopy( meshes[Ri], median ); - } - - do - { - while( R_MBCmp( median, meshes[li] )) li++; - while( R_MBCmp( meshes[ri], median )) ri--; - - if( li <= ri ) - { - R_MBCopy( meshes[ri], tempbuf ); - R_MBCopy( meshes[li], meshes[ri] ); - R_MBCopy( tempbuf, meshes[li] ); - - li++; - ri--; - } - } while( li < ri ); - - if( ( Li < ri ) && ( stackdepth < QSORT_MAX_STACKDEPTH )) - { - lstack[stackdepth] = li; - rstack[stackdepth] = Ri; - stackdepth++; - li = Li; - Ri = ri; - goto mark0; - } - - if( li < Ri ) - { - Li = li; - goto mark0; - } - } - if( stackdepth ) - { - --stackdepth; - Ri = ri = rstack[stackdepth]; - Li = li = lstack[stackdepth]; - goto mark0; - } - - for( li = 1; li < total; li++ ) - { - R_MBCopy( meshes[li], tempbuf ); - ri = li - 1; - - while(( ri >= 0 ) && ( R_MBCmp( meshes[ri], tempbuf ))) - { - R_MBCopy( meshes[ri], meshes[ri+1] ); - ri--; - } - if( li != ri+1 ) - R_MBCopy( tempbuf, meshes[ri+1] ); - } -} - -/* -================ -R_ISortMeshes - -Insertion sort -================ -*/ -static void R_ISortMeshBuffers( meshbuffer_t *meshes, int num_meshes ) -{ - int i, j; - meshbuffer_t tempbuf; - - for( i = 1; i < num_meshes; i++ ) - { - R_MBCopy( meshes[i], tempbuf ); - j = i - 1; - - while(( j >= 0 ) && ( R_MBCmp( meshes[j], tempbuf ))) - { - R_MBCopy( meshes[j], meshes[j+1] ); - j--; - } - if( i != j+1 ) - R_MBCopy( tempbuf, meshes[j+1] ); - } -} - -/* -======================================================================= - -VERTEX BUFFERS - -======================================================================= -*/ -/* -================= -R_UpdateVertexBuffer -================= -*/ -void R_UpdateVertexBuffer( vbo_buffer_t *vertexBuffer, const void *data, size_t size ) -{ - ASSERT( vertexBuffer ); - - if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT )) - { - vertexBuffer->pointer = (char *)data; - return; - } - - if( !r_vertexbuffers->integer ) - { - vertexBuffer->pointer = (char *)data; - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); - return; - } - - vertexBuffer->pointer = NULL; - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vertexBuffer->bufNum ); - pglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, 0, size, data ); -} - -/* -================= -R_AllocVertexBuffer -================= -*/ -vbo_buffer_t *R_AllocVertexBuffer( size_t size, GLuint usage ) -{ - vbo_buffer_t *vertexBuffer; - - if( tr.numVertexBufferObjects == MAX_VERTEX_BUFFER_OBJECTS ) - Host_Error( "RB_AllocVertexBuffer: MAX_VERTEX_BUFFER_OBJECTS limit exceeds\n" ); - - vertexBuffer = &tr.vertexBufferObjects[tr.numVertexBufferObjects++]; - - vertexBuffer->pointer = NULL; - vertexBuffer->size = size; - vertexBuffer->usage = usage; - - if(!GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT )) - return vertexBuffer; - - pglGenBuffersARB( 1, &vertexBuffer->bufNum ); - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vertexBuffer->bufNum ); - pglBufferDataARB( GL_ARRAY_BUFFER_ARB, vertexBuffer->size, NULL, vertexBuffer->usage ); - - return vertexBuffer; -} - -/* -================= -R_InitVertexBuffers -================= -*/ -void R_InitVertexBuffers( void ) -{ - int i; - - tr.vertexBuffer = R_AllocVertexBuffer( MAX_ARRAY_VERTS * sizeof( vec4_t ), GL_DYNAMIC_DRAW_ARB ); - tr.colorsBuffer = R_AllocVertexBuffer( MAX_ARRAY_VERTS * sizeof( rgba_t ), GL_DYNAMIC_DRAW_ARB ); - tr.normalBuffer = R_AllocVertexBuffer( MAX_ARRAY_VERTS * sizeof( vec4_t ), GL_DYNAMIC_DRAW_ARB ); - for( i = 0; i < MAX_TEXTURE_UNITS; i++ ) - tr.tcoordBuffer[i] = R_AllocVertexBuffer( MAX_ARRAY_VERTS * sizeof( vec4_t ), GL_DYNAMIC_DRAW_ARB ); -} - -/* -================= -R_ShutdownVertexBuffers -================= -*/ -void R_ShutdownVertexBuffers( void ) -{ - vbo_buffer_t *vertexBuffer; - int i; - - if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT )) - { - Mem_Set( tr.vertexBufferObjects, 0, sizeof( tr.vertexBufferObjects )); - tr.numVertexBufferObjects = 0; - return; - } - - pglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); - for( i = 0, vertexBuffer = tr.vertexBufferObjects; i < tr.numVertexBufferObjects; i++, vertexBuffer++ ) - pglDeleteBuffersARB( 1, &vertexBuffer->bufNum ); - - Mem_Set( tr.vertexBufferObjects, 0, sizeof( tr.vertexBufferObjects )); - tr.numVertexBufferObjects = 0; -} - -/* -================= -R_ReAllocMeshList -================= -*/ -int R_ReAllocMeshList( meshbuffer_t **mb, int minMeshes, int maxMeshes ) -{ - int oldSize, newSize; - meshbuffer_t *newMB; - - oldSize = maxMeshes; - newSize = max( minMeshes, oldSize * 2 ); - - newMB = Mem_Alloc( r_meshlistmempool, newSize * sizeof( meshbuffer_t )); - if( *mb ) - { - Mem_Copy( newMB, *mb, oldSize * sizeof( meshbuffer_t )); - Mem_Free( *mb ); - } - *mb = newMB; - - // NULL all pointers to old membuffers so we don't crash - if( r_worldmodel && RI.drawWorld ) - Mem_Set( RI.surfmbuffers, 0, r_worldbrushmodel->numsurfaces * sizeof( meshbuffer_t* )); - - return newSize; -} - -/* -================= -R_AddMeshToList - -Calculate sortkey and store info used for batching and sorting. -All 3D-geometry passes this function. -================= -*/ -meshbuffer_t *R_AddMeshToList( int type, mfog_t *fog, ref_shader_t *shader, int infokey ) -{ - meshlist_t *list; - meshbuffer_t *meshbuf; - - if( !shader ) return NULL; - - if( RI.currententity && ( shader->flags & SHADER_RENDERMODE )) - { - switch( RI.currententity->rendermode ) - { - case kRenderTransTexture: - case kRenderGlow: - case kRenderTransAdd: - case kRenderTransColor: - shader->sort = SORT_ADDITIVE; - break; - case kRenderTransAlpha: - shader->sort = SORT_ALPHATEST; - break; - case kRenderNormal: - default: shader->sort = shader->realsort; // restore original - break; - } - shader->sortkey = Shader_Sortkey( shader, shader->sort ); // update sortkey too - } - - list = RI.meshlist; - if( shader->sort > SORT_OPAQUE ) - { - if( list->num_translucent_meshes >= list->max_translucent_meshes ) // reallocate if needed - list->max_translucent_meshes = R_ReAllocMeshList( &list->meshbuffer_translucent, MIN_RENDER_MESHES/2, list->max_translucent_meshes ); - - if( shader->flags & SHADER_PORTAL ) - { - if( RI.params & ( RP_MIRRORVIEW|RP_PORTALVIEW|RP_SKYPORTALVIEW )) - return NULL; - RI.meshlist->num_portal_translucent_meshes++; - } - meshbuf = &list->meshbuffer_translucent[list->num_translucent_meshes++]; - } - else - { - if( list->num_opaque_meshes >= list->max_opaque_meshes ) // reallocate if needed - list->max_opaque_meshes = R_ReAllocMeshList( &list->meshbuffer_opaque, MIN_RENDER_MESHES, list->max_opaque_meshes ); - - if( shader->flags & SHADER_PORTAL ) - { - if( RI.params & ( RP_MIRRORVIEW|RP_PORTALVIEW|RP_SKYPORTALVIEW ) ) - return NULL; - RI.meshlist->num_portal_opaque_meshes++; - } - meshbuf = &list->meshbuffer_opaque[list->num_opaque_meshes++]; - } - - meshbuf->sortkey = MB_ENTITY2NUM( RI.currententity ) | MB_FOG2NUM( fog ) | type; - meshbuf->shaderkey = shader->sortkey; - meshbuf->infokey = infokey; - meshbuf->dlightbits = 0; - meshbuf->shadowbits = r_entShadowBits[RI.currententity - r_entities]; - - return meshbuf; -} - -/* -================= -R_AddMeshToList -================= -*/ -void R_AddModelMeshToList( uint modhandle, mfog_t *fog, ref_shader_t *shader, int meshnum ) -{ - meshbuffer_t *mb; - - mb = R_AddMeshToList( MB_MODEL, fog, shader, -( meshnum+1 ) ); - if( mb ) mb->modhandle = modhandle; -} - -/* -================ -R_BatchMeshBuffer - -Draw the mesh or batch it. -================ -*/ -static void R_BatchMeshBuffer( const meshbuffer_t *mb, const meshbuffer_t *nextmb ) -{ - int type, features; - qboolean nonMergable; - msurface_t *surf, *nextSurf; - decal_t *decal, *nextDecal; - ref_shader_t *shader; - ref_entity_t *ent; - - MB_NUM2ENTITY( mb->sortkey, ent ); - - if( RI.currententity != ent ) - { - RI.previousentity = RI.currententity; - RI.currententity = ent; - RI.currentmodel = ent->model; - } - - type = mb->sortkey & 3; - tr.iRenderMode = RI.currententity->rendermode; - - switch( type ) - { - case MB_MODEL: - switch( ent->model->type ) - { - case mod_world: - case mod_brush: - MB_NUM2SHADER( mb->shaderkey, shader ); - - if( shader->flags & SHADER_SKYPARMS ) - { - // draw sky - if(!( RI.params & RP_NOSKY )) - { - R_DrawSky( tr.currentSkyShader ); - } - return; - } - - surf = &r_worldbrushmodel->surfaces[mb->infokey-1]; - R_UpdateSurfaceLightmap( surf ); - - nextSurf = NULL; - - features = shader->features; - if( r_shownormals->integer ) - features |= MF_NORMALS; - - if( features & MF_NONBATCHED ) - { - nonMergable = true; - } - else - { // check if we need to render batched geometry this frame - if( nextmb - && ( nextmb->shaderkey == mb->shaderkey ) - && ( nextmb->sortkey == mb->sortkey ) - && ( nextmb->dlightbits == mb->dlightbits ) - && ( nextmb->shadowbits == mb->shadowbits )) - { - if( nextmb->infokey > 0 ) - { - nextSurf = &r_worldbrushmodel->surfaces[nextmb->infokey-1]; - R_UpdateSurfaceLightmap( nextSurf ); - } - } - - nonMergable = nextSurf ? R_MeshOverflow2( surf->mesh, nextSurf->mesh ) : true; - if( nonMergable && !r_backacc.numVerts ) - features |= MF_NONBATCHED; - } - - R_PushMesh( surf->mesh, features ); - - if( nonMergable ) - { - if( RI.previousentity != RI.currententity ) - R_RotateForEntity( RI.currententity ); - R_RenderMeshBuffer( mb ); - } - break; - case mod_studio: - R_DrawStudioModel( mb ); - break; - case mod_sprite: - R_DrawSpriteModel( mb ); - break; - default: - Host_Error( "R_DrawModel: bad modeltype %i\n", type ); - break; - } - break; - case MB_CORONA: - nonMergable = R_PushSpritePoly( mb ); - if( nonMergable || !nextmb || (( nextmb->shaderkey & 0xFC000FFF ) != ( mb->shaderkey & 0xFC000FFF )) - || (( nextmb->sortkey & 0xFFFFF ) != ( mb->sortkey & 0xFFFFF )) || R_SpriteOverflow() ) - { - if( !nonMergable ) - { - RI.currententity = r_worldent; - RI.currentmodel = r_worldmodel; - } - - // no rotation for sprites - if( RI.previousentity != RI.currententity ) - R_TranslateForEntity( RI.currententity ); - R_RenderMeshBuffer( mb ); - } - break; - case MB_POLY: - // polys are already batched at this point - R_PushPoly( mb ); - - if( RI.previousentity != RI.currententity ) - R_LoadIdentity(); - R_RenderMeshBuffer( mb ); - break; - case MB_DECAL: - MB_NUM2SHADER( mb->shaderkey, shader ); - - features = shader->features; - if( r_shownormals->integer ) - features |= MF_NORMALS; - - nextDecal = NULL; - decal = R_DecalFromMeshbuf( mb ); - - if( features & MF_NONBATCHED ) - { - nonMergable = true; - } - else - { // check if we need to render batched geometry this frame - if( nextmb - && ( nextmb->shaderkey == mb->shaderkey ) - && ( nextmb->sortkey == mb->sortkey ) -// && ( nextmb->dlightbits == mb->dlightbits ) - && ( nextmb->shadowbits == mb->shadowbits )) - { - if(( nextmb->sortkey & 3 ) == MB_DECAL ) - nextDecal = R_DecalFromMeshbuf( nextmb ); - - if( nextDecal && decal->currentFrame != nextDecal->currentFrame ) - nextDecal = NULL; // force to flush - } - - nonMergable = nextDecal ? R_MeshOverflow2( decal->mesh, nextDecal->mesh ) : true; - if( nonMergable && !r_backacc.numVerts ) - features |= MF_NONBATCHED; - } - - R_PushDecal( mb ); - - if( nonMergable ) - { - if( RI.previousentity != RI.currententity ) - R_RotateForEntity( RI.currententity ); - R_RenderMeshBuffer( mb ); - } - break; - } -} - -/* -================ -R_SortMeshList - -Use quicksort for opaque meshes and insertion sort for translucent meshes. -================ -*/ -void R_SortMeshes( void ) -{ - if( r_draworder->integer ) - return; - - if( RI.meshlist->num_opaque_meshes ) - R_QSortMeshBuffers( RI.meshlist->meshbuffer_opaque, 0, RI.meshlist->num_opaque_meshes - 1 ); - if( RI.meshlist->num_translucent_meshes ) - R_ISortMeshBuffers( RI.meshlist->meshbuffer_translucent, RI.meshlist->num_translucent_meshes ); -} - -/* -================ -R_DrawPortals - -Render portal views. For regular portals we stop after rendering the -first valid portal view. -Skyportal views are rendered afterwards. -================ -*/ -void R_DrawPortals( void ) -{ - int i, trynum, num_meshes, total_meshes; - ref_shader_t *shader; - meshbuffer_t *mb; - - if( r_viewleaf == NULL ) - return; - - if( !( RI.params & ( RP_MIRRORVIEW|RP_PORTALVIEW|RP_SHADOWMAPVIEW ))) - { - if( RI.meshlist->num_portal_opaque_meshes || RI.meshlist->num_portal_translucent_meshes ) - { - trynum = 0; - - R_AddPortalSurface( NULL ); - - do - { - switch( trynum ) - { - case 0: - mb = RI.meshlist->meshbuffer_opaque; - total_meshes = RI.meshlist->num_opaque_meshes; - num_meshes = RI.meshlist->num_portal_opaque_meshes; - break; - case 1: - mb = RI.meshlist->meshbuffer_translucent; - total_meshes = RI.meshlist->num_translucent_meshes; - num_meshes = RI.meshlist->num_portal_translucent_meshes; - break; - default: - mb = NULL; - total_meshes = num_meshes = 0; - break; - } - - for( i = 0; i < total_meshes && num_meshes; i++, mb++ ) - { - MB_NUM2SHADER( mb->shaderkey, shader ); - - if( shader->flags & SHADER_PORTAL ) - { - num_meshes--; - - if( r_fastsky->integer && !( shader->flags & SHADER_PORTAL_CAPTURE ) ) - continue; - - if( !R_AddPortalSurface( mb )) - { - if( R_DrawPortalSurface()) - { - trynum = 2; - break; - } - } - } - } - } while( ++trynum < 2 ); - - R_DrawPortalSurface(); - } - } - - if(( RI.rdflags & RDF_SKYPORTALINVIEW ) && !( RI.params & RP_NOSKY ) && !r_fastsky->integer ) - { - for( i = 0, mb = RI.meshlist->meshbuffer_opaque; i < RI.meshlist->num_opaque_meshes; i++, mb++ ) - { - MB_NUM2SHADER( mb->shaderkey, shader ); - - if( shader->flags & SHADER_SKYPARMS ) - { - R_DrawSky( tr.currentSkyShader ); - RI.params |= RP_NOSKY; - return; - } - } - } -} - -/* -=============== -R_RenderFog -=============== -*/ -void R_RenderFog( void ) -{ - if( !triState.fogEnabled ) return; - - pglEnable( GL_FOG ); -// pglFogf( GL_FOG_DENSITY, 0.0025 ); - pglFogi( GL_FOG_MODE, GL_LINEAR ); - pglFogfv( GL_FOG_COLOR, triState.fogColor ); - pglFogf( GL_FOG_START, triState.fogStartDist ); - pglFogf( GL_FOG_END, triState.fogEndDist ); - pglHint( GL_FOG_HINT, GL_NICEST ); -} - -/* -================ -R_DrawMeshes -================ -*/ -void R_DrawMeshes( void ) -{ - int i; - meshbuffer_t *meshbuf; - - R_RenderFog(); - - RI.previousentity = NULL; - if( RI.meshlist->num_opaque_meshes ) - { - meshbuf = RI.meshlist->meshbuffer_opaque; - for( i = 0; i < RI.meshlist->num_opaque_meshes - 1; i++, meshbuf++ ) - R_BatchMeshBuffer( meshbuf, meshbuf+1 ); - R_BatchMeshBuffer( meshbuf, NULL ); - } - Tri_RenderCallback( false ); - - // don't fogging translucent surfaces - if( triState.fogEnabled ) pglDisable( GL_FOG ); - - if( !( RI.params & RP_NONVIEWERREF )) - { - // all solid meshes are drawing. It's time to call sound extra update - ri.ExtraUpdate(); - } - - if( RI.meshlist->num_translucent_meshes ) - { - meshbuf = RI.meshlist->meshbuffer_translucent; - for( i = 0; i < RI.meshlist->num_translucent_meshes - 1; i++, meshbuf++ ) - { - ref_entity_t *ent; - msurface_t *surf; - int type = meshbuf->sortkey & 3; - - MB_NUM2ENTITY( meshbuf->sortkey, ent ); - - if( type == MB_MODEL && ent && ent->model ) - { - switch( ent->model->type ) - { - case mod_world: - case mod_brush: - surf = &r_worldbrushmodel->surfaces[meshbuf->infokey-1]; - R_UpdateSurfaceLightmap( surf ); - break; - } - } - } - - meshbuf = RI.meshlist->meshbuffer_translucent; - for( i = 0; i < RI.meshlist->num_translucent_meshes - 1; i++, meshbuf++ ) - R_BatchMeshBuffer( meshbuf, meshbuf + 1 ); - R_BatchMeshBuffer( meshbuf, NULL ); - } - Tri_RenderCallback( true ); - - R_LoadIdentity(); - - // clearing fog after each frame - if( !( RI.params & RP_NONVIEWERREF )) - triState.fogEnabled = false; -} - -/* -=============== -R_InitMeshLists -=============== -*/ -void R_InitMeshLists( void ) -{ - if( !r_meshlistmempool ) - r_meshlistmempool = Mem_AllocPool( "MeshList" ); -} - -/* -=============== -R_AllocMeshbufPointers -=============== -*/ -void R_AllocMeshbufPointers( refinst_t *RI ) -{ - ASSERT( r_worldmodel ); - - if( !RI->surfmbuffers ) - RI->surfmbuffers = Mem_Alloc( r_meshlistmempool, r_worldbrushmodel->numsurfaces * sizeof( meshbuffer_t* )); -} - -/* -=============== -R_FreeMeshLists -=============== -*/ -void R_FreeMeshLists( void ) -{ - if( !r_meshlistmempool ) - return; - - r_portalSurfMbuffers = NULL; - r_skyPortalSurfMbuffers = NULL; - - Mem_FreePool( &r_meshlistmempool ); - - Mem_Set( &r_worldlist, 0, sizeof( meshlist_t )); - Mem_Set( &r_shadowlist, 0, sizeof( meshlist_t )); - Mem_Set( &r_portallist, 0, sizeof( meshlist_t )); - Mem_Set( &r_skyportallist, 0, sizeof( r_skyportallist )); -} - -/* -=============== -R_ClearMeshList -=============== -*/ -void R_ClearMeshList( meshlist_t *meshlist ) -{ - // clear counters - meshlist->num_opaque_meshes = 0; - meshlist->num_translucent_meshes = 0; - - meshlist->num_portal_opaque_meshes = 0; - meshlist->num_portal_translucent_meshes = 0; -} - -/* -=============== -R_DrawTriangleOutlines -=============== -*/ -void R_DrawTriangleOutlines( qboolean showTris, qboolean showNormals ) -{ - if( !showTris && !showNormals ) - return; - - RI.params |= (showTris ? RP_TRISOUTLINES : 0) | (showNormals ? RP_SHOWNORMALS : 0); - R_BackendBeginTriangleOutlines(); - R_DrawMeshes(); - R_BackendEndTriangleOutlines(); - RI.params &= ~(RP_TRISOUTLINES|RP_SHOWNORMALS); -} - -/* -=============== -R_ScissorForPortal - -Returns the on-screen scissor box for given bounding box in 3D-space. -=============== -*/ -qboolean R_ScissorForPortal( ref_entity_t *ent, vec3_t mins, vec3_t maxs, int *x, int *y, int *w, int *h ) -{ - int i; - int ix1, iy1, ix2, iy2; - float x1, y1, x2, y2; - vec3_t v, bbox[8]; - - R_TransformEntityBBox( ent, mins, maxs, bbox, true ); - - x1 = y1 = 999999; - x2 = y2 = -999999; - for( i = 0; i < 8; i++ ) - { - // compute and rotate a full bounding box - vec_t *corner = bbox[i]; - R_TransformToScreen_Vec3( corner, v ); - - if( v[2] < 0 || v[2] > 1 ) - { - // the test point is behind the nearclip plane - if( PlaneDiff( corner, &RI.frustum[0] ) < PlaneDiff( corner, &RI.frustum[1] )) - v[0] = 0; - else v[0] = RI.refdef.viewport[2]; - - if( PlaneDiff( corner, &RI.frustum[2] ) < PlaneDiff( corner, &RI.frustum[3] )) - v[1] = 0; - else v[1] = RI.refdef.viewport[3]; - } - - x1 = min( x1, v[0] ); - y1 = min( y1, v[1] ); - x2 = max( x2, v[0] ); - y2 = max( y2, v[1] ); - } - - ix1 = max( x1 - 1.0f, 0 ); - ix2 = min( x2 + 1.0f, RI.refdef.viewport[2] ); - if( ix1 >= ix2 ) return false; // FIXME - - iy1 = max( y1 - 1.0f, 0 ); - iy2 = min( y2 + 1.0f, RI.refdef.viewport[3] ); - if( iy1 >= iy2 ) return false; // FIXME - - *x = ix1; - *y = iy1; - *w = ix2 - ix1; - *h = iy2 - iy1; - - return true; -} - -/* -=============== -R_AddPortalSurface -=============== -*/ -static ref_entity_t *r_portal_ent; -static mplane_t r_portal_plane, r_original_portal_plane; -static ref_shader_t *r_portal_shader; -static vec3_t r_portal_mins, r_portal_maxs, r_portal_centre; - -static qboolean R_AddPortalSurface( const meshbuffer_t *mb ) -{ - int i; - float dist; - ref_entity_t *ent; - ref_shader_t *shader; - msurface_t *surf; - mplane_t plane, oplane; - mesh_t *mesh; - vec3_t mins, maxs, centre; - vec3_t v[3], entity_rotation[3]; - - if( !mb ) - { - r_portal_ent = r_worldent; - r_portal_shader = NULL; - VectorClear( r_portal_plane.normal ); - ClearBounds( r_portal_mins, r_portal_maxs ); - return false; - } - - MB_NUM2ENTITY( mb->sortkey, ent ); - if( !ent->model ) return false; - - surf = mb->infokey > 0 ? &r_worldbrushmodel->surfaces[mb->infokey-1] : NULL; - if( !surf || !( mesh = surf->mesh ) || !mesh->vertexArray ) - return false; - - MB_NUM2SHADER( mb->shaderkey, shader ); - - VectorCopy( mesh->vertexArray[mesh->elems[0]], v[0] ); - VectorCopy( mesh->vertexArray[mesh->elems[1]], v[1] ); - VectorCopy( mesh->vertexArray[mesh->elems[2]], v[2] ); - PlaneFromPoints( v, &oplane ); - oplane.dist += DotProduct( ent->origin, oplane.normal ); - CategorizePlane( &oplane ); - - if( !Matrix3x3_Compare( ent->axis, matrix3x3_identity )) - { - Matrix3x3_Transpose( entity_rotation, ent->axis ); - Matrix3x3_Transform( entity_rotation, mesh->vertexArray[mesh->elems[0]], v[0] ); - VectorMA( ent->origin, ent->scale, v[0], v[0] ); - Matrix3x3_Transform( entity_rotation, mesh->vertexArray[mesh->elems[1]], v[1] ); - VectorMA( ent->origin, ent->scale, v[1], v[1] ); - Matrix3x3_Transform( entity_rotation, mesh->vertexArray[mesh->elems[2]], v[2] ); - VectorMA( ent->origin, ent->scale, v[2], v[2] ); - PlaneFromPoints( v, &plane ); - CategorizePlane( &plane ); - } - else - { - plane = oplane; - } - - if(( dist = PlaneDiff( RI.viewOrigin, &plane )) <= BACKFACE_EPSILON ) - { - if(!( shader->flags & SHADER_PORTAL_CAPTURE2 )) - return true; - } - - // check if we are too far away and the portal view is obscured - // by an alphagen portal stage - for( i = 0; i < shader->num_stages; i++ ) - { - if( shader->stages[i].alphaGen.type == ALPHAGEN_PORTAL ) - { - if( dist > ( 1.0f / shader->stages[i].alphaGen.args[0] ) ) - return true; // completely alpha'ed out - } - } - - if( OCCLUSION_QUERIES_ENABLED( RI )) - { - if( !R_GetOcclusionQueryResultBool( OQ_CUSTOM, R_SurfOcclusionQueryKey( ent, surf ), true ) ) - return true; - } - - VectorAdd( ent->origin, surf->mins, mins ); - VectorAdd( ent->origin, surf->maxs, maxs ); - VectorAdd( mins, maxs, centre ); - VectorScale( centre, 0.5f, centre ); - - if( r_portal_shader && ( shader != r_portal_shader )) - { - if( VectorDistance2( RI.viewOrigin, centre ) > VectorDistance2( RI.viewOrigin, r_portal_centre )) - return true; - VectorClear( r_portal_plane.normal ); - ClearBounds( r_portal_mins, r_portal_maxs ); - } - r_portal_shader = shader; - - if( !Matrix3x3_Compare( ent->axis, matrix3x3_identity )) - { - r_portal_ent = ent; - r_portal_plane = plane; - r_original_portal_plane = oplane; - VectorCopy( surf->mins, r_portal_mins ); - VectorCopy( surf->maxs, r_portal_maxs ); - return false; - } - - if( !VectorCompare( r_portal_plane.normal, vec3_origin ) && !( VectorCompare( plane.normal, r_portal_plane.normal ) && plane.dist == r_portal_plane.dist ) ) - { - if( VectorDistance2( RI.viewOrigin, centre ) > VectorDistance2( RI.viewOrigin, r_portal_centre )) - return true; - VectorClear( r_portal_plane.normal ); - ClearBounds( r_portal_mins, r_portal_maxs ); - } - - if( VectorCompare( r_portal_plane.normal, vec3_origin ) ) - { - r_portal_plane = plane; - r_original_portal_plane = oplane; - } - - AddPointToBounds( mins, r_portal_mins, r_portal_maxs ); - AddPointToBounds( maxs, r_portal_mins, r_portal_maxs ); - VectorAdd( r_portal_mins, r_portal_maxs, r_portal_centre ); - VectorScale( r_portal_centre, 0.5, r_portal_centre ); - - return true; -} - -/* -=============== -R_DrawPortalSurface - -Renders the portal view and captures the results from framebuffer if -we need to do a $portalmap stage. Note that for $portalmaps we must -use a different viewport. -Return true upon success so that we can stop rendering portals. -=============== -*/ -static qboolean R_DrawPortalSurface( void ) -{ - float dist, d; - refinst_t oldRI; - vec3_t origin, angles; - ref_entity_t *ent; - mplane_t *portal_plane = &r_portal_plane; - mplane_t *original_plane = &r_original_portal_plane; - ref_shader_t *shader = r_portal_shader; - qboolean mirror, refraction = false; - texture_t **captureTexture; - int captureTextureID; - qboolean doReflection, doRefraction; - int i, x, y, w, h; - - if( !r_portal_shader ) - return false; - - doReflection = doRefraction = true; - if( shader->flags & SHADER_PORTAL_CAPTURE1 ) - { - ref_stage_t *pass; - - captureTexture = &tr.portaltexture1; - captureTextureID = 1; - - for( i = 0, pass = shader->stages; i < shader->num_stages; i++, pass++ ) - { - if( pass->program && pass->program_type == PROGRAM_TYPE_DISTORTION ) - { - if(( pass->alphaGen.type == ALPHAGEN_CONST && pass->alphaGen.args[0] == 1 )) - doRefraction = false; - else if(( pass->alphaGen.type == ALPHAGEN_CONST && pass->alphaGen.args[0] == 0 ) ) - doReflection = false; - break; - } - } - } - else - { - captureTexture = NULL; - captureTextureID = 0; - } - - // copy portal plane here because we may be flipped later for refractions - RI.portalPlane = *portal_plane; - - if(( dist = PlaneDiff( RI.viewOrigin, portal_plane ) ) <= BACKFACE_EPSILON || !doReflection ) - { - if( !( shader->flags & SHADER_PORTAL_CAPTURE2 ) || !doRefraction ) - return false; - - // even if we're behind the portal, we still need to capture - // the second portal image for refraction - refraction = true; - captureTexture = &tr.portaltexture2; - captureTextureID = 2; - if( dist < 0 ) - { - VectorNegate( portal_plane->normal, portal_plane->normal ); - portal_plane->dist = -portal_plane->dist; - } - } - - if( !R_ScissorForPortal( r_portal_ent, r_portal_mins, r_portal_maxs, &x, &y, &w, &h )) - return false; - - mirror = true; // default to mirror view - // it is stupid IMO that mirrors require a RT_PORTALSURFACE entity - - ent = r_portal_ent; - for( i = 1; i < r_numEntities; i++ ) - { - ent = &r_entities[i]; - - if( ent->rtype == RT_PORTALSURFACE ) - { - if( ent->flags & EF_NODRAW ) continue; // disabled - d = PlaneDiff( ent->origin, original_plane ); - if( ( d >= -64 ) && ( d <= 64 ) ) - { - if( !VectorCompare( ent->origin, ent->origin2 )) // portal - mirror = false; - ent->rtype = -1; - break; - } - } - } - - if(( i == r_numEntities ) && !captureTexture ) - return false; - -setup_and_render: - RI.previousentity = NULL; - Mem_Copy( &oldRI, &prevRI, sizeof( refinst_t ) ); - Mem_Copy( &prevRI, &RI, sizeof( refinst_t ) ); - - if( refraction ) - { - VectorNegate( portal_plane->normal, portal_plane->normal ); - portal_plane->dist = -portal_plane->dist - 1; - CategorizePlane( portal_plane ); - VectorCopy( RI.viewOrigin, origin ); - VectorCopy( RI.refdef.viewangles, angles ); - - RI.params = RP_PORTALVIEW; - if( r_viewleaf != NULL ) - RI.params |= RP_OLDVIEWLEAF; - } - else if( mirror ) - { - vec3_t M[3]; - - d = -2 * ( DotProduct( RI.viewOrigin, portal_plane->normal ) - portal_plane->dist ); - VectorMA( RI.viewOrigin, d, portal_plane->normal, origin ); - - for( i = 0; i < 3; i++ ) - { - d = -2 * DotProduct( RI.viewAxis[i], portal_plane->normal ); - VectorMA( RI.viewAxis[i], d, portal_plane->normal, M[i] ); - VectorNormalize( M[i] ); - } - - Matrix3x3_ToAngles( M, angles, true ); - angles[ROLL] = -angles[ROLL]; - - RI.params = RP_MIRRORVIEW|RP_FLIPFRONTFACE; - if( r_viewleaf != NULL ) - RI.params |= RP_OLDVIEWLEAF; - } - else - { - vec3_t tvec; - vec3_t A[3], B[3], C[3], rot[3]; - - // build world-to-portal rotation matrix - VectorNegate( portal_plane->normal, A[0] ); - NormalVectorToAxis( A[0], A ); - - // build portal_dest-to-world rotation matrix - // FIXME: movedir isn't used, portals are broken - VectorCopy( ent->movedir, portal_plane->normal ); - NormalVectorToAxis( portal_plane->normal, B ); - Matrix3x3_Transpose( C, B ); - - // multiply to get world-to-world rotation matrix - Matrix3x3_Concat( rot, C, A ); - - // translate view origin - VectorSubtract( RI.viewOrigin, ent->origin, tvec ); - Matrix3x3_Transform( rot, tvec, origin ); - VectorAdd( origin, ent->origin2, origin ); - - for( i = 0; i < 3; i++ ) Matrix3x3_Transform( A, RI.viewAxis[i], rot[i] ); - Matrix3x3_Concat( B, ent->axis, rot ); - for( i = 0; i < 3; i++ ) Matrix3x3_Transform( C, B[i], A[i] ); - - // set up portal_plane -// VectorCopy( A[0], portal_plane->normal ); - portal_plane->dist = DotProduct( ent->origin2, portal_plane->normal ); - CategorizePlane( portal_plane ); - - // calculate Euler angles for our rotation matrix - Matrix3x3_ToAngles( A, angles, true ); - - // for portals, vis data is taken from portal origin, not - // view origin, because the view point moves around and - // might fly into (or behind) a wall - RI.params = RP_PORTALVIEW; - VectorCopy( ent->origin2, RI.pvsOrigin ); - } - - RI.shadowGroup = NULL; - RI.meshlist = &r_portallist; - RI.surfmbuffers = r_portalSurfMbuffers; - - RI.params |= RP_CLIPPLANE; - RI.clipPlane = *portal_plane; - - RI.clipFlags |= ( 1<<5 ); - VectorNegate( portal_plane->normal, RI.frustum[5].normal ); - RI.frustum[5].dist = -portal_plane->dist; - RI.frustum[5] = *portal_plane; - CategorizePlane( &RI.frustum[5] ); - - if( captureTexture ) - { - R_InitPortalTexture( captureTexture, captureTextureID, r_lastRefdef.viewport[2], r_lastRefdef.viewport[3] ); - - x = y = 0; - w = ( *captureTexture )->width; - h = ( *captureTexture )->height; - RI.refdef.viewport[2] = w; - RI.refdef.viewport[3] = h; - Vector4Set( RI.viewport, RI.refdef.viewport[0], RI.refdef.viewport[1], w, h ); - } - - Vector4Set( RI.scissor, RI.refdef.viewport[0] + x, RI.refdef.viewport[1] + y, w, h ); - VectorCopy( origin, RI.refdef.vieworg ); - for( i = 0; i < 3; i++ ) - RI.refdef.viewangles[i] = anglemod( angles[i] ); - - R_RenderView( &RI.refdef ); - - if( !( RI.params & RP_OLDVIEWLEAF )) - r_oldviewleaf = r_viewleaf = NULL; // force markleafs next frame - - r_portalSurfMbuffers = RI.surfmbuffers; - - Mem_Copy( &RI, &prevRI, sizeof( refinst_t ) ); - Mem_Copy( &prevRI, &oldRI, sizeof( refinst_t ) ); - - if( captureTexture ) - { - GL_Cull( 0 ); - GL_SetState( GLSTATE_NO_DEPTH_TEST ); - pglColor4f( 1, 1, 1, 1 ); - - // grab the results from framebuffer - GL_Bind( 0, *captureTexture ); - pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, RI.refdef.viewport[0], RI.refdef.viewport[1], ( *captureTexture )->width, ( *captureTexture )->height ); - RI.params |= ( refraction ? RP_PORTALCAPTURED2 : RP_PORTALCAPTURED ); - } - - if( doRefraction && !refraction && ( shader->flags & SHADER_PORTAL_CAPTURE2 ) ) - { - refraction = true; - captureTexture = &tr.portaltexture2; - captureTextureID = 2; - goto setup_and_render; - } - - R_AddPortalSurface( NULL ); - - return true; -} - -/* -=============== -R_DrawSkyPortal -=============== -*/ -void R_DrawSkyPortal( skyportal_t *skyportal, vec3_t mins, vec3_t maxs ) -{ - int x, y, w, h; - refinst_t oldRI; - - if( !R_ScissorForPortal( r_worldent, mins, maxs, &x, &y, &w, &h )) - return; - - RI.previousentity = NULL; - Mem_Copy( &oldRI, &prevRI, sizeof( refinst_t )); - Mem_Copy( &prevRI, &RI, sizeof( refinst_t )); - - RI.params = ( RI.params|RP_SKYPORTALVIEW ) & ~( RP_OLDVIEWLEAF|RP_PORTALCAPTURED|RP_PORTALCAPTURED2 ); - VectorCopy( skyportal->vieworg, RI.pvsOrigin ); - - RI.clipFlags = 15; - RI.shadowGroup = NULL; - RI.meshlist = &r_skyportallist; - RI.surfmbuffers = r_skyPortalSurfMbuffers; - Vector4Set( RI.scissor, RI.refdef.viewport[0] + x, RI.refdef.viewport[1] + y, w, h ); -// Vector4Set( RI.viewport, RI.refdef.viewport[0], glState.height - RI.refdef.viewport[3] - RI.refdef.viewport[1], RI.refdef.viewport[2], RI.refdef.viewport[3] ); - - if( skyportal->scale ) - { - vec3_t centre, diff; - - VectorAdd( r_worldmodel->mins, r_worldmodel->maxs, centre ); - VectorScale( centre, 0.5f, centre ); - VectorSubtract( centre, RI.viewOrigin, diff ); - VectorMA( skyportal->vieworg, -skyportal->scale, diff, RI.refdef.vieworg ); - } - else - { - VectorCopy( skyportal->vieworg, RI.refdef.vieworg ); - } - - VectorCopy( skyportal->viewangles, RI.refdef.viewangles ); - - RI.rdflags &= ~RDF_SKYPORTALINVIEW; - if( skyportal->fov ) - { - RI.refdef.fov_x = skyportal->fov; - RI.refdef.fov_y = CalcFov( RI.refdef.fov_x, RI.refdef.viewport[2], RI.refdef.viewport[3] ); - if( glState.wideScreen && r_adjust_fov->integer ) - AdjustFov( &RI.refdef.fov_x, &RI.refdef.fov_y, glState.width, glState.height, false ); - } - - R_RenderView( &RI.refdef ); - - r_skyPortalSurfMbuffers = RI.surfmbuffers; - r_oldviewleaf = r_viewleaf = NULL; // force markleafs next frame - - Mem_Copy( &RI, &prevRI, sizeof( refinst_t )); - Mem_Copy( &prevRI, &oldRI, sizeof( refinst_t )); -} - -/* -=============== -R_DrawCubemapView -=============== -*/ -void R_DrawCubemapView( const vec3_t origin, const vec3_t angles, int size ) -{ - ref_params_t *fd; - - fd = &RI.refdef; - *fd = r_lastRefdef; - fd->time = 0; - fd->viewport[0] = RI.refdef.viewport[1] = 0; - fd->viewport[2] = size; - fd->viewport[3] = size; - fd->fov_x = 90; - fd->fov_y = 90; - VectorCopy( origin, fd->vieworg ); - VectorCopy( angles, fd->viewangles ); - - r_numPolys = 0; - r_numDlights = 0; - - R_RenderScene( fd, RI.drawWorld ); - - r_oldviewleaf = r_viewleaf = NULL; // force markleafs next frame -} - -/* -=============== -R_BuildTangentVectors -=============== -*/ -void R_BuildTangentVectors( int numVertexes, vec4_t *vertexArray, vec4_t *normalsArray, vec2_t *stArray, int numTris, elem_t *elems, vec4_t *sVectorsArray ) -{ - int i, j; - float d, *v[3], *tc[3]; - vec_t *s, *t, *n; - vec3_t stvec[3], cross; - vec3_t stackTVectorsArray[128]; - vec3_t *tVectorsArray; - - if( numVertexes > sizeof( stackTVectorsArray )/sizeof( stackTVectorsArray[0] ) ) - tVectorsArray = Mem_Alloc( r_temppool, sizeof( vec3_t ) * numVertexes ); - else - tVectorsArray = stackTVectorsArray; - - // assuming arrays have already been allocated - // this also does some nice precaching - memset( sVectorsArray, 0, numVertexes * sizeof( *sVectorsArray ) ); - memset( tVectorsArray, 0, numVertexes * sizeof( *tVectorsArray ) ); - - for( i = 0; i < numTris; i++, elems += 3 ) - { - for( j = 0; j < 3; j++ ) - { - v[j] = ( float * )( vertexArray + elems[j] ); - tc[j] = ( float * )( stArray + elems[j] ); - } - - // calculate two mostly perpendicular edge directions - VectorSubtract( v[1], v[0], stvec[0] ); - VectorSubtract( v[2], v[0], stvec[1] ); - - // we have two edge directions, we can calculate the normal then - CrossProduct( stvec[1], stvec[0], cross ); - - for( j = 0; j < 3; j++ ) - { - stvec[0][j] = ( ( tc[1][1] - tc[0][1] ) * ( v[2][j] - v[0][j] ) - ( tc[2][1] - tc[0][1] ) * ( v[1][j] - v[0][j] ) ); - stvec[1][j] = ( ( tc[1][0] - tc[0][0] ) * ( v[2][j] - v[0][j] ) - ( tc[2][0] - tc[0][0] ) * ( v[1][j] - v[0][j] ) ); - } - - // inverse tangent vectors if their cross product goes in the opposite - // direction to triangle normal - CrossProduct( stvec[1], stvec[0], stvec[2] ); - if( DotProduct( stvec[2], cross ) < 0 ) - { - VectorNegate( stvec[0], stvec[0] ); - VectorNegate( stvec[1], stvec[1] ); - } - - for( j = 0; j < 3; j++ ) - { - VectorAdd( sVectorsArray[elems[j]], stvec[0], sVectorsArray[elems[j]] ); - VectorAdd( tVectorsArray[elems[j]], stvec[1], tVectorsArray[elems[j]] ); - } - } - - // normalize - for( i = 0, s = *sVectorsArray, t = *tVectorsArray, n = *normalsArray; i < numVertexes; i++, s += 4, t += 3, n += 4 ) - { - // keep s\t vectors perpendicular - d = -DotProduct( s, n ); - VectorMA( s, d, n, s ); - VectorNormalize( s ); - - d = -DotProduct( t, n ); - VectorMA( t, d, n, t ); - - // store polarity of t-vector in the 4-th coordinate of s-vector - CrossProduct( n, s, cross ); - if( DotProduct( cross, t ) < 0 ) - s[3] = -1; - else - s[3] = 1; - } - - if( tVectorsArray != stackTVectorsArray ) - Mem_Free( tVectorsArray ); -} diff --git a/vid_gl/r_mesh.h b/vid_gl/r_mesh.h deleted file mode 100644 index fea62dcb..00000000 --- a/vid_gl/r_mesh.h +++ /dev/null @@ -1,114 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2009 -// r_mesh.h - generic mesh container -//======================================================================= - -#ifndef R_MESH_H -#define R_MESH_H - -enum -{ - MF_NONE = 0, - MF_NORMALS = BIT( 0 ), - MF_STCOORDS = BIT( 1 ), - MF_LMCOORDS = BIT( 2 ), - MF_COLORS = BIT( 3 ), - MF_ENABLENORMALS = BIT( 4 ), - MF_DEFORMVS = BIT( 5 ), - MF_SVECTORS = BIT( 6 ), - MF_TVECTORS = BIT( 7 ), - - // global features - MF_NOCULL = BIT( 16 ), - MF_TRIFAN = BIT( 17 ), - MF_NONBATCHED = BIT( 18 ), - MF_KEEPLOCK = BIT( 19 ) -}; - -enum -{ - MB_MODEL, - MB_POLY, - MB_DECAL, - MB_CORONA, - MB_MAXTYPES = 4 -}; - -typedef struct mesh_s -{ - int numVerts; - int numElems; - - vec4_t *vertexArray; - vec4_t *normalsArray; - vec4_t *sVectorsArray; - vec4_t *tVectorsArray; - vec2_t *stCoordArray; - vec2_t *lmCoordArray; - rgba_t *colorsArray; - elem_t *elems; - - struct mesh_s *next; // temporary chain of subdivided surfaces -} mesh_t; - -#define MB_FOG2NUM( fog ) ((fog) ? ((((int)((fog) - r_worldbrushmodel->fogs))+1) << 2) : 0 ) -#define MB_NUM2FOG( num, fog ) ((fog) = r_worldbrushmodel->fogs+(((num)>>2) & 0xFF), (fog) = ( (fog) == r_worldbrushmodel->fogs ? NULL : (fog)-1 )) - -#define MB_ENTITY2NUM( ent ) ((int)((ent)-r_entities)<<20 ) -#define MB_NUM2ENTITY( num, ent ) (ent = r_entities+(((num)>>20)&MAX_ENTITIES-1)) - -#define MB_SHADER2NUM( s ) ((s)->sort << 26 ) | ((s) - r_shaders ) -#define MB_NUM2SHADER( num, s ) ((s) = r_shaders + ((num) & 0xFFF)) -#define MB_NUM2SHADERSORT( num ) (((num) >> 26) & 0x1F ) - -#define MIN_RENDER_MESHES 2048 - -typedef struct -{ - int shaderkey; - uint sortkey; - int infokey; // surface number or mesh number - union - { - int lastPoly; - uint dlightbits; - uint modhandle; - uint placeTime; // decal createtime - }; - uint shadowbits; -} meshbuffer_t; - -typedef struct -{ - int num_opaque_meshes, max_opaque_meshes; - meshbuffer_t *meshbuffer_opaque; - - int num_translucent_meshes, max_translucent_meshes; - meshbuffer_t *meshbuffer_translucent; - - int num_portal_opaque_meshes; - int num_portal_translucent_meshes; -} meshlist_t; - -enum -{ - SKYBOX_RIGHT, - SKYBOX_LEFT, - SKYBOX_FRONT, - SKYBOX_BACK, - SKYBOX_TOP, - SKYBOX_BOTTOM // not used for skydome, but is used for skybox -}; - -typedef struct -{ - float skyHeight; - mesh_t *meshes; - vec2_t *sphereStCoords[6]; - vec2_t *linearStCoords[6]; - - struct ref_shader_s *farboxShaders[6]; - struct ref_shader_s *nearboxShaders[6]; -} skydome_t; - -#endif /*__R_MESH_H__*/ diff --git a/vid_gl/r_model.c b/vid_gl/r_model.c deleted file mode 100644 index 4ae674e2..00000000 --- a/vid_gl/r_model.c +++ /dev/null @@ -1,2778 +0,0 @@ -/* -Copyright (C) 1997-2001 Id Software, Inc. -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// r_model.c -- model loading and caching - -#include "stdio.h" // sscanf -#include "r_local.h" -#include "wadfile.h" -#include "mathlib.h" -#include "matrix_lib.h" -#include "bspfile.h" -#include "cl_entity.h" - -#define Mod_CopyString( m, str ) com.stralloc( (m)->mempool, str, __FILE__, __LINE__ ) -#define MAX_SIDE_VERTS 256 // per one polygon - -typedef struct epair_s -{ - struct epair_s *next; - char *key; - char *value; -} epair_t; - -typedef struct -{ - vec3_t origin; - epair_t *epairs; -} mapent_t; - -typedef enum -{ - emit_point, - emit_spotlight, - emit_surface, - emit_skylight -} emittype_t; - -typedef struct -{ - int numpoints; - int maxpoints; - vec3_t points[8]; // variable sized -} winding_t; - -typedef struct -{ - vec3_t dir; - vec3_t color; - int style; -} contribution_t; - -typedef struct light_s -{ - struct light_s *next; - emittype_t type; - int style; - vec3_t origin; - vec3_t color; - vec3_t normal; // for surfaces and spotlights - float photons; - float dist; - float stopdot; // for spotlights - float stopdot2; // for spotlights - winding_t *w; -} light_t; - -typedef struct -{ - char name[32]; - ref_shader_t *shader; - - mip_t *base; // general texture - - qboolean animated; - mip_t *anim_frames[2][10];// (indexed as [alternate][frame]) - int anim_total[2]; // total frames in sequence and alternate sequence - - int width; - int height; -} cachedimage_t; - -// intermediate cached data -static struct -{ - int version; // brushmodel version - string modelname; // mapname without path, extension etc - vec3_t *vertexes; // intermediate data comes here - int numvertexes; - dedge_t *edges; - int numedges; - dsurfedge_t *surfedges; - int numsurfedges; - cachedimage_t *textures; - int numtextures; - light_t *lights; // stored pointlights - int numPointLights; - script_t *entscript; - mapent_t *entities; // sizeof( mapent_t ) * GI->max_edicts - int numents; -} cached; - -static ref_model_t *loadmodel; -static byte *cached_mempool; - -void Mod_SpriteLoadModel( ref_model_t *mod, const void *buffer ); -void Mod_StudioLoadModel( ref_model_t *mod, const void *buffer ); -void Mod_BrushLoadModel( ref_model_t *mod, const void *buffer ); - -ref_model_t *Mod_LoadModel( ref_model_t *mod, qboolean crash ); - -static ref_model_t *r_inlinemodels = NULL; -static byte mod_novis[MAX_MAP_LEAFS/8]; -static ref_model_t r_models[MAX_MODELS]; -static int r_nummodels; - -/* -=================== -Mod_DecompressVis -=================== -*/ -static byte *Mod_DecompressVis( const byte *in, mbrushmodel_t *model ) -{ - static byte decompressed[MAX_MAP_LEAFS/8]; - int c, row; - byte *out; - - if( !model ) - { - Host_Error( "Mod_DecompressVis: no worldmodel\n" ); - return NULL; - } - - row = (model->numleafs + 7)>>3; - out = decompressed; - - if( !in ) - { - // no vis info, so make all visible - while( row ) - { - *out++ = 0xff; - row--; - } - return decompressed; - } - - do - { - if( *in ) - { - *out++ = *in++; - continue; - } - - c = in[1]; - in += 2; - - while( c ) - { - *out++ = 0; - c--; - } - } while( out - decompressed < row ); - - return decompressed; -} - -/* -=============== -Mod_PointInLeaf -=============== -*/ -mleaf_t *Mod_PointInLeaf( const vec3_t p, ref_model_t *model ) -{ - mnode_t *node; - mplane_t *plane; - mbrushmodel_t *bmodel; - - if( !model || !( bmodel = ( mbrushmodel_t *)model->extradata ) || !bmodel->nodes ) - { - Host_Error( "Mod_PointInLeaf: bad model\n" ); - return NULL; - } - - node = bmodel->nodes; - do - { - plane = node->plane; - node = node->children[PlaneDiff( p, plane ) < 0]; - } while( node->plane != NULL ); - - return (mleaf_t *)node; -} - -/* -============== -Mod_LeafPVS -============== -*/ -byte *Mod_LeafPVS( mleaf_t *leaf, ref_model_t *model ) -{ - mbrushmodel_t *bmodel = (mbrushmodel_t *)model->extradata; - - if( !model || !bmodel || !leaf || leaf == bmodel->leafs || !bmodel->visdata ) - return mod_novis; - return Mod_DecompressVis( leaf->compressed_vis, bmodel ); -} - - -//=============================================================================== - -/* -================ -Mod_Modellist_f -================ -*/ -void Mod_Modellist_f( void ) -{ - int i, nummodels; - ref_model_t *mod; - - Msg( "\n" ); - Msg( "-----------------------------------\n" ); - - for( i = nummodels = 0, mod = r_models; i < r_nummodels; i++, mod++ ) - { - if( !mod->name ) continue; // free slot - Msg( "%s%s\n", mod->name, (mod->type == mod_bad) ? " (DEFAULTED)" : "" ); - nummodels++; - } - - Msg( "-----------------------------------\n" ); - Msg( "%i total models\n", nummodels ); - Msg( "\n" ); -} - -/* -================ -Mod_FreeModel -================ -*/ -void Mod_FreeModel( ref_model_t *mod ) -{ - if( !mod || !mod->mempool ) return; - - Mem_FreePool( &mod->mempool ); - Mem_Set( mod, 0, sizeof( *mod )); -} - -/* -================ -Mod_FreeAll -================ -*/ -void Mod_FreeAll( void ) -{ - int i; - - if( r_inlinemodels ) - { - Mem_Free( r_inlinemodels ); - r_inlinemodels = NULL; - } - - for( i = 0; i < r_nummodels; i++ ) - Mod_FreeModel( &r_models[i] ); -} - -/* -=============== -R_InitModels -=============== -*/ -void R_InitModels( void ) -{ - Mem_Set( mod_novis, 0xff, sizeof( mod_novis )); - cached_mempool = Mem_AllocPool( "Mod cache" ); - r_nummodels = 0; - - R_StudioInit(); - R_SpriteInit(); -} - -/* -================ -R_ShutdownModels -================ -*/ -void R_ShutdownModels( void ) -{ - if( !cached_mempool ) return; - - R_StudioShutdown(); - Mod_FreeAll(); - - r_worldmodel = NULL; - r_worldbrushmodel = NULL; - - r_nummodels = 0; - Mem_Set( r_models, 0, sizeof( r_models )); - Mem_FreePool( &cached_mempool ); -} - -/* -================== -Mod_FindSlot -================== -*/ -static ref_model_t *Mod_FindSlot( const char *name ) -{ - ref_model_t *mod; - int i; - - // find a free model slot spot - for( i = 0, mod = r_models; i < r_nummodels; i++, mod++ ) - if( !mod->name ) break; // free spot - - if( i == r_nummodels ) - { - if( r_nummodels == MAX_MODELS ) - Host_Error( "Mod_ForName: MAX_MODELS limit exceeded\n" ); - r_nummodels++; - } - return mod; -} - -/* -================== -Mod_Handle -================== -*/ -uint Mod_Handle( ref_model_t *mod ) -{ - return mod - r_models; -} - -/* -================== -Mod_ForHandle -================== -*/ -ref_model_t *Mod_ForHandle( uint handle ) -{ - return r_models + handle; -} - -/* -================= -Mod_UpdateShaders - -update shader and associated textures -================= -*/ -static void Mod_UpdateShaders( ref_model_t *mod ) -{ - ref_shader_t *shader; - int i; - - if( !mod || !mod->name ) - return; - - if( mod->type == mod_world || mod->type == mod_brush ) - { - mbrushmodel_t *bmodel; - - // clearing all linked decals here - bmodel = (mbrushmodel_t *)mod->extradata; - for( i = 0; i < bmodel->numsurfaces; i++ ) - bmodel->surfaces[i].pdecals = NULL; - } - - for( i = 0; i < mod->numshaders; i++ ) - { - shader = mod->shaders[i]; - if( !shader || !shader->name ) continue; - Shader_TouchImages( shader, false ); - } - - if( mod == r_worldmodel && tr.currentSkyShader ) - Shader_TouchImages( tr.currentSkyShader, false ); -} - -/* -================== -Mod_ForName - -Loads in a model for the given name -================== -*/ -ref_model_t *Mod_ForName( const char *name, qboolean crash ) -{ - ref_model_t *mod; - uint *buf; - int i; - - if( !name[0] ) Host_Error( "Mod_ForName: NULL name\n" ); - - // inline models are grabbed only from worldmodel - if( name[0] == '*' ) - { - i = com.atoi( name + 1 ); - if( i < 1 || !r_worldmodel || i >= r_worldbrushmodel->numsubmodels ) - { - MsgDev( D_ERROR, "bad inline model number %i\n", i ); - return NULL; - } - return &r_inlinemodels[i]; - } - - // search the currently loaded models - for( i = 0, mod = r_models; i < r_nummodels; i++, mod++ ) - { - if( !mod->name ) continue; - if( !com.strcmp( mod->name, name )) - { - // prolonge registration - mod->touchFrame = tr.registration_sequence; - return mod; - } - } - - mod = Mod_FindSlot( name ); - - ASSERT( mod ); - - // load the file - buf = (uint *)FS_LoadFile( name, NULL ); - if( !buf ) - { - if( crash ) Host_Error( "Mod_ForName: %s not found\n", name ); - return NULL; // return the NULL model - } - - loadmodel = mod; - Mem_EmptyPool( cached_mempool ); - Mem_Set( &cached, 0, sizeof( cached )); - - mod->type = mod_bad; - mod->mempool = Mem_AllocPool( va( "cl: ^1%s^7", name )); - mod->name = Mod_CopyString( mod, name ); - FS_FileBase( mod->name, cached.modelname ); - - // call the apropriate loader - switch( *(uint *)buf ) - { - case IDSTUDIOHEADER: - Mod_StudioLoadModel( mod, buf ); - break; - case IDSPRITEHEADER: - Mod_SpriteLoadModel( mod, buf ); - break; - default: - Mod_BrushLoadModel( mod, buf ); - break; - } - - Mem_Free( buf ); - - if( mod->type == mod_bad ) - { - // check for loading problems - if( crash ) Host_Error( "Mod_ForName: %s unknown format\n", name ); - else MsgDev( D_ERROR, "Mod_ForName: %s unknown format\n", name ); - Mod_FreeModel( mod ); - return NULL; - } - return mod; -} - -/* -=============================================================================== - -BRUSHMODEL LOADING - -=============================================================================== -*/ - -static byte *mod_base; -static mbrushmodel_t *loadbmodel; - -/* -================= -Mod_CheckDeluxemaps -================= -*/ -static void Mod_CheckDeluxemaps( const dlump_t *l, byte *lmData ) -{ - if( !r_lighting_deluxemapping->integer ) - return; - - // deluxemapping temporare disabled - // FIXME: re-enable it again -// if( GL_Support( R_SHADER_GLSL100_EXT )) - mapConfig.deluxeMappingEnabled = false; -} - -/* -================= -Mod_SetNodeParent -================= -*/ -static void Mod_SetNodeParent( mnode_t *node, mnode_t *parent ) -{ - node->parent = parent; - if( node->contents < 0 ) return; // it's a leaf - - Mod_SetNodeParent( node->children[0], node ); - Mod_SetNodeParent( node->children[1], node ); -} - -/* -================= -Mod_CalcSurfaceBounds - -fills in surf->mins and surf->maxs -================= -*/ -static void Mod_CalcSurfaceBounds( msurface_t *surf ) -{ - int i, e; - float *v; - - ClearBounds( surf->mins, surf->maxs ); - - for( i = 0; i < surf->numedges; i++ ) - { - e = cached.surfedges[surf->firstedge + i]; - if( e >= 0 ) v = (float *)&cached.vertexes[cached.edges[e].v[0]]; - else v = (float *)&cached.vertexes[cached.edges[-e].v[1]]; - AddPointToBounds( v, surf->mins, surf->maxs ); - } -} - -/* -================= -Mod_CalcSurfaceExtents - -Fills in surf->textureMins and surf->extents -================= -*/ -static void Mod_CalcSurfaceExtents( msurface_t *surf ) -{ - float mins[2], maxs[2], val; - int bmins[2], bmaxs[2]; - int i, j, e; - float *v; - - if( surf->flags & SURF_DRAWTURB ) - { - surf->extents[0] = surf->extents[1] = 16384; - surf->textureMins[0] = surf->textureMins[1] = -8192; - return; - } - - mins[0] = mins[1] = 999999; - maxs[0] = maxs[1] = -999999; - - for( i = 0; i < surf->numedges; i++ ) - { - e = cached.surfedges[surf->firstedge + i]; - if( e >= 0 ) v = (float *)&cached.vertexes[cached.edges[e].v[0]]; - else v = (float *)&cached.vertexes[cached.edges[-e].v[1]]; - - for( j = 0; j < 2; j++ ) - { - val = DotProduct( v, surf->texinfo->vecs[j] ) + surf->texinfo->vecs[j][3]; - if( val < mins[j] ) mins[j] = val; - if( val > maxs[j] ) maxs[j] = val; - } - } - - for( i = 0; i < 2; i++ ) - { - bmins[i] = floor( mins[i] / LM_SAMPLE_SIZE ); - bmaxs[i] = ceil( maxs[i] / LM_SAMPLE_SIZE ); - - surf->textureMins[i] = bmins[i] * LM_SAMPLE_SIZE; - surf->extents[i] = (bmaxs[i] - bmins[i]) * LM_SAMPLE_SIZE; - } -} - -/* -================= -Mod_BuildPolygon -================= -*/ -static void Mod_BuildPolygon( msurface_t *surf, int numVerts, const float *verts ) -{ - float s, t; - uint index, bufSize; - mtexinfo_t *texinfo = surf->texinfo; - qboolean createSTverts = false; - int i, numElems; - byte *buffer; - vec3_t normal; - mesh_t *mesh; - - // allocate mesh - numElems = (numVerts - 2) * 3; - - if( mapConfig.deluxeMappingEnabled || ( surf->shader->flags & SHADER_PORTAL_CAPTURE2 )) - createSTverts = true; - - // mesh + ( align vertex, align normal, (st + lmst) + elem * numElems) * numVerts; - bufSize = sizeof( mesh_t ) + numVerts * ( sizeof( vec4_t ) + sizeof( vec4_t ) + sizeof( vec4_t )) + numElems * sizeof( elem_t ); - if( createSTverts ) bufSize += numVerts * sizeof( vec4_t ); - - buffer = Mod_Malloc( loadmodel, bufSize ); - - mesh = (mesh_t *)buffer; - buffer += sizeof( mesh_t ); - mesh->numVerts = numVerts; - mesh->numElems = numElems; - - // setup pointers - mesh->vertexArray = (vec4_t *)buffer; - buffer += numVerts * sizeof( vec4_t ); - mesh->normalsArray = (vec4_t *)buffer; - buffer += numVerts * sizeof( vec4_t ); - mesh->stCoordArray = (vec2_t *)buffer; - buffer += numVerts * sizeof( vec2_t ); - mesh->lmCoordArray = (vec2_t *)buffer; - buffer += numVerts * sizeof( vec2_t ); - mesh->elems = (elem_t *)buffer; - buffer += numElems * sizeof( elem_t ); - - mesh->next = surf->mesh; - surf->mesh = mesh; - - // create indices - for( i = 0, index = 2; i < mesh->numElems; i += 3, index++ ) - { - mesh->elems[i+0] = 0; - mesh->elems[i+1] = index - 1; - mesh->elems[i+2] = index; - } - - // setup normal - if( surf->flags & SURF_PLANEBACK ) - VectorNegate( surf->plane->normal, normal ); - else VectorCopy( surf->plane->normal, normal ); - - VectorNormalize( normal ); - - // create vertices - mesh->numVerts = numVerts; - - for( i = 0; i < numVerts; i++, verts += 3 ) - { - // vertex - VectorCopy( verts, mesh->vertexArray[i] ); - VectorCopy( normal, mesh->normalsArray[i] ); - - mesh->vertexArray[i][3] = 1.0f; - mesh->normalsArray[i][3] = 1.0f; - - // texture coordinates - s = DotProduct( verts, texinfo->vecs[0] ) + texinfo->vecs[0][3]; - if( texinfo->width != -1 ) s /= texinfo->width; - else s /= surf->shader->stages[0].textures[0]->width; - - t = DotProduct( verts, texinfo->vecs[1] ) + texinfo->vecs[1][3]; - if( texinfo->height != -1 ) t /= texinfo->height; - else t /= surf->shader->stages[0].textures[0]->height; - - mesh->stCoordArray[i][0] = s; - mesh->stCoordArray[i][1] = t; - - // lightmap texture coordinates - s = DotProduct( verts, texinfo->vecs[0] ) + texinfo->vecs[0][3] - surf->textureMins[0]; - s += surf->lmS * LM_SAMPLE_SIZE; - s += LM_SAMPLE_SIZE >> 1; - s /= LIGHTMAP_TEXTURE_WIDTH * LM_SAMPLE_SIZE; - - t = DotProduct( verts, texinfo->vecs[1] ) + texinfo->vecs[1][3] - surf->textureMins[1]; - t += surf->lmT * LM_SAMPLE_SIZE; - t += LM_SAMPLE_SIZE >> 1; - t /= LIGHTMAP_TEXTURE_HEIGHT * LM_SAMPLE_SIZE; - - mesh->lmCoordArray[i][0] = s; - mesh->lmCoordArray[i][1] = t; - } - - if( createSTverts ) - { - mesh->sVectorsArray = (vec4_t *)buffer; - buffer += numVerts * sizeof( vec4_t ); - R_BuildTangentVectors( mesh->numVerts, mesh->vertexArray, mesh->normalsArray, mesh->stCoordArray, mesh->numElems / 3, mesh->elems, mesh->sVectorsArray ); - } -} - -/* -================= -Mod_SubdividePolygon -================= -*/ -static void Mod_SubdividePolygon( msurface_t *surf, int numVerts, float *verts ) -{ - int i, j, f, b, subdivideSize; - vec3_t vTotal, nTotal, mins, maxs; - mtexinfo_t *texinfo = surf->texinfo; - vec3_t front[MAX_SIDE_VERTS], back[MAX_SIDE_VERTS]; - float *v, m, oneDivVerts, dist, dists[MAX_SIDE_VERTS]; - qboolean createSTverts = false; - vec2_t totalST, totalLM; - uint bufSize; - byte *buffer; - float s, t; - mesh_t *mesh; - - subdivideSize = surf->shader->tessSize; - - ClearBounds( mins, maxs ); - for( i = 0, v = verts; i < numVerts; i++, v += 3 ) - AddPointToBounds( v, mins, maxs ); - - for( i = 0; i < 3; i++ ) - { - m = subdivideSize * floor((( mins[i] + maxs[i] ) * 0.5f ) / subdivideSize + 0.5f ); - - if( maxs[i] - m < 8 ) continue; - if( m - mins[i] < 8 ) continue; - - // cut it - v = verts + i; - for( j = 0; j < numVerts; j++, v += 3 ) - dists[j] = *v - m; - - // wrap cases - dists[j] = dists[0]; - v -= i; - VectorCopy( verts, v ); - - for( f = j = b = 0, v = verts; j < numVerts; j++, v += 3 ) - { - if( dists[j] >= 0 ) - { - VectorCopy( v, front[f] ); - f++; - } - if( dists[j] <= 0 ) - { - VectorCopy( v, back[b] ); - b++; - } - - if( dists[j] == 0 || dists[j+1] == 0 ) - continue; - - if((dists[j] > 0) != (dists[j+1] > 0)) - { - // clip point - dist = dists[j] / (dists[j] - dists[j+1]); - front[f][0] = back[b][0] = v[0] + (v[3] - v[0]) * dist; - front[f][1] = back[b][1] = v[1] + (v[4] - v[1]) * dist; - front[f][2] = back[b][2] = v[2] + (v[5] - v[2]) * dist; - f++; - b++; - } - } - - Mod_SubdividePolygon( surf, f, front[0] ); - Mod_SubdividePolygon( surf, b, back[0] ); - return; - } - - if( mapConfig.deluxeMappingEnabled || ( surf->shader->flags & SHADER_PORTAL_CAPTURE2 )) - createSTverts = true; - - // allocate mesh - bufSize = sizeof( mesh_t ) + ((numVerts + 2) * sizeof( rgba_t )) + ((numVerts + 2) * sizeof( vec4_t ) * 2) + ((numVerts + 2) * sizeof( vec2_t ) * 2); - if( createSTverts ) bufSize += (numVerts + 2) * sizeof( vec4_t ); - - buffer = Mod_Malloc( loadmodel, bufSize ); - - mesh = (mesh_t *)buffer; - buffer += sizeof( mesh_t ); - - // create vertices - mesh->numVerts = numVerts + 2; - mesh->numElems = numVerts * 3; - - // setup pointers - mesh->colorsArray = (rgba_t *)buffer; - buffer += mesh->numVerts * sizeof( rgba_t ); - mesh->vertexArray = (vec4_t *)buffer; - buffer += mesh->numVerts * sizeof( vec4_t ); - mesh->normalsArray = (vec4_t *)buffer; - buffer += mesh->numVerts * sizeof( vec4_t ); - mesh->stCoordArray = (vec2_t *)buffer; - buffer += mesh->numVerts * sizeof( vec2_t ); - mesh->lmCoordArray = (vec2_t *)buffer; - buffer += mesh->numVerts * sizeof( vec2_t ); - - VectorClear( vTotal ); - VectorClear( nTotal ); - totalST[0] = totalST[1] = 0; - totalLM[0] = totalLM[1] = 0; - - for( i = 0; i < numVerts; i++, verts += 3 ) - { - // colors - Vector4Set( mesh->colorsArray[i+1], 255, 255, 255, 255 ); - - // vertex - VectorCopy( verts, mesh->vertexArray[i+1] ); - - // setup normal - if( surf->flags & SURF_PLANEBACK ) - VectorNegate( surf->plane->normal, mesh->normalsArray[i+1] ); - else VectorCopy( surf->plane->normal, mesh->normalsArray[i+1] ); - - mesh->vertexArray[i+1][3] = 1.0f; - mesh->normalsArray[i+1][3] = 1.0f; - - VectorAdd( vTotal, verts, vTotal ); - VectorAdd( nTotal, surf->plane->normal, nTotal ); - - // texture coordinates - s = DotProduct( verts, texinfo->vecs[0] ) + texinfo->vecs[0][3]; - if( texinfo->width != -1 ) s /= texinfo->width; - else s /= surf->shader->stages[0].textures[0]->width; - - t = DotProduct( verts, texinfo->vecs[1] ) + texinfo->vecs[1][3]; - if( texinfo->height != -1 ) t /= texinfo->height; - else t /= surf->shader->stages[0].textures[0]->height; - - mesh->stCoordArray[i+1][0] = s; - mesh->stCoordArray[i+1][1] = t; - - totalST[0] += s; - totalST[1] += t; - - // lightmap texture coordinates - s = DotProduct( verts, texinfo->vecs[0] ) + texinfo->vecs[0][3] - surf->textureMins[0]; - s += surf->lmS * LM_SAMPLE_SIZE; - s += LM_SAMPLE_SIZE >> 1; - s /= LIGHTMAP_TEXTURE_WIDTH * LM_SAMPLE_SIZE; - - t = DotProduct( verts, texinfo->vecs[1] ) + texinfo->vecs[1][3] - surf->textureMins[1]; - t += surf->lmT * LM_SAMPLE_SIZE; - t += LM_SAMPLE_SIZE >> 1; - t /= LIGHTMAP_TEXTURE_HEIGHT * LM_SAMPLE_SIZE; - - mesh->lmCoordArray[i+1][0] = s; - mesh->lmCoordArray[i+1][1] = t; - - totalLM[0] += s; - totalLM[1] += t; - } - - // vertex - oneDivVerts = ( 1.0f / (float)numVerts ); - - Vector4Set( mesh->colorsArray[0], 255, 255, 255, 255 ); - VectorScale( vTotal, oneDivVerts, mesh->vertexArray[0] ); - VectorScale( nTotal, oneDivVerts, mesh->normalsArray[0] ); - VectorNormalize( mesh->normalsArray[0] ); - - // texture coordinates - mesh->stCoordArray[0][0] = totalST[0] * oneDivVerts; - mesh->stCoordArray[0][1] = totalST[1] * oneDivVerts; - - // lightmap texture coordinates - mesh->lmCoordArray[0][0] = totalLM[0] * oneDivVerts; - mesh->lmCoordArray[0][1] = totalLM[1] * oneDivVerts; - - // copy first vertex to last - Vector4Set( mesh->colorsArray[i+1], 255, 255, 255, 255 ); - VectorCopy( mesh->vertexArray[1], mesh->vertexArray[i+1] ); - VectorCopy( mesh->normalsArray[1], mesh->normalsArray[i+1] ); - Vector2Copy( mesh->stCoordArray[1], mesh->stCoordArray[i+1] ); - Vector2Copy( mesh->lmCoordArray[1], mesh->lmCoordArray[i+1] ); - - if( createSTverts ) - { - mesh->sVectorsArray = (vec4_t *)buffer; - buffer += (numVerts + 2) * sizeof( vec4_t ); - R_BuildTangentVectors( mesh->numVerts, mesh->vertexArray, mesh->normalsArray, mesh->stCoordArray, mesh->numElems / 3, mesh->elems, mesh->sVectorsArray ); - } - - mesh->next = surf->mesh; - surf->mesh = mesh; -} - -/* -================ -Mod_ConvertSurface -================ -*/ -static void Mod_ConvertSurface( msurface_t *surf ) -{ - byte *buffer, *mem; - mesh_t *poly, *next; - uint totalIndexes; - uint totalVerts; - byte *outColors; - float *outCoords; - elem_t *outIndexes; - float *outLMCoords; - mesh_t *outMesh; - float *outNormals; - float *outVerts; - int i; - - // find the total vertex count and index count - totalIndexes = 0; - totalVerts = 0; - - for( poly = surf->mesh; poly; poly = poly->next ) - { - totalIndexes += ( poly->numVerts - 2 ) * 3; - totalVerts += poly->numVerts; - } - - // allocate space - if( surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB)) - { - - mem = buffer = Mod_Malloc( loadmodel, sizeof( mesh_t ) - + (totalVerts * sizeof( vec4_t ) * 2 ) - + (totalIndexes * sizeof( elem_t )) - + (totalVerts * sizeof( vec2_t )) - + (totalVerts * sizeof( rgba_t ))); - } - else - { - mem = buffer = Mod_Malloc( loadmodel, sizeof( mesh_t ) - + (totalVerts * sizeof( vec4_t ) * 2 ) - + (totalIndexes * sizeof( elem_t )) - + (totalVerts * sizeof( vec2_t ) * 2 ) - + (totalVerts * sizeof( rgba_t ))); - } - - outMesh = (mesh_t *)buffer; - outMesh->numElems = totalIndexes; - outMesh->numVerts = totalVerts; - - buffer += sizeof( mesh_t ); - outVerts = (float *)buffer; - - buffer += sizeof( vec4_t ) * totalVerts; - outNormals = (float *)buffer; - - buffer += sizeof( vec4_t ) * totalVerts; - outIndexes = (elem_t *)buffer; - - buffer += sizeof( elem_t ) * totalIndexes; - outCoords = (float *)buffer; - - if( surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB)) - { - outLMCoords = NULL; - } - else - { - buffer += sizeof( vec2_t ) * totalVerts; - outLMCoords = (float *)buffer; - } - - buffer += sizeof( vec2_t ) * totalVerts; - outColors = (byte *)buffer; - - outMesh->colorsArray = (rgba_t *)outColors; - outMesh->stCoordArray = (vec2_t *)outCoords; - outMesh->elems = (elem_t *)outIndexes; - outMesh->lmCoordArray = (vec2_t *)outLMCoords; - outMesh->normalsArray = (vec4_t *)outNormals; - outMesh->vertexArray = (vec4_t *)outVerts; - outMesh->sVectorsArray = NULL; - outMesh->tVectorsArray = NULL; - - // check mesh validity - if( R_InvalidMesh( outMesh )) - { - MsgDev( D_ERROR, "Mod_ConvertSurface: surface mesh is invalid!\n" ); - Mem_Free( mem ); - return; - } - - // store vertex data - totalIndexes = 0; - totalVerts = 0; - - for( poly = surf->mesh; poly; poly = poly->next ) - { - // indexes - outIndexes = outMesh->elems + totalIndexes; - totalIndexes += (poly->numVerts - 2) * 3; - - for( i = 2; i < poly->numVerts; i++ ) - { - outIndexes[0] = totalVerts; - outIndexes[1] = totalVerts + i - 1; - outIndexes[2] = totalVerts + i; - outIndexes += 3; - } - - for( i = 0; i < poly->numVerts; i++ ) - { - // vertices - outVerts[0] = poly->vertexArray[i][0]; - outVerts[1] = poly->vertexArray[i][1]; - outVerts[2] = poly->vertexArray[i][2]; - outVerts[3] = 1.0f; - - // Normals - outNormals[0] = poly->normalsArray[i][0]; - outNormals[1] = poly->normalsArray[i][1]; - outNormals[2] = poly->normalsArray[i][2]; - outNormals[3] = 1.0f; - - // colors - outColors[0] = 255; - outColors[1] = 255; - outColors[2] = 255; - outColors[3] = 255; - - // coords - outCoords[0] = poly->stCoordArray[i][0]; - outCoords[1] = poly->stCoordArray[i][1]; - - outVerts += 4; - outNormals += 4; - outColors += 4; - outCoords += 2; - } - - totalVerts += poly->numVerts; - } - - // lightmap coords - if(!( surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB ))) - { - for( poly = surf->mesh; poly; poly = poly->next ) - { - for( i = 0; i < poly->numVerts; i++ ) - { - outLMCoords[0] = poly->lmCoordArray[i][0]; - outLMCoords[1] = poly->lmCoordArray[i][1]; - - outLMCoords += 2; - } - } - } - - // release the old q2_polys crap - for( poly = surf->mesh; poly; poly = next ) - { - next = poly->next; - Mem_Free( poly ); - } - - surf->mesh = outMesh; -} - -/* -================= -Mod_BuildSurfacePolygons -================= -*/ -static void Mod_BuildSurfacePolygons( msurface_t *surf ) -{ - float *v; - int i, e; - vec3_t verts[MAX_SIDE_VERTS]; - vec3_t ebbox = { 0, 0, 0 }; - - // convert edges back to a normal polygon - for( i = 0; i < surf->numedges; i++ ) - { - if( i == 256 ) break; // too big polygon ? - - e = cached.surfedges[surf->firstedge + i]; - if( e >= 0 ) v = cached.vertexes[cached.edges[e].v[0]]; - else v = cached.vertexes[cached.edges[-e].v[1]]; - VectorCopy( v, verts[i] ); - } - - R_DeformvBBoxForShader( surf->shader, ebbox ); - - if( surf->shader->tessSize != 0.0f ) - { - Mod_SubdividePolygon( surf, surf->numedges, verts[0] ); - Mod_ConvertSurface( surf ); - } - else Mod_BuildPolygon( surf, surf->numedges, verts[0] ); - - if( !surf->mesh ) return; - - ClearBounds( surf->mins, surf->maxs ); - for( i = 0, v = surf->mesh->vertexArray[0]; i < surf->mesh->numVerts; i++, v += 4 ) - AddPointToBounds( v, surf->mins, surf->maxs ); - VectorSubtract( surf->mins, ebbox, surf->mins ); - VectorAdd( surf->maxs, ebbox, surf->maxs ); -} - -/* -================= -Mod_LoadTexture -================= -*/ -texture_t *Mod_LoadTexture( mip_t *mt ) -{ - texture_t *tx; - - ASSERT( mt ); - - if( mt->offsets[0] > 0 ) - { - // NOTE: imagelib detect miptex version by size - // 770 additional bytes is indicated custom palette - int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6); - if( cached.version == HLBSP_VERSION ) size += sizeof( short ) + 768; - - // loading internal texture if present - tx = R_FindTexture( va( "\"#%s.mip\"", mt->name ), (byte *)mt, size, 0 ); - } - else - { - // okay, loading it from wad - tx = R_FindTexture( va( "\"%s.mip\"", mt->name ), NULL, 0, 0 ); - } - - // apply emo-texture if missing :) - if( !tx ) tx = tr.defaultTexture; - - if( tx->srcFlags & IMAGE_HAS_LUMA ) - Msg( "Texture %s has luma\n", tx->name ); - - R_ShaderAddStageTexture( tx ); - - return tx; -} - -/* -================= -Mod_LoadCachedImage -================= -*/ -static ref_shader_t *Mod_LoadCachedImage( cachedimage_t *image ) -{ - mip_t *mt = image->base; - int i, shader_type = SHADER_TEXTURE; - texture_t *tx; - - // see if already loaded - if( image->shader ) - return image->shader; - - ASSERT( mt ); - - com.strncpy( image->name, mt->name, sizeof( image->name )); - - if( R_ShaderCheckCache( image->name )) - { - R_SetInternalTexture( mt ); // support map $default - goto load_shader; // external shader found - } - else R_SetInternalTexture( NULL ); - - // build the unique shadername because we don't want keep this for other maps -#if 0 - if( mt->offsets[0] > 0 && com.strncmp( mt->name, "sky", 3 )) - com.snprintf( image->name, sizeof( image->name ), "%s/%s", cached.modelname, mt->name ); -#endif - - // determine shader parms by texturename - if( !com.strncmp( mt->name, "scroll", 6 )) - R_ShaderSetMiptexFlags( MIPTEX_CONVEYOR ); - - if( mt->name[0] == '*' || mt->name[0] == '!' || !com.strnicmp( mt->name, "water", 5 )) - R_ShaderSetMiptexFlags( MIPTEX_WARPSURFACE|MIPTEX_NOLIGHTMAP ); - - if( image->animated ) - { - float fps = ( cached.version == HLBSP_VERSION ) ? 10.0f : 5.0f; - - R_SetAnimFrequency( fps ); // set primary animation - for( i = 0; i < image->anim_total[0]; i++ ) - tx = Mod_LoadTexture( image->anim_frames[0][i] ); - - R_SetAnimFrequency( fps ); // set alternate animation - for( i = 0; i < image->anim_total[1]; i++ ) - tx = Mod_LoadTexture( image->anim_frames[1][i] ); - } - else tx = Mod_LoadTexture( mt ); // load the base image - - // force to get it from texture - if( tx == tr.defaultTexture ) - image->width = image->height = -1; - -load_shader: - if( !com.strncmp( mt->name, "sky", 3 ) && cached.version == Q1BSP_VERSION ) - shader_type = SHADER_SKY; - - image->shader = R_LoadShader( image->name, shader_type, false, 0, SHADER_INVALID ); - - return image->shader; -} - -/* -================= -Mod_LoadTextures -================= -*/ -static void Mod_LoadTextures( const dlump_t *l ) -{ - dmiptexlump_t *in; - cachedimage_t *out, *tx1, *tx2, *anims[10], *altanims[10]; - convar_t *scr_loading = Cvar_Get( "scr_loading", "0", 0, "loading bar progress" ); - int i, j, k, num, max, altmax, count; - qboolean incomplete; - mip_t *mt; - - if( !l->filelen ) - { - loadmodel->numshaders = 0; - return; - } - - in = (void *)(mod_base + l->fileofs); - count = in->nummiptex; - - cached.textures = Mem_Alloc( cached_mempool, count * sizeof( *out )); - - loadmodel->shaders = Mod_Malloc( loadmodel, count * sizeof( ref_shader_t* )); - loadmodel->numshaders = count; - - out = cached.textures; - cached.numtextures = count; - - for( i = 0; i < count; i++, out++ ) - { - if( in->dataofs[i] == -1 ) - { - out->shader = tr.defaultShader; - out->width = out->height = -1; - continue; // texture is completely missing - } - - mt = (mip_t *)((byte *)in + in->dataofs[i] ); - - if( !mt->name[0] ) - { - MsgDev( D_WARN, "unnamed texture in %s\n", loadmodel->name ); - com.snprintf( mt->name, sizeof( mt->name ), "*MIPTEX%i", i ); - } - - // convert to lowercase - com.strnlwr( mt->name, mt->name, sizeof( mt->name )); - com.strncpy( out->name, mt->name, sizeof( out->name )); - - // original dimensions for adjust lightmap on a face - out->width = mt->width; - out->height = mt->height; - out->base = mt; - - // sky must be loading first - if( !com.strncmp( mt->name, "sky", 3 )) - Mod_LoadCachedImage( out ); - } - - // sequence the animations - for( i = 0; i < count; i++ ) - { - tx1 = cached.textures + i; - - if( tx1->name[0] != '+' || tx1->name[1] == 0 || tx1->name[2] == 0 ) - continue; - - if( tx1->anim_total[0] || tx1->anim_total[1] ) - continue; // already sequenced - - // find the number of frames in the animation - Mem_Set( anims, 0, sizeof( anims )); - Mem_Set( altanims, 0, sizeof( altanims )); - - for( j = i; j < count; j++ ) - { - tx2 = cached.textures + j; - if( tx2->name[0] != '+' || com.strcmp( tx2->name + 2, tx1->name + 2 )) - continue; - - num = tx2->name[1]; - if( num >= '0' && num <= '9' ) - anims[num - '0'] = tx2; - else if( num >= 'a' && num <= 'j' ) - altanims[num - 'a'] = tx2; - else MsgDev( D_WARN, "bad animating texture %s\n", tx1->name ); - } - - max = altmax = 0; - for( j = 0; j < 10; j++ ) - { - if( anims[j] ) max = j + 1; - if( altanims[j] ) altmax = j + 1; - } - - MsgDev( D_NOTE, "linking animation %s ( %i:%i frames )\n", tx1->name, max, altmax ); - - incomplete = false; - for( j = 0; j < max; j++ ) - { - if( !anims[j] ) - { - MsgDev( D_WARN, "missing frame %i of %s\n", j, tx1->name ); - incomplete = true; - } - } - - for( j = 0; j < altmax; j++ ) - { - if( !altanims[j] ) - { - MsgDev( D_WARN, "missing altframe %i of %s\n", j, tx1->name ); - incomplete = true; - } - } - - // bad animchain - if( incomplete ) continue; - - if( altmax < 1 ) - { - // if there is no alternate animation, duplicate the primary - // animation into the alternate - altmax = max; - for( k = 0; k < 10; k++ ) - altanims[k] = anims[k]; - } - - // link together the primary animation - for( j = 0; j < max; j++ ) - { - tx2 = anims[j]; - tx2->animated = true; - tx2->anim_total[0] = max; - tx2->anim_total[1] = altmax; - - for( k = 0; k < 10; k++ ) - { - tx2->anim_frames[0][k] = (anims[k]) ? anims[k]->base : NULL; - tx2->anim_frames[1][k] = (altanims[k]) ? altanims[k]->base : NULL; - } - } - - // if there really is an alternate anim... - if( anims[0] != altanims[0] ) - { - // link together the alternate animation - for( j = 0; j < altmax; j++ ) - { - tx2 = altanims[j]; - tx2->animated = true; - - // the primary/alternate are reversed here - tx2->anim_total[0] = altmax; - tx2->anim_total[1] = max; - - for( k = 0; k < 10; k++ ) - { - tx2->anim_frames[0][k] = (altanims[k]) ? altanims[k]->base : NULL; - tx2->anim_frames[1][k] = (anims[k]) ? anims[k]->base : NULL; - } - } - } - } - - // load single frames and sequence groups - for( i = 0; i < count; i++ ) - { - out = cached.textures + i; - -// out->contents = Mod_ContentsFromShader( out->name ); // FIXME: implement - loadmodel->shaders[i] = Mod_LoadCachedImage( out ); - - Cvar_SetFloat( "scr_loading", scr_loading->value + 50.0f / count ); - - if( ri.UpdateScreen && ( Cvar_VariableInteger( "allow_levelshots" ) || glw_state.developer > 3 )) - ri.UpdateScreen(); - } -} - -/* -================= -Mod_LoadLighting -================= -*/ -static void Mod_LoadLighting( const dlump_t *l ) -{ - byte d, *in, *out; - int i; - - if( !l->filelen ) return; - in = (mod_base + l->fileofs); - - Mod_CheckDeluxemaps( l, in ); - - switch( cached.version ) - { - case Q1BSP_VERSION: - // expand the white lighting data - loadbmodel->lightdata = Mod_Malloc( loadmodel, l->filelen * 3 ); - out = loadbmodel->lightdata; - - for( i = 0; i < l->filelen; i++ ) - { - d = *in++; - *out++ = d; - *out++ = d; - *out++ = d; - } - break; - case HLBSP_VERSION: - // load colored lighting - loadbmodel->lightdata = Mod_Malloc( loadmodel, l->filelen ); - Mem_Copy( loadbmodel->lightdata, in, l->filelen ); - break; - } -} - -/* -================= -Mod_LoadVertexes -================= -*/ -static void Mod_LoadVertexes( const dlump_t *l ) -{ - dvertex_t *in; - float *out; - int i, j, count; - - in = (void *)( mod_base + l->fileofs ); - if( l->filelen % sizeof( *in ) ) - Host_Error( "Mod_LoadVertexes: funny lump size in %s\n", loadmodel->name ); - count = l->filelen / sizeof( *in ); - - cached.numvertexes = count; - out = (float *)cached.vertexes = Mem_Alloc( cached_mempool, count * sizeof( vec3_t )); - - for( i = 0; i < count; i++, in++, out += 3 ) - { - for( j = 0; j < 3; j++ ) - out[j] = in->point[j]; - } -} - -/* -================= -Mod_LoadSubmodels -================= -*/ -static void Mod_LoadSubmodels( const dlump_t *l ) -{ - int i, j, count; - dmodel_t *in; - mmodel_t *out; - mbrushmodel_t *bmodel; - - in = ( void * )( mod_base + l->fileofs ); - if( l->filelen % sizeof( *in ) ) - Host_Error( "Mod_LoadSubmodels: funny lump size in %s\n", loadmodel->name ); - count = l->filelen / sizeof( *in ); - out = Mod_Malloc( loadmodel, count * sizeof( *out )); - - r_inlinemodels = Mod_Malloc( loadmodel, count * ( sizeof( *r_inlinemodels ) + sizeof( *bmodel ))); - loadmodel->extradata = bmodel = (mbrushmodel_t *)((byte*)r_inlinemodels + count * sizeof( *r_inlinemodels )); - - loadbmodel = bmodel; - loadbmodel->submodels = out; - loadbmodel->numsubmodels = count; - - for( i = 0; i < count; i++, in++, out++ ) - { - r_inlinemodels[i].extradata = bmodel + i; - - for( j = 0; j < 3; j++ ) - { - out->mins[j] = in->mins[j]; - out->maxs[j] = in->maxs[j]; - out->origin[j] = in->origin[j]; - } - - out->radius = RadiusFromBounds( out->mins, out->maxs ); - out->firstnode = in->headnode[0]; // drawing hull #0 - out->firstface = in->firstface; - out->numfaces = in->numfaces; - out->visleafs = in->visleafs; - } -} - -/* -================= -Mod_LoadTexInfo -================= -*/ -static void Mod_LoadTexInfo( const dlump_t *l ) -{ - dtexinfo_t *in; - mtexinfo_t *out; - int miptex; - int i, j, count; - uint surfaceParm = 0; - - in = (void *)(mod_base + l->fileofs); - if( l->filelen % sizeof( *in )) - Host_Error( "Mod_LoadTexInfo: funny lump size in %s\n", loadmodel->name ); - - count = l->filelen / sizeof( *in ); - out = Mod_Malloc( loadmodel, count * sizeof( *out )); - - loadbmodel->texinfo = out; - loadbmodel->numtexinfo = count; - - for( i = 0; i < count; i++, in++, out++ ) - { - for( j = 0; j < 8; j++ ) - out->vecs[0][j] = in->vecs[0][j]; - - miptex = in->miptex; - if( miptex < 0 || miptex > loadmodel->numshaders ) - Host_Error( "Mod_LoadTexInfo: bad shader number in '%s'\n", loadmodel->name ); - out->texturenum = miptex; - - // also copy additional info from cachedinfo - out->width = cached.textures[miptex].width; - out->height = cached.textures[miptex].height; - } -} - -/* -================= -Mod_LoadSurfaces -================= -*/ -static void Mod_LoadSurfaces( const dlump_t *l ) -{ - dface_t *in; - msurface_t *out; - cachedimage_t *texture; - size_t lightofs; - int i, texnum, count; - - in = (void *)(mod_base + l->fileofs); - if( l->filelen % sizeof( dface_t )) - Host_Error( "R_LoadFaces: funny lump size in '%s'\n", loadmodel->name ); - count = l->filelen / sizeof( dface_t ); - - loadbmodel->numsurfaces = count; - loadbmodel->surfaces = Mod_Malloc( loadmodel, count * sizeof( msurface_t )); - out = loadbmodel->surfaces; - - R_BeginBuildingLightmaps(); - - for( i = 0; i < count; i++, in++, out++ ) - { - out->firstedge = in->firstedge; - out->numedges = in->numedges; - - if( in->side ) out->flags |= SURF_PLANEBACK; - out->plane = loadbmodel->planes + in->planenum; - out->texinfo = loadbmodel->texinfo + in->texinfo; - texnum = out->texinfo->texturenum; - - if( texnum < 0 || texnum > cached.numtextures ) - Host_Error( "Mod_LoadFaces: bad texture number in '%s'\n", loadmodel->name ); - - texture = &cached.textures[texnum]; - out->shader = texture->shader; - out->fog = NULL; // FIXME: build conception of realtime fogs - - if( !com.strncmp( texture->name, "sky", 3 )) - out->flags |= (SURF_DRAWSKY|SURF_DRAWTILED); - - if( texture->name[0] == '*' || texture->name[0] == '!' || !com.strnicmp( texture->name, "water", 5 )) - out->flags |= (SURF_DRAWTURB|SURF_DRAWTILED); - - Mod_CalcSurfaceBounds( out ); - Mod_CalcSurfaceExtents( out ); - - // lighting info - out->lmWidth = (out->extents[0] >> 4) + 1; - out->lmHeight = (out->extents[1] >> 4) + 1; - - if( out->flags & SURF_DRAWTILED ) lightofs = -1; - else lightofs = in->lightofs; - - if( loadbmodel->lightdata && lightofs != -1 ) - { - if( cached.version == HLBSP_VERSION ) - out->samples = loadbmodel->lightdata + lightofs; - else out->samples = loadbmodel->lightdata + (lightofs * 3); - } - - while( out->numstyles < LM_STYLES && in->styles[out->numstyles] != 255 ) - { - out->styles[out->numstyles] = in->styles[out->numstyles]; - out->numstyles++; - } - - if( out->flags & SURF_DRAWSKY ) - { - // create fake skyshader for detect it while drawing - out->shader->flags |= SHADER_SKYPARMS; - out->shader->sort = SORT_SKY; - out->shader->skyParms = NULL; - } - - // create lightmap - R_BuildSurfaceLightmap( out ); - - // create polygons - Mod_BuildSurfacePolygons( out ); - - // create unique lightstyle for right sorting surfaces - out->superLightStyle = R_AddSuperLightStyle( out->lmNum, out->styles ); - } - R_EndBuildingLightmaps(); -} - -/* -================= -Mod_LoadMarkFaces -================= -*/ -static void Mod_LoadMarkFaces( const dlump_t *l ) -{ - dmarkface_t *in; - int i, j, count; - - in = (void *)( mod_base + l->fileofs ); - if( l->filelen % sizeof( *in )) - Host_Error( "Mod_LoadMarkFaces: funny lump size in %s\n", loadmodel->name ); - - count = l->filelen / sizeof( *in ); - loadbmodel->marksurfaces = Mod_Malloc( loadmodel, count * sizeof( msurface_t* )); - - for( i = 0; i < count; i++ ) - { - j = in[i]; - if( j < 0 || j >= loadbmodel->numsurfaces ) - Host_Error( "Mod_LoadMarkFaces: bad surface number in '%s'\n", loadmodel->name ); - loadbmodel->marksurfaces[i] = loadbmodel->surfaces + j; - } -} - -/* -================= -Mod_LoadNodes -================= -*/ -static void Mod_LoadNodes( const dlump_t *l ) -{ - int i, j, count, p; - dnode_t *in; - mnode_t *out; - - in = (void *)( mod_base + l->fileofs ); - if( l->filelen % sizeof( *in ) ) - Host_Error( "Mod_LoadNodes: funny lump size in %s\n", loadmodel->name ); - - count = l->filelen / sizeof( *in ); - out = Mod_Malloc( loadmodel, count * sizeof( *out )); - - loadbmodel->nodes = out; - loadbmodel->numnodes = count; - - for( i = 0; i < count; i++, in++, out++ ) - { - qboolean badBounds = false; - - out->plane = loadbmodel->planes + in->planenum; - out->firstface = loadbmodel->surfaces + in->firstface; - out->numfaces = in->numfaces; - out->contents = CONTENTS_NODE; - - for( j = 0; j < 3; j++ ) - { - out->mins[j] = (float)in->mins[j]; - out->maxs[j] = (float)in->maxs[j]; - if( out->mins[j] > out->maxs[j] ) badBounds = true; - } - - if( !badBounds && VectorCompare( out->mins, out->maxs )) - badBounds = true; - - if( badBounds ) - { - MsgDev( D_WARN, "bad node %i bounds:\n", i ); - MsgDev( D_WARN, "mins: %i %i %i\n", Q_rint( out->mins[0] ), Q_rint( out->mins[1] ), Q_rint( out->mins[2] )); - MsgDev( D_WARN, "maxs: %i %i %i\n", Q_rint( out->maxs[0] ), Q_rint( out->maxs[1] ), Q_rint( out->maxs[2] )); - } - - for( j = 0; j < 2; j++ ) - { - p = in->children[j]; - if( p >= 0 ) out->children[j] = loadbmodel->nodes + p; - else out->children[j] = (mnode_t *)(loadbmodel->leafs + ( -1 - p )); - } - } - - Mod_SetNodeParent( loadbmodel->nodes, NULL ); -} - -/* -================= -Mod_LoadLeafs -================= -*/ -static void Mod_LoadLeafs( const dlump_t *l ) -{ - dleaf_t *in; - mleaf_t *out; - int i, j, p, count; - - in = (void *)( mod_base + l->fileofs ); - if( l->filelen % sizeof( *in )) - Host_Error( "Mod_LoadLeafs: funny lump size in %s\n", loadmodel->name ); - - count = l->filelen / sizeof( *in ); - out = Mod_Malloc( loadmodel, count * sizeof( *out )); - - loadbmodel->numleafs = count; - loadbmodel->leafs = out; - - for( i = 0; i < count; i++, in++, out++ ) - { - qboolean badBounds = false; - - for( j = 0; j < 3; j++ ) - { - out->mins[j] = (float)in->mins[j]; - out->maxs[j] = (float)in->maxs[j]; - if( out->mins[j] > out->maxs[j] ) badBounds = true; - } - - if( !badBounds && VectorCompare( out->mins, out->maxs )) - badBounds = true; - - if(( i > 0 ) && badBounds ) - { - MsgDev( D_NOTE, "bad leaf %i bounds:\n", i ); - MsgDev( D_NOTE, "mins: %i %i %i\n", Q_rint( out->mins[0] ), Q_rint( out->mins[1] ), Q_rint( out->mins[2] )); - MsgDev( D_NOTE, "maxs: %i %i %i\n", Q_rint( out->maxs[0] ), Q_rint( out->maxs[1] ), Q_rint( out->maxs[2] )); - } - - out->plane = NULL; // to differentiate from nodes - out->contents = in->contents; - - p = in->visofs; - out->compressed_vis = (p == -1) ? NULL : loadbmodel->visdata + p; - - out->firstMarkSurface = loadbmodel->marksurfaces + in->firstmarksurface; - out->numMarkSurfaces = in->nummarksurfaces; - } -} - -/* -================= -Mod_LoadEdges -================= -*/ -static void Mod_LoadEdges( const dlump_t *l ) -{ - dedge_t *in, *out; - int i, count; - - in = (void *)( mod_base + l->fileofs ); - if( l->filelen % sizeof( *in )) - Host_Error( "Mod_LoadEdges: funny lump size in %s\n", loadmodel->name ); - - count = l->filelen / sizeof( dedge_t ); - cached.edges = out = Mem_Alloc( cached_mempool, count * sizeof( dedge_t )); - cached.numedges = count; - - for( i = 0; i < count; i++, in++, out++ ) - { - out->v[0] = (word)in->v[0]; - out->v[1] = (word)in->v[1]; - } -} - -/* -================= -Mod_LoadSurfEdges -================= -*/ -static void Mod_LoadSurfEdges( const dlump_t *l ) -{ - dsurfedge_t *in, *out; - int count; - - in = (void *)( mod_base + l->fileofs ); - if( l->filelen % sizeof( *in )) - Host_Error( "Mod_LoadSurfEdges: funny lump size in %s\n", loadmodel->name ); - - count = l->filelen / sizeof( dsurfedge_t ); - cached.surfedges = out = Mem_Alloc( cached_mempool, count * sizeof( dsurfedge_t )); - cached.numsurfedges = count; - - Mem_Copy( out, in, count * sizeof( dsurfedge_t )); -} - -/* -================= -Mod_LoadPlanes -================= -*/ -static void Mod_LoadPlanes( const dlump_t *l ) -{ - mplane_t *out; - dplane_t *in; - int i, count; - - in = (void *)( mod_base + l->fileofs ); - if( l->filelen % sizeof( *in )) - Host_Error( "Mod_LoadPlanes: funny lump size in %s\n", loadmodel->name ); - - count = l->filelen / sizeof( *in ); - out = Mod_Malloc( loadmodel, count*sizeof( *out )); - - loadbmodel->planes = out; - loadbmodel->numplanes = count; - - for( i = 0; i < count; i++, in++, out++ ) - { - VectorCopy( in->normal, out->normal ); - out->signbits = SignbitsForPlane( out->normal ); - out->dist = in->dist; - out->type = in->type; - } -} - -/* -================= -Mod_LoadVisibility -================= -*/ -void Mod_LoadVisibility( dlump_t *l ) -{ - if( !l->filelen ) - { - loadbmodel->visdata = NULL; - return; - } - - loadbmodel->visdata = Mod_Malloc( loadmodel, l->filelen ); - Mem_Copy( loadbmodel->visdata, (void *)(mod_base + l->fileofs), l->filelen ); -} - -void StripTrailing( char *e ) -{ - char *s; - - s = e + com.strlen( e ) - 1; - while( s >= e && *s <= 32 ) - { - *s = 0; - s--; - } -} - -/* -================ -ValueForKey - -gets the value for an entity key -================ -*/ -const char *ValueForKey( const mapent_t *ent, const char *key ) -{ - epair_t *ep; - - if( !ent ) return ""; - - for( ep = ent->epairs; ep != NULL; ep = ep->next ) - { - if( !com.strcmp( ep->key, key )) - return ep->value; - } - return ""; -} - -/* -================ -IntForKey - -gets the integer point value for an entity key -================ -*/ -int IntForKey( const mapent_t *ent, const char *key ) -{ - return com.atoi( ValueForKey( ent, key )); -} - -/* -================ -FloatForKey - -gets the floating point value for an entity key -================ -*/ -float FloatForKey( const mapent_t *ent, const char *key ) -{ - return com.atof( ValueForKey( ent, key )); -} - -/* -================ -GetVectorForKey - -gets a 3-element vector value for an entity key -================ -*/ -void GetVectorForKey( const mapent_t *ent, const char *key, vec3_t vec ) -{ - const char *k; - double v1, v2, v3; - - k = ValueForKey( ent, key ); - - // scanf into doubles, then assign, so it is vec_t size independent - v1 = v2 = v3 = 0.0; - sscanf( k, "%lf %lf %lf", &v1, &v2, &v3 ); - VectorSet( vec, v1, v2, v3 ); -} - -/* -================ -FindTargetEntity - -finds an entity target -================ -*/ -mapent_t *FindTargetEntity( const char *target ) -{ - int i; - const char *n; - - for( i = 0; i < cached.numents; i++ ) - { - n = ValueForKey( &cached.entities[i], "targetname" ); - if( !com.strcmp( n, target )) return &cached.entities[i]; - } - return NULL; -} - -/* -================= -Mod_ParseEpair - -parses a single quoted "key" "value" pair into an epair struct -================= -*/ -static epair_t *Mod_ParseEpair( script_t *script, token_t *token ) -{ - epair_t *e; - - e = Mem_Alloc( cached_mempool, sizeof( epair_t )); - e->key = com.stralloc( cached_mempool, token->string, __FILE__, __LINE__ ); - - Com_ReadToken( script, SC_PARSE_GENERIC, token ); - e->value = com.stralloc( cached_mempool, token->string, __FILE__, __LINE__ ); - - // strip trailing spaces if needs - StripTrailing( e->key ); - StripTrailing( e->value ); - - return e; -} - -/* -================ -ParseEntity - -parses an entity's epairs -================ -*/ -static qboolean Mod_ParseEntity( void ) -{ - epair_t *pair; - token_t token; - mapent_t *mapEnt; - - if( !Com_ReadToken( cached.entscript, SC_ALLOW_NEWLINES, &token )) - return false; - - if( com.stricmp( token.string, "{" )) Host_Error( "Mod_ParseEntity: '{' not found\n" ); - if( cached.numents == GI->max_edicts ) return false; // probably stupid user set wrong limit - - mapEnt = &cached.entities[cached.numents]; - cached.numents++; - - while( 1 ) - { - if( !Com_ReadToken( cached.entscript, SC_ALLOW_NEWLINES|SC_PARSE_GENERIC, &token )) - Host_Error( "Mod_ParseEntity: EOF without closing brace\n" ); - if( !com.stricmp( token.string, "}" )) break; - pair = Mod_ParseEpair( cached.entscript, &token ); - pair->next = mapEnt->epairs; - mapEnt->epairs = pair; - } - return true; -} - -/* -================= -Mod_LoadEntities -================= -*/ -static void Mod_LoadEntities( const dlump_t *l, vec3_t ambient ) -{ - float ambientScale = 0.0f; - const char *name, *target; - mapent_t *e, *e2; - float angle; - vec3_t dest; - light_t *dl; - int i; - - cached.entscript = Com_OpenScript( "entities", (char *)mod_base + l->fileofs, l->filelen ); - if( !cached.entscript ) return; - - cached.entities = Mem_Alloc( cached_mempool, sizeof( mapent_t ) * GI->max_edicts ); - cached.numents = 0; - - // read all the ents - while( Mod_ParseEntity( )); - Com_CloseScript( cached.entscript ); - cached.entscript = NULL; - - VectorClear( ambient ); - - for( i = 0; i < cached.numents; i++ ) - { - const char *pLight; - double r, g, b, scaler; - int argCnt; - - e = &cached.entities[i]; - - name = ValueForKey( e, "classname" ); - if( !com.strncmp( name, "worldspawn", 10 )) - { - GetVectorForKey( e, "_color", ambient ); - ambientScale = FloatForKey( e, "_ambient" ); - - if( VectorIsNull( ambient )) VectorSet( ambient, 1.0f, 1.0f, 1.0f ); - if( ambientScale > 0.0f ) VectorScale( ambient, ambientScale, ambient ); - } - - name = ValueForKey( e, "classname" ); - if( com.strncmp( name, "light", 5 )) - continue; - - cached.numPointLights++; - dl = Mem_Alloc( cached_mempool, sizeof( light_t )); - - GetVectorForKey( e, "origin", dl->origin ); - - dl->next = cached.lights; - cached.lights = dl; - - dl->style = IntForKey( e, "style" ); - - pLight = ValueForKey( e, "_light" ); - if( !*pLight ) - { - pLight = ValueForKey( e, "light" ); - dl->photons = com.atof( pLight ); - argCnt = 1; - } - else - { - // scanf into doubles, then assign, so it is vec_t size independent - r = g = b = scaler = 0; - argCnt = sscanf( pLight, "%lf %lf %lf %lf", &r, &g, &b, &scaler ); - dl->color[0] = (float)r; - } - - if( argCnt == 1 ) - { - // The R,G,B values are all equal. - dl->color[0] = dl->color[1] = dl->color[2] = 1.0f; - } - else if( argCnt == 3 || argCnt == 4 ) - { - // save the other two G,B values. - dl->color[0] = (float)r; - dl->color[1] = (float)g; - dl->color[2] = (float)b; - - // did we also get an "intensity" scaler value too? - if( argCnt == 4 ) - { - // scale the normalized 0-255 R,G,B values by the intensity scaler -// dl->color[0] = dl->color[0] / 255 * (float)scaler; -// dl->color[1] = dl->color[1] / 255 * (float)scaler; -// dl->color[2] = dl->color[2] / 255 * (float)scaler; - dl->photons = scaler; - } - } - else - { - MsgDev( D_WARN, "entity at (%f,%f,%f) has bad '_light' value : '%s'\n", - dl->origin[0], dl->origin[1], dl->origin[2], pLight ); - continue; - } - - if( !dl->photons ) dl->photons = 300; - ColorNormalize( dl->color, dl->color ); - - target = ValueForKey (e, "target"); - - if( !com.strcmp( name, "light_spot" ) || !com.strcmp( name, "light_environment" ) || target[0] ) - { - if( !VectorAvg( dl->color )) - VectorSet( dl->color, 500, 500, 500 ); - - dl->type = emit_spotlight; - dl->stopdot = FloatForKey( e, "_cone" ); - if( !dl->stopdot ) dl->stopdot = 10; - dl->stopdot2 = FloatForKey( e, "_cone2" ); - if( !dl->stopdot2 ) dl->stopdot2 = dl->stopdot; - if( dl->stopdot2 < dl->stopdot ) dl->stopdot2 = dl->stopdot; - dl->stopdot2 = (float)com.cos( dl->stopdot2 / 180 * M_PI ); - dl->stopdot = (float)com.cos( dl->stopdot / 180 * M_PI ); - - if( target[0] ) - { - // point towards target - e2 = FindTargetEntity( target ); - if( !e2 ) - { - MsgDev( D_WARN, "light at (%i %i %i) has missing target\n", - (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2] ); - } - else - { - GetVectorForKey( e2, "origin", dest ); - VectorSubtract( dest, dl->origin, dl->normal ); - VectorNormalize( dl->normal ); - } - } - else - { // point down angle - vec3_t vAngles; - - GetVectorForKey( e, "angles", vAngles ); - - angle = IntForKey( e, "angle" ); - - if( angle == ANGLE_UP ) - { - VectorSet( dl->normal, 0.0f, 0.0f, 1.0f ); - } - else if( angle == ANGLE_DOWN ) - { - VectorSet( dl->normal, 0.0f, 0.0f, -1.0f ); - } - else - { - // if we don't have a specific "angle" use the "angles" YAW - if( !angle ) angle = vAngles[1]; - - dl->normal[2] = 0; - dl->normal[0] = (float)com.cos( angle / 180 * M_PI ); - dl->normal[1] = (float)com.sin( angle / 180 * M_PI ); - } - - angle = FloatForKey( e, "pitch" ); - - // if we don't have a specific "pitch" use the "angles" PITCH - if( !angle ) angle = vAngles[0]; - - dl->normal[2] = (float)com.sin( angle / 180 * M_PI ); - dl->normal[0] *= (float)com.cos( angle / 180 * M_PI ); - dl->normal[1] *= (float)com.cos( angle / 180 * M_PI ); - } - - if( IntForKey( e, "_sky" ) || !com.strcmp( name, "light_environment" )) - { - dl->type = emit_skylight; - dl->stopdot2 = FloatForKey( e, "_sky" ); // hack stopdot2 to a sky key number - } - } - else - { - if( !VectorAvg( dl->color )) - VectorSet( dl->color, 1.0f, 1.0f, 1.0f ); - dl->type = emit_point; - } - - dl->photons *= 7500; -/* - if( dl->type != emit_skylight ) - { - float l1 = max( dl->intensity[0], max( dl->intensity[1], dl->intensity[2] )); - l1 = l1 * l1 / 10; - - dl->intensity[0] *= l1; - dl->intensity[1] *= l1; - dl->intensity[2] *= l1; - } -*/ - } -} - -/* -============================================================================= - - LIGHTGRID CALCULATING - -============================================================================= -*/ -static qboolean R_PointInSolid( const vec3_t p ) -{ - return (Mod_PointInLeaf( p, loadmodel )->contents == CONTENTS_SOLID); -} - -/* -================ -R_PointToPolygonFormFactor -================ -*/ -float R_PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w ) -{ - float total; - vec3_t dirs[64]; - vec3_t triVector, triNormal; - float dot, angle, facing; - int i, j; - - for( i = 0; i < w->numpoints; i++ ) - { - VectorSubtract( w->points[i], point, dirs[i] ); - VectorNormalize( dirs[i] ); - } - - // duplicate first vertex to avoid mod operation - VectorCopy( dirs[0], dirs[i] ); - - total = 0; - for( i = 0 ; i < w->numpoints; i++ ) - { - j = i + 1; - dot = DotProduct( dirs[i], dirs[j] ); - - // roundoff can cause slight creep, which gives an IND from acos - dot = bound( -1.0f, dot, 1.0f ); - - angle = com.acos( dot ); - CrossProduct( dirs[i], dirs[j], triVector ); - if( VectorNormalizeLength2( triVector, triNormal ) < 0.0001f ) - continue; - - facing = DotProduct( normal, triNormal ); - total += facing * angle; - - if( total > 6.3f || total < -6.3f ) - return 0; - } - - total /= M_PI2; // now in the range of 0 to 1 over the entire incoming hemisphere - - return total; -} - -/* -======================== -R_LightContributionToPoint -======================== -*/ -qboolean R_LightContributionToPoint( const light_t *light, const vec3_t origin, vec3_t color ) -{ - pmtrace_t trace; - float add; - - add = 0; - - VectorClear( color ); - - // testing exact PTPFF - if( light->type == emit_surface ) - { - float d, factor; - vec3_t normal; - - // see if the point is behind the light - d = DotProduct( origin, light->normal ) - light->dist; - if( d < 1 ) return false; // point is behind light - - // test occlusion - // clip the line, tracing from the surface towards the light - R_TraceLine( &trace, origin, light->origin, FTRACE_IGNORE_GLASS ); - if( trace.fraction != 1.0f ) return false; - - // calculate the contribution - VectorSubtract( light->origin, origin, normal ); - if( VectorNormalizeLength( normal ) == 0 ) - return false; - - factor = R_PointToPolygonFormFactor( origin, normal, light->w ); - if( factor <= 0 ) return false; - - // FIXME: we needs to rescale color with factor ? - VectorScale( light->color, factor, color ); - return true; - } - - // calculate the amount of light at this sample - if( light->type == emit_point || light->type == emit_spotlight ) - { - vec3_t dir; - float dist; - - VectorSubtract( light->origin, origin, dir ); - dist = VectorLength( dir ); - - // clamp the distance to prevent super hot spots - if( dist < 16 ) dist = 16; - - add = light->photons * (1.0 / 8000) - dist; - - add = light->photons / ( dist * dist ); -// add = light->color[0] + light->color[1] + light->color[2]; - } - else - { - return false; - } - - if( add <= 1.0f ) - { - return false; - } - - // clip the line, tracing from the surface towards the light - if( R_TraceLine( &trace, origin, light->origin, FTRACE_IGNORE_GLASS )) - return false; - - // other light rays must not hit anything - if( trace.fraction != 1.0f ) - return false; - - // add the result - VectorScale( light->color, add, color ); - - return true; -} - -static void R_TraceGrid( int num ) -{ - int x, y, z; - vec3_t origin; - light_t *light; - vec3_t summedDir; - vec3_t ambientColor[LM_STYLES]; - vec3_t directedColor[LM_STYLES]; - contribution_t contributions[1024]; - int i, j, mod, numCon, numStyles; - mgridlight_t *gp; - - mod = num; - z = mod / ( loadbmodel->gridBounds[0] * loadbmodel->gridBounds[1] ); - mod -= z * ( loadbmodel->gridBounds[0] * loadbmodel->gridBounds[1] ); - - y = mod / loadbmodel->gridBounds[0]; - mod -= y * loadbmodel->gridBounds[0]; - - x = mod; - - origin[0] = loadbmodel->gridMins[0] + x * loadbmodel->gridSize[0]; - origin[1] = loadbmodel->gridMins[1] + y * loadbmodel->gridSize[1]; - origin[2] = loadbmodel->gridMins[2] + z * loadbmodel->gridSize[2]; - - if( R_PointInSolid( origin )) - { - vec3_t baseOrigin; - int step; - - VectorCopy( origin, baseOrigin ); - - // try to nudge the origin around to find a valid point - for( step = 9; step <= 18; step += 9 ) - { - for( i = 0; i < 8; i++ ) - { - VectorCopy( baseOrigin, origin ); - - if( i & 1 ) origin[0] += step; - else origin[0] -= step; - - if( i & 2 ) origin[1] += step; - else origin[1] -= step; - - if( i & 4 ) origin[2] += step; - else origin[2] -= step; - - if( !R_PointInSolid( origin )) - break; - } - - if( i != 8 ) break; - } - - // can't find a valid point at all - if( step > 18 ) return; - } - - VectorClear( summedDir ); - - // trace to all the lights - - // find the major light direction, and divide the - // total light between that along the direction and - // the remaining in the ambient - numCon = 0; - for( light = cached.lights; light; light = light->next ) - { - vec3_t add; - vec3_t dir; - float addSize; - - if( !R_LightContributionToPoint( light, origin, add )) - continue; - - VectorSubtract( light->origin, origin, dir ); - VectorNormalize( dir ); - - VectorCopy( add, contributions[numCon].color ); - VectorCopy( dir, contributions[numCon].dir ); - contributions[numCon].style = light->style; - numCon++; - - addSize = VectorLength( add ); - VectorMA( summedDir, addSize, dir, summedDir ); - - if( numCon == 1023 ) - break; - } - - // now that we have identified the primary light direction, - // go back and seperate all the light into directed and ambient - VectorNormalize( summedDir ); - - for( i = 0; i < LM_STYLES; i++ ) - { - VectorClear( ambientColor[i] ); - VectorClear( directedColor[i] ); - } - - gp = loadbmodel->lightgrid + num; - - numStyles = 1; - for( i = 0; i < numCon; i++ ) - { - float d; - - d = DotProduct( contributions[i].dir, summedDir ); - if( d < 0.0f ) d = 0.0f; - - // find appropriate style - for( j = 0; j < numStyles; j++ ) - { - if( gp->styles[j] == contributions[i].style ) - break; - } - - // style not found? - if( j >= numStyles ) - { - // add a new style - if( numStyles < LM_STYLES ) - { - gp->styles[numStyles] = contributions[i].style; - numStyles++; - } - else j = 0; - } - - VectorMA( directedColor[j], d, contributions[i].color, directedColor[j] ); - - // the ambient light will be at 1/4 the value of directed light - d = 0.25f * ( 1.0f - d ); - VectorMA( ambientColor[j], d, contributions[i].color, ambientColor[j] ); - } - - // store off sample - for( i = 0; i < LM_STYLES; i++ ) - { - VectorMA( ambientColor[i], 0.125f, directedColor[i], ambientColor[i] ); - - // save the resulting value out - ColorToBytes( ambientColor[i], gp->ambient[i] ); - ColorToBytes( directedColor[i], gp->diffuse[i] ); - } - - // now do some fudging to keep the ambient from being too low - VectorNormalize( summedDir ); - NormToLatLong( summedDir, gp->direction ); -} - -void R_BuildLightGrid( mbrushmodel_t *world ) -{ - double timestart = Sys_DoubleTime(); - int i; - - MsgDev( D_INFO, "Building LightGrid...\n" ); - - // assume lightgrid size as player hull (eg. 64x64x128) - VectorSet( world->gridSize, 64, 64, 128 ); - - for( i = 0; i < 3; i++ ) - { - vec3_t maxs; - - world->gridMins[i] = world->gridSize[i] * ceil(( world->submodels[0].mins[i] + 1 ) / world->gridSize[i] ); - maxs[i] = world->gridSize[i] * floor(( world->submodels[0].maxs[i] - 1 ) / world->gridSize[i] ); - world->gridBounds[i] = ( maxs[i] - world->gridMins[i] ) / world->gridSize[i] + 1; - } - - world->numgridpoints = world->gridBounds[2] * world->gridBounds[1] * world->gridBounds[0]; - world->gridBounds[3] = world->gridBounds[1] * world->gridBounds[0]; - world->lightgrid = Mod_Malloc( loadmodel, world->numgridpoints * sizeof( mgridlight_t )); - r_worldent->model = loadmodel; // setup trace world - - for( i = 0; i < world->numgridpoints; i++ ) - R_TraceGrid( i ); - - Msg( "numGridPoints %i, mem %s\n", world->numgridpoints, memprint( world->numgridpoints * sizeof( mgridlight_t ))); - MsgDev( D_INFO, "LightGrid building time: %g secs\n", Sys_DoubleTime() - timestart ); -} - -/* -================= -Mod_Finish -================= -*/ -static void Mod_Finish( const dlump_t *faces, const dlump_t *light, vec3_t ambient ) -{ - // set up lightgrid -// R_BuildLightGrid( loadbmodel ); - Mem_EmptyPool( cached_mempool ); -} - -/* -================= -Mod_BrushLoadModel -================= -*/ -void Mod_BrushLoadModel( ref_model_t *mod, const void *buffer ) -{ - dheader_t *header; - mmodel_t *bm; - vec3_t ambient; - int i, j; - - header = (dheader_t *)buffer; - cached.version = header->version; - - switch( cached.version ) - { - case Q1BSP_VERSION: - case HLBSP_VERSION: - break; - default: - MsgDev( D_ERROR, "Mod_BrushModel: %s has wrong version number (%i should be %i)", loadmodel->name, cached.version, HLBSP_VERSION ); - return; - } - - mod->type = mod_brush; - mod_base = (byte *)header; - - // load into heap - Mod_LoadSubmodels( &header->lumps[LUMP_MODELS] ); - - if( header->lumps[LUMP_PLANES].filelen % sizeof( dplane_t )) - { - // blue-shift swapped lumps - Mod_LoadEntities( &header->lumps[LUMP_PLANES], ambient ); - Mod_LoadPlanes( &header->lumps[LUMP_ENTITIES] ); - } - else - { - // normal half-life lumps - Mod_LoadEntities( &header->lumps[LUMP_ENTITIES], ambient ); - Mod_LoadPlanes( &header->lumps[LUMP_PLANES] ); - } - - Mod_LoadVertexes( &header->lumps[LUMP_VERTEXES] ); - Mod_LoadEdges( &header->lumps[LUMP_EDGES] ); - Mod_LoadSurfEdges( &header->lumps[LUMP_SURFEDGES] ); - Mod_LoadTextures( &header->lumps[LUMP_TEXTURES] ); - Mod_LoadLighting( &header->lumps[LUMP_LIGHTING] ); - Mod_LoadVisibility( &header->lumps[LUMP_VISIBILITY] ); - Mod_LoadTexInfo( &header->lumps[LUMP_TEXINFO] ); - Mod_LoadSurfaces( &header->lumps[LUMP_FACES] ); - Mod_LoadMarkFaces( &header->lumps[LUMP_MARKSURFACES] ); - Mod_LoadLeafs( &header->lumps[LUMP_LEAFS] ); - Mod_LoadNodes( &header->lumps[LUMP_NODES] ); - - Mod_Finish( &header->lumps[LUMP_FACES], &header->lumps[LUMP_LIGHTING], ambient ); - mod->touchFrame = tr.registration_sequence; // register model - - // set up the submodels - for( i = 0; i < loadbmodel->numsubmodels; i++ ) - { - ref_model_t *starmod; - mbrushmodel_t *bmodel; - - bm = &loadbmodel->submodels[i]; - starmod = &r_inlinemodels[i]; - bmodel = (mbrushmodel_t *)starmod->extradata; - - Mem_Copy( starmod, mod, sizeof( ref_model_t )); - Mem_Copy( bmodel, mod->extradata, sizeof( mbrushmodel_t )); - - bmodel->firstmodelsurface = bmodel->surfaces + bm->firstface; - bmodel->firstmodelnode = bmodel->nodes + bm->firstnode; - bmodel->nummodelsurfaces = bm->numfaces; - bmodel->numleafs = bm->visleafs + 1; // include solid leaf - starmod->extradata = bmodel; - - VectorCopy( bm->maxs, starmod->maxs ); - VectorCopy( bm->mins, starmod->mins ); - starmod->radius = bm->radius; - - for( j = 0; i != 0 && j < bmodel->nummodelsurfaces; j++ ) - { - msurface_t *surf = bmodel->firstmodelsurface + j; - vec3_t normal, vup = { 0, 0, 1 }; - - // kill water backplanes for submodels (half-life rules) - if( surf->flags & SURF_DRAWTURB ) - { - if( surf->flags & SURF_PLANEBACK ) - VectorNegate( surf->plane->normal, normal ); - else VectorCopy( surf->plane->normal, normal ); - if( surf->mins[2] == bm->mins[2] || !VectorCompare( normal, vup )) - { - if( surf->flags & SURF_PLANEBACK ) - surf->mesh = NULL; // legacy for software renderer - else surf->flags |= SURF_WATERCSG; - } - } - } - - if( i == 0 ) *mod = *starmod; - else bmodel->numsubmodels = 0; - } -} -//============================================================================= - -/* -================= -R_RegisterWorldModel - -Specifies the model that will be used as the world -================= -*/ -void R_BeginRegistration( const char *mapname ) -{ - string fullname; - - tr.registration_sequence++; - mapConfig.deluxeMappingEnabled = false; - VectorClear( mapConfig.ambient ); - - com.strncpy( fullname, mapname, MAX_STRING ); - - // now replacement table is invalidate - Mem_Set( cl_models, 0, sizeof( cl_models )); - - // explicitly free the old map if different - if( com.strcmp( r_models[0].name, fullname )) - { - Mod_FreeModel( &r_models[0] ); - } - else - { - // update progress bar - Cvar_SetFloat( "scr_loading", 50.0f ); - if( ri.UpdateScreen ) ri.UpdateScreen(); - } - - R_NewMap (); - - r_farclip_min = Z_NEAR; // sky shaders will most likely modify this value - r_environment_color->modified = true; - - r_worldmodel = Mod_ForName( fullname, true ); - r_worldbrushmodel = (mbrushmodel_t *)r_worldmodel->extradata; - r_worldmodel->type = mod_world; - - r_worldent->scale = 1.0f; - r_worldent->model = r_worldmodel; - r_worldent->rtype = RT_MODEL; - r_worldent->ent_type = ET_NORMAL; - r_worldent->renderamt = 255; // i'm hope we don't want to see semisolid world :) - Matrix3x3_LoadIdentity( r_worldent->axis ); - Mod_UpdateShaders( r_worldmodel ); - - r_framecount = r_framecount2 = 1; - r_oldviewleaf = r_viewleaf = NULL; // force markleafs -} - -void R_EndRegistration( const char *skyname ) -{ - int i; - ref_model_t *mod; - - // half-life or quake2 skybox-style - R_SetupSky( skyname ); - - for( i = 0, mod = r_models; i < r_nummodels; i++, mod++ ) - { - if( !mod->name ) continue; - if( mod->touchFrame != tr.registration_sequence ) - Mod_FreeModel( mod ); - } - - // purge all unused shaders - R_ShaderFreeUnused(); -} - -/* -================= -R_RegisterModel -================= -*/ -ref_model_t *R_RegisterModel( const char *name ) -{ - ref_model_t *mod; - - mod = Mod_ForName( name, false ); - Mod_UpdateShaders( mod ); - - return mod; -} - -/* -================= -R_ModelBounds -================= -*/ -void R_ModelBounds( const ref_model_t *model, vec3_t mins, vec3_t maxs ) -{ - if( model ) - { - VectorCopy( model->mins, mins ); - VectorCopy( model->maxs, maxs ); - } - else if( r_worldmodel ) - { - VectorCopy( r_worldmodel->mins, mins ); - VectorCopy( r_worldmodel->maxs, maxs ); - } -} diff --git a/vid_gl/r_model.h b/vid_gl/r_model.h deleted file mode 100644 index f61a3d0b..00000000 --- a/vid_gl/r_model.h +++ /dev/null @@ -1,356 +0,0 @@ -/* -Copyright (C) 1997-2001 Id Software, Inc. -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#ifndef R_MODEL_H -#define R_MODEL_H - -/* - -d*_t structures are on-disk representations -m*_t structures are in-memory - -*/ - -#include "sprite.h" -#include "studio.h" - -/* -============================================================================== - -BRUSH MODELS - -============================================================================== -*/ -// -// in memory representation -// -typedef enum -{ - mod_bad = -1, - mod_brush, - mod_sprite, - mod_alias, - mod_studio, - mod_world, // added -} modtype_t; - -typedef struct -{ - vec3_t mins, maxs; - vec3_t origin; - float radius; - int firstnode; // used for lighting bmodels - int firstface; - int numfaces; - int visleafs; -} mmodel_t; - -typedef struct -{ - ref_shader_t *shader; - mplane_t *visibleplane; - - int numplanes; - mplane_t *planes; -} mfog_t; - -typedef struct decal_s -{ - struct decal_s *pnext; // linked list for each surface - struct msurface_s *psurf; // surface id for persistence / unlinking - ref_shader_t *shader; // decal image - - vec3_t position; // location of the decal center in world space. - vec3_t worldPos; // untransformed position, keep for serialization - vec3_t saxis; // direction of the s axis in world space - float dx, dy; // Offsets into surface texture - float scale; // pixel scale - short flags; // decal flags FDECAL_* - short entityIndex; // entity this is attached to - mesh_t *mesh; // cached mesh, created on first decal rendering - - // dynamic decals stuff - float fadeDuration; // Negative value means to fade in - float fadeStartTime; - float currentFrame; // for animated decals - rgba_t color; -} decal_t; - -// miptex features (will be convert to a shader settings) -#define MIPTEX_CONVEYOR BIT( 0 ) // create conveyour surface -#define MIPTEX_LIQUID BIT( 1 ) // is a liquid -#define MIPTEX_TRANSPARENT BIT( 2 ) // transparent texture -#define MIPTEX_RENDERMODE BIT( 3 ) // this surface requires a rendermode stuff -#define MIPTEX_NOLIGHTMAP BIT( 4 ) // this surface if fullbright -#define MIPTEX_WARPSURFACE BIT( 5 ) // this surface is warped - -typedef struct mtexinfo_s -{ - float vecs[2][4]; - short texturenum; // number in cached.textures - short width; - short height; -} mtexinfo_t; - -typedef struct msurface_s -{ - int visframe; // should be drawn when node is crossed - int flags; // see SURF_ for details - int contents; - - int firstedge; // look up in model->edges[]. negative - int numedges; // numbers are backwards edges - - short textureMins[2]; - short extents[2]; - - mtexinfo_t *texinfo; - ref_shader_t *shader; - mesh_t *mesh; - mfog_t *fog; - decal_t *pdecals; // linked surface decals - mplane_t *plane; - - union - { - float origin[3]; - float mins[3]; - }; - union - { - float maxs[3]; - float color[3]; - }; - - // lighting info - int lmWidth; - int lmHeight; - int lmS; - int lmT; - int lmNum; // real lightmap texnum - byte *samples; - int numstyles; - byte styles[LM_STYLES]; - float cached[LM_STYLES]; // values currently used in lightmap - - int superLightStyle; - int fragmentframe; // for multi-check avoidance -} msurface_t; - -#define CONTENTS_NODE 1 // fake contents to determine nodes - -typedef struct mnode_s -{ - // common with leaf - mplane_t *plane; - int pvsframe; - int contents; // for fast checking solid leafs - - float mins[3]; - float maxs[3]; // for bounding box culling - - struct mnode_s *parent; - - // node specific - struct mnode_s *children[2]; - msurface_t *firstface; // used for grab lighting info, decals etc - uint numfaces; -} mnode_t; - -typedef struct mleaf_s -{ - // common with node - mplane_t *plane; - int pvsframe; - int contents; - - float mins[3]; - float maxs[3]; // for bounding box culling - - struct mnode_s *parent; - - // leaf specific - byte *compressed_vis; - int visframe; - - msurface_t **firstMarkSurface; - int numMarkSurfaces; -} mleaf_t; - -typedef struct -{ - byte ambient[LM_STYLES][3]; - byte diffuse[LM_STYLES][3]; - byte styles[LM_STYLES]; - byte direction[2]; -} mgridlight_t; - -typedef struct -{ - int texNum; - float texMatrix[2][2]; -} mlightmapRect_t; - -typedef struct -{ - int numsubmodels; - mmodel_t *submodels; - - int nummodelsurfaces; - msurface_t *firstmodelsurface; - - mnode_t *firstmodelnode; // used for lighting bmodels - - int numplanes; - mplane_t *planes; - - int numleafs; // number of visible leafs, not counting 0 - mleaf_t *leafs; - - int numnodes; - mnode_t *nodes; - - int numsurfaces; - msurface_t *surfaces; - msurface_t **marksurfaces; - - int numgridpoints; - mgridlight_t *lightgrid; - - int numtexinfo; - mtexinfo_t *texinfo; - - byte *visdata; // compressed visdata - byte *lightdata; - - int numfogs; - mfog_t *fogs; - mfog_t *globalfog; - - vec3_t gridSize; - vec3_t gridMins; - int gridBounds[4]; -} mbrushmodel_t; - -/* -============================================================================== - -STUDIO MODELS - -============================================================================== -*/ -typedef struct -{ - studiohdr_t *phdr; - studiohdr_t *thdr; - - void *submodels; - int numsubmodels; - vec3_t *m_pSVectors; // UNDONE: calc SVectors on loading, simple transform on rendering -} mstudiodata_t; - -/* -============================================================================== - -SPRITE MODELS - -============================================================================== -*/ -// -// in memory representation -// -typedef struct mspriteframe_s -{ - int width; - int height; - float up, down, left, right; - float radius; - shader_t shader; -} mspriteframe_t; - -typedef struct -{ - int numframes; - float *intervals; - mspriteframe_t *frames[1]; -} mspritegroup_t; - -typedef struct -{ - frametype_t type; - mspriteframe_t *frameptr; -} mspriteframedesc_t; - -typedef struct -{ - int type; - int rendermode; - int numframes; - mspriteframedesc_t frames[1]; -} msprite_t; - -//=================================================================== - -// -// Whole model -// -typedef struct ref_model_s -{ - char *name; - modtype_t type; - - int touchFrame; // registration sequence - - // volume occupied by the model graphics - vec3_t mins, maxs; - float radius; - int flags; // effect flags - - // memory representation pointer - byte *mempool; - void *extradata; - - // shader pointers for refresh registration_sequence - int numshaders; - ref_shader_t **shaders; -} ref_model_t; - -//============================================================================ - -void R_InitModels( void ); -void R_ShutdownModels( void ); - -void Mod_ClearAll( void ); -ref_model_t *Mod_ForName( const char *name, qboolean crash ); -mleaf_t *Mod_PointInLeaf( const vec3_t p, ref_model_t *model ); -byte *Mod_LeafPVS( mleaf_t *leaf, ref_model_t *model ); -uint Mod_Handle( ref_model_t *mod ); -ref_model_t *Mod_ForHandle( unsigned int elem ); -ref_model_t *R_RegisterModel( const char *name ); -void R_BeginRegistration( const char *model ); -void R_EndRegistration( const char *skyname ); -texture_t *Mod_LoadTexture( struct mip_s *mt ); - -#define Mod_Malloc( mod, size ) Mem_Alloc(( mod )->mempool, size ) -#define Mod_Realloc( mod, data, size ) Mem_Realloc(( mod )->mempool, data, size ) -#define Mod_Free( data ) Mem_Free( data ) -void Mod_Modellist_f( void ); - -#endif // R_MODEL_H \ No newline at end of file diff --git a/vid_gl/r_opengl.c b/vid_gl/r_opengl.c deleted file mode 100644 index c04b6095..00000000 --- a/vid_gl/r_opengl.c +++ /dev/null @@ -1,713 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2007 -// r_opengl.c - openg32.dll handler -//======================================================================= - -#include "r_local.h" - -glwstate_t glw_state; - -#define MAX_PFDS 256 -#define num_vidmodes ((int)(sizeof(vidmode) / sizeof(vidmode[0])) - 1) -#define WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_SYSMENU|WS_CAPTION|WS_VISIBLE) -#define WINDOW_EX_STYLE (0) -#define GL_DRIVER_OPENGL "OpenGL32" - -typedef enum -{ - rserr_ok, - rserr_invalid_fullscreen, - rserr_invalid_mode, - rserr_unknown -} rserr_t; - -typedef struct vidmode_s -{ - const char *desc; - int width; - int height; - qboolean wideScreen; -} vidmode_t; - -vidmode_t vidmode[] = -{ -{"Mode 0: 4x3", 400, 300, false }, -{"Mode 1: 4x3", 512, 384, false }, -{"Mode 2: 4x3", 640, 480, false }, -{"Mode 3: 4x3", 800, 600, false }, -{"Mode 4: 4x3", 960, 720, false }, -{"Mode 5: 4x3", 1024, 768, false }, -{"Mode 6: 4x3", 1152, 864, false }, -{"Mode 7: 4x3", 1280, 800, false }, -{"Mode 8: 4x3", 1280, 960, false }, -{"Mode 9: 4x3", 1280, 1024, false }, -{"Mode 10: 4x3", 1600, 1200, false }, -{"Mode 11: 4x3", 2048, 1536, false }, -{"Mode 12: 16x9", 856, 480, true }, -{"Mode 13: 16x9", 1024, 576, true }, -{"Mode 14: 16x9", 1280, 720, true }, -{"Mode 15: 16x9", 1360, 768, true }, -{"Mode 16: 16x9", 1440, 900, true }, -{"Mode 17: 16x9", 1680, 1050, true }, -{"Mode 18: 16x9", 1920, 1200, true }, -{"Mode 19: 16x9", 2560, 1600, true }, -{NULL, 0, 0, 0 }, -}; - -static dllfunc_t wgl_funcs[] = -{ - {"wglChoosePixelFormat", (void **) &pwglChoosePixelFormat}, - {"wglDescribePixelFormat", (void **) &pwglDescribePixelFormat}, -// {"wglGetPixelFormat", (void **) &pwglGetPixelFormat}, - {"wglSetPixelFormat", (void **) &pwglSetPixelFormat}, - {"wglSwapBuffers", (void **) &pwglSwapBuffers}, - {"wglCreateContext", (void **) &pwglCreateContext}, - {"wglDeleteContext", (void **) &pwglDeleteContext}, - {"wglGetProcAddress", (void **) &pwglGetProcAddress}, - {"wglMakeCurrent", (void **) &pwglMakeCurrent}, - {"wglGetCurrentContext", (void **) &pwglGetCurrentContext}, - {"wglGetCurrentDC", (void **) &pwglGetCurrentDC}, - {NULL, NULL} -}; - -dll_info_t opengl_dll = { "opengl32.dll", wgl_funcs, NULL, NULL, NULL, true }; - -qboolean R_DeleteContext( void ) -{ - if( glw_state.hGLRC ) - { - pwglDeleteContext( glw_state.hGLRC ); - glw_state.hGLRC = NULL; - } - if( glw_state.hDC ) - { - ReleaseDC( glw_state.hWnd, glw_state.hDC ); - glw_state.hDC = NULL; - } - return false; -} - -/* -================= -R_ChoosePFD -================= -*/ -static int R_ChoosePFD( int colorBits, int depthBits, int stencilBits ) -{ - PIXELFORMATDESCRIPTOR PFDs[MAX_PFDS], *current, *selected; - int i, numPFDs, pixelFormat = 0; - uint flags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER; - - MsgDev( D_NOTE, "R_ChoosePFD( %i, %i, %i )\n", colorBits, depthBits, stencilBits); - - // Count PFDs - if( glw_state.minidriver ) - numPFDs = pwglDescribePixelFormat( glw_state.hDC, 0, 0, NULL ); - else numPFDs = DescribePixelFormat( glw_state.hDC, 0, 0, NULL ); - - if( numPFDs > MAX_PFDS ) - { - MsgDev( D_NOTE, "too many PFDs returned (%i > %i), reduce it\n", numPFDs, MAX_PFDS ); - numPFDs = MAX_PFDS; - } - else if( numPFDs < 1 ) - { - MsgDev( D_ERROR, "R_ChoosePFD failed\n" ); - return 0; - } - - MsgDev( D_NOTE, "R_ChoosePFD: %i PFDs found\n", numPFDs ); - - // run through all the PFDs, looking for the best match - for( i = 1, current = PFDs; i <= numPFDs; i++, current++ ) - { - if( glw_state.minidriver ) - pwglDescribePixelFormat( glw_state.hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), current ); - else DescribePixelFormat( glw_state.hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), current ); - - // check acceleration - if(( current->dwFlags & PFD_GENERIC_FORMAT ) && !r_allow_software->integer ) - continue; - - // check flags - if(( current->dwFlags & flags ) != flags ) - continue; - - // check pixel type - if( current->iPixelType != PFD_TYPE_RGBA ) - continue; - - // check color bits - if( current->cColorBits < colorBits ) - continue; - - // check depth bits - if( current->cDepthBits < depthBits ) - continue; - - // check stencil bits - if( current->cStencilBits < stencilBits ) - continue; - - // if we don't have a selected PFD yet, then use it - if( !pixelFormat ) - { - selected = current; - pixelFormat = i; - continue; - } - - if( colorBits != selected->cColorBits ) - { - if( colorBits == current->cColorBits || current->cColorBits > selected->cColorBits ) - { - selected = current; - pixelFormat = i; - continue; - } - } - - if( depthBits != selected->cDepthBits ) - { - if( depthBits == current->cDepthBits || current->cDepthBits > selected->cDepthBits ) - { - selected = current; - pixelFormat = i; - continue; - } - } - - if( stencilBits != selected->cStencilBits ) - { - if( stencilBits == current->cStencilBits || current->cStencilBits > selected->cStencilBits ) - { - selected = current; - pixelFormat = i; - continue; - } - } - } - - if( !pixelFormat ) - { - MsgDev( D_ERROR, "R_ChoosePFD: no hardware acceleration found\n" ); - return 0; - } - - if( selected->dwFlags & PFD_GENERIC_FORMAT ) - { - if( selected->dwFlags & PFD_GENERIC_ACCELERATED ) - { - MsgDev( D_NOTE, "R_ChoosePFD:: MCD acceleration found\n" ); - glw_state.software = false; - } - else - { - MsgDev( D_NOTE, "R_ChoosePFD: using software emulation\n" ); - glw_state.software = true; - } - } - else - { - MsgDev( D_NOTE, "using hardware acceleration\n"); - glw_state.software = false; - } - MsgDev( D_NOTE, "R_ChoosePFD: PIXELFORMAT %i selected\n", pixelFormat ); - - return pixelFormat; -} - -qboolean R_SetPixelformat( void ) -{ - PIXELFORMATDESCRIPTOR PFD; - int colorBits, depthBits, stencilBits; - int pixelFormat; - size_t gamma_size; - byte *savedGamma; - - Sys_LoadLibrary( NULL, &opengl_dll ); // load opengl32.dll - if( !opengl_dll.link ) return false; - - glw_state.minidriver = false; // FIXME: allow 3dfx drivers too - - if( glw_state.minidriver ) - { - if(( glw_state.hDC = pwglGetCurrentDC()) == NULL ) - return false; - } - else - { - if(( glw_state.hDC = GetDC( glw_state.hWnd )) == NULL ) - return false; - } - - // set color/depth/stencil - colorBits = (r_colorbits->integer) ? r_colorbits->integer : 32; - depthBits = (r_depthbits->integer) ? r_depthbits->integer : 24; - stencilBits = (r_stencilbits->integer) ? r_stencilbits->integer : 0; - - // choose a pixel format - pixelFormat = R_ChoosePFD( colorBits, depthBits, stencilBits ); - if( !pixelFormat ) - { - // try again with default color/depth/stencil - if( colorBits > 16 || depthBits > 16 || stencilBits > 0 ) - pixelFormat = R_ChoosePFD( 16, 16, 0 ); - else pixelFormat = R_ChoosePFD( 32, 24, 0 ); - - if( !pixelFormat ) - { - MsgDev( D_ERROR, "R_SetPixelformat: failed to find an appropriate PIXELFORMAT\n" ); - ReleaseDC( glw_state.hWnd, glw_state.hDC ); - glw_state.hDC = NULL; - return false; - } - } - - // set the pixel format - if( glw_state.minidriver ) - { - pwglDescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD ); - - if( !pwglSetPixelFormat( glw_state.hDC, pixelFormat, &PFD )) - { - MsgDev( D_ERROR, "R_SetPixelformat: wglSetPixelFormat failed\n" ); - return R_DeleteContext(); - } - } - else - { - DescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD ); - - if( !SetPixelFormat( glw_state.hDC, pixelFormat, &PFD )) - { - MsgDev( D_ERROR, "R_SetPixelformat: failed\n" ); - return R_DeleteContext(); - } - } - - glConfig.color_bits = PFD.cColorBits; - glConfig.depth_bits = PFD.cDepthBits; - glConfig.stencil_bits = PFD.cStencilBits; - - if(!(glw_state.hGLRC = pwglCreateContext( glw_state.hDC ))) - return R_DeleteContext(); - if(!(pwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ))) - return R_DeleteContext(); - - if( PFD.cStencilBits != 0 ) - glState.stencilEnabled = true; - else glState.stencilEnabled = false; - - // print out PFD specifics - MsgDev( D_NOTE, "GL PFD: color(%d-bits) Z(%d-bit)\n", ( int )PFD.cColorBits, ( int )PFD.cDepthBits ); - - // init gamma ramp - ZeroMemory( glState.stateRamp, sizeof(glState.stateRamp)); - - if( pwglGetDeviceGammaRamp3DFX ) - glConfig.deviceSupportsGamma = pwglGetDeviceGammaRamp3DFX( glw_state.hDC, glState.stateRamp ); - else glConfig.deviceSupportsGamma = GetDeviceGammaRamp( glw_state.hDC, glState.stateRamp ); - - // share this extension so engine can grab them - GL_SetExtension( R_HARDWARE_GAMMA_CONTROL, glConfig.deviceSupportsGamma ); - - savedGamma = FS_LoadFile( "gamma.dat", &gamma_size ); - if( !savedGamma || gamma_size != sizeof( glState.stateRamp )) - { - // saved gamma not found or corrupted file - FS_WriteFile( "gamma.dat", glState.stateRamp, sizeof(glState.stateRamp)); - MsgDev( D_NOTE, "gamma.dat initialized\n" ); - if( savedGamma ) Mem_Free( savedGamma ); - } - else - { - GL_BuildGammaTable(); - - // validate base gamma - if( !memcmp( savedGamma, glState.stateRamp, sizeof( glState.stateRamp ))) - { - // all ok, previous gamma is valid - MsgDev( D_NOTE, "R_SetPixelformat: validate screen gamma - ok\n" ); - } - else if( !memcmp( glState.gammaRamp, glState.stateRamp, sizeof( glState.stateRamp ))) - { - // screen gamma is equal to render gamma (probably previous instance crashed) - // run additional check to make sure it - if( memcmp( savedGamma, glState.stateRamp, sizeof( glState.stateRamp ))) - { - // yes, current gamma it's totally wrong, restore it from gamma.dat - MsgDev( D_NOTE, "R_SetPixelformat: restore original gamma after crash\n" ); - Mem_Copy( glState.stateRamp, savedGamma, sizeof( glState.gammaRamp )); - } - else - { - // oops, savedGamma == glState.stateRamp == glState.gammaRamp - // probably r_gamma set as default - MsgDev( D_NOTE, "R_SetPixelformat: validate screen gamma - disabled\n" ); - } - } - else if( !memcmp( glState.gammaRamp, savedGamma, sizeof( glState.stateRamp ))) - { - // saved gamma is equal render gamma, probably gamma.dat writed after crash - // run additional check to make sure it - if( memcmp( savedGamma, glState.stateRamp, sizeof( glState.stateRamp ))) - { - // yes, saved gamma it's totally wrong, get origianl gamma from screen - MsgDev( D_NOTE, "R_SetPixelformat: merge gamma.dat after crash\n" ); - FS_WriteFile( "gamma.dat", glState.stateRamp, sizeof( glState.stateRamp )); - } - else - { - // oops, savedGamma == glState.stateRamp == glState.gammaRamp - // probably r_gamma set as default - MsgDev( D_NOTE, "R_SetPixelformat: validate screen gamma - disabled\n" ); - } - } - else - { - // current gamma unset by other application, we can restore it here - MsgDev( D_NOTE, "R_SetPixelformat: restore original gamma after crash\n" ); - Mem_Copy( glState.stateRamp, savedGamma, sizeof( glState.gammaRamp )); - } - Mem_Free( savedGamma ); - } - r_gamma->modified = true; - - return true; -} - -void R_RestoreGamma( void ) -{ - if( !glw_state.hDC ) return; - SetDeviceGammaRamp( glw_state.hDC, glState.stateRamp ); -} - -void R_Free_OpenGL( void ) -{ - R_RestoreGamma (); - - if( pwglMakeCurrent ) pwglMakeCurrent( NULL, NULL ); - if( glw_state.hGLRC ) - { - if( pwglDeleteContext ) pwglDeleteContext( glw_state.hGLRC ); - glw_state.hGLRC = NULL; - } - if( glw_state.hDC ) - { - ReleaseDC( glw_state.hWnd, glw_state.hDC ); - glw_state.hDC = NULL; - } - if( glw_state.hWnd ) - { - DestroyWindow ( glw_state.hWnd ); - glw_state.hWnd = NULL; - } - - UnregisterClass( "Xash Window", glw_state.hInst ); - - if( glState.fullScreen ) - { - ChangeDisplaySettings( 0, 0 ); - glState.fullScreen = false; - } - Sys_FreeLibrary( &opengl_dll ); - - // now all extensions are disabled - Mem_Set( glConfig.extension, 0, sizeof( glConfig.extension[0] ) * R_EXTCOUNT ); - glw_state.initialized = false; -} - -void R_SaveVideoMode( int vid_mode ) -{ - int mode = bound( 0, vid_mode, num_vidmodes ); // check range - - glState.width = vidmode[mode].width; - glState.height = vidmode[mode].height; - glState.wideScreen = vidmode[mode].wideScreen; - - Cvar_FullSet( "width", va( "%i", vidmode[mode].width ), CVAR_READ_ONLY ); - Cvar_FullSet( "height", va( "%i", vidmode[mode].height ), CVAR_READ_ONLY ); - Cvar_SetFloat( "r_mode", mode ); // merge if it out of bounds - - MsgDev( D_NOTE, "Set: %s [%dx%d]\n", vidmode[mode].desc, vidmode[mode].width, vidmode[mode].height ); -} - -qboolean R_CreateWindow( int width, int height, qboolean fullscreen ) -{ - WNDCLASS wc; - RECT rect; - convar_t *r_xpos, *r_ypos; - int x = 0, y = 0, w, h; - int stylebits = WINDOW_STYLE; - int exstyle = WINDOW_EX_STYLE; - static string wndname; - - com.snprintf( wndname, sizeof( wndname ), "%s", GI->title ); - - // register the frame class - wc.style = CS_OWNDC|CS_NOCLOSE; - wc.lpfnWndProc = (WNDPROC)glw_state.wndproc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = glw_state.hInst; - wc.hCursor = LoadCursor( NULL, IDC_ARROW ); - wc.hbrBackground = (void *)COLOR_3DSHADOW; - wc.lpszClassName = "Xash Window"; - wc.lpszMenuName = 0; - - // find the icon file in the filesystem - if( FS_FileExistsEx( "game.ico", true )) - { - char localPath[MAX_PATH]; - - com.snprintf( localPath, sizeof( localPath ), "%s/game.ico", GI->gamedir ); - wc.hIcon = LoadImage( NULL, localPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE|LR_DEFAULTSIZE ); - if( !wc.hIcon ) - { - MsgDev( D_INFO, "Extract game.ico from pak if you want to see it.\n" ); - wc.hIcon = LoadIcon( glw_state.hInst, MAKEINTRESOURCE( 101 )); - } - } - else wc.hIcon = LoadIcon( glw_state.hInst, MAKEINTRESOURCE( 101 )); - - if( !RegisterClass( &wc )) - { - MsgDev( D_ERROR, "R_CreateWindow: couldn't register window class %s\n" "Xash Window" ); - return false; - } - - if( fullscreen ) - { - stylebits = WS_POPUP|WS_VISIBLE; - exstyle = WS_EX_TOPMOST; - } - - rect.left = 0; - rect.top = 0; - rect.right = width; - rect.bottom = height; - - AdjustWindowRect( &rect, stylebits, FALSE ); - w = rect.right - rect.left; - h = rect.bottom - rect.top; - - if( !fullscreen ) - { - r_xpos = Cvar_Get( "r_xpos", "130", CVAR_RENDERINFO, "window position by horizontal" ); - r_ypos = Cvar_Get( "r_ypos", "48", CVAR_RENDERINFO, "window position by vertical" ); - x = r_xpos->integer; - y = r_ypos->integer; - - // adjust window coordinates if necessary - // so that the window is completely on screen - if( x < 0 ) x = 0; - if( y < 0 ) y = 0; - - if( Cvar_VariableInteger( "r_mode" ) != glConfig.prev_mode ) - { - if(( x + w > glw_state.desktopWidth ) || ( y + h > glw_state.desktopHeight )) - { - x = ( glw_state.desktopWidth - w ) / 2; - y = ( glw_state.desktopHeight - h ) / 2; - } - } - } - - glw_state.hWnd = CreateWindowEx( exstyle, "Xash Window", wndname, stylebits, x, y, w, h, NULL, NULL, glw_state.hInst, NULL ); - - if( !glw_state.hWnd ) - { - MsgDev( D_ERROR, "R_CreateWindow: couldn't create '%s'\n", wndname ); - return false; - } - - ShowWindow( glw_state.hWnd, SW_SHOW ); - UpdateWindow( glw_state.hWnd ); - - // init all the gl stuff for the window - if( !R_SetPixelformat( )) - { - ShowWindow( glw_state.hWnd, SW_HIDE ); - DestroyWindow( glw_state.hWnd ); - glw_state.hWnd = NULL; - - UnregisterClass( "Xash Window", glw_state.hInst ); - MsgDev( D_ERROR, "OpenGL driver not installed\n" ); - return false; - } - - SetForegroundWindow( glw_state.hWnd ); - SetFocus( glw_state.hWnd ); - return true; -} - -rserr_t R_ChangeDisplaySettings( int vid_mode, qboolean fullscreen ) -{ - int width, height; - HDC hDC; - - R_SaveVideoMode( vid_mode ); - - width = r_width->integer; - height = r_height->integer; - - // check our desktop attributes - hDC = GetDC( GetDesktopWindow() ); - glw_state.desktopBitsPixel = GetDeviceCaps( hDC, BITSPIXEL ); - glw_state.desktopWidth = GetDeviceCaps( hDC, HORZRES ); - glw_state.desktopHeight = GetDeviceCaps( hDC, VERTRES ); - ReleaseDC( GetDesktopWindow(), hDC ); - - // destroy the existing window - if( glw_state.hWnd ) R_Free_OpenGL(); - - // do a CDS if needed - if( fullscreen ) - { - DEVMODE dm; - - ZeroMemory( &dm, sizeof( dm )); - dm.dmSize = sizeof( dm ); - dm.dmPelsWidth = width; - dm.dmPelsHeight = height; - dm.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT; - - if( vid_displayfrequency->integer > 0 ) - { - dm.dmFields |= DM_DISPLAYFREQUENCY; - dm.dmDisplayFrequency = vid_displayfrequency->integer; - } - - if( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) == DISP_CHANGE_SUCCESSFUL ) - { - glState.fullScreen = true; - if( !R_CreateWindow( width, height, true )) - return rserr_invalid_mode; - return rserr_ok; - } - else - { - dm.dmPelsWidth = width * 2; - dm.dmPelsHeight = height; - dm.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT; - if( r_depthbits->integer != 0 ) - { - dm.dmBitsPerPel = r_depthbits->integer; - dm.dmFields |= DM_BITSPERPEL; - } - - // our first CDS failed, so maybe we're running on some weird dual monitor system - if( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL ) - { - ChangeDisplaySettings( 0, 0 ); - glState.fullScreen = false; - if( !R_CreateWindow( width, height, false )) - return rserr_invalid_mode; - return rserr_invalid_fullscreen; - } - else - { - if( !R_CreateWindow( width, height, true )) - return rserr_invalid_mode; - glState.fullScreen = true; - return rserr_ok; - } - } - } - else - { - ChangeDisplaySettings( 0, 0 ); - glState.fullScreen = false; - if( !R_CreateWindow( width, height, false )) - return rserr_invalid_mode; - } - return rserr_ok; -} - -/* -================== -R_Init_OpenGL -================== -*/ -qboolean R_Init_OpenGL( void ) -{ - rserr_t err; - qboolean fullscreen; - - fullscreen = vid_fullscreen->integer; - vid_fullscreen->modified = false; - r_mode->modified = false; - - if(( err = R_ChangeDisplaySettings( r_mode->integer, fullscreen )) == rserr_ok ) - { - glConfig.prev_mode = r_mode->integer; - } - else - { - if( err == rserr_invalid_fullscreen ) - { - Cvar_SetFloat( "fullscreen", 0 ); - vid_fullscreen->modified = false; - MsgDev( D_ERROR, "R_SetMode: fullscreen unavailable in this mode\n" ); - if(( err = R_ChangeDisplaySettings( r_mode->integer, false )) == rserr_ok ) - return true; - } - else if( err == rserr_invalid_mode ) - { - Cvar_SetFloat( "r_mode", glConfig.prev_mode ); - r_mode->modified = false; - MsgDev( D_ERROR, "R_SetMode: invalid mode\n" ); - } - - // try setting it back to something safe - if(( err = R_ChangeDisplaySettings( glConfig.prev_mode, false )) != rserr_ok ) - { - MsgDev( D_ERROR, "R_SetMode: could not revert to safe mode\n" ); - return false; - } - } - return true; -} - -/* -================= -R_CheckForErrors -================= -*/ -void R_CheckForErrors_( const char *filename, const int fileline ) -{ - int err; - char *str; - - if( !r_check_errors->integer ) - return; - if((err = pglGetError()) == GL_NO_ERROR ) - return; - - switch( err ) - { - case GL_STACK_OVERFLOW: - str = "GL_STACK_OVERFLOW"; - break; - case GL_STACK_UNDERFLOW: - str = "GL_STACK_UNDERFLOW"; - break; - case GL_INVALID_ENUM: - str = "GL_INVALID_ENUM"; - break; - case GL_INVALID_VALUE: - str = "GL_INVALID_VALUE"; - break; - case GL_INVALID_OPERATION: - str = "GL_INVALID_OPERATION"; - break; - case GL_OUT_OF_MEMORY: - str = "GL_OUT_OF_MEMORY"; - break; - default: - str = "UNKNOWN ERROR"; - break; - } - Host_Error( "R_CheckForErrors: %s (called at %s:%i)\n", str, filename, fileline ); -} \ No newline at end of file diff --git a/vid_gl/r_opengl.h b/vid_gl/r_opengl.h deleted file mode 100644 index 6c31ea97..00000000 --- a/vid_gl/r_opengl.h +++ /dev/null @@ -1,1128 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2007 -// r_opengl.h - opengl definition -//======================================================================= - -#ifndef R_OPENGL_H -#define R_OPENGL_H - -#ifndef APIENTRY -#define APIENTRY -#endif - -typedef uint GLenum; -typedef byte GLqbooleanean; -typedef uint GLbitfield; -typedef void GLvoid; -typedef signed char GLbyte; -typedef short GLshort; -typedef int GLint; -typedef byte GLubyte; -typedef word GLushort; -typedef uint GLuint; -typedef int GLsizei; -typedef float GLfloat; -typedef float GLclampf; -typedef double GLdouble; -typedef double GLclampd; -typedef int GLintptrARB; -typedef int GLsizeiptrARB; -typedef char GLcharARB; -typedef uint GLhandleARB; - -#define GL_MODELVIEW 0x1700 -#define GL_PROJECTION 0x1701 -#define GL_TEXTURE 0x1702 -#define GL_MATRIX_MODE 0x0BA0 -#define GL_MODELVIEW_MATRIX 0x0BA6 -#define GL_PROJECTION_MATRIX 0x0BA7 -#define GL_TEXTURE_MATRIX 0x0BA8 - -#define GL_DONT_CARE 0x1100 -#define GL_FASTEST 0x1101 -#define GL_NICEST 0x1102 - -#define GL_DEPTH_TEST 0x0B71 - -#define GL_CULL_FACE 0x0B44 -#define GL_CW 0x0900 -#define GL_CCW 0x0901 -#define GL_BLEND 0x0BE2 -#define GL_ALPHA_TEST 0x0BC0 - -// shading model -#define GL_FLAT 0x1D00 -#define GL_SMOOTH 0x1D01 - -#define GL_ZERO 0x0 -#define GL_ONE 0x1 -#define GL_SRC_COLOR 0x0300 -#define GL_ONE_MINUS_SRC_COLOR 0x0301 -#define GL_DST_COLOR 0x0306 -#define GL_ONE_MINUS_DST_COLOR 0x0307 -#define GL_SRC_ALPHA 0x0302 -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 -#define GL_DST_ALPHA 0x0304 -#define GL_ONE_MINUS_DST_ALPHA 0x0305 -#define GL_SRC_ALPHA_SATURATE 0x0308 -#define GL_CONSTANT_COLOR 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 -#define GL_CONSTANT_ALPHA 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 - -#define GL_TEXTURE_ENV 0x2300 -#define GL_TEXTURE_ENV_MODE 0x2200 -#define GL_TEXTURE_ENV_COLOR 0x2201 -#define GL_TEXTURE_1D 0x0DE0 -#define GL_TEXTURE_2D 0x0DE1 -#define GL_TEXTURE_WRAP_S 0x2802 -#define GL_TEXTURE_WRAP_T 0x2803 -#define GL_TEXTURE_WRAP_R 0x8072 -#define GL_TEXTURE_BORDER_COLOR 0x1004 -#define GL_TEXTURE_MAG_FILTER 0x2800 -#define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_PACK_ALIGNMENT 0x0D05 -#define GL_UNPACK_ALIGNMENT 0x0CF5 -#define GL_TEXTURE_BINDING_1D 0x8068 -#define GL_TEXTURE_BINDING_2D 0x8069 -#define GL_CLAMP_TO_EDGE 0x812F -#define GL_NEAREST 0x2600 -#define GL_LINEAR 0x2601 -#define GL_NEAREST_MIPMAP_NEAREST 0x2700 -#define GL_NEAREST_MIPMAP_LINEAR 0x2702 -#define GL_LINEAR_MIPMAP_NEAREST 0x2701 -#define GL_LINEAR_MIPMAP_LINEAR 0x2703 - -#define GL_LINE 0x1B01 -#define GL_FILL 0x1B02 - -#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF - -#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD -#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500 -#define GL_TEXTURE_LOD_BIAS_EXT 0x8501 - -#define GL_CLAMP_TO_BORDER_ARB 0x812D - -#define GL_ADD 0x0104 -#define GL_DECAL 0x2101 -#define GL_MODULATE 0x2100 - -#define GL_REPEAT 0x2901 -#define GL_CLAMP 0x2900 - -#define GL_POINTS 0x0000 -#define GL_LINES 0x0001 -#define GL_LINE_LOOP 0x0002 -#define GL_LINE_STRIP 0x0003 -#define GL_TRIANGLES 0x0004 -#define GL_TRIANGLE_STRIP 0x0005 -#define GL_TRIANGLE_FAN 0x0006 -#define GL_QUADS 0x0007 -#define GL_QUAD_STRIP 0x0008 -#define GL_POLYGON 0x0009 - -#define GL_FALSE 0x0 -#define GL_TRUE 0x1 - -#define GL_BYTE 0x1400 -#define GL_UNSIGNED_BYTE 0x1401 -#define GL_SHORT 0x1402 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_INT 0x1404 -#define GL_UNSIGNED_INT 0x1405 -#define GL_FLOAT 0x1406 -#define GL_DOUBLE 0x140A -#define GL_2_BYTES 0x1407 -#define GL_3_BYTES 0x1408 -#define GL_4_BYTES 0x1409 - -#define GL_VERTEX_ARRAY 0x8074 -#define GL_NORMAL_ARRAY 0x8075 -#define GL_COLOR_ARRAY 0x8076 -#define GL_INDEX_ARRAY 0x8077 -#define GL_TEXTURE_COORD_ARRAY 0x8078 -#define GL_EDGE_FLAG_ARRAY 0x8079 - -#define GL_NONE 0 -#define GL_FRONT_LEFT 0x0400 -#define GL_FRONT_RIGHT 0x0401 -#define GL_BACK_LEFT 0x0402 -#define GL_BACK_RIGHT 0x0403 -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 -#define GL_LEFT 0x0406 -#define GL_RIGHT 0x0407 -#define GL_FRONT_AND_BACK 0x0408 -#define GL_AUX0 0x0409 -#define GL_AUX1 0x040A -#define GL_AUX2 0x040B -#define GL_AUX3 0x040C - -#define GL_VENDOR 0x1F00 -#define GL_RENDERER 0x1F01 -#define GL_VERSION 0x1F02 -#define GL_EXTENSIONS 0x1F03 - -#define GL_NO_ERROR 0x0 -#define GL_INVALID_VALUE 0x0501 -#define GL_INVALID_ENUM 0x0500 -#define GL_INVALID_OPERATION 0x0502 -#define GL_STACK_OVERFLOW 0x0503 -#define GL_STACK_UNDERFLOW 0x0504 -#define GL_OUT_OF_MEMORY 0x0505 - -#define GL_DITHER 0x0BD0 -#define GL_RGB 0x1907 -#define GL_RGBA 0x1908 -#define GL_BGR 0x80E0 -#define GL_BGRA 0x80E1 -#define GL_ALPHA4 0x803B -#define GL_ALPHA8 0x803C -#define GL_ALPHA12 0x803D -#define GL_ALPHA16 0x803E -#define GL_LUMINANCE4 0x803F -#define GL_LUMINANCE8 0x8040 -#define GL_LUMINANCE12 0x8041 -#define GL_LUMINANCE16 0x8042 -#define GL_LUMINANCE4_ALPHA4 0x8043 -#define GL_LUMINANCE6_ALPHA2 0x8044 -#define GL_LUMINANCE8_ALPHA8 0x8045 -#define GL_LUMINANCE12_ALPHA4 0x8046 -#define GL_LUMINANCE12_ALPHA12 0x8047 -#define GL_LUMINANCE16_ALPHA16 0x8048 -#define GL_DEPTH_COMPONENT 0x1902 -#define GL_INTENSITY 0x8049 -#define GL_INTENSITY4 0x804A -#define GL_INTENSITY8 0x804B -#define GL_INTENSITY12 0x804C -#define GL_INTENSITY16 0x804D -#define GL_R3_G3_B2 0x2A10 -#define GL_RGB4 0x804F -#define GL_RGB5 0x8050 -#define GL_RGB8 0x8051 -#define GL_RGB10 0x8052 -#define GL_RGB12 0x8053 -#define GL_RGB16 0x8054 -#define GL_RGBA2 0x8055 -#define GL_RGBA4 0x8056 -#define GL_RGB5_A1 0x8057 -#define GL_RGBA8 0x8058 -#define GL_RGB10_A2 0x8059 -#define GL_RGBA12 0x805A -#define GL_RGBA16 0x805B -#define GL_TEXTURE_RED_SIZE 0x805C -#define GL_TEXTURE_GREEN_SIZE 0x805D -#define GL_TEXTURE_BLUE_SIZE 0x805E -#define GL_TEXTURE_ALPHA_SIZE 0x805F -#define GL_TEXTURE_LUMINANCE_SIZE 0x8060 -#define GL_TEXTURE_INTENSITY_SIZE 0x8061 -#define GL_PROXY_TEXTURE_1D 0x8063 -#define GL_PROXY_TEXTURE_2D 0x8064 -#define GL_MAX_TEXTURE_SIZE 0x0D33 - -// texture coord name -#define GL_S 0x2000 -#define GL_T 0x2001 -#define GL_R 0x2002 -#define GL_Q 0x2003 - -// texture gen mode -#define GL_EYE_LINEAR 0x2400 -#define GL_OBJECT_LINEAR 0x2401 -#define GL_SPHERE_MAP 0x2402 - -// texture gen parameter -#define GL_TEXTURE_GEN_MODE 0x2500 -#define GL_OBJECT_PLANE 0x2501 -#define GL_EYE_PLANE 0x2502 -#define GL_FOG_HINT 0x0C54 -#define GL_TEXTURE_GEN_S 0x0C60 -#define GL_TEXTURE_GEN_T 0x0C61 -#define GL_TEXTURE_GEN_R 0x0C62 -#define GL_TEXTURE_GEN_Q 0x0C63 - -#define GL_SCISSOR_BOX 0x0C10 -#define GL_SCISSOR_TEST 0x0C11 - -#define GL_NEVER 0x0200 -#define GL_LESS 0x0201 -#define GL_EQUAL 0x0202 -#define GL_LEQUAL 0x0203 -#define GL_GREATER 0x0204 -#define GL_NOTEQUAL 0x0205 -#define GL_GEQUAL 0x0206 -#define GL_ALWAYS 0x0207 -#define GL_DEPTH_TEST 0x0B71 - -#define GL_RED_SCALE 0x0D14 -#define GL_GREEN_SCALE 0x0D18 -#define GL_BLUE_SCALE 0x0D1A -#define GL_ALPHA_SCALE 0x0D1C - -#define GL_DEPTH_BUFFER_BIT 0x00000100 -#define GL_ACCUM_BUFFER_BIT 0x00000200 -#define GL_STENCIL_BUFFER_BIT 0x00000400 -#define GL_COLOR_BUFFER_BIT 0x00004000 - -#define GL_STENCIL_TEST 0x0B90 -#define GL_KEEP 0x1E00 -#define GL_REPLACE 0x1E01 -#define GL_INCR 0x1E02 -#define GL_DECR 0x1E03 - -// fog stuff -#define GL_FOG 0x0B60 -#define GL_FOG_INDEX 0x0B61 -#define GL_FOG_DENSITY 0x0B62 -#define GL_FOG_START 0x0B63 -#define GL_FOG_END 0x0B64 -#define GL_FOG_MODE 0x0B65 -#define GL_FOG_COLOR 0x0B66 - -#define GL_POLYGON_OFFSET_FACTOR 0x8038 -#define GL_POLYGON_OFFSET_UNITS 0x2A00 -#define GL_POLYGON_OFFSET_POINT 0x2A01 -#define GL_POLYGON_OFFSET_LINE 0x2A02 -#define GL_POLYGON_OFFSET_FILL 0x8037 - -#define GL_POINT_SMOOTH 0x0B10 -#define GL_LINE_SMOOTH 0x0B20 -#define GL_POLYGON_SMOOTH 0x0B41 -#define GL_POLYGON_STIPPLE 0x0B42 -#define GL_CLIP_PLANE0 0x3000 -#define GL_CLIP_PLANE1 0x3001 -#define GL_CLIP_PLANE2 0x3002 -#define GL_CLIP_PLANE3 0x3003 -#define GL_CLIP_PLANE4 0x3004 -#define GL_CLIP_PLANE5 0x3005 -#define GL_POINT_SIZE_MIN_EXT 0x8126 -#define GL_POINT_SIZE_MAX_EXT 0x8127 -#define GL_POINT_FADE_THRESHOLD_SIZE_EXT 0x8128 -#define GL_DISTANCE_ATTENUATION_EXT 0x8129 -#define GL_ACTIVE_TEXTURE_ARB 0x84E0 -#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1 -#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 -#define GL_TEXTURE0_ARB 0x84C0 -#define GL_TEXTURE1_ARB 0x84C1 -#define GL_TEXTURE0_SGIS 0x835E -#define GL_TEXTURE1_SGIS 0x835F -#define GL_GENERATE_MIPMAP_SGIS 0x8191 -#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 -#define GL_TEXTURE_RECTANGLE_NV 0x84F5 -#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6 -#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7 -#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 -#define GL_TEXTURE_RECTANGLE_EXT 0x84F5 -#define GL_TEXTURE_BINDING_RECTANGLE_EXT 0x84F6 -#define GL_PROXY_TEXTURE_RECTANGLE_EXT 0x84F7 -#define GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT 0x84F8 -#define GL_MAX_TEXTURE_UNITS 0x84E2 -#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2 - -#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 -#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 -#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 -#define GL_COMPRESSED_ALPHA_ARB 0x84E9 -#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA -#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB -#define GL_COMPRESSED_INTENSITY_ARB 0x84EC -#define GL_COMPRESSED_RGB_ARB 0x84ED -#define GL_COMPRESSED_RGBA_ARB 0x84EE -#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF -#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 -#define GL_TEXTURE_COMPRESSED_ARB 0x86A1 -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 -#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 -#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 -#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 -#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#define GL_TEXTURE_MAX_LEVEL 0x813D -#define GL_GENERATE_MIPMAP 0x8191 -#define GL_ADD_SIGNED 0x8574 - -#define GL_PROGRAM_OBJECT_ARB 0x8B40 -#define GL_OBJECT_TYPE_ARB 0x8B4E -#define GL_OBJECT_SUBTYPE_ARB 0x8B4F -#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 -#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 -#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 -#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 -#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 -#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 -#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 -#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 -#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 -#define GL_SHADER_OBJECT_ARB 0x8B48 -#define GL_FLOAT_VEC2_ARB 0x8B50 -#define GL_FLOAT_VEC3_ARB 0x8B51 -#define GL_FLOAT_VEC4_ARB 0x8B52 -#define GL_INT_VEC2_ARB 0x8B53 -#define GL_INT_VEC3_ARB 0x8B54 -#define GL_INT_VEC4_ARB 0x8B55 -#define GL_BOOL_ARB 0x8B56 -#define GL_BOOL_VEC2_ARB 0x8B57 -#define GL_BOOL_VEC3_ARB 0x8B58 -#define GL_BOOL_VEC4_ARB 0x8B59 -#define GL_FLOAT_MAT2_ARB 0x8B5A -#define GL_FLOAT_MAT3_ARB 0x8B5B -#define GL_FLOAT_MAT4_ARB 0x8B5C -#define GL_SAMPLER_1D_ARB 0x8B5D -#define GL_SAMPLER_2D_ARB 0x8B5E -#define GL_SAMPLER_3D_ARB 0x8B5F -#define GL_SAMPLER_CUBE_ARB 0x8B60 -#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 -#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 -#define GL_SAMPLER_2D_RECT_ARB 0x8B63 -#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 - -#define GL_PACK_SKIP_IMAGES 0x806B -#define GL_PACK_IMAGE_HEIGHT 0x806C -#define GL_UNPACK_SKIP_IMAGES 0x806D -#define GL_UNPACK_IMAGE_HEIGHT 0x806E -#define GL_TEXTURE_3D 0x806F -#define GL_PROXY_TEXTURE_3D 0x8070 -#define GL_TEXTURE_DEPTH 0x8071 -#define GL_TEXTURE_WRAP_R 0x8072 -#define GL_MAX_3D_TEXTURE_SIZE 0x8073 -#define GL_TEXTURE_BINDING_3D 0x806A - -#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910 -#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911 -#define GL_STENCIL_BACK_FUNC 0x8800 -#define GL_STENCIL_BACK_FAIL 0x8801 -#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 -#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 - -#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B -#define GL_TEXTURE_COMPARE_MODE_ARB 0x884C -#define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D -#define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E -#define GL_TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF - -#define GL_QUERY_COUNTER_BITS_ARB 0x8864 -#define GL_CURRENT_QUERY_ARB 0x8865 -#define GL_QUERY_RESULT_ARB 0x8866 -#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 -#define GL_SAMPLES_PASSED_ARB 0x8914 - -#define GL_FUNC_ADD_EXT 0x8006 -#define GL_FUNC_SUBTRACT_EXT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B -#define GL_MIN_EXT 0x8007 -#define GL_MAX_EXT 0x8008 -#define GL_BLEND_EQUATION_EXT 0x8009 - -#define GL_VERTEX_SHADER_ARB 0x8B31 -#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A -#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B -#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 -#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 -#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C -#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D -#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 -#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 -#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 -#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 -#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A -#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 -#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 -#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 -#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 -#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A -#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 -#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 -#define GL_FLOAT_VEC2_ARB 0x8B50 -#define GL_FLOAT_VEC3_ARB 0x8B51 -#define GL_FLOAT_VEC4_ARB 0x8B52 -#define GL_FLOAT_MAT2_ARB 0x8B5A -#define GL_FLOAT_MAT3_ARB 0x8B5B -#define GL_FLOAT_MAT4_ARB 0x8B5C - -#define GL_FRAGMENT_SHADER_ARB 0x8B30 -#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 -#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 -#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 -#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B - -//GL_ARB_vertex_buffer_object -#define GL_ARRAY_BUFFER_ARB 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 -#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 -#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 -#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 -#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 -#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 -#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 -#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A -#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B -#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E -#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F -#define GL_STREAM_DRAW_ARB 0x88E0 -#define GL_STREAM_READ_ARB 0x88E1 -#define GL_STREAM_COPY_ARB 0x88E2 -#define GL_STATIC_DRAW_ARB 0x88E4 -#define GL_STATIC_READ_ARB 0x88E5 -#define GL_STATIC_COPY_ARB 0x88E6 -#define GL_DYNAMIC_DRAW_ARB 0x88E8 -#define GL_DYNAMIC_READ_ARB 0x88E9 -#define GL_DYNAMIC_COPY_ARB 0x88EA -#define GL_READ_ONLY_ARB 0x88B8 -#define GL_WRITE_ONLY_ARB 0x88B9 -#define GL_READ_WRITE_ARB 0x88BA -#define GL_BUFFER_SIZE_ARB 0x8764 -#define GL_BUFFER_USAGE_ARB 0x8765 -#define GL_BUFFER_ACCESS_ARB 0x88BB -#define GL_BUFFER_MAPPED_ARB 0x88BC -#define GL_BUFFER_MAP_POINTER_ARB 0x88BD -#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C -#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D - -#define GL_NORMAL_MAP_ARB 0x8511 -#define GL_REFLECTION_MAP_ARB 0x8512 -#define GL_TEXTURE_CUBE_MAP_ARB 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A -#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C - -#define GL_COMBINE_ARB 0x8570 -#define GL_COMBINE_RGB_ARB 0x8571 -#define GL_COMBINE_ALPHA_ARB 0x8572 -#define GL_SOURCE0_RGB_ARB 0x8580 -#define GL_SOURCE1_RGB_ARB 0x8581 -#define GL_SOURCE2_RGB_ARB 0x8582 -#define GL_SOURCE0_ALPHA_ARB 0x8588 -#define GL_SOURCE1_ALPHA_ARB 0x8589 -#define GL_SOURCE2_ALPHA_ARB 0x858A -#define GL_OPERAND0_RGB_ARB 0x8590 -#define GL_OPERAND1_RGB_ARB 0x8591 -#define GL_OPERAND2_RGB_ARB 0x8592 -#define GL_OPERAND0_ALPHA_ARB 0x8598 -#define GL_OPERAND1_ALPHA_ARB 0x8599 -#define GL_OPERAND2_ALPHA_ARB 0x859A -#define GL_RGB_SCALE_ARB 0x8573 -#define GL_ADD_SIGNED_ARB 0x8574 -#define GL_INTERPOLATE_ARB 0x8575 -#define GL_SUBTRACT_ARB 0x84E7 -#define GL_CONSTANT_ARB 0x8576 -#define GL_PRIMARY_COLOR_ARB 0x8577 -#define GL_PREVIOUS_ARB 0x8578 - -#define GL_DOT3_RGB_ARB 0x86AE -#define GL_DOT3_RGBA_ARB 0x86AF - -#define GL_COLOR_SUM_ARB 0x8458 -#define GL_VERTEX_PROGRAM_ARB 0x8620 -#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 -#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 -#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 -#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 -#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 -#define GL_PROGRAM_LENGTH_ARB 0x8627 -#define GL_PROGRAM_STRING_ARB 0x8628 -#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E -#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F -#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 -#define GL_CURRENT_MATRIX_ARB 0x8641 -#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 -#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 -#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 -#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B -#define GL_PROGRAM_BINDING_ARB 0x8677 -#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 -#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A -#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 -#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 -#define GL_PROGRAM_FORMAT_ARB 0x8876 -#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 -#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 -#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 -#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 -#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 -#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 -#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 -#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 -#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 -#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 -#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA -#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB -#define GL_PROGRAM_ATTRIBS_ARB 0x88AC -#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD -#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE -#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF -#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 -#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 -#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 -#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 -#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 -#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 -#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 -#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 -#define GL_MATRIX0_ARB 0x88C0 -#define GL_MATRIX1_ARB 0x88C1 -#define GL_MATRIX2_ARB 0x88C2 -#define GL_MATRIX3_ARB 0x88C3 -#define GL_MATRIX4_ARB 0x88C4 -#define GL_MATRIX5_ARB 0x88C5 -#define GL_MATRIX6_ARB 0x88C6 -#define GL_MATRIX7_ARB 0x88C7 -#define GL_MATRIX8_ARB 0x88C8 -#define GL_MATRIX9_ARB 0x88C9 -#define GL_MATRIX10_ARB 0x88CA -#define GL_MATRIX11_ARB 0x88CB -#define GL_MATRIX12_ARB 0x88CC -#define GL_MATRIX13_ARB 0x88CD -#define GL_MATRIX14_ARB 0x88CE -#define GL_MATRIX15_ARB 0x88CF -#define GL_MATRIX16_ARB 0x88D0 -#define GL_MATRIX17_ARB 0x88D1 -#define GL_MATRIX18_ARB 0x88D2 -#define GL_MATRIX19_ARB 0x88D3 -#define GL_MATRIX20_ARB 0x88D4 -#define GL_MATRIX21_ARB 0x88D5 -#define GL_MATRIX22_ARB 0x88D6 -#define GL_MATRIX23_ARB 0x88D7 -#define GL_MATRIX24_ARB 0x88D8 -#define GL_MATRIX25_ARB 0x88D9 -#define GL_MATRIX26_ARB 0x88DA -#define GL_MATRIX27_ARB 0x88DB -#define GL_MATRIX28_ARB 0x88DC -#define GL_MATRIX29_ARB 0x88DD -#define GL_MATRIX30_ARB 0x88DE -#define GL_MATRIX31_ARB 0x88DF -#define GL_FRAGMENT_PROGRAM_ARB 0x8804 -#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 -#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 -#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 -#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 -#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 -#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A -#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B -#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C -#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D -#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E -#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F -#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 -#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 -#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 - - -// helper opengl functions -GLenum ( APIENTRY *pglGetError )(void); -const GLubyte * ( APIENTRY *pglGetString )(GLenum name); - -// base gl functions -void ( APIENTRY *pglAccum )(GLenum op, GLfloat value); -void ( APIENTRY *pglAlphaFunc )(GLenum func, GLclampf ref); -void ( APIENTRY *pglArrayElement )(GLint i); -void ( APIENTRY *pglBegin )(GLenum mode); -void ( APIENTRY *pglBindTexture )(GLenum target, GLuint texture); -void ( APIENTRY *pglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap); -void ( APIENTRY *pglBlendFunc )(GLenum sfactor, GLenum dfactor); -void ( APIENTRY *pglCallList )(GLuint list); -void ( APIENTRY *pglCallLists )(GLsizei n, GLenum type, const GLvoid *lists); -void ( APIENTRY *pglClear )(GLbitfield mask); -void ( APIENTRY *pglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -void ( APIENTRY *pglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); -void ( APIENTRY *pglClearDepth )(GLclampd depth); -void ( APIENTRY *pglClearIndex )(GLfloat c); -void ( APIENTRY *pglClearStencil )(GLint s); -void ( APIENTRY *pglClipPlane )(GLenum plane, const GLdouble *equation); -void ( APIENTRY *pglColor3b )(GLbyte red, GLbyte green, GLbyte blue); -void ( APIENTRY *pglColor3bv )(const GLbyte *v); -void ( APIENTRY *pglColor3d )(GLdouble red, GLdouble green, GLdouble blue); -void ( APIENTRY *pglColor3dv )(const GLdouble *v); -void ( APIENTRY *pglColor3f )(GLfloat red, GLfloat green, GLfloat blue); -void ( APIENTRY *pglColor3fv )(const GLfloat *v); -void ( APIENTRY *pglColor3i )(GLint red, GLint green, GLint blue); -void ( APIENTRY *pglColor3iv )(const GLint *v); -void ( APIENTRY *pglColor3s )(GLshort red, GLshort green, GLshort blue); -void ( APIENTRY *pglColor3sv )(const GLshort *v); -void ( APIENTRY *pglColor3ub )(GLubyte red, GLubyte green, GLubyte blue); -void ( APIENTRY *pglColor3ubv )(const GLubyte *v); -void ( APIENTRY *pglColor3ui )(GLuint red, GLuint green, GLuint blue); -void ( APIENTRY *pglColor3uiv )(const GLuint *v); -void ( APIENTRY *pglColor3us )(GLushort red, GLushort green, GLushort blue); -void ( APIENTRY *pglColor3usv )(const GLushort *v); -void ( APIENTRY *pglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); -void ( APIENTRY *pglColor4bv )(const GLbyte *v); -void ( APIENTRY *pglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); -void ( APIENTRY *pglColor4dv )(const GLdouble *v); -void ( APIENTRY *pglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -void ( APIENTRY *pglColor4fv )(const GLfloat *v); -void ( APIENTRY *pglColor4i )(GLint red, GLint green, GLint blue, GLint alpha); -void ( APIENTRY *pglColor4iv )(const GLint *v); -void ( APIENTRY *pglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha); -void ( APIENTRY *pglColor4sv )(const GLshort *v); -void ( APIENTRY *pglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); -void ( APIENTRY *pglColor4ubv )(const GLubyte *v); -void ( APIENTRY *pglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha); -void ( APIENTRY *pglColor4uiv )(const GLuint *v); -void ( APIENTRY *pglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha); -void ( APIENTRY *pglColor4usv )(const GLushort *v); -void ( APIENTRY *pglColorMask )(GLqbooleanean red, GLqbooleanean green, GLqbooleanean blue, GLqbooleanean alpha); -void ( APIENTRY *pglColorMaterial )(GLenum face, GLenum mode); -void ( APIENTRY *pglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -void ( APIENTRY *pglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); -void ( APIENTRY *pglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border); -void ( APIENTRY *pglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -void ( APIENTRY *pglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); -void ( APIENTRY *pglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -void ( APIENTRY *pglCullFace )(GLenum mode); -void ( APIENTRY *pglDeleteLists )(GLuint list, GLsizei range); -void ( APIENTRY *pglDeleteTextures )(GLsizei n, const GLuint *textures); -void ( APIENTRY *pglDepthFunc )(GLenum func); -void ( APIENTRY *pglDepthMask )(GLqbooleanean flag); -void ( APIENTRY *pglDepthRange )(GLclampd zNear, GLclampd zFar); -void ( APIENTRY *pglDisable )(GLenum cap); -void ( APIENTRY *pglDisableClientState )(GLenum array); -void ( APIENTRY *pglDrawArrays )(GLenum mode, GLint first, GLsizei count); -void ( APIENTRY *pglDrawBuffer )(GLenum mode); -void ( APIENTRY *pglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -void ( APIENTRY *pglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -void ( APIENTRY *pglEdgeFlag )(GLqbooleanean flag); -void ( APIENTRY *pglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer); -void ( APIENTRY *pglEdgeFlagv )(const GLqbooleanean *flag); -void ( APIENTRY *pglEnable )(GLenum cap); -void ( APIENTRY *pglEnableClientState )(GLenum array); -void ( APIENTRY *pglEnd )(void); -void ( APIENTRY *pglEndList )(void); -void ( APIENTRY *pglEvalCoord1d )(GLdouble u); -void ( APIENTRY *pglEvalCoord1dv )(const GLdouble *u); -void ( APIENTRY *pglEvalCoord1f )(GLfloat u); -void ( APIENTRY *pglEvalCoord1fv )(const GLfloat *u); -void ( APIENTRY *pglEvalCoord2d )(GLdouble u, GLdouble v); -void ( APIENTRY *pglEvalCoord2dv )(const GLdouble *u); -void ( APIENTRY *pglEvalCoord2f )(GLfloat u, GLfloat v); -void ( APIENTRY *pglEvalCoord2fv )(const GLfloat *u); -void ( APIENTRY *pglEvalMesh1 )(GLenum mode, GLint i1, GLint i2); -void ( APIENTRY *pglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); -void ( APIENTRY *pglEvalPoint1 )(GLint i); -void ( APIENTRY *pglEvalPoint2 )(GLint i, GLint j); -void ( APIENTRY *pglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer); -void ( APIENTRY *pglFinish )(void); -void ( APIENTRY *pglFlush )(void); -void ( APIENTRY *pglFogf )(GLenum pname, GLfloat param); -void ( APIENTRY *pglFogfv )(GLenum pname, const GLfloat *params); -void ( APIENTRY *pglFogi )(GLenum pname, GLint param); -void ( APIENTRY *pglFogiv )(GLenum pname, const GLint *params); -void ( APIENTRY *pglFrontFace )(GLenum mode); -void ( APIENTRY *pglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -void ( APIENTRY *pglGenTextures )(GLsizei n, GLuint *textures); -void ( APIENTRY *pglGetBooleanv )(GLenum pname, GLqbooleanean *params); -void ( APIENTRY *pglGetClipPlane )(GLenum plane, GLdouble *equation); -void ( APIENTRY *pglGetDoublev )(GLenum pname, GLdouble *params); -void ( APIENTRY *pglGetFloatv )(GLenum pname, GLfloat *params); -void ( APIENTRY *pglGetIntegerv )(GLenum pname, GLint *params); -void ( APIENTRY *pglGetLightfv )(GLenum light, GLenum pname, GLfloat *params); -void ( APIENTRY *pglGetLightiv )(GLenum light, GLenum pname, GLint *params); -void ( APIENTRY *pglGetMapdv )(GLenum target, GLenum query, GLdouble *v); -void ( APIENTRY *pglGetMapfv )(GLenum target, GLenum query, GLfloat *v); -void ( APIENTRY *pglGetMapiv )(GLenum target, GLenum query, GLint *v); -void ( APIENTRY *pglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params); -void ( APIENTRY *pglGetMaterialiv )(GLenum face, GLenum pname, GLint *params); -void ( APIENTRY *pglGetPixelMapfv )(GLenum map, GLfloat *values); -void ( APIENTRY *pglGetPixelMapuiv )(GLenum map, GLuint *values); -void ( APIENTRY *pglGetPixelMapusv )(GLenum map, GLushort *values); -void ( APIENTRY *pglGetPointerv )(GLenum pname, GLvoid* *params); -void ( APIENTRY *pglGetPolygonStipple )(GLubyte *mask); -void ( APIENTRY *pglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params); -void ( APIENTRY *pglGetTexEnviv )(GLenum target, GLenum pname, GLint *params); -void ( APIENTRY *pglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params); -void ( APIENTRY *pglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params); -void ( APIENTRY *pglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params); -void ( APIENTRY *pglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels); -void ( APIENTRY *pglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params); -void ( APIENTRY *pglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params); -void ( APIENTRY *pglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params); -void ( APIENTRY *pglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params); -void ( APIENTRY *pglHint )(GLenum target, GLenum mode); -void ( APIENTRY *pglIndexMask )(GLuint mask); -void ( APIENTRY *pglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); -void ( APIENTRY *pglIndexd )(GLdouble c); -void ( APIENTRY *pglIndexdv )(const GLdouble *c); -void ( APIENTRY *pglIndexf )(GLfloat c); -void ( APIENTRY *pglIndexfv )(const GLfloat *c); -void ( APIENTRY *pglIndexi )(GLint c); -void ( APIENTRY *pglIndexiv )(const GLint *c); -void ( APIENTRY *pglIndexs )(GLshort c); -void ( APIENTRY *pglIndexsv )(const GLshort *c); -void ( APIENTRY *pglIndexub )(GLubyte c); -void ( APIENTRY *pglIndexubv )(const GLubyte *c); -void ( APIENTRY *pglInitNames )(void); -void ( APIENTRY *pglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer); -void ( APIENTRY *pglLightModelf )(GLenum pname, GLfloat param); -void ( APIENTRY *pglLightModelfv )(GLenum pname, const GLfloat *params); -void ( APIENTRY *pglLightModeli )(GLenum pname, GLint param); -void ( APIENTRY *pglLightModeliv )(GLenum pname, const GLint *params); -void ( APIENTRY *pglLightf )(GLenum light, GLenum pname, GLfloat param); -void ( APIENTRY *pglLightfv )(GLenum light, GLenum pname, const GLfloat *params); -void ( APIENTRY *pglLighti )(GLenum light, GLenum pname, GLint param); -void ( APIENTRY *pglLightiv )(GLenum light, GLenum pname, const GLint *params); -void ( APIENTRY *pglLineStipple )(GLint factor, GLushort pattern); -void ( APIENTRY *pglLineWidth )(GLfloat width); -void ( APIENTRY *pglListBase )(GLuint base); -void ( APIENTRY *pglLoadIdentity )(void); -void ( APIENTRY *pglLoadMatrixd )(const GLdouble *m); -void ( APIENTRY *pglLoadMatrixf )(const GLfloat *m); -void ( APIENTRY *pglLoadName )(GLuint name); -void ( APIENTRY *pglLogicOp )(GLenum opcode); -void ( APIENTRY *pglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points); -void ( APIENTRY *pglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points); -void ( APIENTRY *pglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); -void ( APIENTRY *pglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); -void ( APIENTRY *pglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2); -void ( APIENTRY *pglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2); -void ( APIENTRY *pglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); -void ( APIENTRY *pglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); -void ( APIENTRY *pglMaterialf )(GLenum face, GLenum pname, GLfloat param); -void ( APIENTRY *pglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params); -void ( APIENTRY *pglMateriali )(GLenum face, GLenum pname, GLint param); -void ( APIENTRY *pglMaterialiv )(GLenum face, GLenum pname, const GLint *params); -void ( APIENTRY *pglMatrixMode )(GLenum mode); -void ( APIENTRY *pglMultMatrixd )(const GLdouble *m); -void ( APIENTRY *pglMultMatrixf )(const GLfloat *m); -void ( APIENTRY *pglNewList )(GLuint list, GLenum mode); -void ( APIENTRY *pglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz); -void ( APIENTRY *pglNormal3bv )(const GLbyte *v); -void ( APIENTRY *pglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz); -void ( APIENTRY *pglNormal3dv )(const GLdouble *v); -void ( APIENTRY *pglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz); -void ( APIENTRY *pglNormal3fv )(const GLfloat *v); -void ( APIENTRY *pglNormal3i )(GLint nx, GLint ny, GLint nz); -void ( APIENTRY *pglNormal3iv )(const GLint *v); -void ( APIENTRY *pglNormal3s )(GLshort nx, GLshort ny, GLshort nz); -void ( APIENTRY *pglNormal3sv )(const GLshort *v); -void ( APIENTRY *pglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer); -void ( APIENTRY *pglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); -void ( APIENTRY *pglPassThrough )(GLfloat token); -void ( APIENTRY *pglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values); -void ( APIENTRY *pglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values); -void ( APIENTRY *pglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values); -void ( APIENTRY *pglPixelStoref )(GLenum pname, GLfloat param); -void ( APIENTRY *pglPixelStorei )(GLenum pname, GLint param); -void ( APIENTRY *pglPixelTransferf )(GLenum pname, GLfloat param); -void ( APIENTRY *pglPixelTransferi )(GLenum pname, GLint param); -void ( APIENTRY *pglPixelZoom )(GLfloat xfactor, GLfloat yfactor); -void ( APIENTRY *pglPointSize )(GLfloat size); -void ( APIENTRY *pglPolygonMode )(GLenum face, GLenum mode); -void ( APIENTRY *pglPolygonOffset )(GLfloat factor, GLfloat units); -void ( APIENTRY *pglPolygonStipple )(const GLubyte *mask); -void ( APIENTRY *pglPopAttrib )(void); -void ( APIENTRY *pglPopClientAttrib )(void); -void ( APIENTRY *pglPopMatrix )(void); -void ( APIENTRY *pglPopName )(void); -void ( APIENTRY *pglPushAttrib )(GLbitfield mask); -void ( APIENTRY *pglPushClientAttrib )(GLbitfield mask); -void ( APIENTRY *pglPushMatrix )(void); -void ( APIENTRY *pglPushName )(GLuint name); -void ( APIENTRY *pglRasterPos2d )(GLdouble x, GLdouble y); -void ( APIENTRY *pglRasterPos2dv )(const GLdouble *v); -void ( APIENTRY *pglRasterPos2f )(GLfloat x, GLfloat y); -void ( APIENTRY *pglRasterPos2fv )(const GLfloat *v); -void ( APIENTRY *pglRasterPos2i )(GLint x, GLint y); -void ( APIENTRY *pglRasterPos2iv )(const GLint *v); -void ( APIENTRY *pglRasterPos2s )(GLshort x, GLshort y); -void ( APIENTRY *pglRasterPos2sv )(const GLshort *v); -void ( APIENTRY *pglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z); -void ( APIENTRY *pglRasterPos3dv )(const GLdouble *v); -void ( APIENTRY *pglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z); -void ( APIENTRY *pglRasterPos3fv )(const GLfloat *v); -void ( APIENTRY *pglRasterPos3i )(GLint x, GLint y, GLint z); -void ( APIENTRY *pglRasterPos3iv )(const GLint *v); -void ( APIENTRY *pglRasterPos3s )(GLshort x, GLshort y, GLshort z); -void ( APIENTRY *pglRasterPos3sv )(const GLshort *v); -void ( APIENTRY *pglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); -void ( APIENTRY *pglRasterPos4dv )(const GLdouble *v); -void ( APIENTRY *pglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); -void ( APIENTRY *pglRasterPos4fv )(const GLfloat *v); -void ( APIENTRY *pglRasterPos4i )(GLint x, GLint y, GLint z, GLint w); -void ( APIENTRY *pglRasterPos4iv )(const GLint *v); -void ( APIENTRY *pglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w); -void ( APIENTRY *pglRasterPos4sv )(const GLshort *v); -void ( APIENTRY *pglReadBuffer )(GLenum mode); -void ( APIENTRY *pglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels); -void ( APIENTRY *pglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); -void ( APIENTRY *pglRectdv )(const GLdouble *v1, const GLdouble *v2); -void ( APIENTRY *pglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); -void ( APIENTRY *pglRectfv )(const GLfloat *v1, const GLfloat *v2); -void ( APIENTRY *pglRecti )(GLint x1, GLint y1, GLint x2, GLint y2); -void ( APIENTRY *pglRectiv )(const GLint *v1, const GLint *v2); -void ( APIENTRY *pglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2); -void ( APIENTRY *pglRectsv )(const GLshort *v1, const GLshort *v2); -void ( APIENTRY *pglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); -void ( APIENTRY *pglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); -void ( APIENTRY *pglScaled )(GLdouble x, GLdouble y, GLdouble z); -void ( APIENTRY *pglScalef )(GLfloat x, GLfloat y, GLfloat z); -void ( APIENTRY *pglScissor )(GLint x, GLint y, GLsizei width, GLsizei height); -void ( APIENTRY *pglSelectBuffer )(GLsizei size, GLuint *buffer); -void ( APIENTRY *pglShadeModel )(GLenum mode); -void ( APIENTRY *pglStencilFunc )(GLenum func, GLint ref, GLuint mask); -void ( APIENTRY *pglStencilMask )(GLuint mask); -void ( APIENTRY *pglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass); -void ( APIENTRY *pglTexCoord1d )(GLdouble s); -void ( APIENTRY *pglTexCoord1dv )(const GLdouble *v); -void ( APIENTRY *pglTexCoord1f )(GLfloat s); -void ( APIENTRY *pglTexCoord1fv )(const GLfloat *v); -void ( APIENTRY *pglTexCoord1i )(GLint s); -void ( APIENTRY *pglTexCoord1iv )(const GLint *v); -void ( APIENTRY *pglTexCoord1s )(GLshort s); -void ( APIENTRY *pglTexCoord1sv )(const GLshort *v); -void ( APIENTRY *pglTexCoord2d )(GLdouble s, GLdouble t); -void ( APIENTRY *pglTexCoord2dv )(const GLdouble *v); -void ( APIENTRY *pglTexCoord2f )(GLfloat s, GLfloat t); -void ( APIENTRY *pglTexCoord2fv )(const GLfloat *v); -void ( APIENTRY *pglTexCoord2i )(GLint s, GLint t); -void ( APIENTRY *pglTexCoord2iv )(const GLint *v); -void ( APIENTRY *pglTexCoord2s )(GLshort s, GLshort t); -void ( APIENTRY *pglTexCoord2sv )(const GLshort *v); -void ( APIENTRY *pglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r); -void ( APIENTRY *pglTexCoord3dv )(const GLdouble *v); -void ( APIENTRY *pglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r); -void ( APIENTRY *pglTexCoord3fv )(const GLfloat *v); -void ( APIENTRY *pglTexCoord3i )(GLint s, GLint t, GLint r); -void ( APIENTRY *pglTexCoord3iv )(const GLint *v); -void ( APIENTRY *pglTexCoord3s )(GLshort s, GLshort t, GLshort r); -void ( APIENTRY *pglTexCoord3sv )(const GLshort *v); -void ( APIENTRY *pglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q); -void ( APIENTRY *pglTexCoord4dv )(const GLdouble *v); -void ( APIENTRY *pglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q); -void ( APIENTRY *pglTexCoord4fv )(const GLfloat *v); -void ( APIENTRY *pglTexCoord4i )(GLint s, GLint t, GLint r, GLint q); -void ( APIENTRY *pglTexCoord4iv )(const GLint *v); -void ( APIENTRY *pglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q); -void ( APIENTRY *pglTexCoord4sv )(const GLshort *v); -void ( APIENTRY *pglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -void ( APIENTRY *pglTexEnvf )(GLenum target, GLenum pname, GLfloat param); -void ( APIENTRY *pglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params); -void ( APIENTRY *pglTexEnvi )(GLenum target, GLenum pname, GLint param); -void ( APIENTRY *pglTexEnviv )(GLenum target, GLenum pname, const GLint *params); -void ( APIENTRY *pglTexGend )(GLenum coord, GLenum pname, GLdouble param); -void ( APIENTRY *pglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params); -void ( APIENTRY *pglTexGenf )(GLenum coord, GLenum pname, GLfloat param); -void ( APIENTRY *pglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params); -void ( APIENTRY *pglTexGeni )(GLenum coord, GLenum pname, GLint param); -void ( APIENTRY *pglTexGeniv )(GLenum coord, GLenum pname, const GLint *params); -void ( APIENTRY *pglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -void ( APIENTRY *pglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -void ( APIENTRY *pglTexParameterf )(GLenum target, GLenum pname, GLfloat param); -void ( APIENTRY *pglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params); -void ( APIENTRY *pglTexParameteri )(GLenum target, GLenum pname, GLint param); -void ( APIENTRY *pglTexParameteriv )(GLenum target, GLenum pname, const GLint *params); -void ( APIENTRY *pglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels); -void ( APIENTRY *pglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -void ( APIENTRY *pglTranslated )(GLdouble x, GLdouble y, GLdouble z); -void ( APIENTRY *pglTranslatef )(GLfloat x, GLfloat y, GLfloat z); -void ( APIENTRY *pglVertex2d )(GLdouble x, GLdouble y); -void ( APIENTRY *pglVertex2dv )(const GLdouble *v); -void ( APIENTRY *pglVertex2f )(GLfloat x, GLfloat y); -void ( APIENTRY *pglVertex2fv )(const GLfloat *v); -void ( APIENTRY *pglVertex2i )(GLint x, GLint y); -void ( APIENTRY *pglVertex2iv )(const GLint *v); -void ( APIENTRY *pglVertex2s )(GLshort x, GLshort y); -void ( APIENTRY *pglVertex2sv )(const GLshort *v); -void ( APIENTRY *pglVertex3d )(GLdouble x, GLdouble y, GLdouble z); -void ( APIENTRY *pglVertex3dv )(const GLdouble *v); -void ( APIENTRY *pglVertex3f )(GLfloat x, GLfloat y, GLfloat z); -void ( APIENTRY *pglVertex3fv )(const GLfloat *v); -void ( APIENTRY *pglVertex3i )(GLint x, GLint y, GLint z); -void ( APIENTRY *pglVertex3iv )(const GLint *v); -void ( APIENTRY *pglVertex3s )(GLshort x, GLshort y, GLshort z); -void ( APIENTRY *pglVertex3sv )(const GLshort *v); -void ( APIENTRY *pglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w); -void ( APIENTRY *pglVertex4dv )(const GLdouble *v); -void ( APIENTRY *pglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w); -void ( APIENTRY *pglVertex4fv )(const GLfloat *v); -void ( APIENTRY *pglVertex4i )(GLint x, GLint y, GLint z, GLint w); -void ( APIENTRY *pglVertex4iv )(const GLint *v); -void ( APIENTRY *pglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w); -void ( APIENTRY *pglVertex4sv )(const GLshort *v); -void ( APIENTRY *pglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -void ( APIENTRY *pglViewport )(GLint x, GLint y, GLsizei width, GLsizei height); -void ( APIENTRY *pglPointParameterfEXT)( GLenum param, GLfloat value ); -void ( APIENTRY *pglPointParameterfvEXT)( GLenum param, const GLfloat *value ); -void ( APIENTRY *pglLockArraysEXT) (int , int); -void ( APIENTRY *pglUnlockArraysEXT) (void); -void ( APIENTRY *pglActiveTextureARB)( GLenum ); -void ( APIENTRY *pglClientActiveTextureARB)( GLenum ); -void ( APIENTRY *pglGetCompressedTexImage)( GLenum target, GLint lod, const GLvoid* data ); -void ( APIENTRY *pglDrawRangeElements)( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices ); -void ( APIENTRY *pglDrawRangeElementsEXT)( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices ); -void ( APIENTRY *pglDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -void ( APIENTRY *pglVertexPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -void ( APIENTRY *pglNormalPointer)(GLenum type, GLsizei stride, const GLvoid *ptr); -void ( APIENTRY *pglColorPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -void ( APIENTRY *pglTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); -void ( APIENTRY *pglArrayElement)(GLint i); -void ( APIENTRY *pglMultiTexCoord1f) (GLenum, GLfloat); -void ( APIENTRY *pglMultiTexCoord2f) (GLenum, GLfloat, GLfloat); -void ( APIENTRY *pglMultiTexCoord3f) (GLenum, GLfloat, GLfloat, GLfloat); -void ( APIENTRY *pglMultiTexCoord4f) (GLenum, GLfloat, GLfloat, GLfloat, GLfloat); -void ( APIENTRY *pglActiveTexture) (GLenum); -void ( APIENTRY *pglClientActiveTexture) (GLenum); -void ( APIENTRY *pglCompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); -void ( APIENTRY *pglCompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); -void ( APIENTRY *pglCompressedTexImage1DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); -void ( APIENTRY *pglCompressedTexSubImage3DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); -void ( APIENTRY *pglCompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); -void ( APIENTRY *pglCompressedTexSubImage1DARB)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); -void ( APIENTRY *pglDeleteObjectARB)(GLhandleARB obj); -GLhandleARB ( APIENTRY *pglGetHandleARB)(GLenum pname); -void ( APIENTRY *pglDetachObjectARB)(GLhandleARB containerObj, GLhandleARB attachedObj); -GLhandleARB ( APIENTRY *pglCreateShaderObjectARB)(GLenum shaderType); -void ( APIENTRY *pglShaderSourceARB)(GLhandleARB shaderObj, GLsizei count, const GLcharARB **string, const GLint *length); -void ( APIENTRY *pglCompileShaderARB)(GLhandleARB shaderObj); -GLhandleARB ( APIENTRY *pglCreateProgramObjectARB)(void); -void ( APIENTRY *pglAttachObjectARB)(GLhandleARB containerObj, GLhandleARB obj); -void ( APIENTRY *pglLinkProgramARB)(GLhandleARB programObj); -void ( APIENTRY *pglUseProgramObjectARB)(GLhandleARB programObj); -void ( APIENTRY *pglValidateProgramARB)(GLhandleARB programObj); -void ( APIENTRY *pglBindProgramARB)(GLenum target, GLuint program); -void ( APIENTRY *pglDeleteProgramsARB)(GLsizei n, const GLuint *programs); -void ( APIENTRY *pglGenProgramsARB)(GLsizei n, GLuint *programs); -void ( APIENTRY *pglProgramStringARB)(GLenum target, GLenum format, GLsizei len, const GLvoid *string); -void ( APIENTRY *pglProgramEnvParameter4fARB)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -void ( APIENTRY *pglProgramLocalParameter4fARB)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -void ( APIENTRY *pglUniform1fARB)(GLint location, GLfloat v0); -void ( APIENTRY *pglUniform2fARB)(GLint location, GLfloat v0, GLfloat v1); -void ( APIENTRY *pglUniform3fARB)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -void ( APIENTRY *pglUniform4fARB)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -void ( APIENTRY *pglUniform1iARB)(GLint location, GLint v0); -void ( APIENTRY *pglUniform2iARB)(GLint location, GLint v0, GLint v1); -void ( APIENTRY *pglUniform3iARB)(GLint location, GLint v0, GLint v1, GLint v2); -void ( APIENTRY *pglUniform4iARB)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -void ( APIENTRY *pglUniform1fvARB)(GLint location, GLsizei count, const GLfloat *value); -void ( APIENTRY *pglUniform2fvARB)(GLint location, GLsizei count, const GLfloat *value); -void ( APIENTRY *pglUniform3fvARB)(GLint location, GLsizei count, const GLfloat *value); -void ( APIENTRY *pglUniform4fvARB)(GLint location, GLsizei count, const GLfloat *value); -void ( APIENTRY *pglUniform1ivARB)(GLint location, GLsizei count, const GLint *value); -void ( APIENTRY *pglUniform2ivARB)(GLint location, GLsizei count, const GLint *value); -void ( APIENTRY *pglUniform3ivARB)(GLint location, GLsizei count, const GLint *value); -void ( APIENTRY *pglUniform4ivARB)(GLint location, GLsizei count, const GLint *value); -void ( APIENTRY *pglUniformMatrix2fvARB)(GLint location, GLsizei count, GLqbooleanean transpose, const GLfloat *value); -void ( APIENTRY *pglUniformMatrix3fvARB)(GLint location, GLsizei count, GLqbooleanean transpose, const GLfloat *value); -void ( APIENTRY *pglUniformMatrix4fvARB)(GLint location, GLsizei count, GLqbooleanean transpose, const GLfloat *value); -void ( APIENTRY *pglGetObjectParameterfvARB)(GLhandleARB obj, GLenum pname, GLfloat *params); -void ( APIENTRY *pglGetObjectParameterivARB)(GLhandleARB obj, GLenum pname, GLint *params); -void ( APIENTRY *pglGetInfoLogARB)(GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog); -void ( APIENTRY *pglGetAttachedObjectsARB)(GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj); -GLint ( APIENTRY *pglGetUniformLocationARB)(GLhandleARB programObj, const GLcharARB *name); -void ( APIENTRY *pglGetActiveUniformARB)(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); -void ( APIENTRY *pglGetUniformfvARB)(GLhandleARB programObj, GLint location, GLfloat *params); -void ( APIENTRY *pglGetUniformivARB)(GLhandleARB programObj, GLint location, GLint *params); -void ( APIENTRY *pglGetShaderSourceARB)(GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *source); -void ( APIENTRY *pglPolygonStipple)(const GLubyte *mask); -void ( APIENTRY *pglTexImage3D)( GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels ); -void ( APIENTRY *pglTexSubImage3D)( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels ); -void ( APIENTRY *pglCopyTexSubImage3D)( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ); -void ( APIENTRY *pglBlendEquationEXT)(GLenum); -void ( APIENTRY *pglStencilOpSeparate)(GLenum, GLenum, GLenum, GLenum); -void ( APIENTRY *pglStencilFuncSeparate)(GLenum, GLenum, GLint, GLuint); -void ( APIENTRY *pglActiveStencilFaceEXT)(GLenum); -void ( APIENTRY *pglVertexAttribPointerARB)(GLuint index, GLint size, GLenum type, GLqbooleanean normalized, GLsizei stride, const GLvoid *pointer); -void ( APIENTRY *pglEnableVertexAttribArrayARB)(GLuint index); -void ( APIENTRY *pglDisableVertexAttribArrayARB)(GLuint index); -void ( APIENTRY *pglBindAttribLocationARB)(GLhandleARB programObj, GLuint index, const GLcharARB *name); -void ( APIENTRY *pglGetActiveAttribARB)(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name); -GLint ( APIENTRY *pglGetAttribLocationARB)(GLhandleARB programObj, const GLcharARB *name); -void ( APIENTRY *pglBindBufferARB) (GLenum target, GLuint buffer); -void ( APIENTRY *pglDeleteBuffersARB) (GLsizei n, const GLuint *buffers); -void ( APIENTRY *pglGenBuffersARB) (GLsizei n, GLuint *buffers); -GLqbooleanean ( APIENTRY *pglIsBufferARB) (GLuint buffer); -GLvoid* ( APIENTRY *pglMapBufferARB) (GLenum target, GLenum access); -GLqbooleanean ( APIENTRY *pglUnmapBufferARB) (GLenum target); -void ( APIENTRY *pglBufferDataARB) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); -void ( APIENTRY *pglBufferSubDataARB) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); -void ( APIENTRY *pglGenQueriesARB) (GLsizei n, GLuint *ids); -void ( APIENTRY *pglDeleteQueriesARB) (GLsizei n, const GLuint *ids); -GLqbooleanean ( APIENTRY *pglIsQueryARB) (GLuint id); -void ( APIENTRY *pglBeginQueryARB) (GLenum target, GLuint id); -void ( APIENTRY *pglEndQueryARB) (GLenum target); -void ( APIENTRY *pglGetQueryivARB) (GLenum target, GLenum pname, GLint *params); -void ( APIENTRY *pglGetQueryObjectivARB) (GLuint id, GLenum pname, GLint *params); -void ( APIENTRY *pglGetQueryObjectuivARB) (GLuint id, GLenum pname, GLuint *params); -void ( APIENTRY * pglSelectTextureSGIS) ( GLenum ); -void ( APIENTRY * pglMTexCoord2fSGIS) ( GLenum, GLfloat, GLfloat ); -void ( APIENTRY * pglSwapInterval) ( int interval ); - -extern void *pglGetProcAddress( const GLubyte * ); -const char *(*pglGetGLWExtensionsString)( void ); - -// -// r_backend.c -// -extern void pglPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ); - -const char * ( WINAPI * pwglGetExtensionsStringEXT )( void ); -int ( WINAPI * pwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *); -int ( WINAPI * pwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); -int ( WINAPI * pwglGetPixelFormat)(HDC); -BOOL ( WINAPI * pwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *); -BOOL ( WINAPI * pwglSwapBuffers)(HDC); -BOOL ( WINAPI * pwglCopyContext)(HGLRC, HGLRC, UINT); -HGLRC ( WINAPI * pwglCreateContext)(HDC); -HGLRC ( WINAPI * pwglCreateLayerContext)(HDC, int); -BOOL ( WINAPI * pwglDeleteContext)(HGLRC); -HGLRC ( WINAPI * pwglGetCurrentContext)(VOID); -HDC ( WINAPI * pwglGetCurrentDC)(VOID); -PROC ( WINAPI * pwglGetProcAddress)(LPCSTR); -BOOL ( WINAPI * pwglMakeCurrent)(HDC, HGLRC); -BOOL ( WINAPI * pwglShareLists)(HGLRC, HGLRC); -BOOL ( WINAPI * pwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD); -BOOL ( WINAPI * pwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT, FLOAT, int, LPGLYPHMETRICSFLOAT); -BOOL ( WINAPI * pwglDescribeLayerPlane)(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR); -int ( WINAPI * pwglSetLayerPaletteEntries)(HDC, int, int, int, CONST COLORREF *); -int ( WINAPI * pwglGetLayerPaletteEntries)(HDC, int, int, int, COLORREF *); -BOOL ( WINAPI * pwglRealizeLayerPalette)(HDC, int, BOOL); -BOOL ( WINAPI * pwglSwapLayerBuffers)(HDC, UINT); -BOOL ( WINAPI * pwglSwapIntervalEXT)( int interval ); -BOOL ( WINAPI * pwglGetDeviceGammaRampEXT ) ( unsigned char *pRed, unsigned char *pGreen, unsigned char *pBlue ); -BOOL ( WINAPI * pwglSetDeviceGammaRampEXT ) ( const unsigned char *pRed, const unsigned char *pGreen, const unsigned char *pBlue ); -BOOL ( WINAPI * pwglGetDeviceGammaRamp3DFX )( HDC, WORD * ); -BOOL ( WINAPI * pwglSetDeviceGammaRamp3DFX )( HDC, WORD * ); - -enum -{ - GL_TEXTURE0 = 0, - GL_TEXTURE1, - GL_TEXTURE2, - GL_TEXTURE3 -}; - -typedef struct -{ - HINSTANCE hInst; - void *wndproc; - - HDC hDC; // handle to device context - HWND hWnd; // handle to window - HGLRC hGLRC; // handle to GL rendering context - - HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library - - int desktopBitsPixel; - int desktopWidth; - int desktopHeight; - - qboolean software; // software emulation uses RB_RenderShader() - qboolean initialized; // OpenGL subsystem started - qboolean minidriver; - int developer; // engine developer level; - -} glwstate_t; - -extern glwstate_t glw_state; - -#endif//R_OPENGL_H \ No newline at end of file diff --git a/vid_gl/r_poly.c b/vid_gl/r_poly.c deleted file mode 100644 index 3609e17b..00000000 --- a/vid_gl/r_poly.c +++ /dev/null @@ -1,456 +0,0 @@ -/* -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// r_poly.c - handles fragments and arbitrary polygons - -#include "r_local.h" -#include "mathlib.h" -#include "matrix_lib.h" - -static mesh_t poly_mesh; - -/* -================= -R_PushPoly -================= -*/ -void R_PushPoly( const meshbuffer_t *mb ) -{ - poly_t *p; - ref_shader_t *shader; - int i, j, features; - - MB_NUM2SHADER( mb->shaderkey, shader ); - - features = ( shader->features|MF_TRIFAN ); - - for( i = -mb->infokey-1, p = r_polys + i; i < mb->lastPoly; i++, p++ ) - { - poly_mesh.numVerts = p->numverts; - poly_mesh.vertexArray = inVertsArray; - poly_mesh.normalsArray = inNormalsArray; - poly_mesh.stCoordArray = p->stcoords; - poly_mesh.colorsArray = p->colors; - - for( j = 0; j < p->numverts; j++ ) - { - Vector4Set( inVertsArray[r_backacc.numVerts+j], p->verts[j][0], p->verts[j][1], p->verts[j][2], 1 ); - VectorCopy( p->normal, inNormalsArray[r_backacc.numVerts+j] ); - } - - R_PushMesh( &poly_mesh, features ); - } -} - -/* -================= -R_AddPolysToList -================= -*/ -void R_AddPolysToList( void ) -{ - uint i, nverts = 0; - int fognum = -1; - mfog_t *fog, *lastFog = NULL; - meshbuffer_t *mb = NULL; - ref_shader_t *shader; - vec3_t lastNormal = { 0, 0, 0 }; - poly_t *p; - - RI.currententity = r_worldent; - - for( i = 0, p = r_polys; i < r_numPolys; nverts += p->numverts, mb->lastPoly++, i++, p++ ) - { - shader = p->shader; - if( p->fognum < 0 ) fognum = -1; - else if( p->fognum ) fognum = bound( 1, p->fognum, r_worldbrushmodel->numfogs + 1 ); - else fognum = r_worldbrushmodel->numfogs ? 0 : -1; - - if( fognum == -1 ) fog = NULL; - else if( !fognum ) fog = R_FogForSphere( p->verts[0], 0 ); - else fog = r_worldbrushmodel->fogs + fognum - 1; - - // we ignore SHADER_ENTITY_MERGABLE here because polys are just regular trifans - if( !mb || mb->shaderkey != (int)shader->sortkey - || lastFog != fog || nverts + p->numverts > MAX_ARRAY_VERTS - || (( shader->flags & SHADER_MATERIAL ) && !VectorCompare( p->normal, lastNormal ))) - { - nverts = 0; - lastFog = fog; - VectorCopy( p->normal, lastNormal ); - - mb = R_AddMeshToList( MB_POLY, fog, shader, -( (signed int)i+1 ) ); - mb->lastPoly = i; - } - } -} - -//================================================================================== - -static int r_fragmentframecount; -static vec3_t trace_start, trace_end; -static vec3_t trace_absmins, trace_absmaxs; -static float trace_fraction; - -static vec3_t trace_impact; -static mplane_t trace_plane; -static msurface_t *trace_surface; -static int trace_hitbox; - -/* -================= -R_TraceAgainstTriangle - -Ray-triangle intersection as per -http://geometryalgorithms.com/Archive/algorithm_0105/algorithm_0105.htm -(original paper by Dan Sunday) -================= -*/ -static void R_TraceAgainstTriangle( const vec_t *a, const vec_t *b, const vec_t *c ) -{ - const vec_t *p1 = trace_start, *p2 = trace_end, *p0 = a; - vec3_t u, v, w, n, p; - float d1, d2, d, frac; - float uu, uv, vv, wu, wv, s, t; - - // calculate two mostly perpendicular edge directions - VectorSubtract( b, p0, u ); - VectorSubtract( c, p0, v ); - - // we have two edge directions, we can calculate the normal - CrossProduct( v, u, n ); - if( VectorCompare( n, vec3_origin ) ) - return; // degenerate triangle - - VectorSubtract( p2, p1, p ); - VectorSubtract( p1, p0, w ); - - d1 = -DotProduct( n, w ); - d2 = DotProduct( n, p ); - if( fabs( d2 ) < 0.0001 ) - return; - - // get intersect point of ray with triangle plane - frac = (d1) / d2; - if( frac <= 0 ) return; - if( frac >= trace_fraction ) - return; // we have hit something earlier - - // calculate the impact point - VectorLerp( p1, frac, p2, p ); - - // does p lie inside triangle? - uu = DotProduct( u, u ); - uv = DotProduct( u, v ); - vv = DotProduct( v, v ); - - VectorSubtract( p, p0, w ); - wu = DotProduct( w, u ); - wv = DotProduct( w, v ); - d = uv * uv - uu * vv; - - // get and test parametric coords - - s = (uv * wv - vv * wu) / d; - if( s < 0.0 || s > 1.0 ) - return; // p is outside - - t = (uv * wu - uu * wv) / d; - if( t < 0.0 || (s + t) > 1.0 ) - return; // p is outside - - trace_fraction = frac; - VectorCopy( p, trace_impact ); - VectorCopy( n, trace_plane.normal ); -} - -/* -================= -R_TraceAgainstSurface -================= -*/ -static qboolean R_TraceAgainstSurface( msurface_t *surf ) -{ - int i; - mesh_t *mesh; - elem_t *elem; - vec4_t *verts; - float old_frac = trace_fraction; - - if( !surf ) return false; - mesh = surf->mesh; - if( !mesh ) return false; - elem = mesh->elems; - if( !elem ) return false; - verts = mesh->vertexArray; - if( !verts ) return false; - - // clip each triangle individually - for( i = 0; i < mesh->numElems; i += 3, elem += 3 ) - { - R_TraceAgainstTriangle( verts[elem[0]], verts[elem[1]], verts[elem[2]] ); - if( old_frac > trace_fraction ) - { - // flip normal is we are on the backside (does it really happen?)... - if( DotProduct( trace_plane.normal, surf->plane->normal ) < 0 ) - VectorNegate( trace_plane.normal, trace_plane.normal ); - return true; - } - } - return false; -} - -/* -================= -R_TraceAgainstLeaf -================= -*/ -static int R_TraceAgainstLeaf( mleaf_t *leaf ) -{ - msurface_t *surf, **mark; - int i; - - if( leaf->contents == CONTENTS_SOLID ) - return 1; // solid leaf - - mark = leaf->firstMarkSurface; - - for( i = 0, mark = leaf->firstMarkSurface; i < leaf->numMarkSurfaces; i++, mark++ ) - { - surf = *mark; - - if( surf->fragmentframe == r_fragmentframecount ) - continue; // do not test the same surface more than once - surf->fragmentframe = r_fragmentframecount; - - if( surf->mesh ) - { - if( R_TraceAgainstSurface( surf ) ) - trace_surface = surf; // impact surface - } - } - return 0; -} - -/* -================= -R_TraceAgainstBmodel -================= -*/ -static int R_TraceAgainstBmodel( mbrushmodel_t *bmodel ) -{ - int i; - msurface_t *surf; - - for( i = 0; i < bmodel->nummodelsurfaces; i++ ) - { - surf = bmodel->firstmodelsurface + i; - - if( R_TraceAgainstSurface( surf ) ) - trace_surface = surf; // impact point - } - - return 0; -} - -/* -================= -R_RecursiveHullCheck -================= -*/ -static int R_RecursiveHullCheck( mnode_t *node, const vec3_t start, const vec3_t end ) -{ - int side, r; - float t1, t2; - float frac; - vec3_t mid; - const vec_t *p1 = start, *p2 = end; - mplane_t *plane; - -loc0: - plane = node->plane; - if( !plane ) - return R_TraceAgainstLeaf( ( mleaf_t * )node ); - - if( plane->type < 3 ) - { - t1 = p1[plane->type] - plane->dist; - t2 = p2[plane->type] - plane->dist; - } - else - { - t1 = DotProduct( plane->normal, p1 ) - plane->dist; - t2 = DotProduct( plane->normal, p2 ) - plane->dist; - } - - if( t1 >= -ON_EPSILON && t2 >= -ON_EPSILON ) - { - node = node->children[0]; - goto loc0; - } - - if( t1 < ON_EPSILON && t2 < ON_EPSILON ) - { - node = node->children[1]; - goto loc0; - } - - side = t1 < 0; - frac = t1 / (t1 - t2); - VectorLerp( p1, frac, p2, mid ); - - r = R_RecursiveHullCheck( node->children[side], p1, mid ); - if( r ) - return r; - - return R_RecursiveHullCheck( node->children[!side], mid, p2 ); -} - -/* -================= -R_TraceLine -================= -*/ -msurface_t *R_TransformedTraceLine( pmtrace_t *tr, const vec3_t start, const vec3_t end, ref_entity_t *test, int flags ) -{ - ref_model_t *model; - - r_fragmentframecount++; // for multi-check avoidance - - // fill in a default trace - Mem_Set( tr, 0, sizeof( pmtrace_t )); - - trace_hitbox = -1; - trace_surface = NULL; - trace_fraction = 1.0f; - VectorCopy( end, trace_impact ); - Mem_Set( &trace_plane, 0, sizeof( trace_plane )); - - // skip glass ents - if(( flags & FTRACE_IGNORE_GLASS ) && test->rendermode != kRenderNormal && test->renderamt < 200 ) - { - tr->fraction = trace_fraction; - VectorCopy( trace_impact, tr->endpos ); - - return trace_surface; - } - - ClearBounds( trace_absmins, trace_absmaxs ); - AddPointToBounds( start, trace_absmins, trace_absmaxs ); - AddPointToBounds( end, trace_absmins, trace_absmaxs ); - - model = test->model; - if( model ) - { - if( model->type == mod_world || model->type == mod_brush || model->type == mod_studio ) - { - mbrushmodel_t *bmodel = (mbrushmodel_t *)model->extradata; - qboolean rotated = !Matrix3x3_Compare( test->axis, matrix3x3_identity ); - vec3_t temp, start_l, end_l, axis[3]; - vec3_t model_mins, model_maxs; - float v, max = 0.0f; - int i; - - // transform - VectorSubtract( start, test->origin, start_l ); - VectorSubtract( end, test->origin, end_l ); - - if( rotated ) - { - VectorCopy( start_l, temp ); - Matrix3x3_Transform( test->axis, temp, start_l ); - VectorCopy( end_l, temp ); - Matrix3x3_Transform( test->axis, temp, end_l ); - - // expand mins/maxs for rotation - for( i = 0; i < 3; i++ ) - { - v = fabs( model->mins[i] ); - if( v > max ) max = v; - v = fabs( model->maxs[i] ); - if( v > max ) max = v; - } - - for( i = 0; i < 3; i++ ) - { - model_mins[i] = test->origin[i] - max; - model_maxs[i] = test->origin[i] + max; - } - - } - else - { - VectorAdd( test->origin, model->mins, model_mins ); - VectorAdd( test->origin, model->maxs, model_maxs ); - } - - VectorCopy( start_l, trace_start ); - VectorCopy( end_l, trace_end ); - - // world uses a recursive approach using BSP tree, submodels - // just walk the list of surfaces linearly - if( model->type == mod_world ) - R_RecursiveHullCheck( bmodel->nodes, start_l, end_l ); - else if( BoundsIntersect( model_mins, model_maxs, trace_absmins, trace_absmaxs )) - { - if( model->type == mod_brush ) - R_TraceAgainstBmodel( bmodel ); - else if( model->type == mod_studio ) - { - pmtrace_t tr; - - if( R_StudioTrace( test, trace_start, trace_end, &tr )) - { - VectorCopy( tr.endpos, trace_impact ); - VectorCopy( tr.plane.normal, trace_plane.normal ); - trace_fraction = tr.fraction; - trace_hitbox = tr.hitgroup; - } - } - } - - // transform back - if( rotated && trace_fraction != 1 ) - { - Matrix3x3_Transpose( axis, test->axis ); - VectorCopy( tr->plane.normal, temp ); - Matrix3x3_Transform( axis, temp, trace_plane.normal ); - } - } - } - - // calculate the impact plane, if any - if( trace_fraction < 1.0f ) - { - VectorNormalize( trace_plane.normal ); - trace_plane.dist = DotProduct( trace_plane.normal, trace_impact ); - CategorizePlane( &trace_plane ); - - tr->plane.dist = trace_plane.dist; - VectorCopy( trace_plane.normal, tr->plane.normal ); - tr->ent = test - r_entities; - } - - tr->hitgroup = trace_hitbox; - tr->fraction = trace_fraction; - VectorCopy( trace_impact, tr->endpos ); - - return trace_surface; -} diff --git a/vid_gl/r_program.c b/vid_gl/r_program.c deleted file mode 100644 index b149ad82..00000000 --- a/vid_gl/r_program.c +++ /dev/null @@ -1,1139 +0,0 @@ -/* -Copyright (C) 2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// r_program.c - OpenGL Shading Language support - -#include "r_local.h" - -#define APPLICATION "Xash3D" -#define MAX_GLSL_PROGRAMS 1024 -#define R_GLSLProgramCopyString( str ) com.stralloc( r_glslProgramsPool, str, __FILE__, __LINE__ ) - -typedef struct -{ - int bit; - const char *define; - const char *suffix; -} glsl_feature_t; - -typedef struct -{ - char *name; - uint features; - const char *string; - - int object; - int vertexShader; - int fragmentShader; - - int locEyeOrigin; - int locLightDir; - int locLightOrigin; - int locLightAmbient; - int locLightDiffuse; - int locGlossIntensity; - int locGlossExponent; - int locOffsetMappingScale; - int locFrontPlane; - int locTextureWidth; - int locTextureHeight; - int locProjDistance; - int locDeluxemapOffset[LM_STYLES]; - int loclsColor[LM_STYLES]; -} glsl_program_t; - -static glsl_program_t r_glslprograms[MAX_GLSL_PROGRAMS]; -static byte *r_glslProgramsPool; - -static void R_GetProgramUniformLocations( glsl_program_t *program ); - -static const char *r_defaultGLSLProgram; -static const char *r_defaultDistortionGLSLProgram; -static const char *r_defaultShadowmapGLSLProgram; - -/* -================ -R_InitGLSLPrograms -================ -*/ -void R_InitGLSLPrograms( void ) -{ - int features = 0; - - Mem_Set( r_glslprograms, 0, sizeof( r_glslprograms )); - - if( !GL_Support( R_SHADER_GLSL100_EXT )) - return; - - r_glslProgramsPool = Mem_AllocPool( "GLSL Programs" ); - - if( GL_Support( R_GLSL_BRANCHING )) - features |= PROGRAM_APPLY_BRANCHING; - if( GL_Support( R_GLSL_NO_HALF_TYPES )) - features |= PROGRAM_APPLY_NO_HALF_TYPES; - - // register programs that are most likely to be used - R_RegisterGLSLProgram( DEFAULT_GLSL_PROGRAM, NULL, 0|features ); - R_RegisterGLSLProgram( DEFAULT_GLSL_PROGRAM, NULL, PROGRAM_APPLY_FB_LIGHTMAP|PROGRAM_APPLY_LIGHTSTYLE0|features ); - R_RegisterGLSLProgram( DEFAULT_GLSL_PROGRAM, NULL, PROGRAM_APPLY_FB_LIGHTMAP|PROGRAM_APPLY_LIGHTSTYLE0|PROGRAM_APPLY_SPECULAR|features ); - R_RegisterGLSLProgram( DEFAULT_GLSL_PROGRAM, NULL, PROGRAM_APPLY_FB_LIGHTMAP|PROGRAM_APPLY_LIGHTSTYLE0 - |PROGRAM_APPLY_SPECULAR|PROGRAM_APPLY_AMBIENT_COMPENSATION|features ); - - R_RegisterGLSLProgram( DEFAULT_GLSL_PROGRAM, NULL, PROGRAM_APPLY_DIRECTIONAL_LIGHT|features ); -// R_RegisterGLSLProgram( DEFAULT_GLSL_PROGRAM, NULL, PROGRAM_APPLY_DIRECTIONAL_LIGHT|PROGRAM_APPLY_SPECULAR|features ); - R_RegisterGLSLProgram( DEFAULT_GLSL_PROGRAM, NULL, PROGRAM_APPLY_DIRECTIONAL_LIGHT|PROGRAM_APPLY_OFFSETMAPPING|features ); - - R_RegisterGLSLProgram( DEFAULT_GLSL_DISTORTION_PROGRAM, r_defaultDistortionGLSLProgram, 0|features ); - - R_RegisterGLSLProgram( DEFAULT_GLSL_SHADOWMAP_PROGRAM, r_defaultShadowmapGLSLProgram, 0|features ); -} - -/* -================ -R_DeleteGLSLProgram -================ -*/ -static void R_DeleteGLSLProgram( glsl_program_t *program ) -{ - if( program->vertexShader ) - { - pglDetachObjectARB( program->object, program->vertexShader ); - pglDeleteObjectARB( program->vertexShader ); - program->vertexShader = 0; - } - - if( program->fragmentShader ) - { - pglDetachObjectARB( program->object, program->fragmentShader ); - pglDeleteObjectARB( program->fragmentShader ); - program->fragmentShader = 0; - } - - if( program->object ) - pglDeleteObjectARB( program->object ); - - if( program->name ) - Mem_Free( program->name ); - - Mem_Set( program, 0, sizeof( glsl_program_t )); -} - -/* -================ -R_CompileGLSLShader -================ -*/ -static int R_CompileGLSLShader( int program, const char *programName, const char *shaderName, int shaderType, const char **strings, int numStrings ) -{ - int shader, compiled; - - shader = pglCreateShaderObjectARB( (GLenum)shaderType ); - if( !shader ) - return 0; - - // if lengths is NULL, then each string is assumed to be null-terminated - pglShaderSourceARB( shader, numStrings, strings, NULL ); - pglCompileShaderARB( shader ); - pglGetObjectParameterivARB( shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled ); - - if( !compiled ) - { - char log[4096]; - - pglGetInfoLogARB( shader, sizeof( log ) - 1, NULL, log ); - log[sizeof( log ) - 1] = 0; - - if( log[0] ) - MsgDev( D_ERROR, "Failed to compile %s shader for program %s:\n%s\n", shaderName, programName, log ); - - pglDeleteObjectARB( shader ); - return 0; - } - - pglAttachObjectARB( program, shader ); - - return shader; -} - -/* -================ -R_FindGLSLProgram -================ -*/ -int R_FindGLSLProgram( const char *name ) -{ - int i; - glsl_program_t *program; - - for( i = 0, program = r_glslprograms; i < MAX_GLSL_PROGRAMS; i++, program++ ) - { - if( !program->name ) - break; - if( !com.stricmp( program->name, name ) ) - return ( i+1 ); - } - - return 0; -} - -#define MAX_DEFINES_FEATURES 255 - -static const glsl_feature_t glsl_features[] = -{ -{ PROGRAM_APPLY_LIGHTSTYLE0, "#define APPLY_LIGHTSTYLE0\n", "_ls0" }, -{ PROGRAM_APPLY_FB_LIGHTMAP, "#define APPLY_FBLIGHTMAP\n", "_fb" }, -{ PROGRAM_APPLY_LIGHTSTYLE1, "#define APPLY_LIGHTSTYLE1\n", "_ls1" }, -{ PROGRAM_APPLY_LIGHTSTYLE2, "#define APPLY_LIGHTSTYLE2\n", "_ls2" }, -{ PROGRAM_APPLY_LIGHTSTYLE3, "#define APPLY_LIGHTSTYLE3\n", "_ls3" }, -{ PROGRAM_APPLY_DIRECTIONAL_LIGHT, "#define APPLY_DIRECTIONAL_LIGHT\n", "_dirlight" }, -{ PROGRAM_APPLY_SPECULAR, "#define APPLY_SPECULAR\n", "_gloss" }, -{ PROGRAM_APPLY_OFFSETMAPPING, "#define APPLY_OFFSETMAPPING\n", "_offmap" }, -{ PROGRAM_APPLY_RELIEFMAPPING, "#define APPLY_RELIEFMAPPING\n", "_relmap" }, -{ PROGRAM_APPLY_AMBIENT_COMPENSATION, "#define APPLY_AMBIENT_COMPENSATION\n", "_amb" }, -{ PROGRAM_APPLY_DECAL, "#define APPLY_DECAL\n", "_decal" }, -{ PROGRAM_APPLY_BASETEX_ALPHA_ONLY, "#define APPLY_BASETEX_ALPHA_ONLY\n", "_alpha" }, - -{ PROGRAM_APPLY_EYEDOT, "#define APPLY_EYEDOT\n", "_eyedot" }, -{ PROGRAM_APPLY_DISTORTION_ALPHA, "#define APPLY_DISTORTION_ALPHA\n", "_alpha" }, - -{ PROGRAM_APPLY_PCF2x2, "#define APPLY_PCF2x2\n", "_pcf2x2" }, -{ PROGRAM_APPLY_PCF3x3, "#define APPLY_PCF3x3\n", "_pcf3x3" }, - -{ PROGRAM_APPLY_BRANCHING, "#define APPLY_BRANCHING\n", "_branch" }, -{ PROGRAM_APPLY_CLIPPING, "#define APPLY_CLIPPING\n", "_clip" }, -{ PROGRAM_APPLY_NO_HALF_TYPES, "#define APPLY_NO_HALF_TYPES\n", "_nohalf" } -}; - -static const char *r_defaultGLSLProgram = -"// " APPLICATION " GLSL shader\n" -"\n" -"#if !defined(__GLSL_CG_DATA_TYPES) || defined(APPLY_NO_HALF_TYPES)\n" -"#define myhalf float\n" -"#define myhalf2 vec2\n" -"#define myhalf3 vec3\n" -"#define myhalf4 vec4\n" -"#else\n" -"#define myhalf half\n" -"#define myhalf2 half2\n" -"#define myhalf3 half3\n" -"#define myhalf4 half4\n" -"#endif\n" -"\n" -"varying vec2 TexCoord;\n" -"#ifdef APPLY_LIGHTSTYLE0\n" -"varying vec4 LightmapTexCoord01;\n" -"#ifdef APPLY_LIGHTSTYLE2\n" -"varying vec4 LightmapTexCoord23;\n" -"#endif\n" -"#endif\n" -"\n" -"#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)\n" -"varying vec3 EyeVector;\n" -"#endif\n" -"\n" -"#ifdef APPLY_DIRECTIONAL_LIGHT\n" -"varying vec3 LightVector;\n" -"#endif\n" -"\n" -"varying mat3 strMatrix; // directions of S/T/R texcoords (tangent, binormal, normal)\n" -"\n" -"#ifdef VERTEX_SHADER\n" -"// Vertex shader\n" -"\n" -"uniform vec3 EyeOrigin;\n" -"\n" -"#ifdef APPLY_DIRECTIONAL_LIGHT\n" -"uniform vec3 LightDir;\n" -"#endif\n" -"\n" -"void main()\n" -"{\n" -"gl_FrontColor = gl_Color;\n" -"\n" -"TexCoord = vec2 (gl_TextureMatrix[0] * gl_MultiTexCoord0);\n" -"\n" -"#ifdef APPLY_LIGHTSTYLE0\n" -"LightmapTexCoord01.st = gl_MultiTexCoord4.st;\n" -"#ifdef APPLY_LIGHTSTYLE1\n" -"LightmapTexCoord01.pq = gl_MultiTexCoord5.st;\n" -"#ifdef APPLY_LIGHTSTYLE2\n" -"LightmapTexCoord23.st = gl_MultiTexCoord6.st;\n" -"#ifdef APPLY_LIGHTSTYLE3\n" -"LightmapTexCoord23.pq = gl_MultiTexCoord7.st;\n" -"#endif\n" -"#endif\n" -"#endif\n" -"#endif\n" -"\n" -"strMatrix[0] = gl_MultiTexCoord1.xyz;\n" -"strMatrix[2] = gl_Normal.xyz;\n" -"strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);\n" -"\n" -"#if defined(APPLY_SPECULAR) || defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)\n" -"vec3 EyeVectorWorld = EyeOrigin - gl_Vertex.xyz;\n" -"EyeVector = EyeVectorWorld * strMatrix;\n" -"#endif\n" -"\n" -"#ifdef APPLY_DIRECTIONAL_LIGHT\n" -"LightVector = LightDir * strMatrix;\n" -"#endif\n" -"\n" -"gl_Position = ftransform ();\n" -"#ifdef APPLY_CLIPPING\n" -"#ifdef __GLSL_CG_DATA_TYPES\n" -"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" -"#endif\n" -"#endif\n" -"}\n" -"\n" -"#endif // VERTEX_SHADER\n" -"\n" -"\n" -"#ifdef FRAGMENT_SHADER\n" -"// Fragment shader\n" -"\n" -"#ifdef APPLY_LIGHTSTYLE0\n" -"uniform sampler2D LightmapTexture0;\n" -"uniform float DeluxemapOffset0; // s-offset for LightmapTexCoord\n" -"uniform myhalf3 lsColor0; // lightstyle color\n" -"\n" -"#ifdef APPLY_LIGHTSTYLE1\n" -"uniform sampler2D LightmapTexture1;\n" -"uniform float DeluxemapOffset1;\n" -"uniform myhalf3 lsColor1;\n" -"\n" -"#ifdef APPLY_LIGHTSTYLE2\n" -"uniform sampler2D LightmapTexture2;\n" -"uniform float DeluxemapOffset2;\n" -"uniform myhalf3 lsColor2;\n" -"\n" -"#ifdef APPLY_LIGHTSTYLE3\n" -"uniform sampler2D LightmapTexture3;\n" -"uniform float DeluxemapOffset3;\n" -"uniform myhalf3 lsColor3;\n" -"\n" -"#endif\n" -"#endif\n" -"#endif\n" -"#endif\n" -"\n" -"uniform sampler2D BaseTexture;\n" -"uniform sampler2D NormalmapTexture;\n" -"uniform sampler2D GlossTexture;\n" -"#ifdef APPLY_DECAL\n" -"uniform sampler2D DecalTexture;\n" -"#endif\n" -"\n" -"#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)\n" -"uniform float OffsetMappingScale;\n" -"#endif\n" -"\n" -"uniform myhalf3 LightAmbient;\n" -"#ifdef APPLY_DIRECTIONAL_LIGHT\n" -"uniform myhalf3 LightDiffuse;\n" -"#endif\n" -"\n" -"uniform myhalf GlossIntensity; // gloss scaling factor\n" -"uniform myhalf GlossExponent; // gloss exponent factor\n" -"\n" -"#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)\n" -"// The following reliefmapping and offsetmapping routine was taken from DarkPlaces\n" -"// The credit goes to LordHavoc (as always)\n" -"vec2 OffsetMapping(vec2 TexCoord)\n" -"{\n" -"#ifdef APPLY_RELIEFMAPPING\n" -"// 14 sample relief mapping: linear search and then binary search\n" -"// this basically steps forward a small amount repeatedly until it finds\n" -"// itself inside solid, then jitters forward and back using decreasing\n" -"// amounts to find the impact\n" -"//vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1), -1);\n" -"//vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1), -1);\n" -"vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1), -1);\n" -"vec3 RT = vec3(TexCoord, 1);\n" -"OffsetVector *= 0.1;\n" -"RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);\n" -"RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);\n" -"RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);\n" -"RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);\n" -"RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);\n" -"RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);\n" -"RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);\n" -"RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);\n" -"RT += OffsetVector * step(texture2D(NormalmapTexture, RT.xy).a, RT.z);\n" -"RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) - 0.5);\n" -"RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.5 - 0.25);\n" -"RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.25 - 0.125);\n" -"RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.125 - 0.0625);\n" -"RT += OffsetVector * (step(texture2D(NormalmapTexture, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n" -"return RT.xy;\n" -"#else\n" -"// 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n" -"// this basically moves forward the full distance, and then backs up based\n" -"// on height of samples\n" -"//vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMappingScale) * vec2(-1, 1));\n" -"//vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMappingScale * vec2(-1, 1));\n" -"vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMappingScale * vec2(-1, 1));\n" -"TexCoord += OffsetVector;\n" -"OffsetVector *= 0.5;\n" -"TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;\n" -"TexCoord -= OffsetVector * texture2D(NormalmapTexture, TexCoord).a;\n" -"return TexCoord;\n" -"#endif\n" -"}\n" -"#endif\n" -"\n" -"void main()\n" -"{\n" -"#if defined(APPLY_OFFSETMAPPING) || defined(APPLY_RELIEFMAPPING)\n" -"// apply offsetmapping\n" -"vec2 TexCoordOffset = OffsetMapping(TexCoord);\n" -"#define TexCoord TexCoordOffset\n" -"#endif\n" -"myhalf3 surfaceNormal;\n" -"myhalf3 diffuseNormalModelspace;\n" -"myhalf3 diffuseNormal = myhalf3 (0.0, 0.0, -1.0);\n" -"float diffuseProduct;\n" -"\n" -"myhalf3 weightedDiffuseNormal;\n" -"myhalf3 specularNormal;\n" -"float specularProduct;\n" -"\n" -"#if !defined(APPLY_DIRECTIONAL_LIGHT) && !defined(APPLY_LIGHTSTYLE0)\n" -"myhalf4 color = myhalf4 (1.0, 1.0, 1.0, 1.0);\n" -"#else\n" -"myhalf4 color = myhalf4 (0.0, 0.0, 0.0, 1.0);\n" -"#endif\n" -"\n" -"// get the surface normal\n" -"surfaceNormal = normalize (myhalf3 (texture2D (NormalmapTexture, TexCoord)) - myhalf3 (0.5));\n" -"\n" -"#ifdef APPLY_DIRECTIONAL_LIGHT\n" -"diffuseNormal = myhalf3 (LightVector);\n" -"weightedDiffuseNormal = diffuseNormal;\n" -"diffuseProduct = float (dot (surfaceNormal, diffuseNormal));\n" -"color.rgb += LightDiffuse.rgb * myhalf(max (diffuseProduct, 0.0)) + LightAmbient.rgb;\n" -"#endif\n" -"\n" -"// deluxemapping using light vectors in modelspace\n" -"\n" -"#ifdef APPLY_LIGHTSTYLE0\n" -"\n" -"// get light normal\n" -"diffuseNormalModelspace = myhalf3 (texture2D(LightmapTexture0, vec2(LightmapTexCoord01.s+DeluxemapOffset0,LightmapTexCoord01.t)).rgb) - myhalf3 (0.5);\n" -"diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));\n" -"// calculate directional shading\n" -"diffuseProduct = float (dot (surfaceNormal, diffuseNormal));\n" -"\n" -"#ifdef APPLY_FBLIGHTMAP\n" -"weightedDiffuseNormal = diffuseNormal;\n" -"// apply lightmap color\n" -"color.rgb += myhalf3 (max (diffuseProduct, 0.0) * texture2D (LightmapTexture0, LightmapTexCoord01.st).rgb);\n" -"#else\n" -"\n" -"#define NORMALIZE_DIFFUSE_NORMAL\n" -"\n" -"weightedDiffuseNormal = lsColor0.rgb * diffuseNormal;\n" -"// apply lightmap color\n" -"color.rgb += lsColor0 * myhalf(max (diffuseProduct, 0.0)) * texture2D (LightmapTexture0, LightmapTexCoord01.st).rgb;\n" -"#endif\n" -"\n" -"#ifdef APPLY_AMBIENT_COMPENSATION\n" -"// compensate for ambient lighting\n" -"color.rgb += myhalf((1.0 - max (diffuseProduct, 0.0))) * LightAmbient;\n" -"#endif\n" -"\n" -"#ifdef APPLY_LIGHTSTYLE1\n" -"diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture1, vec2(LightmapTexCoord01.p+DeluxemapOffset1,LightmapTexCoord01.q))) - myhalf3 (0.5);\n" -"diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));\n" -"diffuseProduct = float (dot (surfaceNormal, diffuseNormal));\n" -"weightedDiffuseNormal += lsColor1.rgb * diffuseNormal;\n" -"color.rgb += lsColor1 * myhalf(max (diffuseProduct, 0.0)) * texture2D (LightmapTexture1, LightmapTexCoord01.pq).rgb;\n" -"\n" -"#ifdef APPLY_LIGHTSTYLE2\n" -"diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture2, vec2(LightmapTexCoord23.s+DeluxemapOffset2,LightmapTexCoord23.t))) - myhalf3 (0.5);\n" -"diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));\n" -"diffuseProduct = float (dot (surfaceNormal, diffuseNormal));\n" -"weightedDiffuseNormal += lsColor2.rgb * diffuseNormal;\n" -"color.rgb += lsColor2 * myhalf(max (diffuseProduct, 0.0)) * texture2D (LightmapTexture2, LightmapTexCoord23.st).rgb;\n" -"\n" -"#ifdef APPLY_LIGHTSTYLE3\n" -"diffuseNormalModelspace = myhalf3 (texture2D (LightmapTexture3, vec2(LightmapTexCoord23.p+DeluxemapOffset3,LightmapTexCoord23.q))) - myhalf3 (0.5);;\n" -"diffuseNormal = normalize (myhalf3(dot(diffuseNormalModelspace,myhalf3(strMatrix[0])),dot(diffuseNormalModelspace,myhalf3(strMatrix[1])),dot(diffuseNormalModelspace,myhalf3(strMatrix[2]))));\n" -"diffuseProduct = float (dot (surfaceNormal, diffuseNormal));\n" -"weightedDiffuseNormal += lsColor3.rgb * diffuseNormal;\n" -"color.rgb += lsColor3 * myhalf(max (diffuseProduct, 0.0)) * texture2D (LightmapTexture3, LightmapTexCoord23.pq).rgb;\n" -"\n" -"#endif\n" -"#endif\n" -"#endif\n" -"#endif\n" -"\n" -"#ifdef APPLY_SPECULAR\n" -"\n" -"#ifdef NORMALIZE_DIFFUSE_NORMAL\n" -"specularNormal = normalize (myhalf3 (normalize (weightedDiffuseNormal)) + myhalf3 (normalize (EyeVector)));\n" -"#else\n" -"specularNormal = normalize (weightedDiffuseNormal + myhalf3 (normalize (EyeVector)));\n" -"#endif\n" -"\n" -"specularProduct = float (dot (surfaceNormal, specularNormal));\n" -"color.rgb += (myhalf3(texture2D(GlossTexture, TexCoord).rgb) * GlossIntensity) * pow(myhalf(max(specularProduct, 0.0)), GlossExponent);\n" -"#endif\n" -"\n" -"#ifdef APPLY_BASETEX_ALPHA_ONLY\n" -"color = min(color, myhalf4(texture2D(BaseTexture, TexCoord).a));\n" -"#else\n" -"color = min(color, myhalf4(1.0)) * myhalf4(texture2D(BaseTexture, TexCoord).rgba);\n" -"#endif\n" -"\n" -"#ifdef APPLY_DECAL\n" -"myhalf4 decal = myhalf4(gl_Color.rgba);\n" -"#ifdef APPLY_BRANCHING\n" -"if (decal.a > 0.0)\n" -"{\n" -"#endif\n" -"decal = decal * myhalf4(texture2D(DecalTexture, TexCoord).rgba);\n" -"color.rgb = decal.rgb * decal.a + color.rgb * (1.0-decal.a);\n" -"#ifdef APPLY_BRANCHING\n" -"}\n" -"#endif\n" -"#else\n" -"color = color * myhalf4(gl_Color.rgba);\n" -"#endif\n" -"\n" -"gl_FragColor = vec4(color);\n" -"}\n" -"\n" -"#endif // FRAGMENT_SHADER\n" -"\n"; - -static const char *r_defaultDistortionGLSLProgram = -"// " APPLICATION " GLSL shader\n" -"\n" -"#if !defined(__GLSL_CG_DATA_TYPES) || defined(APPLY_NO_HALF_TYPES)\n" -"#define myhalf float\n" -"#define myhalf2 vec2\n" -"#define myhalf3 vec3\n" -"#define myhalf4 vec4\n" -"#else\n" -"#define myhalf half\n" -"#define myhalf2 half2\n" -"#define myhalf3 half3\n" -"#define myhalf4 half4\n" -"#endif\n" -"\n" -"varying vec4 TexCoord;\n" -"varying vec4 ProjVector;\n" -"#ifdef APPLY_EYEDOT\n" -"varying vec3 EyeVector;\n" -"#endif\n" -"\n" -"#ifdef VERTEX_SHADER\n" -"// Vertex shader\n" -"\n" -"#ifdef APPLY_EYEDOT\n" -"uniform vec3 EyeOrigin;\n" -"uniform float FrontPlane;\n" -"#endif\n" -"\n" -"void main(void)\n" -"{\n" -"gl_FrontColor = gl_Color;\n" -"\n" -"mat4 textureMatrix;\n" -"\n" -"textureMatrix = gl_TextureMatrix[0];\n" -"TexCoord.st = vec2 (textureMatrix * gl_MultiTexCoord0);\n" -"\n" -"textureMatrix = gl_TextureMatrix[0];\n" -"textureMatrix[0] = -textureMatrix[0];\n" -"textureMatrix[1] = -textureMatrix[1];\n" -"TexCoord.pq = vec2 (textureMatrix * gl_MultiTexCoord0);\n" -"\n" -"#ifdef APPLY_EYEDOT\n" -"mat3 strMatrix;\n" -"strMatrix[0] = gl_MultiTexCoord1.xyz;\n" -"strMatrix[2] = gl_Normal.xyz;\n" -"strMatrix[1] = gl_MultiTexCoord1.w * cross (strMatrix[2], strMatrix[0]);\n" -"\n" -"vec3 EyeVectorWorld = (EyeOrigin - gl_Vertex.xyz) * FrontPlane;\n" -"EyeVector = EyeVectorWorld * strMatrix;\n" -"#endif\n" -"\n" -"gl_Position = ftransform();\n" -"ProjVector = gl_Position;\n" -"#ifdef APPLY_CLIPPING\n" -"#ifdef __GLSL_CG_DATA_TYPES\n" -"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" -"#endif\n" -"#endif\n" -"}\n" -"\n" -"#endif // VERTEX_SHADER\n" -"\n" -"\n" -"#ifdef FRAGMENT_SHADER\n" -"// Fragment shader\n" -"\n" -"uniform sampler2D DuDvMapTexture;\n" -"#ifdef APPLY_EYEDOT\n" -"uniform sampler2D NormalmapTexture;\n" -"#endif\n" -"uniform sampler2D ReflectionTexture;\n" -"uniform sampler2D RefractionTexture;\n" -"uniform float TextureWidth, TextureHeight;\n" -"\n" -"void main(void)\n" -"{\n" -"myhalf3 color;\n" -"\n" -"vec3 displacement = vec3(texture2D(DuDvMapTexture, vec2(TexCoord.pq) * vec2(0.25)));\n" -"vec2 coord = vec2(TexCoord.st) + vec2(displacement) * vec2 (0.2);\n" -"\n" -"vec3 fdist = vec3 (normalize(vec3(texture2D(DuDvMapTexture, coord)) - vec3 (0.5))) * vec3(0.005);\n" -"\n" -"// get projective texcoords\n" -"float scale = float(1.0 / float(ProjVector.w));\n" -"float inv2NW = 1.0 / (2.0 * float (TextureWidth));\n" -"float inv2NH = 1.0 / (2.0 * float (TextureHeight));\n" -"vec3 projCoord = (vec3(ProjVector.xyz) * scale + vec3 (1.0)) * vec3 (0.5) + fdist;\n" -"projCoord.s = float (clamp (float(projCoord.s), inv2NW, 1.0 - inv2NW));\n" -"projCoord.t = float (clamp (float(projCoord.t), inv2NH, 1.0 - inv2NH));\n" -"projCoord.r = float (clamp (float(projCoord.r), 0.0, 1.0));\n" -"\n" -"#ifdef APPLY_EYEDOT\n" -"// calculate dot product between the surface normal and eye vector\n" -"// great for simulating varying water translucency based on the view angle\n" -"myhalf3 surfaceNormal = normalize(myhalf3(texture2D(NormalmapTexture, coord).rgb) - myhalf3 (0.5));\n" -"vec3 eyeNormal = normalize(myhalf3(EyeVector));\n" -"\n" -"float refrdot = float(dot(surfaceNormal, eyeNormal));\n" -"//refrdot = float (clamp (refrdot, 0.0, 1.0));\n" -"float refldot = 1.0 - refrdot;\n" -"// get refraction and reflection\n" -"myhalf3 refr = (myhalf3(texture2D(RefractionTexture, vec2(projCoord.st))).rgb) * refrdot;\n" -"myhalf3 refl = (myhalf3(texture2D(ReflectionTexture, vec2(projCoord.st))).rgb) * refldot;\n" -"#else\n" -"myhalf3 refr = (myhalf3(texture2D(RefractionTexture, vec2(projCoord.st))).rgb);\n" -"myhalf3 refl = (myhalf3(texture2D(ReflectionTexture, vec2(projCoord.st))).rgb);\n" -"#endif\n" -"\n" -"\n" -"// add reflection and refraction\n" -"#ifdef APPLY_DISTORTION_ALPHA\n" -"color = myhalf3(gl_Color.rgb) + myhalf3(mix (refr, refl, float(gl_Color.a)));\n" -"#else\n" -"color = myhalf3(gl_Color.rgb) + refr + refl;\n" -"#endif\n" -"\n" -"gl_FragColor = vec4(vec3(color), 1.0);\n" -"}\n" -"\n" -"#endif // FRAGMENT_SHADER\n" -"\n"; - -static const char *r_defaultShadowmapGLSLProgram = -"// " APPLICATION " GLSL shader\n" -"\n" -"\n" -"varying vec4 ProjVector;\n" -"\n" -"#ifdef VERTEX_SHADER\n" -"// Vertex shader\n" -"\n" -"void main(void)\n" -"{\n" -"gl_FrontColor = gl_Color;\n" -"\n" -"\n" -"mat4 textureMatrix;\n" -"\n" -"textureMatrix = gl_TextureMatrix[0];\n" -"\n" -"gl_Position = ftransform();\n" -"ProjVector = textureMatrix * gl_Vertex;\n" -"}\n" -"\n" -"#endif // VERTEX_SHADER\n" -"\n" -"\n" -"#ifdef FRAGMENT_SHADER\n" -"// Fragment shader\n" -"\n" -"uniform float TextureWidth, TextureHeight;\n" -"uniform float ProjDistance;\n" -"uniform sampler2DShadow ShadowmapTexture;\n" -"\n" -"void main(void)\n" -"{\n" -"vec4 color = vec4 (1.0);\n" -"\n" -"#ifdef APPLY_BRANCHING\n" -"\n" -"if (ProjVector.w > 0.0)\n" -"{\n" -"\n" -"if (ProjVector.w < ProjDistance)\n" -"{\n" -"#endif\n" -"\n" -"float dtW = 1.0 / TextureWidth;\n" -"float dtH = 1.0 / TextureHeight;\n" -"vec3 coord = vec3 (ProjVector.xyz / ProjVector.w);\n" -"coord = (coord + vec3 (1.0)) * vec3 (0.5);\n" -"coord.s = float (clamp (float(coord.s), dtW, 1.0 - dtW));\n" -"coord.t = float (clamp (float(coord.t), dtH, 1.0 - dtH));\n" -"coord.r = float (clamp (float(coord.r), 0.0, 1.0));\n" -"\n" -"float shadow0 = float(shadow2D(ShadowmapTexture, coord).r);\n" -"float shadow = shadow0;\n" -"\n" -"#if defined(APPLY_PCF2x2) || defined(APPLY_PCF3x3)\n" -"\n" -"vec3 coord2 = coord + vec3(0.0, dtH, 0.0);\n" -"float shadow1 = float (shadow2D (ShadowmapTexture, coord2).r);\n" -"\n" -"coord2 = coord + vec3(dtW, dtH, 0.0);\n" -"float shadow2 = float (shadow2D (ShadowmapTexture, coord2).r);\n" -"\n" -"coord2 = coord + vec3(dtW, 0.0, 0.0);\n" -"float shadow3 = float (shadow2D (ShadowmapTexture, coord2).r);\n" -"\n" -"#if defined(APPLY_PCF3x3)\n" -"coord2 = coord + vec3(-dtW, 0.0, 0.0);\n" -"float shadow4 = float (shadow2D (ShadowmapTexture, coord2).r);\n" -"\n" -"coord2 = coord + vec3(-dtW, -dtH, 0.0);\n" -"float shadow5 = float (shadow2D (ShadowmapTexture, coord2).r);\n" -"\n" -"coord2 = coord + vec3(0.0, -dtH, 0.0);\n" -"float shadow6 = float (shadow2D (ShadowmapTexture, coord2).r);\n" -"\n" -"coord2 = coord + vec3(dtW, -dtH, 0.0);\n" -"float shadow7 = float (shadow2D (ShadowmapTexture, coord2).r);\n" -"\n" -"coord2 = coord + vec3(-dtW, dtH, 0.0);\n" -"float shadow8 = float (shadow2D (ShadowmapTexture, coord2).r);\n" -"\n" -"shadow = (shadow0 + shadow1 + shadow2 + shadow3 + shadow4 + shadow5 + shadow6 + shadow7 + shadow8) * 0.11;\n" -"#else\n" -"shadow = (shadow0 + shadow1 + shadow2 + shadow3) * 0.25;\n" -"#endif\n" -"#else\n" -"shadow = shadow0;\n" -"#endif\n" -"\n" -"float attenuation = float (ProjVector.w) / ProjDistance;\n" -"#ifdef APPLY_BRANCHING\n" -"shadow = shadow + attenuation;\n" -"#else\n" -"shadow = shadow + 1.0 - step (0.0, float(ProjVector.w)) + max(attenuation, 0.0);\n" -"#endif\n" -"color.rgb = vec3 (shadow);\n" -"\n" -"#ifdef APPLY_BRANCHING\n" -"}\n" -"}\n" -"#endif\n" -"\n" -"gl_FragColor = vec4(color);\n" -"}\n" -"\n" -"#endif // FRAGMENT_SHADER\n" -"\n"; - -/* -================ -R_ProgramFeatures2Defines - -Return an array of strings for bitflags -================ -*/ -static const char **R_ProgramFeatures2Defines( int features, char *name, size_t size ) -{ - int i, p; - static const char *headers[MAX_DEFINES_FEATURES+1]; // +1 for NULL safe-guard - - for( i = 0, p = 0; i < sizeof( glsl_features ) / sizeof( glsl_features[0] ); i++ ) - { - if( features & glsl_features[i].bit ) - { - headers[p++] = glsl_features[i].define; - if( name ) - com.strncat( name, glsl_features[i].suffix, size ); - - if( p == MAX_DEFINES_FEATURES ) - break; - } - } - - if( p ) - { - headers[p] = NULL; - return headers; - } - - return NULL; -} - -/* -================ -R_RegisterGLSLProgram -================ -*/ -int R_RegisterGLSLProgram( const char *name, const char *string, unsigned int features ) -{ - int i, linked, body, error = 0; - uint minfeatures; - glsl_program_t *program, *parent; - char fullName[MAX_STRING]; - const char **header; - const char *vertexShaderStrings[MAX_DEFINES_FEATURES+2]; - const char *fragmentShaderStrings[MAX_DEFINES_FEATURES+2]; - - if( !GL_Support( R_SHADER_GLSL100_EXT )) - return 0; // fail early - - parent = NULL; - minfeatures = features; - for( i = 0, program = r_glslprograms; i < MAX_GLSL_PROGRAMS; i++, program++ ) - { - if( !program->name ) - break; - - if( !com.stricmp( program->name, name ) ) - { - if ( program->features == features ) - return ( i+1 ); - - if( !parent || (program->features < minfeatures) ) - { - parent = program; - minfeatures = program->features; - } - } - } - - if( i == MAX_GLSL_PROGRAMS ) - { - MsgDev( D_ERROR, "R_RegisterGLSLProgram: GLSL programs limit exceeded\n" ); - return 0; - } - - if( !string ) - { - if( parent ) - string = parent->string; - else - string = r_defaultGLSLProgram; - } - - program = r_glslprograms + i; - program->object = pglCreateProgramObjectARB(); - if( !program->object ) - { - error = 1; - goto done; - } - - body = 1; - com.strncpy( fullName, name, sizeof( fullName ) ); - header = R_ProgramFeatures2Defines( features, fullName, sizeof( fullName ) ); - - if( header ) - for( ; header[body-1] && *header[body-1]; body++ ); - - vertexShaderStrings[0] = "#define VERTEX_SHADER\n"; - for( i = 1; i < body; i++ ) - vertexShaderStrings[i] = ( char * )header[i-1]; - // find vertex shader header - vertexShaderStrings[body] = string; - - fragmentShaderStrings[0] = "#define FRAGMENT_SHADER\n"; - for( i = 1; i < body; i++ ) - fragmentShaderStrings[i] = ( char * )header[i-1]; - // find fragment shader header - fragmentShaderStrings[body] = string; - - // compile vertex shader - program->vertexShader = R_CompileGLSLShader( program->object, fullName, "vertex", GL_VERTEX_SHADER_ARB, vertexShaderStrings, body+1 ); - if( !program->vertexShader ) - { - error = 1; - goto done; - } - - // compile fragment shader - program->fragmentShader = R_CompileGLSLShader( program->object, fullName, "fragment", GL_FRAGMENT_SHADER_ARB, fragmentShaderStrings, body+1 ); - if( !program->fragmentShader ) - { - error = 1; - goto done; - } - - // link - pglLinkProgramARB( program->object ); - pglGetObjectParameterivARB( program->object, GL_OBJECT_LINK_STATUS_ARB, &linked ); - if( !linked ) - { - char log[8192]; - - pglGetInfoLogARB( program->object, sizeof( log ), NULL, log ); - log[sizeof( log ) - 1] = 0; - - if( log[0] ) - MsgDev( D_ERROR, "Failed to compile link object for program %s:\n%s\n", fullName, log ); - - error = 1; - goto done; - } - -done: - if( error ) - R_DeleteGLSLProgram( program ); - - program->features = features; - program->name = R_GLSLProgramCopyString( name ); - program->string = string; - - if( program->object ) - { - pglUseProgramObjectARB( program->object ); - R_GetProgramUniformLocations( program ); - pglUseProgramObjectARB( 0 ); - } - - return ( program - r_glslprograms ) + 1; -} - -/* -================ -R_GetProgramObject -================ -*/ -int R_GetProgramObject( int elem ) -{ - return r_glslprograms[elem - 1].object; -} - -/* -================ -R_ProgramList_f -================ -*/ -void R_ProgramList_f( void ) -{ - int i; - glsl_program_t *program; - string fullName; - const char **header; - - Msg( "------------------\n" ); - for( i = 0, program = r_glslprograms; i < MAX_GLSL_PROGRAMS; i++, program++ ) - { - if( !program->name ) - break; - - com.strncpy( fullName, program->name, sizeof( fullName ) ); - header = R_ProgramFeatures2Defines( program->features, fullName, sizeof( fullName )); - - Msg( " %3i %s\n", i+1, fullName ); - } - Msg( "%i programs total\n", i ); -} - -/* -================ -R_ProgramDump_f -================ -*/ -#define DUMP_PROGRAM(p) { file_t *file; file = FS_Open( va("programs/%s.glsl", #p), "w" ); if( file ){ FS_Write( file, r_##p, com.strlen( r_##p )); FS_Close( file ); } } -void R_ProgramDump_f( void ) -{ - DUMP_PROGRAM( defaultGLSLProgram ); - DUMP_PROGRAM( defaultDistortionGLSLProgram ); - DUMP_PROGRAM( defaultShadowmapGLSLProgram ); -} -#undef DUMP_PROGRAM - -/* -================ -R_UpdateProgramUniforms -================ -*/ -void R_UpdateProgramUniforms( int elem, vec3_t eyeOrigin, vec3_t lightOrigin, vec3_t lightDir, vec4_t ambient, - vec4_t diffuse, ref_style_t *lightStyle, qboolean frontPlane, int TexWidth, int TexHeight, - float projDistance, float offsetmappingScale ) -{ - glsl_program_t *program = r_glslprograms + elem - 1; - - if( program->locEyeOrigin >= 0 && eyeOrigin ) - pglUniform3fARB( program->locEyeOrigin, eyeOrigin[0], eyeOrigin[1], eyeOrigin[2] ); - - if( program->locLightOrigin >= 0 && lightOrigin ) - pglUniform3fARB( program->locLightOrigin, lightOrigin[0], lightOrigin[1], lightOrigin[2] ); - if( program->locLightDir >= 0 && lightDir ) - pglUniform3fARB( program->locLightDir, lightDir[0], lightDir[1], lightDir[2] ); - - if( program->locLightAmbient >= 0 && ambient ) - pglUniform3fARB( program->locLightAmbient, ambient[0], ambient[1], ambient[2] ); - if( program->locLightDiffuse >= 0 && diffuse ) - pglUniform3fARB( program->locLightDiffuse, diffuse[0], diffuse[1], diffuse[2] ); - - if( program->locGlossIntensity >= 0 ) - pglUniform1fARB( program->locGlossIntensity, r_lighting_glossintensity->value ); - if( program->locGlossExponent >= 0 ) - pglUniform1fARB( program->locGlossExponent, r_lighting_glossexponent->value ); - - if( program->locOffsetMappingScale >= 0 ) - pglUniform1fARB( program->locOffsetMappingScale, offsetmappingScale ); - - if( program->locFrontPlane >= 0 ) - pglUniform1fARB( program->locFrontPlane, frontPlane ? 1 : -1 ); - - if( program->locTextureWidth >= 0 ) - pglUniform1fARB( program->locTextureWidth, TexWidth ); - if( program->locTextureHeight >= 0 ) - pglUniform1fARB( program->locTextureHeight, TexHeight ); - - if( program->locProjDistance >= 0 ) - pglUniform1fARB( program->locProjDistance, projDistance ); - - if( lightStyle ) - { - int i; - - for( i = 0; i < LM_STYLES && lightStyle->lightmapStyles[i] != 255; i++ ) - { - vec_t *rgb = r_lightStyles[lightStyle->lightmapStyles[i]].rgb; - - if( program->locDeluxemapOffset[i] >= 0 ) - pglUniform1fARB( program->locDeluxemapOffset[i], lightStyle->stOffset[0] ); - if( program->loclsColor[i] >= 0 ) - pglUniform3fARB( program->loclsColor[i], rgb[0], rgb[1], rgb[2] ); - } - - for( ; i < LM_STYLES; i++ ) - { - if( program->loclsColor[i] >= 0 ) - pglUniform3fARB( program->loclsColor[i], 0, 0, 0 ); - } - } -} - -/* -================ -R_GetProgramUniformLocations -================ -*/ -static void R_GetProgramUniformLocations( glsl_program_t *program ) -{ - int i; - int locBaseTexture, locNormalmapTexture, locGlossTexture; - int locDecalTexture, locLightmapTexture[LM_STYLES]; - int locDuDvMapTexture, locReflectionTexture; - int locRefractionTexture, locShadowmapTexture; - char uniformName[128]; - - program->locEyeOrigin = pglGetUniformLocationARB( program->object, "EyeOrigin" ); - program->locLightDir = pglGetUniformLocationARB( program->object, "LightDir" ); - program->locLightOrigin = pglGetUniformLocationARB( program->object, "LightOrigin" ); - program->locLightAmbient = pglGetUniformLocationARB( program->object, "LightAmbient" ); - program->locLightDiffuse = pglGetUniformLocationARB( program->object, "LightDiffuse" ); - - locBaseTexture = pglGetUniformLocationARB( program->object, "BaseTexture" ); - locNormalmapTexture = pglGetUniformLocationARB( program->object, "NormalmapTexture" ); - locGlossTexture = pglGetUniformLocationARB( program->object, "GlossTexture" ); - locDecalTexture = pglGetUniformLocationARB( program->object, "DecalTexture" ); - - locDuDvMapTexture = pglGetUniformLocationARB( program->object, "DuDvMapTexture" ); - locReflectionTexture = pglGetUniformLocationARB( program->object, "ReflectionTexture" ); - locRefractionTexture = pglGetUniformLocationARB( program->object, "RefractionTexture" ); - - locShadowmapTexture = pglGetUniformLocationARB( program->object, "ShadowmapTexture" ); - - for( i = 0; i < LM_STYLES; i++ ) - { - com.snprintf( uniformName, sizeof( uniformName ), "LightmapTexture%i", i ); - locLightmapTexture[i] = pglGetUniformLocationARB( program->object, uniformName ); - - com.snprintf( uniformName, sizeof( uniformName ), "DeluxemapOffset%i", i ); - program->locDeluxemapOffset[i] = pglGetUniformLocationARB( program->object, uniformName ); - - com.snprintf( uniformName, sizeof( uniformName ), "lsColor%i", i ); - program->loclsColor[i] = pglGetUniformLocationARB( program->object, uniformName ); - } - - program->locGlossIntensity = pglGetUniformLocationARB( program->object, "GlossIntensity" ); - program->locGlossExponent = pglGetUniformLocationARB( program->object, "GlossExponent" ); - - program->locOffsetMappingScale = pglGetUniformLocationARB( program->object, "OffsetMappingScale" ); - - program->locFrontPlane = pglGetUniformLocationARB( program->object, "FrontPlane" ); - - program->locTextureWidth = pglGetUniformLocationARB( program->object, "TextureWidth" ); - program->locTextureHeight = pglGetUniformLocationARB( program->object, "TextureHeight" ); - - program->locProjDistance = pglGetUniformLocationARB( program->object, "ProjDistance" ); - - if( locBaseTexture >= 0 ) pglUniform1iARB( locBaseTexture, 0 ); - if( locDuDvMapTexture >= 0 ) pglUniform1iARB( locDuDvMapTexture, 0 ); - - if( locNormalmapTexture >= 0 ) pglUniform1iARB( locNormalmapTexture, 1 ); - if( locGlossTexture >= 0 ) pglUniform1iARB( locGlossTexture, 2 ); - if( locDecalTexture >= 0 ) pglUniform1iARB( locDecalTexture, 3 ); - - if( locReflectionTexture >= 0 ) pglUniform1iARB( locReflectionTexture, 2 ); - if( locRefractionTexture >= 0 ) pglUniform1iARB( locRefractionTexture, 3 ); - - if( locShadowmapTexture >= 0 ) pglUniform1iARB( locShadowmapTexture, 0 ); - - for( i = 0; i < LM_STYLES; i++ ) - { - if( locLightmapTexture[i] >= 0 ) - pglUniform1iARB( locLightmapTexture[i], i+4 ); - } -} - -/* -================ -R_ShutdownGLSLPrograms -================ -*/ -void R_ShutdownGLSLPrograms( void ) -{ - int i; - glsl_program_t *program; - - if( !r_glslProgramsPool ) - return; - if( !GL_Support( R_SHADER_GLSL100_EXT )) - return; - - for( i = 0, program = r_glslprograms; i < MAX_GLSL_PROGRAMS; i++, program++ ) - { - if( !program->object ) - break; - - R_DeleteGLSLProgram( program ); - } - - Mem_FreePool( &r_glslProgramsPool ); -} \ No newline at end of file diff --git a/vid_gl/r_register.c b/vid_gl/r_register.c deleted file mode 100644 index 054357fd..00000000 --- a/vid_gl/r_register.c +++ /dev/null @@ -1,1123 +0,0 @@ -/* -Copyright (C) 2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// r_register.c -#include "r_local.h" -#include "mathlib.h" - -glconfig_t glConfig; -glstate_t glState; -byte *r_temppool; - -convar_t *r_norefresh; -convar_t *r_drawentities; -convar_t *r_drawworld; -convar_t *r_speeds; -convar_t *r_drawelements; -convar_t *r_fullbright; -convar_t *r_lightmap; -convar_t *r_novis; -convar_t *r_nocull; -convar_t *r_ignorehwgamma; -convar_t *r_check_errors; -convar_t *r_overbrightbits; -convar_t *r_vertexbuffers; -convar_t *r_flares; -convar_t *r_flaresize; -convar_t *r_flarefade; -convar_t *r_spriteflares; -convar_t *r_cullflares; -convar_t *r_dynamiclight; -convar_t *r_coronascale; -convar_t *r_detailtextures; -convar_t *r_subdivisions; -convar_t *r_faceplanecull; -convar_t *gl_wireframe; -convar_t *r_shownormals; -convar_t *r_showtextures; -convar_t *r_adjust_fov; -convar_t *r_draworder; -convar_t *r_width; -convar_t *r_height; -convar_t *r_fastsky; -convar_t *r_portalonly; -convar_t *r_portalmaps; -convar_t *r_portalmaps_maxtexsize; - -convar_t *r_lighting_bumpscale; -convar_t *r_lighting_deluxemapping; -convar_t *r_lighting_diffuse2heightmap; -convar_t *r_lighting_specular; -convar_t *r_lighting_glossintensity; -convar_t *r_lighting_glossexponent; -convar_t *r_lighting_models_followdeluxe; -convar_t *r_lighting_ambientscale; -convar_t *r_lighting_directedscale; -convar_t *r_lighting_modulate; - -convar_t *r_offsetmapping; -convar_t *r_offsetmapping_scale; -convar_t *r_offsetmapping_reliefmapping; - -convar_t *r_occlusion_queries; -convar_t *r_occlusion_queries_finish; - -convar_t *r_shadows; -convar_t *r_shadows_alpha; -convar_t *r_shadows_nudge; -convar_t *r_shadows_projection_distance; -convar_t *r_shadows_maxtexsize; -convar_t *r_shadows_pcf; -convar_t *r_shadows_self_shadow; - -convar_t *r_bloom_alpha; -convar_t *r_bloom_diamond_size; -convar_t *r_bloom_intensity; -convar_t *r_bloom_darken; -convar_t *r_bloom_sample_size; -convar_t *r_bloom_fast_sample; - -convar_t *r_allow_software; -convar_t *r_3dlabs_broken; - -convar_t *r_decals; -convar_t *r_himodels; -convar_t *r_lefthand; -convar_t *r_physbdebug; - -convar_t *r_environment_color; -convar_t *r_stencilbits; -convar_t *r_gamma; -convar_t *r_colorbits; -convar_t *r_depthbits; -convar_t *r_texturebits; -convar_t *gl_texturemode; -convar_t *gl_texture_anisotropy; -convar_t *gl_texture_lodbias; -convar_t *gl_round_down; -convar_t *gl_compress_textures; -convar_t *r_mode; -convar_t *r_picmip; -convar_t *r_skymip; -convar_t *r_nobind; -convar_t *gl_clear; -convar_t *r_lockpvs; -convar_t *r_swapInterval; -convar_t *r_frontbuffer; - -convar_t *gl_extensions; -convar_t *gl_driver; -convar_t *gl_finish; -convar_t *gl_delayfinish; -convar_t *gl_cull; - -convar_t *vid_fullscreen; -convar_t *vid_displayfrequency; - -static void GL_SetDefaultState( void ); - -// set initial values -extern dll_info_t opengl_dll; - -static dllfunc_t wglswapintervalfuncs[] = -{ - {"wglSwapIntervalEXT", (void **) &pwglSwapIntervalEXT}, - {NULL, NULL} -}; - -static dllfunc_t wgl3DFXgammacontrolfuncs[] = -{ - {"wglGetDeviceGammaRamp3DFX", (void **) &pwglGetDeviceGammaRamp3DFX}, - {"wglSetDeviceGammaRamp3DFX", (void **) &pwglSetDeviceGammaRamp3DFX}, - {NULL, NULL} -}; - -static dllfunc_t opengl_110funcs[] = -{ - {"glClearColor", (void **) &pglClearColor}, - {"glClear", (void **) &pglClear}, - {"glAlphaFunc", (void **) &pglAlphaFunc}, - {"glBlendFunc", (void **) &pglBlendFunc}, - {"glCullFace", (void **) &pglCullFace}, - {"glDrawBuffer", (void **) &pglDrawBuffer}, - {"glReadBuffer", (void **) &pglReadBuffer}, - {"glEnable", (void **) &pglEnable}, - {"glDisable", (void **) &pglDisable}, - {"glEnableClientState", (void **) &pglEnableClientState}, - {"glDisableClientState", (void **) &pglDisableClientState}, - {"glGetBooleanv", (void **) &pglGetBooleanv}, - {"glGetDoublev", (void **) &pglGetDoublev}, - {"glGetFloatv", (void **) &pglGetFloatv}, - {"glGetIntegerv", (void **) &pglGetIntegerv}, - {"glGetError", (void **) &pglGetError}, - {"glGetString", (void **) &pglGetString}, - {"glFinish", (void **) &pglFinish}, - {"glFlush", (void **) &pglFlush}, - {"glClearDepth", (void **) &pglClearDepth}, - {"glDepthFunc", (void **) &pglDepthFunc}, - {"glDepthMask", (void **) &pglDepthMask}, - {"glDepthRange", (void **) &pglDepthRange}, - {"glFrontFace", (void **) &pglFrontFace}, - {"glDrawElements", (void **) &pglDrawElements}, - {"glColorMask", (void **) &pglColorMask}, - {"glIndexPointer", (void **) &pglIndexPointer}, - {"glVertexPointer", (void **) &pglVertexPointer}, - {"glNormalPointer", (void **) &pglNormalPointer}, - {"glColorPointer", (void **) &pglColorPointer}, - {"glTexCoordPointer", (void **) &pglTexCoordPointer}, - {"glArrayElement", (void **) &pglArrayElement}, - {"glColor3f", (void **) &pglColor3f}, - {"glColor3fv", (void **) &pglColor3fv}, - {"glColor4f", (void **) &pglColor4f}, - {"glColor4fv", (void **) &pglColor4fv}, - {"glColor4ub", (void **) &pglColor4ub}, - {"glColor4ubv", (void **) &pglColor4ubv}, - {"glTexCoord1f", (void **) &pglTexCoord1f}, - {"glTexCoord2f", (void **) &pglTexCoord2f}, - {"glTexCoord3f", (void **) &pglTexCoord3f}, - {"glTexCoord4f", (void **) &pglTexCoord4f}, - {"glTexGenf", (void **) &pglTexGenf}, - {"glTexGenfv", (void **) &pglTexGenfv}, - {"glTexGeni", (void **) &pglTexGeni}, - {"glVertex2f", (void **) &pglVertex2f}, - {"glVertex3f", (void **) &pglVertex3f}, - {"glVertex3fv", (void **) &pglVertex3fv}, - {"glNormal3f", (void **) &pglNormal3f}, - {"glNormal3fv", (void **) &pglNormal3fv}, - {"glBegin", (void **) &pglBegin}, - {"glEnd", (void **) &pglEnd}, - {"glLineWidth", (void**) &pglLineWidth}, - {"glPointSize", (void**) &pglPointSize}, - {"glMatrixMode", (void **) &pglMatrixMode}, - {"glOrtho", (void **) &pglOrtho}, - {"glRasterPos2f", (void **) &pglRasterPos2f}, - {"glFrustum", (void **) &pglFrustum}, - {"glViewport", (void **) &pglViewport}, - {"glPushMatrix", (void **) &pglPushMatrix}, - {"glPopMatrix", (void **) &pglPopMatrix}, - {"glLoadIdentity", (void **) &pglLoadIdentity}, - {"glLoadMatrixd", (void **) &pglLoadMatrixd}, - {"glLoadMatrixf", (void **) &pglLoadMatrixf}, - {"glMultMatrixd", (void **) &pglMultMatrixd}, - {"glMultMatrixf", (void **) &pglMultMatrixf}, - {"glRotated", (void **) &pglRotated}, - {"glRotatef", (void **) &pglRotatef}, - {"glScaled", (void **) &pglScaled}, - {"glScalef", (void **) &pglScalef}, - {"glTranslated", (void **) &pglTranslated}, - {"glTranslatef", (void **) &pglTranslatef}, - {"glReadPixels", (void **) &pglReadPixels}, - {"glDrawPixels", (void **) &pglDrawPixels}, - {"glStencilFunc", (void **) &pglStencilFunc}, - {"glStencilMask", (void **) &pglStencilMask}, - {"glStencilOp", (void **) &pglStencilOp}, - {"glClearStencil", (void **) &pglClearStencil}, - {"glTexEnvf", (void **) &pglTexEnvf}, - {"glTexEnvfv", (void **) &pglTexEnvfv}, - {"glTexEnvi", (void **) &pglTexEnvi}, - {"glTexParameterf", (void **) &pglTexParameterf}, - {"glTexParameterfv", (void **) &pglTexParameterfv}, - {"glTexParameteri", (void **) &pglTexParameteri}, - {"glHint", (void **) &pglHint}, - {"glPixelStoref", (void **) &pglPixelStoref}, - {"glPixelStorei", (void **) &pglPixelStorei}, - {"glGenTextures", (void **) &pglGenTextures}, - {"glDeleteTextures", (void **) &pglDeleteTextures}, - {"glBindTexture", (void **) &pglBindTexture}, - {"glTexImage1D", (void **) &pglTexImage1D}, - {"glTexImage2D", (void **) &pglTexImage2D}, - {"glTexSubImage1D", (void **) &pglTexSubImage1D}, - {"glTexSubImage2D", (void **) &pglTexSubImage2D}, - {"glCopyTexImage1D", (void **) &pglCopyTexImage1D}, - {"glCopyTexImage2D", (void **) &pglCopyTexImage2D}, - {"glCopyTexSubImage1D", (void **) &pglCopyTexSubImage1D}, - {"glCopyTexSubImage2D", (void **) &pglCopyTexSubImage2D}, - {"glScissor", (void **) &pglScissor}, - {"glPolygonOffset", (void **) &pglPolygonOffset}, - {"glPolygonMode", (void **) &pglPolygonMode}, - {"glPolygonStipple", (void **) &pglPolygonStipple}, - {"glClipPlane", (void **) &pglClipPlane}, - {"glGetClipPlane", (void **) &pglGetClipPlane}, - {"glShadeModel", (void **) &pglShadeModel}, - {"glFogfv", (void **) &pglFogfv}, - {"glFogf", (void **) &pglFogf}, - {"glFogi", (void **) &pglFogi}, - {NULL, NULL} -}; - -static dllfunc_t pointparametersfunc[] = -{ - {"glPointParameterfEXT", (void **) &pglPointParameterfEXT}, - {"glPointParameterfvEXT", (void **) &pglPointParameterfvEXT}, - {NULL, NULL} -}; - -static dllfunc_t drawrangeelementsfuncs[] = -{ - {"glDrawRangeElements", (void **) &pglDrawRangeElements}, - {NULL, NULL} -}; - -static dllfunc_t drawrangeelementsextfuncs[] = -{ - {"glDrawRangeElementsEXT", (void **) &pglDrawRangeElementsEXT}, - {NULL, NULL} -}; - -static dllfunc_t sgis_multitexturefuncs[] = -{ - {"glSelectTextureSGIS", (void **) &pglSelectTextureSGIS}, - {"glMTexCoord2fSGIS", (void **) &pglMTexCoord2fSGIS}, - {NULL, NULL} -}; - -static dllfunc_t multitexturefuncs[] = -{ - {"glMultiTexCoord1fARB", (void **) &pglMultiTexCoord1f}, - {"glMultiTexCoord2fARB", (void **) &pglMultiTexCoord2f}, - {"glMultiTexCoord3fARB", (void **) &pglMultiTexCoord3f}, - {"glMultiTexCoord4fARB", (void **) &pglMultiTexCoord4f}, - {"glActiveTextureARB", (void **) &pglActiveTextureARB}, - {"glClientActiveTextureARB", (void **) &pglClientActiveTexture}, - {"glClientActiveTextureARB", (void **) &pglClientActiveTextureARB}, - {NULL, NULL} -}; - -static dllfunc_t compiledvertexarrayfuncs[] = -{ - {"glLockArraysEXT", (void **) &pglLockArraysEXT}, - {"glUnlockArraysEXT", (void **) &pglUnlockArraysEXT}, - {"glDrawArrays", (void **) &pglDrawArrays}, - {NULL, NULL} -}; - -static dllfunc_t texture3dextfuncs[] = -{ - {"glTexImage3DEXT", (void **) &pglTexImage3D}, - {"glTexSubImage3DEXT", (void **) &pglTexSubImage3D}, - {"glCopyTexSubImage3DEXT", (void **) &pglCopyTexSubImage3D}, - {NULL, NULL} -}; - -static dllfunc_t atiseparatestencilfuncs[] = -{ - {"glStencilOpSeparateATI", (void **) &pglStencilOpSeparate}, - {"glStencilFuncSeparateATI", (void **) &pglStencilFuncSeparate}, - {NULL, NULL} -}; - -static dllfunc_t gl2separatestencilfuncs[] = -{ - {"glStencilOpSeparate", (void **) &pglStencilOpSeparate}, - {"glStencilFuncSeparate", (void **) &pglStencilFuncSeparate}, - {NULL, NULL} -}; - -static dllfunc_t stenciltwosidefuncs[] = -{ - {"glActiveStencilFaceEXT", (void **) &pglActiveStencilFaceEXT}, - {NULL, NULL} -}; - -static dllfunc_t blendequationfuncs[] = -{ - {"glBlendEquationEXT", (void **) &pglBlendEquationEXT}, - {NULL, NULL} -}; - -static dllfunc_t shaderobjectsfuncs[] = -{ - {"glDeleteObjectARB", (void **) &pglDeleteObjectARB}, - {"glGetHandleARB", (void **) &pglGetHandleARB}, - {"glDetachObjectARB", (void **) &pglDetachObjectARB}, - {"glCreateShaderObjectARB", (void **) &pglCreateShaderObjectARB}, - {"glShaderSourceARB", (void **) &pglShaderSourceARB}, - {"glCompileShaderARB", (void **) &pglCompileShaderARB}, - {"glCreateProgramObjectARB", (void **) &pglCreateProgramObjectARB}, - {"glAttachObjectARB", (void **) &pglAttachObjectARB}, - {"glLinkProgramARB", (void **) &pglLinkProgramARB}, - {"glUseProgramObjectARB", (void **) &pglUseProgramObjectARB}, - {"glValidateProgramARB", (void **) &pglValidateProgramARB}, - {"glUniform1fARB", (void **) &pglUniform1fARB}, - {"glUniform2fARB", (void **) &pglUniform2fARB}, - {"glUniform3fARB", (void **) &pglUniform3fARB}, - {"glUniform4fARB", (void **) &pglUniform4fARB}, - {"glUniform1iARB", (void **) &pglUniform1iARB}, - {"glUniform2iARB", (void **) &pglUniform2iARB}, - {"glUniform3iARB", (void **) &pglUniform3iARB}, - {"glUniform4iARB", (void **) &pglUniform4iARB}, - {"glUniform1fvARB", (void **) &pglUniform1fvARB}, - {"glUniform2fvARB", (void **) &pglUniform2fvARB}, - {"glUniform3fvARB", (void **) &pglUniform3fvARB}, - {"glUniform4fvARB", (void **) &pglUniform4fvARB}, - {"glUniform1ivARB", (void **) &pglUniform1ivARB}, - {"glUniform2ivARB", (void **) &pglUniform2ivARB}, - {"glUniform3ivARB", (void **) &pglUniform3ivARB}, - {"glUniform4ivARB", (void **) &pglUniform4ivARB}, - {"glUniformMatrix2fvARB", (void **) &pglUniformMatrix2fvARB}, - {"glUniformMatrix3fvARB", (void **) &pglUniformMatrix3fvARB}, - {"glUniformMatrix4fvARB", (void **) &pglUniformMatrix4fvARB}, - {"glGetObjectParameterfvARB", (void **) &pglGetObjectParameterfvARB}, - {"glGetObjectParameterivARB", (void **) &pglGetObjectParameterivARB}, - {"glGetInfoLogARB", (void **) &pglGetInfoLogARB}, - {"glGetAttachedObjectsARB", (void **) &pglGetAttachedObjectsARB}, - {"glGetUniformLocationARB", (void **) &pglGetUniformLocationARB}, - {"glGetActiveUniformARB", (void **) &pglGetActiveUniformARB}, - {"glGetUniformfvARB", (void **) &pglGetUniformfvARB}, - {"glGetUniformivARB", (void **) &pglGetUniformivARB}, - {"glGetShaderSourceARB", (void **) &pglGetShaderSourceARB}, - {"glVertexAttribPointerARB", (void **) &pglVertexAttribPointerARB}, - {"glEnableVertexAttribArrayARB", (void **) &pglEnableVertexAttribArrayARB}, - {"glDisableVertexAttribArrayARB", (void **) &pglDisableVertexAttribArrayARB}, - {"glBindAttribLocationARB", (void **) &pglBindAttribLocationARB}, - {"glGetActiveAttribARB", (void **) &pglGetActiveAttribARB}, - {"glGetAttribLocationARB", (void **) &pglGetAttribLocationARB}, - {NULL, NULL} -}; - -static dllfunc_t vertexshaderfuncs[] = -{ - {"glVertexAttribPointerARB", (void **) &pglVertexAttribPointerARB}, - {"glEnableVertexAttribArrayARB", (void **) &pglEnableVertexAttribArrayARB}, - {"glDisableVertexAttribArrayARB", (void **) &pglDisableVertexAttribArrayARB}, - {"glBindAttribLocationARB", (void **) &pglBindAttribLocationARB}, - {"glGetActiveAttribARB", (void **) &pglGetActiveAttribARB}, - {"glGetAttribLocationARB", (void **) &pglGetAttribLocationARB}, - {NULL, NULL} -}; - -static dllfunc_t vbofuncs[] = -{ - {"glBindBufferARB" , (void **) &pglBindBufferARB}, - {"glDeleteBuffersARB" , (void **) &pglDeleteBuffersARB}, - {"glGenBuffersARB" , (void **) &pglGenBuffersARB}, - {"glIsBufferARB" , (void **) &pglIsBufferARB}, - {"glMapBufferARB" , (void **) &pglMapBufferARB}, - {"glUnmapBufferARB" , (void **) &pglUnmapBufferARB}, - {"glBufferDataARB" , (void **) &pglBufferDataARB}, - {"glBufferSubDataARB" , (void **) &pglBufferSubDataARB}, - {NULL, NULL} -}; - -static dllfunc_t occlusionfunc[] = -{ - {"glGenQueriesARB" , (void **) &pglGenQueriesARB}, - {"glDeleteQueriesARB" , (void **) &pglDeleteQueriesARB}, - {"glIsQueryARB" , (void **) &pglIsQueryARB}, - {"glBeginQueryARB" , (void **) &pglBeginQueryARB}, - {"glEndQueryARB" , (void **) &pglEndQueryARB}, - {"glGetQueryivARB" , (void **) &pglGetQueryivARB}, - {"glGetQueryObjectivARB" , (void **) &pglGetQueryObjectivARB}, - {"glGetQueryObjectuivARB", (void **) &pglGetQueryObjectuivARB}, - {NULL, NULL} -}; - -static dllfunc_t texturecompressionfuncs[] = -{ - {"glCompressedTexImage3DARB", (void **) &pglCompressedTexImage3DARB}, - {"glCompressedTexImage2DARB", (void **) &pglCompressedTexImage2DARB}, - {"glCompressedTexImage1DARB", (void **) &pglCompressedTexImage1DARB}, - {"glCompressedTexSubImage3DARB", (void **) &pglCompressedTexSubImage3DARB}, - {"glCompressedTexSubImage2DARB", (void **) &pglCompressedTexSubImage2DARB}, - {"glCompressedTexSubImage1DARB", (void **) &pglCompressedTexSubImage1DARB}, - {"glGetCompressedTexImageARB", (void **) &pglGetCompressedTexImage}, - {NULL, NULL} -}; - -/* -================= -R_RenderInfo_f -================= -*/ -void R_RenderInfo_f( void ) -{ - glConfig.extensions_string = pglGetString( GL_EXTENSIONS ); - Msg("\n"); - Msg("GL_VENDOR: %s\n", glConfig.vendor_string); - Msg("GL_RENDERER: %s\n", glConfig.renderer_string); - Msg("GL_VERSION: %s\n", glConfig.version_string); - Msg("GL_EXTENSIONS: %s\n", glConfig.extensions_string); - - Msg("GL_MAX_TEXTURE_SIZE: %i\n", glConfig.max_2d_texture_size ); - - if( GL_Support( R_ARB_MULTITEXTURE )) - Msg("GL_MAX_TEXTURE_UNITS_ARB: %i\n", glConfig.max_texture_units ); - if( GL_Support( R_TEXTURECUBEMAP_EXT )) - Msg("GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB: %i\n", glConfig.max_cubemap_texture_size ); - if( GL_Support( R_ANISOTROPY_EXT )) - Msg("GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: %.1f\n", glConfig.max_texture_anisotropy ); - if( glConfig.texRectangle ) - Msg("GL_MAX_RECTANGLE_TEXTURE_SIZE_NV: %i\n", glConfig.max_2d_rectangle_size ); - - Msg("\n"); - Msg("MODE: %i, %i x %i %s\n", r_mode->integer, r_width->integer, r_height->integer, (glState.fullScreen) ? "fullscreen" : "windowed" ); - Msg("GAMMA: %s w/ %i overbright bits\n", (glConfig.deviceSupportsGamma) ? "hardware" : "software", (glConfig.deviceSupportsGamma) ? r_overbrightbits->integer : 0 ); - Msg("\n"); - Msg( "CDS: %s\n", glConfig.allowCDS ? "enabled" : "disabled" ); - Msg( "PICMIP: %i\n", r_picmip->integer ); - Msg( "TEXTUREMODE: %s\n", gl_texturemode->string ); - Msg( "VERTICAL SYNC: %s\n", r_swapInterval->integer ? "enabled" : "disabled" ); -} - -//======================================================================= - -void GL_InitCommands( void ) -{ - Cbuf_AddText( "vidlatch\n" ); - Cbuf_Execute(); - - // system screen width and height (don't suppose for change from console at all) - r_width = Cvar_Get( "width", "640", CVAR_READ_ONLY, "screen width" ); - r_height = Cvar_Get( "height", "480", CVAR_READ_ONLY, "screen height" ); - - r_norefresh = Cvar_Get( "r_norefresh", "0", 0, "disable rendering (use with caution)" ); - r_fullbright = Cvar_Get( "r_fullbright", "0", CVAR_CHEAT, "disable lightmaps, get fullbright for entities" ); - r_lightmap = Cvar_Get( "r_lightmap", "0", CVAR_CHEAT, "lightmap debugging tool" ); - r_drawentities = Cvar_Get( "r_drawentities", "1", CVAR_CHEAT|CVAR_ARCHIVE, "render entities" ); - r_drawworld = Cvar_Get( "r_drawworld", "1", CVAR_CHEAT, "render world" ); - r_novis = Cvar_Get( "r_novis", "0", 0, "ignore vis information (perfomance test)" ); - r_nocull = Cvar_Get( "r_nocull", "0", 0, "ignore frustrum culling (perfomance test)" ); - r_speeds = Cvar_Get( "r_speeds", "0", CVAR_ARCHIVE, "shows r_speeds" ); - r_drawelements = Cvar_Get( "r_drawelements", "1", 0, "use gldrawElements or glDrawRangeElements" ); - gl_wireframe = Cvar_Get( "gl_wireframe", "0", CVAR_CHEAT, "show mesh triangles" ); - r_lockpvs = Cvar_Get( "r_lockpvs", "0", CVAR_CHEAT, "lockpvs area at current point (pvs test)" ); - gl_clear = Cvar_Get( "gl_clear", "0", CVAR_ARCHIVE, "clearing screen after each frame" ); - r_mode = Cvar_Get( "r_mode", VID_DEFAULTMODE, CVAR_RENDERINFO, "display resolution mode" ); - r_nobind = Cvar_Get( "r_nobind", "0", 0, "disable all textures (perfomance test)" ); - r_picmip = Cvar_Get( "r_picmip", "0", CVAR_RENDERINFO|CVAR_LATCH_VIDEO, "reduces resolution of textures by powers of 2" ); - r_skymip = Cvar_Get( "r_skymip", "0", CVAR_RENDERINFO|CVAR_LATCH_VIDEO, "reduces resolution of skybox textures by powers of 2" ); - r_lefthand = Cvar_Get( "hand", "0", CVAR_ARCHIVE, "viewmodel handedness" ); - r_physbdebug = Cvar_Get( "cm_debugdraw", "0", CVAR_ARCHIVE, "draw physics hulls" ); - - r_bloom_alpha = Cvar_Get( "r_bloom_alpha", "0.2", CVAR_ARCHIVE, "bloom alpha multiplier" ); - r_bloom_diamond_size = Cvar_Get( "r_bloom_diamond_size", "8", CVAR_ARCHIVE, "bloom diamond size (can be 1, 2, 4, 6 or 8)" ); - r_bloom_intensity = Cvar_Get( "r_bloom_intensity", "0", CVAR_ARCHIVE, "bloom intensity scale" ); - r_bloom_darken = Cvar_Get( "r_bloom_darken", "4", CVAR_ARCHIVE, "bloom darken scale" ); - r_bloom_sample_size = Cvar_Get( "r_bloom_sample_size", "320", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "bloom rendering viewport size (must be power of two)" ); - r_bloom_fast_sample = Cvar_Get( "r_bloom_fast_sample", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "enable fast bloom pass" ); - - r_environment_color = Cvar_Get( "r_environment_color", "128 128 128", CVAR_ARCHIVE, "map environment light color" ); - r_ignorehwgamma = Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "ignore hardware gamma (e.g. not support)" ); - r_overbrightbits = Cvar_Get( "r_overbrightbits", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "renderer overbright bits" ); - r_vertexbuffers = Cvar_Get( "r_vertexbuffers", "0", CVAR_ARCHIVE, "store vertex data in VBOs" ); - - r_detailtextures = Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE, "enable or disable detail textures" ); - r_flares = Cvar_Get( "r_flares", "0", CVAR_ARCHIVE, "enable auto-flares rendering" ); - r_flaresize = Cvar_Get( "r_flaresize", "40", CVAR_ARCHIVE, "override shader flare size" ); - r_flarefade = Cvar_Get( "r_flarefade", "3", CVAR_ARCHIVE, "override shader flare fading" ); - r_spriteflares = Cvar_Get( "r_spriteflares", "0", CVAR_ARCHIVE, "enable env_sprite flares rendering" ); - r_cullflares = Cvar_Get( "r_cullflares", "0", CVAR_ARCHIVE, "enable precision env_sprite flares culling" ); - - r_dynamiclight = Cvar_Get( "r_dynamiclight", "1", CVAR_ARCHIVE, "allow dinamic lights on a map" ); - r_coronascale = Cvar_Get( "r_coronascale", "0.2", 0, "light coronas scale" ); - r_subdivisions = Cvar_Get( "r_subdivisions", "4", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "bezier curve subdivision" ); - r_faceplanecull = Cvar_Get( "r_faceplanecull", "1", CVAR_ARCHIVE, "culling face planes" ); - r_shownormals = Cvar_Get( "r_shownormals", "0", CVAR_CHEAT, "show mesh normals" ); - r_showtextures = Cvar_Get("r_showtextures", "0", CVAR_CHEAT, "show all uploaded textures" ); - r_draworder = Cvar_Get( "r_draworder", "0", CVAR_CHEAT, "ignore mesh sorting" ); - r_adjust_fov = Cvar_Get( "r_adjust_fov", "1", CVAR_ARCHIVE, "making FOV adjustment for wide-screens" ); - - r_fastsky = Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE, "enable algorhytem fo fast sky rendering (for old machines)" ); - r_portalonly = Cvar_Get( "r_portalonly", "0", 0, "render only portals" ); - r_portalmaps = Cvar_Get( "r_portalmaps", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "use portal maps for portal rendering" ); - r_portalmaps_maxtexsize = Cvar_Get( "r_portalmaps_maxtexsize", "512", CVAR_ARCHIVE, "portal maps texture dims" ); - - r_allow_software = Cvar_Get( "r_allow_software", "0", CVAR_ARCHIVE, "allow OpenGL software emulation" ); - r_3dlabs_broken = Cvar_Get( "r_3dlabs_broken", "1", CVAR_ARCHIVE, "3dLabs renderer issues" ); - - r_lighting_bumpscale = Cvar_Get( "r_lighting_bumpscale", "8", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "lighting bumpscale" ); - r_lighting_deluxemapping = Cvar_Get( "r_lighting_deluxemapping", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "allow deluxemapping for some maps" ); - r_lighting_diffuse2heightmap = Cvar_Get( "r_lighting_diffuse2heightmap", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "convert diffuse maps to heightmaps" ); - r_lighting_specular = Cvar_Get( "r_lighting_specular", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "using lighting specular" ); - r_lighting_glossintensity = Cvar_Get( "r_lighting_glossintensity", "2", CVAR_ARCHIVE, "gloss intensity" ); - r_lighting_glossexponent = Cvar_Get( "r_lighting_glossexponent", "48", CVAR_ARCHIVE, "gloss exponent factor" ); - r_lighting_models_followdeluxe = Cvar_Get( "r_lighting_models_followdeluxe", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "no description" ); - r_lighting_ambientscale = Cvar_Get( "r_lighting_ambientscale", "0.6", 0, "map ambient lighting scale" ); - r_lighting_directedscale = Cvar_Get( "r_lighting_directedscale", "1", 0, "map directed lighting scale" ); - r_lighting_modulate = Cvar_Get( "r_lighting_modulate", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "lightstyles modulate scale" ); - - r_offsetmapping = Cvar_Get( "r_offsetmapping", "2", CVAR_ARCHIVE, "offsetmapping factor" ); - r_offsetmapping_scale = Cvar_Get( "r_offsetmapping_scale", "0.02", CVAR_ARCHIVE, "offsetmapping scale" ); - r_offsetmapping_reliefmapping = Cvar_Get( "r_offsetmapping_reliefmapping", "0", CVAR_ARCHIVE, "use reliefmapping instead offesetmapping" ); - - r_occlusion_queries = Cvar_Get( "r_occlusion_queries", "2", CVAR_ARCHIVE, "use occlusion queries culling" ); - r_occlusion_queries_finish = Cvar_Get( "r_occlusion_queries_finish", "1", CVAR_ARCHIVE, "use glFinish for occlusion queries" ); - - r_shadows = Cvar_Get( "r_shadows", "0", CVAR_ARCHIVE, "enable model shadows (1 - simple planar, 2 - shadowmaps)" ); - r_shadows_alpha = Cvar_Get( "r_shadows_alpha", "0.4", CVAR_ARCHIVE, "planar shadows alpha-value" ); - r_shadows_nudge = Cvar_Get( "r_shadows_nudge", "1", CVAR_ARCHIVE, "planar shadows nudge factor" ); - r_shadows_projection_distance = Cvar_Get( "r_shadows_projection_distance", "32", CVAR_ARCHIVE, "maximum projection dist for planar shadows" ); - r_shadows_maxtexsize = Cvar_Get( "r_shadows_maxtexsize", "0", CVAR_ARCHIVE, "shadowmaps texture size (0 - custom)" ); - r_shadows_pcf = Cvar_Get( "r_shadows_pcf", "0", CVAR_ARCHIVE, "allow pcf filtration" ); - r_shadows_self_shadow = Cvar_Get( "r_shadows_self_shadow", "0", CVAR_ARCHIVE, "allow self-shadowing" ); - - r_himodels = Cvar_Get( "cl_himodels", "1", CVAR_ARCHIVE, "draw high-resolution player models in multiplayer" ); - r_decals = Cvar_Get( "r_decals", "4096", CVAR_ARCHIVE, "sets the maximum number of decals" ); - - r_gamma = Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE, "gamma amount" ); - r_colorbits = Cvar_Get( "r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH_VIDEO, "pixelformat color bits (0 - auto)" ); - r_depthbits = Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH_VIDEO, "pixelformat depth bits (0 - auto)" ); - r_texturebits = Cvar_Get( "r_texturebits", "0", CVAR_ARCHIVE | CVAR_LATCH_VIDEO, "no description" ); - gl_texturemode = Cvar_Get( "gl_texturemode", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE, "texture filter" ); - gl_texture_anisotropy = Cvar_Get( "r_anisotropy", "2.0", CVAR_ARCHIVE, "textures anisotropic filter" ); - gl_texture_lodbias = Cvar_Get( "r_texture_lodbias", "0.0", CVAR_ARCHIVE, "LOD bias for mipmapped textures" ); - gl_round_down = Cvar_Get( "gl_round_down", "0", CVAR_RENDERINFO, "down size non-power of two textures" ); - gl_compress_textures = Cvar_Get( "gl_compress_textures", "0", CVAR_ARCHIVE|CVAR_LATCH, "compress textures in video memory" ); - r_stencilbits = Cvar_Get( "r_stencilbits", "8", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "pixelformat stencil bits (0 - auto)" ); - r_check_errors = Cvar_Get("r_check_errors", "1", CVAR_ARCHIVE, "ignore video engine errors" ); - r_swapInterval = Cvar_Get( "r_swapInterval", "0", CVAR_ARCHIVE, "time beetween frames (in msec)" ); - - // make sure r_swapinterval is checked after vid_restart - r_swapInterval->modified = true; - - gl_finish = Cvar_Get( "gl_finish", "0", CVAR_ARCHIVE, "use glFinish instead of glFlush" ); - gl_delayfinish = Cvar_Get( "gl_delayfinish", "1", CVAR_ARCHIVE, "no description" ); - gl_cull = Cvar_Get( "gl_cull", "1", 0, "allow GL_CULL_FACE" ); - gl_driver = Cvar_Get( "gl_driver", "opengl32.dll", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "OpenGl default driver name" ); - r_frontbuffer = Cvar_Get( "r_frontbuffer", "0", 0, "use back or front buffer" ); - gl_extensions = Cvar_Get( "gl_extensions", "1", CVAR_RENDERINFO, "allow gl_extensions" ); - - vid_displayfrequency = Cvar_Get ( "vid_displayfrequency", "0", CVAR_RENDERINFO|CVAR_LATCH_VIDEO, "fullscreen refresh rate" ); - vid_fullscreen = Cvar_Get( "fullscreen", "0", CVAR_RENDERINFO|CVAR_LATCH_VIDEO, "set in 1 to enable fullscreen mode" ); - - Cmd_AddCommand( "texturelist", R_TextureList_f, "display loaded textures list" ); - Cmd_AddCommand( "shaderlist", R_ShaderList_f, "display loaded shaders list" ); - Cmd_AddCommand( "shaderdump", R_ShaderDump_f, "dump specified shader into console" ); - Cmd_AddCommand( "modellist", Mod_Modellist_f, "display loaded models list" ); - Cmd_AddCommand( "r_info", R_RenderInfo_f, "display openGL supported extensions" ); - Cmd_AddCommand( "glslprogramlist", R_ProgramList_f, "display loaded GLSL shaders list" ); - Cmd_AddCommand( "glslprogramdump", R_ProgramDump_f, "sump GLSL shaders into text file" ); - - if( r_lighting_modulate->value < 1.0f ) Cvar_Set( "r_lighting_modulate", "1" ); -} - -void GL_RemoveCommands( void ) -{ - Cmd_RemoveCommand( "modellist" ); - Cmd_RemoveCommand( "shaderlist" ); - Cmd_RemoveCommand( "shaderdump" ); - Cmd_RemoveCommand( "modellist" ); - Cmd_RemoveCommand( "texturelist" ); - Cmd_RemoveCommand( "glslprogramlist" ); - Cmd_RemoveCommand( "glslprogramdump" ); - Cmd_RemoveCommand( "r_info"); -} - -void GL_InitBackend( void ) -{ - GL_InitCommands(); - - glw_state.wndproc = ri.WndProc; - glw_state.hInst = GetModuleHandle( NULL ); - r_temppool = Mem_AllocPool( "Render Memory" ); - - // get developer mode - glw_state.developer = SI->developer; - - GL_SetDefaultState(); -} - -void GL_ShutdownBackend( void ) -{ - GL_RemoveCommands(); - - Mem_FreePool( &r_temppool ); -} - -void GL_SetExtension( int r_ext, int enable ) -{ - if( r_ext >= 0 && r_ext < R_EXTCOUNT ) - glConfig.extension[r_ext] = enable ? GL_TRUE : GL_FALSE; - else MsgDev( D_ERROR, "GL_SetExtension: invalid extension %d\n", r_ext ); -} - -qboolean GL_Support( int r_ext ) -{ - if( r_ext >= 0 && r_ext < R_EXTCOUNT ) - return glConfig.extension[r_ext] ? true : false; - MsgDev( D_ERROR, "GL_Support: invalid extension %d\n", r_ext ); - return false; -} - -void *GL_GetProcAddress( const char *name ) -{ - void *p = NULL; - - if( pwglGetProcAddress != NULL ) - p = (void *)pwglGetProcAddress( name ); - if( !p ) p = (void *)Sys_GetProcAddress( &opengl_dll, name ); - - return p; -} - -void GL_CheckExtension( const char *name, const dllfunc_t *funcs, const char *cvarname, int r_ext ) -{ - const dllfunc_t *func; - convar_t *parm; - - MsgDev( D_NOTE, "GL_CheckExtension: %s ", name ); - - if( gl_extensions->integer == 0 && r_ext != R_OPENGL_110 ) - { - GL_SetExtension( r_ext, 0 ); // update render info - return; - } - - if( cvarname ) - { - // system config disable extensions - parm = Cvar_Get( cvarname, "1", CVAR_RENDERINFO, va( "enable or disable %s", name )); - GL_SetExtension( r_ext, parm->integer ); // update render info - if( parm->integer == 0 ) - { - MsgDev( D_NOTE, "- disabled\n"); - return; // nothing to process at - } - } - - if((name[2] == '_' || name[3] == '_') && !com.strstr( glConfig.extensions_string, name )) - { - GL_SetExtension( r_ext, false ); // update render info - MsgDev( D_NOTE, "- failed\n"); - return; - } - - // clear exports - for( func = funcs; func && func->name; func++ ) - *func->func = NULL; - - GL_SetExtension( r_ext, true ); // predict extension state - for( func = funcs; func && func->name != NULL; func++ ) - { - // functions are cleared before all the extensions are evaluated - if(!(*func->func = (void *)GL_GetProcAddress( func->name ))) - GL_SetExtension( r_ext, false ); // one or more functions are invalid, extension will be disabled - } - if(GL_Support( r_ext )) MsgDev( D_NOTE, "- enabled\n"); -} - -void GL_BuildGammaTable( void ) -{ - int i, v; - double invGamma, div; - - invGamma = 1.0 / bound( 0.5f, r_gamma->value, 3.0f ); - div = (double)( 1 << max( 0, r_overbrightbits->integer )) / 255.5f; - Mem_Copy( glState.gammaRamp, glState.stateRamp, sizeof( glState.gammaRamp )); - - for( i = 0; i < 256; i++ ) - { - v = (int)(65535.0 * pow(((double)i + 0.5 ) * div, invGamma ) + 0.5 ); - glState.gammaRamp[i+0] = ((word)bound( 0, v, 65535 )); - glState.gammaRamp[i+256] = ((word)bound( 0, v, 65535 )); - glState.gammaRamp[i+512] = ((word)bound( 0, v, 65535 )); - } -} - -void GL_UpdateGammaRamp( void ) -{ - if( r_ignorehwgamma->integer ) return; - if( !glConfig.deviceSupportsGamma ) return; - - GL_BuildGammaTable(); - - if( pwglGetDeviceGammaRamp3DFX ) - pwglSetDeviceGammaRamp3DFX( glw_state.hDC, glState.gammaRamp ); - else SetDeviceGammaRamp( glw_state.hDC, glState.gammaRamp ); -} - -/* -=============== -GL_UpdateSwapInterval -=============== -*/ -void GL_UpdateSwapInterval( void ) -{ - if( r_swapInterval->modified ) - { - r_swapInterval->modified = false; - - if( pwglSwapIntervalEXT ) - pwglSwapIntervalEXT( r_swapInterval->integer ); - } -} - -/* -=============== -GL_SetDefaultTexState -=============== -*/ -static void GL_SetDefaultTexState( void ) -{ - Mem_Set( glState.currentTextures, -1, MAX_TEXTURE_UNITS * sizeof( *glState.currentTextures )); - Mem_Set( glState.currentEnvModes, -1, MAX_TEXTURE_UNITS * sizeof( *glState.currentEnvModes )); - Mem_Set( glState.texIdentityMatrix, 0, MAX_TEXTURE_UNITS * sizeof( *glState.texIdentityMatrix )); - Mem_Set( glState.genSTEnabled, 0, MAX_TEXTURE_UNITS * sizeof( *glState.genSTEnabled )); - Mem_Set( glState.texCoordArrayMode, 0, MAX_TEXTURE_UNITS * sizeof( *glState.texCoordArrayMode )); -} - -/* -=============== -GL_SetDefaultState -=============== -*/ -static void GL_SetDefaultState( void ) -{ - Mem_Set( &glState, 0, sizeof( glState )); - GL_SetDefaultTexState (); - - glState.initializedMedia = false; -} - -/* -=============== -GL_SetDefaults -=============== -*/ -static void GL_SetDefaults( void ) -{ - int i; - - pglFinish(); - - pglClearColor( 1, 0, 0.5, 0.5 ); - - pglEnable( GL_DEPTH_TEST ); - pglDisable( GL_CULL_FACE ); - pglEnable( GL_SCISSOR_TEST ); - pglDepthFunc( GL_LEQUAL ); - pglDepthMask( GL_FALSE ); - - pglColor4f( 1, 1, 1, 1 ); - - if( glState.stencilEnabled ) - { - pglDisable( GL_STENCIL_TEST ); - pglStencilMask( ( GLuint ) ~0 ); - pglStencilFunc( GL_EQUAL, 128, 0xFF ); - pglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); - } - - // enable gouraud shading - pglShadeModel( GL_SMOOTH ); - - pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - pglPolygonOffset( -1, -2 ); - - // properly disable multitexturing at startup - for( i = glConfig.max_texture_units - 1; i > 0; i-- ) - { - GL_SelectTexture( i ); - GL_TexEnv( GL_MODULATE ); - pglDisable( GL_BLEND ); - pglDisable( GL_TEXTURE_2D ); - } - - GL_SelectTexture( 0 ); - pglDisable( GL_BLEND ); - pglDisable( GL_ALPHA_TEST ); - pglDisable( GL_POLYGON_OFFSET_FILL ); - pglEnable( GL_TEXTURE_2D ); - - GL_Cull( 0 ); - GL_FrontFace( 0 ); - - GL_SetState( GLSTATE_DEPTHWRITE ); - GL_TexEnv( GL_MODULATE ); - - R_SetTextureParameters(); - - pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); - pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - - pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); -} - -void GL_InitExtensions( void ) -{ - int flags = 0; - - // initialize gl extensions - GL_CheckExtension( "OpenGL 1.1.0", opengl_110funcs, NULL, R_OPENGL_110 ); - - // get our various GL strings - glConfig.vendor_string = pglGetString( GL_VENDOR ); - glConfig.renderer_string = pglGetString( GL_RENDERER ); - glConfig.version_string = pglGetString( GL_VERSION ); - glConfig.extensions_string = pglGetString( GL_EXTENSIONS ); - MsgDev( D_INFO, "Video: %s\n", glConfig.renderer_string ); - - GL_CheckExtension( "WGL_3DFX_gamma_control", wgl3DFXgammacontrolfuncs, NULL, R_WGL_3DFX_GAMMA_CONTROL ); - GL_CheckExtension( "WGL_EXT_swap_control", wglswapintervalfuncs, NULL, R_WGL_SWAPCONTROL ); - GL_CheckExtension( "glDrawRangeElements", drawrangeelementsfuncs, "gl_drawrangeelments", R_DRAW_RANGEELEMENTS_EXT ); - if(!GL_Support( R_DRAW_RANGEELEMENTS_EXT )) GL_CheckExtension("GL_EXT_draw_range_elements", drawrangeelementsextfuncs, "gl_drawrangeelments", R_DRAW_RANGEELEMENTS_EXT ); - - // multitexture - glConfig.max_texture_units = 1; - GL_CheckExtension("GL_ARB_multitexture", multitexturefuncs, "gl_arb_multitexture", R_ARB_MULTITEXTURE ); - if(GL_Support( R_ARB_MULTITEXTURE )) - { - pglGetIntegerv( GL_MAX_TEXTURE_UNITS_ARB, &glConfig.max_texture_units ); - GL_CheckExtension( "GL_ARB_texture_env_combine", NULL, "gl_texture_env_combine", R_ENV_COMBINE_EXT ); - if(!GL_Support( R_ENV_COMBINE_EXT )) GL_CheckExtension("GL_EXT_texture_env_combine", NULL, "gl_texture_env_combine", R_ENV_COMBINE_EXT ); - if(GL_Support( R_ENV_COMBINE_EXT )) GL_CheckExtension( "GL_ARB_texture_env_dot3", NULL, "gl_texture_env_dot3", R_DOT3_ARB_EXT ); - } - else - { - GL_CheckExtension( "GL_SGIS_multitexture", sgis_multitexturefuncs, "gl_sgis_multitexture", R_ARB_MULTITEXTURE ); - if( GL_Support( R_ARB_MULTITEXTURE )) glConfig.max_texture_units = 2; - } - if( glConfig.max_texture_units == 1 ) GL_SetExtension( R_ARB_MULTITEXTURE, false ); - - // 3d texture support - GL_CheckExtension( "GL_EXT_texture3D", texture3dextfuncs, "gl_texture_3d", R_TEXTURE_3D_EXT ); - if(GL_Support( R_TEXTURE_3D_EXT )) - { - pglGetIntegerv( GL_MAX_3D_TEXTURE_SIZE, &glConfig.max_3d_texture_size ); - if( glConfig.max_3d_texture_size < 32 ) - { - GL_SetExtension( R_TEXTURE_3D_EXT, false ); - MsgDev( D_ERROR, "GL_EXT_texture3D reported bogus GL_MAX_3D_TEXTURE_SIZE, disabled\n" ); - } - } - - GL_CheckExtension( "GL_SGIS_generate_mipmap", NULL, "gl_sgis_generate_mipmaps", R_SGIS_MIPMAPS_EXT ); - - // hardware cubemaps - GL_CheckExtension( "GL_ARB_texture_cube_map", NULL, "gl_texture_cubemap", R_TEXTURECUBEMAP_EXT ); - if(GL_Support( R_TEXTURECUBEMAP_EXT )) pglGetIntegerv( GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, &glConfig.max_cubemap_texture_size ); - - // point particles extension - GL_CheckExtension( "GL_EXT_point_parameters", pointparametersfunc, NULL, R_EXT_POINTPARAMETERS ); - - GL_CheckExtension( "GL_ARB_texture_non_power_of_two", NULL, "gl_texture_npot", R_ARB_TEXTURE_NPOT_EXT ); - GL_CheckExtension( "GL_ARB_texture_compression", texturecompressionfuncs, "gl_dds_hardware_support", R_TEXTURE_COMPRESSION_EXT ); - GL_CheckExtension( "GL_EXT_compiled_vertex_array", compiledvertexarrayfuncs, "gl_cva_support", R_CUSTOM_VERTEX_ARRAY_EXT ); - if(!GL_Support(R_CUSTOM_VERTEX_ARRAY_EXT)) GL_CheckExtension( "GL_SGI_compiled_vertex_array", compiledvertexarrayfuncs, "gl_cva_support", R_CUSTOM_VERTEX_ARRAY_EXT ); - GL_CheckExtension( "GL_EXT_texture_edge_clamp", NULL, "gl_clamp_to_edge", R_CLAMPTOEDGE_EXT ); - if(!GL_Support( R_CLAMPTOEDGE_EXT )) GL_CheckExtension("GL_SGIS_texture_edge_clamp", NULL, "gl_clamp_to_edge", R_CLAMPTOEDGE_EXT ); - - glConfig.max_texture_anisotropy = 0.0f; - GL_CheckExtension( "GL_EXT_texture_filter_anisotropic", NULL, "gl_ext_anisotropic_filter", R_ANISOTROPY_EXT ); - if(GL_Support( R_ANISOTROPY_EXT )) pglGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glConfig.max_texture_anisotropy ); - - GL_CheckExtension( "GL_EXT_texture_lod_bias", NULL, "gl_ext_texture_lodbias", R_TEXTURE_LODBIAS ); - if(GL_Support( R_TEXTURE_LODBIAS )) pglGetFloatv( GL_MAX_TEXTURE_LOD_BIAS_EXT, &glConfig.max_texture_lodbias ); - - GL_CheckExtension( "GL_ARB_texture_border_clamp", NULL, "gl_ext_texborder_clamp", R_CLAMP_TEXBORDER_EXT ); - - GL_CheckExtension( "GL_EXT_blend_minmax", blendequationfuncs, "gl_ext_customblend", R_BLEND_MINMAX_EXT ); - GL_CheckExtension( "GL_EXT_blend_subtract", blendequationfuncs, "gl_ext_customblend", R_BLEND_SUBTRACT_EXT ); - - GL_CheckExtension( "glStencilOpSeparate", gl2separatestencilfuncs, "gl_separate_stencil",R_SEPARATESTENCIL_EXT ); - if(!GL_Support( R_SEPARATESTENCIL_EXT )) GL_CheckExtension("GL_ATI_separate_stencil", atiseparatestencilfuncs, "gl_separate_stencil", R_SEPARATESTENCIL_EXT ); - - GL_CheckExtension( "GL_EXT_stencil_two_side", stenciltwosidefuncs, "gl_stenciltwoside", R_STENCILTWOSIDE_EXT ); - GL_CheckExtension( "GL_ARB_vertex_buffer_object", vbofuncs, "gl_vertex_buffer_object", R_ARB_VERTEX_BUFFER_OBJECT_EXT ); - - // we don't care if it's an extension or not, they are identical functions, so keep it simple in the rendering code - if( pglDrawRangeElementsEXT == NULL ) pglDrawRangeElementsEXT = pglDrawRangeElements; - - GL_CheckExtension( "GL_ARB_texture_env_add", NULL, "gl_texture_env_add", R_TEXTURE_ENV_ADD_EXT ); - - // vp and fp shaders - GL_CheckExtension( "GL_ARB_shader_objects", shaderobjectsfuncs, "gl_shaderobjects", R_SHADER_OBJECTS_EXT ); - GL_CheckExtension( "GL_ARB_shading_language_100", NULL, "gl_glslprogram", R_SHADER_GLSL100_EXT ); - GL_CheckExtension( "GL_ARB_vertex_shader", vertexshaderfuncs, "gl_vertexshader", R_VERTEX_SHADER_EXT ); - GL_CheckExtension( "GL_ARB_fragment_shader", NULL, "gl_pixelshader", R_FRAGMENT_SHADER_EXT ); - - GL_CheckExtension( "GL_ARB_depth_texture", NULL, "gl_depthtexture", R_DEPTH_TEXTURE ); - GL_CheckExtension( "GL_ARB_shadow", NULL, "gl_arb_shadow", R_SHADOW_EXT ); - GL_CheckExtension( "GLSL_no_half_types", NULL, "glsl_no_half_types", R_GLSL_NO_HALF_TYPES ); - GL_CheckExtension( "GLSL_branching", NULL, "glsl_branching", R_GLSL_BRANCHING ); - - // occlusion queries - GL_CheckExtension( "GL_ARB_occlusion_query", occlusionfunc, "gl_occlusion_queries", R_OCCLUSION_QUERIES_EXT ); - - // rectangle textures support - if( com.strstr( glConfig.extensions_string, "GL_NV_texture_rectangle" )) - { - glConfig.texRectangle = GL_TEXTURE_RECTANGLE_NV; - pglGetIntegerv( GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, &glConfig.max_2d_rectangle_size ); - } - else if( com.strstr( glConfig.extensions_string, "GL_EXT_texture_rectangle" )) - { - glConfig.texRectangle = GL_TEXTURE_RECTANGLE_EXT; - pglGetIntegerv( GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT, &glConfig.max_2d_rectangle_size ); - } - else glConfig.texRectangle = glConfig.max_2d_rectangle_size = 0; // no rectangle - - glConfig.max_2d_texture_size = 0; - pglGetIntegerv( GL_MAX_TEXTURE_SIZE, &glConfig.max_2d_texture_size ); - if( glConfig.max_2d_texture_size <= 0 ) glConfig.max_2d_texture_size = 256; - - Cvar_Get( "gl_max_texture_size", "0", CVAR_INIT, "opengl texture max dims" ); - Cvar_Set( "gl_max_texture_size", va( "%i", glConfig.max_2d_texture_size )); - - // MCD has buffering issues - if(com.strstr( glConfig.renderer_string, "gdi" )) - Cvar_SetFloat( "gl_finish", 1 ); - - glConfig.allowCDS = true; - if( com.strstr( glConfig.renderer_string, "permedia" ) || com.strstr( glConfig.renderer_string, "glint" )) - { - if( r_3dlabs_broken->integer ) - glConfig.allowCDS = false; - else glConfig.allowCDS = true; - } - - Cvar_Set( "r_anisotropy", va( "%f", bound( 0, gl_texture_anisotropy->value, glConfig.max_texture_anisotropy ))); - - // software mipmap generator does wrong result with NPOT textures ... - if( !GL_Support( R_SGIS_MIPMAPS_EXT )) GL_SetExtension( R_ARB_TEXTURE_NPOT_EXT, false ); - - flags |= IL_USE_LERPING|IL_ALLOW_OVERWRITE; - - Image_Init( NULL, flags ); - glw_state.initialized = true; -} - -/* -=============== -R_InitMedia -=============== -*/ -static void R_InitMedia( void ) -{ - if( glState.initializedMedia ) - return; - - R_InitMeshLists(); - R_InitGLSLPrograms(); - R_InitImages(); - R_InitShaders(); - R_InitModels(); - R_InitDecals(); - R_InitCoronas(); - R_InitShadows(); - R_InitOcclusionQueries(); - R_InitCustomColors (); - - GL_SetDefaultTexState (); - - Mem_Set( &RI, 0, sizeof( refinst_t )); - - glState.initializedMedia = true; -} - -/* -=============== -R_FreeMedia -=============== -*/ -static void R_FreeMedia( void ) -{ - if( !glState.initializedMedia ) - return; - - R_FreeSky(); - R_ShutdownOcclusionQueries(); - R_ShutdownDecals(); - R_ShutdownShadows(); - R_ShutdownModels(); - R_ShutdownShaders(); - R_ShutdownImages(); - R_ShutdownGLSLPrograms(); - - R_FreeMeshLists(); - - glState.initializedMedia = false; -} - -qboolean R_Init( qboolean full ) -{ - if( full ) - { - GL_InitBackend(); - - // create the window and set up the context - if( !R_Init_OpenGL()) - { - R_Free_OpenGL(); - return false; - } - - GL_InitExtensions(); - GL_SetDefaults(); - - R_BackendInit(); - R_ClearScene(); - } - R_InitMedia(); - R_CheckForErrors(); - - return true; -} - -/* -=============== -R_Shutdown -=============== -*/ -void R_Shutdown( qboolean full ) -{ - // free shaders, models, etc. - R_FreeMedia(); - - if( full ) - { - GL_ShutdownBackend (); - - // shutdown rendering backend - R_BackendShutdown(); - - // shut down OS specific OpenGL stuff like contexts, etc. - R_Free_OpenGL(); - } -} - -/* -=============== -R_NewMap - -do some cleanup operations -=============== -*/ -void R_NewMap( void ) -{ - R_ShutdownOcclusionQueries(); - R_FreeMeshLists(); - - R_InitMeshLists(); - R_InitOcclusionQueries(); - - R_InitCustomColors(); // clear custom colors - R_InitCoronas(); // update corona shader (because we can't make it static) - - R_StudioFreeAllExtradata(); // free boneposes - R_ClearDecals(); // purge all decals - - Mem_EmptyPool( r_temppool ); // release all temp data - GL_SetDefaultTexState (); - Mem_Set( &RI, 0, sizeof( refinst_t )); - r_worldbrushmodel = NULL; // during loading process - r_worldmodel = NULL; -} \ No newline at end of file diff --git a/vid_gl/r_shader.c b/vid_gl/r_shader.c deleted file mode 100644 index a81d9bf4..00000000 --- a/vid_gl/r_shader.c +++ /dev/null @@ -1,4191 +0,0 @@ -/* -Copyright (C) 1999 Stephen C. Taylor -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// r_shader.c - -#include "r_local.h" -#include "wadfile.h" -#include "mathlib.h" - -typedef struct ref_script_s -{ - char *name; - int type; - char *source; - int line; - char *buffer; - size_t size; - struct ref_script_s *nextHash; -} ref_script_t; - -typedef struct -{ - const char *name; - qboolean (*func)( ref_shader_t *shader, ref_stage_t *pass, script_t *script ); -} ref_parsekey_t; - -typedef enum -{ - FREE_IGNORE = 0, // don't free images - FREE_NORMAL, // free dead images that registration period is expired - FREE_FORCE, // must be free anyway -} e_free; - -byte *r_shaderpool; -static table_t *r_tablesHashTable[TABLES_HASH_SIZE]; -static ref_script_t *r_shaderScriptsHash[SHADERS_HASH_SIZE]; -static ref_shader_t *r_shadersHash[SHADERS_HASH_SIZE]; -static table_t *r_tables[MAX_TABLES]; -static int r_numTables; -ref_shader_t r_shaders[MAX_SHADERS]; -static int r_numShaders = 0; -static deform_t r_currentDeforms[MAX_SHADER_DEFORMS]; -static ref_stage_t r_currentPasses[MAX_SHADER_STAGES]; -static float r_currentRGBgenArgs[MAX_SHADER_STAGES][3], r_currentAlphagenArgs[MAX_SHADER_STAGES][2]; -static waveFunc_t r_currentRGBgenFuncs[MAX_SHADER_STAGES], r_currentAlphagenFuncs[MAX_SHADER_STAGES]; -static tcMod_t r_currentTcmods[MAX_SHADER_STAGES][MAX_SHADER_TCMODS]; -static vec4_t r_currentTcGen[MAX_SHADER_STAGES][2]; -const char *r_skyBoxSuffix[6] = { "rt", "bk", "lf", "ft", "up", "dn" }; // FIXME: get rid of this - -static mip_t *r_internalTexture; // pointer to built-in map texture -static texture_t *r_stageTexture[MAX_STAGE_TEXTURES]; // MAX_FRAMES in spritegen.c -static uint r_miptexFeatures; // bmodel miptex features -static int r_shaderRenderMode; // sprite or studiomodel rendermode -static int r_numStageTextures; // num textures in group -static float r_stageAnimFrequency[2]; // anim fps / alt anim fps -static int r_stageAnimOffset; // offset for alternative animation -static qboolean r_shaderTwoSided; -static qboolean r_shaderNoMipMaps; -static qboolean r_shaderNoPicMip; -static qboolean r_shaderNoCompress; -static qboolean r_shaderNearest; -static qboolean r_shaderHasDlightPass; - -#define Shader_CopyString( str ) com.stralloc( r_shaderpool, str, __FILE__, __LINE__ ) -#define Shader_Malloc( size ) Mem_Alloc( r_shaderpool, size ) -#define Shader_Free( data ) Mem_Free( data ) - -/* -======================================================================= - - TABLE PARSING - -======================================================================= -*/ -/* -================= -R_LoadTable -================= -*/ -static void R_LoadTable( const char *name, tableFlags_t flags, size_t size, float *values ) -{ - table_t *table; - uint hash; - - if( r_numTables == MAX_TABLES ) - Host_Error( "R_LoadTable: MAX_TABLES limit exceeds\n" ); - - // fill it in - table = r_tables[r_numTables++] = Mem_Alloc( r_shaderpool, sizeof( table_t )); - table->name = Shader_CopyString( name ); - table->index = r_numTables - 1; - table->flags = flags; - table->size = size; - - table->values = Mem_Alloc( r_shaderpool, size * sizeof( float )); - Mem_Copy( table->values, values, size * sizeof( float )); - - // add to hash table - hash = Com_HashKey( table->name, TABLES_HASH_SIZE ); - table->nextHash = r_tablesHashTable[hash]; - r_tablesHashTable[hash] = table; -} - -/* -================= -R_FindTable -================= -*/ -static table_t *R_FindTable( const char *name ) -{ - table_t *table; - uint hash; - - if( !name || !name[0] ) return NULL; - if( com.strlen( name ) >= MAX_STRING ) - Host_Error( "R_FindTable: table name exceeds %i symbols\n", MAX_STRING ); - - // see if already loaded - hash = Com_HashKey( name, TABLES_HASH_SIZE ); - - for( table = r_tablesHashTable[hash]; table; table = table->nextHash ) - { - if( !com.stricmp( table->name, name )) - return table; - } - return NULL; -} - -/* -================= -R_ParseTable -================= -*/ -static qboolean R_ParseTable( script_t *script, tableFlags_t flags ) -{ - token_t token; - string name; - size_t size = 0, bufsize = 0; - qboolean variable = false; - float *values = NULL; - - if( !Com_ReadToken( script, SC_ALLOW_NEWLINES, &token )) - { - MsgDev( D_WARN, "missing table name\n" ); - return false; - } - - com.strncpy( name, token.string, sizeof( name )); - - Com_ReadToken( script, false, &token ); - if( com.stricmp( token.string, "[" )) - { - MsgDev( D_WARN, "expected '[', found '%s' instead in table '%s'\n", token.string, name ); - return false; - } - - Com_ReadToken( script, false, &token ); - if( com.stricmp( token.string, "]" )) - { - bufsize = com.atoi( token.string ); - if( bufsize <= 0 ) - { - MsgDev( D_WARN, "'%s' have invalid size\n", name ); - return false; - } - - // reserve one slot to avoid corrupt memory - values = Mem_Alloc( r_shaderpool, sizeof( float ) * (bufsize + 1)); - Com_ReadToken( script, false, &token ); - if( com.stricmp( token.string, "]" )) - { - MsgDev( D_WARN, "expected ']', found '%s' instead in table '%s'\n", token.string, name ); - return false; - } - } - else variable = true; // variable sized - - Com_ReadToken( script, false, &token ); - if( com.stricmp( token.string, "=" )) - { - MsgDev( D_WARN, "expected '=', found '%s' instead in table '%s'\n", token.string, name ); - return false; - } - - // parse values now - while( 1 ) - { - if( !Com_ReadToken( script, SC_ALLOW_NEWLINES, &token )) - { - MsgDev( D_WARN, "missing parameters for table '%s'\n", name ); - return false; - } - - if( com.stricmp( token.string, "{" )) - { - MsgDev( D_WARN, "expected '{', found '%s' instead in table '%s'\n", token.string, name ); - return false; - } - - while( 1 ) - { - if( size >= bufsize ) - { - if( variable ) - { - bufsize = size + 8; - values = Mem_Realloc( r_shaderpool, values, sizeof(float) * bufsize ); - } - else if( size > bufsize ) - { - MsgDev( D_WARN, "'%s' too many initializers\n", name ); - if( values ) Mem_Free( values ); - return false; - } - } - - if( size != 0 ) - { - Com_ReadToken( script, SC_ALLOW_NEWLINES, &token ); - if( !com.stricmp( token.string, "}" )) break; // end - else if( !com.stricmp( token.string, ";" )) - { - // save token, to let grab semicolon properly - Com_SaveToken( script, &token ); - break; - } - else if( com.stricmp( token.string, "," )) - { - MsgDev( D_WARN, "expected ',', found '%s' instead in table '%s'\n", token.string, name ); - if( values ) Mem_Free( values ); - return false; - } - } - - if( !Com_ReadFloat( script, SC_ALLOW_NEWLINES, &values[size] )) - { - if( size != 0 ) continue; // probably end of the table - else - { - MsgDev( D_WARN, "'%s' is empty table\n", name ); - if( values ) Mem_Free( values ); - return false; // empty table ? - } - } - size++; - } - break; - } - - // check sizes - if( !variable && size < bufsize ) - MsgDev( D_WARN, "'%s' have explicit size %i, but real size is %i\n", name, bufsize, size ); - - Com_ReadToken( script, SC_ALLOW_NEWLINES, &token ); - if( com.stricmp( token.string, ";" )) - { - MsgDev( D_WARN, "'%s' missing seimcolon at end of table definition\n", name ); - Com_SaveToken( script, &token ); - } - - // register new table - R_LoadTable( name, flags, size, values ); - return true; -} - -/* -================= -R_LookupTable -================= -*/ -float R_LookupTable( int tableIndex, float index ) -{ - table_t *table; - float frac, value; - uint curIndex, oldIndex; - - if( tableIndex < 0 || tableIndex >= r_numTables ) - Host_Error( "R_LookupTable: out of range\n" ); - - table = r_tables[tableIndex]; - - index *= table->size; - frac = index - floor(index); - - curIndex = (uint)index + 1; - oldIndex = (uint)index; - - if( table->flags & TABLE_CLAMP ) - { - curIndex = bound( 0, curIndex, table->size - 1 ); - oldIndex = bound( 0, oldIndex, table->size - 1 ); - } - else - { - curIndex %= table->size; - oldIndex %= table->size; - } - - if( table->flags & TABLE_SNAP ) value = table->values[oldIndex]; - else value = table->values[oldIndex] + (table->values[curIndex] - table->values[oldIndex]) * frac; - - return value; -} - -/* -================= -R_GetTableByHandle -================= -*/ -float *R_GetTableByHandle( int tableIndex ) -{ - table_t *table; - - if( tableIndex < 0 || tableIndex >= r_numTables ) - { - MsgDev( D_ERROR, "R_GetTableByHandle: out of range\n" ); - return NULL; - } - table = r_tables[tableIndex]; - - if( !table ) return NULL; - return table->values; -} - - -/* -======================================================================= - - SHADER PARSING - -======================================================================= -*/ -static qboolean Shader_ParseVector( script_t *script, float *v, size_t size ) -{ - uint i; - token_t token; - qboolean bracket = false; - - if( v == NULL || size == 0 ) - return false; - - Mem_Set( v, 0, sizeof( *v ) * size ); - - if( size == 1 ) - return Com_ReadFloat( script, 0, v ); - - if( !Com_ReadToken( script, false, &token )) - return false; - if( token.type == TT_PUNCTUATION && !com.stricmp( token.string, "(" )) - bracket = true; - else Com_SaveToken( script, &token ); // save token to right get it again - - for( i = 0; i < size; i++ ) - { - if( !Com_ReadFloat( script, false, &v[i] )) - v[i] = 0; // because Com_ReadFloat may return 0 if parsing expression it's not a number - } - - if( !bracket ) return true; // done - - if( !Com_ReadToken( script, false, &token )) - return false; - - if( token.type == TT_PUNCTUATION && !com.stricmp( token.string, ")" )) - return true; - return false; -} - -static void Shader_SkipLine( script_t *script ) -{ - Com_SkipRestOfLine( script ); -} - -static void Shader_SkipBlock( script_t *script ) -{ - Com_SkipBracedSection( script, 1 ); -} - -#define MAX_CONDITIONS 8 -typedef enum -{ - COP_LS, - COP_LE, - COP_EQ, - COP_GR, - COP_GE, - COP_NE -} conOp_t; - -typedef enum -{ - COP2_AND, - COP2_OR -} conOp2_t; - -typedef struct -{ - int operand; - conOp_t op; - qboolean negative; - int val; - conOp2_t logic; -} shaderCon_t; - -char *conOpStrings[] = { "<", "<=", "==", ">", ">=", "!=", NULL }; -char *conOpStrings2[] = { "&&", "||", NULL }; - -static qboolean Shader_ParseConditions( script_t *script, ref_shader_t *shader ) -{ - int i; - token_t tok; - int numConditions; - shaderCon_t conditions[MAX_CONDITIONS]; - qboolean result = false, val = false, skip, expectingOperator; - static const int falseCondition = 0; - - numConditions = 0; - Mem_Set( conditions, 0, sizeof( conditions )); - - skip = false; - expectingOperator = false; - while( 1 ) - { - if( !Com_ReadToken( script, false, &tok )) - { - if( expectingOperator ) - numConditions++; - break; - } - if( skip ) continue; - - for( i = 0; conOpStrings[i]; i++ ) - { - if( !com.stricmp( tok.string, conOpStrings[i] )) - break; - } - - if( conOpStrings[i] ) - { - if( !expectingOperator ) - { - MsgDev( D_ERROR, "bad syntax condition in shader '%s'\n", shader->name ); - skip = true; - } - else - { - conditions[numConditions].op = i; - expectingOperator = false; - } - continue; - } - - for( i = 0; conOpStrings2[i]; i++ ) - { - if( !com.stricmp( tok.string, conOpStrings2[i] )) - break; - } - - if( conOpStrings2[i] ) - { - if( !expectingOperator ) - { - MsgDev( D_ERROR, "bad syntax condition in shader '%s'\n", shader->name ); - skip = true; - } - else - { - conditions[numConditions++].logic = i; - if( numConditions == MAX_CONDITIONS ) - skip = true; - else expectingOperator = false; - } - continue; - } - - if( expectingOperator ) - { - MsgDev( D_ERROR, "bad syntax condition in shader '%s'\n", shader->name ); - skip = true; - continue; - } - - if( !com.stricmp( tok.string, "!" )) - { - conditions[numConditions].negative = !conditions[numConditions].negative; - continue; - } - - if( !conditions[numConditions].operand ) - { - if( !com.stricmp( tok.string, "maxTextureSize" )) - conditions[numConditions].operand = glConfig.max_2d_texture_size; - else if( !com.stricmp( tok.string, "maxTextureCubemapSize" )) - conditions[numConditions].operand = glConfig.max_cubemap_texture_size; - else if( !com.stricmp( tok.string, "maxTextureUnits" )) - conditions[numConditions].operand = glConfig.max_texture_units; - else if( !com.stricmp( tok.string, "textureCubeMap" )) - conditions[numConditions].operand = GL_Support( R_TEXTURECUBEMAP_EXT ); - else if( !com.stricmp( tok.string, "textureEnvCombine" )) - conditions[numConditions].operand = GL_Support( R_ENV_COMBINE_EXT ); - else if( !com.stricmp( tok.string, "textureEnvDot3" )) - conditions[numConditions].operand = GL_Support( R_SHADER_GLSL100_EXT ); - else if( !com.stricmp( tok.string, "GLSL" )) - conditions[numConditions].operand = GL_Support( R_SHADER_GLSL100_EXT ); - else if( !com.stricmp( tok.string, "deluxeMaps" ) || !com.stricmp( tok.string, "deluxe" )) - conditions[numConditions].operand = mapConfig.deluxeMappingEnabled; - else if( !com.stricmp( tok.string, "portalMaps" )) - conditions[numConditions].operand = r_portalmaps->integer; - else - { - MsgDev( D_WARN, "unknown expression '%s' in shader '%s'\n", tok, shader->name ); - conditions[numConditions].operand = falseCondition; - } - - conditions[numConditions].operand++; - if( conditions[numConditions].operand < 0 ) - conditions[numConditions].operand = 0; - - if( !skip ) - { - conditions[numConditions].op = COP_NE; - expectingOperator = true; - } - continue; - } - - if( !com.stricmp( tok.string, "false" )) - conditions[numConditions].val = 0; - else if( !com.stricmp( tok.string, "true" )) - conditions[numConditions].val = 1; - else conditions[numConditions].val = com.atoi( tok.string ); - expectingOperator = true; - } - - if( skip ) return false; - - if( !conditions[0].operand ) - { - MsgDev( D_WARN, "empty 'if' statement in shader '%s'\n", shader->name ); - return false; - } - - for( i = 0; i < numConditions; i++ ) - { - conditions[i].operand--; - - switch( conditions[i].op ) - { - case COP_LS: - val = ( conditions[i].operand < conditions[i].val ); - break; - case COP_LE: - val = ( conditions[i].operand <= conditions[i].val ); - break; - case COP_EQ: - val = ( conditions[i].operand == conditions[i].val ); - break; - case COP_GR: - val = ( conditions[i].operand > conditions[i].val ); - break; - case COP_GE: - val = ( conditions[i].operand >= conditions[i].val ); - break; - case COP_NE: - val = ( conditions[i].operand != conditions[i].val ); - break; - default: - break; - } - - if( conditions[i].negative ) - val = !val; - if( i ) - { - switch( conditions[i-1].logic ) - { - case COP2_AND: - result = result && val; - break; - case COP2_OR: - result = result || val; - break; - } - } - else result = val; - } - return result; -} - -static qboolean Shader_SkipConditionBlock( script_t *script ) -{ - token_t tok; - int condition_count = 1; - - while( condition_count > 0 ) - { - if( !Com_ReadToken( script, SC_ALLOW_NEWLINES, &tok )) - return false; - if( !com.stricmp( tok.string, "if" )) - condition_count++; - else if( !com.stricmp( tok.string, "endif" )) - condition_count--; - } - return true; -} - -//=========================================================================== -static qboolean Shader_CheckSkybox( const char *name ) -{ - const char *skybox_ext[5] = { "tga", "bmp", "jpg", "dds" }; - int i, j, num_checked_sides; - const char *sidename; - string loadname; - - com.strncpy( loadname, name, sizeof( loadname )); - FS_StripExtension( loadname ); - if( loadname[com.strlen( loadname ) - 1] == '_' ) - loadname[com.strlen( loadname ) - 1] = '\0'; - - if( FS_FileExists( va( "%s.dds", loadname ))) - return true; - - if( FS_FileExists( va( "%s_.dds", loadname ))) - return true; - - // complex cubemap pack not found, search for skybox images - for( i = 0; i < 5; i++ ) - { - num_checked_sides = 0; - for( j = 0; j < 6; j++ ) - { - // build side name - sidename = va( "%s%s.%s", loadname, r_skyBoxSuffix[j], skybox_ext[i] ); - if( FS_FileExists( sidename )) num_checked_sides++; - - } - - if( num_checked_sides == 6 ) - return true; // image exists - - for( j = 0; j < 6; j++ ) - { - // build side name - sidename = va( "%s_%s.%s", loadname, r_skyBoxSuffix[j], skybox_ext[i] ); - if( FS_FileExists( sidename )) num_checked_sides++; - } - - if( num_checked_sides == 6 ) - return true; // images exists - } - return false; -} - -static qboolean Shader_ParseSkySides( script_t *script, ref_shader_t *shader, ref_shader_t **shaders, qboolean farbox ) -{ - int i, shaderType; - texture_t *image; - string name; - token_t tok; - - Mem_Set( shaders, 0, sizeof( ref_shader_t* ) * 6 ); - - switch( shader->type ) - { - case SHADER_TEXTURE: - case SHADER_SKY: break; - default: - MsgDev( D_ERROR, "'skyParms' not allowed in shader '%s'[%i]\n", shader->name, shader->type ); - return false; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'skyParms' in shader '%s'\n", shader->name ); - return false; - } - - if( com.stricmp( tok.string, "-" ) && com.stricmp( tok.string, "full" )) - { - shaderType = ( farbox ? SHADER_FARBOX : SHADER_NEARBOX ); - if( tok.string[com.strlen( tok.string ) - 1] == '_' ) - tok.string[com.strlen( tok.string ) - 1] = '\0'; - - for( i = 0; i < 6; i++ ) - { - com.snprintf( name, sizeof( name ), "%s%s", tok.string, r_skyBoxSuffix[i] ); - image = R_FindTexture( name, NULL, 0, TF_CLAMP|TF_NOMIPMAP|TF_SKYSIDE ); - if( !image ) break; - shaders[i] = R_LoadShader( image->name, shaderType, true, image->flags, SHADER_INVALID ); - } - if( i == 6 ) return true; - - for( i = 0; i < 6; i++ ) - { - com.snprintf( name, sizeof( name ), "%s_%s", tok.string, r_skyBoxSuffix[i] ); - image = R_FindTexture( name, NULL, 0, TF_CLAMP|TF_NOMIPMAP|TF_SKYSIDE ); - if( !image ) break; - shaders[i] = R_LoadShader( image->name, shaderType, true, image->flags, SHADER_INVALID ); - } - if( i == 6 ) return true; - - // create default skybox - for( i = 0; i < 6; i++ ) - { - image = tr.skyTexture; - shaders[i] = R_LoadShader( image->name, shaderType, true, image->flags, SHADER_INVALID ); - } - return true; - } - return true; -} - -static qboolean Shader_ParseFunc( script_t *script, waveFunc_t *func, ref_shader_t *shader ) -{ - token_t tok; - table_t *tb; - - if( !Com_ReadToken( script, false, &tok )) - return false; - - func->tableIndex = -1; - - if( !com.stricmp( tok.string, "0" )) func->type = WAVEFORM_SIN; - else if( !com.stricmp( tok.string, "sin" )) func->type = WAVEFORM_SIN; - else if( !com.stricmp( tok.string, "triangle" )) func->type = WAVEFORM_TRIANGLE; - else if( !com.stricmp( tok.string, "square" )) func->type = WAVEFORM_SQUARE; - else if( !com.stricmp( tok.string, "sawtooth" )) func->type = WAVEFORM_SAWTOOTH; - else if( !com.stricmp( tok.string, "inverseSawtooth" )) func->type = WAVEFORM_INVERSESAWTOOTH; - else if( !com.stricmp( tok.string, "noise" )) func->type = WAVEFORM_NOISE; - else - { // check for custom table - tb = R_FindTable( tok.string ); - if( tb ) - { - func->type = WAVEFORM_TABLE; - func->tableIndex = tb->index; - } - else - { - MsgDev( D_WARN, "unknown waveform '%s' in shader '%s', defaulting to sin\n", tok.string, shader->name ); - func->type = WAVEFORM_SIN; - } - } - - if( !Shader_ParseVector( script, func->args, 4 )) - { - MsgDev( D_ERROR, "misson waveform parms in shader '%s'\n", shader->name ); - return false; - } - return true; -} - -//=========================================================================== - -static int Shader_SetImageFlags( ref_shader_t *shader ) -{ - int flags = 0; - - if( shader->flags & SHADER_SKYPARMS ) - flags |= TF_SKYSIDE; - if( r_shaderNoMipMaps ) - flags |= TF_NOMIPMAP; - if( r_shaderNoPicMip ) - flags |= TF_NOPICMIP; - if( r_shaderNoCompress ) - flags |= TF_UNCOMPRESSED; - if( r_shaderNearest ) - flags |= TF_NEAREST; - return flags; -} - -static texture_t *Shader_FindImage( ref_shader_t *shader, const char *name, int flags ) -{ - texture_t *image; - string srcpath; - - if( !com.stricmp( name, "$whiteimage" ) || !com.stricmp( name, "*white" )) - return tr.whiteTexture; - if( !com.stricmp( name, "$blackimage" ) || !com.stricmp( name, "*black" )) - return tr.blackTexture; - if( !com.stricmp( name, "$blankbumpimage" ) || !com.stricmp( name, "*blankbump" )) - return tr.blankbumpTexture; - if( !com.stricmp( name, "$particle" ) || !com.stricmp( name, "*particle" )) - return tr.particleTexture; - if( !com.stricmp( name, "$corona" ) || !com.stricmp( name, "*corona" )) - return tr.coronaTexture; - if( !com.stricmp( name, "$default" )) - { - if( !r_internalTexture ) - { - if( r_numStageTextures ) - { - // most usefully by SHADER_NOMIP - // HACKHACK: apply imageflags specified by shader with external image - image = r_stageTexture[0]; - image->flags |= Shader_SetImageFlags( shader ); - GL_TexFilter( image ); - } - else - { - // this never should happens - MsgDev( D_ERROR, "$default image is missing, apply 'default' image\n" ); - image = tr.defaultTexture; - } - } - else image = Mod_LoadTexture( r_internalTexture ); - - // reset textures counter - r_numStageTextures = 0; - - return image; - } - if( !com.strnicmp( name, "*lm", 3 )) - { - MsgDev( D_WARN, "shader %s has a stage with explicit lightmap image.\n", shader->name ); - return tr.whiteTexture; - } - - if( GI->texpath[0] && shader->type == SHADER_TEXTURE ) - com.snprintf( srcpath, sizeof( srcpath ), "%s/%s", GI->texpath, name ); - else com.strncpy( srcpath, name, sizeof( srcpath )); - if( shader->type != SHADER_STUDIO ) FS_StripExtension( srcpath ); - - image = R_FindTexture( srcpath, NULL, 0, flags ); - if( !image ) - { - MsgDev( D_WARN, "couldn't find texture '%s' in shader '%s'\n", srcpath, shader->name ); - return tr.defaultTexture; - } - return image; -} - -/****************** shader keyword functions ************************/ - -static qboolean Shader_Cull( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - token_t tok; - - shader->flags &= ~(SHADER_CULL_FRONT|SHADER_CULL_BACK); - - if( !Com_ReadToken( script, false, &tok )) - { - shader->flags |= SHADER_CULL_FRONT; - } - else - { - if( !com.stricmp( tok.string, "front" )) - shader->flags |= SHADER_CULL_FRONT; - else if( !com.stricmp( tok.string, "back" ) || !com.stricmp( tok.string, "backSide" ) || !com.stricmp( tok.string, "backSided" )) - shader->flags |= SHADER_CULL_BACK; - else if( !com.stricmp( tok.string, "disable" ) || !com.stricmp( tok.string, "none" ) || !com.stricmp( tok.string, "twoSided" )) - shader->flags &= ~(SHADER_CULL_FRONT|SHADER_CULL_BACK); - else - { - MsgDev( D_ERROR, "unknown 'cull' parameter '%s' in shader '%s'\n", tok.string, shader->name ); - return false; - } - } - return true; -} - -static qboolean Shader_shaderNoMipMaps( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - r_shaderNoMipMaps = r_shaderNoPicMip = true; - return true; -} - -static qboolean Shader_shaderNoPicMip( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - r_shaderNoPicMip = true; - return true; -} - -static qboolean Shader_shaderNoCompress( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - r_shaderNoCompress = true; - return true; -} - -static qboolean Shader_shaderNearest( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - r_shaderNearest = true; - return true; -} - -static qboolean Shader_DeformVertexes( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - token_t tok; - deform_t *deformv; - - if( shader->numDeforms == MAX_SHADER_DEFORMS ) - { - MsgDev( D_ERROR, "MAX_SHADER_DEFORMS hit in shader '%s'\n", shader->name ); - return false; - } - - deformv = &r_currentDeforms[shader->numDeforms]; - - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'deformVertexes' in shader '%s'\n", shader->name ); - return false; - } - - if( !com.stricmp( tok.string, "wave" )) - { - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'deformVertexes wave' in shader '%s'\n", shader->name ); - return false; - } - - deformv->args[0] = com.atof( tok.string ); - if( deformv->args[0] == 0.0f ) - { - MsgDev( D_ERROR, "illegal div value of 0 for 'deformVertexes wave' in shader '%s', defaulting to 100\n", shader->name ); - deformv->args[0] = 100.0f; - } - deformv->args[0] = 1.0 / deformv->args[0]; - - if( !Shader_ParseFunc( script, &deformv->func, shader )) - { - MsgDev( D_ERROR, "missing waveform parameters for 'deformVertexes wave' in shader '%s'\n", shader->name ); - return false; - } - deformv->type = DEFORM_WAVE; - } - else if( !com.stricmp( tok.string, "normal" ) ) - { - if( !Shader_ParseVector( script, deformv->args, 2 )) - { - MsgDev( D_ERROR, "missing parameters for 'deformVertexes move' in shader '%s'\n", shader->name ); - return false; - } - shader->flags |= SHADER_DEFORM_NORMAL; - deformv->type = DEFORM_NORMAL; - } - else if( !com.stricmp( tok.string, "bulge" )) - { - if( !Shader_ParseVector( script, deformv->args, 3 )) - { - MsgDev( D_ERROR, "missing parameters for 'deformVertexes bulge' in shader '%s'\n", shader->name ); - return false; - } - deformv->type = DEFORM_BULGE; - } - else if( !com.stricmp( tok.string, "move" )) - { - if( !Shader_ParseVector( script, deformv->args, 3 )) - { - MsgDev( D_ERROR, "missing parameters for 'deformVertexes move' in shader '%s'\n", shader->name ); - return false; - } - - if(!Shader_ParseFunc( script, &deformv->func, shader )) - { - MsgDev( D_ERROR, "missing waveform parameters for 'deformVertexes move' in shader '%s'\n", shader->name ); - return false; - } - deformv->type = DEFORM_MOVE; - } - else if( !com.stricmp( tok.string, "autosprite" )) - { - deformv->type = DEFORM_AUTOSPRITE; - shader->flags |= SHADER_AUTOSPRITE; - } - else if( !com.stricmp( tok.string, "autosprite2" )) - { - deformv->type = DEFORM_AUTOSPRITE2; - shader->flags |= SHADER_AUTOSPRITE; - } - else if( !com.stricmp( tok.string, "projectionShadow" )) - { - deformv->type = DEFORM_PROJECTION_SHADOW; - } - else if( !com.stricmp( tok.string, "autoparticle" )) - { - deformv->type = DEFORM_AUTOPARTICLE; - } - else - { - MsgDev( D_WARN, "unknown 'deformVertexes' parameter '%s' in shader '%s'\n", tok.string, shader->name ); - Shader_SkipLine( script ); - return true; - } - - shader->numDeforms++; - return true; -} - -static qboolean Shader_SkyParms( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - float cloudHeight; - ref_shader_t *farboxShaders[6]; - ref_shader_t *nearboxShaders[6]; - token_t tok; - - if( shader->skyParms ) - { - R_FreeSkydome( shader->skyParms ); - shader->skyParms = NULL; - } - if( !Shader_ParseSkySides( script, shader, farboxShaders, true )) - { - MsgDev( D_ERROR, "missing far skybox parameters for 'skyParms' in shader '%s'\n", shader->name ); - return false; - } - - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'skyParms' in shader '%s'\n", shader->name ); - return false; - } - - if( com.stricmp( tok.string, "-" )) - { - cloudHeight = com.atof( tok.string ); - if( cloudHeight < 8.0f || cloudHeight > 1024.0f ) - { - MsgDev( D_WARN, "out of range cloudHeight value of %f for 'skyParms' in shader '%s', defaulting to 512\n", cloudHeight, shader->name ); - cloudHeight = 512.0f; - } - } - else cloudHeight = 512.0f; - - // merge farclip - if( cloudHeight * 2 > r_farclip_min ) r_farclip_min = cloudHeight * 2; - - if( !Shader_ParseSkySides( script, shader, nearboxShaders, false )) - { - MsgDev( D_ERROR, "missing near skybox parameters for 'skyParms' in shader '%s'\n", shader->name ); - return false; - } - - shader->skyParms = R_CreateSkydome( r_shaderpool, cloudHeight, farboxShaders, nearboxShaders ); - shader->flags |= SHADER_SKYPARMS; - shader->sort = SORT_SKY; - - return true; -} - -static qboolean Shader_FogParms( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - float div; - vec3_t color, fcolor; - - if( !r_ignorehwgamma->integer ) - div = 1.0f / pow( 2, max( 0, floor( r_overbrightbits->value ))); - else div = 1.0f; - if( IS_NAN( div )) div = 1.0f; // FIXME: strange bug - - Vector4Set( shader->fog_color, 0, 0, 0, 0 ); - shader->fog_dist = shader->fog_clearDist = 0; - - if( !Shader_ParseVector( script, color, 3 )) - { - MsgDev( D_ERROR, "missing fog color for 'fogParms' in shader '%s'\n", shader->name ); - return false; - } - - ColorNormalize( color, fcolor ); - VectorScale( fcolor, div, fcolor ); - - shader->fog_color[0] = R_FloatToByte( fcolor[0] ); - shader->fog_color[1] = R_FloatToByte( fcolor[1] ); - shader->fog_color[2] = R_FloatToByte( fcolor[2] ); - shader->fog_color[3] = 255; - - if( !Com_ReadFloat( script, false, &shader->fog_dist )) - { - MsgDev( D_ERROR, "missing fog distance for 'fogParms' in shader '%s'\n", shader->name ); - return false; - } - - if( shader->fog_dist <= 0.1f ) shader->fog_dist = 128.0f; - - // clear dist is optionally parm - Com_ReadFloat( script, false, &shader->fog_clearDist ); - - if( shader->fog_clearDist > shader->fog_dist - 128.0f ) - shader->fog_clearDist = shader->fog_dist - 128.0f; - if( shader->fog_clearDist <= 0.0f ) shader->fog_clearDist = 0.0f; - - return true; -} - -static qboolean Shader_SkyRotate( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - VectorSet( shader->skyAxis, 0.0f, 0.0f, 1.0f ); - shader->skySpeed = 0.0f; - - if( !Com_ReadFloat( script, false, &shader->skySpeed )) - { - MsgDev( D_ERROR, "missing sky speed for 'skyRotate' in shader '%s'\n", shader->name ); - return false; - } - - if( !Shader_ParseVector( script, shader->skyAxis, 3 )) // skyAxis is optionally - { - VectorSet( shader->skyAxis, 0.0f, 0.0f, 1.0f ); - return true; - } - - if( VectorIsNull( shader->skyAxis )) - VectorSet( shader->skyAxis, 0.0f, 0.0f, 1.0f ); - VectorNormalize( shader->skyAxis ); - - return true; -} - -static qboolean Shader_CustomDecal( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - shader->flags |= SHADER_DECALPARMS; - return true; -} - -static qboolean Shader_Sort( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - token_t tok; - - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'sort' in shader '%s'\n", shader->name ); - return false; - } - - if( !com.stricmp( tok.string, "portal" )) shader->sort = SORT_PORTAL; - else if( !com.stricmp( tok.string, "sky" )) shader->sort = SORT_SKY; - else if( !com.stricmp( tok.string, "decal" )) shader->sort = SORT_DECAL; - else if( !com.stricmp( tok.string, "opaque" )) shader->sort = SORT_OPAQUE; - else if( !com.stricmp( tok.string, "banner" )) shader->sort = SORT_BANNER; - else if( !com.stricmp( tok.string, "alphaTest" )) shader->sort = SORT_ALPHATEST; - else if( !com.stricmp( tok.string, "seeThrough" )) shader->sort = SORT_ALPHATEST; - else if( !com.stricmp( tok.string, "underWater" )) shader->sort = SORT_UNDERWATER; - else if( !com.stricmp( tok.string, "additive" )) shader->sort = SORT_ADDITIVE; - else if( !com.stricmp( tok.string, "nearest" )) shader->sort = SORT_NEAREST; - else if( !com.stricmp( tok.string, "water" )) shader->sort = SORT_WATER; - else - { - shader->sort = com.atoi( tok.string ); - if( shader->sort < 1 || shader->sort > 16 ) - { - MsgDev( D_WARN, "unknown 'sort' parameter '%s' in shader '%s', defaulting to 'opaque'\n", tok.string, shader->name ); - shader->sort = SORT_OPAQUE; - } - } - return true; -} - -static qboolean Shader_Portal( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - shader->flags |= SHADER_PORTAL; - shader->sort = SORT_PORTAL; - - return true; -} - -static qboolean Shader_PolygonOffset( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - shader->flags |= SHADER_POLYGONOFFSET; - return true; -} - -static qboolean Shader_EntityMergable( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - shader->flags |= SHADER_ENTITY_MERGABLE; - return true; -} - -static qboolean Shader_If( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - if( !Shader_ParseConditions( script, shader )) - { - if( !Shader_SkipConditionBlock( script )) - { - MsgDev( D_ERROR, "mismatched if/endif pair in shader '%s'\n", shader->name ); - return false; - } - } - return true; -} - -static qboolean Shader_Endif( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - return true; -} - -static qboolean Shader_SurfaceParm( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - Com_SkipRestOfLine( script ); - return true; -} - -static qboolean Shader_TessSize( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - Com_ReadFloat( script, false, &shader->tessSize ); - return true; -} - -static qboolean Shader_Light( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - Com_SkipRestOfLine( script ); - return true; -} - -static qboolean Shader_NoModulativeDlights( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - shader->flags |= SHADER_NO_MODULATIVE_DLIGHTS; - return true; -} - -static qboolean Shader_OffsetMappingScale( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - if( !Com_ReadFloat( script, false, &shader->offsetmapping_scale )) - { - MsgDev( D_ERROR, "missing value 'offsetMappingScale' in shader '%s'\n", shader->name ); - return false; - } - - if( shader->offsetmapping_scale < 0.0f ) shader->offsetmapping_scale = 0.0f; - return true; -} - -static const ref_parsekey_t shaderkeys[] = -{ -{ "if", Shader_If }, -{ "sort", Shader_Sort }, -{ "cull", Shader_Cull }, -{ "light", Shader_Light }, -{ "endif", Shader_Endif }, -{ "portal", Shader_Portal }, -{ "fogvars", Shader_FogParms }, // RTCW fog params -{ "decal", Shader_CustomDecal }, -{ "skyParms", Shader_SkyParms }, -{ "skyRotate", Shader_SkyRotate }, -{ "fogparms", Shader_FogParms }, -{ "tessSize", Shader_TessSize }, -{ "nopicmip", Shader_shaderNoPicMip }, -{ "nomipmap", Shader_shaderNoMipMaps }, -{ "nomipmaps", Shader_shaderNoMipMaps }, -{ "nocompress", Shader_shaderNoCompress }, -{ "nearest", Shader_shaderNearest }, -{ "surfaceParm", Shader_SurfaceParm, }, -{ "polygonoffset", Shader_PolygonOffset }, -{ "deformvertexes", Shader_DeformVertexes }, -{ "entitymergable", Shader_EntityMergable }, -{ "offsetmappingscale", Shader_OffsetMappingScale }, -{ "nomodulativedlights", Shader_NoModulativeDlights }, -{ NULL, NULL } -}; - -// =============================================================== -static qboolean Shaderpass_LoadMaterial( texture_t **normalmap, texture_t **glossmap, texture_t **decalmap, const char *name, int addFlags, float bumpScale ) -{ - texture_t *images[3]; - - // set defaults - images[0] = images[1] = images[2] = NULL; - - // load normalmap image - images[0] = R_FindTexture( va( "heightMap( \"%s_bump\", %g );", name, bumpScale ), NULL, 0, addFlags ); - if( !images[0] ) - { - images[0] = R_FindTexture( va( "mergeDepthmap( \"%s_norm\", \"%s_depth\" );", name, name ), NULL, 0, (addFlags|TF_NORMALMAP)); - - if( !images[0] ) - { - if( !r_lighting_diffuse2heightmap->integer ) - return false; - images[0] = R_FindTexture( va( "heightMap( \"%s\", 2.0f );", name ), NULL, 0, addFlags ); - if( !images[0] ) return false; - } - } - - // load glossmap image - if( r_lighting_specular->integer ) - images[1] = R_FindTexture( va( "%s_gloss", name ), NULL, 0, addFlags ); - - images[2] = R_FindTexture( va( "%s_decal", name ), NULL, 0, addFlags ); - - *normalmap = images[0]; - *glossmap = images[1]; - *decalmap = images[2]; - - return true; -} - -static qboolean Shaderpass_AnimFrequency( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - float anim_fps; - - if( !Com_ReadFloat( script, false, &anim_fps )) - { - MsgDev( D_ERROR, "missing parameters for 'animFrequency' in shader '%s\n", shader->name ); - return false; - } - - pass->flags |= SHADERSTAGE_ANIMFREQUENCY; - if( pass->num_textures ) - { - if( pass->anim_offset ) - { - // someone tired specify third anim sequence - MsgDev( D_ERROR, "too many 'animFrequency' declared in shader '%s\n", shader->name ); - return false; - } - pass->animFrequency[1] = anim_fps; - pass->anim_offset = pass->num_textures; - } - else - { - pass->animFrequency[0] = anim_fps; - pass->anim_offset = 0; - } - return true; -} - -static qboolean Shaderpass_MapExt( ref_shader_t *shader, ref_stage_t *pass, int addFlags, script_t *script ) -{ - int flags; - string name; - token_t tok; - - if( pass->num_textures ) - { - if( pass->num_textures == MAX_STAGE_TEXTURES ) - { - MsgDev( D_ERROR, "MAX_STAGE_TEXTURES hit in shader '%s'\n", shader->name ); - return false; - } - if(!( pass->flags & SHADERSTAGE_ANIMFREQUENCY )) - pass->flags |= SHADERSTAGE_FRAMES; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'map' in shader '%s'\n", shader->name ); - return false; - } - - com.strncpy( name, tok.string, sizeof( name )); - - if( !com.stricmp( tok.string, "$lightmap" )) - { - pass->tcgen = TCGEN_LIGHTMAP; - pass->flags = ( pass->flags & ~(SHADERSTAGE_PORTALMAP|SHADERSTAGE_DLIGHT)) | SHADERSTAGE_LIGHTMAP; - pass->animFrequency[0] = pass->animFrequency[1] = 0.0f; - pass->anim_offset = 0; - pass->textures[0] = NULL; - return true; - } - else if( !com.stricmp( tok.string, "$dlight" )) - { - pass->tcgen = TCGEN_BASE; - pass->flags = ( pass->flags & ~(SHADERSTAGE_LIGHTMAP|SHADERSTAGE_PORTALMAP)) | SHADERSTAGE_DLIGHT; - pass->animFrequency[0] = pass->animFrequency[1] = 0.0f; - pass->anim_offset = 0; - pass->textures[0] = NULL; - r_shaderHasDlightPass = true; - return true; - } - else if( !com.stricmp( tok.string, "$portalmap" ) || !com.stricmp( tok.string, "$mirrormap" )) - { - pass->tcgen = TCGEN_PROJECTION; - pass->flags = ( pass->flags & ~(SHADERSTAGE_LIGHTMAP|SHADERSTAGE_DLIGHT)) | SHADERSTAGE_PORTALMAP; - pass->animFrequency[0] = pass->animFrequency[1] = 0.0f; - pass->anim_offset = 0; - pass->textures[0] = NULL; - if(( shader->flags & SHADER_PORTAL ) && ( shader->sort == SORT_PORTAL )) - shader->sort = 0; // reset sorting so we can figure it out later. FIXME? - shader->flags |= SHADER_PORTAL|( r_portalmaps->integer ? SHADER_PORTAL_CAPTURE1 : 0 ); - return true; - } - else if( !com.stricmp( tok.string, "$whiteImage" )) - { - pass->textures[0] = tr.whiteTexture; - } - else if( !com.stricmp( tok.string, "$blackImage" )) - { - pass->textures[0] = tr.blackTexture; - } - else if( !com.stricmp( tok.string, "$particle" )) - { - pass->textures[0] = tr.particleTexture; - } - else - { - flags = Shader_SetImageFlags( shader ) | addFlags; - - while( 1 ) - { - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - break; - - com.strncat( name, " ", sizeof( name )); - com.strncat( name, tok.string, sizeof( name )); - } - - pass->textures[pass->num_textures] = Shader_FindImage( shader, name, flags ); - pass->tcgen = TCGEN_BASE; - pass->flags &= ~(SHADERSTAGE_LIGHTMAP|SHADERSTAGE_DLIGHT|SHADERSTAGE_PORTALMAP); - } - pass->num_textures++; - - return true; -} - -static qboolean Shaderpass_AnimMapExt( ref_shader_t *shader, ref_stage_t *pass, int addFlags, script_t *script ) -{ - int flags; - float anim_fps; - token_t tok; - - flags = Shader_SetImageFlags( shader ) | addFlags; - - pass->tcgen = TCGEN_BASE; - pass->flags &= ~( SHADERSTAGE_LIGHTMAP|SHADERSTAGE_DLIGHT|SHADERSTAGE_PORTALMAP ); - - if( !Com_ReadFloat( script, false, &anim_fps )) - { - MsgDev( D_ERROR, "missing 'AnimFrequency' parameter for 'animMap' in shader '%s\n", shader->name ); - return false; - } - - if( pass->num_textures ) - { - if( pass->anim_offset ) - { - // someone tired specify third anim sequence - MsgDev( D_ERROR, "too many 'animFrequency' declared in shader '%s\n", shader->name ); - return false; - } - pass->animFrequency[1] = anim_fps; - pass->anim_offset = pass->num_textures; - } - else - { - pass->animFrequency[0] = anim_fps; - pass->anim_offset = 0; - } - pass->flags |= (SHADERSTAGE_ANIMFREQUENCY|SHADERSTAGE_FRAMES); - - while( 1 ) - { - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - break; - if( pass->num_textures < MAX_STAGE_TEXTURES ) - pass->textures[pass->num_textures++] = Shader_FindImage( shader, tok.string, flags ); - } - - if( pass->num_textures == 0 ) - { - MsgDev( D_WARN, "missing animation frames for 'animMap' in shader '%s'\n", shader->name ); - pass->flags &= ~(SHADERSTAGE_ANIMFREQUENCY|SHADERSTAGE_FRAMES); - pass->animFrequency[0] = pass->animFrequency[1] = 0.0f; - pass->anim_offset = 0; - } - return true; -} - -static qboolean Shaderpass_CubeMapExt( ref_shader_t *shader, ref_stage_t *pass, int addFlags, int tcgen, script_t *script ) -{ - int flags; - string name; - token_t tok; - - if( pass->num_textures ) - { - if( pass->num_textures == MAX_STAGE_TEXTURES ) - { - MsgDev( D_ERROR, "MAX_STAGE_TEXTURES hit in shader '%s'\n", shader->name ); - return false; - } - if(!( pass->flags & SHADERSTAGE_ANIMFREQUENCY )) - pass->flags |= SHADERSTAGE_FRAMES; - } - - pass->flags &= ~(SHADERSTAGE_LIGHTMAP|SHADERSTAGE_DLIGHT|SHADERSTAGE_PORTALMAP); - - if( !GL_Support( R_TEXTURECUBEMAP_EXT )) - { - MsgDev( D_ERROR, "Shader %s has an unsupported cubemap stage: %s.\n", shader->name ); - pass->textures[0] = tr.defaultTexture; - pass->tcgen = TCGEN_BASE; - return false; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'cubeMap' in shader '%s'\n", shader->name ); - return false; - } - - com.strncpy( name, tok.string, sizeof( name )); - flags = Shader_SetImageFlags( shader ) | addFlags | TF_CUBEMAP; - - while( 1 ) - { - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - break; - - com.strncat( name, " ", sizeof( name )); - com.strncat( name, tok.string, sizeof( name )); - } - - pass->tcgen = TCGEN_BASE; - pass->textures[pass->num_textures] = Shader_FindImage( shader, name, flags ); - pass->flags &= ~(SHADERSTAGE_LIGHTMAP|SHADERSTAGE_DLIGHT|SHADERSTAGE_PORTALMAP); - if( pass->textures[pass->num_textures] != tr.defaultTexture ) pass->tcgen = tcgen; - pass->num_textures++; - - return true; -} - -static qboolean Shaderpass_Map( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - return Shaderpass_MapExt( shader, pass, 0, script ); -} - -static qboolean Shaderpass_ClampMap( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - return Shaderpass_MapExt( shader, pass, TF_CLAMP, script ); -} - -static qboolean Shaderpass_AnimMap( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - return Shaderpass_AnimMapExt( shader, pass, 0, script ); -} - -static qboolean Shaderpass_AnimClampMap( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - return Shaderpass_AnimMapExt( shader, pass, TF_CLAMP, script ); -} - -static qboolean Shaderpass_CubeMap( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - return Shaderpass_CubeMapExt( shader, pass, TF_CLAMP, TCGEN_REFLECTION, script ); -} - -static qboolean Shaderpass_ShadeCubeMap( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - return Shaderpass_CubeMapExt( shader, pass, TF_CLAMP, TCGEN_REFLECTION_CELLSHADE, script ); -} - -static qboolean Shaderpass_NormalMap( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - int flags; - const char *name; - float bumpScale = 0; - token_t tok; - - if( !GL_Support( R_SHADER_GLSL100_EXT )) - { - MsgDev( D_ERROR, "shader %s has a normalmap stage, while GLSL is not supported\n", shader->name ); - return false; - } - - flags = Shader_SetImageFlags( shader ); - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'normalMap' in shader '%s'\n", shader->name ); - return false; - } - - if( !com.stricmp( tok.string, "$heightmap" ) ) - { - if( !Com_ReadFloat( script, false, &bumpScale )) - { - MsgDev( D_WARN, "missing bumpScale parameter for 'normalMap $heightmap' in shader '%s', defaulting to 2.0f\n", shader->name ); - bumpScale = 2.0f; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'normalMap $heightmap' in shader '%s'\n", shader->name ); - return false; - } - name = va( "heightMap( \"%s\", %g );", tok.string, bumpScale ); - } - else name = tok.string; - - pass->tcgen = TCGEN_BASE; - pass->flags &= ~(SHADERSTAGE_LIGHTMAP|SHADERSTAGE_DLIGHT|SHADERSTAGE_PORTALMAP); - pass->textures[1] = Shader_FindImage( shader, name, flags ); - pass->num_textures++; - if( pass->textures[1] != tr.defaultTexture ) - { - pass->program = DEFAULT_GLSL_PROGRAM; - pass->program_type = PROGRAM_TYPE_MATERIAL; - } - - // basemap parameter is optionally - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - { - pass->textures[0] = tr.whiteTexture; - return true; - } - - if( !com.stricmp( tok.string, "$noimage" )) - pass->textures[0] = tr.whiteTexture; - else pass->textures[0] = Shader_FindImage( shader, tok.string, Shader_SetImageFlags( shader )); - pass->num_textures++; - - return true; -} - -static qboolean Shaderpass_Material( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - int flags; - float bumpScale = 0; - const char *name; - token_t tok; - - if( !GL_Support( R_SHADER_GLSL100_EXT )) - { - MsgDev( D_ERROR, "shader %s has a normalmap stage, while GLSL is not supported\n", shader->name ); - return false; - } - - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'material' in shader '%s'\n", shader->name ); - return false; - } - - if( pass->num_textures ) - { - pass->num_textures = 0; - pass->flags &= ~(SHADERSTAGE_ANIMFREQUENCY|SHADERSTAGE_FRAMES); - } - - flags = Shader_SetImageFlags( shader ); - - if( !com.stricmp( tok.string, "$rgb" )) - { - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )); - return false; - name = va( "clearPixels( \"%s\", alpha );", tok.string ); - } - else if( !com.stricmp( tok.string, "$alpha" )) - { - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )); - return false; - name = va( "clearPixels( \"%s\", color );", tok.string ); - } - else name = tok.string; - - pass->textures[0] = Shader_FindImage( shader, name, flags ); - if( pass->textures[0] == tr.defaultTexture ) - { - MsgDev( D_ERROR, "failed to load base/diffuse image for material %s in shader %s.\n", tok.string, shader->name ); - return false; - } - pass->num_textures++; - - pass->textures[1] = pass->textures[2] = pass->textures[3] = NULL; - - pass->tcgen = TCGEN_BASE; - pass->flags &= ~(SHADERSTAGE_LIGHTMAP|SHADERSTAGE_DLIGHT|SHADERSTAGE_PORTALMAP); - - while( 1 ) - { - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - break; - - if( com.is_digit( tok.string )) - { - bumpScale = com.atoi( tok.string ); - } - else if( !pass->textures[1] ) - { - if( bumpScale ) - pass->textures[1] = Shader_FindImage( shader, va( "heightMap( \"%s\", %g );", tok.string, bumpScale ), flags ); - else pass->textures[1] = Shader_FindImage( shader, tok.string, flags ); - pass->num_textures++; - if( pass->textures[1] == tr.defaultTexture ) - { - MsgDev( D_WARN, "missing normalmap image '%s' in shader '%s'\n", tok.string, shader->name ); - pass->textures[1] = tr.blankbumpTexture; - } - else - { - pass->program = DEFAULT_GLSL_PROGRAM; - pass->program_type = PROGRAM_TYPE_MATERIAL; - } - } - else if( !pass->textures[2] ) - { - if( com.stricmp( tok.string, "-" ) && r_lighting_specular->integer ) - { - pass->textures[2] = Shader_FindImage( shader, tok.string, flags ); - if( pass->textures[2] == tr.defaultTexture ) - MsgDev( D_WARN, "missing glossmap image '%s' in shader '%s'\n", tok.string, shader->name ); - } - - // set gloss to r_blacktexture so we know we have already parsed the gloss image - if( pass->textures[2] == tr.defaultTexture ) pass->textures[2] = tr.blackTexture; - pass->num_textures++; - } - else - { - pass->textures[3] = Shader_FindImage( shader, tok.string, flags ); - if( pass->textures[3] == tr.defaultTexture ) - { - MsgDev( D_WARN, "missing decal image '%s' in shader '%s'\n", tok.string, shader->name ); - pass->textures[3] = NULL; - } - else pass->num_textures++; - } - } - - // black texture => no gloss, so don't waste time in the GLSL program - if( pass->textures[2] == tr.blackTexture ) - { - pass->num_textures--; - pass->textures[2] = NULL; - } - if( pass->textures[1] ) - return true; - - // try loading default images - if( Shaderpass_LoadMaterial( &pass->textures[1], &pass->textures[2], &pass->textures[3], pass->textures[0]->name, flags, bumpScale )) - { - pass->program = DEFAULT_GLSL_PROGRAM; - pass->program_type = PROGRAM_TYPE_MATERIAL; - } - else MsgDev( D_WARN, "failed to load default images for material '%s' in shader '%s'\n", pass->textures[0]->name, shader->name ); - - return true; -} - -static qboolean Shaderpass_Distortion( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - int flags; - float bumpScale = 0; - token_t tok; - - if( !GL_Support( R_SHADER_GLSL100_EXT ) || !r_portalmaps->integer ) - { - if( !r_portalmaps->integer ) - MsgDev( D_ERROR, "shader %s has a distortion stage, while portalmaps is disabled\n", shader->name ); - else MsgDev( D_ERROR, "shader %s has a distortion stage, while GLSL is not supported\n", shader->name ); - return false; - } - - if( pass->num_textures ) - { - pass->num_textures = 0; - pass->flags &= ~(SHADERSTAGE_ANIMFREQUENCY|SHADERSTAGE_FRAMES); - } - - flags = Shader_SetImageFlags( shader ); - pass->flags &= ~(SHADERSTAGE_LIGHTMAP|SHADERSTAGE_DLIGHT|SHADERSTAGE_PORTALMAP); - pass->textures[0] = pass->textures[1] = NULL; - - while( 1 ) - { - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - break; - - if( com.is_digit( tok.string )) - { - bumpScale = com.atoi( tok.string ); - } - else if( !pass->textures[0] ) - { - pass->textures[0] = Shader_FindImage( shader, tok.string, flags ); - if( pass->textures[0] == tr.defaultTexture ) - { - MsgDev( D_WARN, "missing dudvmap image '%s' in shader '%s'\n", tok.string, shader->name ); - pass->textures[0] = tr.blackTexture; - } - pass->program = DEFAULT_GLSL_DISTORTION_PROGRAM; - pass->program_type = PROGRAM_TYPE_DISTORTION; - pass->num_textures++; - } - else - { - if( bumpScale ) - pass->textures[1] = Shader_FindImage( shader, va( "heightMap( \"%s\", %g );", tok.string, bumpScale ), flags ); - else pass->textures[1] = Shader_FindImage( shader, tok.string, flags ); - if( pass->textures[1] == tr.defaultTexture ) pass->textures[1] = NULL; - pass->num_textures++; - } - } - - if( pass->rgbGen.type == RGBGEN_UNKNOWN ) - { - pass->rgbGen.type = RGBGEN_CONST; - VectorClear( pass->rgbGen.args ); - } - - shader->flags |= (SHADER_PORTAL|SHADER_PORTAL_CAPTURE); - return true; -} - -static qboolean Shaderpass_RGBGen( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - token_t tok; - - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'rgbGen' in shader '%s'\n", shader->name ); - return false; - } - - if( !com.stricmp( tok.string, "identityLighting" )) pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING; - else if( !com.stricmp( tok.string, "identity" )) pass->rgbGen.type = RGBGEN_IDENTITY; - else if( !com.stricmp( tok.string, "wave" )) - { - if( !Shader_ParseFunc( script, pass->rgbGen.func, shader )) - { - MsgDev( D_ERROR, "missing waveform parameters for 'rgbGen wave' in shader '%s'\n", shader->name ); - return false; - } - pass->rgbGen.type = RGBGEN_WAVE; - VectorSet( pass->rgbGen.args, 1.0f, 1.0f, 1.0f ); - } - else if( !com.stricmp( tok.string, "colorWave" )) - { - if( !Shader_ParseVector( script, pass->rgbGen.args, 3 )) - { - MsgDev( D_ERROR, "missing parameters for 'rgbGen colorWave' in shader '%s'\n", shader->name ); - return false; - } - if( !Shader_ParseFunc( script, pass->rgbGen.func, shader )) - { - MsgDev( D_ERROR, "missing waveform parameters for 'rgbGen colorWave' in shader '%s'\n", shader->name ); - return false; - } - pass->rgbGen.type = RGBGEN_COLORWAVE; - } - else if( !com.stricmp( tok.string, "entity" )) pass->rgbGen.type = RGBGEN_ENTITY; - else if( !com.stricmp( tok.string, "oneMinusEntity" )) pass->rgbGen.type = RGBGEN_ONE_MINUS_ENTITY; - else if( !com.stricmp( tok.string, "vertex" )) pass->rgbGen.type = RGBGEN_VERTEX; - else if( !com.stricmp( tok.string, "oneMinusVertex" )) pass->rgbGen.type = RGBGEN_ONE_MINUS_VERTEX; - else if( !com.stricmp( tok.string, "lightingDiffuse" )) pass->rgbGen.type = RGBGEN_LIGHTING_DIFFUSE; - else if( !com.stricmp( tok.string, "exactVertex" )) pass->rgbGen.type = RGBGEN_EXACT_VERTEX; - else if( !com.stricmp( tok.string, "lightingAmbient" )) - { - // optional undocs parm 'invLight' - if( Com_ReadToken( script, false, &tok )) - if( !com.stricmp( tok.string, "invLight" )) - pass->rgbGen.args[0] = true; - pass->rgbGen.type = RGBGEN_LIGHTING_AMBIENT; - } - else if( !com.stricmp( tok.string, "const" ) || !com.stricmp( tok.string, "constant" )) - { - float div; - vec3_t color; - - if( !Shader_ParseVector( script, color, 3 )) - { - MsgDev( D_ERROR, "missing parameters for 'rgbGen const' in shader '%s'\n", shader->name ); - return false; - } - - if( !r_ignorehwgamma->integer ) - div = 1.0f / pow( 2, max( 0, floor( r_overbrightbits->value ) ) ); - else div = 1.0f; - - pass->rgbGen.type = RGBGEN_CONST; - ColorNormalize( color, pass->rgbGen.args ); - VectorScale( pass->rgbGen.args, div, pass->rgbGen.args ); - } - else if( !com.stricmp( tok.string, "custom" ) || !com.stricmp( tok.string, "teamcolor" )) - { - // the "teamcolor" thing comes from warsow - pass->rgbGen.type = RGBGEN_CUSTOM; - - if( !Com_ReadFloat( script, false, &pass->rgbGen.args[0] )) - MsgDev( D_WARN, "missing parameters for 'rgbGen teamcolor' in shader '%s'\n", shader->name ); - if( pass->rgbGen.args[0] < 0 || pass->rgbGen.args[0] >= NUM_CUSTOMCOLORS ) - pass->rgbGen.args[0] = 0; - } - else - { - MsgDev( D_WARN, "unknown 'rgbGen' parameter '%s' in shader '%s'\n", tok.string, shader->name ); - pass->rgbGen.type = RGBGEN_IDENTITY; - Shader_SkipLine( script ); - return true; - } - return true; -} - -static qboolean Shaderpass_AlphaGen( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - token_t tok; - - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'alphaGen' in shader '%s'\n", shader->name ); - return false; - } - - if( !com.stricmp( tok.string, "portal" )) - { - pass->alphaGen.type = ALPHAGEN_PORTAL; - Com_ReadFloat( script, false, &pass->alphaGen.args[0] ); - pass->alphaGen.args[0] = fabs( pass->alphaGen.args[0] ); - - if( !pass->alphaGen.args[0] ) pass->alphaGen.args[0] = 256.0f; - pass->alphaGen.args[0] = 1.0f / pass->alphaGen.args[0]; - } - else if( !com.stricmp( tok.string, "identity" )) pass->alphaGen.type = ALPHAGEN_IDENTITY; - else if( !com.stricmp( tok.string, "vertex" )) pass->alphaGen.type = ALPHAGEN_VERTEX; - else if( !com.stricmp( tok.string, "oneMinusVertex" )) pass->alphaGen.type = ALPHAGEN_ONE_MINUS_VERTEX; - else if( !com.stricmp( tok.string, "entity" )) pass->alphaGen.type = ALPHAGEN_ENTITY; - else if( !com.stricmp( tok.string, "wave" )) - { - if( !Shader_ParseFunc( script, pass->alphaGen.func, shader )) - { - MsgDev( D_ERROR, "missing waveform parameters for 'alphaGen wave' in shader '%s'\n", shader->name ); - return false; - } - pass->alphaGen.type = ALPHAGEN_WAVE; - } - else if( !com.stricmp( tok.string, "alphaWave" )) - { - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'alphaGen alphaWave' in shader '%s'\n", shader->name ); - return false; - } - pass->alphaGen.args[0] = com.atof( tok.string ); - - if( !Shader_ParseFunc( script, pass->alphaGen.func, shader )) - { - MsgDev( D_ERROR, "missing waveform parameters for 'alphaGen alphaWave' in shader '%s'\n", shader->name ); - return false; - } - pass->alphaGen.type = ALPHAGEN_ALPHAWAVE; - } - else if( !com.stricmp( tok.string, "lightingSpecular" )) - { - pass->alphaGen.type = ALPHAGEN_SPECULAR; - Com_ReadFloat( script, false, &pass->alphaGen.args[0] ); - pass->alphaGen.args[0] = fabs( pass->alphaGen.args[0] ); - if( !pass->alphaGen.args[0] ) pass->alphaGen.args[0] = 5.0f; - } - else if( !com.stricmp( tok.string, "const" ) || !com.stricmp( tok.string, "constant" )) - { - pass->alphaGen.type = ALPHAGEN_CONST; - Com_ReadFloat( script, false, &pass->alphaGen.args[0] ); - pass->alphaGen.args[0] = fabs( pass->alphaGen.args[0] ); - } - else if( !com.stricmp( tok.string, "dot" )) - { - Com_ReadFloat( script, false, &pass->alphaGen.args[0] ); - pass->alphaGen.args[0] = fabs( pass->alphaGen.args[0] ); - Com_ReadFloat( script, false, &pass->alphaGen.args[1] ); - pass->alphaGen.args[1] = fabs( pass->alphaGen.args[1] ); - if( !pass->alphaGen.args[1] ) pass->alphaGen.args[1] = 1.0f; - pass->alphaGen.type = ALPHAGEN_DOT; - } - else if( !com.stricmp( tok.string, "oneMinusDot" ) ) - { - Com_ReadFloat( script, false, &pass->alphaGen.args[0] ); - pass->alphaGen.args[0] = fabs( pass->alphaGen.args[0] ); - Com_ReadFloat( script, false, &pass->alphaGen.args[1] ); - pass->alphaGen.args[1] = fabs( pass->alphaGen.args[1] ); - if( !pass->alphaGen.args[1] ) pass->alphaGen.args[1] = 1.0f; - pass->alphaGen.type = ALPHAGEN_ONE_MINUS_DOT; - } - else if( !com.stricmp( tok.string, "fade" )) - { - if( !Com_ReadToken( script, false, &tok )) - { - pass->alphaGen.args[0] = 0.0f; - pass->alphaGen.args[1] = 256.0f; - pass->alphaGen.args[2] = 1.0f / 256.0f; - } - else - { - pass->alphaGen.args[0] = com.atof( tok.string ); - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'alphaGen fade' in shader '%s'\n", shader->name ); - return false; - } - - pass->alphaGen.args[1] = com.atof( tok.string ); - pass->alphaGen.args[2] = pass->alphaGen.args[1] - pass->alphaGen.args[0]; - if( pass->alphaGen.args[2] ) pass->alphaGen.args[2] = 1.0f / pass->alphaGen.args[2]; - } - pass->alphaGen.type = ALPHAGEN_FADE; - } - else if( !com.stricmp( tok.string, "oneMinusFade" )) - { - if( !Com_ReadToken( script, false, &tok )) - { - pass->alphaGen.args[0] = 0.0f; - pass->alphaGen.args[1] = 256.0f; - pass->alphaGen.args[2] = 1.0f / 256.0f; - } - else - { - pass->alphaGen.args[0] = com.atof( tok.string ); - - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'alphaGen oneMinusFade' in shader '%s'\n", shader->name ); - return false; - } - - pass->alphaGen.args[1] = com.atof( tok.string ); - pass->alphaGen.args[2] = pass->alphaGen.args[1] - pass->alphaGen.args[0]; - if( pass->alphaGen.args[2] ) pass->alphaGen.args[2] = 1.0f / pass->alphaGen.args[2]; - } - pass->alphaGen.type = ALPHAGEN_ONE_MINUS_FADE; - } - else - { - MsgDev( D_WARN, "unknown 'alphaGen' parameter '%s' in shader '%s'\n", tok.string, shader->name ); - pass->alphaGen.type = ALPHAGEN_IDENTITY; - Shader_SkipLine( script ); - return true; - } - return true; -} - -static _inline int Shaderpass_SrcBlendBits( const char *token ) -{ - if( !com.stricmp( token, "gl_zero" )) - return GLSTATE_SRCBLEND_ZERO; - if( !com.stricmp( token, "gl_one" )) - return GLSTATE_SRCBLEND_ONE; - if( !com.stricmp( token, "gl_dst_color" )) - return GLSTATE_SRCBLEND_DST_COLOR; - if( !com.stricmp( token, "gl_one_minus_dst_color" )) - return GLSTATE_SRCBLEND_ONE_MINUS_DST_COLOR; - if( !com.stricmp( token, "gl_src_alpha" )) - return GLSTATE_SRCBLEND_SRC_ALPHA; - if( !com.stricmp( token, "gl_one_minus_src_alpha" )) - return GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA; - if( !com.stricmp( token, "gl_dst_alpha" )) - return GLSTATE_SRCBLEND_DST_ALPHA; - if( !com.stricmp( token, "gl_one_minus_dst_alpha" )) - return GLSTATE_SRCBLEND_ONE_MINUS_DST_ALPHA; - return GLSTATE_SRCBLEND_ONE; -} - -static _inline int Shaderpass_DstBlendBits( const char *token ) -{ - if( !com.stricmp( token, "gl_zero" )) - return GLSTATE_DSTBLEND_ZERO; - if( !com.stricmp( token, "gl_one" )) - return GLSTATE_DSTBLEND_ONE; - if( !com.stricmp( token, "gl_src_color" )) - return GLSTATE_DSTBLEND_SRC_COLOR; - if( !com.stricmp( token, "gl_one_minus_src_color" )) - return GLSTATE_DSTBLEND_ONE_MINUS_SRC_COLOR; - if( !com.stricmp( token, "gl_src_alpha" )) - return GLSTATE_DSTBLEND_SRC_ALPHA; - if( !com.stricmp( token, "gl_one_minus_src_alpha" )) - return GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA; - if( !com.stricmp( token, "gl_dst_alpha" )) - return GLSTATE_DSTBLEND_DST_ALPHA; - if( !com.stricmp( token, "gl_one_minus_dst_alpha" )) - return GLSTATE_DSTBLEND_ONE_MINUS_DST_ALPHA; - return GLSTATE_DSTBLEND_ONE; -} - -static qboolean Shaderpass_BlendFunc( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - token_t tok; - - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'blendFunc' in shader '%s'\n", shader->name ); - return false; - } - - pass->glState &= ~(GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK); - if( !com.stricmp( tok.string, "blend" )) - { - pass->glState |= GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA; - } - else if( !com.stricmp( tok.string, "filter" )) - { - pass->glState |= GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_ZERO; - } - else if( !com.stricmp( tok.string, "add" )) - { - pass->glState |= GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE; - } - else - { - pass->glState |= Shaderpass_SrcBlendBits( tok.string ); - - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'blendFunc' in shader '%s'\n", shader->name ); - return false; - } - pass->glState |= Shaderpass_DstBlendBits( tok.string ); - } - return true; -} - -static qboolean Shaderpass_AlphaFunc( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - token_t tok; - - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'alphaFunc' in shader '%s'\n", shader->name ); - return false; - } - - pass->glState &= ~(GLSTATE_ALPHAFUNC); - if( !com.stricmp( tok.string, "GT0" )) - pass->glState |= GLSTATE_AFUNC_GT0; - else if( !com.stricmp( tok.string, "LT128" )) - pass->glState |= GLSTATE_AFUNC_LT128; - else if( !com.stricmp( tok.string, "GE128" )) - pass->glState |= GLSTATE_AFUNC_GE128; - else - { - MsgDev( D_ERROR, "unknown 'alphaFunc' parameter '%s' in shader '%s'\n", tok.string, shader->name ); - return false; - } - return true; -} - -static qboolean Shaderpass_DepthFunc( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - token_t tok; - - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'depthFunc' in shader '%s'\n", shader->name ); - return false; - } - - if( !com.stricmp( tok.string, "equal" )) - pass->glState |= GLSTATE_DEPTHFUNC_EQ; - else if( !com.stricmp( tok.string, "lequal" )) - pass->glState &= ~GLSTATE_DEPTHFUNC_EQ; - else - { - MsgDev( D_ERROR, "unknown 'depthFunc' parameter '%s' in shader '%s'\n", tok.string, shader->name ); - return false; - } - return true; -} - -static qboolean Shaderpass_DepthWrite( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - shader->flags |= SHADER_DEPTHWRITE; - pass->glState |= GLSTATE_DEPTHWRITE; - - return true; -} - -static qboolean Shaderpass_TcMod( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - int i; - tcMod_t *tcMod; - token_t tok; - - if( pass->numtcMods == MAX_SHADER_TCMODS ) - { - MsgDev( D_ERROR, "shader %s has too many tcmods\n", shader->name ); - return false; - } - - tcMod = &pass->tcMods[pass->numtcMods]; - - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'tcMod' in shader '%s'\n", shader->name ); - return false; - } - - if( !com.stricmp( tok.string, "rotate" )) - { - if( !Com_ReadFloat( script, false, &tcMod->args[0] )) - { - MsgDev( D_ERROR, "missing parameters for 'tcMod rotate' in shader '%s'\n", shader->name ); - return false; - } - tcMod->args[0] = -tcMod->args[0] / 360.0f; - Com_ReadFloat( script, false, NULL ); // skip second parm if present - if( !tcMod->args[0] ) return true; - tcMod->type = TCMOD_ROTATE; - } - else if( !com.stricmp( tok.string, "scale" )) - { - if( !Shader_ParseVector( script, tcMod->args, 2 )) - { - MsgDev( D_ERROR, "missing parameters for 'tcMod scale' in shader '%s'\n", shader->name ); - return false; - } - tcMod->type = TCMOD_SCALE; - } - else if( !com.stricmp( tok.string, "scroll" )) - { - if( !Shader_ParseVector( script, tcMod->args, 2 )) - { - MsgDev( D_ERROR, "missing parameters for 'tcMod scroll' in shader '%s'\n", shader->name ); - return false; - } - tcMod->type = TCMOD_SCROLL; - } - else if( !com.stricmp( tok.string, "translate" )) - { - if( !Shader_ParseVector( script, tcMod->args, 2 )) - { - MsgDev( D_ERROR, "missing parameters for 'tcMod translate' in shader '%s'\n", shader->name ); - return false; - } - tcMod->type = TCMOD_TRANSLATE; - } - else if( !com.stricmp( tok.string, "stretch" )) - { - waveFunc_t func; - - if( !Shader_ParseFunc( script, &func, shader )) - { - MsgDev( D_ERROR, "missing waveform parameters for 'tcMod stretch' in shader '%s'\n", shader->name ); - return false; - } - tcMod->args[0] = func.type; - tcMod->args[5] = func.tableIndex; - for( i = 1; i < 5; i++ ) - tcMod->args[i] = func.args[i-1]; - tcMod->type = TCMOD_STRETCH; - } - else if( !com.stricmp( tok.string, "transform" )) - { - if( !Shader_ParseVector( script, tcMod->args, 6 )) - { - MsgDev( D_ERROR, "missing parameters for 'tcMod transform' in shader '%s'\n", shader->name ); - return false; - } - tcMod->args[4] = tcMod->args[4] - floor( tcMod->args[4] ); - tcMod->args[5] = tcMod->args[5] - floor( tcMod->args[5] ); - tcMod->type = TCMOD_TRANSFORM; - } - else if( !com.stricmp( tok.string, "turb" )) - { - if( !Shader_ParseVector( script, tcMod->args, 4 )) - { - MsgDev( D_ERROR, "missing parameters for 'tcMod turb' in shader '%s'\n", shader->name ); - return false; - } - Com_ReadFloat( script, false, NULL ); // skip five parm if present - tcMod->type = TCMOD_TURB; - } - else if( !com.stricmp( tok.string, "conveyor" )) - { - tcMod->type = TCMOD_CONVEYOR; - } - else - { - MsgDev( D_WARN, "unknown 'tcMod' parameter '%s' in shader '%s'\n", tok.string, shader->name ); - Shader_SkipLine( script ); - return true; - } - - r_currentPasses[shader->num_stages].numtcMods++; - return true; -} - -static qboolean Shaderpass_TcGen( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - token_t tok; - - if( !Com_ReadToken( script, false, &tok )) - { - MsgDev( D_ERROR, "missing parameters for 'tcGen' in shader '%s'\n", shader->name ); - return false; - } - - if( !com.stricmp( tok.string, "base" ) || !com.stricmp( tok.string, "texture" )) - pass->tcgen = TCGEN_BASE; - else if( !com.stricmp( tok.string, "lightmap" )) - pass->tcgen = TCGEN_LIGHTMAP; - else if( !com.stricmp( tok.string, "environment" )) - pass->tcgen = TCGEN_ENVIRONMENT; - else if( !com.stricmp( tok.string, "vector" )) - { - if(!Shader_ParseVector( script, &pass->tcgenVec[0], 4 )) - { - MsgDev( D_ERROR, "missing parameters for 'tcGen vector' in shader '%s'\n", shader->name ); - return false; - } - if(!Shader_ParseVector( script, &pass->tcgenVec[4], 4 )) - { - MsgDev( D_ERROR, "missing parameters for 'tcGen vector' in shader '%s'\n", shader->name ); - return false; - } - pass->tcgen = TCGEN_VECTOR; - } - else if( !com.stricmp( tok.string, "warp" )) - pass->tcgen = TCGEN_WARP; - else if( !com.stricmp( tok.string, "reflection" )) - pass->tcgen = TCGEN_REFLECTION; - else if( !com.stricmp( tok.string, "normal")) - pass->tcgen = TCGEN_NORMAL; - else if( !com.stricmp( tok.string, "cellShade" )) - pass->tcgen = TCGEN_REFLECTION_CELLSHADE; - else - { - MsgDev( D_WARN, "unknown 'tcGen' parameter '%s' in shader '%s'\n", tok.string, shader->name ); - Shader_SkipLine( script ); - return true; - } - return true; -} - -static qboolean Shaderpass_Detail( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - pass->flags |= SHADERSTAGE_DETAIL; - return true; -} - -static qboolean Shaderpass_RenderMode( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) -{ - shader->flags |= SHADER_RENDERMODE; - pass->flags |= SHADERSTAGE_RENDERMODE; - return true; -} - -static const ref_parsekey_t shaderpasskeys[] = -{ -{ "rgbGen", Shaderpass_RGBGen }, -{ "blendFunc", Shaderpass_BlendFunc }, -{ "depthFunc", Shaderpass_DepthFunc }, -{ "depthWrite", Shaderpass_DepthWrite }, -{ "alphaFunc", Shaderpass_AlphaFunc }, -{ "tcMod", Shaderpass_TcMod }, -{ "AnimFrequency", Shaderpass_AnimFrequency }, -{ "map", Shaderpass_Map }, -{ "animMap", Shaderpass_AnimMap }, -{ "cubeMap", Shaderpass_CubeMap }, -{ "shadeCubeMap", Shaderpass_ShadeCubeMap }, -{ "clampMap", Shaderpass_ClampMap }, -{ "animClampMap", Shaderpass_AnimClampMap }, -{ "normalMap", Shaderpass_NormalMap }, -{ "material", Shaderpass_Material }, -{ "distortion", Shaderpass_Distortion }, -{ "tcGen", Shaderpass_TcGen }, -{ "alphaGen", Shaderpass_AlphaGen }, -{ "detail", Shaderpass_Detail }, -{ "renderMode", Shaderpass_RenderMode }, -{ NULL, NULL } -}; - -// =============================================================== -static void Shader_ParseFile( script_t *script, const char *name ) -{ - ref_script_t *shaderScript; - tableFlags_t table_flags = 0; - char *buffer, *end; - int tableStatus = 0; - uint hashKey; - token_t tok; - size_t size; - - while( 1 ) - { - // parse the name - if( !Com_ReadToken( script, SC_ALLOW_NEWLINES|SC_PARSE_GENERIC, &tok )) - break; // end of data - - // check for table parms - while( 1 ) - { - if( !com.stricmp( tok.string, "clamp" )) - table_flags |= TABLE_CLAMP; - else if( !com.stricmp( tok.string, "snap" )) - table_flags |= TABLE_SNAP; - else if( !com.stricmp( tok.string, "table" )) - { - if( !R_ParseTable( script, table_flags )) - tableStatus = -1; // parsing failed - else tableStatus = 1; - break; - } - else - { - tableStatus = table_flags = 0; // not a table - break; - } - Com_ReadToken( script, false, &tok ); - } - - if( tableStatus != 0 ) - { - if( tableStatus == -1 ) - Com_SkipRestOfLine( script ); - continue; // table status will be reset on a next loop - } - - // parse the script - buffer = script->text; - Com_SkipBracedSection( script, 0 ); - end = script->text; - - if( !buffer ) buffer = script->buffer; // missing body ? - if( !end ) end = script->buffer + script->size; // EOF ? - size = end - buffer; - - // store the script - shaderScript = Mem_Alloc( r_shaderpool, sizeof( ref_script_t )); - shaderScript->name = Shader_CopyString( tok.string ); - shaderScript->type = SHADER_INVALID; - - shaderScript->source =Shader_CopyString( name ); - shaderScript->line = tok.line; - shaderScript->buffer = Mem_Alloc( r_shaderpool, size + 1 ); - Mem_Copy( shaderScript->buffer, buffer, size ); - shaderScript->buffer[size] = 0; // terminator - shaderScript->size = size; - - // add to hash table - hashKey = Com_HashKey( shaderScript->name, SHADERS_HASH_SIZE ); - shaderScript->nextHash = r_shaderScriptsHash[hashKey]; - r_shaderScriptsHash[hashKey] = shaderScript; - } -} - -static ref_script_t *Shader_GetCache( const char *name, int type, uint hashKey ) -{ - ref_script_t *cache = NULL; - - // see if there's a script for this shader - for( cache = r_shaderScriptsHash[hashKey]; cache; cache = cache->nextHash ) - { - if( !com.stricmp( cache->name, name )) - { - if( cache->type == SHADER_INVALID ) break; // not initialized - if( cache->type == type ) break; - } - } - return cache; -} - -/* -=============== -R_ShaderList_f -=============== -*/ -void R_ShaderList_f( void ) -{ - ref_shader_t *shader; - int i, shaderCount; - - Msg( "\n" ); - Msg( "-----------------------------------\n" ); - - for( i = shaderCount = 0, shader = r_shaders; i < r_numShaders; i++, shader++ ) - { - if( !shader->shadernum ) continue; - - Msg( "%i ", shader->num_stages ); - - switch( shader->type ) - { - case SHADER_SKY: - Msg( "sky " ); - break; - case SHADER_FARBOX: - Msg( "far " ); - break; - case SHADER_NEARBOX: - Msg( "near " ); - break; - case SHADER_TEXTURE: - Msg( "bsp " ); - break; - case SHADER_DECAL: - Msg( "decal" ); - break; - case SHADER_STUDIO: - Msg( "mdl " ); - break; - case SHADER_SPRITE: - Msg( "spr " ); - break; - case SHADER_FLARE: - Msg( "flare" ); - break; - case SHADER_PLANAR_SHADOW: - Msg( "shdw " ); - break; - case SHADER_OPAQUE_OCCLUDER: - Msg( "occl " ); - break; - case SHADER_NOMIP: - Msg( "pic " ); - break; - case SHADER_GENERIC: - Msg( "gen " ); - break; - default: - Msg( "?? %i", shader->type ); - break; - } - Msg( " %s", shader->name ); - if( shader->flags & SHADER_DEFAULTED ) - Msg( " DEFAULTED\n" ); - else Msg( "\n" ); - shaderCount++; - } - - Msg( "-----------------------------------\n" ); - Msg( "%i total shaders\n", shaderCount ); - Msg( "\n" ); -} - -/* -=============== -R_ShaderDump_f -=============== -*/ -void R_ShaderDump_f( void ) -{ - const char *name; - ref_shader_t *shader; - ref_script_t *cache; - uint hashKey; - - if(( Cmd_Argc() < 2 ) && !r_debug_surface ) - { - Msg( "Usage: shaderdump \n" ); - return; - } - - if( Cmd_Argc() < 2 ) - name = r_debug_surface->shader->name; - else name = Cmd_Argv( 1 ); - - hashKey = Com_HashKey( name, SHADERS_HASH_SIZE ); - for( shader = r_shadersHash[hashKey]; shader; shader = shader->nextHash ) - { - if( !com.stricmp( shader->name, name )) - break; - } - if( !shader ) - { - Msg( "could not find shader %s\n", name ); - return; - } - cache = Shader_GetCache( name, shader->type, hashKey ); - if( !cache ) - { - if( shader->stages[0].num_textures ) - { - int i; - - for( i = 0; i < shader->stages[0].num_textures; i++ ) - { - if( shader->stages[0].textures[i] ) - Msg( "tex[%i] %s\n", i, shader->stages[0].textures[i] ->name ); - else Msg( "missing texture %i\n" ); - } - } - - Msg( "could not find shader %s in cache\n", name ); - return; - } - - Msg( "found in %s:\n\n", cache->source ); - Msg( "^2%s%s\n", name, cache->buffer ); -} - -qboolean R_ShaderCheckCache( const char *name ) -{ - return (Shader_GetCache( name, SHADER_INVALID, Com_HashKey( name, SHADERS_HASH_SIZE ))) ? true : false; -} - -void R_RegisterBuiltinShaders( void ) -{ - tr.defaultShader = R_LoadShader( MAP_DEFAULT_SHADER, SHADER_NOMIP, true, (TF_NOMIPMAP|TF_NOPICMIP), SHADER_UNKNOWN ); - tr.fillShader = R_LoadShader( "*white", SHADER_NOMIP, true, (TF_CLAMP|TF_NOMIPMAP|TF_NOPICMIP), SHADER_UNKNOWN ); - tr.currentSkyShader = R_LoadShader( "*sky", SHADER_GENERIC, true, (TF_CLAMP|TF_NOMIPMAP|TF_NOPICMIP), SHADER_UNKNOWN ); - tr.currentSkyShader->flags |= SHADER_STATIC; -} - -void R_InitShaders( void ) -{ - script_t *script; - search_t *t; - int i; - - MsgDev( D_NOTE, "R_InitShaders()\n" ); - r_shaderpool = Mem_AllocPool( "Shader Zone" ); - - t = FS_Search( "scripts/*.shader", true ); - if( !t ) MsgDev( D_ERROR, "couldn't find any shaders!\n"); - - // load them - for( i = 0; t && i < t->numfilenames; i++ ) - { - script = Com_OpenScript( t->filenames[i], NULL, 0 ); - if( !script ) - { - MsgDev( D_ERROR, "Couldn't load '%s'\n", t->filenames[i] ); - continue; - } - - // parse this file - Shader_ParseFile( script, t->filenames[i] ); - Com_CloseScript( script ); - } - if( t ) Mem_Free( t ); // free search - - // init sprite frames - for( i = 0; i < MAX_STAGE_TEXTURES; i++ ) - r_stageTexture[i] = tr.defaultTexture; - - r_shaderTwoSided = 0; - r_miptexFeatures = 0; - r_stageAnimOffset = 0; - r_numStageTextures = 0; - r_stageAnimFrequency[0] = 0.0f; - r_stageAnimFrequency[1] = 0.0f; - r_shaderRenderMode = kRenderNormal; - - R_RegisterBuiltinShaders (); -} - -void Shader_TouchImages( ref_shader_t *shader, e_free free_unused ) -{ - int i, j; - int c_total = 0; - ref_stage_t *stage; - texture_t *texture; - - ASSERT( shader ); - - // reset parms - r_shaderTwoSided = 0; - r_miptexFeatures = 0; - r_stageAnimOffset = 0; - r_numStageTextures = 0; - r_stageAnimFrequency[0] = 0.0f; - r_stageAnimFrequency[1] = 0.0f; - - if( free_unused == FREE_IGNORE ) - shader->touchFrame = tr.registration_sequence; - - for( i = 0; i < shader->num_stages; i++ ) - { - stage = &shader->stages[i]; - - for( j = 0; j < stage->num_textures; j++ ) - { - // prolonge registration for all shader textures - texture = stage->textures[j]; - - if( !texture || !texture->texnum ) - continue; - - if( free_unused == FREE_FORCE && texture->texType != TEX_SYSTEM ) - { - // because even 'force' mode can't unload system textures - R_FreeImage( texture ); - } - else - { - if( texture->flags & TF_STATIC ) continue; - if( free_unused == FREE_NORMAL && texture->touchFrame != tr.registration_sequence ) - R_FreeImage( texture ); - else texture->touchFrame = tr.registration_sequence; - } - c_total++; // just for debug - } - } - - if( shader->flags & SHADER_SKYPARMS && shader->skyParms ) - { - for( i = 0; i < 6; i++ ) - { - if( shader->skyParms->farboxShaders[i] ) - Shader_TouchImages( shader->skyParms->farboxShaders[i], free_unused ); - if( shader->skyParms->nearboxShaders[i] ) - Shader_TouchImages( shader->skyParms->nearboxShaders[i], free_unused ); - } - } -} - -void Shader_FreeShader( ref_shader_t *shader, e_free free_unused ) -{ - uint i, hashKey; - ref_shader_t *cur, **prev; - shader_t handle; - - ASSERT( shader ); - - if( !shader->shadernum ) - return; // already freed - - // free uinque shader images only - Shader_TouchImages( shader, free_unused ); - - // remove from hash table - hashKey = Com_HashKey( shader->name, SHADERS_HASH_SIZE ); - prev = &r_shadersHash[hashKey]; - - while( 1 ) - { - cur = *prev; - if( !cur ) break; - - if( cur == shader ) - { - *prev = cur->nextHash; - break; - } - prev = &cur->nextHash; - } - - handle = shader - r_shaders; - if(( shader->flags & SHADER_SKYPARMS ) && shader->skyParms ) - { - for( i = 0; i < 6; i++ ) - { - if( shader->skyParms->farboxShaders[i] ) - Shader_FreeShader( shader->skyParms->farboxShaders[i], free_unused ); - if( shader->skyParms->nearboxShaders[i] ) - Shader_FreeShader( shader->skyParms->nearboxShaders[i], free_unused ); - } - - if( free_unused != FREE_IGNORE ) - { - R_FreeSkydome( shader->skyParms ); - shader->skyParms = NULL; - } - } - - if( free_unused != FREE_IGNORE ) - { - // free all allocated memory by shader - Shader_Free( shader->name ); - Mem_Set( shader, 0, sizeof( ref_shader_t )); - } -} - -void Mod_FreeShader( const char *name ) -{ - ref_shader_t *shader; - string shortname; - ref_script_t *cache = NULL; - uint i, hashKey, length; - - if( !name || !name[0] ) return; - - for( i = ( name[0] == '/' || name[0] == '\\' ), length = 0; name[i] && ( length < sizeof( shortname )-1 ); i++ ) - { - if( name[i] == '\\' ) shortname[length++] = '/'; - else shortname[length++] = com.tolower( name[i] ); - } - - if( !length ) return; - shortname[length] = 0; - - // see if already loaded - hashKey = Com_HashKey( shortname, SHADERS_HASH_SIZE ); - - for( shader = r_shadersHash[hashKey]; shader; shader = shader->nextHash ) - { - if( !com.stricmp( shader->name, shortname )) - { - // remove shader - Shader_FreeShader( shader, FREE_FORCE ); - return; - } - } -} - -void R_ShutdownShaders( void ) -{ - int i; - ref_shader_t *shader; - - if( !r_shaderpool ) - return; - - for( i = 0, shader = r_shaders; i < r_numShaders; i++, shader++ ) - { - if( !shader->shadernum ) continue; // already freed - Shader_FreeShader( shader, FREE_NORMAL ); // images will be frees in other place - } - - Mem_FreePool( &r_shaderpool ); - Mem_Set( r_shaderScriptsHash, 0, sizeof( r_shaderScriptsHash )); - Mem_Set( r_shadersHash, 0, sizeof( r_shadersHash )); - Mem_Set( r_shaders, 0, sizeof( r_shaders )); - r_numShaders = 0; -} - -void Shader_SetBlendmode( ref_stage_t *pass ) -{ - int blendsrc, blenddst; - - if( pass->flags & SHADERSTAGE_BLENDMODE ) - return; - if( !pass->textures[0] && !( pass->flags & ( SHADERSTAGE_LIGHTMAP|SHADERSTAGE_DLIGHT ))) - return; - - if(!( pass->glState & (GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK))) - { - if(( pass->rgbGen.type == RGBGEN_IDENTITY ) && ( pass->alphaGen.type == ALPHAGEN_IDENTITY )) - pass->flags |= SHADERSTAGE_BLEND_REPLACE; - else pass->flags |= SHADERSTAGE_BLEND_MODULATE; - return; - } - - blendsrc = pass->glState & GLSTATE_SRCBLEND_MASK; - blenddst = pass->glState & GLSTATE_DSTBLEND_MASK; - - if( blendsrc == GLSTATE_SRCBLEND_ONE && blenddst == GLSTATE_DSTBLEND_ZERO ) - pass->flags |= SHADERSTAGE_BLEND_MODULATE; - else if(( blendsrc == GLSTATE_SRCBLEND_ZERO && blenddst == GLSTATE_DSTBLEND_SRC_COLOR ) || ( blendsrc == GLSTATE_SRCBLEND_DST_COLOR && blenddst == GLSTATE_DSTBLEND_ZERO )) - pass->flags |= SHADERSTAGE_BLEND_MODULATE; - else if( blendsrc == GLSTATE_SRCBLEND_ONE && blenddst == GLSTATE_DSTBLEND_ONE ) - pass->flags |= SHADERSTAGE_BLEND_ADD; - else if( blendsrc == GLSTATE_SRCBLEND_SRC_ALPHA && blenddst == GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA ) - pass->flags |= SHADERSTAGE_BLEND_DECAL; - else if( blendsrc == GLSTATE_DSTBLEND_SRC_COLOR && blenddst == GLSTATE_SRCBLEND_DST_COLOR ) - pass->flags |= SHADERSTAGE_BLEND_DECAL; // for detail textures -} - -static qboolean Shader_ParseCommand( ref_shader_t *shader, script_t *script, const char *command ) -{ - const ref_parsekey_t *cmd; - - for( cmd = shaderkeys; cmd->name != NULL; cmd++ ) - { - if( !com.stricmp( cmd->name, command )) - return cmd->func( shader, NULL, script ); - } - - // compiler or mapeditor commands ignored silently - if( !com.strnicmp( "q3map_", command, 6 ) || !com.strnicmp( "qer_", command, 4 ) || !com.strnicmp( "fxrad_", command, 4 )) - { - Com_SkipRestOfLine( script ); - return true; - } - - MsgDev( D_WARN, "unknown general command '%s' in shader '%s'\n", command, shader->name ); - Shader_SkipLine( script ); - return true; -} - -static qboolean Shader_ParseStageCommand( ref_shader_t *shader, ref_stage_t *stage, script_t *script, const char *command ) -{ - const ref_parsekey_t *cmd; - - for( cmd = shaderpasskeys; cmd->name != NULL; cmd++ ) - { - if(!com.stricmp( cmd->name, command )) - return cmd->func( shader, stage, script ); - } - - MsgDev( D_WARN, "unknown stage command '%s' in shader '%s'\n", command, shader->name ); - Shader_SkipLine( script ); - return true; -} - -static qboolean Shader_ParseShader( ref_shader_t *shader, script_t *script ) -{ - ref_stage_t *stage; - token_t tok; - int n; - - if( !Com_ReadToken( script, SC_ALLOW_NEWLINES, &tok )) - { - MsgDev( D_ERROR, "shader '%s' has an empty script\n", shader->name ); - return false; - } - - // parse the shader - if( !com.stricmp( tok.string, "{" )) - { - while( 1 ) - { - if( !Com_ReadToken( script, SC_ALLOW_NEWLINES, &tok )) - { - MsgDev( D_ERROR, "no concluding '}' in shader '%s'\n", shader->name ); - return false; // end of data - } - - if( !com.stricmp( tok.string, "}" )) break; // end of shader - - // parse a stage - if( !com.stricmp( tok.string, "{" )) - { - // create a new stage - if( shader->num_stages == MAX_SHADER_STAGES ) - { - MsgDev( D_ERROR, "MAX_SHADER_STAGES hit in shader '%s'\n", shader->name ); - return false; - } - - n = shader->num_stages; - - // set defaults - stage = &r_currentPasses[n]; - Mem_Set( stage, 0, sizeof( ref_stage_t )); - stage->rgbGen.type = RGBGEN_UNKNOWN; - stage->rgbGen.args = r_currentRGBgenArgs[n]; - stage->rgbGen.func = &r_currentRGBgenFuncs[n]; - stage->alphaGen.type = ALPHAGEN_UNKNOWN; - stage->alphaGen.args = r_currentAlphagenArgs[n]; - stage->alphaGen.func = &r_currentAlphagenFuncs[n]; - stage->tcgenVec = r_currentTcGen[n][0]; - stage->tcgen = TCGEN_BASE; - stage->tcMods = r_currentTcmods[n]; - - // parse it - while( 1 ) - { - if( !Com_ReadToken( script, SC_ALLOW_NEWLINES, &tok )) - { - MsgDev( D_ERROR, "no matching '}' in shader '%s'\n", shader->name ); - return false; // end of data - } - - if( !com.stricmp( tok.string, "}" )) break; // end of stage - - // parse the command - if( !Shader_ParseStageCommand( shader, stage, script, tok.string )) - return false; - } - - if((( stage->glState & GLSTATE_SRCBLEND_MASK ) == GLSTATE_SRCBLEND_ONE ) && (( stage->glState & GLSTATE_DSTBLEND_MASK ) == GLSTATE_DSTBLEND_ZERO )) - { - stage->glState &= ~(GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK); - stage->flags |= SHADERSTAGE_BLEND_MODULATE; - } - - if(!( stage->glState & (GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK))) - stage->glState |= GLSTATE_DEPTHWRITE; - if( stage->glState & GLSTATE_DEPTHWRITE ) - shader->flags |= SHADER_DEPTHWRITE; - - switch( stage->rgbGen.type ) - { - case RGBGEN_IDENTITY_LIGHTING: - case RGBGEN_IDENTITY: - case RGBGEN_CONST: - case RGBGEN_WAVE: - case RGBGEN_COLORWAVE: - case RGBGEN_ENTITY: - case RGBGEN_ONE_MINUS_ENTITY: - case RGBGEN_LIGHTING_AMBIENT: - case RGBGEN_CUSTOM: - case RGBGEN_UNKNOWN: // assume RGBGEN_IDENTITY or RGBGEN_IDENTITY_LIGHTING - switch( stage->alphaGen.type ) - { - case ALPHAGEN_UNKNOWN: - case ALPHAGEN_IDENTITY: - case ALPHAGEN_CONST: - case ALPHAGEN_WAVE: - case ALPHAGEN_ALPHAWAVE: - case ALPHAGEN_ENTITY: - stage->flags |= SHADERSTAGE_NOCOLORARRAY; - break; - default: break; - } - break; - default: break; - } - - if(( shader->flags & SHADER_SKYPARMS ) && ( shader->flags & SHADER_DEPTHWRITE )) - { - if( stage->glState & GLSTATE_DEPTHWRITE ) - stage->glState &= ~GLSTATE_DEPTHWRITE; - } - shader->num_stages++; - continue; - } - - // parse the command - if( !Shader_ParseCommand( shader, script, tok.string )) - return false; - } - return true; - } - else - { - MsgDev( D_WARN, "expected '{', found '%s' instead in shader '%s'\n", shader->name ); - return false; - } - return false; -} - -static void Shader_SetRenderMode( ref_shader_t *s ) -{ - int i; - ref_stage_t *pass; - - for( i = 0, pass = s->stages; i < s->num_stages; i++, pass++ ) - { - pass->prev.glState = pass->glState; - pass->prev.flags = pass->flags; - pass->prev.rgbGen = pass->rgbGen; - pass->prev.alphaGen = pass->alphaGen; - } - s->realsort = s->sort; -} - -static void Shader_SetFeatures( ref_shader_t *s ) -{ - int i; - ref_stage_t *pass; - - if( s->numDeforms ) - s->features |= MF_DEFORMVS; - if( s->flags & SHADER_AUTOSPRITE ) - s->features |= MF_NOCULL; - - for( i = 0; i < s->numDeforms; i++ ) - { - switch( s->deforms[i].type ) - { - case DEFORM_BULGE: - s->features |= MF_STCOORDS; - case DEFORM_WAVE: - case DEFORM_NORMAL: - s->features |= MF_NORMALS; - break; - case DEFORM_MOVE: - break; - default: - break; - } - } - - for( i = 0, pass = s->stages; i < s->num_stages; i++, pass++ ) - { - if( pass->program && ( pass->program_type == PROGRAM_TYPE_MATERIAL || pass->program_type == PROGRAM_TYPE_DISTORTION )) - s->features |= MF_NORMALS|MF_SVECTORS|MF_LMCOORDS|MF_ENABLENORMALS; - - if( pass->flags & SHADERSTAGE_RENDERMODE ) - s->features |= MF_COLORS; - - switch( pass->rgbGen.type ) - { - case RGBGEN_LIGHTING_DIFFUSE: - s->features |= MF_NORMALS; - break; - case RGBGEN_VERTEX: - case RGBGEN_ONE_MINUS_VERTEX: - case RGBGEN_EXACT_VERTEX: - s->features |= MF_COLORS; - break; - } - - switch( pass->alphaGen.type ) - { - case ALPHAGEN_SPECULAR: - case ALPHAGEN_DOT: - case ALPHAGEN_ONE_MINUS_DOT: - s->features |= MF_NORMALS; - break; - case ALPHAGEN_VERTEX: - case ALPHAGEN_ONE_MINUS_VERTEX: - s->features |= MF_COLORS; - break; - } - - switch( pass->tcgen ) - { - case TCGEN_LIGHTMAP: - s->features |= MF_LMCOORDS; - break; - case TCGEN_ENVIRONMENT: - s->features |= MF_NORMALS; - break; - case TCGEN_REFLECTION: - case TCGEN_REFLECTION_CELLSHADE: - s->features |= MF_NORMALS|MF_ENABLENORMALS; - break; - default: - s->features |= MF_STCOORDS; - break; - } - } -} - -void Shader_Finish( ref_shader_t *s ) -{ - int i, j; - const char *oldname = s->name; - size_t size = com.strlen( oldname ) + 1; - ref_stage_t *pass; - byte *buffer; - - // if the portal capture texture hasn't been initialized yet, do that - if(( s->flags & SHADER_PORTAL_CAPTURE1 ) && !tr.portaltexture1 ) - R_InitPortalTexture( &tr.portaltexture1, 1, glState.width, glState.height ); - if(( s->flags & SHADER_PORTAL_CAPTURE2 ) && !tr.portaltexture2 ) - R_InitPortalTexture( &tr.portaltexture2, 2, glState.width, glState.height ); - - if( !s->num_stages && !s->sort ) - { - if( s->numDeforms ) - { - s->deforms = Shader_Malloc( s->numDeforms * sizeof( deform_t )); - Mem_Copy( s->deforms, r_currentDeforms, s->numDeforms * sizeof( deform_t )); - } - if( s->flags & SHADER_PORTAL ) - s->sort = SORT_PORTAL; - else s->sort = SORT_ADDITIVE; - } - - if( s->flags & SHADER_DECALPARMS ) - s->flags |= SHADER_POLYGONOFFSET; - - if( ( s->flags & SHADER_POLYGONOFFSET ) && !s->sort ) - s->sort = SORT_DECAL; - - size += s->numDeforms * sizeof( deform_t ) + s->num_stages * sizeof( ref_stage_t ); - - for( i = 0, pass = r_currentPasses; i < s->num_stages; i++, pass++ ) - { - // rgbgen args - if( pass->rgbGen.type == RGBGEN_WAVE || pass->rgbGen.type == RGBGEN_COLORWAVE || - pass->rgbGen.type == RGBGEN_CONST || pass->rgbGen.type == RGBGEN_CUSTOM ) - size += sizeof( float ) * 3; - - // alphagen args - if( pass->alphaGen.type == ALPHAGEN_PORTAL || pass->alphaGen.type == ALPHAGEN_SPECULAR || - pass->alphaGen.type == ALPHAGEN_CONST || pass->alphaGen.type == ALPHAGEN_DOT || - pass->alphaGen.type == ALPHAGEN_ONE_MINUS_DOT ) - size += sizeof( float ) * 2; - - if( pass->rgbGen.type == RGBGEN_WAVE || pass->rgbGen.type == RGBGEN_COLORWAVE ) - size += sizeof( waveFunc_t ); - if( pass->alphaGen.type == ALPHAGEN_WAVE || pass->alphaGen.type == ALPHAGEN_ALPHAWAVE ) - size += sizeof( waveFunc_t ); - size += pass->numtcMods * sizeof( tcMod_t ); - if( pass->tcgen == TCGEN_VECTOR ) - size += sizeof( vec4_t ) * 2; - } - - buffer = Shader_Malloc( size ); - - s->name = (char *)buffer; buffer += strlen( oldname ) + 1; - s->stages = ( ref_stage_t * )buffer; buffer += s->num_stages * sizeof( ref_stage_t ); - - com.strcpy( s->name, oldname ); - Mem_Copy( s->stages, r_currentPasses, s->num_stages * sizeof( ref_stage_t )); - - for( i = 0, pass = s->stages; i < s->num_stages; i++, pass++ ) - { - if( pass->rgbGen.type == RGBGEN_WAVE || pass->rgbGen.type == RGBGEN_COLORWAVE || - pass->rgbGen.type == RGBGEN_CONST || pass->rgbGen.type == RGBGEN_CUSTOM ) - { - pass->rgbGen.args = ( float * )buffer; buffer += sizeof( float ) * 3; - Mem_Copy( pass->rgbGen.args, r_currentPasses[i].rgbGen.args, sizeof( float ) * 3 ); - } - - if( pass->alphaGen.type == ALPHAGEN_PORTAL || pass->alphaGen.type == ALPHAGEN_SPECULAR || - pass->alphaGen.type == ALPHAGEN_CONST || pass->alphaGen.type == ALPHAGEN_DOT || pass->alphaGen.type == ALPHAGEN_ONE_MINUS_DOT ) - { - pass->alphaGen.args = ( float * )buffer; buffer += sizeof( float ) * 2; - Mem_Copy( pass->alphaGen.args, r_currentPasses[i].alphaGen.args, sizeof( float ) * 2 ); - } - - if( pass->rgbGen.type == RGBGEN_WAVE || pass->rgbGen.type == RGBGEN_COLORWAVE ) - { - pass->rgbGen.func = ( waveFunc_t * )buffer; buffer += sizeof( waveFunc_t ); - Mem_Copy( pass->rgbGen.func, r_currentPasses[i].rgbGen.func, sizeof( waveFunc_t )); - } - else - { - pass->rgbGen.func = NULL; - } - - if( pass->alphaGen.type == ALPHAGEN_WAVE || pass->alphaGen.type == ALPHAGEN_ALPHAWAVE ) - { - pass->alphaGen.func = ( waveFunc_t * )buffer; buffer += sizeof( waveFunc_t ); - Mem_Copy( pass->alphaGen.func, r_currentPasses[i].alphaGen.func, sizeof( waveFunc_t )); - } - else - { - pass->alphaGen.func = NULL; - } - - if( pass->numtcMods ) - { - pass->tcMods = ( tcMod_t * )buffer; buffer += r_currentPasses[i].numtcMods * sizeof( tcMod_t ); - pass->numtcMods = r_currentPasses[i].numtcMods; - Mem_Copy( pass->tcMods, r_currentPasses[i].tcMods, r_currentPasses[i].numtcMods * sizeof( tcMod_t )); - } - - if( pass->tcgen == TCGEN_VECTOR ) - { - pass->tcgenVec = ( vec_t * )buffer; buffer += sizeof( vec4_t ) * 2; - Vector4Copy( &r_currentPasses[i].tcgenVec[0], &pass->tcgenVec[0] ); - Vector4Copy( &r_currentPasses[i].tcgenVec[4], &pass->tcgenVec[4] ); - } - - if( pass->tcgen == TCGEN_WARP && s->tessSize == 0.0f ) - { - MsgDev( D_WARN, "shader '%s' has pass with 'tcGen warp' without specified 'tessSize'\n", s->name ); - pass->tcgen = TCGEN_BASE; - } - } - - if( s->numDeforms ) - { - s->deforms = ( deform_t * )buffer; - Mem_Copy( s->deforms, r_currentDeforms, s->numDeforms * sizeof( deform_t )); - } - - if( s->flags & SHADER_AUTOSPRITE ) - s->flags &= ~( SHADER_CULL_FRONT|SHADER_CULL_BACK ); - - if( r_shaderHasDlightPass ) - s->flags |= SHADER_NO_MODULATIVE_DLIGHTS; - - for( i = 0, pass = s->stages; i < s->num_stages; i++, pass++ ) - { - if( pass->flags & SHADERSTAGE_ANIMFREQUENCY && pass->anim_offset == 0 ) - { - pass->anim_offset = pass->num_textures; // alt-anim is missing - pass->animFrequency[1] = 0.0f; - } - if( pass->flags & SHADERSTAGE_LIGHTMAP ) - s->flags |= SHADER_HASLIGHTMAP; - if( pass->program ) - { - s->flags |= SHADER_NO_MODULATIVE_DLIGHTS; - if( pass->program_type == PROGRAM_TYPE_MATERIAL ) - s->flags |= SHADER_MATERIAL; - if( r_shaderHasDlightPass ) - pass->textures[5] = ( (texture_t *)1); // HACKHACK no dlights - } - - // custom lightmapped decals are handled seperately - if( s->flags & SHADER_DECALPARMS ) - pass->flags |= SHADERSTAGE_BLEND_REPLACE; - else Shader_SetBlendmode( pass ); - } - - for( i = 0, pass = s->stages; i < s->num_stages; i++, pass++ ) - { - if( !( pass->glState & ( GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK ))) - break; - } - - // all passes have blendfuncs - if( i == s->num_stages ) - { - int opaque = -1; - - for( i = 0, pass = s->stages; i < s->num_stages; i++, pass++ ) - { - if((( pass->glState & GLSTATE_SRCBLEND_MASK ) == GLSTATE_SRCBLEND_ONE ) && (( pass->glState & GLSTATE_DSTBLEND_MASK ) == GLSTATE_DSTBLEND_ZERO )) - opaque = i; - - if( pass->rgbGen.type == RGBGEN_UNKNOWN ) - { - if( !s->fog_dist && !( pass->flags & SHADERSTAGE_LIGHTMAP )) - pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING; - else pass->rgbGen.type = RGBGEN_IDENTITY; - } - - if( pass->alphaGen.type == ALPHAGEN_UNKNOWN ) - { - if( pass->rgbGen.type == RGBGEN_VERTEX /* || pass->rgbGen.type == RGBGEN_EXACT_VERTEX*/ ) - pass->alphaGen.type = ALPHAGEN_VERTEX; - else pass->alphaGen.type = ALPHAGEN_IDENTITY; - } - } - - if(!( s->flags & SHADER_SKYPARMS ) && !s->sort ) - { - if( s->flags & SHADER_DEPTHWRITE || ( opaque != -1 && s->stages[opaque].glState & GLSTATE_ALPHAFUNC )) - s->sort = SORT_ALPHATEST; - else if( opaque == -1 ) - s->sort = SORT_ADDITIVE; - else s->sort = SORT_OPAQUE; - } - } - else - { - ref_stage_t *sp; - - for( j = 0, sp = s->stages; j < s->num_stages; j++, sp++ ) - { - if( sp->rgbGen.type == RGBGEN_UNKNOWN ) - { - if( sp->glState & GLSTATE_ALPHAFUNC && !( j && s->stages[j-1].flags & SHADERSTAGE_LIGHTMAP )) // FIXME! - sp->rgbGen.type = RGBGEN_IDENTITY_LIGHTING; - else sp->rgbGen.type = RGBGEN_IDENTITY; - } - - if( sp->alphaGen.type == ALPHAGEN_UNKNOWN ) - { - if( sp->rgbGen.type == RGBGEN_VERTEX /* || sp->rgbGen.type == RGBGEN_EXACT_VERTEX*/ ) - sp->alphaGen.type = ALPHAGEN_VERTEX; - else sp->alphaGen.type = ALPHAGEN_IDENTITY; - } - } - - if( !s->sort ) - { - if( pass->glState & GLSTATE_ALPHAFUNC ) - s->sort = SORT_ALPHATEST; - } - - if( !( pass->glState & GLSTATE_DEPTHWRITE ) && !( s->flags & SHADER_SKYPARMS )) - { - pass->glState |= GLSTATE_DEPTHWRITE; - s->flags |= SHADER_DEPTHWRITE; - } - } - - if( !s->sort ) s->sort = SORT_OPAQUE; - - if(( s->flags & SHADER_SKYPARMS ) && ( s->flags & SHADER_DEPTHWRITE )) - s->flags &= ~SHADER_DEPTHWRITE; - - Shader_SetRenderMode( s ); - Shader_SetFeatures( s ); - - // refresh registration sequence - Shader_TouchImages( s, FREE_IGNORE ); -} - -void R_DeformvBBoxForShader( const ref_shader_t *shader, vec3_t ebbox ) -{ - int dv; - - if( !shader ) return; - for( dv = 0; dv < shader->numDeforms; dv++ ) - { - switch( shader->deforms[dv].type ) - { - case DEFORM_WAVE: - ebbox[0] = max( ebbox[0], fabs( shader->deforms[dv].func.args[1] ) + shader->deforms[dv].func.args[0] ); - ebbox[1] = ebbox[0]; - ebbox[2] = ebbox[0]; - break; - default: - break; - } - } -} - -static ref_shader_t *Shader_CreateDefault( ref_shader_t *shader, int type, int addFlags, const char *shortname ) -{ - ref_stage_t *pass; - texture_t *materialImages[MAX_STAGE_TEXTURES]; - script_t *script; - char *skyParms; - uint i, hashKey; - size_t length; - - length = com.strlen( shortname ); - - // make a default shader - switch( type ) - { - case SHADER_DECAL: - shader->type = SHADER_DECAL; - shader->flags = SHADER_CULL_FRONT|SHADER_POLYGONOFFSET|SHADER_HASLIGHTMAP; - shader->features = MF_STCOORDS|MF_LMCOORDS; - shader->sort = SORT_DECAL; - shader->num_stages = 2; - shader->name = Shader_Malloc( length + 1 + sizeof( ref_stage_t ) * shader->num_stages ); - strcpy( shader->name, shortname ); - shader->stages = (ref_stage_t *)((byte *)shader->name + length + 1 ); - pass = &shader->stages[0]; - pass->flags = SHADERSTAGE_BLEND_REPLACE; - pass->glState = GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA; - pass->tcgen = TCGEN_BASE; - pass->textures[0] = Shader_FindImage( shader, shortname, TF_CLAMP|addFlags ); - pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING; - pass->alphaGen.type = ALPHAGEN_VERTEX; // for fading decals - pass->num_textures++; - pass = &shader->stages[1]; - pass->flags = SHADERSTAGE_LIGHTMAP|SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_REPLACE; - pass->glState = GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_ZERO; - pass->tcgen = TCGEN_LIGHTMAP; - pass->rgbGen.type = RGBGEN_IDENTITY; - pass->alphaGen.type = ALPHAGEN_IDENTITY; - break; - case SHADER_FLARE: - shader->type = SHADER_FLARE; - shader->features = MF_STCOORDS|MF_COLORS; - shader->sort = SORT_ADDITIVE; - shader->num_stages = 1; - shader->name = Shader_Malloc( length + 1 + sizeof( ref_stage_t ) * shader->num_stages ); - strcpy( shader->name, shortname ); - shader->stages = ( ref_stage_t * )(( byte * )shader->name + length + 1 ); - pass = &shader->stages[0]; - pass->flags = SHADERSTAGE_BLEND_ADD; - pass->glState = GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE; - pass->textures[0] = Shader_FindImage( shader, shortname, addFlags ); - pass->rgbGen.type = RGBGEN_VERTEX; - pass->alphaGen.type = ALPHAGEN_IDENTITY; - pass->tcgen = TCGEN_BASE; - pass->num_textures++; - break; - case SHADER_STUDIO: - shader->type = SHADER_STUDIO; - shader->flags = SHADER_DEPTHWRITE|SHADER_CULL_FRONT|SHADER_RENDERMODE; - shader->features = MF_STCOORDS|MF_NORMALS; - shader->num_stages = 1; - shader->name = Shader_Malloc( length + 1 + sizeof( ref_stage_t ) * shader->num_stages ); - strcpy( shader->name, shortname ); - shader->stages = ( ref_stage_t * )(( byte * )shader->name + length + 1 ); - pass = &shader->stages[0]; - pass->tcgen = TCGEN_BASE; - - switch( r_shaderRenderMode ) - { - case kRenderTransTexture: - // normal transparency - pass->flags |= SHADERSTAGE_BLEND_MODULATE; - pass->glState = GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_DEPTHWRITE; - pass->rgbGen.type = RGBGEN_LIGHTING_AMBIENT; - pass->alphaGen.type = ALPHAGEN_ENTITY; - shader->sort = SORT_ADDITIVE; - break; - case kRenderTransAdd: - pass->flags |= SHADERSTAGE_BLEND_ADD; - pass->glState = (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE); - pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING; // models ignore color in 'add' mode - pass->alphaGen.type = ALPHAGEN_ENTITY; - shader->sort = SORT_ADDITIVE; - break; - case kRenderTransAlpha: - pass->flags |= SHADERSTAGE_BLEND_DECAL; - pass->glState = GLSTATE_AFUNC_GE128|GLSTATE_DEPTHWRITE; - pass->rgbGen.type = RGBGEN_LIGHTING_AMBIENT; - pass->alphaGen.type = ALPHAGEN_ENTITY; - shader->sort = SORT_ALPHATEST; - break; - default: - pass->flags |= SHADERSTAGE_RENDERMODE; // any studio model can overrided himself rendermode - pass->glState = GLSTATE_DEPTHWRITE; - pass->rgbGen.type = RGBGEN_LIGHTING_DIFFUSE; - pass->alphaGen.type = ALPHAGEN_IDENTITY; - shader->sort = SORT_OPAQUE; - break; - } - - if( MOD_ALLOWBUMP() && r_numStageTextures == 4 ) - { - // material - shader->flags &= ~SHADER_RENDERMODE; - pass->flags &= ~SHADERSTAGE_RENDERMODE; - pass->rgbGen.type = RGBGEN_IDENTITY; - pass->program = DEFAULT_GLSL_PROGRAM; - pass->program_type = PROGRAM_TYPE_MATERIAL; - pass->textures[0] = r_stageTexture[0]; // diffusemap - pass->num_textures++; - pass->textures[1] = r_stageTexture[1]; // normalmap - pass->num_textures++; - pass->textures[2] = (r_lighting_specular->integer) ? r_stageTexture[2] : NULL; // glossmap - pass->num_textures++; - pass->textures[3] = r_stageTexture[3]; // decalmap - pass->num_textures++; - shader->features |= MF_SVECTORS|MF_ENABLENORMALS; - shader->flags |= SHADER_MATERIAL; - } - else - { - pass->textures[0] = r_stageTexture[0]; - pass->num_textures++; - - if( !pass->textures[0] ) - { - MsgDev( D_WARN, "couldn't find studio skin for shader '%s', using default...\n", shader->name ); - pass->textures[0] = tr.defaultTexture; - } - } - break; - case SHADER_SPRITE: - shader->type = SHADER_SPRITE; - shader->flags = SHADER_RENDERMODE; - shader->flags |= (r_shaderTwoSided) ? 0 : SHADER_CULL_FRONT; - shader->features = MF_STCOORDS|MF_COLORS; - shader->num_stages = 1; - shader->name = Shader_Malloc( length + 1 + sizeof( ref_stage_t ) * shader->num_stages ); - strcpy( shader->name, shortname ); - shader->stages = (ref_stage_t *)( ( byte * )shader->name + length + 1 ); - pass = &shader->stages[0]; - pass->tcgen = TCGEN_BASE; - if( r_stageAnimFrequency[0] == -8.0f && r_numStageTextures == 8 ) - { - // store angled map into one bundle - pass->flags |= SHADERSTAGE_ANGLEDMAP; - - for( i = 0; i < 8; i++ ) - { - if( !r_stageTexture[i] ) pass->textures[i] = tr.defaultTexture; - else pass->textures[i] = r_stageTexture[i]; - pass->num_textures++; - } - } - else if( r_numStageTextures > 1 ) - { - // store group frames into one stage - pass->flags |= SHADERSTAGE_FRAMES; - if( r_stageAnimFrequency[0] != 0.0f ) - { - pass->flags |= SHADERSTAGE_ANIMFREQUENCY; - pass->animFrequency[0] = r_stageAnimFrequency[0]; - } - for( i = 0; i < r_numStageTextures; i++ ) - { - if( !r_stageTexture[i] ) pass->textures[i] = tr.defaultTexture; - else pass->textures[i] = r_stageTexture[i]; - pass->num_textures++; - } - - } - else - { - // single frame - pass->textures[0] = r_stageTexture[0]; - pass->num_textures++; - - if( !pass->textures[0] ) - { - MsgDev( D_WARN, "couldn't find spriteframe for shader '%s', using default...\n", shader->name ); - pass->textures[0] = tr.defaultTexture; - } - } - - pass->flags |= SHADERSTAGE_RENDERMODE; // any sprite can overrided himself rendermode - - switch( r_shaderRenderMode ) - { - case kRenderTransTexture: // normal transparency - pass->glState = (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA); - pass->flags = SHADERSTAGE_BLEND_MODULATE; - pass->rgbGen.type = RGBGEN_VERTEX; - pass->alphaGen.type = ALPHAGEN_VERTEX; - shader->sort = SORT_ADDITIVE; - break; - case kRenderTransAdd: - pass->flags |= SHADERSTAGE_BLEND_ADD; - pass->glState = (GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE); - pass->alphaGen.type = ALPHAGEN_VERTEX; - pass->rgbGen.type = RGBGEN_VERTEX; - shader->sort = SORT_ADDITIVE; - break; - case kRenderGlow: - pass->flags |= SHADERSTAGE_BLEND_ADD; - pass->glState = GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_DSTBLEND_ONE|GLSTATE_NO_DEPTH_TEST; - pass->alphaGen.type = ALPHAGEN_VERTEX; - pass->rgbGen.type = RGBGEN_VERTEX; - shader->sort = SORT_ADDITIVE; - break; - case kRenderTransAlpha: - shader->flags |= SHADER_DEPTHWRITE; - pass->flags |= SHADERSTAGE_BLEND_DECAL; - pass->glState = GLSTATE_AFUNC_GE128|GLSTATE_DEPTHWRITE; - pass->rgbGen.type = RGBGEN_LIGHTING_AMBIENT; - pass->alphaGen.type = ALPHAGEN_IDENTITY; - shader->sort = SORT_ALPHATEST; - break; - default: - shader->flags |= SHADER_DEPTHWRITE; - pass->glState = GLSTATE_DEPTHWRITE; - pass->rgbGen.type = RGBGEN_LIGHTING_AMBIENT; - pass->alphaGen.type = ALPHAGEN_IDENTITY; - shader->sort = SORT_OPAQUE; - break; - } - break; - case SHADER_NOMIP: - shader->type = SHADER_NOMIP; - shader->features = MF_STCOORDS|MF_COLORS; - shader->flags = SHADER_STATIC|SHADER_RENDERMODE; - shader->sort = SORT_NEAREST; - shader->num_stages = 1; - shader->name = Shader_Malloc( length + 1 + sizeof( ref_stage_t ) * shader->num_stages ); - strcpy( shader->name, shortname ); - shader->stages = (ref_stage_t *)((byte *)shader->name + length + 1 ); - pass = &shader->stages[0]; - pass->flags = SHADERSTAGE_BLEND_REPLACE|SHADERSTAGE_RENDERMODE; - pass->glState = GLSTATE_NONE; - - if( r_numStageTextures ) pass->textures[0] = r_stageTexture[0]; - else pass->textures[0] = Shader_FindImage( shader, shortname, addFlags|TF_NOPICMIP|TF_CLAMP|TF_NOMIPMAP ); - - pass->rgbGen.type = RGBGEN_IDENTITY; - pass->alphaGen.type = ALPHAGEN_IDENTITY; - pass->tcgen = TCGEN_BASE; - pass->num_textures++; - break; - case SHADER_SKY: - shader->type = SHADER_SKY|SHADER_STATIC; - shader->name = Shader_Malloc( length + 1 ); - strcpy( shader->name, shortname ); - // create simple sky parms, when Shader_SkyParms parsing it properly - skyParms = va( "%s - -", shortname ); - script = Com_OpenScript( "skybox", skyParms, com.strlen( skyParms )); - Shader_SkyParms( shader, NULL, script ); - Com_CloseScript( script ); - break; - case SHADER_FARBOX: - shader->type = SHADER_FARBOX; - shader->features = MF_STCOORDS; - shader->sort = SORT_SKY; - shader->flags = SHADER_SKYPARMS|SHADER_STATIC; - shader->num_stages = 1; - shader->name = Shader_Malloc( length + 1 + sizeof( ref_stage_t ) * shader->num_stages ); - strcpy( shader->name, shortname ); - shader->stages = ( ref_stage_t * )( ( byte * )shader->name + length + 1 ); - pass = &shader->stages[0]; - pass->flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE; -// pass->glState = GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ZERO; - pass->textures[0] = R_FindTexture( shortname, NULL, 0, addFlags|TF_CLAMP|TF_NOMIPMAP ); - pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING; - pass->alphaGen.type = ALPHAGEN_IDENTITY; - pass->tcgen = TCGEN_BASE; - pass->num_textures++; - break; - case SHADER_NEARBOX: - shader->type = SHADER_NEARBOX; - shader->features = MF_STCOORDS; - shader->sort = SORT_SKY; - shader->num_stages = 1; - shader->flags = SHADER_SKYPARMS|SHADER_STATIC; - shader->name = Shader_Malloc( length + 1 + sizeof( ref_stage_t ) * shader->num_stages ); - strcpy( shader->name, shortname ); - shader->stages = ( ref_stage_t * )( ( byte * )shader->name + length + 1 ); - pass = &shader->stages[0]; - pass->flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_DECAL; - pass->glState = GLSTATE_ALPHAFUNC|GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_SRC_COLOR; - pass->textures[0] = R_FindTexture( shortname, NULL, 0, addFlags|TF_CLAMP|TF_NOMIPMAP ); - pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING; - pass->alphaGen.type = ALPHAGEN_IDENTITY; - pass->tcgen = TCGEN_BASE; - pass->num_textures++; - break; - case SHADER_PLANAR_SHADOW: - shader->type = SHADER_PLANAR_SHADOW; - shader->features = MF_DEFORMVS; - shader->sort = SORT_DECAL; - shader->flags = SHADER_STATIC; - shader->numDeforms = 1; - shader->num_stages = 1; - shader->name = Shader_Malloc( length + 1 + shader->numDeforms * sizeof( deform_t ) + sizeof( ref_stage_t ) * shader->num_stages ); - strcpy( shader->name, shortname ); - shader->deforms = ( deform_t * )( ( byte * )shader->name + length + 1 ); - shader->deforms[0].type = DEFORM_PROJECTION_SHADOW; - shader->stages = ( ref_stage_t * )((byte *)shader->deforms + shader->numDeforms * sizeof( deform_t ) ); - pass = &shader->stages[0]; - pass->flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_STENCILSHADOW|SHADERSTAGE_BLEND_DECAL; - pass->glState = GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA; - pass->rgbGen.type = RGBGEN_IDENTITY; - pass->alphaGen.type = ALPHAGEN_IDENTITY; - pass->tcgen = TCGEN_NONE; - break; - case SHADER_OPAQUE_OCCLUDER: - shader->type = SHADER_OPAQUE_OCCLUDER; - shader->sort = SORT_OPAQUE; - shader->flags = SHADER_CULL_FRONT|SHADER_DEPTHWRITE|SHADER_STATIC; - shader->num_stages = 1; - shader->name = Shader_Malloc( length + 1 + sizeof( ref_stage_t ) * shader->num_stages + 3 * sizeof( float ) ); - strcpy( shader->name, shortname ); - shader->stages = ( ref_stage_t * )( ( byte * )shader->name + length + 1 ); - pass = &shader->stages[0]; - pass->textures[0] = tr.whiteTexture; - pass->flags = SHADERSTAGE_NOCOLORARRAY; - pass->glState = GLSTATE_DEPTHWRITE; - pass->rgbGen.type = RGBGEN_ENVIRONMENT; - pass->rgbGen.args = ( float * )( ( byte * )shader->stages + sizeof( ref_stage_t ) * shader->num_stages ); - VectorClear( pass->rgbGen.args ); - pass->alphaGen.type = ALPHAGEN_IDENTITY; - pass->tcgen = TCGEN_NONE; - pass->num_textures++; - break; - case SHADER_TEXTURE: - if( mapConfig.deluxeMappingEnabled && Shaderpass_LoadMaterial( &materialImages[0], &materialImages[1], &materialImages[2], shortname, addFlags, 1 )) - { - shader->type = SHADER_TEXTURE; - shader->flags = SHADER_DEPTHWRITE|SHADER_CULL_FRONT|SHADER_NO_MODULATIVE_DLIGHTS|SHADER_HASLIGHTMAP|SHADER_MATERIAL; - shader->features = MF_STCOORDS|MF_LMCOORDS|MF_NORMALS|MF_SVECTORS|MF_ENABLENORMALS; - shader->sort = SORT_OPAQUE; - shader->num_stages = 1; - shader->name = Shader_Malloc( length + 1 + sizeof( ref_stage_t ) * shader->num_stages ); - com.strcpy( shader->name, shortname ); - shader->stages = (ref_stage_t *)(( byte * )shader->name + length + 1 ); - pass = &shader->stages[0]; - pass->flags = SHADERSTAGE_LIGHTMAP|SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_REPLACE; - pass->glState = GLSTATE_DEPTHWRITE; - pass->tcgen = TCGEN_BASE; - pass->rgbGen.type = RGBGEN_IDENTITY; - pass->alphaGen.type = ALPHAGEN_IDENTITY; - pass->program = DEFAULT_GLSL_PROGRAM; - pass->program_type = PROGRAM_TYPE_MATERIAL; - pass->textures[0] = Shader_FindImage( shader, shortname, addFlags ); - pass->num_textures++; - pass->textures[1] = materialImages[0]; // normalmap - pass->num_textures++; - pass->textures[2] = materialImages[1]; // glossmap - pass->num_textures++; - pass->textures[3] = materialImages[2]; // decalmap - pass->num_textures++; - } - else - { - int size, offset; - qboolean hasLightmap = ( r_miptexFeatures & MIPTEX_NOLIGHTMAP ) ? false : true; - - shader->type = SHADER_TEXTURE; - shader->flags = SHADER_DEPTHWRITE|SHADER_CULL_FRONT|SHADER_RENDERMODE; - if( hasLightmap ) shader->flags |= SHADER_HASLIGHTMAP; - shader->features = MF_STCOORDS; - if( hasLightmap ) shader->features |= MF_LMCOORDS; - shader->sort = SORT_OPAQUE; - shader->num_stages = ( hasLightmap ) ? 2 : 1; - size = length + 1 + sizeof( ref_stage_t ) * shader->num_stages; - if( r_miptexFeatures & MIPTEX_CONVEYOR ) size += sizeof( tcMod_t ); - if( r_miptexFeatures & MIPTEX_WARPSURFACE ) size += sizeof( deform_t ); - - shader->name = Shader_Malloc( size ); - com.strcpy( shader->name, shortname ); - shader->stages = (ref_stage_t *)((byte *)shader->name + length + 1 ); - pass = &shader->stages[0]; - pass->flags = SHADERSTAGE_RENDERMODE|SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_REPLACE; - pass->glState = GLSTATE_DEPTHWRITE; - if( r_miptexFeatures & MIPTEX_WARPSURFACE ) - { - pass->tcgen = TCGEN_WARP; - shader->tessSize = 64.0f; - - // apply waves - offset = length + 1 + sizeof( ref_stage_t ) * shader->num_stages; - if( r_miptexFeatures & MIPTEX_CONVEYOR ) offset += sizeof( tcMod_t ); - shader->features |= (MF_DEFORMVS|MF_NORMALS); - - shader->deforms = (deform_t *)((byte *)shader->name + offset ); - shader->deforms->type = DEFORM_WAVE; - shader->deforms->func.type = WAVEFORM_SIN; - shader->deforms->args[0] = 0.01f; - shader->deforms->func.args[3] = 0.5f; - shader->numDeforms++; - shader->flags &= ~SHADER_CULL_FRONT; // water is drawing backface - } - else pass->tcgen = TCGEN_BASE; - - if( r_numStageTextures > 1 ) - { - // extended sequence - if( r_stageAnimFrequency[0] != 0.0f ) - { - pass->flags |= SHADERSTAGE_ANIMFREQUENCY; - pass->animFrequency[0] = r_stageAnimFrequency[0]; - pass->animFrequency[1] = r_stageAnimFrequency[1]; - pass->anim_offset = (r_stageAnimOffset == 0) ? r_numStageTextures : r_stageAnimOffset; - } - else pass->flags |= SHADERSTAGE_FRAMES; - - for( i = 0; i < r_numStageTextures; i++ ) - { - if( !r_stageTexture[i] ) - pass->textures[i] = tr.defaultTexture; - else pass->textures[i] = r_stageTexture[i]; - pass->num_textures++; - } - pass->textures[0] = r_stageTexture[0]; - } - else if( r_numStageTextures == 1 ) - { - pass->textures[0] = r_stageTexture[0]; - pass->num_textures++; - } - else pass->textures[0] = Shader_FindImage( shader, shortname, addFlags ); - pass->rgbGen.type = RGBGEN_IDENTITY_LIGHTING; - pass->alphaGen.type = ALPHAGEN_IDENTITY; - - if( r_miptexFeatures & MIPTEX_CONVEYOR ) - { - pass->tcMods = (tcMod_t *)((byte *)shader->name + length + 1 + sizeof( ref_stage_t ) * shader->num_stages ); - pass->tcMods[0].type = TCMOD_CONVEYOR; - pass->numtcMods++; - } - - if( !hasLightmap ) break; - pass = &shader->stages[1]; - pass->flags = SHADERSTAGE_LIGHTMAP|SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_REPLACE; - pass->glState = GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_ZERO|GLSTATE_DEPTHFUNC_EQ; - pass->tcgen = TCGEN_LIGHTMAP; - pass->rgbGen.type = RGBGEN_IDENTITY; - pass->alphaGen.type = ALPHAGEN_IDENTITY; - } - break; - case SHADER_GENERIC: - default: shader->type = SHADER_GENERIC; - shader->flags = SHADER_DEPTHWRITE|SHADER_CULL_FRONT|SHADER_NO_MODULATIVE_DLIGHTS; - shader->features = MF_STCOORDS; - shader->sort = SORT_OPAQUE; - shader->num_stages = 1; - shader->name = Shader_Malloc( length + 1 + sizeof( ref_stage_t ) * shader->num_stages ); - strcpy( shader->name, shortname ); - shader->stages = (ref_stage_t *)(( byte * )shader->name + length + 1 ); - pass = &shader->stages[0]; - pass->flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE; - pass->glState = GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR; - pass->tcgen = TCGEN_BASE; - pass->textures[0] = Shader_FindImage( shader, shortname, addFlags ); - pass->rgbGen.type = RGBGEN_IDENTITY; - pass->alphaGen.type = ALPHAGEN_IDENTITY; - pass->num_textures++; - break; - } - - Shader_SetRenderMode( shader ); - - // refresh registration sequence - Shader_TouchImages( shader, FREE_IGNORE ); - - // calculate sortkey - shader->sortkey = Shader_Sortkey( shader, shader->sort ); - shader->flags |= SHADER_DEFAULTED; - - // add to hash table - hashKey = Com_HashKey( shortname, SHADERS_HASH_SIZE ); - shader->nextHash = r_shadersHash[hashKey]; - r_shadersHash[hashKey] = shader; - - return shader; -} - -/* -================ -R_CleanupShaderName - -kill backward slashes and turn all leters -into lower register -================ -*/ -static qboolean R_CleanupShaderName( const char *name, char *outname, size_t outsize ) -{ - int i, length = 0; - - if( !name || !name[0] || !outname ) - return false; - - for( i = ( name[0] == '/' || name[0] == '\\' ); name[i] && ( length < outsize - 1 ); i++ ) - { - if( name[i] == '\\' ) outname[length++] = '/'; - else outname[length++] = com.tolower( name[i] ); - } - - if( !length ) - return false; - - outname[length] = 0; - - return true; -} - -ref_shader_t *R_FindShader( const char *name, int type, int ignoreType ) -{ - ref_shader_t *shader; - string shortname; - uint hashKey; - - if( !R_CleanupShaderName( name, shortname, sizeof( shortname ))) - return NULL; - - // see if already loaded - hashKey = Com_HashKey( shortname, SHADERS_HASH_SIZE ); - - for( shader = r_shadersHash[hashKey]; shader; shader = shader->nextHash ) - { - if( shader->type == ignoreType ) continue; - - if( !com.stricmp( shader->name, shortname )) - { - if( shader->type != type ) - { - if( shader->flags & SHADER_SKYPARMS ) - MsgDev( D_WARN, "reused shader '%s' with mixed types (%i should be %i)\n", shortname, shader->type, type ); - else continue; - } - // prolonge registration - Shader_TouchImages( shader, FREE_IGNORE ); - return shader; - } - } - return NULL; -} - -ref_shader_t *R_LoadShader( const char *name, int type, qboolean forceDefault, int addFlags, int ignoreType ) -{ - ref_shader_t *shader; - string shortname; - ref_script_t *cache = NULL; - uint i, hashKey; - - if( !R_CleanupShaderName( name, shortname, sizeof( shortname ))) - return NULL; - - // see if already loaded - hashKey = Com_HashKey( shortname, SHADERS_HASH_SIZE ); - - for( shader = r_shadersHash[hashKey]; shader; shader = shader->nextHash ) - { - if( shader->type == ignoreType ) continue; - - if( !com.stricmp( shader->name, shortname )) - { - if( shader->type != type ) - { - if( shader->flags & SHADER_SKYPARMS ) - MsgDev( D_WARN, "reused shader '%s' with mixed types (%i should be %i)\n", shortname, shader->type, type ); - else continue; - } - // prolonge registration - Shader_TouchImages( shader, FREE_IGNORE ); - return shader; - } - } - - // find a free shader_t slot - for( i = 0, shader = r_shaders; i < r_numShaders; i++, shader++ ) - if( !shader->name ) break; - - if( i == r_numShaders ) - { - if( r_numShaders == MAX_SHADERS ) - Host_Error( "R_LoadShader: MAX_SHADERS limit exceeded\n" ); - r_numShaders++; - } - - shader = &r_shaders[i]; - Mem_Set( shader, 0, sizeof( ref_shader_t )); - shader->offsetmapping_scale = 1.0f; - shader->name = shortname; - shader->shadernum = i; - - if( ignoreType == SHADER_UNKNOWN ) - forceDefault = true; - - r_shaderNoMipMaps = false; - r_shaderNoPicMip = false; - r_shaderNoCompress = false; - r_shaderHasDlightPass = false; - r_shaderNearest = false; - - if( !forceDefault ) - cache = Shader_GetCache( shortname, type, hashKey ); - - // the shader is in the shader scripts - if( cache ) - { - script_t *script; - - MsgDev( D_NOTE, "Loading shader %s from cache...\n", name ); - - // set defaults - shader->type = type; - shader->flags = SHADER_CULL_FRONT; - shader->features = MF_NONE; - - shader->cache = cache; - - // load the script text - script = Com_OpenScript( cache->name, cache->buffer, cache->size ); - if( !script ) return Shader_CreateDefault( shader, type, addFlags, shortname ); - - if( !Shader_ParseShader( shader, script )) - { - Mem_Set( shader, 0, sizeof( ref_shader_t )); - shader->offsetmapping_scale = 1.0f; - shader->name = shortname; - shader->shadernum = i; - - Com_CloseScript( script ); - return Shader_CreateDefault( shader, type, addFlags, shortname ); - } - Com_CloseScript( script ); - Shader_Finish( shader ); - } - else return Shader_CreateDefault( shader, type, addFlags, shortname ); - - // calculate sortkey - shader->sortkey = Shader_Sortkey( shader, shader->sort ); - - // add to hash table - shader->nextHash = r_shadersHash[hashKey]; - r_shadersHash[hashKey] = shader; - - return shader; -} - -void R_ShaderFreeUnused( void ) -{ - ref_shader_t *shader; - int i; - - for( i = 0, shader = r_shaders; i < r_numShaders; i++, shader++ ) - { - if( !shader->shadernum ) continue; - - // used this sequence - if( shader->touchFrame == tr.registration_sequence ) continue; - if( shader->flags & SHADER_STATIC ) continue; - Shader_FreeShader( shader, FREE_NORMAL ); - } -} - -void R_SetInternalTexture( mip_t *mt ) -{ - r_internalTexture = mt; -} - -void R_ShaderAddStageTexture( texture_t *mipTex ) -{ - if( r_numStageTextures >= MAX_STAGE_TEXTURES ) return; - r_stageTexture[r_numStageTextures++] = mipTex; -} - -void R_ShaderSetMiptexFlags( uint addFlags ) -{ - r_miptexFeatures |= addFlags; -} - -void R_ShaderSetRenderMode( int mode, qboolean twoSided ) -{ - r_shaderRenderMode = mode; - r_shaderTwoSided = twoSided; -} - -void R_ShaderAddStageIntervals( float interval ) -{ - r_stageAnimFrequency[0] += interval; -} - -void R_SetAnimFrequency( float anim_fps ) -{ - if( r_numStageTextures ) - { - // tired to specify third anim sequence, ignore - if( r_stageAnimOffset ) return; - - r_stageAnimFrequency[1] = anim_fps; - r_stageAnimOffset = r_numStageTextures; - } - else - { - r_stageAnimFrequency[0] = anim_fps; - r_stageAnimOffset = 0; - } -} - -/* -================= -R_SetupSky -================= -*/ -void R_SetupSky( const char *name ) -{ - string loadname; - qboolean shader_valid = false; - qboolean force_default = false; - ref_script_t *cache; - ref_shader_t *shader; - uint hashKey; - int index; - - if( !name || !name[0] ) return; - - com.snprintf( loadname, sizeof( loadname ), "%s/%s", SI->envpath, name ); - - // make sure what new shader it's a skyShader and existing - hashKey = Com_HashKey( loadname, SHADERS_HASH_SIZE ); - - for( shader = r_shadersHash[hashKey]; shader; shader = shader->nextHash ) - { - if( !com.stricmp( shader->name, loadname )) - break; - } - - if( shader ) - { - // already loaded, check parms - if( shader->flags & SHADER_SKYPARMS && shader->skyParms ) - shader_valid = true; - } - else - { - cache = Shader_GetCache( loadname, SHADER_INVALID, hashKey ); - if( cache ) - { - script_t *script = Com_OpenScript( cache->name, cache->buffer, cache->size ); - token_t tok; - - while( Com_ReadToken( script, SC_ALLOW_NEWLINES, &tok )) - { - if( !com.stricmp( "skyParms", tok.string )) - { - // check only far skybox images for existing - // because near skybox without far will be ignored by engine - if( Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - { - if( com.stricmp( "-", tok.string )) - { - if( Shader_CheckSkybox( tok.string )) - { - shader_valid = true; - break; - } - } - else - { - shader_valid = true; - break; // new shader just reset skybox - } - } - } - else if( !com.stricmp( "surfaceParm", tok.string )) - { - // check only far skybox images for existing - // because near skybox without far will be ignored by engine - if( Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - { - if( !com.stricmp( "sky", tok.string )) - { - shader_valid = true; - break; // yes it's q3-style skyshader - } - } - } - } - Com_CloseScript( script ); - } - else - { - if( Shader_CheckSkybox( loadname )) - shader_valid = true; - force_default = true; - } - } - - if( !shader_valid ) - { - MsgDev( D_ERROR, "R_SetupSky: 'couldn't find shader '%s'\n", name ); - return; - } - - if( tr.currentSkyShader == NULL ) - { - MsgDev( D_ERROR, "R_SetupSky: tr.currentSkyShader == NULL\n" ); - return; - } - - index = tr.currentSkyShader->shadernum; - Shader_FreeShader( tr.currentSkyShader, FREE_FORCE ); // release old sky - - // new sky shader - tr.currentSkyShader = R_LoadShader( loadname, SHADER_SKY, true, 0, SHADER_INVALID ); - if( index != tr.currentSkyShader->shadernum ) - MsgDev( D_ERROR, "R_SetupSky: mismatch shader indexes %i != %i\n", index, tr.currentSkyShader->shadernum ); -} - -void R_FreeSky( void ) -{ - // already freed ? - if( tr.currentSkyShader == NULL ) return; - Shader_FreeShader( tr.currentSkyShader, FREE_FORCE ); - tr.currentSkyShader = NULL; -} \ No newline at end of file diff --git a/vid_gl/r_shader.h b/vid_gl/r_shader.h deleted file mode 100644 index 3cafe6bd..00000000 --- a/vid_gl/r_shader.h +++ /dev/null @@ -1,359 +0,0 @@ -/* -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#ifndef R_SHADER_H -#define R_SHADER_H - -#define MAX_SHADERS 4096 -#define SHADERS_HASH_SIZE 256 -#define MAX_STAGE_TEXTURES 256 // same as MAX_SPRITE_FRAMES -#define MAX_SHADER_STAGES 8 -#define MAX_SHADER_DEFORMS 8 -#define MAX_SHADER_TCMODS 8 - -#define MAX_TABLES 4096 -#define TABLES_HASH_SIZE 1024 - -// shader types -#define SHADER_INVALID -1 -#define SHADER_UNKNOWN 0 -#define SHADER_SKY 1 -#define SHADER_NOMIP 2 -#define SHADER_DECAL 3 -#define SHADER_SPRITE 4 -#define SHADER_GENERIC 5 -#define SHADER_TEXTURE 6 -#define SHADER_FLARE 7 -#define SHADER_STUDIO 8 -#define SHADER_FARBOX 9 -#define SHADER_NEARBOX 10 -#define SHADER_PLANAR_SHADOW 11 -#define SHADER_OPAQUE_OCCLUDER 12 - -// shader flags -typedef enum -{ - SHADER_STATIC = BIT(0), // never freed by R_ShaderFreeUnused - SHADER_DEPTHWRITE = BIT(1), - SHADER_SKYPARMS = BIT(2), - SHADER_DECALPARMS = BIT(3), // it's a lightmapped decal - SHADER_POLYGONOFFSET = BIT(4), - SHADER_CULL_FRONT = BIT(5), - SHADER_CULL_BACK = BIT(6), - SHADER_DEFAULTED = BIT(7), - SHADER_MATERIAL = BIT(8), - SHADER_DEFORM_NORMAL = BIT(9), - SHADER_ENTITY_MERGABLE = BIT(10), - SHADER_AUTOSPRITE = BIT(11), - SHADER_NO_MODULATIVE_DLIGHTS = BIT(12), - SHADER_HASLIGHTMAP = BIT(13), - SHADER_PORTAL = BIT(14), - SHADER_PORTAL_CAPTURE1 = BIT(15), - SHADER_PORTAL_CAPTURE2 = BIT(16), - SHADER_RENDERMODE = BIT(17), - SHADER_PORTAL_CAPTURE = (SHADER_PORTAL_CAPTURE1|SHADER_PORTAL_CAPTURE1), - SHADER_CULL = (SHADER_CULL_FRONT|SHADER_CULL_BACK), - -} shaderFlags_t; - -// shaderstage flags -enum -{ - SHADERSTAGE_ANIMFREQUENCY = BIT(0), // auto-animate value - SHADERSTAGE_FRAMES = BIT(1), // bundle have anim frames, thats can be switching manually - SHADERSTAGE_ANGLEDMAP = BIT(2), // doom1 eight angle-aligned ( 360 / 8 ) textures - SHADERSTAGE_LIGHTMAP = BIT(3), - SHADERSTAGE_DETAIL = BIT(4), - SHADERSTAGE_NOCOLORARRAY = BIT(5), - SHADERSTAGE_DLIGHT = BIT(6), - SHADERSTAGE_PORTALMAP = BIT(7), - SHADERSTAGE_STENCILSHADOW = BIT(8), - SHADERSTAGE_RENDERMODE = BIT(9), - SHADERSTAGE_BLEND_REPLACE = BIT(10), - SHADERSTAGE_BLEND_MODULATE = BIT(11), - SHADERSTAGE_BLEND_ADD = BIT(12), - SHADERSTAGE_BLEND_DECAL = BIT(13) -} stageFlags_t; - -#define SHADERSTAGE_BLENDMODE (SHADERSTAGE_BLEND_REPLACE|SHADERSTAGE_BLEND_MODULATE|SHADERSTAGE_BLEND_ADD|SHADERSTAGE_BLEND_DECAL) - -// sorting -typedef enum -{ - SORT_NONE = 0, - SORT_PORTAL = 1, - SORT_SKY = 2, - SORT_OPAQUE = 3, - SORT_DECAL = 4, - SORT_ALPHATEST = 5, - SORT_BANNER = 6, - SORT_UNDERWATER = 7, - SORT_WATER = 8, - SORT_ADDITIVE = 9, - SORT_NEAREST = 16 -} sort_t; - -// transform functions -typedef enum -{ - WAVEFORM_NONE = 0, - WAVEFORM_SIN, - WAVEFORM_TRIANGLE, - WAVEFORM_SQUARE, - WAVEFORM_SAWTOOTH, - WAVEFORM_INVERSESAWTOOTH, - WAVEFORM_NOISE, - WAVEFORM_CONSTANT, - WAVEFORM_TABLE // custom table -} waveForm_t; - -// RGB colors generation -typedef enum -{ - RGBGEN_UNKNOWN = 0, - RGBGEN_IDENTITY, - RGBGEN_IDENTITY_LIGHTING, - RGBGEN_CONST, - RGBGEN_WAVE, - RGBGEN_COLORWAVE, - RGBGEN_ENTITY, - RGBGEN_ONE_MINUS_ENTITY, - RGBGEN_VERTEX, - RGBGEN_ONE_MINUS_VERTEX, - RGBGEN_LIGHTING_DIFFUSE, - RGBGEN_LIGHTING_AMBIENT, - RGBGEN_EXACT_VERTEX, - RGBGEN_CUSTOM, - RGBGEN_FOG, // followed extensions only for internal use - RGBGEN_ENVIRONMENT -} rgbGenType_t; - -// alpha channel generation -typedef enum -{ - ALPHAGEN_UNKNOWN = 0, - ALPHAGEN_IDENTITY, - ALPHAGEN_CONST, - ALPHAGEN_PORTAL, - ALPHAGEN_VERTEX, - ALPHAGEN_ONE_MINUS_VERTEX, - ALPHAGEN_ENTITY, - ALPHAGEN_ONE_MINUS_ENTITY, - ALPHAGEN_SPECULAR, - ALPHAGEN_WAVE, - ALPHAGEN_ALPHAWAVE, - ALPHAGEN_FADE, // same as portal but for other things - ALPHAGEN_ONE_MINUS_FADE, - ALPHAGEN_DOT, - ALPHAGEN_ONE_MINUS_DOT, -} alphaGenType_t; - -// texture coordinates generation -typedef enum -{ - TCGEN_NONE = 0, - TCGEN_BASE, - TCGEN_LIGHTMAP, - TCGEN_ENVIRONMENT, - TCGEN_VECTOR, - TCGEN_WARP, - TCGEN_REFLECTION, - TCGEN_FOG, - TCGEN_REFLECTION_CELLSHADE, - TCGEN_SVECTORS, - TCGEN_PROJECTION, - TCGEN_PROJECTION_SHADOW, - TCGEN_NORMAL -} tcGenType_t; - -// tcmod functions -typedef enum -{ - TCMOD_NONE = 0, - TCMOD_TRANSLATE, - TCMOD_SCALE, - TCMOD_SCROLL, - TCMOD_ROTATE, - TCMOD_STRETCH, - TCMOD_TRANSFORM, - TCMOD_TURB, - TCMOD_CONVEYOR // same as TCMOD_SCROLL, but can be controlled by entity -} tcModType_t; - -// vertices deformation -typedef enum -{ - DEFORM_NONE = 0, - DEFORM_WAVE, - DEFORM_NORMAL, - DEFORM_BULGE, - DEFORM_MOVE, - DEFORM_AUTOSPRITE, - DEFORM_AUTOSPRITE2, - DEFORM_PROJECTION_SHADOW, - DEFORM_AUTOPARTICLE, -} deformType_t; - -typedef enum -{ - TABLE_SNAP = BIT(0), - TABLE_CLAMP = BIT(1) -} tableFlags_t; - -typedef struct table_s -{ - char *name; // table name - int index; - tableFlags_t flags; - - int size; - float *values; // float[] - struct table_s *nextHash; -} table_t; - -typedef struct -{ - waveForm_t type; // SHADER_FUNC enum - uint tableIndex; // valid only for WAVEFORM_TABLE - float args[4]; // offset, amplitude, phase_offset, rate -} waveFunc_t; - -typedef struct -{ - tcModType_t type; - float args[6]; -} tcMod_t; - -typedef struct -{ - rgbGenType_t type; - float *args; - waveFunc_t *func; -} rgbGen_t; - -typedef struct -{ - alphaGenType_t type; - float *args; - waveFunc_t *func; -} alphaGen_t; - -typedef struct -{ - deformType_t type; - float args[4]; - waveFunc_t func; -} deform_t; - -typedef struct old_stage_s -{ - uint flags; - uint glState; // GLSTATE_ flags - - rgbGen_t rgbGen; - alphaGen_t alphaGen; -} old_stage_t; - -// Per-pass rendering state information -typedef struct ref_stage_s -{ - uint flags; - uint glState; // GLSTATE_ flags - - rgbGen_t rgbGen; - alphaGen_t alphaGen; - - old_stage_t prev; - - word tcgen; - vec_t *tcgenVec; - - word numtcMods; - tcMod_t *tcMods; - - const char *program; - word program_type; - - float animFrequency[2]; // anim fps / alt anim fps - word anim_offset; // offset for alternative animation - word num_textures; - texture_t *textures[MAX_STAGE_TEXTURES]; // texture refs -} ref_stage_t; - -// Shader information -typedef struct ref_shader_s -{ - char *name; - word type; - - shader_t shadernum; // 0 = free - uint flags; - word features; - sort_t sort; - sort_t realsort; // member original sort type until rendermode is reset - uint sortkey; - uint touchFrame; // 0 = free - - word num_stages; - ref_stage_t *stages; - - word numDeforms; - deform_t *deforms; - - skydome_t *skyParms; - vec3_t skyAxis; - float skySpeed; - - rgba_t fog_color; - float fog_dist; - float fog_clearDist; - - float offsetmapping_scale; - float tessSize; // used for tcGen warp - - struct ref_script_s *cache; - struct ref_shader_s *nextHash; -} ref_shader_t; - -extern ref_shader_t r_shaders[MAX_SHADERS]; -#define Shader_Sortkey( shader, sort ) ((( sort )<<26 )|( shader - r_shaders )) - -void R_InitShaders( void ); -void R_ShutdownShaders( void ); -void R_ShaderList_f( void ); -void R_ShaderDump_f( void ); -ref_shader_t *R_FindShader( const char *name, int type, int ignoreType ); -ref_shader_t *R_LoadShader( const char *name, int type, qboolean forceDefault, int addFlags, int ignoreType ); -void Mod_FreeShader( const char *name ); // used for delete save menu previews only - -// misc utilities -void R_ShaderFreeUnused( void ); -float R_LookupTable( int tableIndex, float index ); -float *R_GetTableByHandle( int tableIndex ); -qboolean R_ShaderCheckCache( const char *name ); -void R_SetInternalTexture( struct mip_s *mt ); -void Shader_TouchImages( ref_shader_t *shader, qboolean free_unused ); -void R_ShaderAddStageTexture( texture_t *mipTex ); -void R_ShaderSetMiptexFlags( uint addFlags ); -void R_ShaderSetRenderMode( int mode, qboolean twoSided ); -void R_SetAnimFrequency( float anim_fps ); -void R_ShaderAddStageIntervals( float interval ); -void R_DeformvBBoxForShader( const ref_shader_t *shader, vec3_t ebbox ); - -#endif // R_SHADER_H \ No newline at end of file diff --git a/vid_gl/r_shadow.c b/vid_gl/r_shadow.c deleted file mode 100644 index c3f2aea3..00000000 --- a/vid_gl/r_shadow.c +++ /dev/null @@ -1,476 +0,0 @@ -/* -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "r_local.h" -#include "mathlib.h" -#include "matrix_lib.h" -#include "cl_entity.h" - -/* -============================================================= - -PLANAR STENCIL SHADOWS - -============================================================= -*/ - -static ref_shader_t *r_planarShadowShader; - -/* -=============== -R_InitPlanarShadows -=============== -*/ -static void R_InitPlanarShadows( void ) -{ - r_planarShadowShader = R_LoadShader( "***r_planarShadow***", SHADER_PLANAR_SHADOW, true, 0, 0 ); -} - -/* -=============== -R_PlanarShadowShader -=============== -*/ -ref_shader_t *R_PlanarShadowShader( void ) -{ - return r_planarShadowShader; -} - -/* -=============== -R_GetShadowImpactAndDir -=============== -*/ -static void R_GetShadowImpactAndDir( ref_entity_t *e, pmtrace_t *tr, vec3_t lightdir ) -{ - vec3_t point; - - R_LightDir( e->lightingOrigin, lightdir, e->model->radius * e->scale ); - - VectorSet( lightdir, -lightdir[0], -lightdir[1], -1 ); - VectorNormalizeFast( lightdir ); - VectorMA( e->origin, 1024.0f, lightdir, point ); - - R_TraceLine( tr, e->origin, point, 0 ); -} - -/* -=============== -R_CullPlanarShadow -=============== -*/ -qboolean R_CullPlanarShadow( ref_entity_t *e, vec3_t mins, vec3_t maxs, qboolean occlusion_query ) -{ - float planedist, dist; - vec3_t lightdir, point; - vec3_t bbox[8], newmins, newmaxs; - pmtrace_t tr; - int i; - - if(( e->flags & EF_NOSHADOW ) || ( e->ent_type == ET_VIEWENTITY )) - return true; - if( RP_LOCALCLIENT( e )) - return false; - - R_GetShadowImpactAndDir( e, &tr, lightdir ); - if( tr.fraction == 1.0f ) - return true; - - R_TransformEntityBBox( e, mins, maxs, bbox, true ); - - VectorSubtract( tr.endpos, e->origin, point ); - planedist = DotProduct( point, tr.plane.normal ) + 1; - dist = -1.0f / DotProduct( lightdir, tr.plane.normal ); - VectorScale( lightdir, dist, lightdir ); - - ClearBounds( newmins, newmaxs ); - for( i = 0; i < 8; i++ ) - { - VectorSubtract( bbox[i], e->origin, bbox[i] ); - dist = DotProduct( bbox[i], tr.plane.normal ) - planedist; - if( dist > 0 ) VectorMA( bbox[i], dist, lightdir, bbox[i] ); - AddPointToBounds( bbox[i], newmins, newmaxs ); - } - - VectorAdd( newmins, e->origin, newmins ); - VectorAdd( newmaxs, e->origin, newmaxs ); - - if( R_CullBox( newmins, newmaxs, RI.clipFlags )) - return true; - - // mins/maxs are pretransfomed so use r_worldent here - if( occlusion_query && OCCLUSION_QUERIES_ENABLED( RI ) ) - R_IssueOcclusionQuery( R_GetOcclusionQueryNum( OQ_PLANARSHADOW, e - r_entities ), r_worldent, newmins, newmaxs ); - - return false; -} - -/* -=============== -R_DeformVPlanarShadow -=============== -*/ -void R_DeformVPlanarShadow( int numV, float *v ) -{ - float planedist, dist; - ref_entity_t *e = RI.currententity; - vec3_t planenormal, lightdir, lightdir2, point; - pmtrace_t tr; - - R_GetShadowImpactAndDir( e, &tr, lightdir ); - - Matrix3x3_Transform( e->axis, lightdir, lightdir2 ); - Matrix3x3_Transform( e->axis, tr.plane.normal, planenormal ); - VectorScale( planenormal, e->scale, planenormal ); - - VectorSubtract( tr.endpos, e->origin, point ); - planedist = DotProduct( point, tr.plane.normal ) + 1; - dist = -1.0f / DotProduct( lightdir2, planenormal ); - VectorScale( lightdir2, dist, lightdir2 ); - - for( ; numV > 0; numV--, v += 4 ) - { - dist = DotProduct( v, planenormal ) - planedist; - if( dist > 0 ) VectorMA( v, dist, lightdir2, v ); - } -} - -/* -=============== -R_PlanarShadowPass -=============== -*/ -void R_PlanarShadowPass( int state ) -{ - GL_EnableTexGen( GL_S, 0 ); - GL_EnableTexGen( GL_T, 0 ); - GL_EnableTexGen( GL_R, 0 ); - GL_EnableTexGen( GL_Q, 0 ); - GL_SetTexCoordArrayMode( 0 ); - - GL_SetState( state ); - pglColor4f( 0, 0, 0, bound( 0.0f, r_shadows_alpha->value, 1.0f ) ); - - pglDisable( GL_TEXTURE_2D ); - if( glState.stencilEnabled ) - pglEnable( GL_STENCIL_TEST ); - - R_FlushArrays(); - - if( glState.stencilEnabled ) - pglDisable( GL_STENCIL_TEST ); - pglEnable( GL_TEXTURE_2D ); -} - -/* -============================================================= - -STANDARD PROJECTIVE SHADOW MAPS (SSM) - -============================================================= -*/ - -int r_numShadowGroups; -shadowGroup_t r_shadowGroups[MAX_SHADOWGROUPS]; -int r_entShadowBits[MAX_ENTITIES]; - -#define SHADOWGROUPS_HASH_SIZE 8 -static shadowGroup_t *r_shadowGroups_hash[SHADOWGROUPS_HASH_SIZE]; -static byte r_shadowCullBits[MAX_SHADOWGROUPS/8]; - -/* -=============== -R_InitShadowmaps -=============== -*/ -static void R_InitShadowmaps( void ) -{ - // clear all possible values, should be called once per scene - r_numShadowGroups = 0; - - Mem_Set( r_shadowGroups, 0, sizeof( r_shadowGroups )); - Mem_Set( r_entShadowBits, 0, sizeof( r_entShadowBits )); - Mem_Set( r_shadowGroups_hash, 0, sizeof( r_shadowGroups_hash )); -} - -/* -=============== -R_ClearShadowmaps -=============== -*/ -void R_ClearShadowmaps( void ) -{ - r_numShadowGroups = 0; - - if( r_shadows->integer != SHADOW_MAPPING || !RI.drawWorld ) - return; - - // clear all possible values, should be called once per scene - Mem_Set( r_shadowGroups, 0, sizeof( r_shadowGroups )); - Mem_Set( r_entShadowBits, 0, sizeof( r_entShadowBits )); - Mem_Set( r_shadowGroups_hash, 0, sizeof( r_shadowGroups_hash )); -} - -/* -=============== -R_AddShadowCaster -=============== -*/ -qboolean R_AddShadowCaster( ref_entity_t *ent ) -{ - int i; - float radius; - vec3_t origin; - unsigned int hash_key; - shadowGroup_t *group; - mleaf_t *leaf; - vec3_t mins, maxs, bbox[8]; - - if( r_shadows->integer != SHADOW_MAPPING || !RI.drawWorld ) - return false; - if( !GL_Support( R_SHADER_GLSL100_EXT ) || !GL_Support( R_DEPTH_TEXTURE ) || !GL_Support( R_SHADOW_EXT )) - return false; - - VectorCopy( ent->lightingOrigin, origin ); - if( VectorIsNull( origin )) - return false; - - // find lighting group containing entities with same lightingOrigin as ours - hash_key = (uint)( origin[0] * 7 + origin[1] * 5 + origin[2] * 3 ); - hash_key &= (SHADOWGROUPS_HASH_SIZE - 1); - - for( group = r_shadowGroups_hash[hash_key]; group; group = group->hashNext ) - { - if( VectorCompare( group->origin, origin )) - goto add; // found an existing one, add - } - - if( r_numShadowGroups == MAX_SHADOWGROUPS ) - return false; // no free groups - - leaf = Mod_PointInLeaf( origin, r_worldmodel ); - - // start a new group - group = &r_shadowGroups[r_numShadowGroups]; - group->bit = ( 1<vis = Mod_LeafPVS( leaf, r_worldmodel ); - - // clear group bounds - VectorCopy( origin, group->origin ); - ClearBounds( group->mins, group->maxs ); - - // add to hash table - group->hashNext = r_shadowGroups_hash[hash_key]; - r_shadowGroups_hash[hash_key] = group; - - r_numShadowGroups++; -add: - // get model bounds - switch( ent->model->type ) - { - case mod_studio: - R_StudioModelBBox( ent, mins, maxs ); - break; - default: - VectorClear( mins ); - VectorClear( maxs ); - break; - } - - for( i = 0; i < 3; i++ ) - { - if( mins[i] >= maxs[i] ) - return false; - } - - r_entShadowBits[ent - r_entities] |= group->bit; - if( ent->ent_type == ET_VIEWENTITY ) - return true; - - // rotate local bounding box and compute the full bounding box for this group - R_TransformEntityBBox( ent, mins, maxs, bbox, true ); - for( i = 0; i < 8; i++ ) - AddPointToBounds( bbox[i], group->mins, group->maxs ); - - // increase projection distance if needed - VectorSubtract( group->mins, origin, mins ); - VectorSubtract( group->maxs, origin, maxs ); - radius = RadiusFromBounds( mins, maxs ); - group->projDist = max( group->projDist, radius * ent->scale * 2 + min( r_shadows_projection_distance->value, 64 )); - - return true; -} - -/* -=============== -R_CullShadowmapGroups -=============== -*/ -void R_CullShadowmapGroups( void ) -{ - int i, j; - vec3_t mins, maxs; - shadowGroup_t *group; - - if( !RI.drawWorld ) return; - - Mem_Set( r_shadowCullBits, 0, sizeof( r_shadowCullBits )); - - for( i = 0, group = r_shadowGroups; i < r_numShadowGroups; i++, group++ ) - { - for( j = 0; j < 3; j++ ) - { - mins[j] = group->origin[j] - group->projDist * 1.75 * 0.5 * 0.5; - maxs[j] = group->origin[j] + group->projDist * 1.75 * 0.5 * 0.5; - } - - // check if view point is inside the bounding box... - for( j = 0; j < 3; j++ ) - { - if( RI.viewOrigin[j] < mins[j] || RI.viewOrigin[j] > maxs[j] ) - break; - } - - if( j == 3 ) continue; // ...it is, so trivially accept - - if( R_CullBox( mins, maxs, RI.clipFlags ) ) - r_shadowCullBits[i>>3] |= (1<<(i&7)); // trivially reject - else if( OCCLUSION_QUERIES_ENABLED( RI )) - R_IssueOcclusionQuery( R_GetOcclusionQueryNum( OQ_SHADOWGROUP, i ), r_worldent, mins, maxs ); - } -} - -/* -=============== -R_DrawShadowmaps -=============== -*/ -void R_DrawShadowmaps( void ) -{ - int i, j; - int width, height, textureWidth, textureHeight; - vec3_t angles; - vec3_t lightdir, M[3]; - refinst_t oldRI; - shadowGroup_t *group; - - if( !r_numShadowGroups ) - return; - - width = r_lastRefdef.viewport[2]; - height = r_lastRefdef.viewport[3]; - - RI.previousentity = NULL; - Mem_Copy( &oldRI, &prevRI, sizeof( refinst_t )); - Mem_Copy( &prevRI, &RI, sizeof( refinst_t )); - RI.rdflags &= ~RDF_SKYPORTALINVIEW; - - // find lighting group containing entities with same lightingOrigin as ours - for( i = 0, group = r_shadowGroups; i < r_numShadowGroups; i++, group++ ) - { - if( r_shadowCullBits[i>>3] & ( 1<<( i&7 ) ) ) - continue; - - if( OCCLUSION_QUERIES_ENABLED( prevRI ) ) - { - if( !R_GetOcclusionQueryResultBool( OQ_SHADOWGROUP, i, true ) ) - continue; - } - - RI.farClip = group->projDist; - RI.clipFlags |= ( 1<<4 ); // clip by far plane too - RI.shadowBits = 0; // no shadowing yet - RI.meshlist = &r_shadowlist; - RI.shadowGroup = group; - RI.params = RP_SHADOWMAPVIEW|RP_FLIPFRONTFACE|RP_OLDVIEWLEAF; // make sure RP_WORLDSURFVISIBLE isn't set - - // allocate/resize the texture if needed - R_InitShadowmapTexture( &( tr.shadowmapTextures[i] ), i, width, height ); - - group->depthTexture = tr.shadowmapTextures[i]; - textureWidth = group->depthTexture->width; - textureHeight = group->depthTexture->height; - - // default to fov 90, R_SetupFrame will most likely alter the values to give depth more precision - RI.refdef.viewport[2] = textureWidth; - RI.refdef.viewport[3] = textureHeight; - RI.refdef.fov_x = 90; - RI.refdef.fov_y = CalcFov( RI.refdef.fov_x, RI.refdef.viewport[2], RI.refdef.viewport[3] ); - Vector4Set( RI.viewport, RI.refdef.viewport[0], RI.refdef.viewport[1], textureWidth, textureHeight ); - Vector4Set( RI.scissor, RI.refdef.viewport[0], RI.refdef.viewport[1], textureWidth, textureHeight ); - - // set the view transformation matrix according to lightgrid - R_LightDir( group->origin, lightdir, group->projDist * 0.5f ); - VectorSet( lightdir, -lightdir[0], -lightdir[1], -lightdir[2] ); - VectorNormalizeFast( lightdir ); - - NormalVectorToAxis( lightdir, M ); - Matrix3x3_ToAngles( M, angles, true ); - - for( j = 0; j < 3; j++ ) - RI.refdef.viewangles[j] = anglemod( angles[j] ); - - // position the light source in the opposite direction - VectorMA( group->origin, -group->projDist * 0.5, lightdir, RI.refdef.vieworg ); - - R_RenderView( &RI.refdef ); - - if( !( RI.params & RP_WORLDSURFVISIBLE ) ) - continue; // we didn't cast any shadows on opaque meshes so discard this group - - if( !( prevRI.shadowBits & group->bit )) - { - // capture results from framebuffer into depth texture - prevRI.shadowBits |= group->bit; - GL_Bind( 0, group->depthTexture ); - pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, RI.refdef.viewport[0], RI.refdef.viewport[1], textureWidth, textureHeight ); - } - - Matrix4x4_Copy( group->worldviewProjectionMatrix, RI.worldviewProjectionMatrix ); - } - - oldRI.shadowBits |= prevRI.shadowBits; // set shadowBits for all RI's so that we won't - Mem_Copy( &RI, &prevRI, sizeof( refinst_t )); - Mem_Copy( &prevRI, &oldRI, sizeof( refinst_t )); -} - -//================================================================================== - -/* -=============== -R_InitShadows -=============== -*/ -void R_InitShadows( void ) -{ - R_InitPlanarShadows(); - - R_InitShadowmaps(); -} - -/* -=============== -R_ShutdownShadows -=============== -*/ -void R_ShutdownShadows( void ) -{ - r_planarShadowShader = NULL; -} diff --git a/vid_gl/r_shadow.h b/vid_gl/r_shadow.h deleted file mode 100644 index 6ddd97ef..00000000 --- a/vid_gl/r_shadow.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -#ifndef __R_SHADOW_H__ -#define __R_SHADOW_H__ - -typedef struct shadowGroup_s -{ - uint bit; - texture_t *depthTexture; - - vec3_t origin; - byte *vis; - - float projDist; - vec3_t mins, maxs; - - matrix4x4 worldviewProjectionMatrix; - struct shadowGroup_s *hashNext; -} shadowGroup_t; - -extern int r_numShadowGroups; -extern shadowGroup_t r_shadowGroups[MAX_SHADOWGROUPS]; -extern int r_entShadowBits[MAX_ENTITIES]; - -void R_InitShadows( void ); -void R_ShutdownShadows( void ); - -qboolean R_CullPlanarShadow( struct ref_entity_s *e, vec3_t mins, vec3_t maxs, qboolean occclusionQuery ); -void R_DeformVPlanarShadow( int numV, float *v ); -void R_PlanarShadowPass( int state ); -ref_shader_t *R_PlanarShadowShader( void ); - -void R_ClearShadowmaps( void ); -void R_GroupShadowCasters( void ); -qboolean R_AddShadowCaster( struct ref_entity_s *ent ); -void R_CullShadowmapGroups( void ); -void R_DrawShadowmaps( void ); - -#endif /*__R_SHADOW_H__*/ diff --git a/vid_gl/r_sky.c b/vid_gl/r_sky.c deleted file mode 100644 index 24b46587..00000000 --- a/vid_gl/r_sky.c +++ /dev/null @@ -1,652 +0,0 @@ -/* -Copyright (C) 1999 Stephen C. Taylor -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// r_sky.c - -#include "r_local.h" -#include "mathlib.h" -#include "matrix_lib.h" - -#define MAX_CLIP_VERTS 64 -#define SIDE_SIZE 9 -#define POINTS_LEN ( SIDE_SIZE * SIDE_SIZE ) -#define ELEM_LEN (( SIDE_SIZE-1 ) * ( SIDE_SIZE-1 ) * 6 ) - -#define SPHERE_RAD 10.0f -#define EYE_RAD 9.0f - -#define SCALE_S 4.0f // arbitrary (?) texture scaling factors -#define SCALE_T 4.0f -#define BOX_SIZE 1.0f -#define BOX_STEP BOX_SIZE / ( SIDE_SIZE-1 ) * 2.0f - -elem_t r_skydome_elems[6][ELEM_LEN]; -meshbuffer_t r_skydome_mbuffer; - -static mfog_t *r_skyfog; -static msurface_t *r_warpface; -static qboolean r_warpfacevis; - -static void Gen_BoxSide( skydome_t *skydome, int side, vec3_t orig, vec3_t drow, vec3_t dcol, float skyheight ); -static void MakeSkyVec( float x, float y, float z, int axis, vec3_t v ); -static void Gen_Box( skydome_t *skydome, float skyheight ); - -/* -============== -R_CreateSkydome -============== -*/ -skydome_t *R_CreateSkydome( byte *mempool, float skyheight, ref_shader_t **farboxShaders, ref_shader_t **nearboxShaders ) -{ - int i, size; - mesh_t *mesh; - skydome_t *skydome; - byte *buffer; - - size = sizeof( skydome_t ) + sizeof( mesh_t ) * 6 + sizeof( vec4_t ) * POINTS_LEN * 6 + - sizeof( vec4_t ) * POINTS_LEN * 6 + sizeof( vec2_t ) * POINTS_LEN * 12; - buffer = Mem_Alloc( mempool, size ); - - skydome = ( skydome_t * )buffer; - Mem_Copy( skydome->farboxShaders, farboxShaders, sizeof( ref_shader_t* ) * 6 ); - Mem_Copy( skydome->nearboxShaders, nearboxShaders, sizeof( ref_shader_t* ) * 6 ); - buffer += sizeof( skydome_t ); - - skydome->skyHeight = skyheight; - skydome->meshes = ( mesh_t* )buffer; - buffer += sizeof( mesh_t ) * 6; - - for( i = 0, mesh = skydome->meshes; i < 6; i++, mesh++ ) - { - mesh->numVerts = POINTS_LEN; - mesh->vertexArray = ( vec4_t * )buffer; buffer += sizeof( vec4_t ) * POINTS_LEN; - mesh->normalsArray = ( vec4_t * )buffer; buffer += sizeof( vec4_t ) * POINTS_LEN; - skydome->sphereStCoords[i] = ( vec2_t * )buffer; buffer += sizeof( vec2_t ) * POINTS_LEN; - skydome->linearStCoords[i] = ( vec2_t * )buffer; buffer += sizeof( vec2_t ) * POINTS_LEN; - - mesh->numElems = ELEM_LEN; - mesh->elems = r_skydome_elems[i]; - } - - Gen_Box( skydome, skyheight ); - - return skydome; -} - -/* -============== -R_FreeSkydome -============== -*/ -void R_FreeSkydome( skydome_t *skydome ) -{ - if( skydome ) Mem_Free( skydome ); -} - -/* -============== -Gen_Box -============== -*/ -static void Gen_Box( skydome_t *skydome, float skyheight ) -{ - int axis; - vec3_t orig, drow, dcol; - - for( axis = 0; axis < 6; axis++ ) - { - MakeSkyVec( -BOX_SIZE, -BOX_SIZE, BOX_SIZE, axis, orig ); - MakeSkyVec( 0, BOX_STEP, 0, axis, drow ); - MakeSkyVec( BOX_STEP, 0, 0, axis, dcol ); - Gen_BoxSide( skydome, axis, orig, drow, dcol, skyheight ); - } -} - -/* -================ -Gen_BoxSide - -I don't know exactly what Q3A does for skybox texturing, but -this is at least fairly close. We tile the texture onto the -inside of a large sphere, and put the camera near the top of -the sphere. We place the box around the camera, and cast rays -through the box verts to the sphere to find the texture coordinates. -================ -*/ -static void Gen_BoxSide( skydome_t *skydome, int side, vec3_t orig, vec3_t drow, vec3_t dcol, float skyheight ) -{ - vec3_t pos, w, row, norm; - float *v, *n, *st, *st2; - float t, d, d2, b, b2, q[2], s; - int r, c; - - s = 1.0 / ( SIDE_SIZE-1 ); - d = EYE_RAD; // sphere center to camera distance - d2 = d * d; - b = SPHERE_RAD; // sphere radius - b2 = b * b; - q[0] = 1.0 / ( 2.0 * SCALE_S ); - q[1] = 1.0 / ( 2.0 * SCALE_T ); - - v = skydome->meshes[side].vertexArray[0]; - n = skydome->meshes[side].normalsArray[0]; - st = skydome->sphereStCoords[side][0]; - st2 = skydome->linearStCoords[side][0]; - - VectorCopy( orig, row ); - VectorClear( norm ); - - for( r = 0; r < SIDE_SIZE; r++ ) - { - VectorCopy( row, pos ); - for( c = 0; c < SIDE_SIZE; c++ ) - { - // pos points from eye to vertex on box - VectorScale( pos, skyheight, v ); - VectorCopy( pos, w ); - - // Normalize pos -> w - VectorNormalize( w ); - - // Find distance along w to sphere - t = sqrt( d2 * ( w[2] * w[2] - 1.0 ) + b2 ) - d * w[2]; - w[0] *= t; - w[1] *= t; - - // use x and y on sphere as s and t - // minus is here so skies scoll in correct (Q3A's) direction - st[0] = -w[0] * q[0]; - st[1] = -w[1] * q[1]; - - // avoid bilerp seam - st[0] = ( bound( -1, st[0], 1 ) + 1.0 ) * 0.5; - st[1] = ( bound( -1, st[1], 1 ) + 1.0 ) * 0.5; - - st2[0] = c * s; - st2[1] = 1.0 - r * s; - - VectorAdd( pos, dcol, pos ); - VectorCopy( norm, n ); - - v += 4; - n += 4; - st += 2; - st2 += 2; - } - VectorAdd( row, drow, row ); - } -} - -/* -============== -R_DrawSkySide -============== -*/ -static void R_DrawSkySide( skydome_t *skydome, int side, ref_shader_t *shader, int features ) -{ - meshbuffer_t *mbuffer = &r_skydome_mbuffer; - - if( RI.skyMins[0][side] >= RI.skyMaxs[0][side] || RI.skyMins[1][side] >= RI.skyMaxs[1][side] ) - return; - - mbuffer->shaderkey = shader->sortkey; - mbuffer->dlightbits = 0; - mbuffer->sortkey = MB_FOG2NUM( r_skyfog ); - - skydome->meshes[side].stCoordArray = skydome->linearStCoords[side]; - R_PushMesh( &skydome->meshes[side], features ); - R_RenderMeshBuffer( mbuffer ); -} - -/* -============== -R_DrawSkyBox -============== -*/ -static void R_DrawSkyBox( skydome_t *skydome, ref_shader_t **shaders ) -{ - int i, features; - const int skytexorder[6] = { SKYBOX_RIGHT, SKYBOX_FRONT, SKYBOX_LEFT, SKYBOX_BACK, SKYBOX_TOP, SKYBOX_BOTTOM }; - - features = shaders[0]->features; - if( r_shownormals->integer ) - features |= MF_NORMALS; - - for( i = 0; i < 6; i++ ) - R_DrawSkySide( skydome, i, shaders[skytexorder[i]], features ); -} - -/* -============== -R_DrawBlackBottom - -Draw dummy skybox side to prevent the HOM effect -============== -*/ -static void R_DrawBlackBottom( skydome_t *skydome ) -{ - int features; - - features = tr.defaultShader->features; - if( r_shownormals->integer ) - features |= MF_NORMALS; - R_DrawSkySide( skydome, 5, tr.defaultShader, features ); -} - -/* -============== -R_DrawSky -============== -*/ -void R_DrawSky( ref_shader_t *shader ) -{ - int i; - vec3_t mins, maxs; - matrix4x4 m, oldm; - elem_t *elem; - skydome_t *skydome; - meshbuffer_t *mbuffer = &r_skydome_mbuffer; - int u, v, umin, umax, vmin, vmax; - - if( !shader ) return; - skydome = shader->skyParms ? shader->skyParms : NULL; - if( !skydome ) return; - - ClearBounds( mins, maxs ); - for( i = 0; i < 6; i++ ) - { - if( RI.skyMins[0][i] >= RI.skyMaxs[0][i] || RI.skyMins[1][i] >= RI.skyMaxs[1][i] ) - continue; - - umin = (int)(( RI.skyMins[0][i] + 1.0f ) * 0.5f * (float)( SIDE_SIZE-1 )); - umax = (int)(( RI.skyMaxs[0][i] + 1.0f ) * 0.5f * (float)( SIDE_SIZE-1 )) + 1; - vmin = (int)(( RI.skyMins[1][i] + 1.0f ) * 0.5f * (float)( SIDE_SIZE-1 )); - vmax = (int)(( RI.skyMaxs[1][i] + 1.0f ) * 0.5f * (float)( SIDE_SIZE-1 )) + 1; - - umin = bound( 0, umin, SIDE_SIZE-1 ); - umax = bound( 0, umax, SIDE_SIZE-1 ); - vmin = bound( 0, vmin, SIDE_SIZE-1 ); - vmax = bound( 0, vmax, SIDE_SIZE-1 ); - - // box elems in tristrip order - elem = skydome->meshes[i].elems; - for( v = vmin; v < vmax; v++ ) - { - for( u = umin; u < umax; u++ ) - { - elem[0] = v * SIDE_SIZE + u; - elem[1] = elem[4] = elem[0] + SIDE_SIZE; - elem[2] = elem[3] = elem[0] + 1; - elem[5] = elem[1] + 1; - elem += 6; - } - } - - AddPointToBounds( skydome->meshes[i].vertexArray[vmin*SIDE_SIZE+umin], mins, maxs ); - AddPointToBounds( skydome->meshes[i].vertexArray[vmax*SIDE_SIZE+umax], mins, maxs ); - - skydome->meshes[i].numElems = ( vmax-vmin )*( umax-umin ) * 6; - } - - VectorAdd( mins, RI.viewOrigin, mins ); - VectorAdd( maxs, RI.viewOrigin, maxs ); - - if( RI.rdflags & RDF_SKYPORTALINVIEW ) - { - R_DrawSkyPortal( &RI.skyportal, mins, maxs ); - return; - } - - // center skydome on camera to give the illusion of a larger space - Matrix4x4_Copy( oldm, RI.modelviewMatrix ); - Matrix4x4_Copy( RI.modelviewMatrix, RI.worldviewMatrix ); - Matrix4x4_Copy( m, RI.worldviewMatrix ); - - if( shader->skySpeed ) - { - float angle = shader->skySpeed * RI.refdef.time; - Matrix4x4_ConcatRotate( m, angle, shader->skyAxis[0], shader->skyAxis[1], shader->skyAxis[2] ); - } - Matrix4x4_SetOrigin( m, 0, 0, 0 ); - m[3][3] = 1.0f; - GL_LoadMatrix( m ); - - gldepthmin = 1; - gldepthmax = 1; - pglDepthRange( gldepthmin, gldepthmax ); - - if( RI.params & RP_CLIPPLANE ) - pglDisable( GL_CLIP_PLANE0 ); - - // it can happen that sky surfaces have no fog hull specified - // yet there's a global fog hull (see wvwq3dm7) - if( !r_skyfog ) r_skyfog = r_worldbrushmodel->globalfog; - - if( skydome->farboxShaders[0] ) - R_DrawSkyBox( skydome, skydome->farboxShaders ); - else R_DrawBlackBottom( skydome ); - - if( shader->num_stages ) - { - qboolean flush = false; - int features = shader->features; - - if( r_shownormals->integer ) - features |= MF_NORMALS; - - for( i = 0; i < 6; i++ ) - { - if( RI.skyMins[0][i] >= RI.skyMaxs[0][i] || RI.skyMins[1][i] >= RI.skyMaxs[1][i] ) - continue; - - flush = true; - mbuffer->shaderkey = shader->sortkey; - mbuffer->dlightbits = 0; - mbuffer->sortkey = MB_FOG2NUM( r_skyfog ); - - skydome->meshes[i].stCoordArray = skydome->sphereStCoords[i]; - R_PushMesh( &skydome->meshes[i], features ); - } - if( flush ) R_RenderMeshBuffer( mbuffer ); - } - - if( skydome->nearboxShaders[0] ) - R_DrawSkyBox( skydome, skydome->nearboxShaders ); - - if( RI.params & RP_CLIPPLANE ) - pglEnable( GL_CLIP_PLANE0 ); - - Matrix4x4_Copy( RI.modelviewMatrix, oldm ); - GL_LoadMatrix( RI.worldviewMatrix ); - - gldepthmin = 0; - gldepthmax = 1; - pglDepthRange( gldepthmin, gldepthmax ); - - r_skyfog = NULL; -} - -//=================================================================== - -vec3_t skyclip[6] = -{ -{ 1, 1, 0 }, -{ 1, -1, 0 }, -{ 0, -1, 1 }, -{ 0, 1, 1 }, -{ 1, 0, 1 }, -{ -1, 0, 1 } -}; - -// 1 = s, 2 = t, 3 = 2048 -int st_to_vec[6][3] = -{ -{ 3, -1, 2 }, -{ -3, 1, 2 }, -{ 1, 3, 2 }, -{ -1, -3, 2 }, -{ -2, -1, 3 }, // 0 degrees yaw, look straight up -{ 2, -1, -3 } // look straight down -}; - -// s = [0]/[2], t = [1]/[2] -int vec_to_st[6][3] = -{ -{ -2, 3, 1 }, -{ 2, 3, -1 }, -{ 1, 3, 2 }, -{ -1, 3, -2 }, -{ -2, -1, 3 }, -{ -2, 1, -3 } -}; - -/* -============== -DrawSkyPolygon -============== -*/ -void DrawSkyPolygon( int nump, vec3_t vecs ) -{ - int i, j; - vec3_t v, av; - float s, t, dv; - int axis; - float *vp; - - // decide which face it maps to - VectorClear( v ); - - for( i = 0, vp = vecs; i < nump; i++, vp += 3 ) - VectorAdd( vp, v, v ); - - av[0] = fabs( v[0] ); - av[1] = fabs( v[1] ); - av[2] = fabs( v[2] ); - - if(( av[0] > av[1] ) && ( av[0] > av[2] )) - axis = ( v[0] < 0 ) ? 1 : 0; - else if(( av[1] > av[2] ) && ( av[1] > av[0] )) - axis = ( v[1] < 0 ) ? 3 : 2; - else axis = ( v[2] < 0 ) ? 5 : 4; - - if( !r_skyfog ) - r_skyfog = r_warpface->fog; - r_warpfacevis = true; - - // project new texture coords - for( i = 0; i < nump; i++, vecs += 3 ) - { - j = vec_to_st[axis][2]; - dv = ( j > 0 ) ? vecs[j - 1] : -vecs[-j - 1]; - - if( dv < 0.001f ) - continue; // don't divide by zero - - dv = 1.0f / dv; - - j = vec_to_st[axis][0]; - s = ( j < 0 ) ? -vecs[-j -1] * dv : vecs[j-1] * dv; - - j = vec_to_st[axis][1]; - t = ( j < 0 ) ? -vecs[-j -1] * dv : vecs[j-1] * dv; - - if( s < RI.skyMins[0][axis] ) RI.skyMins[0][axis] = s; - if( t < RI.skyMins[1][axis] ) RI.skyMins[1][axis] = t; - if( s > RI.skyMaxs[0][axis] ) RI.skyMaxs[0][axis] = s; - if( t > RI.skyMaxs[1][axis] ) RI.skyMaxs[1][axis] = t; - } -} - -/* -============== -ClipSkyPolygon -============== -*/ -void ClipSkyPolygon( int nump, vec3_t vecs, int stage ) -{ - float *norm; - float *v; - qboolean front, back; - float d, e; - float dists[MAX_CLIP_VERTS + 1]; - int sides[MAX_CLIP_VERTS + 1]; - vec3_t newv[2][MAX_CLIP_VERTS + 1]; - int newc[2]; - int i, j; - - if( nump > MAX_CLIP_VERTS ) - Host_Error( "ClipSkyPolygon: MAX_CLIP_VERTS\n" ); - -loc1: - if( stage == 6 ) - { - // fully clipped, so draw it - DrawSkyPolygon( nump, vecs ); - return; - } - - front = back = false; - norm = skyclip[stage]; - for( i = 0, v = vecs; i < nump; i++, v += 3 ) - { - d = DotProduct( v, norm ); - if( d > ON_EPSILON ) - { - front = true; - sides[i] = SIDE_FRONT; - } - else if( d < -ON_EPSILON ) - { - back = true; - sides[i] = SIDE_BACK; - } - else - { - sides[i] = SIDE_ON; - } - dists[i] = d; - } - - if( !front || !back ) - { - // not clipped - stage++; - goto loc1; - } - - // clip it - sides[i] = sides[0]; - dists[i] = dists[0]; - VectorCopy( vecs, ( vecs + ( i * 3 ))); - newc[0] = newc[1] = 0; - - for( i = 0, v = vecs; i < nump; i++, v += 3 ) - { - switch( sides[i] ) - { - case SIDE_FRONT: - VectorCopy( v, newv[0][newc[0]] ); - newc[0]++; - break; - case SIDE_BACK: - VectorCopy( v, newv[1][newc[1]] ); - newc[1]++; - break; - case SIDE_ON: - VectorCopy( v, newv[0][newc[0]] ); - newc[0]++; - VectorCopy( v, newv[1][newc[1]] ); - newc[1]++; - break; - } - - if( sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i] ) - continue; - - d = dists[i] / ( dists[i] - dists[i+1] ); - for( j = 0; j < 3; j++ ) - { - e = v[j] + d * ( v[j+3] - v[j] ); - newv[0][newc[0]][j] = e; - newv[1][newc[1]][j] = e; - } - newc[0]++; - newc[1]++; - } - - // continue - ClipSkyPolygon( newc[0], newv[0][0], stage + 1 ); - ClipSkyPolygon( newc[1], newv[1][0], stage + 1 ); -} - -/* -================= -R_AddSkySurface -================= -*/ -qboolean R_AddSkySurface( msurface_t *fa ) -{ - int i; - vec4_t *vert; - elem_t *elem; - mesh_t *mesh; - vec3_t verts[4]; - - // calculate vertex values for sky box - r_warpface = fa; - r_warpfacevis = false; - - if( tr.currentSkyShader && tr.currentSkyShader->skySpeed ) - { - // HACK: force full sky to draw when rotating - for( i = 0; i < 6; i++ ) - { - RI.skyMins[0][i] = RI.skyMins[1][i] = -1; - RI.skyMaxs[0][i] = RI.skyMaxs[1][i] = 1; - } - } - - mesh = fa->mesh; - elem = mesh->elems; - vert = mesh->vertexArray; - - for( i = 0; i < mesh->numElems; i += 3, elem += 3 ) - { - VectorSubtract( vert[elem[0]], RI.viewOrigin, verts[0] ); - VectorSubtract( vert[elem[1]], RI.viewOrigin, verts[1] ); - VectorSubtract( vert[elem[2]], RI.viewOrigin, verts[2] ); - ClipSkyPolygon( 3, verts[0], 0 ); - } - - return r_warpfacevis; -} - -/* -============== -R_ClearSkyBox -============== -*/ -void R_ClearSkyBox( void ) -{ - int i; - - RI.params |= RP_NOSKY; - for( i = 0; i < 6; i++ ) - { - RI.skyMins[0][i] = RI.skyMins[1][i] = 9999999; - RI.skyMaxs[0][i] = RI.skyMaxs[1][i] = -9999999; - } -} - -static void MakeSkyVec( float x, float y, float z, int axis, vec3_t v ) -{ - int j, k; - vec3_t b; - - VectorSet( b, x, y, z ); - - for( j = 0; j < 3; j++ ) - { - k = st_to_vec[axis][j]; - if( k < 0 ) v[j] = -b[-k-1]; - else v[j] = b[k-1]; - } -} \ No newline at end of file diff --git a/vid_gl/r_sprite.c b/vid_gl/r_sprite.c deleted file mode 100644 index 4931407c..00000000 --- a/vid_gl/r_sprite.c +++ /dev/null @@ -1,891 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2007 -// r_sprite.c - render sprite models -//======================================================================= - -#include "r_local.h" -#include "mathlib.h" -#include "const.h" -#include "cl_entity.h" - -/* -============================================================= - - SPRITE MODELS - -============================================================= -*/ -string frame_prefix; -uint frame_type; -uint group_num; -string sp_name; -ref_shader_t **frames = NULL; -convar_t *r_sprite_lerping; -uint tex_flags = 0; -vec3_t sprite_mins, sprite_maxs; -float sprite_radius; - -/* -==================== -R_SpriteInit - -==================== -*/ -void R_SpriteInit( void ) -{ - r_sprite_lerping = Cvar_Get( "r_sprite_lerping", "1", CVAR_ARCHIVE, "enables sprite model animation lerping" ); -} - -/* -==================== -Sprite model loader -==================== -*/ -static dframetype_t *R_SpriteLoadFrame( ref_model_t *mod, void *pin, mspriteframe_t **ppframe, int framenum ) -{ - texture_t *tex; - dspriteframe_t *pinframe; - mspriteframe_t *pspriteframe; - string name, shadername; - - // build uinque frame name - if( !sp_name[0] ) FS_FileBase( mod->name, sp_name ); - com.snprintf( name, MAX_STRING, "Sprite( %s_%s_%i%i )", sp_name, frame_prefix, framenum/10, framenum%10 ); - - pinframe = (dspriteframe_t *)pin; - - // setup frame description - pspriteframe = Mem_Alloc( mod->mempool, sizeof( mspriteframe_t )); - pspriteframe->width = pinframe->width; - pspriteframe->height = pinframe->height; - pspriteframe->up = pinframe->origin[1]; - pspriteframe->left = pinframe->origin[0]; - pspriteframe->down = pinframe->origin[1] - pinframe->height; - pspriteframe->right = pinframe->width + pinframe->origin[0]; - pspriteframe->radius = com.sqrt((pinframe->width * pinframe->width) + (pinframe->height * pinframe->height)); - tex = R_FindTexture( name, (byte *)pin, pinframe->width * pinframe->height, 0 ); - tex_flags |= tex->flags; - *ppframe = pspriteframe; - - R_ShaderAddStageTexture( tex ); - - if( frame_type == FRAME_SINGLE ) - { - com.snprintf( shadername, MAX_STRING, "sprites/%s.spr/%s_%i%i )", sp_name, frame_prefix, framenum/10, framenum%10 ); - pspriteframe->shader = R_LoadShader( shadername, SHADER_SPRITE, true, tex_flags, SHADER_INVALID )->shadernum; - frames = Mem_Realloc( mod->mempool, frames, sizeof( ref_shader_t* ) * (mod->numshaders + 1)); - frames[mod->numshaders++] = &r_shaders[pspriteframe->shader]; - } - return (dframetype_t *)((byte *)(pinframe + 1) + pinframe->width * pinframe->height ); -} - -static dframetype_t *CL_LoadSpriteFrame( const char *szSpriteName, void *pin, int framenum ) -{ - texture_t *tex; - string name; - dspriteframe_t *pinframe; - - // build uinque frame name - if( !sp_name[0] ) FS_FileBase( szSpriteName, sp_name ); - com.snprintf( name, MAX_STRING, "Sprite( \"%s_%s_%i%i\" )", sp_name, frame_prefix, framenum/10, framenum%10 ); - - pinframe = (dspriteframe_t *)pin; - - // NOTE: just loading all single frame into one shader - // we supported only single frames in this case - // because we can't properly merge multiple groups into single shader - tex = R_FindTexture( name, (byte *)pin, pinframe->width * pinframe->height, tex_flags ); - R_ShaderAddStageTexture( tex ); - - return (dframetype_t *)((byte *)(pinframe + 1) + pinframe->width * pinframe->height ); -} - -static dframetype_t *CL_SpriteSkipGroup( const char *szSpriteName, void *pin, int framenum ) -{ - dspritegroup_t *pingroup; - dspriteinterval_t *pin_intervals; - dspriteframe_t *pinframe; - void *ptemp; - int i; - - // throw warning - MsgDev( D_WARN, "CL_LoadSprite: %s ignore group frame %i\n", szSpriteName, framenum ); - - pingroup = (dspritegroup_t *)pin; - pin_intervals = (dspriteinterval_t *)(pingroup + 1); - - // skip intervals - for( i = 0; i < pingroup->numframes; i++ ) - pin_intervals++; - - // skip group frames - ptemp = (void *)pin_intervals; - for( i = 0; i < pingroup->numframes; i++ ) - { - pinframe = (dspriteframe_t *)ptemp; - ptemp = (dframetype_t *)((byte *)(pinframe + 1) + pinframe->width * pinframe->height ); - } - return (dframetype_t *)ptemp; -} - -static dframetype_t *R_SpriteLoadGroup( ref_model_t *mod, void * pin, mspriteframe_t **ppframe, int framenum ) -{ - dspritegroup_t *pingroup; - mspritegroup_t *pspritegroup; - dspriteinterval_t *pin_intervals; - float *poutintervals; - shader_t group_shader; - int i, groupsize, numframes; - string shadername; - void *ptemp; - - pingroup = (dspritegroup_t *)pin; - numframes = pingroup->numframes; - - groupsize = sizeof(mspritegroup_t) + (numframes - 1) * sizeof( pspritegroup->frames[0] ); - pspritegroup = Mem_Alloc( mod->mempool, groupsize ); - pspritegroup->numframes = numframes; - - *ppframe = (mspriteframe_t *)pspritegroup; - pin_intervals = (dspriteinterval_t *)(pingroup + 1); - poutintervals = Mem_Alloc( mod->mempool, numframes * sizeof( float )); - pspritegroup->intervals = poutintervals; - - for( i = 0; i < numframes; i++ ) - { - *poutintervals = pin_intervals->interval; - if( *poutintervals <= 0.0 ) *poutintervals = 1.0f; // set error value - if( frame_type == FRAME_GROUP ) R_ShaderAddStageIntervals( *poutintervals ); - else if( frame_type == FRAME_ANGLED ) R_ShaderAddStageIntervals( -1.0f ); - poutintervals++; - pin_intervals++; - } - - ptemp = (void *)pin_intervals; - for( i = 0; i < numframes; i++ ) - { - ptemp = R_SpriteLoadFrame( mod, ptemp, &pspritegroup->frames[i], framenum * 10 + i ); - } - - com.snprintf( shadername, MAX_STRING, "sprites/%s.spr/%s_%i%i", sp_name, frame_prefix, group_num/10, group_num%10 ); - group_shader = R_LoadShader( shadername, SHADER_SPRITE, true, tex_flags, SHADER_INVALID )->shadernum; - frames = Mem_Realloc( mod->mempool, frames, sizeof( ref_shader_t* ) * (mod->numshaders + 1)); - frames[mod->numshaders++] = &r_shaders[group_shader]; - - // apply this shader for all frames in group - for( i = 0; i < numframes; i++ ) - pspritegroup->frames[i]->shader = group_shader; - group_num++; - - return (dframetype_t *)ptemp; -} - -void Mod_SpriteLoadModel( ref_model_t *mod, const void *buffer ) -{ - dsprite_t *pin; - short *numi; - msprite_t *psprite; - dframetype_t *pframetype; - int i, size, numframes; - qboolean twoSided; - - pin = (dsprite_t *)buffer; - i = pin->version; - - if( i != SPRITE_VERSION ) - { - MsgDev( D_ERROR, "%s has wrong version number (%i should be %i)\n", mod->name, i, SPRITE_VERSION ); - return; - } - - numframes = pin->numframes; - size = sizeof( msprite_t ) + ( numframes - 1 ) * sizeof( psprite->frames ); - - psprite = Mem_Alloc( mod->mempool, size ); - mod->extradata = psprite; // make link to extradata - mod->numshaders = 0; // reset frames - - psprite->type = pin->type; - psprite->rendermode = pin->texFormat; - psprite->numframes = numframes; - twoSided = ( pin->facetype == SPR_CULL_NONE ) ? true : false; - mod->mins[0] = mod->mins[1] = -pin->bounds[0] / 2; - mod->maxs[0] = mod->maxs[1] = pin->bounds[0] / 2; - mod->mins[2] = -pin->bounds[1] / 2; - mod->maxs[2] = pin->bounds[1] / 2; - numi = (short *)(pin + 1); - - if( *numi == 256 ) - { - byte *src = (byte *)(numi+1); - rgbdata_t *pal; - - // install palette - switch( psprite->rendermode ) - { - case SPR_ADDGLOW: - pal = FS_LoadImage( "#normal.pal", src, 768 ); - R_ShaderSetRenderMode( kRenderGlow, twoSided ); - break; - case SPR_ADDITIVE: - pal = FS_LoadImage( "#normal.pal", src, 768 ); - R_ShaderSetRenderMode( kRenderTransAdd, twoSided ); - break; - case SPR_INDEXALPHA: - pal = FS_LoadImage( "#decal.pal", src, 768 ); - R_ShaderSetRenderMode( kRenderTransTexture, twoSided ); - break; - case SPR_ALPHTEST: - pal = FS_LoadImage( "#transparent.pal", src, 768 ); - R_ShaderSetRenderMode( kRenderTransAlpha, twoSided ); - break; - case SPR_NORMAL: - default: - pal = FS_LoadImage( "#normal.pal", src, 768 ); - R_ShaderSetRenderMode( kRenderNormal, twoSided ); - break; - } - pframetype = (dframetype_t *)(src + 768); - FS_FreeImage( pal ); // palette installed, no reason to keep this data - } - else - { - MsgDev( D_ERROR, "%s has wrong number of palette colors %i (should be 256)\n", mod->name, numi ); - return; - } - - if( numframes < 1 ) - { - MsgDev( D_ERROR, "%s has invalid # of frames: %d\n", mod->name, numframes ); - return; - } - - mod->touchFrame = tr.registration_sequence; - frames = NULL; // invalidate pointer - sp_name[0] = 0; - group_num = 0; - - for( i = 0; i < numframes; i++ ) - { - frametype_t frametype = pframetype->type; - psprite->frames[i].type = frametype; - frame_type = frametype; - - switch( frametype ) - { - case FRAME_SINGLE: - tex_flags = 0; - com.strncpy( frame_prefix, "one", MAX_STRING ); - pframetype = R_SpriteLoadFrame( mod, pframetype + 1, &psprite->frames[i].frameptr, i ); - break; - case FRAME_GROUP: - tex_flags = 0; - com.strncpy( frame_prefix, "grp", MAX_STRING ); - pframetype = R_SpriteLoadGroup( mod, pframetype + 1, &psprite->frames[i].frameptr, i ); - break; - case FRAME_ANGLED: - tex_flags = 0; - com.strncpy( frame_prefix, "ang", MAX_STRING ); - pframetype = R_SpriteLoadGroup( mod, pframetype + 1, &psprite->frames[i].frameptr, i ); - break; - } - if( pframetype == NULL ) break; // technically an error - } - mod->shaders = frames; // setup texture links - mod->type = mod_sprite; -} - -/* -================ -CL_LoadSprite - -client version for loading sprites -and convert them to shaders with multiple frames -================ -*/ -ref_shader_t *CL_LoadSprite( const char *szSpriteName ) -{ - dsprite_t *pin; - ref_shader_t *shader; - byte *buffer; - dframetype_t *pframetype; - qboolean twoSided; - int i, numframes; - short *numi; - - if( !szSpriteName || !szSpriteName[0] ) - return r_shaders; - - shader = R_FindShader( szSpriteName, SHADER_SPRITE, SHADER_INVALID ); - if( shader ) return shader; // already loaded - - buffer = FS_LoadFile( szSpriteName, NULL ); - if( !buffer ) return r_shaders; // sprite is missed - - pin = (dsprite_t *)buffer; - - // make sure what is really sprite - if( pin->ident != IDSPRITEHEADER ) - { - MsgDev( D_ERROR, "CL_LoadSprite: %s not a sprite\n", szSpriteName ); - Mem_Free( buffer ); - return r_shaders; - } - - if( pin->version != SPRITE_VERSION ) - { - MsgDev( D_ERROR, "CL_LoadSprite: %s invalid sprite version\n", szSpriteName ); - Mem_Free( buffer ); - return r_shaders; - } - - numframes = pin->numframes; - twoSided = ( pin->facetype == SPR_CULL_NONE ) ? true : false; - numi = (short *)( pin + 1 ); - - // NOTE: TriAPI and hud sprites not used auto-rendermode feature - - if( *numi == 256 ) - { - byte *src = (byte *)(numi+1); - rgbdata_t *pal; - - // install palette - switch( pin->texFormat ) - { - case SPR_ADDGLOW: - pal = FS_LoadImage( "#normal.pal", src, 768 ); - R_ShaderSetRenderMode( kRenderNormal, twoSided ); - break; - case SPR_ADDITIVE: - pal = FS_LoadImage( "#normal.pal", src, 768 ); - R_ShaderSetRenderMode( kRenderNormal, twoSided ); - break; - case SPR_INDEXALPHA: - pal = FS_LoadImage( "#decal.pal", src, 768 ); - R_ShaderSetRenderMode( kRenderNormal, twoSided ); - break; - case SPR_ALPHTEST: - pal = FS_LoadImage( "#transparent.pal", src, 768 ); - R_ShaderSetRenderMode( kRenderNormal, twoSided ); - break; - case SPR_NORMAL: - default: - pal = FS_LoadImage( "#normal.pal", src, 768 ); - R_ShaderSetRenderMode( kRenderNormal, twoSided ); - break; - } - pframetype = (dframetype_t *)(src + 768); - FS_FreeImage( pal ); // palette installed, no reason to keep this data - } - else - { - MsgDev( D_ERROR, "CL_LoadSprite: %s has invalid palette\n", szSpriteName ); - Mem_Free( buffer ); - return r_shaders; - } - - if( numframes < 1 ) - { - MsgDev( D_ERROR, "CL_LoadSprite: %s has invalid # of frames: %d\n", szSpriteName, numframes ); - Mem_Free( buffer ); - return r_shaders; - } - - com.strncpy( frame_prefix, "one", MAX_STRING ); - tex_flags = TF_CLAMP|TF_NOMIPMAP|TF_NOPICMIP; - frames = NULL; // invalidate pointer - sp_name[0] = 0; - group_num = 0; - - for( i = 0; i < numframes; i++ ) - { - switch( pframetype->type ) - { - case FRAME_SINGLE: - pframetype = CL_LoadSpriteFrame( szSpriteName, pframetype + 1, i ); - break; - case FRAME_GROUP: - case FRAME_ANGLED: - pframetype = CL_SpriteSkipGroup( szSpriteName, pframetype + 1, i ); - break; - } - if( pframetype == NULL ) break; // technically an error - } - - // all frames uploaded, release buffer - Mem_Free( buffer ); - - return R_LoadShader( szSpriteName, SHADER_SPRITE, true, tex_flags, SHADER_INVALID ); -} - -/* -================ -R_GetSpriteFrame - -assume pModel is valid -================ -*/ -mspriteframe_t *R_GetSpriteFrame( ref_model_t *pModel, int frame, float yawAngle ) -{ - msprite_t *psprite; - int i, numframes; - mspritegroup_t *pspritegroup; - mspriteframe_t *pspriteframe; - float *pintervals, fullinterval, targettime, time; - - ASSERT( pModel ); - psprite = pModel->extradata; - - if( frame < 0 ) - { - frame = 0; - } - else if( frame >= psprite->numframes ) - { - MsgDev( D_WARN, "R_GetSpriteFrame: no such frame %d (%s)\n", frame, pModel->name ); - frame = psprite->numframes - 1; - } - - if( psprite->frames[frame].type == FRAME_SINGLE ) - { - pspriteframe = psprite->frames[frame].frameptr; - } - else if( psprite->frames[frame].type == FRAME_GROUP ) - { - pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; - pintervals = pspritegroup->intervals; - numframes = pspritegroup->numframes; - fullinterval = pintervals[numframes-1]; - time = RI.refdef.time; - - // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values - // are positive, so we don't have to worry about division by zero - targettime = time - ((int)(time / fullinterval)) * fullinterval; - - for( i = 0; i < (numframes - 1); i++ ) - { - if( pintervals[i] > targettime ) - break; - } - pspriteframe = pspritegroup->frames[i]; - } - else if( psprite->frames[frame].type == FRAME_ANGLED ) - { - // e.g. doom-style sprite monsters - float yaw = yawAngle - 45; // angled bias - int angleframe = (int)(( RI.refdef.viewangles[1] - yaw ) / 360 * 8 + 0.5 - 4) & 7; - - pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; - pspriteframe = pspritegroup->frames[angleframe]; - } - return pspriteframe; -} - -/* -================ -R_GetSpriteFrameInterpolant - -NOTE: we using prevblending[0] and [1] for holds interval -between frames where are we lerping -================ -*/ -float R_GetSpriteFrameInterpolant( ref_entity_t *ent, mspriteframe_t **oldframe, mspriteframe_t **curframe ) -{ - msprite_t *psprite; - mspritegroup_t *pspritegroup; - int i, j, numframes, frame; - float lerpFrac, time, jtime, jinterval; - float *pintervals, fullinterval, targettime; - int m_fDoInterp; - - psprite = ent->model->extradata; - frame = (int)ent->lerp->curstate.frame; - lerpFrac = 1.0f; - - // misc info - if( r_sprite_lerping->integer ) - m_fDoInterp = (ent->flags & EF_NOINTERP) ? false : true; - else m_fDoInterp = false; - - if( frame < 0 ) - { - frame = 0; - } - else if( frame >= psprite->numframes ) - { - MsgDev( D_WARN, "R_GetSpriteFrame: no such frame %d (%s)\n", frame, ent->model->name ); - frame = psprite->numframes - 1; - } - - if( psprite->frames[frame].type == FRAME_SINGLE ) - { - if( m_fDoInterp ) - { - if( ent->lerp->latched.prevblending[0] >= psprite->numframes || psprite->frames[ent->lerp->latched.prevblending[0]].type != FRAME_SINGLE ) - { - // this can be happens when rendering switched between single and angled frames - // or change model on replace delta-entity - ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame; - ent->lerp->latched.prevanimtime = RI.refdef.time; - lerpFrac = 1.0f; - } - - if( ent->lerp->latched.prevanimtime < RI.refdef.time ) - { - if( frame != ent->lerp->latched.prevblending[1] ) - { - ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1]; - ent->lerp->latched.prevblending[1] = frame; - ent->lerp->latched.prevanimtime = RI.refdef.time; - lerpFrac = 0.0f; - } - else lerpFrac = (RI.refdef.time - ent->lerp->latched.prevanimtime) * ent->framerate; - } - else - { - ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame; - ent->lerp->latched.prevanimtime = RI.refdef.time; - lerpFrac = 0.0f; - } - } - else - { - ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame; - lerpFrac = 1.0f; - } - - if( ent->lerp->latched.prevblending[0] >= psprite->numframes ) - { - // reset interpolation on change model - ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame; - ent->lerp->latched.prevanimtime = RI.refdef.time; - lerpFrac = 0.0f; - } - - // get the interpolated frames - if( oldframe ) *oldframe = psprite->frames[ent->lerp->latched.prevblending[0]].frameptr; - if( curframe ) *curframe = psprite->frames[frame].frameptr; - } - else if( psprite->frames[frame].type == FRAME_GROUP ) - { - pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; - pintervals = pspritegroup->intervals; - numframes = pspritegroup->numframes; - fullinterval = pintervals[numframes-1]; - jinterval = pintervals[1] - pintervals[0]; - time = RI.refdef.time; - jtime = 0.0f; - - // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values - // are positive, so we don't have to worry about division by zero - targettime = time - ((int)(time / fullinterval)) * fullinterval; - - // LordHavoc: since I can't measure the time properly when it loops from numframes - 1 to 0, - // i instead measure the time of the first frame, hoping it is consistent - for( i = 0, j = numframes - 1; i < (numframes - 1); i++ ) - { - if( pintervals[i] > targettime ) - break; - j = i; - jinterval = pintervals[i] - jtime; - jtime = pintervals[i]; - } - - if( m_fDoInterp ) - lerpFrac = (targettime - jtime) / jinterval; - else j = i; // no lerping - - // get the interpolated frames - if( oldframe ) *oldframe = pspritegroup->frames[j]; - if( curframe ) *curframe = pspritegroup->frames[i]; - } - else if( psprite->frames[frame].type == FRAME_ANGLED ) - { - // e.g. doom-style sprite monsters - float yaw = ent->angles[1] - 45; // angled bias - int angleframe = (int)((RI.refdef.viewangles[1] - yaw) / 360 * 8 + 0.5 - 4) & 7; - - if( m_fDoInterp ) - { - if( ent->lerp->latched.prevblending[0] >= psprite->numframes || psprite->frames[ent->lerp->latched.prevblending[0]].type != FRAME_ANGLED ) - { - // this can be happens when rendering switched between single and angled frames - // or change model on replace delta-entity - ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame; - ent->lerp->latched.prevanimtime = RI.refdef.time; - lerpFrac = 1.0f; - } - - if( ent->lerp->latched.prevanimtime < RI.refdef.time ) - { - if( frame != ent->lerp->latched.prevblending[1] ) - { - ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1]; - ent->lerp->latched.prevblending[1] = frame; - ent->lerp->latched.prevanimtime = RI.refdef.time; - lerpFrac = 0.0f; - } - else lerpFrac = (RI.refdef.time - ent->lerp->latched.prevanimtime) * ent->framerate; - } - else - { - ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame; - ent->lerp->latched.prevanimtime = RI.refdef.time; - lerpFrac = 0.0f; - } - } - else - { - ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame; - lerpFrac = 1.0f; - } - - pspritegroup = (mspritegroup_t *)psprite->frames[ent->lerp->latched.prevblending[0]].frameptr; - if( oldframe ) *oldframe = pspritegroup->frames[angleframe]; - - pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; - if( curframe ) *curframe = pspritegroup->frames[angleframe]; - } - return lerpFrac; -} - -static float R_GlowSightDistance( vec3_t glowOrigin ) -{ - float dist; - vec3_t glowDist; - pmtrace_t tr; - - VectorSubtract( glowOrigin, RI.viewOrigin, glowDist ); - dist = VectorLength( glowDist ); - - R_TraceLine( &tr, RI.viewOrigin, glowOrigin, FTRACE_IGNORE_GLASS|FTRACE_SIMPLEBOX ); - - if(( 1.0f - tr.fraction ) * dist > 8 ) - return -1; - return dist; -} - -static float R_SpriteGlowBlend( ref_entity_t *e ) -{ - float dist = R_GlowSightDistance( e->origin ); - float brightness; - - if( dist <= 0 ) return 0.0f; // occluded - - if( e->renderfx == kRenderFxNoDissipation ) - return (float)e->renderamt * (1.0f/255.0f); - - // UNDONE: Tweak these magic numbers (19000 - falloff & 200 - sprite size) - brightness = 19000.0 / ( dist * dist ); - brightness = bound( 0.05f, brightness, 1.0f ); - - // Make the glow fixed size in screen space, taking into consideration the scale setting. - if( e->scale == 0 ) e->scale = 1.0f; - e->scale *= dist * (1.0f / 200.0f ); - - return brightness; -} - -qboolean R_SpriteOccluded( ref_entity_t *e ) -{ - if( e->rendermode == kRenderGlow ) - { - float blend = 1.0f; - float depth; - vec3_t v; - - R_TransformToScreen_Vec3( e->origin, v ); - - if( v[0] < RI.refdef.viewport[0] || v[0] > RI.refdef.viewport[0] + RI.refdef.viewport[2] ) - return true; // do scissor - if( v[1] < RI.refdef.viewport[1] || v[1] > RI.refdef.viewport[1] + RI.refdef.viewport[3] ) - return true; // do scissor - - if( r_cullflares->integer ) - { - pglReadPixels((int)( v[0] ), (int)( v[1] ), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth ); - if( depth + 1e-4 < v[2] ) return true; // occluded - } - - blend *= R_SpriteGlowBlend( e ); - e->renderamt *= blend; - - if( blend <= 0.05f ) - return true; // faded - } - return false; -} - -/* -================= -R_DrawSpriteModel -================= -*/ -void R_DrawSpriteModel( const meshbuffer_t *mb ) -{ - ref_entity_t *e; - mspriteframe_t *frame, *oldframe; - msprite_t *psprite; - ref_model_t *model; - float lerp = 1.0f, ilerp; - meshbuffer_t *rb = (meshbuffer_t *)mb; - byte renderamt; - - MB_NUM2ENTITY( mb->sortkey, e ); - model = e->model; - - if( OCCLUSION_QUERIES_ENABLED( RI ) && OCCLUSION_TEST_ENTITY( e )) - { - ref_shader_t *shader; - - MB_NUM2SHADER( mb->shaderkey, shader ); - if( !R_GetOcclusionQueryResultBool( shader->type == 1 ? OQ_PLANARSHADOW : OQ_ENTITY, e - r_entities, true )) - return; - } - - psprite = (msprite_t * )model->extradata; - - switch( e->rendermode ) - { - case kRenderNormal: - case kRenderTransColor: - case kRenderTransAlpha: - frame = oldframe = R_GetSpriteFrame( e->model, e->lerp->curstate.frame, e->angles[YAW] ); - break; - case kRenderTransTexture: - case kRenderTransAdd: - case kRenderGlow: - lerp = R_GetSpriteFrameInterpolant( e, &oldframe, &frame ); - break; - default: - Host_Error( "R_DrawSpriteModel: %s bad rendermode %i\n", model->name, e->rendermode ); - break; - } - - // do movewith - if( e->parent && e->movetype == MOVETYPE_FOLLOW ) - { - if( e->body > 0 && e->parent->model && e->parent->model->type == mod_studio ) - { - int num = bound( 1, e->body, MAXSTUDIOATTACHMENTS ); - - // pev->colormap is hardcoded to attachment number - // NOTE: use interpolated origin to avoid flickering attachments - VectorCopy( e->parent->lerp->attachment[num-1], e->origin2 ); - } - else VectorCopy( e->parent->origin, e->origin2 ); - } - - // no rotation for sprites - R_TranslateForEntity( e ); - - if( e->rendermode == kRenderGlow ) - pglDepthRange( gldepthmin, gldepthmin + 0.3 * ( gldepthmax - gldepthmin )); - - if( oldframe == frame ) - { - // draw the single non-lerped frame - if( R_PushSprite( rb, psprite->type, frame->left, frame->right, frame->down, frame->up )) - R_RenderMeshBuffer( rb ); - } - else - { - // draw two combined lerped frames - renderamt = e->renderamt; - - lerp = bound( 0.0f, lerp, 1.0f ); - ilerp = 1.0f - lerp; - - if( ilerp != 0 ) - { - e->renderamt = renderamt * ilerp; // merge prevframe alpha - - if( e->customShader ) rb->shaderkey = e->customShader->sortkey; - else rb->shaderkey = r_shaders[oldframe->shader].sortkey; - if( R_PushSprite( rb, psprite->type, oldframe->left, oldframe->right, oldframe->down, oldframe->up )) - R_RenderMeshBuffer( rb ); - } - - if( lerp != 0 ) - { - e->renderamt = renderamt * lerp; // merge frame alpha - - if( e->customShader ) rb->shaderkey = e->customShader->sortkey; - else rb->shaderkey = r_shaders[frame->shader].sortkey; - if( R_PushSprite( rb, psprite->type, frame->left, frame->right, frame->down, frame->up )) - R_RenderMeshBuffer( rb ); - } - - // restore current values (e.g. for right mirror passes) - e->renderamt = renderamt; - } - - if( e->rendermode == kRenderGlow ) - pglDepthRange( gldepthmin, gldepthmax ); -} - -qboolean R_CullSpriteModel( ref_entity_t *e ) -{ - qboolean frustum, query, clipped; - - if( !e->model->extradata ) - return true; - - if( e->ent_type == ET_VIEWENTITY && r_lefthand->integer >= 2 ) - return true; - - VectorCopy( e->model->mins, sprite_mins ); - VectorCopy( e->model->maxs, sprite_maxs ); - - sprite_radius = RadiusFromBounds( sprite_mins, sprite_maxs ); - clipped = R_CullModel( e, sprite_mins, sprite_maxs, sprite_radius ); - frustum = clipped & 1; - if( clipped & 2 ) return true; - - query = OCCLUSION_QUERIES_ENABLED( RI ) && OCCLUSION_TEST_ENTITY( e ) ? true : false; - if( !frustum && query ) R_IssueOcclusionQuery( R_GetOcclusionQueryNum( OQ_ENTITY, e - r_entities ), e, sprite_mins, sprite_maxs ); - - return frustum; -} - -void R_SpriteDrawDebug( void ) -{ - vec3_t bbox[8]; - ref_model_t *model; - int i; - - if( r_drawentities->integer != 5 ) - return; - - model = RI.currententity->model; - - // compute a full bounding box - for( i = 0; i < 8; i++ ) - { - bbox[i][0] = (i & 1) ? model->mins[0] : model->maxs[0]; - bbox[i][1] = (i & 2) ? model->mins[1] : model->maxs[1]; - bbox[i][2] = (i & 4) ? model->mins[2] : model->maxs[2]; - } - - R_TranslateForEntity( RI.currententity ); - pglColor4f( 0.0f, 0.0f, 1.0f, 1.0f ); // blue bboxes for sprites - - pglBegin( GL_LINES ); - for( i = 0; i < 2; i += 1 ) - { - pglVertex3fv( bbox[i+0] ); - pglVertex3fv( bbox[i+2] ); - pglVertex3fv( bbox[i+4] ); - pglVertex3fv( bbox[i+6] ); - pglVertex3fv( bbox[i+0] ); - pglVertex3fv( bbox[i+4] ); - pglVertex3fv( bbox[i+2] ); - pglVertex3fv( bbox[i+6] ); - pglVertex3fv( bbox[i*2+0] ); - pglVertex3fv( bbox[i*2+1] ); - pglVertex3fv( bbox[i*2+4] ); - pglVertex3fv( bbox[i*2+5] ); - } - pglEnd(); -} \ No newline at end of file diff --git a/vid_gl/r_studio.c b/vid_gl/r_studio.c deleted file mode 100644 index f90c6a3a..00000000 --- a/vid_gl/r_studio.c +++ /dev/null @@ -1,2694 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2007 -// r_studio.c - render studio models -//======================================================================= - -#include "r_local.h" -#include "mathlib.h" -#include "matrix_lib.h" -#include "cl_entity.h" -#include "const.h" - -#define DIST_EPSILON (0.03125) -#define EVENT_CLIENT 5000 // less than this value it's a server-side studio events - -/* -============================================================= - - STUDIO MODELS - -============================================================= -*/ -float (*m_protationmatrix)[4]; -matrix4x4 *m_pbonestransform; - -// lighting stuff -vec3_t *m_pxformverts; -vec3_t *m_pxformnorms; -vec3_t *m_pxformlight; - -// chrome stuff -vec2_t *m_pchrome; -int *m_pchromeage; -vec3_t *m_pchromeup; -vec3_t *m_pchromeright; - -// player gait sequence stuff -int m_fGaitEstimation; -float m_flGaitMovement; - -// misc variables -int m_fDoInterp; -mstudiomodel_t *m_pSubModel; -mstudiobodyparts_t *m_pBodyPart; -player_info_t *m_pPlayerInfo; -studiohdr_t *m_pStudioHeader; -studiohdr_t *m_pTextureHeader; -mplane_t studio_planes[12]; -pmtrace_t studio_trace; -vec3_t studio_mins, studio_maxs; -float studio_radius; - -// studio cvars -convar_t *r_studio_lerping; - -typedef struct studioverts_s -{ - vec3_t *verts; - vec3_t *norms; - vec3_t *light; // light values - vec2_t *chrome; // size match with numverts - int numverts; - int numnorms; - int m_nCachedFrame; // to avoid transform it twice -} studioverts_t; - -typedef struct studiovars_s -{ - cl_entity_t *lerp; // duplicate e->lerp pointer for consistency - - // cached values, valid only for CURRENT frame - char bonenames[MAXSTUDIOBONES][32];// used for attached entities - studioverts_t *mesh[MAXSTUDIOMODELS]; - matrix4x4 rotationmatrix; - matrix4x4 *bonestransform; - vec3_t *chromeright; - vec3_t *chromeup; - int *chromeage; - int numbones; -} studiovars_t; - -static vec3_t hullcolor[8] = -{ -{ 1.0, 1.0, 1.0 }, -{ 1.0, 0.5, 0.5 }, -{ 0.5, 1.0, 0.5 }, -{ 1.0, 1.0, 0.5 }, -{ 0.5, 0.5, 1.0 }, -{ 1.0, 0.5, 1.0 }, -{ 0.5, 1.0, 1.0 }, -{ 1.0, 1.0, 1.0 } -}; - -void R_StudioInitBoxHull( void ); - -/* -==================== -R_StudioInit - -==================== -*/ -void R_StudioInit( void ) -{ - int i; - - m_pBodyPart = NULL; - m_pStudioHeader = NULL; - m_flGaitMovement = 1; - - r_studio_lerping = Cvar_Get( "r_studio_lerping", "1", CVAR_ARCHIVE, "enables studio model animation lerping" ); - - for( i = 1; i < MAX_ENTITIES; i++ ) - { - r_entities[i].mempool = NULL; - r_entities[i].extradata = NULL; - } - - R_StudioInitBoxHull(); -} - -/* -==================== -R_StudioFreeAllExtradata - -release all ref_entity mempools -==================== -*/ -void R_StudioFreeAllExtradata( void ) -{ - int i; - - for( i = 1; i < MAX_ENTITIES; i++ ) - { - Mem_FreePool( &r_entities[i].mempool ); - r_entities[i].extradata = NULL; - } - Mem_Set( r_entities, 0, sizeof( r_entities )); -} - -/* -==================== -R_StudioShutdown - -==================== -*/ -void R_StudioShutdown( void ) -{ - R_StudioFreeAllExtradata (); -} - -void R_StudioAllocExtradata( cl_entity_t *in, ref_entity_t *e ) -{ - studiovars_t *studio; - qboolean hasChrome = (((mstudiodata_t *)e->model->extradata)->phdr->flags & STUDIO_HAS_CHROME) ? true : false; - int numbones = ((mstudiodata_t *)e->model->extradata)->phdr->numbones; - - if( !e->mempool ) e->mempool = Mem_AllocPool( va( "Entity Pool %i", e - r_entities )); - if( !e->extradata ) e->extradata = (void *)Mem_Alloc( e->mempool, sizeof( studiovars_t )); - studio = (studiovars_t *)e->extradata; - studio->lerp = e->lerp; - - // any stuidio model MUST have previous data for lerping - ASSERT( studio->lerp ); - - if( studio->numbones != numbones ) - { - size_t cache_size = sizeof( matrix4x4 ) * numbones; - size_t names_size = numbones * 32; // bonename length - - // allocate or merge bones cache - studio->bonestransform = (matrix4x4 *)Mem_Realloc( e->mempool, studio->bonestransform, cache_size ); - } - - if( hasChrome ) - { - if( studio->numbones != numbones || !studio->chromeage || !studio->chromeright || !studio->chromeup ) - { - // allocate or merge chrome cache - studio->chromeage = (int *)Mem_Realloc( e->mempool, studio->chromeage, numbones * sizeof( int )); - studio->chromeright = (vec3_t *)Mem_Realloc( e->mempool, studio->chromeright, numbones * sizeof( vec3_t )); - studio->chromeup = (vec3_t *)Mem_Realloc( e->mempool, studio->chromeup, numbones * sizeof( vec3_t )); - } - } - else - { - if( studio->chromeage ) Mem_Free( studio->chromeage ); - if( studio->chromeright ) Mem_Free( studio->chromeright ); - if( studio->chromeup ) Mem_Free( studio->chromeup ); - studio->chromeright = studio->chromeup = NULL; - studio->chromeage = NULL; - } - studio->numbones = numbones; -} - -/* -======================================================= - - MISC STUDIO UTILS - -======================================================= -*/ -/* -==================== -StudioSetupRender - -==================== -*/ -static void R_StudioSetupRender( ref_entity_t *e, ref_model_t *mod ) -{ - mstudiodata_t *m_pRefModel = (mstudiodata_t *)mod->extradata; - - // set global pointers - m_pStudioHeader = m_pRefModel->phdr; - m_pTextureHeader = m_pRefModel->thdr; - - // GetPlayerInfo returns NULL for non player entities - m_pPlayerInfo = ri.GetPlayerInfo( e->index - 1 ); - - m_fGaitEstimation = ( m_pPlayerInfo ) ? 1 : 0; - - ASSERT( e->extradata ); - - // set cached bones - m_protationmatrix = ((studiovars_t *)e->extradata)->rotationmatrix; - m_pbonestransform = ((studiovars_t *)e->extradata)->bonestransform; - - // set chrome bones - m_pchromeup = ((studiovars_t *)e->extradata)->chromeup; - m_pchromeage = ((studiovars_t *)e->extradata)->chromeage; - m_pchromeright = ((studiovars_t *)e->extradata)->chromeright; - - // misc info - if( e->ent_type == ET_VIEWENTITY ) - { - // viewmodel can't properly animate without lerping - m_fDoInterp = true; - } - else if( r_studio_lerping->integer ) - { - m_fDoInterp = (e->flags & EF_NOINTERP) ? false : true; - } - else - { - m_fDoInterp = false; - } -} - -void R_StudioInitBoxHull( void ) -{ - int i, side; - mplane_t *p; - - for( i = 0; i < 6; i++ ) - { - side = i & 1; - - // planes - p = &studio_planes[i*2]; - p->type = i>>1; - p->signbits = 0; - VectorClear( p->normal ); - p->normal[i>>1] = 1.0f; - - p = &studio_planes[i*2+1]; - p->type = 3 + (i>>1); - p->signbits = 0; - VectorClear( p->normal ); - p->normal[i>>1] = -1; - - p->signbits = SignbitsForPlane( p->normal ); - } -} - -void R_StudioBoxHullFromBounds( const vec3_t mins, const vec3_t maxs ) -{ - studio_planes[0].dist = maxs[0]; - studio_planes[1].dist = -maxs[0]; - studio_planes[2].dist = mins[0]; - studio_planes[3].dist = -mins[0]; - studio_planes[4].dist = maxs[1]; - studio_planes[5].dist = -maxs[1]; - studio_planes[6].dist = mins[1]; - studio_planes[7].dist = -mins[1]; - studio_planes[8].dist = maxs[2]; - studio_planes[9].dist = -maxs[2]; - studio_planes[10].dist = mins[2]; - studio_planes[11].dist = -mins[2]; -} - -qboolean R_StudioTraceBox( vec3_t start, vec3_t end ) -{ - int i; - mplane_t *plane, *clipplane; - float enterFrac, leaveFrac; - qboolean getout, startout; - float d1, d2; - float f; - - enterFrac = -1.0; - leaveFrac = 1.0; - clipplane = NULL; - - getout = false; - startout = false; - - // compare the trace against all planes of the brush - // find the latest time the trace crosses a plane towards the interior - // and the earliest time the trace crosses a plane towards the exterior - for( i = 0; i < 6; i++ ) - { - plane = studio_planes + i * 2 + (i & 1); - - d1 = DotProduct( start, plane->normal ) - plane->dist; - d2 = DotProduct( end, plane->normal ) - plane->dist; - - if( d2 > 0.0f ) getout = true; // endpoint is not in solid - if( d1 > 0.0f ) startout = true; - - // if completely in front of face, no intersection with the entire brush - if( d1 > 0 && ( d2 >= DIST_EPSILON || d2 >= d1 )) - return false; - - // if it doesn't cross the plane, the plane isn't relevent - if( d1 <= 0 && d2 <= 0 ) - continue; - - // crosses face - if( d1 > d2 ) - { - // enter - f = ( d1 - DIST_EPSILON ) / ( d1 - d2 ); - if( f < 0.0f ) f = 0.0f; - - if( f > enterFrac ) - { - enterFrac = f; - clipplane = plane; - } - } - else - { - // leave - f = ( d1 + DIST_EPSILON ) / ( d1 - d2 ); - if( f > 1.0f ) f = 1.0f; - - if( f < leaveFrac ) - { - leaveFrac = f; - } - } - } - - // all planes have been checked, and the trace was not - // completely outside the brush - if( !startout ) - { - // original point was inside brush - if( !getout ) studio_trace.fraction = 0.0f; - return true; - } - - if( enterFrac < leaveFrac ) - { - if( enterFrac > -1 && enterFrac < studio_trace.fraction ) - { - if( enterFrac < 0.0f ) - enterFrac = 0.0f; - - studio_trace.fraction = enterFrac; - VectorCopy( clipplane->normal, studio_trace.plane.normal ); - studio_trace.plane.dist = clipplane->dist; - return true; - } - } - return false; -} - -qboolean R_StudioTrace( ref_entity_t *e, const vec3_t start, const vec3_t end, pmtrace_t *tr ) -{ - matrix4x4 m; - vec3_t start_l, end_l; - int i, outBone; - - R_StudioSetupRender( e, e->model ); - - if( !m_pStudioHeader->numhitboxes ) - { - tr->hitgroup = -1; - return false; - } - - // NOTE: we don't need to setup bones because - // it's already setup by rendering code - Mem_Set( &studio_trace, 0, sizeof( pmtrace_t )); - VectorCopy( end, studio_trace.endpos ); - studio_trace.allsolid = true; - studio_trace.fraction = 1.0f; - studio_trace.hitgroup = -1; - outBone = -1; - - for( i = 0; i < m_pStudioHeader->numhitboxes; i++ ) - { - mstudiobbox_t *phitbox = (mstudiobbox_t *)((byte*)m_pStudioHeader + m_pStudioHeader->hitboxindex) + i; - - Matrix4x4_Invert_Simple( m, m_pbonestransform[phitbox->bone] ); - Matrix4x4_VectorTransform( m, start, start_l ); - Matrix4x4_VectorTransform( m, end, end_l ); - - R_StudioBoxHullFromBounds( phitbox->bbmin, phitbox->bbmax ); - - if( R_StudioTraceBox( start_l, end_l )) - { - outBone = phitbox->bone; - studio_trace.hitgroup = i; // it's a hitbox, not a hitgroup! - } - - if( studio_trace.fraction == 0.0f ) - break; - } - - if( studio_trace.fraction > 0.0f ) - studio_trace.allsolid = false; - - // all hitboxes were swept, get trace result - if( outBone >= 0 ) - { - tr->fraction = studio_trace.fraction; - tr->hitgroup = studio_trace.hitgroup; - tr->allsolid = studio_trace.allsolid; - tr->ent = e - r_entities; - - Matrix4x4_VectorRotate( m_pbonestransform[outBone], studio_trace.endpos, tr->endpos ); - if( tr->fraction == 1.0f ) - { - VectorCopy( end, tr->endpos ); - } - else - { - mstudiobone_t *pbone = (mstudiobone_t *)((byte*)m_pStudioHeader + m_pStudioHeader->boneindex) + outBone; - -// MsgDev( D_INFO, "Bone name %s\n", pbone->name ); // debug - VectorLerp( start, tr->fraction, end, tr->endpos ); - r_debug_hitbox = pbone->name; - } - tr->plane.dist = DotProduct( tr->endpos, tr->plane.normal ); - - return true; - } - return false; -} - -// extract texture filename from modelname -char *R_StudioTexName( ref_model_t *mod ) -{ - static string texname; - - com.strncpy( texname, mod->name, MAX_STRING ); - FS_StripExtension( texname ); - com.strncat( texname, "T.mdl", MAX_STRING ); - return texname; -} - -int R_StudioExtractBbox( studiohdr_t *phdr, int sequence, float *mins, float *maxs ) -{ - mstudioseqdesc_t *pseqdesc; - pseqdesc = (mstudioseqdesc_t *)((byte *)phdr + phdr->seqindex); - - if( sequence < 0 || sequence >= phdr->numseq ) - return 0; - - VectorCopy( pseqdesc[sequence].bbmin, mins ); - VectorCopy( pseqdesc[sequence].bbmax, maxs ); - - return 1; -} - -void R_StudioModelLerpBBox( ref_entity_t *e, ref_model_t *mod ) -{ - // FIXME: implement -} - -void R_StudioModelBBox( ref_entity_t *e, vec3_t mins, vec3_t maxs ) -{ - studiohdr_t *hdr; - - if( !e->model ) return; - R_StudioSetupRender( e, e->model ); - - hdr = ((mstudiodata_t *)e->model->extradata)->phdr; - if( !hdr ) return; - R_StudioExtractBbox( hdr, e->lerp->curstate.sequence, mins, maxs ); -} - -/* -==================== -Studio model loader -==================== -*/ -void R_StudioSurfaceParm( mstudiotexture_t *tex ) -{ - if( tex->flags & STUDIO_NF_TRANSPARENT ) - R_ShaderSetRenderMode( kRenderTransAlpha, false ); - else if( tex->flags & STUDIO_NF_ADDITIVE ) - R_ShaderSetRenderMode( kRenderTransAdd, false ); - else if( tex->flags & STUDIO_NF_BLENDED ) - R_ShaderSetRenderMode( kRenderTransTexture, false ); - else R_ShaderSetRenderMode( kRenderNormal, false ); -} - -texture_t *R_StudioLoadTexture( ref_model_t *mod, studiohdr_t *phdr, mstudiotexture_t *ptexture ) -{ - size_t size; - int flags = 0; - string name; - - if( ptexture->flags & STUDIO_NF_TRANSPARENT ) - flags |= (TF_CLAMP|TF_NOMIPMAP); - - if( ptexture->flags & (STUDIO_NF_NORMALMAP|STUDIO_NF_HEIGHTMAP )) - flags |= TF_NORMALMAP; - - // NOTE: replace index with pointer to start of imagebuffer, ImageLib expected it - ptexture->index = (int)((byte *)phdr) + ptexture->index; - size = sizeof( mstudiotexture_t ) + ptexture->width * ptexture->height + 768; - - // build the texname - com.snprintf( name, sizeof( name ), "\"%s/%s\"", mod->name, ptexture->name ); - - if( ptexture->flags & STUDIO_NF_HEIGHTMAP ) - return R_FindTexture( va( "mergeDepthmap( heightMap( Studio( %s ), 2.0 ), Studio( %s ));", name, name ), (byte *)ptexture, size, flags ); - return R_FindTexture( va( "Studio( %s );", name ), (byte *)ptexture, size, flags ); -} - -static int R_StudioLoadTextures( ref_model_t *mod, studiohdr_t *phdr ) -{ - texture_t *texs[4]; - mstudiotexture_t *ptexture = (mstudiotexture_t *)(((byte *)phdr) + phdr->textureindex); - string modname, texname, shadername; - string normalmap, heightmap; - int nm_index, hm_index; - int i, j, numshaders = 0; - - FS_FileBase( mod->name, modname ); - - for( i = 0; i < phdr->numtextures; i++ ) - { - if( ptexture[i].flags & (STUDIO_NF_NORMALMAP|STUDIO_NF_HEIGHTMAP|STUDIO_NF_GLOSSMAP|STUDIO_NF_DECALMAP)) - continue; // doesn't produce dead shaders - - // misc - R_StudioSurfaceParm( &ptexture[i] ); - FS_FileBase( ptexture[i].name, texname ); - if( ptexture[i].flags & STUDIO_NF_CHROME ) phdr->flags |= STUDIO_HAS_CHROME; - com.snprintf( shadername, MAX_STRING, "%s.mdl/%s", modname, texname ); - - if( R_ShaderCheckCache( shadername )) - goto load_shader; // external shader found - - Mem_Set( texs, 0, sizeof( texs )); - normalmap[0] = heightmap[0] = '\0'; - nm_index = hm_index = 0; - - texs[0] = R_StudioLoadTexture( mod, phdr, ptexture + i ); - if( !texs[0] ) texs[0] = tr.defaultTexture; - R_ShaderAddStageTexture( texs[0] ); // load diffuse texture - - // check for normalmap - for( j = 0; j < phdr->numtextures; j++ ) - { - if( !com.strnicmp( texname, ptexture[j].name, com.strlen( texname ))) - { - if( ptexture[j].flags & STUDIO_NF_HEIGHTMAP ) - { - // determine heightmap name - com.snprintf( heightmap, sizeof( heightmap ), "%s/%s", mod->name, ptexture[j].name ); - hm_index = j; - } - else if( ptexture[j].flags & STUDIO_NF_NORMALMAP ) - { - // determine normalmap name - com.snprintf( normalmap, sizeof( normalmap ), "%s/%s", mod->name, ptexture[j].name ); - nm_index = j; - } - } - } - - // load it in - if( heightmap[0] && normalmap[0] ) - { - // merge both textures into single and turn parallax on - texs[1] = R_FindTexture( va( "mergeDepthmap( Studio( \"%s\" ), Studio( \"%s\" ));", normalmap, heightmap ), NULL, 0, TF_NORMALMAP ); - } - else if( normalmap[0] ) texs[1] = R_StudioLoadTexture( mod, phdr, ptexture + nm_index ); - else if( heightmap[0] ) texs[1] = R_StudioLoadTexture( mod, phdr, ptexture + hm_index ); - - if( texs[1] == NULL ) goto load_shader; // failed to load material - R_ShaderAddStageTexture( texs[1] ); - - // check for glossmap - for( j = 0; j < phdr->numtextures; j++ ) - { - if( ptexture[j].flags & (STUDIO_NF_GLOSSMAP) && !com.strnicmp( texname, ptexture[j].name, com.strlen( texname ))) - { - texs[2] = R_StudioLoadTexture( mod, phdr, ptexture + j ); - break; - } - } - R_ShaderAddStageTexture( texs[2] ); - - // check for decalmap - for( j = 0; j < phdr->numtextures; j++ ) - { - if( ptexture[j].flags & (STUDIO_NF_DECALMAP) && !com.strnicmp( texname, ptexture[j].name, com.strlen( texname ))) - { - texs[3] = R_StudioLoadTexture( mod, phdr, ptexture + j ); - break; - } - } - R_ShaderAddStageTexture( texs[3] ); -load_shader: - mod->shaders[numshaders] = R_LoadShader( shadername, SHADER_STUDIO, 0, 0, SHADER_INVALID ); - ptexture[numshaders].index = mod->shaders[numshaders]->shadernum; - numshaders++; - } - return numshaders; -} - -studiohdr_t *R_StudioLoadHeader( ref_model_t *mod, const uint *buffer ) -{ - byte *pin; - studiohdr_t *phdr; - mstudiotexture_t *ptexture; - string modname; - - pin = (byte *)buffer; - phdr = (studiohdr_t *)pin; - - if( phdr->version != STUDIO_VERSION ) - { - MsgDev( D_ERROR, "%s has wrong version number (%i should be %i)\n", phdr->name, phdr->version, STUDIO_VERSION ); - return NULL; - } - FS_FileBase( mod->name, modname ); - - ptexture = (mstudiotexture_t *)(((byte *)phdr) + phdr->textureindex); - if( phdr->textureindex > 0 && phdr->numtextures <= MAXSTUDIOSKINS ) - { - mod->shaders = Mod_Malloc( mod, sizeof( shader_t* ) * phdr->numtextures ); - mod->numshaders = R_StudioLoadTextures( mod, phdr ); - - if( mod->numshaders != phdr->numtextures ) // bump, gloss will be merged into single shader - mod->shaders = Mod_Realloc( mod, mod->shaders, sizeof( shader_t* ) * mod->numshaders ); - } - return (studiohdr_t *)buffer; -} - -void Mod_StudioLoadModel( ref_model_t *mod, const void *buffer ) -{ - studiohdr_t *phdr = R_StudioLoadHeader( mod, buffer ); - studiohdr_t *thdr = NULL; - mstudiodata_t *poutmodel; - void *texbuf; - - if( !phdr ) return; // there were problems - mod->extradata = poutmodel = (mstudiodata_t *)Mod_Malloc( mod, sizeof( mstudiodata_t )); - poutmodel->phdr = (studiohdr_t *)Mod_Malloc( mod, phdr->length ); - Mem_Copy( poutmodel->phdr, buffer, phdr->length ); - - if( phdr->numtextures == 0 ) - { - texbuf = FS_LoadFile( R_StudioTexName( mod ), NULL ); - if( texbuf ) thdr = R_StudioLoadHeader( mod, texbuf ); - else MsgDev( D_ERROR, "StudioLoadModel: %s missing textures file\n", mod->name ); - - if( !thdr ) return; // there were problems - poutmodel->thdr = (studiohdr_t *)Mod_Malloc( mod, thdr->length ); - Mem_Copy( poutmodel->thdr, texbuf, thdr->length ); - if( texbuf ) Mem_Free( texbuf ); - } - else poutmodel->thdr = poutmodel->phdr; // just make link - poutmodel->phdr->flags |= poutmodel->thdr->flags; // copy STUDIO_HAS_CHROME flag - - R_StudioExtractBbox( phdr, 0, mod->mins, mod->maxs ); - mod->radius = RadiusFromBounds( mod->mins, mod->maxs ); - mod->touchFrame = tr.registration_sequence; - mod->type = mod_studio; -} - -/* -==================== -R_StudioProcessEvents - -==================== -*/ -void R_StudioProcessEvents( ref_entity_t *e, cl_entity_t *ent ) -{ - mstudioseqdesc_t *pseqdesc; - mstudioevent_t *pevent; - float flEventFrame; - qboolean bLooped = false; - int i; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + e->lerp->curstate.sequence; - pevent = (mstudioevent_t *)((byte *)m_pStudioHeader + pseqdesc->eventindex); - - // curstate.frame not used for viewmodel animating - flEventFrame = e->lerp->latched.prevframe; - - if( pseqdesc->numevents == 0 ) - return; - - //Msg( "%i frame %f\n", r_framecount, e->lerp->latched.prevframe ); - - if( e->lerp->syncbase == -0.01f ) - { - flEventFrame = 0.0f; - // Msg( "Sequence changed\n" ); - } - - // stalled? - if( flEventFrame == e->lerp->syncbase ) - return; - - //Msg( "(seq %d cycle %.3f ) evframe %.3f prevevframe %.3f (time %.3f)\n", e->lerp->curstate.sequence, e->lerp->latched.prevframe, flEventFrame, e->lerp->syncbase, RI.refdef.time ); - - // check for looping - if( flEventFrame <= e->lerp->syncbase ) - { - if( e->lerp->syncbase - flEventFrame > 0.5f ) - { - bLooped = true; - } - else - { - // things have backed up, which is bad since it'll probably result in a hitch in the animation playback - // but, don't play events again for the same time slice - return; - } - } - - for( i = 0; i < pseqdesc->numevents; i++ ) - { - // ignore all non-client-side events - if( pevent[i].event < EVENT_CLIENT ) - continue; - - // looped - if( bLooped ) - { - if(( pevent[i].frame > e->lerp->syncbase || pevent[i].frame <= flEventFrame )) - { - //Msg( "FE %i Looped frame %i, prev %f ev %f (time %.3f)\n", pevent[i].event, pevent[i].frame, e->lerp->syncbase, flEventFrame, RI.refdef.time ); - ri.StudioEvent( &pevent[i], ent ); - } - } - else - { - if(( pevent[i].frame > e->lerp->syncbase && pevent[i].frame <= flEventFrame )) - { - //Msg( "FE %i Normal frame %i, prev %f ev %f (time %.3f)\n", pevent[i].event, pevent[i].frame, e->lerp->syncbase, flEventFrame, RI.refdef.time ); - ri.StudioEvent( &pevent[i], ent ); - } - } - } - - e->lerp->syncbase = flEventFrame; -} - -/* -==================== -StudioCalcBoneAdj - -==================== -*/ -void R_StudioCalcBoneAdj( float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2, byte mouthopen ) -{ - int i, j; - float value; - mstudiobonecontroller_t *pbonecontroller; - - pbonecontroller = (mstudiobonecontroller_t *)((byte *)m_pStudioHeader + m_pStudioHeader->bonecontrollerindex); - - for (j = 0; j < m_pStudioHeader->numbonecontrollers; j++) - { - i = pbonecontroller[j].index; - - if( i == STUDIO_MOUTH ) - { - // mouth hardcoded at controller 4 - value = mouthopen / 64.0f; - if( value > 1.0f ) value = 1.0f; - value = (1.0f - value) * pbonecontroller[j].start + value * pbonecontroller[j].end; - //Msg( "%d %f\n", mouthopen, value ); - } - else if( i <= MAXSTUDIOCONTROLLERS ) - { - // check for 360% wrapping - if( pbonecontroller[j].type & STUDIO_RLOOP ) - { - if( abs( pcontroller1[i] - pcontroller2[i] ) > 128 ) - { - float a, b; - a = fmod(( pcontroller1[j] + 128 ), 256 ); - b = fmod(( pcontroller2[j] + 128 ), 256 ); - value = ((a * dadt) + (b * (1 - dadt)) - 128) * (360.0/256.0) + pbonecontroller[j].start; - } - else - { - value = ((pcontroller1[i] * dadt + (pcontroller2[i]) * (1.0 - dadt))) * (360.0/256.0) + pbonecontroller[j].start; - } - } - else - { - value = (pcontroller1[i] * dadt + pcontroller2[i] * (1.0 - dadt)) / 255.0; - value = bound( 0.0f, value, 1.0f ); - value = (1.0 - value) * pbonecontroller[j].start + value * pbonecontroller[j].end; - } - //Msg( "%d %d %f : %f\n", RI.currententity->lerp->curstate.controller[j], RI.currententity->lerp->latched.prevcontroller[j], value, dadt ); - } - - switch( pbonecontroller[j].type & STUDIO_TYPES ) - { - case STUDIO_XR: - case STUDIO_YR: - case STUDIO_ZR: - adj[j] = value * (M_PI / 180.0); - break; - case STUDIO_X: - case STUDIO_Y: - case STUDIO_Z: - adj[j] = value; - break; - } - } -} - -/* -==================== -StudioCalcBoneQuaterion - -==================== -*/ -void R_StudioCalcBoneQuaterion( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *q ) -{ - int j, k; - vec4_t q1, q2; - vec3_t angle1, angle2; - mstudioanimvalue_t *panimvalue; - - for( j = 0; j < 3; j++ ) - { - if( panim->offset[j+3] == 0 ) - { - angle2[j] = angle1[j] = pbone->value[j+3]; // default; - } - else - { - panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]); - k = frame; - - // debug - if( panimvalue->num.total < panimvalue->num.valid ) k = 0; - - while( panimvalue->num.total <= k ) - { - k -= panimvalue->num.total; - panimvalue += panimvalue->num.valid + 1; - - // debug - if( panimvalue->num.total < panimvalue->num.valid ) - k = 0; - } - - // bah, missing blend! - if( panimvalue->num.valid > k ) - { - angle1[j] = panimvalue[k+1].value; - - if( panimvalue->num.valid > k + 1 ) - { - angle2[j] = panimvalue[k+2].value; - } - else - { - if( panimvalue->num.total > k + 1 ) - angle2[j] = angle1[j]; - else angle2[j] = panimvalue[panimvalue->num.valid+2].value; - } - } - else - { - angle1[j] = panimvalue[panimvalue->num.valid].value; - - if( panimvalue->num.total > k + 1 ) - { - angle2[j] = angle1[j]; - } - else - { - angle2[j] = panimvalue[panimvalue->num.valid + 2].value; - } - } - - angle1[j] = pbone->value[j+3] + angle1[j] * pbone->scale[j+3]; - angle2[j] = pbone->value[j+3] + angle2[j] * pbone->scale[j+3]; - } - - if( pbone->bonecontroller[j+3] != -1 ) - { - angle1[j] += adj[pbone->bonecontroller[j+3]]; - angle2[j] += adj[pbone->bonecontroller[j+3]]; - } - } - - if( !VectorCompare( angle1, angle2 )) - { - AngleQuaternion( angle1, q1 ); - AngleQuaternion( angle2, q2 ); - QuaternionSlerp( q1, q2, s, q ); - } - else - { - AngleQuaternion( angle1, q ); - } -} - -/* -==================== -StudioCalcBonePosition - -==================== -*/ -void R_StudioCalcBonePosition( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, float *pos ) -{ - int j, k; - mstudioanimvalue_t *panimvalue; - - for( j = 0; j < 3; j++ ) - { - pos[j] = pbone->value[j]; // default; - - if( panim->offset[j] != 0 ) - { - panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]); - - //if( j == 0 ) Msg( "%d %d:%d %f\n", frame, panimvalue->num.valid, panimvalue->num.total, s ); - k = frame; - - // debug - if( panimvalue->num.total < panimvalue->num.valid ) - k = 0; - - // find span of values that includes the frame we want - while( panimvalue->num.total <= k ) - { - k -= panimvalue->num.total; - panimvalue += panimvalue->num.valid + 1; - - // debug - if( panimvalue->num.total < panimvalue->num.valid ) - k = 0; - } - - // if we're inside the span - if( panimvalue->num.valid > k ) - { - // and there's more data in the span - if( panimvalue->num.valid > k + 1 ) - { - pos[j] += (panimvalue[k+1].value * (1.0f - s) + s * panimvalue[k+2].value) * pbone->scale[j]; - } - else - { - pos[j] += panimvalue[k+1].value * pbone->scale[j]; - } - } - else - { - // are we at the end of the repeating values section and there's another section with data? - if( panimvalue->num.total <= k + 1 ) - { - pos[j] += (panimvalue[panimvalue->num.valid].value * (1.0 - s) + s * panimvalue[panimvalue->num.valid + 2].value) * pbone->scale[j]; - } - else - { - pos[j] += panimvalue[panimvalue->num.valid].value * pbone->scale[j]; - } - } - } - if( pbone->bonecontroller[j] != -1 && adj ) - { - pos[j] += adj[pbone->bonecontroller[j]]; - } - } -} - -/* -==================== -StudioSlerpBones - -==================== -*/ -void R_StudioSlerpBones( vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s ) -{ - int i; - vec4_t q3; - float s1; - - s = bound( 0.0f, s, 1.0f ); - - s1 = 1.0f - s; - - for( i = 0; i < m_pStudioHeader->numbones; i++ ) - { - QuaternionSlerp( q1[i], q2[i], s, q3 ); - q1[i][0] = q3[0]; - q1[i][1] = q3[1]; - q1[i][2] = q3[2]; - q1[i][3] = q3[3]; - pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s; - pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s; - pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s; - } -} - -/* -==================== -Cache_Check - -consistency check -==================== -*/ -void *Cache_Check( byte *mempool, cache_user_t *c ) -{ - if( !c->data ) - return NULL; - - if( !Mem_IsAllocated( mempool, c->data )) - return NULL; - - return c->data; -} - -/* -==================== -StudioGetAnim - -==================== -*/ -mstudioanim_t *R_StudioGetAnim( ref_model_t *m_pRefModel, mstudioseqdesc_t *pseqdesc ) -{ - mstudioseqgroup_t *pseqgroup; - cache_user_t *paSequences; - mstudiodata_t *m_pSubModel = (mstudiodata_t *)m_pRefModel->extradata; - size_t filesize; - byte *buf; - - ASSERT( m_pSubModel ); - - pseqgroup = (mstudioseqgroup_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqgroupindex) + pseqdesc->seqgroup; - if( pseqdesc->seqgroup == 0 ) - return (mstudioanim_t *)((byte *)m_pStudioHeader + pseqgroup->data + pseqdesc->animindex); - - paSequences = (cache_user_t *)m_pSubModel->submodels; - - if( paSequences == NULL ) - { - paSequences = (cache_user_t *)Mem_Alloc( m_pRefModel->mempool, MAXSTUDIOGROUPS * sizeof( cache_user_t )); - m_pSubModel->submodels = (void *)paSequences; - } - - if( !Cache_Check( m_pRefModel->mempool, ( cache_user_t *)&( paSequences[pseqdesc->seqgroup] ))) - { - string filepath, modelname, modelpath; - - FS_FileBase( m_pRefModel->name, modelname ); - FS_ExtractFilePath( m_pRefModel->name, modelpath ); - com.snprintf( filepath, sizeof( filepath ), "%s/%s%i%i.mdl", modelpath, modelname, pseqdesc->seqgroup / 10, pseqdesc->seqgroup % 10 ); - - buf = FS_LoadFile( filepath, &filesize ); - if( !buf || !filesize ) Host_Error( "R_StudioGetAnim: can't load %s\n", filepath ); - if( IDSEQGRPHEADER != *(uint *)buf ) - Host_Error( "R_StudioGetAnim: %s is corrupted\n", filepath ); - - MsgDev( D_NOTE, "R_StudioGetAnim: %s\n", filepath ); - - paSequences[pseqdesc->seqgroup].data = Mem_Alloc( m_pRefModel->mempool, filesize ); - Mem_Copy( paSequences[pseqdesc->seqgroup].data, buf, filesize ); - Mem_Free( buf ); - } - return (mstudioanim_t *)((byte *)paSequences[pseqdesc->seqgroup].data + pseqdesc->animindex); -} - -/* -==================== -StudioPlayerBlend - -==================== -*/ -void R_StudioPlayerBlend( mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch ) -{ - // calc up/down pointing - *pBlend = (*pPitch * 3); - - if( *pBlend < pseqdesc->blendstart[0] ) - { - *pPitch -= pseqdesc->blendstart[0] / 3.0f; - *pBlend = 0; - } - else if( *pBlend > pseqdesc->blendend[0] ) - { - *pPitch -= pseqdesc->blendend[0] / 3.0f; - *pBlend = 255; - } - else - { - if( pseqdesc->blendend[0] - pseqdesc->blendstart[0] < 0.1f ) // catch qc error - *pBlend = 127; - else *pBlend = 255.0f * (*pBlend - pseqdesc->blendstart[0]) / (pseqdesc->blendend[0] - pseqdesc->blendstart[0]); - *pPitch = 0; - } -} - -/* -==================== -StudioSetUpTransform - -==================== -*/ -void R_StudioSetUpTransform( ref_entity_t *e, qboolean trivial_accept ) -{ - vec3_t angles, origin; - int i; - - if( trivial_accept ) - { - Matrix4x4_Copy( RI.objectMatrix, ((studiovars_t *)e->extradata)->rotationmatrix ); - Matrix4x4_ConcatTransforms( RI.modelviewMatrix, RI.worldviewMatrix, RI.objectMatrix ); - GL_LoadMatrix( RI.modelviewMatrix ); - tr.modelviewIdentity = false; - return; - } - - if( RP_FOLLOWENTITY( e )) - { - Matrix4x4_Copy( m_protationmatrix, ((studiovars_t *)e->parent->extradata)->rotationmatrix ); - m_protationmatrix = matrix4x4_identity; - return; - } - - VectorCopy( e->origin, origin ); - VectorCopy( e->angles, angles ); - - // interoplate monsters position - if( e->movetype == MOVETYPE_STEP || e->movetype == MOVETYPE_FLY ) - { - float d, f = 0.0f; - cl_entity_t *m_pGroundEntity; - - // don't do it if the goalstarttime hasn't updated in a while. - // NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit - // was increased to 1.0 s., which is 2x the max lag we are accounting for. - - if( m_fDoInterp && ( RI.refdef.time < e->lerp->curstate.animtime + 1.0f ) && ( e->lerp->curstate.animtime != e->lerp->latched.prevanimtime )) - { - f = ( RI.refdef.time - e->lerp->curstate.animtime ) / ( e->lerp->curstate.animtime - e->lerp->latched.prevanimtime ); - // Msg( "%4.2f %.2f %.2f\n", f, e->lerp->curstate.animtime, RI.refdef.time ); - } - - if( m_fDoInterp ) - { - // ugly hack to interpolate angle, position. - // current is reached 0.1 seconds after being set - f = f - 1.0f; - } - - m_pGroundEntity = ri.GetClientEdict( e->lerp->curstate.onground ); - - if( m_pGroundEntity && m_pGroundEntity->curstate.movetype == MOVETYPE_PUSH && !VectorIsNull( m_pGroundEntity->curstate.velocity )) - { - mstudioseqdesc_t *pseqdesc; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + e->lerp->curstate.sequence; - d = RI.lerpFrac; - - origin[0] += ( e->origin[0] - e->lerp->prevstate.origin[0] ) * d; - origin[1] += ( e->origin[1] - e->lerp->prevstate.origin[1] ) * d; - origin[2] += ( e->origin[2] - e->lerp->prevstate.origin[2] ) * d; - - d = f - d; - - // monster walking on moving platform - if( pseqdesc->motiontype & STUDIO_LX ) - { - origin[0] += ( e->lerp->curstate.origin[0] - e->lerp->latched.prevorigin[0] ) * d; - origin[1] += ( e->lerp->curstate.origin[1] - e->lerp->latched.prevorigin[1] ) * d; - origin[2] += ( e->lerp->curstate.origin[2] - e->lerp->latched.prevorigin[2] ) * d; - } - } - else - { - origin[0] += ( e->lerp->curstate.origin[0] - e->lerp->latched.prevorigin[0] ) * f; - origin[1] += ( e->lerp->curstate.origin[1] - e->lerp->latched.prevorigin[1] ) * f; - origin[2] += ( e->lerp->curstate.origin[2] - e->lerp->latched.prevorigin[2] ) * f; - } - - for( i = 0; i < 3; i++ ) - { - float ang1, ang2; - - ang1 = e->lerp->curstate.angles[i]; - ang2 = e->lerp->latched.prevangles[i]; - - d = ang1 - ang2; - - if( d > 180 ) d -= 360; - else if( d < -180 ) d += 360; - - angles[i] += d * f; - } - - // update it so attachments always have right pos - if( !RI.refdef.paused ) VectorCopy( origin, e->origin ); - } - - // don't rotate clients, only aim - if( e->ent_type == ET_PLAYER ) - angles[PITCH] = 0; - - Matrix4x4_CreateFromEntity( m_protationmatrix, origin[0], origin[1], origin[2], -angles[PITCH], angles[YAW], angles[ROLL], e->scale ); - - if( e->ent_type == ET_VIEWENTITY && r_lefthand->integer == 1 ) - { - m_protationmatrix[0][1] = -m_protationmatrix[0][1]; - m_protationmatrix[1][1] = -m_protationmatrix[1][1]; - m_protationmatrix[2][1] = -m_protationmatrix[2][1]; - } - - // save matrix for gl_transform, use identity matrix for bones - m_protationmatrix = matrix4x4_identity; -} - - -/* -==================== -StudioEstimateInterpolant - -==================== -*/ -float R_StudioEstimateInterpolant( void ) -{ - float dadt = 1.0f; - - if( m_fDoInterp && ( RI.currententity->lerp->curstate.animtime >= RI.currententity->lerp->latched.prevanimtime + 0.01f )) - { - dadt = ( RI.refdef.time - RI.currententity->lerp->curstate.animtime ) / 0.1f; - if( dadt > 2.0f ) dadt = 2.0f; - } - return dadt; -} - - -/* -==================== -StudioCalcRotations - -==================== -*/ -void R_StudioCalcRotations( float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f ) -{ - int i; - int frame; - mstudiobone_t *pbone; - studiovars_t *pstudio; - float s; - float adj[MAXSTUDIOCONTROLLERS]; - float dadt; - - if( f > pseqdesc->numframes - 1 ) - { - f = 0.0f; // bah, fix this bug with changing sequences too fast - } - else if( f < -0.01f ) - { - // BUGBUG ( somewhere else ) but this code should validate this data. - // This could cause a crash if the frame # is negative, so we'll go ahead - // and clamp it here - MsgDev( D_ERROR, "R_StudioCalcRotations: f = %g\n", f ); - f = -0.01f; - } - - frame = (int)f; - pstudio = RI.currententity->extradata; - ASSERT( pstudio ); - - //Msg( "%d %.4f %.4f %.4f %.4f %d\n", RI.currententity->lerp->curstate.sequence, RI.refdef.time, RI.currententity->lerp->curstate.animtime, RI.currententity->lerp->curstate.frame, f, frame ); - //Msg( "%f %f %f\n", RI.currententity->angles[ROLL], RI.currententity->angles[PITCH], RI.currententity->angles[YAW] ); - //Msg( "frame %d %d\n", frame1, frame2 ); - - dadt = R_StudioEstimateInterpolant(); - s = (f - frame); - - // add in programtic controllers - pbone = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); - - R_StudioCalcBoneAdj( dadt, adj, pstudio->lerp->curstate.controller, pstudio->lerp->latched.prevcontroller, pstudio->lerp->mouth.mouthopen ); - - for( i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++ ) - { - R_StudioCalcBoneQuaterion( frame, s, pbone, panim, adj, q[i] ); - R_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] ); - // if( 0 && i == 0 ) Msg( "%d %d %d %d\n", RI.currententity->lerp->curstate.sequence, frame, j, k ); - } - - if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f; - if( pseqdesc->motiontype & STUDIO_Y ) pos[pseqdesc->motionbone][1] = 0.0f; - if( pseqdesc->motiontype & STUDIO_Z ) pos[pseqdesc->motionbone][2] = 0.0f; - - // FIXME: enable this ? Half-Life 2 get rid of this code - s = 0 * ((1.0f - (f - (int)(f))) / (pseqdesc->numframes)) * RI.currententity->framerate; - - if( pseqdesc->motiontype & STUDIO_LX ) pos[pseqdesc->motionbone][0] += s * pseqdesc->linearmovement[0]; - if( pseqdesc->motiontype & STUDIO_LY ) pos[pseqdesc->motionbone][1] += s * pseqdesc->linearmovement[1]; - if( pseqdesc->motiontype & STUDIO_LZ ) pos[pseqdesc->motionbone][2] += s * pseqdesc->linearmovement[2]; -} - -/* -==================== -StudioEstimateFrame - -==================== -*/ -float R_StudioEstimateFrame( mstudioseqdesc_t *pseqdesc ) -{ - double dfdt, f; - - if( m_fDoInterp ) - { - if( RI.refdef.time < RI.currententity->lerp->curstate.animtime ) dfdt = 0; - else dfdt = (RI.refdef.time - RI.currententity->lerp->curstate.animtime) * RI.currententity->framerate * pseqdesc->fps; - } - else dfdt = 0; - - if( pseqdesc->numframes <= 1 ) f = 0.0; - else f = (RI.currententity->lerp->curstate.frame * (pseqdesc->numframes - 1)) / 256.0; - - f += dfdt; - - if( pseqdesc->flags & STUDIO_LOOPING ) - { - if( pseqdesc->numframes > 1 ) f -= (int)(f / (pseqdesc->numframes - 1)) * (pseqdesc->numframes - 1); - if( f < 0 ) f += (pseqdesc->numframes - 1); - } - else - { - if( f >= pseqdesc->numframes - 1.001 ) f = pseqdesc->numframes - 1.001; - if( f < 0.0 ) f = 0.0; - } - return f; -} - -/* -==================== -StudioFxTransform - -==================== -*/ -void R_StudioFxTransform( cl_entity_t *ent, matrix4x4 transform ) -{ - switch( ent->curstate.renderfx ) - { - case kRenderFxDistort: - case kRenderFxHologram: - if(!Com_RandomLong( 0, 49 )) - { - int axis = Com_RandomLong( 0, 1 ); - float scale = Com_RandomFloat( 1, 1.484 ); - - if( axis == 1 ) axis = 2; // choose between x & z -#ifdef OPENGL_STYLE - transform[0][axis] *= scale; - transform[1][axis] *= scale; - transform[2][axis] *= scale; -#else - transform[axis][0] *= scale; - transform[axis][1] *= scale; - transform[axis][2] *= scale; -#endif - } - else if(!Com_RandomLong( 0, 49 )) - { - float offset; - int axis = Com_RandomLong( 0, 1 ); - if( axis == 1 ) axis = 2; // choose between x & z - offset = Com_RandomFloat( -10, 10 ); -#ifdef OPENGL_STYLE - transform[3][Com_RandomLong( 0, 2 )] += offset; -#else - transform[Com_RandomLong( 0, 2 )][3] += offset; -#endif - } - break; - case kRenderFxExplode: - { - float scale; - - scale = 1.0f + ( RI.refdef.time - ent->curstate.animtime ) * 10.0f; - if( scale > 2 ) scale = 2; // don't blow up more than 200% -#ifdef OPENGL_STYLE - transform[1][0] *= scale; - transform[1][1] *= scale; - transform[1][2] *= scale; -#else - transform[0][1] *= scale; - transform[1][1] *= scale; - transform[2][1] *= scale; -#endif - } - break; - } -} - -/* -==================== -StudioSetupBones - -==================== -*/ -void R_StudioSetupBones( ref_entity_t *e ) -{ - int i; - double f; - - mstudiobone_t *pbones; - mstudioseqdesc_t *pseqdesc; - mstudioanim_t *panim; - studiovars_t *pstudio; - - static float pos[MAXSTUDIOBONES][3]; - static vec4_t q[MAXSTUDIOBONES]; - matrix4x4 bonematrix; - - static float pos2[MAXSTUDIOBONES][3]; - static vec4_t q2[MAXSTUDIOBONES]; - static float pos3[MAXSTUDIOBONES][3]; - static vec4_t q3[MAXSTUDIOBONES]; - static float pos4[MAXSTUDIOBONES][3]; - static vec4_t q4[MAXSTUDIOBONES]; - - ASSERT( e->model && e->model->extradata ); - - // bones already cached for this frame - if( e->m_nCachedFrameCount == r_framecount2 ) - return; - - RI.currententity = e; - if( e->lerp->curstate.sequence >= m_pStudioHeader->numseq ) e->lerp->curstate.sequence = 0; - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + e->lerp->curstate.sequence; - - f = R_StudioEstimateFrame( pseqdesc ); - -// if( e->lerp->curstate.frame > f ) Msg( "%f %f\n", e->lerp->curstate.frame, f ); - - pstudio = e->extradata; - ASSERT( pstudio ); - - panim = R_StudioGetAnim( e->model, pseqdesc ); - R_StudioCalcRotations( pos, q, pseqdesc, panim, f ); - - if( pseqdesc->numblends > 1 ) - { - float s; - float dadt; - - panim += m_pStudioHeader->numbones; - R_StudioCalcRotations( pos2, q2, pseqdesc, panim, f ); - - dadt = R_StudioEstimateInterpolant(); - s = (pstudio->lerp->curstate.blending[0] * dadt + pstudio->lerp->latched.prevblending[0] * (1.0 - dadt)) / 255.0; - - R_StudioSlerpBones( q, pos, q2, pos2, s ); - - if( pseqdesc->numblends == 4 ) - { - panim += m_pStudioHeader->numbones; - R_StudioCalcRotations( pos3, q3, pseqdesc, panim, f ); - - panim += m_pStudioHeader->numbones; - R_StudioCalcRotations( pos4, q4, pseqdesc, panim, f ); - - s = (pstudio->lerp->curstate.blending[0] * dadt + pstudio->lerp->latched.prevblending[0] * (1.0 - dadt)) / 255.0; - R_StudioSlerpBones( q3, pos3, q4, pos4, s ); - - s = (pstudio->lerp->curstate.blending[1] * dadt + pstudio->lerp->latched.prevblending[1] * (1.0 - dadt)) / 255.0; - R_StudioSlerpBones( q, pos, q3, pos3, s ); - } - } - - if( m_fDoInterp && pstudio->lerp->latched.sequencetime && ( pstudio->lerp->latched.sequencetime + 0.2 > RI.refdef.time) && ( pstudio->lerp->latched.prevsequence < m_pStudioHeader->numseq )) - { - // blend from last sequence - static float pos1b[MAXSTUDIOBONES][3]; - static vec4_t q1b[MAXSTUDIOBONES]; - float s; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pstudio->lerp->latched.prevsequence; - panim = R_StudioGetAnim( e->model, pseqdesc ); - - // clip prevframe - R_StudioCalcRotations( pos1b, q1b, pseqdesc, panim, pstudio->lerp->latched.prevframe ); - - if( pseqdesc->numblends > 1 ) - { - panim += m_pStudioHeader->numbones; - R_StudioCalcRotations( pos2, q2, pseqdesc, panim, pstudio->lerp->latched.prevframe ); - - s = (pstudio->lerp->latched.prevseqblending[0]) / 255.0; - R_StudioSlerpBones( q1b, pos1b, q2, pos2, s ); - - if( pseqdesc->numblends == 4 ) - { - panim += m_pStudioHeader->numbones; - R_StudioCalcRotations( pos3, q3, pseqdesc, panim, pstudio->lerp->latched.prevframe ); - - panim += m_pStudioHeader->numbones; - R_StudioCalcRotations( pos4, q4, pseqdesc, panim, pstudio->lerp->latched.prevframe ); - - s = (pstudio->lerp->latched.prevseqblending[0]) / 255.0; - R_StudioSlerpBones( q3, pos3, q4, pos4, s ); - - s = (pstudio->lerp->latched.prevseqblending[1]) / 255.0; - R_StudioSlerpBones( q1b, pos1b, q3, pos3, s ); - } - } - - s = 1.0f - ( RI.refdef.time - pstudio->lerp->latched.sequencetime ) / 0.2f; - R_StudioSlerpBones( q, pos, q1b, pos1b, s ); - } - else - { - // store prevframe otherwise - //Msg( "prevframe = %4.2f\n", f ); - pstudio->lerp->latched.prevframe = f; - } - - pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); - - // calc gait animation - if( m_pPlayerInfo && m_pPlayerInfo->gaitsequence != 0 ) - { - if( m_pPlayerInfo->gaitsequence >= m_pStudioHeader->numseq ) - m_pPlayerInfo->gaitsequence = 0; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pPlayerInfo->gaitsequence; - - panim = R_StudioGetAnim( e->model, pseqdesc ); - R_StudioCalcRotations( pos2, q2, pseqdesc, panim, m_pPlayerInfo->gaitframe ); - - for( i = 0; i < m_pStudioHeader->numbones; i++ ) - { - // g-cont. hey, what a hell ? - if( !com.strcmp( pbones[i].name, "Bip01 Spine" )) - break; - Mem_Copy( pos[i], pos2[i], sizeof( pos[i] )); - Mem_Copy( q[i], q2[i], sizeof( q[i] )); - } - } - - for( i = 0; i < m_pStudioHeader->numbones; i++ ) - { - Matrix4x4_FromOriginQuat( bonematrix, pos[i][0], pos[i][1], pos[i][2], q[i][0], q[i][1], q[i][2], q[i][3] ); - if( pbones[i].parent == -1 ) - { - Matrix4x4_ConcatTransforms( m_pbonestransform[i], m_protationmatrix, bonematrix ); - - // apply client-side effects to the transformation matrix - R_StudioFxTransform( e->lerp, m_pbonestransform[i] ); - } - else Matrix4x4_ConcatTransforms( m_pbonestransform[i], m_pbonestransform[pbones[i].parent], bonematrix ); - } -} - -/* -==================== -StudioSaveBones - -==================== -*/ -static void R_StudioSaveBones( ref_entity_t *e ) -{ - mstudiobone_t *pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); - int i; - - for( i = 0; i < m_pStudioHeader->numbones; i++ ) - com.strncpy( ((studiovars_t *)e->extradata)->bonenames[i], pbones[i].name, 32 ); -} - -/* -==================== -StudioMergeBones - -==================== -*/ -void R_StudioMergeBones( ref_entity_t *e, ref_model_t *m_pSubModel ) -{ - int i, j; - double f; - int sequence = e->lerp->curstate.sequence; - mstudiobone_t *pbones; - mstudioseqdesc_t *pseqdesc; - mstudioanim_t *panim; - studiovars_t *pstudio; - matrix4x4 bonematrix; - static vec4_t q[MAXSTUDIOBONES]; - static float pos[MAXSTUDIOBONES][3]; - static matrix4x4 localbones[MAXSTUDIOBONES]; - cl_entity_t *cl_entity; - - ASSERT( e->parent ); - cl_entity = e->parent->lerp; // FIXME: rename lerp to cl_ent - pstudio = ((studiovars_t *)e->extradata); - - ASSERT( pstudio ); - Mem_Copy( localbones, pstudio->bonestransform, sizeof( matrix4x4 ) * pstudio->numbones ); - - pstudio = ((studiovars_t *)e->parent->extradata); - - // weaponmodel can't change e->sequence! - if( sequence >= m_pStudioHeader->numseq ) sequence = 0; - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + sequence; - - f = R_StudioEstimateFrame( pseqdesc ); - -// if( e->lerp->curstate.frame > f ) Msg( "%f %f\n", e->lerp->latched.prevframe, f ); - - panim = R_StudioGetAnim( m_pSubModel, pseqdesc ); - R_StudioCalcRotations( pos, q, pseqdesc, panim, f ); - pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); - - for( i = 0; i < m_pStudioHeader->numbones; i++ ) - { - for( j = 0; j < pstudio->numbones; j++ ) - { - if( !com.stricmp( pbones[i].name, pstudio->bonenames[j] )) - { - Matrix4x4_Copy( localbones[i], pstudio->bonestransform[j] ); - break; - } - } - if( j >= pstudio->numbones ) - { - Matrix4x4_FromOriginQuat( bonematrix, pos[i][0], pos[i][1], pos[i][2], q[i][0], q[i][1], q[i][2], q[i][3] ); - if( pbones[i].parent == -1 ) - { - Matrix4x4_ConcatTransforms( localbones[i], m_protationmatrix, bonematrix ); - - // apply client-side effects to the transformation matrix - R_StudioFxTransform( cl_entity, m_pbonestransform[i] ); - } - else Matrix4x4_ConcatTransforms( localbones[i], m_pbonestransform[pbones[i].parent], bonematrix ); - } - } - - pstudio = ((studiovars_t *)e->extradata); - ASSERT( pstudio ); - - // copy bones back to the merged entity - Mem_Copy( pstudio->bonestransform, localbones, sizeof( matrix4x4 ) * m_pStudioHeader->numbones ); -} - - -/* -==================== -StudioCalcAttachments - -==================== -*/ -static void R_StudioCalcAttachments( ref_entity_t *e ) -{ - int i; - matrix4x4 out; - mstudioattachment_t *pAtt; - vec3_t axis[3]; - vec3_t localOrg, localAng, bonepos; - - if( m_pStudioHeader->numattachments <= 0 ) - { - // clear attachments - for( i = 0; i < MAXSTUDIOATTACHMENTS; i++ ) - VectorClear( e->lerp->attachment[i] ); - return; - } - else if( m_pStudioHeader->numattachments > MAXSTUDIOATTACHMENTS ) - { - m_pStudioHeader->numattachments = MAXSTUDIOATTACHMENTS; // reduce it - MsgDev( D_WARN, "R_StudioCalcAttahments: too many attachments on %s\n", e->model->name ); - } - - // calculate attachment points - pAtt = (mstudioattachment_t *)((byte *)m_pStudioHeader + m_pStudioHeader->attachmentindex); - for( i = 0; i < m_pStudioHeader->numattachments; i++ ) - { - // NOTE: m_pbonestransform not contained rotate component so we need do it here - Matrix4x4_Concat( out, ((studiovars_t *)e->extradata)->rotationmatrix, m_pbonestransform[pAtt[i].bone] ); - - // compute pos and angles - Matrix4x4_VectorTransform( out, pAtt[i].org, localOrg ); - Matrix4x4_OriginFromMatrix( out, bonepos ); - VectorSubtract( localOrg, bonepos, axis[0] ); // make forward - VectorNormalizeFast( axis[0] ); - VectorVectors( axis[0], axis[1], axis[2] ); // make right and up - - Matrix3x3_ToAngles( axis, localAng, false ); // FIXME: dll's uses FLU ? - - VectorAdd( e->lerp->origin, localOrg, e->lerp->attachment[i] ); - } -} - -qboolean R_StudioComputeBBox( vec3_t bbox[8] ) -{ - vec3_t tmp_mins, tmp_maxs; - ref_entity_t *e = RI.currententity; - vec3_t vectors[3], angles, p1, p2; - int i, seq = e->lerp->curstate.sequence; - - if( !R_StudioExtractBbox( m_pStudioHeader, seq, tmp_mins, tmp_maxs )) - return false; - - // copy original bbox - VectorCopy( m_pStudioHeader->bbmin, studio_mins ); - VectorCopy( m_pStudioHeader->bbmin, studio_mins ); - - // rotate the bounding box - VectorScale( e->angles, -1, angles ); - - if( e->ent_type == ET_PLAYER ) - angles[PITCH] = 0; // don't rotate player model, only aim - AngleVectorsFLU( angles, vectors[0], vectors[1], vectors[2] ); - - // compute a full bounding box - for( i = 0; i < 8; i++ ) - { - p1[0] = ( i & 1 ) ? tmp_mins[0] : tmp_maxs[0]; - p1[1] = ( i & 2 ) ? tmp_mins[1] : tmp_maxs[1]; - p1[2] = ( i & 4 ) ? tmp_mins[2] : tmp_maxs[2]; - - p2[0] = DotProduct( p1, vectors[0] ); - p2[1] = DotProduct( p1, vectors[1] ); - p2[2] = DotProduct( p1, vectors[2] ); - - if( bbox ) VectorCopy( p2, bbox[i] ); - - if( p2[0] < studio_mins[0] ) studio_mins[0] = p2[0]; - if( p2[0] > studio_maxs[0] ) studio_maxs[0] = p2[0]; - if( p2[1] < studio_mins[1] ) studio_mins[1] = p2[1]; - if( p2[1] > studio_maxs[1] ) studio_maxs[1] = p2[1]; - if( p2[2] < studio_mins[2] ) studio_mins[2] = p2[2]; - if( p2[2] > studio_maxs[2] ) studio_maxs[2] = p2[2]; - } - - studio_radius = RadiusFromBounds( studio_mins, studio_maxs ) * e->scale; - - return true; -} - -/* -==================== -StudioSetupSubModel - -==================== -*/ -static void R_StudioSetupSubModel( int body, int bodypart ) -{ - int index; - - if( bodypart > m_pStudioHeader->numbodyparts ) bodypart = 0; - m_pBodyPart = (mstudiobodyparts_t *)((byte *)m_pStudioHeader + m_pStudioHeader->bodypartindex) + bodypart; - - index = body / m_pBodyPart->base; - index = index % m_pBodyPart->nummodels; - - m_pSubModel = (mstudiomodel_t *)((byte *)m_pStudioHeader + m_pBodyPart->modelindex) + index; -} - -void R_StudioSetupChrome( float *pchrome, int modelnum, int bone, float *normal ) -{ - float n; - - if( m_pchromeage[bone] != ( r_framecount2 + modelnum )) - { - vec3_t chromeupvec; // g_chrome t vector in world reference frame - vec3_t chromerightvec; // g_chrome s vector in world reference frame - vec3_t tmp; // vector pointing at bone in world reference frame - vec3_t v_right = { 0, -1, 0 }; // inverse right vector - - // calculate vectors from the viewer to the bone. This roughly adjusts for position - Matrix4x4_OriginFromMatrix( m_pbonestransform[bone], tmp ); - VectorNormalize( tmp ); - CrossProduct( tmp, v_right, chromeupvec ); - - VectorNormalize( chromeupvec ); - CrossProduct( tmp, chromeupvec, chromerightvec ); - VectorNormalize( chromerightvec ); - - Matrix4x4_VectorIRotate( m_pbonestransform[bone], chromeupvec, m_pchromeup[bone] ); - Matrix4x4_VectorIRotate( m_pbonestransform[bone], chromerightvec, m_pchromeright[bone] ); - m_pchromeage[bone] = (r_framecount2+modelnum); - } - - // calc s coord - n = DotProduct( normal, m_pchromeright[bone] ); - pchrome[0] = (n + 1.0f) * 32.0f; - - // calc t coord - n = DotProduct( normal, m_pchromeup[bone] ); - pchrome[1] = (n + 1.0f) * 32.0f; -} - -void R_StudioDrawMesh( const meshbuffer_t *mb, short *ptricmds, float s, float t, int features, int flags ) -{ - int i; - float *av, *lv; - ref_shader_t *shader; - - MB_NUM2SHADER( mb->shaderkey, shader ); - - while( i = *( ptricmds++ )) - { - int vertexState = 0; - qboolean tri_strip; - - if( i < 0 ) - { - i = -i; - tri_strip = false; - } - else tri_strip = true; - - for( ; i > 0; i--, ptricmds += 4 ) - { - if( r_backacc.numVerts + 256 > MAX_ARRAY_VERTS || r_backacc.numElems + 784 > MAX_ARRAY_ELEMENTS ) - { - MsgDev( D_ERROR, "StudioDrawMesh: %s has too many vertices per submodel ( %i )\n", RI.currentmodel->name, r_backacc.numVerts ); - goto render_now; - } - - if( vertexState++ < 3 ) - { - inElemsArray[r_backacc.numElems++] = r_backacc.numVerts; - } - else if( tri_strip ) - { - // flip triangles between clockwise and counter clockwise - if( vertexState & 1 ) - { - // draw triangle [n-2 n-1 n] - inElemsArray[r_backacc.numElems++] = r_backacc.numVerts - 2; - inElemsArray[r_backacc.numElems++] = r_backacc.numVerts - 1; - inElemsArray[r_backacc.numElems++] = r_backacc.numVerts; - } - else - { - // draw triangle [n-1 n-2 n] - inElemsArray[r_backacc.numElems++] = r_backacc.numVerts - 1; - inElemsArray[r_backacc.numElems++] = r_backacc.numVerts - 2; - inElemsArray[r_backacc.numElems++] = r_backacc.numVerts; - } - } - else - { - // draw triangle fan [0 n-1 n] - inElemsArray[r_backacc.numElems++] = r_backacc.numVerts - ( vertexState - 1 ); - inElemsArray[r_backacc.numElems++] = r_backacc.numVerts - 1; - inElemsArray[r_backacc.numElems++] = r_backacc.numVerts; - } - - if( flags & STUDIO_NF_CHROME ) - Vector2Set( inCoordsArray[r_backacc.numVerts], m_pchrome[ptricmds[1]][0] * s, m_pchrome[ptricmds[1]][1] * t ); - else Vector2Set( inCoordsArray[r_backacc.numVerts], ptricmds[2] * s, ptricmds[3] * t ); - - if( features & MF_NORMALS ) - { - lv = m_pxformnorms[ptricmds[1]]; // normals - Vector4Set( inNormalsArray[r_backacc.numVerts], lv[0], lv[1], lv[2], 1.0f ); - } - - av = m_pxformverts[ptricmds[0]]; // verts - Vector4Set( inVertsArray[r_backacc.numVerts], av[0], av[1], av[2], 1.0f ); - r_backacc.c_totalVerts++; // r_speeds issues - r_backacc.numVerts++; - } - } -render_now: - if( features & MF_SVECTORS ) - R_BuildTangentVectors( r_backacc.numVerts, inVertsArray, inNormalsArray, inCoordsArray, r_backacc.numElems / 3, inElemsArray, inSVectorsArray ); - - R_StudioSetUpTransform( RI.currententity, true ); - r_features = features; - R_RenderMeshBuffer( mb ); -} - -void R_StudioDrawBones( void ) -{ - mstudiobone_t *pbones = (mstudiobone_t *) ((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); - vec3_t point; - int i; - - for( i = 0; i < m_pStudioHeader->numbones; i++ ) - { - if( pbones[i].parent >= 0 ) - { - pglPointSize( 3.0f ); - pglColor3f( 1, 0.7f, 0 ); - pglBegin( GL_LINES ); - - Matrix4x4_OriginFromMatrix( m_pbonestransform[pbones[i].parent], point ); - pglVertex3fv( point ); - Matrix4x4_OriginFromMatrix( m_pbonestransform[i], point ); - pglVertex3fv( point ); - - pglEnd(); - - pglColor3f( 0, 0, 0.8f ); - pglBegin( GL_POINTS ); - if( pbones[pbones[i].parent].parent != -1 ) - { - Matrix4x4_OriginFromMatrix( m_pbonestransform[pbones[i].parent], point ); - pglVertex3fv( point ); - } - Matrix4x4_OriginFromMatrix( m_pbonestransform[i], point ); - pglVertex3fv( point ); - pglEnd(); - } - else - { - // draw parent bone node - pglPointSize( 5.0f ); - pglColor3f( 0.8f, 0, 0 ); - pglBegin( GL_POINTS ); - Matrix4x4_OriginFromMatrix( m_pbonestransform[i], point ); - pglVertex3fv( point ); - pglEnd(); - } - } - pglPointSize( 1.0f ); -} - -void R_StudioDrawHitboxes( int iHitbox ) -{ - int i, j; - - pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); - - for( i = 0; i < m_pStudioHeader->numhitboxes; i++ ) - { - mstudiobbox_t *pbboxes = (mstudiobbox_t *)((byte *)m_pStudioHeader + m_pStudioHeader->hitboxindex); - vec3_t v[8], v2[8], bbmin, bbmax; - - if( iHitbox >= 0 && iHitbox != i ) - continue; - - VectorCopy( pbboxes[i].bbmin, bbmin ); - VectorCopy( pbboxes[i].bbmax, bbmax ); - - v[0][0] = bbmin[0]; - v[0][1] = bbmax[1]; - v[0][2] = bbmin[2]; - - v[1][0] = bbmin[0]; - v[1][1] = bbmin[1]; - v[1][2] = bbmin[2]; - - v[2][0] = bbmax[0]; - v[2][1] = bbmax[1]; - v[2][2] = bbmin[2]; - - v[3][0] = bbmax[0]; - v[3][1] = bbmin[1]; - v[3][2] = bbmin[2]; - - v[4][0] = bbmax[0]; - v[4][1] = bbmax[1]; - v[4][2] = bbmax[2]; - - v[5][0] = bbmax[0]; - v[5][1] = bbmin[1]; - v[5][2] = bbmax[2]; - - v[6][0] = bbmin[0]; - v[6][1] = bbmax[1]; - v[6][2] = bbmax[2]; - - v[7][0] = bbmin[0]; - v[7][1] = bbmin[1]; - v[7][2] = bbmax[2]; - - Matrix4x4_VectorTransform( m_pbonestransform[pbboxes[i].bone], v[0], v2[0] ); - Matrix4x4_VectorTransform( m_pbonestransform[pbboxes[i].bone], v[1], v2[1] ); - Matrix4x4_VectorTransform( m_pbonestransform[pbboxes[i].bone], v[2], v2[2] ); - Matrix4x4_VectorTransform( m_pbonestransform[pbboxes[i].bone], v[3], v2[3] ); - Matrix4x4_VectorTransform( m_pbonestransform[pbboxes[i].bone], v[4], v2[4] ); - Matrix4x4_VectorTransform( m_pbonestransform[pbboxes[i].bone], v[5], v2[5] ); - Matrix4x4_VectorTransform( m_pbonestransform[pbboxes[i].bone], v[6], v2[6] ); - Matrix4x4_VectorTransform( m_pbonestransform[pbboxes[i].bone], v[7], v2[7] ); - - if( iHitbox >= 0 ) j = 0; - else j = (pbboxes[i].group % 8); - - // set properly color for hull - pglColor4f( hullcolor[j][0], hullcolor[j][1], hullcolor[j][2], 1.0f ); - - pglBegin( GL_QUAD_STRIP ); - for( j = 0; j < 10; j++ ) - pglVertex3fv( v2[j & 7] ); - pglEnd( ); - - pglBegin( GL_QUAD_STRIP ); - pglVertex3fv( v2[6] ); - pglVertex3fv( v2[0] ); - pglVertex3fv( v2[4] ); - pglVertex3fv( v2[2] ); - pglEnd( ); - - pglBegin( GL_QUAD_STRIP ); - pglVertex3fv( v2[1] ); - pglVertex3fv( v2[7] ); - pglVertex3fv( v2[3] ); - pglVertex3fv( v2[5] ); - pglEnd( ); - } - - pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); -} - -void R_StudioDrawAttachments( void ) -{ - int i; - - for( i = 0; i < m_pStudioHeader->numattachments; i++ ) - { - mstudioattachment_t *pattachments = (mstudioattachment_t *)((byte *)m_pStudioHeader + m_pStudioHeader->attachmentindex); - vec3_t v[4]; - - Matrix4x4_VectorTransform( m_pbonestransform[pattachments[i].bone], pattachments[i].org, v[0] ); - Matrix4x4_VectorTransform( m_pbonestransform[pattachments[i].bone], pattachments[i].vectors[0], v[1] ); - Matrix4x4_VectorTransform( m_pbonestransform[pattachments[i].bone], pattachments[i].vectors[1], v[2] ); - Matrix4x4_VectorTransform( m_pbonestransform[pattachments[i].bone], pattachments[i].vectors[2], v[3] ); - - pglBegin( GL_LINES ); - pglColor3f( 1, 0, 0 ); - pglVertex3fv( v[0] ); - pglColor3f( 1, 1, 1 ); - pglVertex3fv( v[1] ); - pglColor3f( 1, 0, 0 ); - pglVertex3fv( v[0] ); - pglColor3f( 1, 1, 1 ); - pglVertex3fv( v[2] ); - pglColor3f( 1, 0, 0 ); - pglVertex3fv( v[0] ); - pglColor3f( 1, 1, 1 ); - pglVertex3fv( v[3] ); - pglEnd( ); - - pglPointSize( 5.0f ); - pglColor3f( 0, 1, 0 ); - pglBegin( GL_POINTS ); - pglVertex3fv( v[0] ); - pglEnd( ); - pglPointSize( 1.0f ); - } -} - -void R_StudioDrawHulls( void ) -{ - int i; - vec3_t bbox[8]; - - // looks ugly, skip - if( RI.currententity->ent_type == ET_VIEWENTITY ) - return; - - if(!R_StudioComputeBBox( bbox )) return; - - pglColor4f( 1.0f, 0.0f, 0.0f, 1.0f ); // red bboxes for studiomodels - pglBegin( GL_LINES ); - for( i = 0; i < 2; i += 1 ) - { - pglVertex3fv( bbox[i+0] ); - pglVertex3fv( bbox[i+2] ); - pglVertex3fv( bbox[i+4] ); - pglVertex3fv( bbox[i+6] ); - pglVertex3fv( bbox[i+0] ); - pglVertex3fv( bbox[i+4] ); - pglVertex3fv( bbox[i+2] ); - pglVertex3fv( bbox[i+6] ); - pglVertex3fv( bbox[i*2+0] ); - pglVertex3fv( bbox[i*2+1] ); - pglVertex3fv( bbox[i*2+4] ); - pglVertex3fv( bbox[i*2+5] ); - } - pglEnd(); -} - -/* -==================== -StudioDrawDebug - -==================== -*/ -void R_StudioDrawDebug( void ) -{ - R_StudioSetupRender( RI.currententity, RI.currententity->model ); - R_StudioSetUpTransform( RI.currententity, true ); - - switch( r_drawentities->integer ) - { - case 2: R_StudioDrawBones(); break; - case 3: R_StudioDrawHitboxes(-1 ); break; - case 4: R_StudioDrawAttachments(); break; - case 5: R_StudioDrawHulls(); break; - } -} - -/* -==================== -StudioDrawHitbox - -render a selected hitbox -==================== -*/ -void R_StudioDrawHitbox( ref_entity_t *e, int iHitbox ) -{ - R_StudioSetupRender( e, e->model ); - R_StudioSetUpTransform( e, true ); - R_StudioDrawHitboxes( iHitbox ); -} - - -/* -==================== -StudioEstimateGait - -==================== -*/ -void R_StudioEstimateGait( ref_entity_t *e, entity_state_t *pplayer ) -{ - float dt; - vec3_t est_velocity; - studiovars_t *pstudio = (studiovars_t *)e->extradata; - - ASSERT( pstudio ); - dt = bound( 0.0f, RI.refdef.frametime, 1.0f ); - - if( dt == 0 || m_pPlayerInfo->renderframe == r_framecount2 ) - { - m_flGaitMovement = 0; - return; - } - - // VectorAdd( pplayer->v.velocity, pplayer->v.prediction_error, est_velocity ); - if( m_fGaitEstimation ) - { - VectorSubtract( e->origin, m_pPlayerInfo->prevgaitorigin, est_velocity ); - VectorCopy( e->origin, m_pPlayerInfo->prevgaitorigin ); - - m_flGaitMovement = VectorLength( est_velocity ); - if( dt <= 0 || m_flGaitMovement / dt < 5 ) - { - m_flGaitMovement = 0; - est_velocity[0] = 0; - est_velocity[1] = 0; - } - } - else - { - VectorCopy( pplayer->velocity, est_velocity ); - m_flGaitMovement = VectorLength( est_velocity ) * dt; - } - - if( est_velocity[1] == 0 && est_velocity[0] == 0 ) - { - float flYawDiff = e->angles[YAW] - m_pPlayerInfo->gaityaw; - - flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360; - if( flYawDiff > 180 ) flYawDiff -= 360; - if( flYawDiff < -180 ) flYawDiff += 360; - - if( dt < 0.25f ) flYawDiff *= dt * 4; - else flYawDiff *= dt; - - m_pPlayerInfo->gaityaw += flYawDiff; - m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - (int)(m_pPlayerInfo->gaityaw / 360) * 360; - m_flGaitMovement = 0; - } - else - { - m_pPlayerInfo->gaityaw = (atan2(est_velocity[1], est_velocity[0]) * 180 / M_PI); - if( m_pPlayerInfo->gaityaw > 180 ) m_pPlayerInfo->gaityaw = 180; - if( m_pPlayerInfo->gaityaw < -180 ) m_pPlayerInfo->gaityaw = -180; - } - -} - -/* -==================== -StudioProcessGait - -==================== -*/ -void R_StudioProcessGait( ref_entity_t *e, entity_state_t *pplayer, studiovars_t *pstudio ) -{ - mstudioseqdesc_t *pseqdesc; - float dt, flYaw; // view direction relative to movement - int iBlend; - - if( e->lerp->curstate.sequence >= m_pStudioHeader->numseq ) - e->lerp->curstate.sequence = 0; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + e->lerp->curstate.sequence; - R_StudioPlayerBlend( pseqdesc, &iBlend, &e->lerp->angles[PITCH] ); - - pstudio->lerp->latched.prevangles[PITCH] = e->angles[PITCH]; - pstudio->lerp->curstate.blending[0] = iBlend; - pstudio->lerp->latched.prevblending[0] = pstudio->lerp->curstate.blending[0]; - pstudio->lerp->latched.prevseqblending[0] = pstudio->lerp->curstate.blending[0]; - - //Msg( "%f %d\n", e->angles[PITCH], pstudio->lerp->curstate.blending[0] ); - - dt = bound( 0.0f, RI.refdef.frametime, 1.0f ); - - R_StudioEstimateGait( e, pplayer ); - - //Msg( "%f %f\n", e->angles[YAW], pstudio->lerp->gaityaw ); - - // calc side to side turning - flYaw = e->angles[YAW] - m_pPlayerInfo->gaityaw; - flYaw = flYaw - (int)(flYaw / 360) * 360; - if( flYaw < -180 ) flYaw = flYaw + 360; - if( flYaw > 180 ) flYaw = flYaw - 360; - - if( flYaw > 120 ) - { - m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - 180; - m_flGaitMovement = -m_flGaitMovement; - flYaw = flYaw - 180; - } - else if( flYaw < -120 ) - { - m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw + 180; - m_flGaitMovement = -m_flGaitMovement; - flYaw = flYaw + 180; - } - - // adjust torso - pstudio->lerp->curstate.controller[0] = ((flYaw / 4.0) + 30) / (60.0 / 255.0); - pstudio->lerp->curstate.controller[1] = ((flYaw / 4.0) + 30) / (60.0 / 255.0); - pstudio->lerp->curstate.controller[2] = ((flYaw / 4.0) + 30) / (60.0 / 255.0); - pstudio->lerp->curstate.controller[3] = ((flYaw / 4.0) + 30) / (60.0 / 255.0); - pstudio->lerp->latched.prevcontroller[0] = pstudio->lerp->curstate.controller[0]; - pstudio->lerp->latched.prevcontroller[1] = pstudio->lerp->curstate.controller[1]; - pstudio->lerp->latched.prevcontroller[2] = pstudio->lerp->curstate.controller[2]; - pstudio->lerp->latched.prevcontroller[3] = pstudio->lerp->curstate.controller[3]; - - e->angles[YAW] = m_pPlayerInfo->gaityaw; - if( e->angles[YAW] < -0 ) e->angles[YAW] += 360; - e->lerp->latched.prevangles[YAW] = e->angles[YAW]; - - if( pplayer->gaitsequence >= m_pStudioHeader->numseq ) - pplayer->gaitsequence = 0; - - pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pplayer->gaitsequence; - - // calc gait frame - if( pseqdesc->linearmovement[0] > 0 ) - { - m_pPlayerInfo->gaitframe += (m_flGaitMovement / pseqdesc->linearmovement[0]) * pseqdesc->numframes; - } - else - { - m_pPlayerInfo->gaitframe += pseqdesc->fps * dt; - } - - // do modulo - m_pPlayerInfo->gaitframe = m_pPlayerInfo->gaitframe - (int)(m_pPlayerInfo->gaitframe / pseqdesc->numframes) * pseqdesc->numframes; - if( m_pPlayerInfo->gaitframe < 0 ) m_pPlayerInfo->gaitframe += pseqdesc->numframes; -} - -static qboolean R_StudioSetupModel( ref_entity_t *e, ref_model_t *mod ) -{ - studiovars_t *pstudio = e->extradata; - int i, m_nPlayerIndex; - - if( e->m_nCachedFrameCount == r_framecount2 ) - return 1; - - ASSERT( pstudio ); - - // special handle for player model - if( e->ent_type == ET_PLAYER || e->renderfx == kRenderFxDeadPlayer ) - { - //Msg( "DrawPlayer %d\n", pstudio->lerp->blending[0] ); - //Msg( "DrawPlayer %d %d (%d)\n", r_framecount2, m_pEntity->serialnumber, e->lerp->curstate.sequence ); - //Msg( "Player %.2f %.2f %.2f\n", m_pEntity->v.velocity[0], m_pEntity->v.velocity[1], m_pEntity->v.velocity[2] ); - - if( e->renderfx == kRenderFxDeadPlayer ) - { - // prepare to draw dead player - if( m_pPlayerInfo ) m_pPlayerInfo->gaitsequence = 0; - } - - if( !m_pPlayerInfo ) return 0; - m_nPlayerIndex = e->index - 1; - - if( m_nPlayerIndex < 0 || m_nPlayerIndex >= ri.GetMaxClients( )) - return 0; // weird client ? - - if( e->gaitsequence ) - { - vec3_t orig_angles; - - VectorCopy( e->angles, orig_angles ); - - R_StudioProcessGait( e, &e->lerp->curstate, pstudio ); - m_pPlayerInfo->gaitsequence = e->gaitsequence; -// m_pPlayerInfo = NULL; - - R_StudioSetUpTransform ( e, false ); - VectorCopy( orig_angles, e->angles ); - } - else - { - for( i = 0; i < 4; i++ ) // clear torso controllers - pstudio->lerp->latched.prevcontroller[i] = pstudio->lerp->curstate.controller[i] = 0x7F; - m_pPlayerInfo->gaitsequence = 0; // StudioSetupBones() issuses - - R_StudioSetUpTransform ( e, false ); - } - - - if( r_himodels->integer ) e->body = 255; // show highest resolution multiplayer model - if( !( glw_state.developer == 0 && ri.GetMaxClients() == 1 )) e->body = 1; // force helmet - - } - else R_StudioSetUpTransform ( e, false ); - - if( e->movetype == MOVETYPE_FOLLOW && e->parent ) - { - R_StudioMergeBones( e, mod ); - } - else - { - R_StudioSetupBones( e ); - R_StudioSaveBones( e ); - } - - if( e->movetype != MOVETYPE_FOLLOW && !RI.refdef.paused && e->m_nCachedFrameCount != r_framecount2 ) - { - R_StudioCalcAttachments( e ); - R_StudioProcessEvents( e, e->lerp ); - } - - e->m_nCachedFrameCount = r_framecount2; // cached frame - if( m_pPlayerInfo ) m_pPlayerInfo->renderframe = r_framecount2; - - return 1; -} - -void R_StudioDrawPoints( const meshbuffer_t *mb, ref_entity_t *e ) -{ - int i, j, m_skinnum = RI.currententity->skin; - int modelnum = ((-mb->infokey - 1) & 0xFF); - int meshnum = (((-mb->infokey - 1) & 0xFF00)>>8); - ref_model_t *model = Mod_ForHandle( mb->modhandle ); - vec3_t *pstudioverts, *pstudionorms; - byte *pvertbone, *pnormbone; - short *pskinref, *ptricmds; - int flags, features; - mstudiotexture_t *ptexture; - studiovars_t *studio; - mstudiomesh_t *pmesh; - ref_shader_t *shader; - float s, t; - - MB_NUM2SHADER( mb->shaderkey, shader ); - - R_StudioSetupRender( e, model ); - R_StudioSetupSubModel( RI.currententity->body, modelnum ); - - if( meshnum > m_pSubModel->nummesh ) return; // invalid mesh - - // setup all mesh pointers - pstudioverts = (vec3_t *)((byte *)m_pStudioHeader + m_pSubModel->vertindex); - pstudionorms = (vec3_t *)((byte *)m_pStudioHeader + m_pSubModel->normindex); - pvertbone = ((byte *)m_pStudioHeader + m_pSubModel->vertinfoindex); - pnormbone = ((byte *)m_pStudioHeader + m_pSubModel->norminfoindex); - pmesh = (mstudiomesh_t *)((byte *)m_pStudioHeader + m_pSubModel->meshindex) + meshnum; - ptexture = (mstudiotexture_t *)((byte *)m_pTextureHeader + m_pTextureHeader->textureindex); - pskinref = (short *)((byte *)m_pTextureHeader + m_pTextureHeader->skinindex); - ptricmds = (short *)((byte *)m_pStudioHeader + pmesh->triindex); - if( m_skinnum != 0 && m_skinnum < m_pTextureHeader->numskinfamilies ) - pskinref += (m_skinnum * m_pTextureHeader->numskinref); - s = 1.0f / (float)ptexture[pskinref[pmesh->skinref]].width; - t = 1.0f / (float)ptexture[pskinref[pmesh->skinref]].height; - flags = ptexture[pskinref[pmesh->skinref]].flags; - studio = (studiovars_t *)e->extradata; - - // detect mesh features - features = MF_NONBATCHED | shader->features; - if( RI.params & RP_SHADOWMAPVIEW ) - { - features &= ~( MF_COLORS|MF_SVECTORS|MF_ENABLENORMALS ); - if(!( shader->features & MF_DEFORMVS )) - features &= ~MF_NORMALS; - } - else - { - if(( features & MF_SVECTORS ) || r_shownormals->integer ) - features |= MF_NORMALS; - } - - ASSERT( studio ); - - // initialize vertex cache - if( !studio->mesh[modelnum] ) - studio->mesh[modelnum] = Mem_Alloc( e->mempool, sizeof( studioverts_t )); - - if( studio->mesh[modelnum]->numverts != m_pSubModel->numverts ) - studio->mesh[modelnum]->verts = Mem_Realloc( e->mempool, studio->mesh[modelnum]->verts, sizeof( vec3_t ) * m_pSubModel->numverts ); - - if( studio->mesh[modelnum]->numnorms != m_pSubModel->numnorms ) - { - studio->mesh[modelnum]->norms = Mem_Realloc( e->mempool, studio->mesh[modelnum]->norms, sizeof( vec3_t ) * m_pSubModel->numnorms ); - studio->mesh[modelnum]->chrome = Mem_Realloc( e->mempool, studio->mesh[modelnum]->chrome, sizeof( vec2_t ) * m_pSubModel->numnorms ); - } - - studio->mesh[modelnum]->numverts = m_pSubModel->numverts; - studio->mesh[modelnum]->numnorms = m_pSubModel->numnorms; - - m_pxformverts = studio->mesh[modelnum]->verts; - m_pxformnorms = studio->mesh[modelnum]->norms; - m_pxformlight = studio->mesh[modelnum]->light; - m_pchrome = studio->mesh[modelnum]->chrome; - - // cache transforms - if( studio->mesh[modelnum]->m_nCachedFrame != r_framecount2 ) - { - mstudiomesh_t *pmesh = (mstudiomesh_t *)((byte *)m_pStudioHeader + m_pSubModel->meshindex); - float *lv = (float *)m_pxformlight; - int vertspermesh = 0; - - for( i = 0; i < m_pSubModel->numverts; i++ ) - Matrix4x4_VectorTransform( m_pbonestransform[pvertbone[i]], pstudioverts[i], m_pxformverts[i] ); - - for( i = 0; ( i < m_pSubModel->numnorms ) && ( features & MF_NORMALS ); i++ ) - { - Matrix4x4_VectorRotate( m_pbonestransform[pnormbone[i]], pstudionorms[i], m_pxformnorms[i] ); - } - - if( m_pStudioHeader->flags & STUDIO_HAS_CHROME ) - { - for( i = 0; i < m_pSubModel->nummesh; i++ ) - { - int texflags = ptexture[pskinref[pmesh[i].skinref]].flags; - - for( j = 0; j < pmesh[i].numnorms; j++, lv += 3, pstudionorms++, pnormbone++ ) - { - if(!( texflags & STUDIO_NF_CHROME )) continue; - R_StudioSetupChrome( m_pchrome[(float (*)[3])lv - m_pxformlight], modelnum, *pnormbone, (float *)pstudionorms ); - } - } - } - studio->mesh[modelnum]->m_nCachedFrame = r_framecount2; - } - - R_StudioDrawMesh( mb, ptricmds, s, t, features, flags ); -} - -void R_DrawStudioModel( const meshbuffer_t *mb ) -{ - ref_entity_t *e; - int meshnum = -mb->infokey - 1; - - MB_NUM2ENTITY( mb->sortkey, e ); - - if( OCCLUSION_QUERIES_ENABLED( RI ) && OCCLUSION_TEST_ENTITY( e )) - { - ref_shader_t *shader; - - MB_NUM2SHADER( mb->shaderkey, shader ); - if( !R_GetOcclusionQueryResultBool( shader->type == 1 ? OQ_PLANARSHADOW : OQ_ENTITY, e - r_entities, true )) - return; - } - - // hack the depth range to prevent view model from poking into walls - if( e->ent_type == ET_VIEWENTITY ) - { - pglDepthRange( gldepthmin, gldepthmin + 0.3 * ( gldepthmax - gldepthmin ) ); - - // backface culling for left-handed weapons - if( r_lefthand->integer == 1 ) GL_FrontFace( !glState.frontFace ); - } - - R_StudioDrawPoints( mb, e ); - - if( e->ent_type == ET_VIEWENTITY ) - { - pglDepthRange( gldepthmin, gldepthmax ); - - // backface culling for left-handed weapons - if( r_lefthand->integer == 1 ) GL_FrontFace( !glState.frontFace ); - } -} - -qboolean R_CullStudioModel( ref_entity_t *e ) -{ - int i, j, clipped; - int sequence; - qboolean frustum, query; - uint modhandle; - mstudiotexture_t *ptexture; - short *pskinref; - meshbuffer_t *mb; - - if( !e->model->extradata ) - return true; - - if( e->ent_type == ET_VIEWENTITY && r_lefthand->integer >= 2 ) - return true; // hidden - - modhandle = Mod_Handle( e->model ); - - if( RP_FOLLOWENTITY( e )) - { - // cull child entities with parent volume - R_StudioSetupRender( e->parent, e->parent->model ); - sequence = e->parent->lerp->curstate.sequence; - } - else - { - R_StudioSetupRender( e, e->model ); - sequence = e->lerp->curstate.sequence; - } - - if( !R_StudioComputeBBox( NULL )) - return true; // invalid sequence - - clipped = R_CullModel( e, studio_mins, studio_maxs, studio_radius ); - frustum = clipped & 1; - if( clipped & 2 ) return true; - - query = OCCLUSION_QUERIES_ENABLED( RI ) && OCCLUSION_TEST_ENTITY( e ) ? true : false; - if( !frustum && query ) R_IssueOcclusionQuery( R_GetOcclusionQueryNum( OQ_ENTITY, e - r_entities ), e, studio_mins, studio_maxs ); - - if( !RI.drawWorld || ( r_shadows->integer != 1 ) || R_CullPlanarShadow( e, studio_mins, studio_maxs, query )) - return frustum; // entity is not in PVS or shadow is culled away by frustum culling - - R_StudioSetupRender( e, e->model ); - - // setup bones, play events etc - R_StudioSetupModel( e, e->model ); - - // add it - ptexture = (mstudiotexture_t *)((byte *)m_pTextureHeader + m_pTextureHeader->textureindex); - for( i = 0; i < m_pStudioHeader->numbodyparts; i++ ) - { - R_StudioSetupSubModel( RI.currententity->body, i ); - pskinref = (short *)((byte *)m_pTextureHeader + m_pTextureHeader->skinindex); - if( e->skin != 0 && e->skin < m_pTextureHeader->numskinfamilies ) - pskinref += (e->skin * m_pTextureHeader->numskinref); - - for( j = 0; j < m_pSubModel->nummesh; j++ ) - { - ref_shader_t *shader; - mstudiomesh_t *pmesh; - - pmesh = (mstudiomesh_t *)((byte *)m_pStudioHeader + m_pSubModel->meshindex) + j; - if( e->customShader ) shader = e->customShader; - else shader = &r_shaders[ptexture[pskinref[pmesh->skinref]].index]; - - if( shader && ( shader->sort <= SORT_ALPHATEST )) - { - mb = R_AddMeshToList( MB_MODEL, NULL, R_PlanarShadowShader(), -(((j<<8)|i)+1 )); - if( mb ) mb->modhandle = modhandle; - } - } - } - return frustum; -} - -void R_AddStudioModelToList( ref_entity_t *e ) -{ - uint modhandle; - uint entnum = e - r_entities; - ref_model_t *mod = e->model; - mfog_t *fog = NULL; - mstudiotexture_t *ptexture; - short *pskinref; - int sequence; - int i, j; - - if( !e->model->extradata ) - return; - - if( RP_FOLLOWENTITY( e )) - { - // cull child entities with parent volume - R_StudioSetupRender( e->parent, e->parent->model ); - sequence = e->parent->lerp->curstate.sequence; - } - else - { - R_StudioSetupRender( e, e->model ); - sequence = e->lerp->curstate.sequence; - } - - if( !R_StudioComputeBBox( NULL )) - return; // invalid sequence - - modhandle = Mod_Handle( mod ); - - R_StudioSetupRender( e, e->model ); - if( m_pStudioHeader->numbodyparts == 0 ) return; // nothing to draw - - if( RI.params & RP_SHADOWMAPVIEW ) - { - if( r_entShadowBits[entnum] & RI.shadowGroup->bit ) - { - if( !r_shadows_self_shadow->integer ) - r_entShadowBits[entnum] &= ~RI.shadowGroup->bit; - if( e->ent_type == ET_VIEWENTITY ) - return; - } - else - { - R_StudioModelLerpBBox( e, mod ); - if( !R_CullModel( e, studio_mins, studio_maxs, studio_radius )) - r_entShadowBits[entnum] |= RI.shadowGroup->bit; - return; // mark as shadowed, proceed with caster otherwise - } - } - else - { - fog = R_FogForSphere( e->origin, studio_radius ); -#if 0 - if( !( e->ent_type == ET_VIEWENTITY ) && fog ) - { - R_StudioModelLerpBBox( e, mod ); - if( R_CompletelyFogged( fog, e->origin, studio_radius )) - return; - } -#endif - } - - // setup bones, play events etc - R_StudioSetupModel( e, e->model ); - - // add base model - ptexture = (mstudiotexture_t *)((byte *)m_pTextureHeader + m_pTextureHeader->textureindex); - for( i = 0; i < m_pStudioHeader->numbodyparts; i++ ) - { - R_StudioSetupSubModel( e->body, i ); - pskinref = (short *)((byte *)m_pTextureHeader + m_pTextureHeader->skinindex); - if( e->skin != 0 && e->skin < m_pTextureHeader->numskinfamilies ) - pskinref += (e->skin * m_pTextureHeader->numskinref); - - for( j = 0; j < m_pSubModel->nummesh; j++ ) - { - ref_shader_t *shader; - mstudiomesh_t *pmesh; - - pmesh = (mstudiomesh_t *)((byte *)m_pStudioHeader + m_pSubModel->meshindex) + j; - - if( e->customShader ) shader = e->customShader; - else shader = &r_shaders[ptexture[pskinref[pmesh->skinref]].index]; - - if( shader ) R_AddModelMeshToList( modhandle, fog, shader, ((j<<8)|i)); - } - } -} - -void R_StudioRunEvents( ref_entity_t *e ) -{ - if( !e || !e->model || !e->model->extradata ) - return; - - if( RP_FOLLOWENTITY( e )) return; - - RI.currententity = e; - R_StudioSetupRender( e, e->model ); - if( m_pStudioHeader->numbodyparts == 0 ) - return; // nothing to draw - - // setup bones, play events etc - R_StudioSetupModel( e, e->model ); -} \ No newline at end of file diff --git a/vid_gl/r_surf.c b/vid_gl/r_surf.c deleted file mode 100644 index 5a78a7e9..00000000 --- a/vid_gl/r_surf.c +++ /dev/null @@ -1,718 +0,0 @@ -/* -Copyright (C) 1997-2001 Id Software, Inc. -Copyright (C) 2002-2007 Victor Luchits - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -// r_surf.c: surface-related refresh code - -#include "r_local.h" -#include "mathlib.h" -#include "matrix_lib.h" -#include "bspfile.h" - -static vec3_t modelorg; // relative to viewpoint -static vec3_t modelmins; -static vec3_t modelmaxs; -static byte fatpvs[MAX_MAP_LEAFS/8]; - -/* -============================================================= - -BRUSH MODELS - -============================================================= -*/ -/* -================= -R_SurfPotentiallyVisible -================= -*/ -qboolean R_SurfPotentiallyVisible( msurface_t *surf ) -{ - if( !surf->texinfo ) - return false; - if( !surf->mesh || R_InvalidMesh( surf->mesh )) - return false; - if( !surf->shader ) - return false; - if( !surf->shader->num_stages ) - return false; - return true; -} - -/* -================= -R_CullSurface -================= -*/ -qboolean R_CullSurface( msurface_t *surf, uint clipflags ) -{ - ref_shader_t *shader = surf->shader; - - if(( shader->flags & SHADER_SKYPARMS ) && r_fastsky->integer ) - return true; - - if( surf->flags & SURF_WATERCSG && !( RI.currententity->flags & EF_NOWATERCSG )) - return true; - - if( r_nocull->integer ) - return false; - - if( shader->tessSize ) - return false; - - if( shader->flags & SHADER_AUTOSPRITE ) - return false; - - if( r_faceplanecull->integer && ( shader->flags & (SHADER_CULL_FRONT|SHADER_CULL_BACK))) - { - if( !VectorCompare( surf->plane->normal, vec3_origin )) - { - float dist; - - dist = PlaneDiff( modelorg, surf->plane ); - - if( shader->flags & SHADER_CULL_FRONT || ( RI.params & RP_MIRRORVIEW )) - { - if( surf->flags & SURF_PLANEBACK ) - { - if( dist >= -BACKFACE_EPSILON ) - return true; // wrong side - } - else - { - if( dist <= BACKFACE_EPSILON ) - return true; // wrong side - } - } - else if( shader->flags & SHADER_CULL_BACK ) - { - if( surf->flags & SURF_PLANEBACK ) - { - if( dist <= BACKFACE_EPSILON ) - return true; // wrong side - } - else - { - if( dist >= -BACKFACE_EPSILON ) - return true; // wrong side - } - } - } - } - return ( clipflags && R_CullBox( surf->mins, surf->maxs, clipflags )); -} - -/* -================= -R_AddSurfaceToList -================= -*/ -static meshbuffer_t *R_AddSurfaceToList( msurface_t *surf, unsigned int clipflags ) -{ - ref_shader_t *shader; - meshbuffer_t *mb; - - if( R_CullSurface( surf, clipflags )) - return NULL; - - shader = ((r_drawworld->integer == 2) ? R_OcclusionShader() : surf->shader); - - if( shader->flags & SHADER_SKYPARMS ) - { - qboolean vis = R_AddSkySurface( surf ); - if(( RI.params & RP_NOSKY ) && vis ) - { - R_AddMeshToList( MB_MODEL, surf->fog, shader, surf - r_worldbrushmodel->surfaces + 1 ); - RI.params &= ~RP_NOSKY; - } - return NULL; - } - - if( OCCLUSION_QUERIES_ENABLED( RI )) - { - if( shader->flags & SHADER_PORTAL ) - R_SurfOcclusionQueryKey( RI.currententity, surf ); - - if( OCCLUSION_OPAQUE_SHADER( shader ) ) - R_AddOccludingSurface( surf, shader ); - } - - c_brush_polys++; - mb = R_AddMeshToList( MB_MODEL, surf->fog, shader, surf - r_worldbrushmodel->surfaces + 1 ); - RI.surfmbuffers[surf - r_worldbrushmodel->surfaces] = mb; - - // also add all surface decals - R_AddSurfaceDecals( surf ); - - return mb; -} - -/* -================= -R_CullBrushModel -================= -*/ -qboolean R_CullBrushModel( ref_entity_t *e ) -{ - qboolean rotated; - ref_model_t *model = e->model; - mbrushmodel_t *bmodel = (mbrushmodel_t *)model->extradata; - int i; - - if( bmodel->nummodelsurfaces == 0 ) - return true; - - rotated = !Matrix3x3_Compare( e->axis, matrix3x3_identity ); - - if( rotated ) - { - for( i = 0; i < 3; i++ ) - { - modelmins[i] = e->origin[i] - model->radius * e->scale; - modelmaxs[i] = e->origin[i] + model->radius * e->scale; - } - - if( R_CullSphere( e->origin, model->radius * e->scale, RI.clipFlags )) - return true; - } - else - { - VectorMA( e->origin, e->scale, model->mins, modelmins ); - VectorMA( e->origin, e->scale, model->maxs, modelmaxs ); - - if( R_CullBox( modelmins, modelmaxs, RI.clipFlags )) - return true; - } - - if( RI.rdflags & ( RDF_PORTALINVIEW|RDF_SKYPORTALINVIEW ) || ( RI.params & RP_SKYPORTALVIEW )) - { - if( rotated ) - { - if( R_VisCullSphere( e->origin, model->radius * e->scale )) - return true; - } - else - { - if( R_VisCullBox( modelmins, modelmaxs )) - return true; - } - } - - return false; -} - -void R_BmodelDrawDebug( void ) -{ - vec3_t bbox[8]; - ref_model_t *model; - int i; - - if( r_drawentities->integer != 5 ) - return; - - model = RI.currententity->model; - - // compute a full bounding box - for( i = 0; i < 8; i++ ) - { - bbox[i][0] = (i & 1) ? model->mins[0] : model->maxs[0]; - bbox[i][1] = (i & 2) ? model->mins[1] : model->maxs[1]; - bbox[i][2] = (i & 4) ? model->mins[2] : model->maxs[2]; - } - - R_RotateForEntity( RI.currententity ); - pglColor4f( 1.0f, 1.0f, 0.0f, 1.0f ); // yellow bboxes for brushmodels - - pglBegin( GL_LINES ); - for( i = 0; i < 2; i += 1 ) - { - pglVertex3fv( bbox[i+0] ); - pglVertex3fv( bbox[i+2] ); - pglVertex3fv( bbox[i+4] ); - pglVertex3fv( bbox[i+6] ); - pglVertex3fv( bbox[i+0] ); - pglVertex3fv( bbox[i+4] ); - pglVertex3fv( bbox[i+2] ); - pglVertex3fv( bbox[i+6] ); - pglVertex3fv( bbox[i*2+0] ); - pglVertex3fv( bbox[i*2+1] ); - pglVertex3fv( bbox[i*2+4] ); - pglVertex3fv( bbox[i*2+5] ); - } - pglEnd(); -} - -/* -================= -R_AddBrushModelToList -================= -*/ -void R_AddBrushModelToList( ref_entity_t *e ) -{ - qboolean rotated; - uint i, dlightbits; - ref_model_t *model = e->model; - mbrushmodel_t *bmodel = (mbrushmodel_t *)model->extradata; - msurface_t *psurf; - meshbuffer_t *mb; - - rotated = !Matrix3x3_Compare( e->axis, matrix3x3_identity ); - VectorSubtract( RI.refdef.vieworg, e->origin, modelorg ); - - if( rotated ) - { - vec3_t temp; - - VectorCopy( modelorg, temp ); - Matrix3x3_Transform( e->axis, temp, modelorg ); - } - - dlightbits = 0; - if(( r_dynamiclight->integer == 1 ) && !r_fullbright->integer && !( RI.params & RP_SHADOWMAPVIEW )) - { - for( i = 0; i < r_numDlights; i++ ) - { - if( BoundsIntersect( modelmins, modelmaxs, r_dlights[i].mins, r_dlights[i].maxs )) - dlightbits |= ( 1<firstmodelsurface; i < bmodel->nummodelsurfaces; i++, psurf++ ) - { - if( !R_SurfPotentiallyVisible( psurf )) - continue; - - if( RI.params & RP_SHADOWMAPVIEW ) - { - if( psurf->visframe != r_framecount ) - continue; - - if(( psurf->shader->sort >= SORT_OPAQUE ) && ( psurf->shader->sort <= SORT_BANNER )) - { - if( prevRI.surfmbuffers[psurf - r_worldbrushmodel->surfaces] ) - { - if( !R_CullSurface( psurf, 0 )) - { - RI.params |= RP_WORLDSURFVISIBLE; - prevRI.surfmbuffers[psurf - r_worldbrushmodel->surfaces]->shadowbits |= RI.shadowGroup->bit; - } - } - } - continue; - } - - psurf->visframe = r_framecount; - mb = R_AddSurfaceToList( psurf, 0 ); - if( mb ) - { - mb->sortkey |= (( psurf->superLightStyle+1 ) << 10 ); - if( R_SurfPotentiallyLit( psurf )) - mb->dlightbits = dlightbits; - } - } -} - -/* -============================================================= - -WORLD MODEL - -============================================================= -*/ -/* -================ -R_RecursiveWorldNode -================ -*/ -static void R_RecursiveWorldNode( mnode_t *node, uint clipflags, uint dlightbits ) -{ - const mplane_t *clipplane; - int i, clipped; - uint newDlightbits; - msurface_t **mark, *surf; - mleaf_t *leaf; - meshbuffer_t *mb; - - if( node->contents == CONTENTS_SOLID ) - return; // hit a solid leaf - - if( node->pvsframe != r_pvsframecount ) - return; // not visible for this frame - - if( clipflags ) - { - for( i = 0, clipplane = RI.frustum; i < 6; i++, clipplane++ ) - { - if(!( clipflags & ( 1<mins, node->maxs, clipplane ); - if( clipped == 2 ) return; - if( clipped == 1 ) clipflags &= ~(1<contents == CONTENTS_NODE ) - { - newDlightbits = 0; - if( dlightbits ) - { - float dist; - - for( i = 0; i < r_numDlights; i++ ) - { - if(!( dlightbits & ( 1<plane ); - if( dist < -r_dlights[i].intensity ) - dlightbits &= ~(1<children[0], clipflags, dlightbits ); - - dlightbits = newDlightbits; - R_RecursiveWorldNode( node->children[1], clipflags, dlightbits ); - return; - } - - // if a leaf node, draw stuff - leaf = (mleaf_t *)node; - leaf->visframe = r_framecount; - - if( !leaf->numMarkSurfaces ) - return; // nothing to draw - - // add leaf bounds to view bounds - for( i = 0; i < 3; i++ ) - { - RI.visMins[i] = min( RI.visMins[i], leaf->mins[i] ); - RI.visMaxs[i] = max( RI.visMaxs[i], leaf->maxs[i] ); - } - - // add all the surfaces - for( i = 0, mark = leaf->firstMarkSurface; i < leaf->numMarkSurfaces; i++, mark++ ) - { - surf = *mark; - - // NOTE: that R_AddSurfaceToList may set meshBuffer to NULL - // for world ALL surfaces to prevent referencing to freed memory region - if( surf->visframe != r_framecount ) - { - surf->visframe = r_framecount; - mb = R_AddSurfaceToList( surf, clipflags ); - if( mb ) mb->sortkey |= (( surf->superLightStyle+1 ) << 10 ); - } - else - { - mb = RI.surfmbuffers[surf - r_worldbrushmodel->surfaces]; - } - - newDlightbits = mb ? dlightbits & ~mb->dlightbits : 0; - if( newDlightbits && R_SurfPotentiallyLit( surf )) - mb->dlightbits |= R_AddSurfDlighbits( surf, newDlightbits ); - } - - c_world_leafs++; -} - -/* -================ -R_MarkShadowLeafSurfaces -================ -*/ -static void R_MarkShadowLeafSurfaces( msurface_t **mark, uint numfaces, uint clipflags ) -{ - msurface_t *surf; - meshbuffer_t *mb; - const uint bit = RI.shadowGroup->bit; - int i; - - for( i = 0; i < numfaces; i++ ) - { - surf = *mark++; - - mb = prevRI.surfmbuffers[surf - r_worldbrushmodel->surfaces]; - if( !mb || ( mb->shadowbits & bit )) - continue; - - // this surface is visible in previous RI, not marked as shadowed... - if(( surf->shader->sort >= SORT_OPAQUE ) && ( surf->shader->sort <= SORT_ALPHATEST )) - { - // ...is opaque - if( !R_CullSurface( surf, clipflags )) - { - // and is visible to the light source too - RI.params |= RP_WORLDSURFVISIBLE; - mb->shadowbits |= bit; - } - } - } -} - -/* -================ -R_LinearShadowLeafs -================ -*/ -static void R_LinearShadowLeafs( void ) -{ - uint i, j, cpf; - const mplane_t *clipplane; - int clipped; - mleaf_t *pleaf; - - for( i = 0; i < r_worldbrushmodel->numleafs; i++ ) - { - pleaf = &r_worldbrushmodel->leafs[i+1]; - - if( pleaf->visframe != r_framecount ) - continue; - - if( !( RI.shadowGroup->vis[i>>3] & ( 1<<( i & 7 )))) - continue; - - cpf = RI.clipFlags; - - for( j = 0, clipplane = RI.frustum; j < 6; j++, clipplane++ ) - { - clipped = BoxOnPlaneSide( pleaf->mins, pleaf->maxs, clipplane ); - - if( clipped == 2 ) break; - if( clipped == 1 ) cpf &= ~(1<firstMarkSurface, pleaf->numMarkSurfaces, cpf ); - c_world_leafs++; - } - } -} - -//================================================================================== - -int r_surfQueryKeys[MAX_SURF_QUERIES]; - -/* -=============== -R_ClearSurfOcclusionQueryKeys -=============== -*/ -void R_ClearSurfOcclusionQueryKeys( void ) -{ - Mem_Set( r_surfQueryKeys, -1, sizeof( r_surfQueryKeys )); -} - -/* -=============== -R_SurfOcclusionQueryKey -=============== -*/ -int R_SurfOcclusionQueryKey( ref_entity_t *e, msurface_t *surf ) -{ - int i; - int *keys = r_surfQueryKeys; - int key = surf - r_worldbrushmodel->surfaces; - - if( e != r_worldent ) - return -1; - - for( i = 0; i < MAX_SURF_QUERIES; i++ ) - { - if( keys[i] >= 0 ) - { - if( keys[i] == key ) - return i; - } - else - { - keys[i] = key; - return i; - } - } - - return -1; -} - -/* -=============== -R_SurfIssueOcclusionQueries -=============== -*/ -void R_SurfIssueOcclusionQueries( void ) -{ - int i, *keys = r_surfQueryKeys; - msurface_t *surf; - - for( i = 0; keys[i] >= 0; i++ ) - { - surf = &r_worldbrushmodel->surfaces[keys[i]]; - R_IssueOcclusionQuery( R_GetOcclusionQueryNum( OQ_CUSTOM, i ), r_worldent, surf->mins, surf->maxs ); - } -} - -//================================================================================== - -/* -============= -R_CalcDistancesToFogVolumes -============= -*/ -static void R_CalcDistancesToFogVolumes( void ) -{ - int i; - mfog_t *fog; - - for( i = 0, fog = r_worldbrushmodel->fogs; i < r_worldbrushmodel->numfogs; i++, fog++ ) - RI.fog_dist_to_eye[fog - r_worldbrushmodel->fogs] = PlaneDiff( RI.viewOrigin, fog->visibleplane ); -} - -/* -============= -R_DrawWorld -============= -*/ -void R_DrawWorld( void ) -{ - int clipflags; - uint dlightbits; - double starttime; - - if( !r_drawworld->integer ) - return; - - if( !RI.drawWorld ) return; - - if( !r_worldmodel || !r_worldbrushmodel ) - return; - - VectorCopy( RI.refdef.vieworg, modelorg ); - - RI.previousentity = NULL; - RI.currententity = r_worldent; - RI.currentmodel = RI.currententity->model; - - if(!( RI.params & RP_SHADOWMAPVIEW )) - { - R_AllocMeshbufPointers( &RI ); - Mem_Set( RI.surfmbuffers, 0, r_worldbrushmodel->numsurfaces * sizeof( meshbuffer_t* )); - - R_CalcDistancesToFogVolumes(); - } - - ClearBounds( RI.visMins, RI.visMaxs ); - - R_ClearSkyBox(); - - if( r_nocull->integer ) clipflags = 0; - else clipflags = RI.clipFlags; - - if( r_speeds->integer ) - starttime = Sys_DoubleTime(); - - if( r_dynamiclight->integer != 1 || r_fullbright->integer ) - dlightbits = 0; - else dlightbits = r_numDlights < 32 ? ( 1 << r_numDlights ) - 1 : -1; - - if( RI.params & RP_SHADOWMAPVIEW ) R_LinearShadowLeafs (); - else R_RecursiveWorldNode( r_worldbrushmodel->nodes, clipflags, dlightbits ); - - if( r_speeds->integer ) - r_world_node += Sys_DoubleTime() - starttime; -} - -/* -=============== -R_MarkLeaves - -Mark the leaves and nodes that are in the PVS for the current leaf -=============== -*/ -void R_MarkLeaves( void ) -{ - byte *vis; - mleaf_t *leaf; - mnode_t *node; - int i; - - if( !RI.drawWorld ) return; - - if( RI.params & RP_SHADOWMAPVIEW ) - return; - - if( r_viewleaf == r_oldviewleaf && r_viewleaf2 == r_oldviewleaf2 && !r_novis->integer && r_viewleaf != NULL ) - return; - - // development aid to let you run around - // and see exactly where the pvs ends - if( r_lockpvs->integer ) - return; - - r_pvsframecount++; - r_oldviewleaf = r_viewleaf; - r_oldviewleaf2 = r_viewleaf2; - - if( r_novis->integer || r_viewleaf == NULL || !r_worldbrushmodel->visdata ) - { - // mark everything - for( i = 0, leaf = r_worldbrushmodel->leafs; i < r_worldbrushmodel->numleafs; i++, leaf++ ) - leaf->pvsframe = r_pvsframecount; - for( i = 0, node = r_worldbrushmodel->nodes; i < r_worldbrushmodel->numnodes; i++, node++ ) - node->pvsframe = r_pvsframecount; - return; - } - - // may have to combine two clusters - // because of solid water boundaries - vis = Mod_LeafPVS( r_viewleaf, r_worldmodel ); - - if( r_viewleaf != r_viewleaf2 ) - { - int longs = (r_worldbrushmodel->numleafs + 31)>>5; - - Mem_Copy( fatpvs, vis, longs << 2 ); - vis = Mod_LeafPVS( r_viewleaf2, r_worldmodel ); - - for( i = 0; i < longs; i++ ) - ((int *)fatpvs)[i] |= ((int *)vis)[i]; - - vis = fatpvs; - } - - for( i = 0; i < r_worldbrushmodel->numleafs-1; i++ ) // FIXME: this is right ? - { - if( vis[i>>3] & ( 1<<( i & 7 ))) - { - node = (mnode_t *)&r_worldbrushmodel->leafs[i+1]; - do - { - if( node->pvsframe == r_pvsframecount ) - break; - node->pvsframe = r_pvsframecount; - node = node->parent; - } while( node ); - } - } -} \ No newline at end of file diff --git a/vid_gl/render_api.h b/vid_gl/render_api.h deleted file mode 100644 index 28f86ecc..00000000 --- a/vid_gl/render_api.h +++ /dev/null @@ -1,148 +0,0 @@ -//======================================================================= -// Copyright XashXT Group 2008 -// render_api.h - xash renderer api -//======================================================================= -#ifndef RENDER_API_H -#define RENDER_API_H - -#include "ref_params.h" - -#define MAP_DEFAULT_SHADER "*black" // engine built-in default shader - -// shader types used for shader loading -#define SHADER_SKY 1 // sky box shader -#define SHADER_NOMIP 2 // 2d images -#define SHADER_DECAL 3 // used for decals only -#define SHADER_SPRITE 4 // hud sprites -#define SHADER_GENERIC 5 // generic shader - -// dlight flags -#define DLIGHT_ONLYENTS BIT( 0 ) -#define DLIGHT_DARK BIT( 1 ) - -// screenshot types -#define VID_SCREENSHOT 0 -#define VID_LEVELSHOT 1 -#define VID_MINISHOT 2 - -typedef struct -{ - int numverts; - vec3_t *verts; - vec2_t *stcoords; - rgba_t *colors; - - union - { - struct ref_shader_s *shader; - shader_t shadernum; - }; - - int fognum; - vec3_t normal; - vec3_t lightingOrigin; -} poly_t; - -typedef struct -{ - vec3_t position; - char name[64]; // same as CS_SIZE - short entityIndex; // FIXME: replace with pointer to entity ? - byte depth; - byte flags; - - // this is the surface plane that we hit so that - // we can move certain decals across - // transitions if they hit similar geometry - vec3_t impactPlaneNormal; -} decallist_t; - -/* -============================================================================== - -RENDER.DLL INTERFACE -============================================================================== -*/ -typedef struct render_exp_s -{ - // interface validator - size_t api_size; // must matched with sizeof(render_exp_t) - size_t com_size; // must matched with sizeof(stdlib_api_t) - - // initialize - qboolean (*Init)( qboolean full ); // init all render systems - void (*Shutdown)( qboolean full ); // shutdown all render systems - - void (*BeginRegistration)( const char *map ); - qboolean (*RegisterModel)( const char *name, int cl_index ); // also build replacement index table - shader_t (*RegisterShader)( const char *name, int shaderType ); - shader_t (*RegisterShaderInt)( const char *name, const byte *image_buf, size_t image_size ); // from memory - void (*EndRegistration)( const char *skyname ); - void (*FreeShader)( const char *shadername ); - - // prepare frame to rendering - qboolean (*AddRefEntity)( struct cl_entity_s *pRefEntity, int entityType, shader_t customShader ); - qboolean (*DecalShoot)( shader_t decal, int ent, int model, vec3_t pos, vec3_t saxis, int flags, rgba_t color, float fadeTime, float fadeDuration ); - qboolean (*AddDLight)( vec3_t pos, color24 color, float radius, int flags ); - qboolean (*AddPolygon)( const poly_t *poly ); - qboolean (*AddLightStyle)( int stylenum, vec3_t color ); - void (*ClearScene)( void ); - - void (*BeginFrame)( qboolean clearScene ); - void (*RenderFrame)( const ref_params_t *fd, qboolean drawWorld ); - void (*EndFrame)( void ); - - // triapi implementation - void (*RenderMode)( const int mode ); - shader_t (*GetSpriteTexture)( int spriteIndex, int spriteFrame ); - void (*Normal3f)( const float x, const float y, const float z ); - void (*Vertex3f)( const float x, const float y, const float z ); - void (*Color4ub)( const byte r, const byte g, const byte b, const byte a ); - void (*Fog)( float flFogColor[3], float flStart, float flEnd, int bOn ); - void (*TexCoord2f)( const float u, const float v ); - void (*Bind)( shader_t shader, int frame ); - void (*CullFace)( int mode ); - void (*Begin)( int mode ); - void (*End)( void ); - - // misc utilities - void (*SetColor)( const rgba_t color ); - void (*SetParms)( shader_t handle, int rendermode, int frame ); - void (*GetParms)( int *w, int *h, int *frames, int frame, shader_t shader ); - qboolean (*ScrShot)( const char *filename, int shot_type ); // write screenshot with same name - qboolean (*EnvShot)( const char *filename, uint size, const float *vieworg, qboolean skyshot ); - void (*SetSkyPortal)( const vec3_t vieworg, const vec3_t viewangles, float scale, float fov ); - void (*LightForPoint)( const vec3_t point, vec3_t ambientLight ); - void (*DrawStretchRaw)( float x, float y, float w, float h, int cols, int rows, byte *data, qboolean redraw ); - void (*DrawStretchPic)( float x, float y, float w, float h, float s1, float t1, float s2, float t2, shader_t shader ); - int (*WorldToScreen)( const float *world, float *screen ); - void (*ScreenToWorld)( const float *screen, float *world ); - qboolean (*CullBox)( const vec3_t mins, const vec3_t maxs ); - qboolean (*RSpeedsMessage)( char *out, size_t size ); - int (*CreateDecalList)( decallist_t *pList, qboolean changelevel ); // helper to serialize decals - void (*DecalRemoveAll)( shader_t shader ); - byte *(*GetCurrentVis)( void ); - void (*RestoreGamma)( void ); -} render_exp_t; - -typedef struct render_imp_s -{ - // interface validator - size_t api_size; // must matched with sizeof(render_imp_t) - - // client fundamental callbacks - void (*UpdateScreen)( void ); // update screen while loading - void (*StudioEvent)( struct mstudioevent_s *event, struct cl_entity_s *ent ); - void (*ShowCollision)( cmdraw_t callback ); // debug - long (*WndProc)( void *hWnd, uint uMsg, uint wParam, long lParam ); - struct cl_entity_s *(*GetClientEdict)( int index ); - struct player_info_s *(*GetPlayerInfo)( int playerIndex ); // not an entityIndex!!! - struct cl_entity_s *(*GetLocalPlayer)( void ); - int (*GetMaxClients)( void ); - void (*DrawTriangles)( int fTrans ); - qboolean (*IsThirdPerson)( void ); - void (*ExtraUpdate)( void ); // call during RenderFrame - float (*GetLerpFrac)( void ); -} render_imp_t; - -#endif//RENDER_API_H \ No newline at end of file diff --git a/vid_gl/vid_gl.dsp b/vid_gl/vid_gl.dsp deleted file mode 100644 index 893d053e..00000000 --- a/vid_gl/vid_gl.dsp +++ /dev/null @@ -1,241 +0,0 @@ -# Microsoft Developer Studio Project File - Name="vid_gl" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=vid_gl - Win32 Release -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "vid_gl.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "vid_gl.mak" CFG="vid_gl - Win32 Release" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "vid_gl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "vid_gl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "vid_gl - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "." -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\temp\vid_gl\!release" -# PROP Intermediate_Dir "..\temp\vid_gl\!release" -# PROP Ignore_Export_Lib 1 -# PROP Target_Dir "." -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "../public" /I "../common" /I "../pm_shared" /I "../engine" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c -# SUBTRACT CPP /YX -# ADD BASE MTL /nologo /D "NDEBUG" /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 -# ADD LINK32 msvcrt.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /pdb:none /machine:I386 /nodefaultlib:"libc.lib" /libpath:"../public/libs/" -# SUBTRACT LINK32 /debug -# Begin Custom Build -TargetDir=\Xash3D\src_main\temp\vid_gl\!release -InputPath=\Xash3D\src_main\temp\vid_gl\!release\vid_gl.dll -SOURCE="$(InputPath)" - -"D:\Xash3D\vid_gl.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - copy $(TargetDir)\vid_gl.dll "D:\Xash3D\vid_gl.dll" - -# End Custom Build - -!ELSEIF "$(CFG)" == "vid_gl - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "." -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\temp\vid_gl\!debug" -# PROP Intermediate_Dir "..\temp\vid_gl\!debug" -# PROP Ignore_Export_Lib 1 -# PROP Target_Dir "." -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c -# ADD CPP /nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../public" /I "../common" /I "../pm_shared" /I "../engine" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /FD /c -# SUBTRACT CPP /YX -# ADD BASE MTL /nologo /D "_DEBUG" /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 -# ADD LINK32 msvcrtd.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /pdbtype:sept -# SUBTRACT LINK32 /profile /incremental:no /map -# Begin Custom Build -TargetDir=\Xash3D\src_main\temp\vid_gl\!debug -InputPath=\Xash3D\src_main\temp\vid_gl\!debug\vid_gl.dll -SOURCE="$(InputPath)" - -"D:\Xash3D\vid_gl.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" - copy $(TargetDir)\vid_gl.dll "D:\Xash3D\vid_gl.dll" - -# End Custom Build - -!ENDIF - -# Begin Target - -# Name "vid_gl - Win32 Release" -# Name "vid_gl - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\r_backend.c -# End Source File -# Begin Source File - -SOURCE=.\r_bloom.c -# End Source File -# Begin Source File - -SOURCE=.\r_cull.c -# End Source File -# Begin Source File - -SOURCE=.\r_decals.c -# End Source File -# Begin Source File - -SOURCE=.\r_draw.c -# End Source File -# Begin Source File - -SOURCE=.\r_image.c -# End Source File -# Begin Source File - -SOURCE=.\r_light.c -# End Source File -# Begin Source File - -SOURCE=.\r_main.c -# End Source File -# Begin Source File - -SOURCE=.\r_math.c -# End Source File -# Begin Source File - -SOURCE=.\r_mesh.c -# End Source File -# Begin Source File - -SOURCE=.\r_model.c -# End Source File -# Begin Source File - -SOURCE=.\r_opengl.c -# End Source File -# Begin Source File - -SOURCE=.\r_poly.c -# End Source File -# Begin Source File - -SOURCE=.\r_program.c -# End Source File -# Begin Source File - -SOURCE=.\r_register.c -# End Source File -# Begin Source File - -SOURCE=.\r_shader.c -# End Source File -# Begin Source File - -SOURCE=.\r_shadow.c -# End Source File -# Begin Source File - -SOURCE=.\r_sky.c -# End Source File -# Begin Source File - -SOURCE=.\r_sprite.c -# End Source File -# Begin Source File - -SOURCE=.\r_studio.c -# End Source File -# Begin Source File - -SOURCE=.\r_surf.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" -# Begin Source File - -SOURCE=.\r_backend.h -# End Source File -# Begin Source File - -SOURCE=.\r_local.h -# End Source File -# Begin Source File - -SOURCE=.\r_math.h -# End Source File -# Begin Source File - -SOURCE=.\r_mesh.h -# End Source File -# Begin Source File - -SOURCE=.\r_model.h -# End Source File -# Begin Source File - -SOURCE=.\r_opengl.h -# End Source File -# Begin Source File - -SOURCE=.\r_public.h -# End Source File -# Begin Source File - -SOURCE=.\r_shader.h -# End Source File -# Begin Source File - -SOURCE=.\r_shadow.h -# End Source File -# End Group -# End Target -# End Project diff --git a/vid_gl/warpsin.h b/vid_gl/warpsin.h deleted file mode 100644 index e140acf9..00000000 --- a/vid_gl/warpsin.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright (C) 1997-2001 Id Software, Inc. - -This program 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 2 -of the License, or (at your option) any later version. - -This program 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 this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - - -0.000000, 0.098165, 0.196270, 0.294259, 0.392069, 0.489643, 0.586920, 0.683850, -0.780360, 0.876405, 0.971920, 1.066850, 1.161140, 1.254725, 1.347560, 1.439580, -1.530735, 1.620965, 1.710220, 1.798445, 1.885585, 1.971595, 2.056410, 2.139990, -2.222280, 2.303235, 2.382795, 2.460925, 2.537575, 2.612690, 2.686235, 2.758160, -2.828425, 2.896990, 2.963805, 3.028835, 3.092040, 3.153385, 3.212830, 3.270340, -3.325880, 3.379415, 3.430915, 3.480350, 3.527685, 3.572895, 3.615955, 3.656840, -3.695520, 3.731970, 3.766175, 3.798115, 3.827760, 3.855105, 3.880125, 3.902810, -3.923140, 3.941110, 3.956705, 3.969920, 3.980740, 3.989160, 3.995180, 3.998795, -4.000000, 3.998795, 3.995180, 3.989160, 3.980740, 3.969920, 3.956705, 3.941110, -3.923140, 3.902810, 3.880125, 3.855105, 3.827760, 3.798115, 3.766175, 3.731970, -3.695520, 3.656840, 3.615955, 3.572895, 3.527685, 3.480350, 3.430915, 3.379415, -3.325880, 3.270340, 3.212830, 3.153385, 3.092040, 3.028835, 2.963805, 2.896990, -2.828425, 2.758160, 2.686235, 2.612690, 2.537575, 2.460925, 2.382795, 2.303235, -2.222280, 2.139990, 2.056410, 1.971595, 1.885585, 1.798445, 1.710220, 1.620965, -1.530735, 1.439580, 1.347560, 1.254725, 1.161140, 1.066850, 0.971920, 0.876405, -0.780360, 0.683850, 0.586920, 0.489643, 0.392069, 0.294259, 0.196270, 0.098165, -0.000000, -0.098165, -0.196270, -0.294259, -0.392069, -0.489643, -0.586920, -0.683850, --0.780360, -0.876405, -0.971920, -1.066850, -1.161140, -1.254725, -1.347560, -1.439580, --1.530735, -1.620965, -1.710220, -1.798445, -1.885585, -1.971595, -2.056410, -2.139990, --2.222280, -2.303235, -2.382795, -2.460925, -2.537575, -2.612690, -2.686235, -2.758160, --2.828425, -2.896990, -2.963805, -3.028835, -3.092040, -3.153385, -3.212830, -3.270340, --3.325880, -3.379415, -3.430915, -3.480350, -3.527685, -3.572895, -3.615955, -3.656840, --3.695520, -3.731970, -3.766175, -3.798115, -3.827760, -3.855105, -3.880125, -3.902810, --3.923140, -3.941110, -3.956705, -3.969920, -3.980740, -3.989160, -3.995180, -3.998795, --4.000000, -3.998795, -3.995180, -3.989160, -3.980740, -3.969920, -3.956705, -3.941110, --3.923140, -3.902810, -3.880125, -3.855105, -3.827760, -3.798115, -3.766175, -3.731970, --3.695520, -3.656840, -3.615955, -3.572895, -3.527685, -3.480350, -3.430915, -3.379415, --3.325880, -3.270340, -3.212830, -3.153385, -3.092040, -3.028835, -2.963805, -2.896990, --2.828425, -2.758160, -2.686235, -2.612690, -2.537575, -2.460925, -2.382795, -2.303235, --2.222280, -2.139990, -2.056410, -1.971595, -1.885585, -1.798445, -1.710220, -1.620965, --1.530735, -1.439580, -1.347560, -1.254725, -1.161140, -1.066850, -0.971920, -0.876405, --0.780360, -0.683850, -0.586920, -0.489643, -0.392069, -0.294259, -0.196270, -0.098165,