diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index a4528bd42..1b830fb3b 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -530,7 +530,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con Cbuf_AddText(VM_POINTER(arg[0]), RESTRICT_SERVER); break; case CG_ADDCOMMAND: - Cmd_AddRemCommand(VM_POINTER(arg[0]), NULL); + Cmd_AddCommand(VM_POINTER(arg[0]), NULL); break; case CG_SENDCLIENTCOMMAND: Con_DPrintf("CG_SENDCLIENTCOMMAND: %s", (char*)VM_POINTER(arg[0])); diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 01692230f..92de537bd 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -842,8 +842,6 @@ void CL_Stop_f (void) cls.demooutfile = NULL; cls.demorecording = false; Con_Printf ("Completed demo\n"); - - FS_FlushFSHash(); } @@ -1404,7 +1402,6 @@ void CL_PlayDownloadedDemo(char *name, qboolean success) Con_Printf("Failed to download %s\n", name); else { - FS_FlushFSHash(); Cbuf_AddText(va("playdemo %s\n", name), RESTRICT_LOCAL); } } diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index db3f8936c..2298b502e 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -1250,10 +1250,7 @@ qboolean CL_SendCmdQ2 (sizebuf_t *buf) else MSG_WriteLong (buf, cl.q2frame.serverframe); - if (R_LightPoint) - lightlev = R_LightPoint(cl.simorg[0]); - else - lightlev = 255; + lightlev = R_LightPoint(cl.simorg[0]); // msecs = msecs - (double)msecstouse; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 470a25af2..9d6be8cfd 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -542,7 +542,7 @@ void CL_SendConnectPacket (int mtu, if (mtu > 0) { if (adr.type == NA_LOOPBACK) - mtu = 8192; + mtu = MAX_UDP_PACKET; else if (net_mtu.ival > 64 && mtu > net_mtu.ival) mtu = net_mtu.ival; mtu &= ~7; @@ -3094,6 +3094,9 @@ void CL_Init (void) #endif #ifdef CSQC_DAT CSQC_RegisterCvarsAndThings(); +#endif +#if defined(CSQC_DAT) || defined(MENU_DAT) + PF_Common_RegisterCvars(); #endif Cvar_Register (&host_speeds, cl_controlgroup); Cvar_Register (&developer, cl_controlgroup); @@ -3823,6 +3826,9 @@ void Host_Init (quakeparms_t *parms) CDAudio_Init (); Sbar_Init (); CL_Init (); +#if defined(SERVERONLY) || !(defined(CSQC_DAT) || defined(MENU_DAT)) + PF_Common_RegisterCvars(); +#endif TranslateInit(); #ifndef CLIENTONLY @@ -4021,7 +4027,7 @@ void Host_Shutdown(void) UI_Stop(); #endif - Host_WriteConfiguration (); +// Host_WriteConfiguration (); CDAudio_Shutdown (); S_Shutdown(); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index ad3263b22..53e3a1eea 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -953,6 +953,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) if (cls.protocol == CP_NETQUAKE && !cl_nocsqc.ival && !cls.demoplayback) { char *s; + SCR_SetLoadingFile("csprogs"); s = Info_ValueForKey(cl.serverinfo, "*csprogs"); if (*s) //only allow csqc if the server says so, and the 'checksum' matches. { @@ -977,6 +978,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) #ifdef HLCLIENT if (atstage()) { + SCR_SetLoadingFile("hlclient"); CLHL_LoadClientGame(); endstage(); } @@ -996,6 +998,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) if (anycsqc || *s || cls.demoplayback) //only allow csqc if the server says so, and the 'checksum' matches. { unsigned int chksum = strtoul(s, NULL, 0); + SCR_SetLoadingFile("csprogs"); if (!CSQC_Init(anycsqc, chksum)) { Sbar_Start(); //try and start this before we're actually on the server, @@ -1010,6 +1013,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) if (atstage()) { + SCR_SetLoadingFile("prenewmap"); loadmodel = cl.worldmodel; if (R_PreNewMap) @@ -1031,6 +1035,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) if (atstage()) { + SCR_SetLoadingFile(cl.model_name[i]); #ifdef CSQC_DAT if (i == 1) CSQC_LoadResource(cl.model_name[i], "map"); @@ -1057,6 +1062,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) if (atstage()) { + SCR_SetLoadingFile(cl.model_name_vwep[i]); #ifdef CSQC_DAT CSQC_LoadResource(cl.model_name_vwep[i], "vwep"); #endif @@ -1080,6 +1086,8 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) // Host_EndGame("Worldmodel wasn't loaded\n"); } + SCR_SetLoadingFile("csprogs world"); + #ifdef CSQC_DAT CSQC_WorldLoaded(); #endif @@ -1093,6 +1101,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) continue; if (atstage()) { + SCR_SetLoadingFile(cl.model_csqcname[i]); #ifdef CSQC_DAT if (i == 1) CSQC_LoadResource(cl.model_csqcname[i], "map"); @@ -1110,6 +1119,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) if (atstage()) { + SCR_SetLoadingFile("wads"); Wad_NextDownload(); endstage(); @@ -1117,6 +1127,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) if (atstage()) { + SCR_SetLoadingFile("external textures"); loadmodel = cl.worldmodel; // if (!loadmodel || loadmodel->type == mod_dummy) // Host_EndGame("No worldmodel was loaded\n"); @@ -1129,6 +1140,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) // all done if (atstage()) { + SCR_SetLoadingFile("newmap"); loadmodel = cl.worldmodel; // if (!loadmodel || loadmodel->type == mod_dummy) // Host_EndGame("No worldmodel was loaded\n"); @@ -1143,6 +1155,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) #ifdef CSQC_DAT if (atstage()) { + SCR_SetLoadingFile("csqc init"); if (CSQC_Inited()) { CL_SendClientCommand(true, "enablecsqc"); @@ -1174,6 +1187,7 @@ int CL_LoadSounds(int stage, qboolean dontactuallyload) if (atstage()) { + SCR_SetLoadingFile(cl.sound_name[i]); #ifdef CSQC_DAT CSQC_LoadResource(cl.sound_name[i], "sound"); #endif @@ -1346,7 +1360,7 @@ void CL_RequestNextDownload (void) current_loading_size = cl.contentstage; if (stage < 0) return; - + SCR_SetLoadingFile("prespawn"); cl.sendprespawn = false; #ifdef warningmsg #pragma warningmsg("timedemo timer should start here") @@ -1989,7 +2003,6 @@ void CLDP_ParseDownloadFinished(char *s) Cmd_TokenizeString(s+1, false, false); VFS_CLOSE (cls.downloadqw); - FS_FlushFSHash(); cls.downloadqw = FS_OpenVFS (cls.downloadtempname, "rb", FS_GAME); if (cls.downloadqw) diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 73f7d87e7..3c47b4614 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -221,12 +221,14 @@ cvar_t show_gameclock_y = SCVAR("cl_gameclock_y", "-1"); cvar_t show_speed = SCVAR("show_speed", "0"); cvar_t show_speed_x = SCVAR("show_speed_x", "-1"); cvar_t show_speed_y = SCVAR("show_speed_y", "-9"); +cvar_t scr_loadingrefresh = SCVAR("scr_loadingrefresh", "0"); extern char cl_screengroup[]; void CLSCR_Init(void) { Cmd_AddCommand("cprint", SCR_CPrint_f); + Cvar_Register(&scr_loadingrefresh, cl_screengroup); Cvar_Register(&show_fps, cl_screengroup); Cvar_Register(&show_fps_x, cl_screengroup); Cvar_Register(&show_fps_y, cl_screengroup); @@ -1137,9 +1139,9 @@ void SCR_Init (void) // // register our commands // - Cmd_AddRemCommand ("screenshot",SCR_ScreenShot_f); - Cmd_AddRemCommand ("sizeup",SCR_SizeUp_f); - Cmd_AddRemCommand ("sizedown",SCR_SizeDown_f); + Cmd_AddCommand ("screenshot",SCR_ScreenShot_f); + Cmd_AddCommand ("sizeup",SCR_SizeUp_f); + Cmd_AddCommand ("sizedown",SCR_SizeDown_f); scr_net = R2D_SafePicFromWad ("net"); scr_turtle = R2D_SafePicFromWad ("turtle"); @@ -1446,6 +1448,7 @@ SCR_DrawLoading */ int total_loading_size, current_loading_size, loading_stage; +char *loadingfile; int CL_DownloadRate(void); int SCR_GetLoadingStage(void) @@ -1454,8 +1457,39 @@ int SCR_GetLoadingStage(void) } void SCR_SetLoadingStage(int stage) { + switch(stage) + { + case LS_NONE: + if (loadingfile) + Z_Free(loadingfile); + loadingfile = NULL; + break; + case LS_CONNECTION: + SCR_SetLoadingFile("connection..."); + break; + case LS_SERVER: + if (scr_con_current > vid.height*scr_consize.value) + scr_con_current = vid.height*scr_consize.value; + SCR_SetLoadingFile("server..."); + break; + case LS_CLIENT: + SCR_SetLoadingFile("initial state"); + break; + } loading_stage = stage; } +void SCR_SetLoadingFile(char *str) +{ + if (loadingfile) + Z_Free(loadingfile); + loadingfile = Z_Malloc(strlen(str)+1); + strcpy(loadingfile, str); + + if (scr_loadingrefresh.ival) + { + SCR_UpdateScreen(); + } +} void SCR_DrawLoading (void) { @@ -1520,9 +1554,11 @@ void SCR_DrawLoading (void) Draw_FunString(x+8, y+4, va("Loading %s... %i%%", (loading_stage == LS_SERVER) ? "server" : "client", current_loading_size * 100 / total_loading_size)); - - y += 16; } + y += 16; + + if (loadingfile) + Draw_FunString(x+8, y+4, loadingfile); } else { //hexen2 files diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index a3e8e32b8..86e5bfb99 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -170,7 +170,6 @@ typedef enum #define Q2SPLASH_BLOOD 6 #endif -#define MAX_BEAMS 64 typedef struct { int entity; @@ -188,9 +187,9 @@ typedef struct trailstate_t *emitstate; } beam_t; -beam_t cl_beams[MAX_BEAMS]; +beam_t *cl_beams; +int cl_beams_max; -#define MAX_EXPLOSIONS 256 typedef struct { vec3_t origin; @@ -212,7 +211,8 @@ typedef struct int skinnum; } explosion_t; -explosion_t cl_explosions[MAX_EXPLOSIONS]; +explosion_t *cl_explosions; +int cl_explosions_max; static int explosions_running; static int beams_running; @@ -513,8 +513,13 @@ CL_ClearTEnts */ void CL_ClearTEnts (void) { - memset (&cl_beams, 0, sizeof(cl_beams)); - memset (&cl_explosions, 0, sizeof(cl_explosions)); + cl_beams_max = 0; + BZ_Free(cl_beams); + cl_beams = NULL; + + cl_explosions_max = 0; + BZ_Free(cl_explosions); + cl_explosions = NULL; } static void CL_ClearExplosion(explosion_t *exp) @@ -549,8 +554,14 @@ explosion_t *CL_AllocExplosion (void) } } - if (i == explosions_running && i != MAX_EXPLOSIONS) +// if (i == explosions_running && i < cl_maxexplosions.ival) { + if (i == cl_explosions_max) + { + cl_explosions_max = (i+1)*2; + cl_explosions = BZ_Realloc(cl_explosions, sizeof(*cl_explosions)*cl_explosions_max); + } + explosions_running++; CL_ClearExplosion(&cl_explosions[i]); return &cl_explosions[i]; @@ -560,7 +571,7 @@ explosion_t *CL_AllocExplosion (void) time = cl.time; index = 0; - for (i=0 ; idecoder.buf; + sfx->decoder.buf = NULL; + + qacmStreamClose(dec->acm, 0); + + if (dec->dstdata) + BZ_Free(dec->dstdata); + BZ_Free(dec); +} + /*must be thread safe*/ sfxcache_t *S_MP3_Locate(sfx_t *sfx, sfxcache_t *buf, int start, int length) { @@ -3204,6 +3218,12 @@ sfxcache_t *S_MP3_Locate(sfx_t *sfx, sfxcache_t *buf, int start, int length) if (dec->dstcount > snd_speed*6) { int trim = dec->dstcount - snd_speed; //retain a second of buffer in case we have multiple sound devices + if (dec->dststart + trim > start) + { + trim = start - dec->dststart; + if (trim < 0) + trim = 0; + } // if (trim < 0) // trim = 0; /// if (trim > dec->dstcount) @@ -3298,7 +3318,7 @@ qboolean S_LoadMP3Sound (sfx_t *s, qbyte *data, int datalen, int sndspeed) memcpy(dec->srcdata, data, datalen); dec->srclen = datalen; s->decoder.buf = dec; - s->decoder.abort = NULL; + s->decoder.abort = S_MP3_Abort; s->decoder.decodedata = S_MP3_Locate; dec->dstdata = NULL; diff --git a/engine/client/m_options.c b/engine/client/m_options.c index c06913f21..535f09484 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -822,7 +822,7 @@ qboolean M_VideoApplyShadowLighting (union menuoption_s *op,struct menu_s *menu, char *cvarvd = "0"; char *cvarsrd = "0"; char *cvarsrds = "0"; - switch (info->lightcombo->selectedoption) + switch (info->dlightcombo->selectedoption) { case 1: cvard = "1"; diff --git a/engine/client/menu.c b/engine/client/menu.c index 597f3f058..5910820f7 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -865,62 +865,62 @@ void M_Init_Internal (void) internalmenusregistered = true; #ifndef CLIENTONLY - Cmd_AddRemCommand ("menu_save", M_Menu_Save_f); - Cmd_AddRemCommand ("menu_load", M_Menu_Load_f); - Cmd_AddRemCommand ("menu_loadgame", M_Menu_Load_f); //q2... + Cmd_AddCommand ("menu_save", M_Menu_Save_f); + Cmd_AddCommand ("menu_load", M_Menu_Load_f); + Cmd_AddCommand ("menu_loadgame", M_Menu_Load_f); //q2... #endif - Cmd_AddRemCommand ("menu_single", M_Menu_SinglePlayer_f); - Cmd_AddRemCommand ("menu_multi", M_Menu_MultiPlayer_f); - Cmd_AddRemCommand ("menu_demo", M_Menu_Demos_f); + Cmd_AddCommand ("menu_single", M_Menu_SinglePlayer_f); + Cmd_AddCommand ("menu_multi", M_Menu_MultiPlayer_f); + Cmd_AddCommand ("menu_demo", M_Menu_Demos_f); - Cmd_AddRemCommand ("menu_keys", M_Menu_Keys_f); - Cmd_AddRemCommand ("help", M_Menu_Help_f); - Cmd_AddRemCommand ("menu_quit", M_Menu_Quit_f); - Cmd_AddRemCommand ("menu_media", M_Menu_Media_f); - Cmd_AddRemCommand ("menu_mediafiles", M_Menu_MediaFiles_f); + Cmd_AddCommand ("menu_keys", M_Menu_Keys_f); + Cmd_AddCommand ("help", M_Menu_Help_f); + Cmd_AddCommand ("menu_quit", M_Menu_Quit_f); + Cmd_AddCommand ("menu_media", M_Menu_Media_f); + Cmd_AddCommand ("menu_mediafiles", M_Menu_MediaFiles_f); #ifdef CL_MASTER - Cmd_AddRemCommand ("menu_servers", M_Menu_ServerList2_f); + Cmd_AddCommand ("menu_servers", M_Menu_ServerList2_f); - Cmd_AddRemCommand ("menu_slist", M_Menu_ServerList2_f); + Cmd_AddCommand ("menu_slist", M_Menu_ServerList2_f); #endif - Cmd_AddRemCommand ("menu_setup", M_Menu_Setup_f); - Cmd_AddRemCommand ("menu_newmulti", M_Menu_GameOptions_f); + Cmd_AddCommand ("menu_setup", M_Menu_Setup_f); + Cmd_AddCommand ("menu_newmulti", M_Menu_GameOptions_f); - Cmd_AddRemCommand ("menu_main", M_Menu_Main_f); //I've moved main to last because that way tab give us main and not quit. + Cmd_AddCommand ("menu_main", M_Menu_Main_f); //I've moved main to last because that way tab give us main and not quit. - Cmd_AddRemCommand ("menu_options", M_Menu_Options_f); - Cmd_AddRemCommand ("menu_video", M_Menu_Video_f); - Cmd_AddRemCommand ("menu_audio", M_Menu_Audio_f); + Cmd_AddCommand ("menu_options", M_Menu_Options_f); + Cmd_AddCommand ("menu_video", M_Menu_Video_f); + Cmd_AddCommand ("menu_audio", M_Menu_Audio_f); #ifndef __CYGWIN__ - Cmd_AddRemCommand ("menu_speakers", M_Menu_Audio_Speakers_f); + Cmd_AddCommand ("menu_speakers", M_Menu_Audio_Speakers_f); #endif - Cmd_AddRemCommand ("menu_spcheats", M_Menu_Singleplayer_Cheats_f); - Cmd_AddRemCommand ("menu_fps", M_Menu_FPS_f); - Cmd_AddRemCommand ("menu_render" , M_Menu_Render_f); - Cmd_AddRemCommand ("menu_lighting", M_Menu_Lighting_f); + Cmd_AddCommand ("menu_spcheats", M_Menu_Singleplayer_Cheats_f); + Cmd_AddCommand ("menu_fps", M_Menu_FPS_f); + Cmd_AddCommand ("menu_render" , M_Menu_Render_f); + Cmd_AddCommand ("menu_lighting", M_Menu_Lighting_f); #ifdef GLQUAKE - Cmd_AddRemCommand ("menu_textures", M_Menu_Textures_f); + Cmd_AddCommand ("menu_textures", M_Menu_Textures_f); #endif - Cmd_AddRemCommand ("menu_teamplay", M_Menu_Teamplay_f); - Cmd_AddRemCommand ("menu_teamplay_locations", M_Menu_Teamplay_Locations_f); - Cmd_AddRemCommand ("menu_teamplay_needs", M_Menu_Teamplay_Needs_f); - Cmd_AddRemCommand ("menu_teamplay_items", M_Menu_Teamplay_Items_f); - Cmd_AddRemCommand ("menu_teamplay_armor", M_Menu_Teamplay_Items_Armor_f); - Cmd_AddRemCommand ("menu_teamplay_weapons", M_Menu_Teamplay_Items_Weapons_f); - Cmd_AddRemCommand ("menu_teamplay_powerups", M_Menu_Teamplay_Items_Powerups_f); - Cmd_AddRemCommand ("menu_teamplay_ammo_health", M_Menu_Teamplay_Items_Ammo_Health_f); - Cmd_AddRemCommand ("menu_teamplay_team_fortress", M_Menu_Teamplay_Items_Team_Fortress_f); - Cmd_AddRemCommand ("menu_teamplay_status_location_misc", M_Menu_Teamplay_Items_Status_Location_Misc_f); - Cmd_AddRemCommand ("menu_particles", M_Menu_Particles_f); - Cmd_AddRemCommand ("menu_network", M_Menu_Network_f); + Cmd_AddCommand ("menu_teamplay", M_Menu_Teamplay_f); + Cmd_AddCommand ("menu_teamplay_locations", M_Menu_Teamplay_Locations_f); + Cmd_AddCommand ("menu_teamplay_needs", M_Menu_Teamplay_Needs_f); + Cmd_AddCommand ("menu_teamplay_items", M_Menu_Teamplay_Items_f); + Cmd_AddCommand ("menu_teamplay_armor", M_Menu_Teamplay_Items_Armor_f); + Cmd_AddCommand ("menu_teamplay_weapons", M_Menu_Teamplay_Items_Weapons_f); + Cmd_AddCommand ("menu_teamplay_powerups", M_Menu_Teamplay_Items_Powerups_f); + Cmd_AddCommand ("menu_teamplay_ammo_health", M_Menu_Teamplay_Items_Ammo_Health_f); + Cmd_AddCommand ("menu_teamplay_team_fortress", M_Menu_Teamplay_Items_Team_Fortress_f); + Cmd_AddCommand ("menu_teamplay_status_location_misc", M_Menu_Teamplay_Items_Status_Location_Misc_f); + Cmd_AddCommand ("menu_particles", M_Menu_Particles_f); + Cmd_AddCommand ("menu_network", M_Menu_Network_f); #ifdef WEBCLIENT - Cmd_AddRemCommand ("menu_download", Menu_DownloadStuff_f); + Cmd_AddCommand ("menu_download", Menu_DownloadStuff_f); #endif #ifdef CL_MASTER - Cmd_AddRemCommand ("quickconnect", M_QuickConnect_f); + Cmd_AddCommand ("quickconnect", M_QuickConnect_f); #endif } diff --git a/engine/client/merged.h b/engine/client/merged.h index cf89acf77..f3a40c9d0 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -87,7 +87,6 @@ extern void (*R_RenderView) (void); // must set r_refdef first extern void (*R_NewMap) (void); extern void (*R_PreNewMap) (void); -extern int (*R_LightPoint) (vec3_t point); extern void (*R_AddStain) (vec3_t org, float red, float green, float blue, float radius); extern void (*R_LessenStains) (void); @@ -167,7 +166,7 @@ struct texid_s union { unsigned int num; -#ifdef D3DQUAKE +#if defined(D3DQUAKE) || defined(SWQUAKE) void *ptr; #endif }; @@ -248,7 +247,6 @@ typedef struct rendererinfo_s { void (*R_NewMap) (void); void (*R_PreNewMap) (void); - int (*R_LightPoint) (vec3_t point); void (*R_AddStain) (vec3_t org, float red, float green, float blue, float radius); void (*R_LessenStains) (void); diff --git a/engine/client/p_script.c b/engine/client/p_script.c index b97dbd986..f3ab3fdec 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -2031,16 +2031,16 @@ static qboolean PScript_InitParticles (void) memset(trailstates, 0, r_numtrailstates * sizeof(trailstate_t)); ts_cycle = 0; - Cmd_AddRemCommand("pointfile", P_ReadPointFile_f); //load the leak info produced from qbsp into the particle system to show a line. :) + Cmd_AddCommand("pointfile", P_ReadPointFile_f); //load the leak info produced from qbsp into the particle system to show a line. :) - Cmd_AddRemCommand("r_part", P_ParticleEffect_f); + Cmd_AddCommand("r_part", P_ParticleEffect_f); - Cmd_AddRemCommand("r_exportbuiltinparticles", P_ExportBuiltinSet_f); - Cmd_AddRemCommand("r_importeffectinfo", P_ImportEffectInfo_f); + Cmd_AddCommand("r_exportbuiltinparticles", P_ExportBuiltinSet_f); + Cmd_AddCommand("r_importeffectinfo", P_ImportEffectInfo_f); #if _DEBUG - Cmd_AddRemCommand("r_partinfo", P_PartInfo_f); - Cmd_AddRemCommand("r_beaminfo", P_BeamInfo_f); + Cmd_AddCommand("r_partinfo", P_PartInfo_f); + Cmd_AddCommand("r_beaminfo", P_BeamInfo_f); #endif diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index a50ccc1c8..e909176e4 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -120,6 +120,7 @@ extern sfx_t *cl_sfx_r_exp3; /*These are pointers to the csqc's globals.*/ \ globalfloat(svtime, "time"); /*float Written before entering most qc functions*/ \ globalfloat(frametime, "frametime"); /*float Written before entering most qc functions*/ \ + globalfloat(gamespeed, "gamespeed"); /*float Written before entering most qc functions*/ \ globalfloat(cltime, "cltime"); /*float Written before entering most qc functions*/ \ globalfloat(physics_mode, "physics_mode"); /*float Written before entering most qc functions*/ \ globalentity(self, "self"); /*entity Written before entering most qc functions*/ \ @@ -1622,20 +1623,19 @@ static void QCBUILTIN PF_cs_tracetoss (progfuncs_t *prinst, struct globalvars_s cs_settracevars(&trace); } -static int CS_PointContents(vec3_t org) -{ - if (!cl.worldmodel) - return FTECONTENTS_EMPTY; - return cl.worldmodel->funcs.PointContents(cl.worldmodel, NULL, org); -} static void QCBUILTIN PF_cs_pointcontents(progfuncs_t *prinst, struct globalvars_s *pr_globals) { + world_t *w = prinst->parms->user; + float *v; int cont; v = G_VECTOR(OFS_PARM0); - cont = CS_PointContents(v); + if (!cl.worldmodel) + return FTECONTENTS_EMPTY; + + cont = World_PointContents(w, v); if (cont & FTECONTENTS_SOLID) G_FLOAT(OFS_RETURN) = Q1CONTENTS_SOLID; else if (cont & FTECONTENTS_SKY) @@ -2080,6 +2080,11 @@ static void QCBUILTIN PF_cs_getinputstate (progfuncs_t *prinst, struct globalvar extern usercmd_t independantphysics[MAX_SPLITS]; f = G_FLOAT(OFS_PARM0); + if (cl.paused && f >= cls.netchan.incoming_sequence) + { + G_FLOAT(OFS_RETURN) = false; + return; + } if (f > cls.netchan.outgoing_sequence) { G_FLOAT(OFS_RETURN) = false; @@ -2090,8 +2095,6 @@ static void QCBUILTIN PF_cs_getinputstate (progfuncs_t *prinst, struct globalvar G_FLOAT(OFS_RETURN) = false; return; } - if (cl.paused) - f = cls.netchan.outgoing_sequence; /*outgoing_sequence says how many packets have actually been sent, but there's an extra pending packet which has not been sent yet - be warned though, its data will change in the coming frames*/ if (f == cls.netchan.outgoing_sequence) @@ -3460,7 +3463,7 @@ static void QCBUILTIN PF_cs_registercommand (progfuncs_t *prinst, struct globalv if (!strcmp(str, "+showscores") || !strcmp(str, "-showscores") || !strcmp(str, "+showteamscores") || !strcmp(str, "-showteamscores")) return; - Cmd_AddRemCommand(str, CS_ConsoleCommand_f); + Cmd_AddCommand(str, CS_ConsoleCommand_f); } static qboolean csqc_usinglistener; @@ -3499,7 +3502,7 @@ static void CSQC_LerpStateToCSQC(lerpents_t *le, csqcedict_t *ent, qboolean nole ent->xv->lerpfrac = bound(0, cl.servertime - le->newframestarttime, 0.1); -/* if (nolerp) + if (nolerp) { ent->v->origin[0] = le->neworigin[0]; ent->v->origin[1] = le->neworigin[1]; @@ -3508,7 +3511,7 @@ static void CSQC_LerpStateToCSQC(lerpents_t *le, csqcedict_t *ent, qboolean nole ent->v->angles[1] = le->newangle[1]; ent->v->angles[2] = le->newangle[2]; } - else*/ + else { ent->v->origin[0] = le->origin[0]; ent->v->origin[1] = le->origin[1]; @@ -5324,8 +5327,6 @@ void CSQC_Breakpoint_f(void) static void CSQC_GameCommand_f(void); void CSQC_RegisterCvarsAndThings(void) { - PF_Common_RegisterCvars(); - Cmd_AddCommand("coredump_csqc", CSQC_CoreDump); Cmd_AddCommand ("extensionlist_csqc", PR_CSExtensionList_f); Cmd_AddCommand("cl_cmd", CSQC_GameCommand_f); @@ -5401,6 +5402,17 @@ qboolean CSQC_DrawView(void) *csqcg.clientcommandframe = cls.netchan.outgoing_sequence; if (csqcg.servercommandframe) *csqcg.servercommandframe = cl.ackedinputsequence; + if (csqcg.gamespeed) + *csqcg.gamespeed = cl.gamespeed; + } + else + { + if (csqcg.clientcommandframe) + *csqcg.clientcommandframe = cl.ackedinputsequence; + if (csqcg.servercommandframe) + *csqcg.servercommandframe = cl.ackedinputsequence; + if (csqcg.gamespeed) + *csqcg.gamespeed = 0; } if (csqcg.intermission) *csqcg.intermission = cl.intermission; diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 1358b4dff..9a007ae07 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -1933,8 +1933,6 @@ void MP_Reload_f(void) void MP_RegisterCvarsAndCmds(void) { - PF_Common_RegisterCvars(); - Cmd_AddCommand("coredump_menuqc", MP_CoreDump_f); Cmd_AddCommand("menu_restart", MP_Reload_f); diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 0abb20855..b260389b8 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -1340,6 +1340,7 @@ dynamic: ============================================================= */ +#if 0 static qbyte *R_MarkLeafSurfaces_Q1 (void) { qbyte *vis; @@ -1397,6 +1398,7 @@ static qbyte *R_MarkLeafSurfaces_Q1 (void) } return vis; } +#endif /* ================ @@ -1613,6 +1615,7 @@ static void Surf_RecursiveQ2WorldNode (mnode_t *node) #endif #ifdef Q3BSPS +#if 0 static void Surf_LeafWorldNode (void) { int i; @@ -1678,7 +1681,6 @@ static void Surf_LeafWorldNode (void) - { int j; texture_t *tex; @@ -1699,6 +1701,7 @@ static void Surf_LeafWorldNode (void) } } } +#endif static void Surf_RecursiveQ3WorldNode (mnode_t *node, unsigned int clipflags) { @@ -1945,7 +1948,7 @@ void Surf_SetupFrame(void) V_SetContentsColor (r_viewcontents); } - +/* static mesh_t *surfbatchmeshes[256]; static void Surf_BuildBrushBatch(batch_t *batch) { @@ -1958,11 +1961,13 @@ static void Surf_BuildBrushBatch(batch_t *batch) surfbatchmeshes[i] = model->surfaces[batch->surf_first + i].mesh; } } +*/ void Surf_GenBrushBatches(batch_t **batches, entity_t *ent) { int i; msurface_t *s; + batch_t *ob; model_t *model; batch_t *b; unsigned int bef; @@ -2036,77 +2041,32 @@ void Surf_GenBrushBatches(batch_t **batches, entity_t *ent) if (ent->flags & RF_NOSHADOW) bef |= BEF_NOSHADOWS; - if (!model->surfaces && model->batches) + for (i = 0; i < SHADER_SORT_COUNT; i++) + for (ob = model->batches[i]; ob; ob = ob->next) { - for (i = 0; i < model->numsurfaces; i++) + b = BE_GetTempBatch(); + if (!b) + continue; + *b = *ob; + b->shader = R_TextureAnimation(ent->framestate.g[FS_REG].frame[0], b->texture)->shader; + b->meshes = b->maxmeshes; + b->ent = ent; + + if (bef & BEF_FORCEADDITIVE) { - b = BE_GetTempBatch(); - if (!b) - continue; - *b = model->batches[0][i]; - b->mesh = (mesh_t**)&model->batches[0][i].mesh; - b->ent = ent; - - if (bef & BEF_FORCEADDITIVE) - { - b->next = batches[SHADER_SORT_ADDITIVE]; - batches[SHADER_SORT_ADDITIVE] = b; - } - else if (bef & BEF_FORCETRANSPARENT) - { - b->next = batches[SHADER_SORT_BLEND]; - batches[SHADER_SORT_BLEND] = b; - } - else - { - b->next = batches[b->shader->sort]; - batches[b->shader->sort] = b; - } + b->next = batches[SHADER_SORT_ADDITIVE]; + batches[SHADER_SORT_ADDITIVE] = b; } - return; - } - - b = NULL; - for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) - { - if (!b || b->lightmap != s->lightmaptexturenum || b->texture != s->texinfo->texture || b->surf_count >= sizeof(surfbatchmeshes)/sizeof(surfbatchmeshes[0])) + else if (bef & BEF_FORCETRANSPARENT) { - b = BE_GetTempBatch(); - if (!b) - break; - b->buildmeshes = NULL; - b->ent = ent; - b->texture = s->texinfo->texture; - b->shader = R_TextureAnimation(ent->framestate.g[FS_REG].frame[0], b->texture)->shader; - b->skin = &b->shader->defaulttextures; - b->flags = bef; - if (bef & BEF_FORCEADDITIVE) - { - b->next = batches[SHADER_SORT_ADDITIVE]; - batches[SHADER_SORT_ADDITIVE] = b; - } - else if (bef & BEF_FORCETRANSPARENT) - { - b->next = batches[SHADER_SORT_BLEND]; - batches[SHADER_SORT_BLEND] = b; - } - else - { - b->next = batches[b->shader->sort]; - batches[b->shader->sort] = b; - } - b->surf_first = s - model->surfaces; - b->surf_count = 0; - b->buildmeshes = Surf_BuildBrushBatch; - b->meshes = 0; - b->firstmesh = 0; - b->lightmap = s->lightmaptexturenum; - b->mesh = NULL; - b->vbo = &b->texture->vbo; + b->next = batches[SHADER_SORT_BLEND]; + batches[SHADER_SORT_BLEND] = b; + } + else + { + b->next = batches[b->shader->sort]; + batches[b->shader->sort] = b; } - - b->surf_count++; - b->meshes++; } } @@ -2199,9 +2159,9 @@ void Surf_DrawWorld (void) #endif { //extern cvar_t temp1; - if (0)//temp1.value) - vis = R_MarkLeafSurfaces_Q1(); - else +// if (0)//temp1.value) +// vis = R_MarkLeafSurfaces_Q1(); +// else { vis = R_MarkLeaves_Q1 (); if (!(r_novis.ival & 2)) @@ -2431,6 +2391,20 @@ static int Surf_LM_FillBlock (int texnum, int w, int h, int x, int y) return texnum; } +unsigned int Surf_CalcMemSize(msurface_t *surf) +{ + if (surf->mesh) + return 0; + + if (!surf->numedges) + return 0; + + //figure out how much space this surface needs + return sizeof(mesh_t) + + sizeof(index_t)*(surf->numedges-2)*3 + + (sizeof(vecV_t)+sizeof(vec2_t)*2+sizeof(vec3_t)*3+sizeof(vec4_t))*surf->numedges; +} + /* ================ BuildSurfaceDisplayList @@ -2438,13 +2412,14 @@ FIXME: this is probably misplaced lightmaps are already built by the time this is called ================ */ -void Surf_BuildSurfaceDisplayList (model_t *model, msurface_t *fa) +void Surf_BuildSurfaceDisplayList (model_t *model, msurface_t *fa, void **mem) { int i, lindex, lnumverts; medge_t *pedges, *r_pedge; int vertpage; float *vec; - float s, t; + float s, t, d; + mesh_t *mesh; // reconstruct the polygon pedges = model->edges; @@ -2457,80 +2432,80 @@ void Surf_BuildSurfaceDisplayList (model_t *model, msurface_t *fa) return; } - { //build a nice mesh instead of a poly. - int size = sizeof(mesh_t) + sizeof(index_t)*(lnumverts-2)*3 + (sizeof(vecV_t) + 3*sizeof(vec3_t) + 2*sizeof(vec2_t) + sizeof(vec4_t))*lnumverts; - mesh_t *mesh; + fa->mesh = mesh = *mem; + mesh->xyz_array = (vecV_t*)(mesh + 1); + mesh->normals_array = (vec3_t*)(mesh->xyz_array + lnumverts); + mesh->snormals_array = (vec3_t*)(mesh->normals_array + lnumverts); + mesh->tnormals_array = (vec3_t*)(mesh->snormals_array + lnumverts); + mesh->st_array = (vec2_t*)(mesh->tnormals_array + lnumverts); + mesh->lmst_array = (vec2_t*)(mesh->st_array + lnumverts); + mesh->colors4f_array = (vec4_t*)(mesh->lmst_array + lnumverts); + mesh->indexes = (index_t*)(mesh->colors4f_array + lnumverts); + *mem = (void*)(mesh->indexes + (lnumverts-2)*3); - fa->mesh = mesh = Hunk_Alloc(size); - mesh->xyz_array = (vecV_t*)(mesh + 1); - mesh->normals_array = (vec3_t*)(mesh->xyz_array + lnumverts); - mesh->snormals_array = (vec3_t*)(mesh->normals_array + lnumverts); - mesh->tnormals_array = (vec3_t*)(mesh->snormals_array + lnumverts); - mesh->st_array = (vec2_t*)(mesh->tnormals_array + lnumverts); - mesh->lmst_array = (vec2_t*)(mesh->st_array + lnumverts); - mesh->colors4f_array = (vec4_t*)(mesh->lmst_array + lnumverts); - mesh->indexes = (index_t*)(mesh->colors4f_array + lnumverts); + mesh->numindexes = (lnumverts-2)*3; + mesh->numvertexes = lnumverts; + mesh->istrifan = true; - mesh->numindexes = (lnumverts-2)*3; - mesh->numvertexes = lnumverts; - mesh->istrifan = true; + for (i=0 ; iindexes[i*3] = 0; + mesh->indexes[i*3+1] = i+1; + mesh->indexes[i*3+2] = i+2; + } - for (i=0 ; isurfedges[fa->firstedge + i]; + + if (lindex > 0) { - mesh->indexes[i*3] = 0; - mesh->indexes[i*3+1] = i+1; - mesh->indexes[i*3+2] = i+2; + r_pedge = &pedges[lindex]; + vec = model->vertexes[r_pedge->v[0]].position; + } + else + { + r_pedge = &pedges[-lindex]; + vec = model->vertexes[r_pedge->v[1]].position; } - for (i=0 ; isurfedges[fa->firstedge + i]; + s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; + t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; - if (lindex > 0) - { - r_pedge = &pedges[lindex]; - vec = model->vertexes[r_pedge->v[0]].position; - } - else - { - r_pedge = &pedges[-lindex]; - vec = model->vertexes[r_pedge->v[1]].position; - } + VectorCopy (vec, mesh->xyz_array[i]); + mesh->st_array[i][0] = s/fa->texinfo->texture->width; + mesh->st_array[i][1] = t/fa->texinfo->texture->height; - s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3]; - t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3]; + s -= fa->texturemins[0]; + s += fa->light_s*16; + s += 8; + s /= LMBLOCK_WIDTH*16; - VectorCopy (vec, mesh->xyz_array[i]); - mesh->st_array[i][0] = s/fa->texinfo->texture->width; - mesh->st_array[i][1] = t/fa->texinfo->texture->height; + t -= fa->texturemins[1]; + t += fa->light_t*16; + t += 8; + t /= LMBLOCK_HEIGHT*16; - s -= fa->texturemins[0]; - s += fa->light_s*16; - s += 8; - s /= LMBLOCK_WIDTH*16; + mesh->lmst_array[i][0] = s; + mesh->lmst_array[i][1] = t; - t -= fa->texturemins[1]; - t += fa->light_t*16; - t += 8; - t /= LMBLOCK_HEIGHT*16; + if (fa->flags & SURF_PLANEBACK) + VectorNegate(fa->plane->normal, mesh->normals_array[i]); + else + VectorCopy(fa->plane->normal, mesh->normals_array[i]); + VectorNegate(fa->texinfo->vecs[0], mesh->snormals_array[i]); + VectorNegate(fa->texinfo->vecs[1], mesh->tnormals_array[i]); + d = -DotProduct(mesh->normals_array[i], mesh->snormals_array[i]); + VectorMA(mesh->snormals_array[i], d, mesh->normals_array[i], mesh->snormals_array[i]); + d = -DotProduct(mesh->normals_array[i], mesh->tnormals_array[i]); + VectorMA(mesh->tnormals_array[i], d, mesh->normals_array[i], mesh->tnormals_array[i]); + VectorNormalize(mesh->snormals_array[i]); + VectorNormalize(mesh->tnormals_array[i]); - mesh->lmst_array[i][0] = s; - mesh->lmst_array[i][1] = t; - - if (fa->flags & SURF_PLANEBACK) - VectorNegate(fa->plane->normal, mesh->normals_array[i]); - else - VectorCopy(fa->plane->normal, mesh->normals_array[i]); - VectorNegate(fa->texinfo->vecs[0], mesh->snormals_array[i]); - VectorNegate(fa->texinfo->vecs[1], mesh->tnormals_array[i]); - VectorNormalize(mesh->snormals_array[i]); - VectorNormalize(mesh->tnormals_array[i]); - - mesh->colors4f_array[i][0] = 1; - mesh->colors4f_array[i][1] = 1; - mesh->colors4f_array[i][2] = 1; - mesh->colors4f_array[i][3] = 1; - } + mesh->colors4f_array[i][0] = 1; + mesh->colors4f_array[i][1] = 1; + mesh->colors4f_array[i][2] = 1; + mesh->colors4f_array[i][3] = 1; } } @@ -2627,6 +2602,7 @@ void Surf_DeInit(void) void Surf_Clear(model_t *mod) { batch_t *b; + vbo_t *vbo; int i; if (mod->fromgame == fg_doom3) return;/*they're on the hunk*/ @@ -2640,41 +2616,22 @@ void Surf_Clear(model_t *mod) Z_Free(b); } } -} - -/* -================== -GL_BuildLightmaps - -Builds the lightmap texture -with all the surfaces from all brush models -Groups surfaces into their respective batches (based on the lightmap number). -================== -*/ -void Surf_BuildLightmaps (void) -{ - int i, j, t; - model_t *m; - int shift; - msurface_t *surf; - batch_t *batch, *bstop; - vec3_t sn; - int sortid; - int ptype; - - r_framecount = 1; // no dlightcache - - for (i = 0; i < numlightmaps; i++) + while(mod->vbos) { - if (!lightmap[i]) - break; - BZ_Free(lightmap[i]); - lightmap[i] = NULL; + vbo = mod->vbos; + mod->vbos = vbo->next; + BE_ClearVBO(vbo); } - if (cl.worldmodel->fromgame == fg_doom) - return; //no lightmaps. + BZ_Free(mod->shadowbatches); + mod->numshadowbatches = 0; + mod->shadowbatches = NULL; + Sh_PurgeShadowMeshes(); +} +//pick fastest mode for lightmap data +void Surf_LightmapMode(void) +{ lightmap_bgra = true; switch(qrenderer) @@ -2713,82 +2670,141 @@ void Surf_BuildLightmaps (void) case QR_NONE: break; } +} + +/* +================== +GL_BuildLightmaps + +Builds the lightmap texture +with all the surfaces from all brush models +Groups surfaces into their respective batches (based on the lightmap number). +================== +*/ +void Surf_BuildLightmaps (void) +{ + int i, j, t; + model_t *m; + int shift; + msurface_t *surf; + batch_t *batch, *bstop; + vec3_t sn; + int sortid; + int ptype; + void *mem; + unsigned int memsize; + + r_framecount = 1; // no dlightcache + + for (i = 0; i < numlightmaps; i++) + { + if (!lightmap[i]) + break; + BZ_Free(lightmap[i]); + lightmap[i] = NULL; + } + + Surf_LightmapMode(); + + if (cl.worldmodel->fromgame == fg_doom) + return; //no lightmaps. for (j=1 ; jname[0] == '*') + if (m->type != mod_brush) continue; currentmodel = m; shift = Surf_LightmapShift(currentmodel); + memsize = 0; + for (i=0; inummodelsurfaces; i++) + { + surf = m->surfaces + i + m->firstmodelsurface; + memsize += Surf_CalcMemSize(surf); + } + mem = Hunk_AllocName(memsize, m->name); + + for (i=0; inummodelsurfaces; i++) + { + surf = m->surfaces + i + m->firstmodelsurface; + if (surf->mesh) //there are some surfaces that have a display list already (q3 ones) + continue; + Surf_CreateSurfaceLightmap (surf, shift); + Surf_BuildSurfaceDisplayList (m, surf, &mem); + } + for (t = m->numtextures-1; t >= 0; t--) { if (m == cl.worldmodel) ptype = P_FindParticleType(va("tex_%s", m->textures[t]->name)); else ptype = P_INVALID; - m->textures[t]->wtexno = t; sortid = m->textures[t]->shader->sort; bstop = m->batches[sortid]; batch = NULL; - for (i=0 ; inumsurfaces ; i++) + for (i=0; inummodelsurfaces; i++) {//extra texture loop so we get slightly less texture switches - surf = m->surfaces + i; + surf = m->surfaces + i + m->firstmodelsurface; if (surf->texinfo->texture == m->textures[t]) { P_EmitSkyEffectTris(m, surf, ptype); - Surf_CreateSurfaceLightmap (surf, shift); /*the excessive logic is to give portals separate batches for separate planes*/ - if (sortid == SHADER_SORT_PORTAL) + if (sortid == SHADER_SORT_PORTAL || (m->textures[t]->shader->flags & (SHADER_HASREFLECT | SHADER_HASREFRACT))) { if (surf->flags & SURF_PLANEBACK) VectorNegate(surf->plane->normal, sn); else VectorCopy(surf->plane->normal, sn); + + if (!batch || batch->lightmap != surf->lightmaptexturenum || batch->firstmesh + surf->mesh->numvertexes > MAX_INDICIES || !VectorCompare(sn, batch->normal)) + { + for (batch = m->batches[sortid]; batch != bstop; batch = batch->next) + { + if (batch->lightmap == surf->lightmaptexturenum && VectorCompare(sn, batch->normal) && batch->firstmesh + surf->mesh->numvertexes <= MAX_INDICIES) + break; + } + if (batch == bstop) + { + batch = Z_Malloc(sizeof(*batch)); + batch->lightmap = surf->lightmaptexturenum; + batch->texture = m->textures[t]; + batch->next = m->batches[sortid]; + batch->ent = &r_worldentity; + VectorCopy(sn, batch->normal); + m->batches[sortid] = batch; + } + } } else - VectorClear(sn); - if (!batch || batch->lightmap != surf->lightmaptexturenum || (sortid == SHADER_SORT_PORTAL && !VectorCompare(sn, batch->normal))) { - if (sortid == SHADER_SORT_PORTAL) + if (!batch || batch->lightmap != surf->lightmaptexturenum || batch->firstmesh + surf->mesh->numvertexes > MAX_INDICIES) { for (batch = m->batches[sortid]; batch != bstop; batch = batch->next) { - if (batch->lightmap == surf->lightmaptexturenum && VectorCompare(sn, batch->normal)) + if (batch->lightmap == surf->lightmaptexturenum && batch->firstmesh + surf->mesh->numvertexes <= MAX_INDICIES) break; } - } - else - { - for (batch = m->batches[sortid]; batch != bstop; batch = batch->next) + if (batch == bstop) { - if (batch->lightmap == surf->lightmaptexturenum) - break; + batch = Z_Malloc(sizeof(*batch)); + batch->lightmap = surf->lightmaptexturenum; + batch->texture = m->textures[t]; + batch->next = m->batches[sortid]; + batch->ent = &r_worldentity; + VectorClear(batch->normal); + m->batches[sortid] = batch; } } - if (batch == bstop) - { - batch = Z_Malloc(sizeof(*batch)); - batch->lightmap = surf->lightmaptexturenum; - batch->texture = m->textures[t]; - batch->next = m->batches[sortid]; - batch->ent = &r_worldentity; - VectorCopy(sn, batch->normal); - m->batches[sortid] = batch; - } } surf->sbatch = batch; batch->maxmeshes++; - - if (m->surfaces[i].mesh) //there are some surfaces that have a display list already (q3 ones) - continue; - Surf_BuildSurfaceDisplayList (m, surf); + batch->firstmesh += surf->mesh->numvertexes; } } } @@ -2797,12 +2813,24 @@ void Surf_BuildLightmaps (void) { batch->mesh = BZ_Malloc(sizeof(*batch->mesh)*batch->maxmeshes*2); } + for (i=0; inummodelsurfaces; i++) + { + surf = m->surfaces + i + m->firstmodelsurface; + surf->sbatch->mesh[surf->sbatch->meshes++] = surf->mesh; + } BE_GenBrushModelVBO(m); - for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) + /*for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) for (batch = m->batches[sortid]; batch != NULL; batch = batch->next) { batch->vbo = &batch->texture->vbo; } + */ + for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) + for (batch = m->batches[sortid]; batch != NULL; batch = batch->next) + { + batch->firstmesh = 0; + batch->meshes = 0; + } } BE_UploadAllLightmaps(); diff --git a/engine/client/render.h b/engine/client/render.h index ff9b16cfd..759693ae2 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -197,7 +197,6 @@ void Surf_WipeStains(void); void Surf_DeInit(void); void Surf_Clear(struct model_s *mod); void Surf_BuildLightmaps(void); -void Surf_BuildSurfaceDisplayList (struct model_s *mod, struct msurface_s *fa); void Surf_RenderDynamicLightmaps (struct msurface_s *fa); void Surf_RenderAmbientLightmaps (struct msurface_s *fa, int ambient); int Surf_LightmapShift (struct model_s *model); @@ -249,17 +248,13 @@ void GLR_NewMap (void); void GLR_PushDlights (void); void GLR_DrawWaterSurfaces (void); -void MediaGL_ShowFrame8bit(qbyte *framedata, int inwidth, int inheight, qbyte *palette); -void MediaGL_ShowFrameRGBA_32(qbyte *framedata, int inwidth, int inheight); //top down -void MediaGL_ShowFrameBGR_24_Flip(qbyte *framedata, int inwidth, int inheight); //input is bottom up... - void GLVID_DeInit (void); void GLR_DeInit (void); void GLSCR_DeInit (void); void GLVID_Console_Resize(void); - -int GLR_LightPoint (vec3_t p); #endif +int R_LightPoint (vec3_t p); +void R_RenderDlights (void); enum imageflags { diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 1f9eb22d9..3341cfe81 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -126,6 +126,7 @@ cvar_t r_stainfadetime = SCVAR ("r_stainfadetime", "1"); cvar_t r_stains = CVARFC("r_stains", IFMINIMAL("0","0.75"), CVAR_ARCHIVE, Cvar_Limiter_ZeroToOne_Callback); +cvar_t r_postprocshader = CVARD("r_postprocshader", "", "Specifies a shader to use as a post-processing shader"); cvar_t r_wallcolour = CVARAF ("r_wallcolour", "128 128 128", "r_wallcolor", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);//FIXME: broken cvar_t r_walltexture = CVARF ("r_walltexture", "", @@ -323,6 +324,8 @@ cvar_t r_shadow_realtime_world_shadows = SCVARF ("r_shadow_realtime_world_shado cvar_t r_shadow_realtime_dlight = SCVARF ("r_shadow_realtime_dlight", "1", CVAR_ARCHIVE); cvar_t r_shadow_realtime_dlight_shadows = SCVARF ("r_shadow_realtime_dlight_shadows", "1", CVAR_ARCHIVE); cvar_t r_shadow_realtime_world_lightmaps = SCVARF ("r_shadow_realtime_world_lightmaps", "0", 0); +cvar_t r_sun_dir = SCVAR ("r_sun_dir", "0.2 0.5 0.8"); +cvar_t r_sun_colour = SCVARF ("r_sun_colour", "0 0 0", CVAR_ARCHIVE); cvar_t r_vertexdlights = SCVAR ("r_vertexdlights", "0"); @@ -374,6 +377,7 @@ void GLRenderer_Init(void) Cvar_Register (&gl_finish, GLRENDEREROPTIONS); Cvar_Register (&gl_lateswap, GLRENDEREROPTIONS); Cvar_Register (&gl_lerpimages, GLRENDEREROPTIONS); + Cvar_Register (&r_postprocshader, GLRENDEREROPTIONS); Cvar_Register (&dpcompat_psa_ungroup, GLRENDEREROPTIONS); Cvar_Register (&r_noportals, GLRENDEREROPTIONS); @@ -412,7 +416,6 @@ void GLRenderer_Init(void) Cvar_Register (&gl_texture_anisotropic_filtering, GLRENDEREROPTIONS); Cvar_Register (&gl_savecompressedtex, GLRENDEREROPTIONS); Cvar_Register (&gl_compress, GLRENDEREROPTIONS); - Cvar_Register (&gl_driver, GLRENDEREROPTIONS); Cvar_Register (&gl_detail, GRAPHICALNICETIES); Cvar_Register (&gl_detailscale, GRAPHICALNICETIES); Cvar_Register (&gl_overbright, GRAPHICALNICETIES); @@ -438,7 +441,6 @@ void GLRenderer_Init(void) Cvar_Register (&gl_schematics, GLRENDEREROPTIONS); Cvar_Register (&r_vertexlight, GLRENDEREROPTIONS); - Cvar_Register (&gl_shadeq1_name, GLRENDEREROPTIONS); Cvar_Register (&gl_blend2d, GLRENDEREROPTIONS); @@ -458,7 +460,6 @@ void R_InitTextures (void) // create a simple checkerboard texture for the default r_notexture_mip = Z_Malloc (sizeof(texture_t) + 16*16+8*8+4*4+2*2); - r_notexture_mip->pixbytes = 1; r_notexture_mip->width = r_notexture_mip->height = 16; r_notexture_mip->offsets[0] = sizeof(texture_t); r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16; @@ -512,11 +513,21 @@ void Renderer_Init(void) GLRenderer_Init(); #endif +#ifdef SWQUAKE + { + extern cvar_t sw_interlace; + extern cvar_t sw_threads; + Cvar_Register(&sw_interlace, "Software Rendering Options"); + Cvar_Register(&sw_threads, "Software Rendering Options"); + } +#endif + Cvar_Register (&gl_conback, GRAPHICALNICETIES); Cvar_Register (&r_novis, GLRENDEREROPTIONS); //but register ALL vid_ commands. + Cvar_Register (&gl_driver, GLRENDEREROPTIONS); Cvar_Register (&_vid_wait_override, VIDCOMMANDGROUP); Cvar_Register (&_windowed_mouse, VIDCOMMANDGROUP); Cvar_Register (&vid_renderer, VIDCOMMANDGROUP); @@ -563,7 +574,8 @@ void Renderer_Init(void) Cvar_Register (&r_shadow_realtime_dlight, GRAPHICALNICETIES); Cvar_Register (&r_shadow_realtime_dlight_shadows, GRAPHICALNICETIES); Cvar_Register (&r_shadow_realtime_world_lightmaps, GRAPHICALNICETIES); - + Cvar_Register (&r_sun_dir, GRAPHICALNICETIES); + Cvar_Register (&r_sun_colour, GRAPHICALNICETIES); Cvar_Register(&scr_viewsize, SCREENOPTIONS); Cvar_Register(&scr_fov, SCREENOPTIONS); @@ -616,6 +628,7 @@ void Renderer_Init(void) Cvar_Register (&r_fastsky, GRAPHICALNICETIES); Cvar_Register (&r_fastskycolour, GRAPHICALNICETIES); Cvar_Register (&r_wateralpha, GRAPHICALNICETIES); + Cvar_Register (&gl_shadeq1_name, GLRENDEREROPTIONS); Cvar_Register (&r_clear, GLRENDEREROPTIONS); Cvar_Register (&gl_max_size, GLRENDEREROPTIONS); @@ -683,7 +696,6 @@ void (*R_RenderView) (void); // must set r_refdef first void (*R_NewMap) (void); void (*R_PreNewMap) (void); -int (*R_LightPoint) (vec3_t point); void (*R_AddStain) (vec3_t org, float red, float green, float blue, float radius); void (*R_LessenStains) (void); @@ -747,7 +759,6 @@ rendererinfo_t dedicatedrendererinfo = { NULL, //R_NewMap; NULL, //R_PreNewMap - NULL, //R_LightPoint; NULL, //R_AddStain; @@ -806,9 +817,9 @@ rendererinfo_t dedicatedrendererinfo = { rendererinfo_t *pdedicatedrendererinfo = &dedicatedrendererinfo; rendererinfo_t openglrendererinfo; -rendererinfo_t d3dfglrendererinfo; rendererinfo_t d3drendererinfo; +rendererinfo_t swrendererinfo; rendererinfo_t *rendererinfo[] = { @@ -817,11 +828,13 @@ rendererinfo_t *rendererinfo[] = #endif #ifdef GLQUAKE &openglrendererinfo, - &d3dfglrendererinfo, #endif #ifdef D3DQUAKE &d3drendererinfo, #endif +#ifdef SWQUAKE + &swrendererinfo, +#endif }; @@ -842,7 +855,6 @@ void R_SetRenderer(rendererinfo_t *ri) R_RenderView = ri->R_RenderView; R_NewMap = ri->R_NewMap; R_PreNewMap = ri->R_PreNewMap; - R_LightPoint = ri->R_LightPoint; R_AddStain = ri->R_AddStain; R_LessenStains = ri->R_LessenStains; @@ -928,6 +940,22 @@ void R_ShutdownRenderer(void) S_Shutdown(); } +void R_GenPaletteLookup(void) +{ + int r,g,b,i; + unsigned char *pal = host_basepal; + for (i=0 ; i<256 ; i++) + { + r = pal[0]; + g = pal[1]; + b = pal[2]; + pal += 3; + + d_8to24rgbtable[i] = (255<<24) + (r<<0) + (g<<8) + (b<<16); + } + d_8to24rgbtable[255] &= 0xffffff; // 255 is transparent +} + qboolean R_ApplyRenderer (rendererstate_t *newr) { if (newr->bpp == -1) @@ -970,7 +998,7 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr) isDedicated = false; #endif if (newr) - Con_Printf("Setting mode %i*%i*%i*%i\n", newr->width, newr->height, newr->bpp, newr->rate); + Con_Printf("Setting mode %i*%i*%i*%i %s\n", newr->width, newr->height, newr->bpp, newr->rate, newr->renderer->description); if (host_basepal) BZ_Free(host_basepal); @@ -1015,6 +1043,8 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr) BZ_Free(colormap); } + R_GenPaletteLookup(); + if (h2playertranslations) BZ_Free(h2playertranslations); h2playertranslations = FS_LoadMallocFile ("gfx/player.lmp"); @@ -2095,6 +2125,9 @@ void R_SetFrustum (float projmat[16], float viewmat[16]) frustum[i].signbits = SignbitsForPlane (&frustum[i]); } + if (r_refdef.recurse) + return; + #if FRUSTUMPLANES > 4 //do far plane //fog will not logically not actually reach 0, though precision issues will force it. we cut off at an exponant of -500 diff --git a/engine/client/screen.h b/engine/client/screen.h index 5fb15da07..794c08c9b 100644 --- a/engine/client/screen.h +++ b/engine/client/screen.h @@ -94,6 +94,7 @@ enum }; int SCR_GetLoadingStage(void); void SCR_SetLoadingStage(int stage); +void SCR_SetLoadingFile(char *str); /*fonts*/ diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index 776cb49f2..3c3ecde89 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -1189,6 +1189,8 @@ void S_Shutdown(void) sound_started = 0; S_Purge(false); + + num_sfx = 0; } @@ -1258,10 +1260,8 @@ void S_Purge(qboolean retaintouched) /*if there's any data associated still, kill it. if present, it should be a single sfxcache_t (with data in same alloc)*/ if (sfx->decoder.buf) - { BZ_Free(sfx->decoder.buf); - sfx->decoder.buf = NULL; - } + memset(&sfx->decoder, 0, sizeof(sfx->decoder)); } S_UnlockMixer(); } diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 03582adbc..7658b9f8a 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -30,6 +30,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include +//#define RESTARTTEST + #ifdef MULTITHREAD #include #endif @@ -51,6 +53,10 @@ unsigned int sys_parenttop; unsigned int sys_parentwidth; //valid if sys_parentwindow is set unsigned int sys_parentheight; + +#ifdef RESTARTTEST +jmp_buf restart_jmpbuf; +#endif /* ================ Sys_RandomBytes @@ -873,6 +879,10 @@ void Sys_Quit (void) SV_Shutdown(); #endif +#ifdef RESTARTTEST + longjmp(restart_jmpbuf, 1); +#endif + #ifdef NPFTE { extern jmp_buf host_abort; @@ -1759,6 +1769,7 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin if (hPrevInstance) return 0; + #ifndef MINGW #if _MSC_VER > 1200 Win7_Init(); @@ -1851,6 +1862,10 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin } } +#ifdef RESTARTTEST + setjmp (restart_jmpbuf); +#endif + GetModuleFileName(NULL, cwd, sizeof(cwd)-1); strcpy(exename, COM_SkipPath(cwd)); parms.argv = (const char **)argv; diff --git a/engine/client/vid.h b/engine/client/vid.h index 2d5878bd1..ff0a0c7bc 100644 --- a/engine/client/vid.h +++ b/engine/client/vid.h @@ -25,7 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // a pixel can be one, two, or four bytes typedef qbyte pixel_t; -typedef enum {QR_NONE, QR_OPENGL, QR_DIRECT3D} r_qrenderer_t; +typedef enum {QR_NONE, QR_OPENGL, QR_DIRECT3D, QR_SOFTWARE} r_qrenderer_t; typedef struct { //you are not allowed to make anything not work if it's not based on these vars... diff --git a/engine/client/view.h b/engine/client/view.h index 1e1a8f7f3..096d064bd 100644 --- a/engine/client/view.h +++ b/engine/client/view.h @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // view.h extern cvar_t v_gamma; +extern cvar_t v_contrast; extern cvar_t lcd_x; extern float sw_blend[4]; extern float hw_blend[4]; diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 19373f574..74b0bed39 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -406,6 +406,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define NORETURN __attribute__((noreturn)) #endif +//I'm making my own restrict, because msvc can't cope if I #define restrict to __restrict, and quite possibly other platforms too +#if __STDC_VERSION__ >= 199901L + #define fte_restrict restrict +#elif defined(_MSC_VER) + #define fte_restrict __restrict +#else + #define fte_restrict +#endif + #ifndef FTE_DEPRECATED #define FTE_DEPRECATED diff --git a/engine/common/bspfile.h b/engine/common/bspfile.h index 7dafa11a0..83465d57e 100644 --- a/engine/common/bspfile.h +++ b/engine/common/bspfile.h @@ -858,7 +858,7 @@ typedef struct int patchheight; } rbspface_t; -#define MAX_ENT_LEAFS 16 +#define MAX_ENT_LEAFS 32 typedef struct pvscache_s { int num_leafs; diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 87022da29..44e5fa6b9 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -988,7 +988,6 @@ typedef struct cmd_function_s xcommand_t function; qbyte restriction; //restriction of admin level - qbyte zmalloced; } cmd_function_t; @@ -1438,44 +1437,8 @@ void Cmd_TokenizePunctation (char *text, char *punctuation) Cmd_AddCommand ============ */ -qboolean Cmd_AddCommand (char *cmd_name, xcommand_t function) -{ - cmd_function_t *cmd; - if (host_initialized) // because hunk allocation would get stomped - Sys_Error ("Cmd_AddCommand after host_initialized"); - -// fail if the command is a variable name - if (Cvar_VariableString(cmd_name)[0]) - { - Con_Printf ("Cmd_AddCommand: %s already defined as a var\n", cmd_name); - return false; - } - -// fail if the command already exists - for (cmd=cmd_functions ; cmd ; cmd=cmd->next) - { - if (!Q_strcmp (cmd_name, cmd->name)) - { - if (cmd->function == function) //happens a lot with q3 - Con_DPrintf ("Cmd_AddCommand: %s already defined\n", cmd_name); - else - Con_Printf ("Cmd_AddCommand: %s already defined\n", cmd_name); - return false; - } - } - - cmd = (cmd_function_t*)Hunk_AllocName (sizeof(cmd_function_t), cmd_name); - cmd->name = cmd_name; - cmd->function = function; - cmd->next = cmd_functions; - cmd->restriction = 0; - cmd_functions = cmd; - - return true; -} - -qboolean Cmd_AddRemCommand (char *cmd_name, xcommand_t function) +qboolean Cmd_AddCommand (char *cmd_name, xcommand_t function) { cmd_function_t *cmd; @@ -1508,7 +1471,6 @@ qboolean Cmd_AddRemCommand (char *cmd_name, xcommand_t function) cmd->function = function; cmd->next = cmd_functions; cmd->restriction = 0; - cmd->zmalloced = true; cmd_functions = cmd; return true; @@ -1530,11 +1492,6 @@ void Cmd_RemoveCommand (char *cmd_name) if (!strcmp (cmd_name, cmd->name)) { *back = cmd->next; - if (!cmd->zmalloced) - { - Con_Printf("Cmd_RemoveCommand: %s was not added dynamically\n", cmd_name); - return; - } Z_Free (cmd); return; } @@ -2821,8 +2778,6 @@ void Cmd_WriteConfig_f(void) Cvar_WriteVariables (f, true); VFS_CLOSE(f); - FS_FlushFSHash(); - Cvar_Saved(); } @@ -2889,13 +2844,19 @@ void Cmd_Condump_f(void) void Cmd_Shutdown(void) { + cmd_function_t *c; cmdalias_t *a; //make sure we get no other execution int level; for (level = 0; level < sizeof(cmd_text)/sizeof(cmd_text[0]); level++) SZ_Clear (&cmd_text[level].buf); - cmd_functions = NULL; + while(cmd_functions) + { + c = cmd_functions; + cmd_functions = c->next; + Z_Free(c); + } while(cmd_alias) { a = cmd_alias; @@ -3015,7 +2976,7 @@ void Cmd_Init (void) Cvar_Register(&dpcompat_set, "Darkplaces compatibility"); #ifndef SERVERONLY - rcon_level.ival = atof(rcon_level.string); //client is restricted to not be allowed to change restrictions. + rcon_level.ival = atof(rcon_level.defaultstr); //client is restricted to not be allowed to change restrictions. #else Cvar_Register(&rcon_level, "Access controls"); //server gains versatility. #endif diff --git a/engine/common/cmd.h b/engine/common/cmd.h index 59fad05ea..f7b8057db 100644 --- a/engine/common/cmd.h +++ b/engine/common/cmd.h @@ -73,7 +73,6 @@ void Cmd_Shutdown(void); void Cmd_StuffCmds (void); void Cmd_RemoveCommand (char *cmd_name); -qboolean Cmd_AddRemCommand (char *cmd_name, xcommand_t function); //removable command qboolean Cmd_AddCommand (char *cmd_name, xcommand_t function); // called by the init functions of other parts of the program to // register commands and functions to call for them. diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index a57e167b2..1bd37e9e3 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -351,11 +351,9 @@ static void PSKGenMatrix(float x, float y, float z, float qx, float qy, float qz result[2*4+3] = z; } -#define restrict - #if 0 /*transforms some skeletal vecV_t values*/ -static void Alias_TransformVerticies_V(float *bonepose, int vertcount, qbyte *bidx, float *weights, float *xyzin, float *restrict xyzout) +static void Alias_TransformVerticies_V(float *bonepose, int vertcount, qbyte *bidx, float *weights, float *xyzin, float *fte_restrict xyzout) { int i; float *matrix; @@ -395,8 +393,8 @@ static void Alias_TransformVerticies_V(float *bonepose, int vertcount, qbyte *bi /*transforms some skeletal vecV_t values*/ static void Alias_TransformVerticies_VN(float *bonepose, int vertcount, qbyte *bidx, float *weights, - float *xyzin, float *restrict xyzout, - float *normin, float *restrict normout) + float *xyzin, float *fte_restrict xyzout, + float *normin, float *fte_restrict normout) { int i, j; float *matrix; @@ -441,7 +439,7 @@ static void Alias_TransformVerticies_VN(float *bonepose, int vertcount, qbyte *b #if 0 /*transforms some skeletal vec3_t values*/ -static void Alias_TransformVerticies_3(float *bonepose, int vertcount, qbyte *bidx, float *weights, float *xyzin, float *restrict xyzout) +static void Alias_TransformVerticies_3(float *fte_restrict bonepose, int vertcount, qbyte *bidx, float *weights, float *xyzin, float *fte_restrict xyzout) { int i; float *matrix; @@ -1347,14 +1345,14 @@ static void Alias_BuildSkeletalMesh(mesh_t *mesh, float *bonepose, galiasinfo_t if (inf->ofs_skel_idx) { - float *restrict xyzout = mesh->xyz_array[0]; - float *restrict normout = mesh->normals_array[0]; - qbyte *restrict bidx = (qbyte*)((char*)inf + inf->ofs_skel_idx); - float *restrict xyzin = (float*)((char*)inf + inf->ofs_skel_xyz); - float *restrict normin = (float*)((char*)inf + inf->ofs_skel_norm); - float *restrict svect = (float*)((char*)inf + inf->ofs_skel_svect); - float *restrict tvect = (float*)((char*)inf + inf->ofs_skel_tvect); - float *restrict weight = (float*)((char*)inf + inf->ofs_skel_weight); + float *fte_restrict xyzout = mesh->xyz_array[0]; + float *fte_restrict normout = mesh->normals_array[0]; + qbyte *fte_restrict bidx = (qbyte*)((char*)inf + inf->ofs_skel_idx); + float *fte_restrict xyzin = (float*)((char*)inf + inf->ofs_skel_xyz); + float *fte_restrict normin = (float*)((char*)inf + inf->ofs_skel_norm); + float *fte_restrict svect = (float*)((char*)inf + inf->ofs_skel_svect); + float *fte_restrict tvect = (float*)((char*)inf + inf->ofs_skel_tvect); + float *fte_restrict weight = (float*)((char*)inf + inf->ofs_skel_weight); Alias_TransformVerticies_VN(bonepose, inf->numverts, bidx, weight, xyzin, xyzout, normin, normout); // Alias_TransformVerticies_3(bonepose, inf->numverts, bidx, weight, svect, mesh->snormals_array[0]); @@ -1522,7 +1520,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, ent #ifdef SKELETALMODELS meshcache.usebonepose = NULL; - if (inf->ofs_skel_xyz && !inf->ofs_skel_weight) + if (inf->ofs_skel_xyz && 1)//!inf->ofs_skel_weight) { meshcache.usebonepose = NULL; mesh->xyz_array = (vecV_t*)((char*)inf + inf->ofs_skel_xyz); @@ -1635,6 +1633,8 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, ent if (r_shadow_realtime_world.ival || r_shadow_realtime_dlight.ival) { mesh->xyz2_array = NULL; + mesh->xyz_blendw[0] = 1; + mesh->xyz_blendw[1] = 0; R_LerpFrames(mesh, (galiaspose_t *)((char *)g1 + g1->poseofs + sizeof(galiaspose_t)*frame1), (galiaspose_t *)((char *)g2 + g2->poseofs + sizeof(galiaspose_t)*frame2), 1-lerp, e->fatness); @@ -2815,13 +2815,15 @@ qboolean Mod_LoadQ1Model (model_t *mod, void *buffer) switch(qrenderer) { + default: #if defined(GLQUAKE) || defined(D3DQUAKE) case QR_DIRECT3D: case QR_OPENGL: + case QR_SOFTWARE: pinstverts = (dstvert_t *)Q1_LoadSkins_GL(skinstart, skintranstype); break; #endif - default: + case QR_NONE: pinstverts = (dstvert_t *)Q1_LoadSkins_SV(skinstart, skintranstype); break; } @@ -4022,7 +4024,6 @@ qboolean Mod_LoadQ3Model(model_t *mod, void *buffer) externalskins = LittleLong(surf->numShaders); if (externalskins) { - //extern int gl_bumpmappingpossible; // unused variable char shadname[1024]; skin = Hunk_Alloc((LittleLong(surf->numShaders)+externalskins)*((sizeof(galiasskin_t)+sizeof(shader_t*)))); @@ -5689,7 +5690,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) unsigned short *framedata; vecV_t *opos; - vec3_t *onorm; + vec3_t *onorm1, *onorm2, *onorm3; vec4_t *oweight; byte_vec4_t *oindex; float *opose; @@ -5774,19 +5775,21 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) sizeof(*skin)*h->num_meshes + sizeof(*shaders)*h->num_meshes + #endif sizeof(*fgroup)*(baseposeonly?1:h->num_anims) + sizeof(float)*12*(baseposeonly?h->num_joints:(h->num_poses*h->num_frames)) + sizeof(*bones)*h->num_joints + - (sizeof(*opos) + sizeof(*onorm) + sizeof(*otcoords) + (noweights?0:(sizeof(*oindex)+sizeof(*oweight)))) * h->num_vertexes); + (sizeof(*opos) + sizeof(*onorm1) + sizeof(*onorm2) + sizeof(*onorm3) + sizeof(*otcoords) + (noweights?0:(sizeof(*oindex)+sizeof(*oweight)))) * h->num_vertexes); bones = (galiasbone_t*)(gai + h->num_meshes); opos = (vecV_t*)(bones + h->num_joints); - onorm = (vec3_t*)(opos + h->num_vertexes); + onorm3 = (vec3_t*)(opos + h->num_vertexes); + onorm2 = (vec3_t*)(onorm3 + h->num_vertexes); + onorm1 = (vec3_t*)(onorm2 + h->num_vertexes); if (noweights) { oindex = NULL; oweight = NULL; - otcoords = (vec2_t*)(onorm + h->num_vertexes); + otcoords = (vec2_t*)(onorm1 + h->num_vertexes); } else { - oindex = (byte_vec4_t*)(onorm + h->num_vertexes); + oindex = (byte_vec4_t*)(onorm1 + h->num_vertexes); oweight = (vec4_t*)(oindex + h->num_vertexes); otcoords = (vec2_t*)(oweight + h->num_vertexes); } @@ -5961,9 +5964,9 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) gai[i].shares_verts = i; gai[i].numverts = LittleLong(mesh[i].num_vertexes); gai[i].ofs_skel_xyz = (char*)(opos+offset) - (char*)&gai[i]; - gai[i].ofs_skel_norm = (char*)(onorm+offset) - (char*)&gai[i]; - gai[i].ofs_skel_svect = 0; - gai[i].ofs_skel_tvect = 0; + gai[i].ofs_skel_norm = vnorm?(char*)(onorm1+offset) - (char*)&gai[i]:0; + gai[i].ofs_skel_svect = (vnorm&&vtang)?(char*)(onorm2+offset) - (char*)&gai[i]:0; + gai[i].ofs_skel_tvect = (vnorm&&vtang)?(char*)(onorm3+offset) - (char*)&gai[i]:0; gai[i].ofs_skel_idx = oindex?(char*)(oindex+offset) - (char*)&gai[i]:0; gai[i].ofs_skel_weight = oweight?(char*)(oweight+offset) - (char*)&gai[i]:0; } @@ -5979,7 +5982,18 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) { Vector2Copy(tcoord+i*2, otcoords[i]); VectorCopy(vpos+i*3, opos[i]); - VectorCopy(vnorm+i*4, onorm[i]); + if (vnorm) + { + VectorCopy(vnorm+i*3, onorm1[i]); + } + if (vnorm && vtang) + { + VectorCopy(vtang+i*4, onorm2[i]); + if(LittleFloat(vtang[i*4 + 3]) < 0) + CrossProduct(onorm2[i], onorm1[i], onorm3[i]); + else + CrossProduct(onorm1[i], onorm2[i], onorm3[i]); + } } return gai; } diff --git a/engine/common/common.c b/engine/common/common.c index 4bf39ca3e..db7d32cb4 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -3358,9 +3358,9 @@ void COM_Init (void) COM_CheckRegistered (); if (static_registered) - registered.string = "1"; + registered.defaultstr = "1"; else - registered.string = "0"; + registered.defaultstr = "0"; Cvar_Register (®istered, "Copy protection"); Cvar_Register (&gameversion, "Gamecode"); diff --git a/engine/common/common.h b/engine/common/common.h index c8088e25f..d428af666 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -369,7 +369,9 @@ enum fs_relative{ FS_SKINS //qw/skins/ }; -void FS_FlushFSHash(void); +void FS_FlushFSHashReally(void); +void FS_FlushFSHashWritten(void); +void FS_FlushFSHashRemoved(void); void FS_CreatePath(const char *pname, enum fs_relative relativeto); qboolean FS_Rename(const char *oldf, const char *newf, enum fs_relative relativeto); //0 on success, non-0 on error qboolean FS_Rename2(const char *oldf, const char *newf, enum fs_relative oldrelativeto, enum fs_relative newrelativeto); diff --git a/engine/common/cvar.h b/engine/common/cvar.h index 2b650c99e..bee3106dd 100644 --- a/engine/common/cvar.h +++ b/engine/common/cvar.h @@ -71,11 +71,10 @@ typedef struct cvar_s void (*callback) (struct cvar_s *var, char *oldvalue); char *description; + char *defaultstr; //default int ival; - - char *defaultstr; //default qbyte restriction; #ifdef HLSERVER @@ -85,9 +84,9 @@ typedef struct cvar_s } cvar_t; #ifdef MINIMAL -#define CVARAFDC(ConsoleName,Value,ConsoleName2,Flags,Description,Callback) {ConsoleName, Value, NULL, Flags, 0, 0, 0, ConsoleName2, Callback, NULL} +#define CVARAFDC(ConsoleName,Value,ConsoleName2,Flags,Description,Callback) {ConsoleName, NULL, NULL, Flags, 0, 0, 0, ConsoleName2, Callback, NULL, Value} #else -#define CVARAFDC(ConsoleName,Value,ConsoleName2,Flags,Description,Callback) {ConsoleName, Value, NULL, Flags, 0, 0, 0, ConsoleName2, Callback, Description} +#define CVARAFDC(ConsoleName,Value,ConsoleName2,Flags,Description,Callback) {ConsoleName, NULL, NULL, Flags, 0, 0, 0, ConsoleName2, Callback, Description, Value} #endif #define CVARAFD(ConsoleName,Value,ConsoleName2,Flags,Description)CVARAFDC(ConsoleName, Value, ConsoleName2, Flags, Description, NULL) #define CVARAFC(ConsoleName,Value,ConsoleName2,Flags,Callback) CVARAFC(ConsoleName, Value, ConsoleName2, Flags, NULL, Callback) diff --git a/engine/common/fs.c b/engine/common/fs.c index 47648534f..ea44dddc8 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -413,21 +413,22 @@ static void COM_CopyFile (char *netpath, char *cachepath) int fs_hash_dups; int fs_hash_files; -void FS_FlushFSHash(void) +void FS_FlushFSHashReally(void) { if (filesystemhash.numbuckets) { int i; - bucket_t *bucket, *next; + fsbucket_t *bucket, *next; for (i = 0; i < filesystemhash.numbuckets; i++) { - bucket = filesystemhash.bucket[i]; + bucket = (fsbucket_t*)filesystemhash.bucket[i]; filesystemhash.bucket[i] = NULL; while(bucket) { - next = bucket->next; - if (bucket->key.string == (char*)(bucket+1)) + next = (fsbucket_t*)bucket->buck.next; + /*if the string starts right after the bucket, free it*/ + if (bucket->depth < 0) Z_Free(bucket); bucket = next; } @@ -436,9 +437,53 @@ void FS_FlushFSHash(void) com_fschanged = true; } +void FS_FlushFSHashWritten(void) +{ + /*automatically handled*/ +} +void FS_FlushFSHashRemoved(void) +{ + FS_FlushFSHashReally(); +} + +void FS_AddFileHash(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle) +{ + fsbucket_t *old; + + old = Hash_GetInsensativeBucket(&filesystemhash, fname); + + if (old) + { + fs_hash_dups++; + if (depth >= ((old->depth<0)?(-old->depth-1):old->depth)) + { + return; + } + + //remove the old version + Hash_RemoveBucket(&filesystemhash, fname, &old->buck); + if (old->depth < 0) + Z_Free(old); + } + + if (!filehandle) + { + filehandle = Z_Malloc(sizeof(*filehandle) + strlen(fname)+1); + if (!filehandle) + return; //eep! + strcpy((char*)(filehandle+1), fname); + fname = (char*)(filehandle+1); + filehandle->depth = -depth-1; + } + else filehandle->depth = depth; + + Hash_AddInsensative(&filesystemhash, fname, pathhandle, &filehandle->buck); + fs_hash_files++; +} void FS_RebuildFSHash(void) { + int depth = 1; searchpath_t *search; if (!filesystemhash.numbuckets) { @@ -447,7 +492,7 @@ void FS_RebuildFSHash(void) } else { - FS_FlushFSHash(); + FS_FlushFSHashRemoved(); } Hash_InitTable(&filesystemhash, filesystemhash.numbuckets, filesystemhash.bucket); @@ -458,12 +503,12 @@ void FS_RebuildFSHash(void) { //go for the pure paths first. for (search = com_purepaths; search; search = search->nextpure) { - search->funcs->BuildHash(search->handle); + search->funcs->BuildHash(search->handle, depth++); } } for (search = com_searchpaths ; search ; search = search->next) { - search->funcs->BuildHash(search->handle); + search->funcs->BuildHash(search->handle, depth++); } com_fschanged = false; @@ -1217,7 +1262,7 @@ void COM_FlushTempoaryPacks(void) sp = *link; if (sp->istemporary) { - FS_FlushFSHash(); + FS_FlushFSHashReally(); *link = sp->next; @@ -1422,7 +1467,10 @@ static searchpath_t *FS_AddPathHandle(const char *purepath, const char *probable search->isexplicit = isexplicit; search->handle = handle; search->funcs = funcs; - Q_strncpyz(search->purepath, purepath, sizeof(search->purepath)); + if (funcs == &osfilefuncs) + Q_strncpyz(search->purepath, probablepath, sizeof(search->purepath)); + else + Q_strncpyz(search->purepath, purepath, sizeof(search->purepath)); if (istemporary) { @@ -1466,8 +1514,15 @@ void COM_RefreshFSCache_f(void) void COM_FlushFSCache(void) { + searchpath_t *search; if (com_fs_cache.ival != 2) - com_fschanged=true; + { + for (search = com_searchpaths ; search ; search = search->next) + { + if (search->funcs->PollChanges) + com_fschanged |= search->funcs->PollChanges(search->handle); + } + } } /*since should start as 0, otherwise this can be used to poll*/ @@ -1494,6 +1549,7 @@ void FS_AddGameDirectory (const char *puredir, const char *dir, unsigned int loa searchpath_t *search; char *p; + void *handle; fs_restarts++; @@ -1514,9 +1570,8 @@ void FS_AddGameDirectory (const char *puredir, const char *dir, unsigned int loa // add the directory to the search path // - p = Z_Malloc(strlen(dir)+1); - strcpy(p, dir); - FS_AddPathHandle((*dir?puredir:""), va("%s/", dir), &osfilefuncs, p, false, false, true, loadstuff); + handle = osfilefuncs.OpenNew(NULL, dir); + FS_AddPathHandle((*dir?puredir:""), va("%s/", dir), &osfilefuncs, handle, false, false, true, loadstuff); } char *COM_NextPath (char *prevpath) @@ -1531,8 +1586,8 @@ char *COM_NextPath (char *prevpath) continue; if (prevpath == prev) - return s->handle; - prev = s->handle; + return s->purepath; + prev = s->purepath; } return NULL; @@ -1655,7 +1710,7 @@ void COM_Gamedir (const char *dir) FS_ForceToPure(NULL, NULL, 0); #ifndef SERVERONLY - Host_WriteConfiguration(); //before we change anything. +// Host_WriteConfiguration(); //before we change anything. #endif Q_strncpyz (gamedirfile, dir, sizeof(gamedirfile)); @@ -1667,7 +1722,7 @@ void COM_Gamedir (const char *dir) cl.gamedirchanged = true; #endif - FS_FlushFSHash(); + FS_FlushFSHashReally(); // // free up any current game dir info @@ -1867,7 +1922,7 @@ void FS_ImpurePacks(const char *names, const char *crcs) break; sp = FS_AddPathHandle(pname, local, searchpathformats[i].funcs, handle, true, true, false, (unsigned int)-1); - FS_FlushFSHash(); + FS_FlushFSHashReally(); break; } } @@ -1899,7 +1954,7 @@ void FS_ForceToPure(const char *names, const char *crcs, int seed) { Con_Printf("Pure FS deactivated\n"); com_purepaths = NULL; - FS_FlushFSHash(); + FS_FlushFSHashReally(); } return; } @@ -1993,7 +2048,7 @@ void FS_ForceToPure(const char *names, const char *crcs, int seed) } } - FS_FlushFSHash(); + FS_FlushFSHashReally(); if (com_purepaths && !waspure) Con_Printf("Pure FS activated\n"); @@ -2055,7 +2110,7 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags) } #endif - FS_FlushFSHash(); + FS_FlushFSHashReally(); oldpaths = com_searchpaths; com_searchpaths = NULL; @@ -2360,7 +2415,7 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base void FS_Shutdown(void) { searchpath_t *next; - FS_FlushFSHash(); + FS_FlushFSHashReally(); // // free up any current game dir info diff --git a/engine/common/fs.h b/engine/common/fs.h index ca35fd3c0..be6c79271 100644 --- a/engine/common/fs.h +++ b/engine/common/fs.h @@ -1,4 +1,9 @@ #include "hash.h" +typedef struct +{ + bucket_t buck; + int depth; /*shallower files will remove deeper files*/ +} fsbucket_t; extern hashtable_t filesystemhash; //this table is the one to build your hash references into extern int fs_hash_dups; //for tracking efficiency. no functional use. extern int fs_hash_files; //for tracking efficiency. no functional use. @@ -7,7 +12,7 @@ extern int fs_hash_files; //for tracking efficiency. no functional use. typedef struct { void (*PrintPath)(void *handle); void (*ClosePath)(void *handle); - void (*BuildHash)(void *handle); + void (*BuildHash)(void *handle, int depth); qboolean (*FindFile)(void *handle, flocation_t *loc, const char *name, void *hashedresult); //true if found (hashedresult can be NULL) //note that if rawfile and offset are set, many Com_FileOpens will read the raw file //otherwise ReadFile will be called instead. @@ -19,6 +24,8 @@ typedef struct { int (*GeneratePureCRC) (void *handle, int seed, int usepure); vfsfile_t *(*OpenVFS)(void *handle, flocation_t *loc, const char *mode); + + qboolean (*PollChanges)(void *handle); //returns true if there were changes } searchpathfuncs_t; //the stdio filesystem is special as that's the starting point of the entire filesystem @@ -27,5 +34,7 @@ extern searchpathfuncs_t osfilefuncs; vfsfile_t *VFSOS_Open(const char *osname, const char *mode); vfsfile_t *FS_DecompressGZip(vfsfile_t *infile); +void FS_AddFileHash(int depth, const char *fname, fsbucket_t *filehandle, void *pathhandle); //called inside the BuildHash function + int FS_RegisterFileSystemType(const char *extension, searchpathfuncs_t *funcs, qboolean loadscan); void FS_UnRegisterFileSystemType(int idx); diff --git a/engine/common/fs_pak.c b/engine/common/fs_pak.c index 18c645fee..cbd1c3d2a 100644 --- a/engine/common/fs_pak.c +++ b/engine/common/fs_pak.c @@ -7,11 +7,11 @@ typedef struct { + fsbucket_t bucket; + char name[MAX_QPATH]; int filepos, filelen; - - bucket_t bucket; -} packfile_t; +} mpackfile_t; typedef struct pack_s { @@ -19,7 +19,7 @@ typedef struct pack_s vfsfile_t *handle; unsigned int filepos; //the pos the subfiles left it at (to optimize calls to vfs_seek) int numfiles; - packfile_t *files; + mpackfile_t *files; int references; //seeing as all vfiles from a pak file use the parent's vfsfile, we need to keep the parent open until all subfiles are closed. } pack_t; @@ -77,25 +77,19 @@ void FSPAK_ClosePath(void *handle) Z_Free(pak->files); Z_Free(pak); } -void FSPAK_BuildHash(void *handle) +void FSPAK_BuildHash(void *handle, int depth) { pack_t *pak = handle; int i; for (i = 0; i < pak->numfiles; i++) { - if (!Hash_GetInsensative(&filesystemhash, pak->files[i].name)) - { - fs_hash_files++; - Hash_AddInsensative(&filesystemhash, pak->files[i].name, &pak->files[i], &pak->files[i].bucket); - } - else - fs_hash_dups++; + FS_AddFileHash(depth, pak->files[i].name, &pak->files[i].bucket, &pak->files[i]); } } qboolean FSPAK_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) { - packfile_t *pf = hashedresult; + mpackfile_t *pf = hashedresult; int i, len; pack_t *pak = handle; @@ -193,7 +187,7 @@ void *FSPAK_LoadPackFile (vfsfile_t *file, const char *desc) dpackheader_t header; int i; // int j; - packfile_t *newfiles; + mpackfile_t *newfiles; int numpackfiles; pack_t *pack; vfsfile_t *packhandle; @@ -224,7 +218,7 @@ void *FSPAK_LoadPackFile (vfsfile_t *file, const char *desc) // if (numpackfiles != PAK0_COUNT) // com_modified = true; // not the original file - newfiles = (packfile_t*)Z_Malloc (numpackfiles * sizeof(packfile_t)); + newfiles = (mpackfile_t*)Z_Malloc (numpackfiles * sizeof(mpackfile_t)); VFS_SEEK(packhandle, header.dirofs); // fread (&info, 1, header.dirlen, packhandle); diff --git a/engine/common/fs_stdio.c b/engine/common/fs_stdio.c index 0aa832eb3..18f7665a9 100644 --- a/engine/common/fs_stdio.c +++ b/engine/common/fs_stdio.c @@ -9,12 +9,15 @@ #define Z_Malloc malloc #else #if !defined(_WIN32) || defined(_SDL) -#define VFSSTDIO_Open VFSOS_Open #define stdiofilefuncs osfilefuncs #endif #define FSSTDIO_OpenTemp FS_OpenTemp #endif +typedef struct { + int depth; + char rootpath[1]; +} stdiopath_t; typedef struct { vfsfile_t funcs; FILE *handle; @@ -115,7 +118,7 @@ vfsfile_t *FSSTDIO_OpenTemp(void) vfsfile_t *Sys_OpenAsset(const char *fname); #endif -vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode) +static vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode, qboolean *needsflush) { FILE *f; vfsstdiofile_t *file; @@ -126,6 +129,9 @@ vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode) char newmode[3]; int modec = 0; + if (needsflush) + *needsflush = false; + #if 0//def ANDROID // if (!strncmp("asset/", osname, 6)) { @@ -151,6 +157,12 @@ vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode) if (!f) return NULL; + if (write || append) + { + if (needsflush) + *needsflush = true; + } + file = Z_Malloc(sizeof(vfsstdiofile_t)); file->funcs.ReadBytes = strchr(mode, 'r')?VFSSTDIO_ReadBytes:NULL; file->funcs.WriteBytes = (strchr(mode, 'w')||strchr(mode, 'a'))?VFSSTDIO_WriteBytes:NULL; @@ -164,29 +176,67 @@ vfsfile_t *VFSSTDIO_Open(const char *osname, const char *mode) return (vfsfile_t*)file; } +#if !defined(_WIN32) || defined(_SDL) +vfsfile_t *VFSOS_Open(const char *osname, const char *mode) +{ + vfsfile_t *f; + qboolean needsflush; + f = VFSSTDIO_Open(osname, mode, &needsflush); + if (needsflush) + FS_FlushFSHashReally(); + return f; +} +#endif #ifndef WEBSVONLY static vfsfile_t *FSSTDIO_OpenVFS(void *handle, flocation_t *loc, const char *mode) { + vfsfile_t *f; + stdiopath_t *sp = handle; char diskname[MAX_OSPATH]; + qboolean needsflush; //path is already cleaned, as anything that gets a valid loc needs cleaning up first. - snprintf(diskname, sizeof(diskname), "%s/%s", (char*)handle, loc->rawname); + snprintf(diskname, sizeof(diskname), "%s/%s", sp->rootpath, loc->rawname); - return VFSOS_Open(diskname, mode); + f = VFSSTDIO_Open(diskname, mode, &needsflush); + if (needsflush) + FS_AddFileHash(sp->depth, loc->rawname, NULL, sp); + return f; } static void FSSTDIO_PrintPath(void *handle) { - Con_Printf("%s\n", (char*)handle); + stdiopath_t *np = handle; + Con_Printf("%s\n", np->rootpath); } static void FSSTDIO_ClosePath(void *handle) { Z_Free(handle); } +static qboolean FSSTDIO_PollChanges(void *handle) +{ + stdiopath_t *np = handle; + return true; //can't verify that or not, so we have to assume the worst +} +static void *FSSTDIO_OpenPath(vfsfile_t *mustbenull, const char *desc) +{ + stdiopath_t *np; + int dlen = strlen(desc); + if (mustbenull) + return NULL; + np = Z_Malloc(sizeof(*np) + dlen); + if (np) + { + np->depth = 0; + memcpy(np->rootpath, desc, dlen+1); + } + return np; +} static int FSSTDIO_RebuildFSHash(const char *filename, int filesize, void *data) { + stdiopath_t *sp = data; if (filename[strlen(filename)-1] == '/') { //this is actually a directory @@ -195,27 +245,18 @@ static int FSSTDIO_RebuildFSHash(const char *filename, int filesize, void *data) Sys_EnumerateFiles((char*)data, childpath, FSSTDIO_RebuildFSHash, data); return true; } - if (!Hash_GetInsensative(&filesystemhash, filename)) - { - bucket_t *bucket = (bucket_t*)BZ_Malloc(sizeof(bucket_t) + strlen(filename)+1); - strcpy((char *)(bucket+1), filename); -#ifdef _WIN32 - Q_strlwr((char *)(bucket+1)); -#endif - Hash_AddInsensative(&filesystemhash, (char *)(bucket+1), data, bucket); - - fs_hash_files++; - } - else - fs_hash_dups++; + FS_AddFileHash(sp->depth, filename, NULL, sp); return true; } -static void FSSTDIO_BuildHash(void *handle) +static void FSSTDIO_BuildHash(void *handle, int depth) { - Sys_EnumerateFiles(handle, "*", FSSTDIO_RebuildFSHash, handle); + stdiopath_t *sp = handle; + sp->depth = depth; + Sys_EnumerateFiles(sp->rootpath, "*", FSSTDIO_RebuildFSHash, handle); } static qboolean FSSTDIO_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) { + stdiopath_t *sp = handle; int len; char netpath[MAX_OSPATH]; @@ -232,7 +273,7 @@ static qboolean FSSTDIO_FLocate(void *handle, flocation_t *loc, const char *file */ // check a file in the directory tree - snprintf (netpath, sizeof(netpath)-1, "%s/%s",(char*)handle, filename); + snprintf (netpath, sizeof(netpath)-1, "%s/%s", sp->rootpath, filename); #ifdef ANDROID { @@ -291,9 +332,10 @@ searchpathfuncs_t stdiofilefuncs = { FSSTDIO_FLocate, FSSTDIO_ReadFile, FSSTDIO_EnumerateFiles, + FSSTDIO_OpenPath, NULL, - NULL, - FSSTDIO_OpenVFS + FSSTDIO_OpenVFS, + FSSTDIO_PollChanges }; #endif #endif \ No newline at end of file diff --git a/engine/common/fs_win32.c b/engine/common/fs_win32.c index 218698b54..846df8c94 100644 --- a/engine/common/fs_win32.c +++ b/engine/common/fs_win32.c @@ -12,6 +12,11 @@ #define VFSW32_Open VFSOS_Open #define w32filefuncs osfilefuncs +typedef struct { + HANDLE changenotification; + int hashdepth; + char rootpath[1]; +} vfsw32path_t; typedef struct { vfsfile_t funcs; HANDLE hand; @@ -102,6 +107,8 @@ static void VFSW32_Close(vfsfile_t *file) } CloseHandle(intfile->hand); Z_Free(file); + + COM_FlushFSCache(); } vfsfile_t *VFSW32_Open(const char *osname, const char *mode) @@ -183,49 +190,86 @@ static vfsfile_t *VFSW32_OpenVFS(void *handle, flocation_t *loc, const char *mod static void VFSW32_PrintPath(void *handle) { - Con_Printf("%s\n", (char *)handle); + vfsw32path_t *wp = handle; + Con_Printf("%s\n", wp->rootpath); } static void VFSW32_ClosePath(void *handle) { - Z_Free(handle); + vfsw32path_t *wp = handle; + if (wp->changenotification != INVALID_HANDLE_VALUE) + FindCloseChangeNotification(wp->changenotification); + Z_Free(wp); } -static int VFSW32_RebuildFSHash(const char *filename, int filesize, void *data) +static qboolean VFSW32_PollChanges(void *handle) { + qboolean result = false; + vfsw32path_t *wp = handle; + + if (wp->changenotification == INVALID_HANDLE_VALUE) + return true; + for(;;) + { + switch(WaitForSingleObject(wp->changenotification, 0)) + { + case WAIT_OBJECT_0: + result = true; + break; + case WAIT_TIMEOUT: + return result; + default: + FindCloseChangeNotification(wp->changenotification); + wp->changenotification = INVALID_HANDLE_VALUE; + return true; + } + FindNextChangeNotification(wp->changenotification); + } + return result; +} +static void *VFSW32_OpenPath(vfsfile_t *mustbenull, const char *desc) +{ + vfsw32path_t *np; + int dlen = strlen(desc); + if (mustbenull) + return NULL; + np = Z_Malloc(sizeof(*np) + dlen); + if (np) + { + memcpy(np->rootpath, desc, dlen+1); + + np->changenotification = FindFirstChangeNotification(np->rootpath, true, FILE_NOTIFY_CHANGE_FILE_NAME); + } + return np; +} +static int VFSW32_RebuildFSHash(const char *filename, int filesize, void *handle) +{ + vfsw32path_t *wp = handle; if (filename[strlen(filename)-1] == '/') { //this is actually a directory char childpath[256]; Q_snprintfz(childpath, sizeof(childpath), "%s*", filename); - Sys_EnumerateFiles((char*)data, childpath, VFSW32_RebuildFSHash, data); + Sys_EnumerateFiles(wp->rootpath, childpath, VFSW32_RebuildFSHash, wp); return true; } - if (!Hash_GetInsensative(&filesystemhash, filename)) - { - bucket_t *bucket = (bucket_t*)BZ_Malloc(sizeof(bucket_t) + strlen(filename)+1); - strcpy((char *)(bucket+1), filename); -#ifdef _WIN32 - Q_strlwr((char *)(bucket+1)); -#endif - Hash_AddInsensative(&filesystemhash, (char *)(bucket+1), data, bucket); - fs_hash_files++; - } - else - fs_hash_dups++; + FS_AddFileHash(wp->hashdepth, filename, NULL, wp); return true; } -static void VFSW32_BuildHash(void *handle) +static void VFSW32_BuildHash(void *handle, int hashdepth) { - Sys_EnumerateFiles(handle, "*", VFSW32_RebuildFSHash, handle); + vfsw32path_t *wp = handle; + wp->hashdepth = hashdepth; + Sys_EnumerateFiles(wp->rootpath, "*", VFSW32_RebuildFSHash, handle); } static qboolean VFSW32_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) { + vfsw32path_t *wp = handle; FILE *f; int len; char netpath[MAX_OSPATH]; - if (hashedresult && (void *)hashedresult != handle) + if (hashedresult && (void *)hashedresult != wp) return false; /* @@ -237,7 +281,7 @@ static qboolean VFSW32_FLocate(void *handle, flocation_t *loc, const char *filen */ // check a file in the directory tree - snprintf (netpath, sizeof(netpath)-1, "%s/%s",(char*)handle, filename); + snprintf (netpath, sizeof(netpath)-1, "%s/%s", wp->rootpath, filename); f = fopen(netpath, "rb"); if (!f) @@ -251,13 +295,15 @@ static qboolean VFSW32_FLocate(void *handle, flocation_t *loc, const char *filen loc->len = len; loc->offset = 0; loc->index = 0; - snprintf(loc->rawname, sizeof(loc->rawname), "%s/%s", (char*)handle, filename); + snprintf(loc->rawname, sizeof(loc->rawname), "%s/%s", wp->rootpath, filename); } return true; } static void VFSW32_ReadFile(void *handle, flocation_t *loc, char *buffer) { +// vfsw32path_t *wp = handle; + FILE *f; f = fopen(loc->rawname, "rb"); if (!f) //err... @@ -268,9 +314,11 @@ static void VFSW32_ReadFile(void *handle, flocation_t *loc, char *buffer) } static int VFSW32_EnumerateFiles (void *handle, const char *match, int (*func)(const char *, int, void *), void *parm) { - return Sys_EnumerateFiles(handle, match, func, parm); + vfsw32path_t *wp = handle; + return Sys_EnumerateFiles(wp->rootpath, match, func, parm); } + searchpathfuncs_t w32filefuncs = { VFSW32_PrintPath, VFSW32_ClosePath, @@ -278,7 +326,8 @@ searchpathfuncs_t w32filefuncs = { VFSW32_FLocate, VFSW32_ReadFile, VFSW32_EnumerateFiles, + VFSW32_OpenPath, NULL, - NULL, - VFSW32_OpenVFS + VFSW32_OpenVFS, + VFSW32_PollChanges }; diff --git a/engine/common/fs_zip.c b/engine/common/fs_zip.c index 67cedd2c8..7d351bdbd 100644 --- a/engine/common/fs_zip.c +++ b/engine/common/fs_zip.c @@ -214,10 +214,9 @@ vfsfile_t *FS_DecompressGZip(vfsfile_t *infile) typedef struct { + fsbucket_t bucket; char name[MAX_QPATH]; int filepos, filelen; - - bucket_t bucket; } zpackfile_t; @@ -261,20 +260,14 @@ static void FSZIP_ClosePath(void *handle) Z_Free(zip->files); Z_Free(zip); } -static void FSZIP_BuildHash(void *handle) +static void FSZIP_BuildHash(void *handle, int depth) { zipfile_t *zip = handle; int i; for (i = 0; i < zip->numfiles; i++) { - if (!Hash_GetInsensative(&filesystemhash, zip->files[i].name)) - { - fs_hash_files++; - Hash_AddInsensative(&filesystemhash, zip->files[i].name, &zip->files[i], &zip->files[i].bucket); - } - else - fs_hash_dups++; + FS_AddFileHash(depth, zip->files[i].name, &zip->files[i].bucket, &zip->files[i]); } } static qboolean FSZIP_FLocate(void *handle, flocation_t *loc, const char *filename, void *hashedresult) diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 7b387dc30..72a9e1487 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -937,6 +937,14 @@ void Matrix4x4_CM_Transform3(const float *matrix, const float *vector, float *pr product[1] = matrix[1]*vector[0] + matrix[5]*vector[1] + matrix[9]*vector[2] + matrix[13]; product[2] = matrix[2]*vector[0] + matrix[6]*vector[1] + matrix[10]*vector[2] + matrix[14]; } +void Matrix4x4_CM_Transform34(const float *matrix, const vec3_t vector, vec4_t product) +{ + //transform as though vector[3] == 1 + product[0] = matrix[0]*vector[0] + matrix[4]*vector[1] + matrix[8]*vector[2] + matrix[12]; + product[1] = matrix[1]*vector[0] + matrix[5]*vector[1] + matrix[9]*vector[2] + matrix[13]; + product[2] = matrix[2]*vector[0] + matrix[6]*vector[1] + matrix[10]*vector[2] + matrix[14]; + product[3] = matrix[3]*vector[0] + matrix[7]*vector[1] + matrix[11]*vector[2] + matrix[15]; +} void Matrix4x4_CM_ModelViewMatrix(float *modelview, const vec3_t viewangles, const vec3_t vieworg) { diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index 9baea4fcd..e2ad7b651 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -78,6 +78,7 @@ extern vec3_t vec3_origin; #define VectorInterpolate(a, bness, b, c) FloatInterpolate((a)[0], bness, (b)[0], (c)[0]),FloatInterpolate((a)[1], bness, (b)[1], (c)[1]),FloatInterpolate((a)[2], bness, (b)[2], (c)[2]) #define Vector2Copy(a,b) {(b)[0]=(a)[0];(b)[1]=(a)[1];} #define Vector2Set(r,x,y) {(r)[0] = x; (r)[1] = y;} +#define Vector2Interpolate(a, bness, b, c) FloatInterpolate((a)[0], bness, (b)[0], (c)[0]),FloatInterpolate((a)[1], bness, (b)[1], (c)[1]) #define Vector4Copy(a,b) do{(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];(b)[3]=(a)[3];}while(0) #define Vector4Scale(in,scale,out) ((out)[0]=(in)[0]*scale,(out)[1]=(in)[1]*scale,(out)[2]=(in)[2]*scale,(out)[3]=(in)[3]*scale) @@ -157,6 +158,7 @@ void Matrix3x4_Multiply(const float *a, const float *b, float *out); void Matrix4x4_CM_Project (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy); void Matrix4x4_CM_Transform3 (const float *matrix, const float *vector, float *product); void Matrix4x4_CM_Transform4 (const float *matrix, const float *vector, float *product); +void Matrix4x4_CM_Transform34(const float *matrix, const vec3_t vector, vec4_t product); void Matrix4x4_CM_UnProject (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy); void Matrix3x4_RM_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]); void Matrix4x4_RM_FromVectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]); diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index c33c70210..a6aac8254 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -847,12 +847,18 @@ qboolean Netchan_Process (netchan_t *chan) } if (chan->incoming_unreliable != sequence) { + if (chan->in_fragment_length && showdrop.ival) + Con_Printf("final fragment lost (%i). dropping entire packet\n", offset); /*sequence doesn't match, forget the old*/ chan->in_fragment_length = 0; chan->incoming_unreliable = sequence; } if (offset != chan->in_fragment_length) + { + if (showdrop.ival) + Con_Printf("prior fragment lost (%i-%i). dropping entire packet\n", offset, chan->in_fragment_length); return false; /*dropped one*/ + } memcpy(chan->in_fragment_buf + offset, net_message.data + msg_readcount, len); chan->in_fragment_length += len; diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index d8f18aca3..0a0ae23f8 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -85,7 +85,7 @@ extern cvar_t sv_public, sv_listen_qw, sv_listen_nq, sv_listen_dp, sv_listen_q3; static qboolean allowconnects = false; -#define MAX_LOOPBACK 4 +#define MAX_LOOPBACK 8 typedef struct { qbyte data[MAX_UDP_PACKET]; @@ -1399,7 +1399,12 @@ qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *from, sizebuf_t *message) loop = &loopbacks[sock]; if (loop->send - loop->get > MAX_LOOPBACK) + { + extern cvar_t showdrop; + if (showdrop.ival) + Con_Printf("loopback dropping %i packets\n", (loop->send - MAX_LOOPBACK) - loop->get); loop->get = loop->send - MAX_LOOPBACK; + } if (loop->get >= loop->send) return false; diff --git a/engine/common/plugin.c b/engine/common/plugin.c index ff58385e0..6d629ad76 100644 --- a/engine/common/plugin.c +++ b/engine/common/plugin.c @@ -716,7 +716,7 @@ qintptr_t VARGS Plug_Cmd_AddCommand(void *offset, quintptr_t mask, const qintptr } Q_strncpyz(plugincommandarray[i].command, name, sizeof(plugincommandarray[i].command)); - if (!Cmd_AddRemCommand(plugincommandarray[i].command, Plug_Command_f)) + if (!Cmd_AddCommand(plugincommandarray[i].command, Plug_Command_f)) return false; plugincommandarray[i].plugin = currentplug; //worked return true; diff --git a/engine/common/pmove.c b/engine/common/pmove.c index e6fbfc1a0..a644d170e 100644 --- a/engine/common/pmove.c +++ b/engine/common/pmove.c @@ -789,7 +789,7 @@ void PM_CategorizePosition (void) //bsp objects marked as ladders mark regions to stand in to be classed as on a ladder. cont = PM_ExtraBoxContents(pmove.origin); -#ifdef Q2BSPS +#ifdef Q3BSPS //q3 has surfaceflag-based ladders if (pmove.physents[0].model->fromgame == fg_quake3) { diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index 25f2f1da7..bea1b41f3 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -47,11 +47,6 @@ static char *strtolower(char *s) void PF_Common_RegisterCvars(void) { - static qboolean alreadydone; - if (alreadydone) - return; - alreadydone = true; - Cvar_Register (&pr_brokenfloatconvert, cvargroup_progs); Cvar_Register (&pr_tempstringcount, cvargroup_progs); Cvar_Register (&pr_tempstringsize, cvargroup_progs); diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index 270d61720..af0f28a38 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -309,7 +309,6 @@ void QCBUILTIN PF_whichpack (progfuncs_t *prinst, struct globalvars_s *pr_global void PF_fclose_progs (progfuncs_t *prinst); int QCEditor (progfuncs_t *prinst, char *filename, int line, int nump, char **parms); -void PF_Common_RegisterCvars(void); diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index 096280934..0b6ae3534 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -53,6 +53,22 @@ static int Q1_HullPointContents (hull_t *hull, int num, vec3_t p) return num; } +static int Q1_ModelPointContents (mnode_t *node, vec3_t p) +{ + float d; + mplane_t *plane; + while(node->contents >= 0) + { + plane = node->plane; + if (plane->type < 3) + d = p[plane->type] - plane->dist; + else + d = DotProduct(plane->normal, p) - plane->dist; + node = node->children[d<0]; + } + return node->contents; +} + #define DIST_EPSILON (0.03125) @@ -729,6 +745,10 @@ unsigned int Q1BSP_PointContents(model_t *model, vec3_t axis[3], vec3_t point) transformed[2] = DotProduct(point, axis[2]); return Q1BSP_HullPointContents(&model->hulls[0], transformed); } + if (1) + { + return Q1BSP_TranslateContents(Q1_ModelPointContents(model->nodes, point)); + } return Q1BSP_HullPointContents(&model->hulls[0], point); } diff --git a/engine/common/world.h b/engine/common/world.h index bc35802e4..600948926 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -196,6 +196,8 @@ struct world_s }; typedef struct world_s world_t; +void PF_Common_RegisterCvars(void); + #ifdef USEODE void World_ODE_RemoveFromEntity(world_t *world, wedict_t *ed); void World_ODE_RemoveJointFromEntity(world_t *world, wedict_t *ed); diff --git a/engine/common/zone.c b/engine/common/zone.c index 26e5af1cd..3b8026f46 100644 --- a/engine/common/zone.c +++ b/engine/common/zone.c @@ -66,6 +66,9 @@ qbyte sentinalkey; #define TAGLESS 1 +int zmemtotal; +int zmemdelta; + typedef struct memheader_s { int size; int tag; @@ -347,7 +350,14 @@ void *Z_Realloc(void *data, int newsize) void *BZF_Malloc(int size) //BZ_Malloc but allowed to fail - like straight malloc. { - return malloc(size); + void *mem; + mem = malloc(size); + if (mem) + { + zmemdelta += size; + zmemtotal += size; + } + return mem; } void *BZ_Malloc(int size) //Doesn't clear. The expectation is a large file, rather than sensative data structures. @@ -1206,13 +1216,13 @@ void Hunk_Print (qboolean all) count = 0; sum = 0; totalblocks = 0; - + h = (hunk_t *)hunk_base; endlow = (hunk_t *)(hunk_base + hunk_low_used); starthigh = (hunk_t *)(hunk_base + hunk_size - hunk_high_used); endhigh = (hunk_t *)(hunk_base + hunk_size); - Con_Printf (" :%8i total hunk size\n", hunk_size); + Con_Printf (" :%12i total hunk size\n", hunk_size); Con_Printf ("-------------------------\n"); while (1) @@ -1223,12 +1233,12 @@ void Hunk_Print (qboolean all) if ( h == endlow ) { Con_Printf ("-------------------------\n"); - Con_Printf (" :%8i REMAINING\n", hunk_size - hunk_low_used - hunk_high_used); - Con_Printf (" :%8i USED\n", hunk_low_used + hunk_high_used); + Con_Printf (" : %12i REMAINING\n", hunk_size - hunk_low_used - hunk_high_used); + Con_Printf (" : %12i USED\n", hunk_low_used + hunk_high_used); Con_Printf ("-------------------------\n"); h = starthigh; } - + // // if totally done, break // @@ -1268,8 +1278,8 @@ void Hunk_Print (qboolean all) // memcpy (name, h->name, 8); if (all) - Con_Printf ("%8p :%8i %8s\n",h, h->size, name); - + Con_Printf ("%8p :%12i %8s\n",h, h->size, name); + // // print the total // @@ -1277,7 +1287,7 @@ void Hunk_Print (qboolean all) strncmp (h->name, next->name, 8) ) { if (!all) - Con_Printf (" :%8i %8s (TOTAL)\n",sum, name); + Con_Printf (" :%12i %8s (TOTAL)\n",sum, name); count = 0; sum = 0; } @@ -1748,6 +1758,12 @@ void Hunk_Print_f (void) cacheused += cs->size; } Con_Printf("Cache: %iKB\n", cacheused/1024); + + Con_Printf("Z Delta: %iKB\n", zmemdelta/1024); zmemdelta = 0; + Con_Printf("Z Total: %iKB\n", zmemtotal/1024); + //note: Zone memory isn't tracked reliably. we don't track the mem that is freed, so it'll just climb and climb + //we don't track reallocs either. + #if 0 { zone_t *zone; diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index 9b996d3e9..5c6efe4c9 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -2049,6 +2049,7 @@ void D3DBE_SelectEntity(entity_t *ent) /*Generates an optimised vbo for each of the given model's textures*/ void D3DBE_GenBrushModelVBO(model_t *mod) { +#if 0 unsigned int maxvboverts; unsigned int maxvboelements; @@ -2228,6 +2229,7 @@ void D3DBE_GenBrushModelVBO(model_t *mod) IDirect3DIndexBuffer9_Unlock(ebuff); IDirect3DVertexBuffer9_Unlock(vbuff); } +#endif } /*Wipes a vbo*/ void D3DBE_ClearVBO(vbo_t *vbo) @@ -2438,10 +2440,7 @@ void D3DBE_SubmitBatch(batch_t *batch) BE_RotateForEntity(batch->ent, batch->ent->model); shaderstate.curtime = r_refdef.time - shaderstate.curentity->shaderTime; } - if (batch->texture) - shaderstate.batchvbo = &batch->texture->vbo; - else - shaderstate.batchvbo = batch->vbo; + shaderstate.batchvbo = batch->vbo; shaderstate.meshlist = batch->mesh + batch->firstmesh; shaderstate.curshader = batch->shader; shaderstate.curtexnums = batch->skin; diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index e8a1f09f0..d9af98ed2 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -726,7 +726,6 @@ static qboolean D3D9_VID_Init(rendererstate_t *info, unsigned char *palette) } { - extern cvar_t v_contrast; void GLV_Gamma_Callback(struct cvar_s *var, char *oldvalue); Cvar_Hook(&v_gamma, GLV_Gamma_Callback); Cvar_Hook(&v_contrast, GLV_Gamma_Callback); @@ -776,10 +775,6 @@ static void (D3D9_R_PreNewMap) (void) r_viewleaf2 = NULL; r_oldviewleaf2 = NULL; } -static int (D3D9_R_LightPoint) (vec3_t point) -{ - return 0; -} static void (D3D9_VID_DeInit) (void) { @@ -803,6 +798,9 @@ static void (D3D9_VID_DeInit) (void) DestroyWindow(mainwindow); mainwindow = NULL; } + + Cvar_Unhook(&v_gamma); + Cvar_Unhook(&v_contrast); } static void (D3D9_VID_SetPalette) (unsigned char *palette) @@ -1120,7 +1118,7 @@ static void (D3D9_Draw_Init) (void) { R2D_Init(); } -static void (D3D9_Draw_ReInit) (void) +static void (D3D9_Draw_Shutdown) (void) { } @@ -1220,7 +1218,6 @@ static void (D3D9_R_RenderView) (void) void (D3D9_R_NewMap) (void); void (D3D9_R_PreNewMap) (void); -int (D3D9_R_LightPoint) (vec3_t point); void (D3D9_R_PushDlights) (void); void (D3D9_R_AddStain) (vec3_t org, float red, float green, float blue, float radius); @@ -1251,7 +1248,7 @@ rendererinfo_t d3drendererinfo = QR_DIRECT3D, D3D9_Draw_Init, - D3D9_Draw_ReInit, + D3D9_Draw_Shutdown, D3D9_LoadTexture, D3D9_LoadTexture8Pal24, @@ -1268,7 +1265,6 @@ rendererinfo_t d3drendererinfo = D3D9_R_NewMap, D3D9_R_PreNewMap, - D3D9_R_LightPoint, Surf_AddStain, Surf_LessenStains, diff --git a/engine/dotnet2005/ftequake.sln b/engine/dotnet2005/ftequake.sln index cd1c7e5c2..463ec1ea6 100644 --- a/engine/dotnet2005/ftequake.sln +++ b/engine/dotnet2005/ftequake.sln @@ -25,6 +25,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nacl", "..\nacl\nacl.vcproj", "{4735677B-6D5A-4BE6-A945-CB32A7282F56}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xsv", "..\..\plugins\xsv\xsv.vcproj", "{873CCE24-3549-49D4-A4B4-653F91B1532A}" + ProjectSection(ProjectDependencies) = postProject + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364} = {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -326,7 +329,6 @@ Global {AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.Release|Win32.ActiveCfg = Release|Win32 {AA9D4AA8-2B98-42A8-9F63-B9E5A6221BB6}.Release|x64.ActiveCfg = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DDebug|Win32.ActiveCfg = Debug|Win32 - {4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DDebug|Win32.Build.0 = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DDebug|x64.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DRelease|Win32.ActiveCfg = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DRelease|Win32.Build.0 = Release|Win32 @@ -338,13 +340,11 @@ Global {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Debug|Win32.Build.0 = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.Debug|x64.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.GLDebug|Win32.ActiveCfg = Debug|Win32 - {4735677B-6D5A-4BE6-A945-CB32A7282F56}.GLDebug|Win32.Build.0 = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.GLDebug|x64.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.GLRelease|Win32.ActiveCfg = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.GLRelease|Win32.Build.0 = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.GLRelease|x64.ActiveCfg = Release|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MDebug|Win32.ActiveCfg = Debug|Win32 - {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MDebug|Win32.Build.0 = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MDebug|x64.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLDebug|Win32.ActiveCfg = Debug|Win32 {4735677B-6D5A-4BE6-A945-CB32A7282F56}.MinGLDebug|Win32.Build.0 = Debug|Win32 diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index c93506c90..8de83499d 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -1073,7 +1073,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="true" AdditionalIncludeDirectories="../libs/speex;..\client;../libs/freetype2/include;../common;../server;../gl;../sw;../qclib;../libs;../libs/dxsdk9/include;../libs/dxsdk7/include" - PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;GLQUAKE;D3DQUAKE" + PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;GLQUAKE;D3DQUAKE;SWQUAKE" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" @@ -1475,7 +1475,8 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../libs/speex;..\client;../libs/freetype2/include;../common;../server;../gl;../sw;../qclib;../libs;../libs/dxsdk9/include;../libs/dxsdk7/include" - PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;GLQUAKE;D3DQUAKE" + PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS;GLQUAKE;D3DQUAKE;SWQUAKE;MULTITHREAD" + BasicRuntimeChecks="3" RuntimeLibrary="1" FloatingPointModel="2" UsePrecompiledHeader="2" @@ -27035,6 +27036,34 @@ > + + + + + + + + + + + + + + lightmap = -1; b->surf_first = 0; b->flags |= BEF_NODLIGHT|BEF_NOSHADOWS; - b->vbo = 0; + b->vbo = NULL; b->next = batches[sort]; batches[sort] = b; } diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index edf72f68f..a5ad36e40 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -87,6 +87,7 @@ static const char PCFPASS_SHADER[] = "\ extern cvar_t r_glsl_offsetmapping, r_noportals; static void BE_SendPassBlendDepthMask(unsigned int sbits); +void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destcol, qboolean usedepth); void GLBE_SubmitBatch(batch_t *batch); struct { @@ -119,6 +120,9 @@ struct { texid_t tex_sourcecol; /*this is used by $sourcecolour tgen*/ texid_t tex_sourcedepth; int fbo_depthless; + int fbo_reflection; + texid_t tex_reflection; + texid_t tex_refraction; qboolean force2d; int currenttmu; @@ -1007,6 +1011,12 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass) case T_GEN_SOURCEDEPTH: t = shaderstate.tex_sourcedepth; break; + case T_GEN_REFLECTION: + t = shaderstate.tex_reflection; + break; + case T_GEN_REFRACTION: + t = shaderstate.tex_refraction; + break; } GL_LazyBind(tmu, GL_TEXTURE_2D, t); } @@ -1886,6 +1896,36 @@ static void deformgen(const deformv_t *deformv, int cnt, vecV_t *src, vecV_t *ds } } +static void GenerateVertexBlends(const shader_t *shader) +{ + int i, m; + mesh_t *meshlist; + vecV_t *ov, *iv1, *iv2; + float w1, w2; + for (m = 0; m < shaderstate.meshcount; m++) + { + meshlist = shaderstate.meshes[m]; + + ov = vertexarray+meshlist->vbofirstvert; + iv1 = meshlist->xyz_array; + iv2 = meshlist->xyz2_array; + w1 = meshlist->xyz_blendw[0]; + w2 = meshlist->xyz_blendw[1]; + for (i = 0; i < meshlist->numvertexes; i++) + { + ov[i][0] = iv1[i][0]*w1 + iv2[i][0]*w2; + ov[i][1] = iv1[i][1]*w1 + iv2[i][1]*w2; + ov[i][2] = iv1[i][2]*w1 + iv2[i][2]*w2; + } + for (i = 0; i < shader->numdeforms; i++) + { + deformgen(&shader->deforms[i], meshlist->numvertexes, vertexarray+meshlist->vbofirstvert, vertexarray+meshlist->vbofirstvert, meshlist); + } + } + + shaderstate.pendingvertexpointer = vertexarray; + shaderstate.pendingvertexvbo = 0; +} static void GenerateVertexDeforms(const shader_t *shader) { int i, m; @@ -2074,6 +2114,7 @@ static void GenerateColourMods(const shaderpass_t *pass) alphagen(pass, meshlist->numvertexes, meshlist->colors4f_array, coloursarray + meshlist->vbofirstvert, meshlist); } + shaderstate.colourarraytype = GL_FLOAT; shaderstate.pendingcolourvbo = 0; shaderstate.pendingcolourpointer = coloursarray; } @@ -3063,14 +3104,6 @@ static void DrawMeshes(void) RQuantAdd(RQUANT_ENTBATCHES, 1); } - if (shaderstate.curshader->numdeforms) - GenerateVertexDeforms(shaderstate.curshader); - else - { - shaderstate.pendingvertexpointer = shaderstate.sourcevbo->coord.gl.addr; - shaderstate.pendingvertexvbo = shaderstate.sourcevbo->coord.gl.vbo; - } - #ifndef FORCESTATE if (shaderstate.curcull != (shaderstate.curshader->flags & (SHADER_CULL_FRONT|SHADER_CULL_BACK))) #endif @@ -3092,6 +3125,16 @@ static void DrawMeshes(void) } } + if (shaderstate.sourcevbo->coord2.gl.addr) + GenerateVertexBlends(shaderstate.curshader); + else if (shaderstate.curshader->numdeforms) + GenerateVertexDeforms(shaderstate.curshader); + else + { + shaderstate.pendingvertexpointer = shaderstate.sourcevbo->coord.gl.addr; + shaderstate.pendingvertexvbo = shaderstate.sourcevbo->coord.gl.vbo; + } + BE_PolyOffset(shaderstate.flags & BEF_PUSHDEPTH); switch(shaderstate.mode) { @@ -3341,7 +3384,7 @@ void GLBE_SubmitBatch(batch_t *batch) } } -static void BE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist) +static void GLBE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist) { batch_t *batch, *old; int i; @@ -3362,12 +3405,12 @@ static void BE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist) /*draw already-drawn portals as depth-only, to ensure that their contents are not harmed*/ - BE_SelectMode(BEM_DEPTHONLY); + GLBE_SelectMode(BEM_DEPTHONLY); for (old = worldlist[SHADER_SORT_PORTAL]; old && old != batch; old = old->next) { if (old->meshes == old->firstmesh) continue; - BE_SubmitBatch(old); + GLBE_SubmitBatch(old); } if (!old) { @@ -3375,10 +3418,10 @@ static void BE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist) { if (old->meshes == old->firstmesh) continue; - BE_SubmitBatch(old); + GLBE_SubmitBatch(old); } } - BE_SelectMode(BEM_STANDARD); + GLBE_SelectMode(BEM_STANDARD); GLR_DrawPortal(batch, worldlist); @@ -3391,7 +3434,7 @@ static void BE_SubmitMeshesPortals(batch_t **worldlist, batch_t *dynamiclist) } } -static void BE_SubmitMeshesSortList(batch_t *sortlist) +static void GLBE_SubmitMeshesSortList(batch_t *sortlist) { batch_t *batch; for (batch = sortlist; batch; batch = batch->next) @@ -3430,7 +3473,51 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist) continue; } - BE_SubmitBatch(batch); + if (batch->shader->flags & (SHADER_HASREFLECT | SHADER_HASREFRACT)) + { + //these two flags require rendering some view as an fbo + if (r_refdef.recurse) + return; + + if (batch->shader->flags & SHADER_HASREFLECT) + { + if (!shaderstate.tex_reflection.num) + { + shaderstate.tex_reflection = GL_AllocNewTexture("***tex_reflection***", vid.pixelwidth, vid.pixelheight); + GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_reflection); + qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth, vid.pixelheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_reflection, true); + GL_ForceDepthWritable(); + qglClear(GL_DEPTH_BUFFER_BIT); + GLR_DrawPortal(batch, cl.worldmodel->batches); + GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, false); + } + if (batch->shader->flags & SHADER_HASREFRACT) + { + if (!shaderstate.tex_refraction.num) + { + shaderstate.tex_refraction = GL_AllocNewTexture("***tex_refraction***", vid.pixelwidth, vid.pixelheight); + GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_refraction); + qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth, vid.pixelheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + GLBE_RenderToTexture(r_nulltex, r_nulltex, shaderstate.tex_refraction, true); + GL_ForceDepthWritable(); + qglClear(GL_DEPTH_BUFFER_BIT); + GLR_DrawPortal(batch, cl.worldmodel->batches); + GLBE_RenderToTexture(r_nulltex, r_nulltex, r_nulltex, false); + } + } + + GLBE_SubmitBatch(batch); } } @@ -3444,11 +3531,11 @@ void GLBE_SubmitMeshes (qboolean drawworld, batch_t **blist, int start, int stop if (drawworld) { if (i == SHADER_SORT_PORTAL && !r_noportals.ival && !r_refdef.recurse) - BE_SubmitMeshesPortals(model->batches, blist[i]); + GLBE_SubmitMeshesPortals(model->batches, blist[i]); - BE_SubmitMeshesSortList(model->batches[i]); + GLBE_SubmitMeshesSortList(model->batches[i]); } - BE_SubmitMeshesSortList(blist[i]); + GLBE_SubmitMeshesSortList(blist[i]); } } @@ -3526,7 +3613,7 @@ void GLBE_BaseEntTextures(void) } #endif -void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destcol, texid_t destdepth, qboolean usedepth) +void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destcol, qboolean usedepth) { shaderstate.tex_sourcecol = sourcecol; shaderstate.tex_sourcedepth = sourcedepth; @@ -3534,16 +3621,40 @@ void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destco qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); else { - if (!shaderstate.fbo_depthless) + if (usedepth) { - qglGenFramebuffersEXT(1, &shaderstate.fbo_depthless); - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shaderstate.fbo_depthless); + if (!shaderstate.fbo_diffuse) + { + int drb; - qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - qglReadBuffer(GL_NONE); + qglGenFramebuffersEXT(1, &shaderstate.fbo_diffuse); + qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shaderstate.fbo_diffuse); + + //create an unnamed depth buffer + qglGenRenderbuffersEXT(1, &drb); + qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, drb); + qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB, vid.pixelwidth, vid.pixelheight); + qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, drb); + + qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + qglReadBuffer(GL_NONE); + } + else + qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shaderstate.fbo_diffuse); } else - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shaderstate.fbo_depthless); + { + if (!shaderstate.fbo_depthless) + { + qglGenFramebuffersEXT(1, &shaderstate.fbo_depthless); + qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shaderstate.fbo_depthless); + + qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); + qglReadBuffer(GL_NONE); + } + else + qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shaderstate.fbo_depthless); + } qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, destcol.num, 0); } diff --git a/engine/gl/gl_bloom.c b/engine/gl/gl_bloom.c index 591bdc15c..0f92cd0c8 100644 --- a/engine/gl/gl_bloom.c +++ b/engine/gl/gl_bloom.c @@ -58,7 +58,7 @@ static int texwidth[MAXLEVELS], texheight[MAXLEVELS]; -void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destcol, texid_t destdepth, qboolean usedepth); +void GLBE_RenderToTexture(texid_t sourcecol, texid_t sourcedepth, texid_t destcol, qboolean usedepth); void R_BloomRegister(void) { @@ -188,13 +188,13 @@ void R_BloomBlend (void) qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_refdef.pxrect.x, r_refdef.pxrect.y - r_refdef.pxrect.height, r_refdef.pxrect.width, r_refdef.pxrect.height); /*filter the screen into a downscaled image*/ - GLBE_RenderToTexture(scrtex, r_nulltex, pingtex[0][0], r_nulltex, false); + GLBE_RenderToTexture(scrtex, r_nulltex, pingtex[0][0], false); qglViewport (0, 0, texwidth[0], texheight[0]); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomfilter); /*and downscale that multiple times*/ for (i = 1; i < MAXLEVELS; i++) { - GLBE_RenderToTexture(pingtex[0][i-1], r_nulltex, pingtex[0][i], r_nulltex, false); + GLBE_RenderToTexture(pingtex[0][i-1], r_nulltex, pingtex[0][i], false); qglViewport (0, 0, texwidth[i], texheight[i]); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomrescale); } @@ -205,7 +205,7 @@ void R_BloomBlend (void) /*must be 1.2th of a pixel*/ r_worldentity.glowmod[0] = 1.2 / texwidth[i]; r_worldentity.glowmod[1] = 0; - GLBE_RenderToTexture(pingtex[0][i], r_nulltex, pingtex[1][i], r_nulltex, false); + GLBE_RenderToTexture(pingtex[0][i], r_nulltex, pingtex[1][i], false); qglViewport (0, 0, texwidth[i], texheight[i]); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomblur); } @@ -213,7 +213,7 @@ void R_BloomBlend (void) { r_worldentity.glowmod[0] = 0; r_worldentity.glowmod[1] = 1.2 / texheight[i]; - GLBE_RenderToTexture(pingtex[1][i], r_nulltex, pingtex[0][i], r_nulltex, false); + GLBE_RenderToTexture(pingtex[1][i], r_nulltex, pingtex[0][i], false); qglViewport (0, 0, texwidth[i], texheight[i]); R2D_ScalePic(0, vid.height, vid.width, -(int)vid.height, bloomblur); } @@ -221,7 +221,7 @@ void R_BloomBlend (void) GL_Set2D(false); /*combine them onto the screen*/ - GLBE_RenderToTexture(scrtex, r_nulltex, r_nulltex, r_nulltex, false); + GLBE_RenderToTexture(scrtex, r_nulltex, r_nulltex, false); R2D_ScalePic(r_refdef.vrect.x, r_refdef.vrect.y + r_refdef.vrect.height, r_refdef.vrect.width, -r_refdef.vrect.height, bloomfinal); } void R_InitBloomTextures(void) diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 3aa6d97e3..ae3938f27 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -490,7 +490,7 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); TRACE(("dbg: GLDraw_ReInit: PPL_LoadSpecularFragmentProgram\n")); GL_InitSceneProcessingShaders(); - Cmd_AddRemCommand ("r_imagelist", GLDraw_ImageList_f); + Cmd_AddCommand ("r_imagelist", GLDraw_ImageList_f); } void GLDraw_DeInit (void) @@ -1397,7 +1397,7 @@ void GL_Upload24BGR (char *name, qbyte *framedata, int inwidth, int inheight, un outheight = 512; if (outwidth*outheight > sizeofuploadmemorybufferintermediate/4) - Sys_Error("MediaGL_ShowFrameBGR_24_Flip: image too big (%i*%i)", inwidth, inheight); + Sys_Error("GL_Upload24BGR: image too big (%i*%i)", inwidth, inheight); for (y=0 ; ylightdata, numlightdata*3); VFS_CLOSE(f); - COM_FlushFSCache(); } else Con_Printf("Unable to write \"%s\"\n", filename); @@ -326,7 +325,6 @@ Mod_ClearAll void RMod_ClearAll (void) { int i; - int t; model_t *mod; #ifdef RUNTIMELIGHTING @@ -354,12 +352,6 @@ void RMod_ClearAll (void) if (mod->type == mod_brush) { Surf_Clear(mod); - for (t = 0; t < mod->numtextures; t++) - { - if (!mod->textures[t]) - continue; - BE_ClearVBO(&mod->textures[t]->vbo); - } } #ifdef TERRAIN if (mod->type == mod_heightmap) @@ -386,8 +378,8 @@ void RMod_Init (void) mod_numknown = 0; Q1BSP_Init(); - Cmd_AddRemCommand("mod_texturelist", RMod_TextureList_f); - Cmd_AddRemCommand("mod_usetexture", RMod_BlockTextureColour_f); + Cmd_AddCommand("mod_texturelist", RMod_TextureList_f); + Cmd_AddCommand("mod_usetexture", RMod_BlockTextureColour_f); } void RMod_Shutdown (void) @@ -1066,7 +1058,6 @@ Mod_LoadTextures */ qboolean RMod_LoadTextures (lump_t *l) { - extern int gl_bumpmappingpossible; int i, j, pixels, num, max, altmax; miptex_t *mt; texture_t *tx, *tx2; @@ -1220,13 +1211,10 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n")); tn.bump = r_nulltex; if (r_loadbumpmapping) { - if (r_loadbumpmapping) - { - snprintf(altname, sizeof(altname)-1, "%s_norm", mt->name); - tn.bump = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY|IF_MIPCAP); - if (!TEXVALID(tn.bump)) - tn.bump = R_LoadReplacementTexture(altname, "bmodels", IF_NOGAMMA|IF_MIPCAP); - } + snprintf(altname, sizeof(altname)-1, "%s_norm", mt->name); + tn.bump = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY|IF_MIPCAP); + if (!TEXVALID(tn.bump)) + tn.bump = R_LoadReplacementTexture(altname, "bmodels", IF_NOGAMMA|IF_MIPCAP); if (!TEXVALID(tn.bump)) { if (gl_load24bit.value) @@ -1240,7 +1228,7 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n")); snprintf(altname, sizeof(altname)-1, "%s_bump", mt->name); } -/* if (!TEXVALID(tn.bump) && loadmodel->fromgame != fg_halflife) + if (!TEXVALID(tn.bump) && loadmodel->fromgame != fg_halflife)// && gl_bump_fallbacks.ival) { //no mip levels here, would be absurd. base = (qbyte *)(mt+1); //convert to greyscale. @@ -1249,7 +1237,7 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n")); tn.bump = R_LoadTexture8BumpPal(altname, tx->width, tx->height, base, true); //normalise it and then bump it. } -*/ + //don't do any complex quake 8bit -> glossmap. It would likly look a little ugly... if (gl_specular.value && gl_load24bit.value) { @@ -1372,7 +1360,6 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n")); void RMod_NowLoadExternal(void) { - extern int gl_bumpmappingpossible; int i, width, height; qboolean alphaed; texture_t *tx; @@ -3322,12 +3309,6 @@ qboolean RMod_LoadBrushModel (model_t *mod, void *buffer) mod->numframes = 2; // regular and alternate animation - /*FIXME: move mesh_t and lightmap allocation out of r_surf - for (i=0 ; inumsurfaces ; i++) - { - Surf_BuildSurfaceDisplayList (mod, mod->surfaces + i); - } - */ // // set up the submodels (FIXME: this is confusing) diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 4afd430a2..47017f423 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -113,6 +113,7 @@ typedef struct batch_s /*caller-use, not interpreted by backend*/ union { + unsigned int shadowbatch; //a unique index to accelerate shadowmesh generation (dlights, yay!) struct { unsigned int surf_first; @@ -291,6 +292,8 @@ typedef struct vbo_s unsigned int vbobones; float *bones; unsigned int numbones; + + struct vbo_s *next; } vbo_t; void GL_SelectVBO(int vbo); void GL_SelectEBO(int vbo); @@ -300,13 +303,9 @@ typedef struct texture_s char name[64]; unsigned width, height; - qbyte pixbytes; qbyte alphaed; //gl_blend needed on this surface. struct shader_s *shader; - int wtexno; - - vbo_t vbo; int anim_total; // total tenths in sequence ( 0 = no) int anim_min, anim_max; // time for this frame min <=time< max @@ -949,6 +948,12 @@ typedef struct model_s q3lightgridinfo_t *lightgrid; char *entities; + struct { + texture_t *tex; + vbo_t *vbo; + } *shadowbatches; + int numshadowbatches; + vbo_t *vbos; void *terrain; batch_t *batches[SHADER_SORT_COUNT]; diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 07d6103f6..e1f978ce3 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -817,9 +817,12 @@ void R_LoadRTLights(void) dl->coronascale = coronascale; dl->die = 0; dl->flags = flags; - dl->lightcolourscales[0] = ambientscale; - dl->lightcolourscales[1] = diffusescale; - dl->lightcolourscales[2] = specularscale; + if (ambientscale || diffusescale || specularscale) + { + dl->lightcolourscales[0] = ambientscale; + dl->lightcolourscales[1] = diffusescale; + dl->lightcolourscales[2] = specularscale; + } AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]); Q_strncpyz(dl->cubemapname, cubename, sizeof(dl->cubemapname)); @@ -1153,7 +1156,7 @@ int GLRecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) -int GLR_LightPoint (vec3_t p) +int R_LightPoint (vec3_t p) { vec3_t end; int r; diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index d69437a3e..7e3b533f0 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -69,7 +69,7 @@ cvar_t gl_affinemodels = SCVAR("gl_affinemodels","0"); cvar_t gl_reporttjunctions = SCVAR("gl_reporttjunctions","0"); cvar_t gl_finish = SCVAR("gl_finish","0"); cvar_t gl_dither = SCVAR("gl_dither", "1"); -cvar_t r_postprocshader = CVARD("r_postprocshader", "", "Specifies a shader to use as a post-processing shader"); +extern cvar_t r_postprocshader; extern cvar_t gl_screenangle; @@ -733,6 +733,10 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist) qglClipPlane(GL_CLIP_PLANE0, glplane); qglEnable(GL_CLIP_PLANE0); } + frustum[4].normal[0] = plane.normal[0]; + frustum[4].normal[1] = plane.normal[1]; + frustum[4].normal[2] = plane.normal[2]; + frustum[4].dist = plane.dist + 0.01; R_RenderScene(); if (qglClipPlane) qglDisable(GL_CLIP_PLANE0); diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index e8ae0d62d..5e6c600da 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -450,11 +450,8 @@ void GLR_DeInit (void) Cvar_Unhook(&vid_conautoscale); Cvar_Unhook(&vid_conheight); Cvar_Unhook(&vid_conwidth); - Cvar_Unhook(&r_wallcolour); - Cvar_Unhook(&r_floorcolour); Cvar_Unhook(&r_walltexture); Cvar_Unhook(&r_floortexture); - Cvar_Unhook(&r_fastskycolour); Cvar_Unhook(&r_drawflat); Cvar_Unhook(&v_gamma); Cvar_Unhook(&v_contrast); @@ -466,13 +463,10 @@ void GLR_DeInit (void) void GLR_Init (void) { - Cmd_AddRemCommand ("timerefresh", GLR_TimeRefresh_f); + Cmd_AddCommand ("timerefresh", GLR_TimeRefresh_f); -// Cmd_AddRemCommand ("makewad", R_MakeTexWad_f); +// Cmd_AddCommand ("makewad", R_MakeTexWad_f); -// Cvar_Hook(&r_floorcolour, GLR_Floorcolour_Callback); -// Cvar_Hook(&r_fastskycolour, GLR_Fastskycolour_Callback); -// Cvar_Hook(&r_wallcolour, GLR_Wallcolour_Callback); // Cvar_Hook(&r_floortexture, GLR_Floortexture_Callback); // Cvar_Hook(&r_walltexture, GLR_Walltexture_Callback); // Cvar_Hook(&r_drawflat, GLR_Drawflat_Callback); diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index 69356d5bc..5b62689eb 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -131,12 +131,11 @@ void *allocbuf(char **p, int elements, int elementsize) return ret; } -void GLBE_GenBrushModelVBO(model_t *mod) +void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch) { unsigned int maxvboverts; unsigned int maxvboelements; - unsigned int t; unsigned int i; unsigned int v; unsigned int vcount, ecount; @@ -155,7 +154,166 @@ void GLBE_GenBrushModelVBO(model_t *mod) vec3_t *tvector; vec4_t *colours; index_t *indicies; + batch_t *batch; + + vbo = Z_Malloc(sizeof(*vbo)); + + maxvboverts = 0; + maxvboelements = 0; + meshes = 0; + for(batch = firstbatch; batch != stopbatch; batch = batch->next) + { + for (i=0 ; imeshes ; i++) + { + m = batch->mesh[i]; + meshes++; + maxvboelements += m->numindexes; + maxvboverts += m->numvertexes; + } + } + if (maxvboverts > MAX_INDICIES) + Sys_Error("Building a vbo with too many verticies\n"); + + + vcount = 0; + ecount = 0; + + pervertsize = sizeof(vecV_t)+ //coord + sizeof(vec2_t)+ //tex + sizeof(vec2_t)+ //lm + sizeof(vec3_t)+ //normal + sizeof(vec3_t)+ //sdir + sizeof(vec3_t)+ //tdir + sizeof(vec4_t); //colours + + vbo->vertdata = BZ_Malloc((maxvboverts+1)*pervertsize + (maxvboelements+1)*sizeof(index_t)); + + p = vbo->vertdata; + + vbo->coord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vecV_t)); + vbo->texcoord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec2_t)); + vbo->lmcoord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec2_t)); + vbo->normals.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t)); + vbo->svector.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t)); + vbo->tvector.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t)); + vbo->colours.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec4_t)); + vbo->indicies.gl.addr = allocbuf(&p, maxvboelements, sizeof(index_t)); + + coord = vbo->coord.gl.addr; + texcoord = vbo->texcoord.gl.addr; + lmcoord = vbo->lmcoord.gl.addr; + normals = vbo->normals.gl.addr; + svector = vbo->svector.gl.addr; + tvector = vbo->tvector.gl.addr; + colours = vbo->colours.gl.addr; + indicies = vbo->indicies.gl.addr; + + //vbo->meshcount = meshes; + //vbo->meshlist = BZ_Malloc(meshes*sizeof(*vbo->meshlist)); + + meshes = 0; + + + for(batch = firstbatch; batch != stopbatch; batch = batch->next) + { + batch->vbo = vbo; + for (i=0 ; imeshes ; i++) + { + m = batch->mesh[i]; + +// surf->mark = &vbo->meshlist[meshes++]; +// *surf->mark = NULL; + + m->vbofirstvert = vcount; + m->vbofirstelement = ecount; + for (v = 0; v < m->numindexes; v++) + indicies[ecount++] = vcount + m->indexes[v]; + for (v = 0; v < m->numvertexes; v++) + { + coord[vcount+v][0] = m->xyz_array[v][0]; + coord[vcount+v][1] = m->xyz_array[v][1]; + coord[vcount+v][2] = m->xyz_array[v][2]; + if (m->st_array) + { + texcoord[vcount+v][0] = m->st_array[v][0]; + texcoord[vcount+v][1] = m->st_array[v][1]; + } + if (m->lmst_array) + { + lmcoord[vcount+v][0] = m->lmst_array[v][0]; + lmcoord[vcount+v][1] = m->lmst_array[v][1]; + } + if (m->normals_array) + { + normals[vcount+v][0] = m->normals_array[v][0]; + normals[vcount+v][1] = m->normals_array[v][1]; + normals[vcount+v][2] = m->normals_array[v][2]; + } + if (m->snormals_array) + { + svector[vcount+v][0] = m->snormals_array[v][0]; + svector[vcount+v][1] = m->snormals_array[v][1]; + svector[vcount+v][2] = m->snormals_array[v][2]; + } + if (m->tnormals_array) + { + tvector[vcount+v][0] = m->tnormals_array[v][0]; + tvector[vcount+v][1] = m->tnormals_array[v][1]; + tvector[vcount+v][2] = m->tnormals_array[v][2]; + } + if (m->colors4f_array) + { + colours[vcount+v][0] = m->colors4f_array[v][0]; + colours[vcount+v][1] = m->colors4f_array[v][1]; + colours[vcount+v][2] = m->colors4f_array[v][2]; + colours[vcount+v][3] = m->colors4f_array[v][3]; + } + } + vcount += v; + } + } + + if (GL_BuildVBO(vbo, vbo->vertdata, vcount*pervertsize, indicies, ecount*sizeof(index_t), 0)) + { + BZ_Free(vbo->vertdata); + vbo->vertdata = NULL; + } + + vbo->next = *vbochain; + *vbochain = vbo; +} + +void GLBE_GenBrushModelVBO(model_t *mod) +{ + unsigned int vcount; + + + batch_t *batch, *fbatch; + int sortid; + + fbatch = NULL; + vcount = 0; + for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) + { + if (!mod->batches[sortid]) + continue; + + for (fbatch = batch = mod->batches[sortid]; batch != NULL; batch = batch->next) + { + //firstmesh got reused as the number of verticies in each batch + if (vcount + batch->firstmesh > MAX_INDICIES) + { + GLBE_GenBatchVBOs(&mod->vbos, fbatch, batch); + fbatch = batch; + vcount = 0; + } + vcount += batch->firstmesh; + } + + GLBE_GenBatchVBOs(&mod->vbos, fbatch, batch); + } +#if 0 if (!mod->numsurfaces) return; @@ -292,6 +450,7 @@ void GLBE_GenBrushModelVBO(model_t *mod) vbo->vertdata = NULL; } } +#endif } void GLBE_UploadAllLightmaps(void) diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 96b2c0a03..15c6cc552 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -1040,91 +1040,6 @@ struct sbuiltin_s "}\n" "#endif\n" }, - {QR_OPENGL, 110, "default2d", - "#ifdef VERTEX_SHADER\n" - "attribute vec2 v_texcoord;\n" - "attribute vec4 v_colour;\n" - "varying vec2 tc;\n" - "varying vec4 vc;\n" - - "void main ()\n" - "{\n" - " tc = v_texcoord;\n" - " vc = v_colour;\n" - " gl_Position = ftetransform();\n" - "}\n" - "#endif\n" - - "#ifdef FRAGMENT_SHADER\n" - "uniform sampler2D s_t0;\n" - "in vec2 tc;\n" - "varying vec4 vc;\n" - - "void main ()\n" - "{\n" - " gl_FragColor = texture2D(s_t0, tc) * vc;\n" - "}\n" - "#endif\n" - }, - - {QR_OPENGL, 110, "defaultsprite", - "!!permu FOG\n" - "#include \"sys/fog.h\"\n" - "#ifdef VERTEX_SHADER\n" - "attribute vec2 v_texcoord;\n" - "attribute vec4 v_colour;\n" - "varying vec2 tc;\n" - "varying vec4 vc;\n" - - "void main ()\n" - "{\n" - " tc = v_texcoord;\n" - " vc = v_colour;\n" - " gl_Position = ftetransform();\n" - "}\n" - "#endif\n" - - "#ifdef FRAGMENT_SHADER\n" - "uniform sampler2D s_t0;\n" - "varying vec2 tc;\n" - "varying vec4 vc;\n" - "uniform vec4 e_colourident;\n" - - "void main ()\n" - "{\n" - " gl_FragColor = fog4blend(texture2D(s_t0, tc) * vc * e_colourident);\n" - "}\n" - "#endif\n" - }, - {QR_OPENGL, 110, "defaultadditivesprite", - "!!permu FOG\n" - "#include \"sys/fog.h\"\n" - "#ifdef VERTEX_SHADER\n" - "attribute vec2 v_texcoord;\n" - "attribute vec4 v_colour;\n" - "varying vec2 tc;\n" - "varying vec4 vc;\n" - - "void main ()\n" - "{\n" - " tc = v_texcoord;\n" - " vc = v_colour;\n" - " gl_Position = ftetransform();\n" - "}\n" - "#endif\n" - - "#ifdef FRAGMENT_SHADER\n" - "uniform sampler2D s_t0;\n" - "varying vec2 tc;\n" - "varying vec4 vc;\n" - "uniform vec4 e_colourident;\n" - - "void main ()\n" - "{\n" - " gl_FragColor = fog4additive(texture2D(s_t0, tc) * vc * e_colourident);\n" - "}\n" - "#endif\n" - }, /*draws a wall, with lightmap.*/ {QR_OPENGL/*ES*/, 100, "defaultwall", "#ifdef VERTEX_SHADER\n" @@ -1155,76 +1070,6 @@ struct sbuiltin_s "}\n" "#endif\n" }, - {QR_OPENGL, 110, "defaultwall", - "!!permu OFFSETMAPPING\n" - "!!permu FULLBRIGHT\n" - "!!permu FOG\n" - "!!cvarf r_glsl_offsetmapping_scale\n" - "#include \"sys/fog.h\"\n" - "#if defined(OFFSETMAPPING)\n" - "varying vec3 eyevector;\n" - "#endif\n" - - "#ifdef VERTEX_SHADER\n" - "attribute vec2 v_texcoord;\n" - "attribute vec2 v_lmcoord;\n" - "varying vec2 tc, lm;\n" - - "#if defined(OFFSETMAPPING)\n" - "uniform vec3 e_eyepos;\n" - "attribute vec3 v_normal;\n" - "attribute vec3 v_svector;\n" - "attribute vec3 v_tvector;\n" - "#endif\n" - "void main ()\n" - "{\n" - "#if defined(OFFSETMAPPING)\n" - "vec3 eyeminusvertex = e_eyepos - v_position.xyz;\n" - "eyevector.x = dot(eyeminusvertex, v_svector.xyz);\n" - "eyevector.y = -dot(eyeminusvertex, v_tvector.xyz);\n" - "eyevector.z = dot(eyeminusvertex, v_normal.xyz);\n" - "#endif\n" - " tc = v_texcoord;\n" - " lm = v_lmcoord;\n" - " gl_Position = ftetransform();\n" - "}\n" - "#endif\n" - - "#ifdef FRAGMENT_SHADER\n" - "uniform sampler2D s_t0;\n" /*tex_diffuse*/ - "uniform sampler2D s_t1;\n" /*tex_lightmap*/ - "#ifdef OFFSETMAPPING\n" - "uniform sampler2D s_t2;\n" /*tex_normalmap*/ - "#endif\n" - //"uniform sampler2D s_t3;\n" /*tex_deluxmap*/ - "#ifdef FULLBRIGHT\n" - "uniform sampler2D s_t4;\n" /*tex_fullbright*/ - "#endif\n" - "varying vec2 tc, lm;\n" - "uniform vec4 e_lmscale;\n" - "uniform vec4 e_colourident;\n" - - "#ifdef OFFSETMAPPING\n" - "#include \"sys/offsetmapping.h\"\n" - "#endif\n" - - "void main ()\n" - "{\n" - "#ifdef OFFSETMAPPING\n" - "vec2 tcoffsetmap = offsetmap(s_t2, tc, eyevector);\n" - "#define tc tcoffsetmap\n" - "#endif\n" - " gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * e_lmscale;\n" - "#ifdef FULLBRIGHT\n" - " gl_FragColor.rgb += texture2D(s_t4, tc).rgb;\n" - "#endif\n" - "gl_FragColor = gl_FragColor * e_colourident;\n" - "#ifdef FOG\n" - "gl_FragColor = fog4(gl_FragColor);\n" - "#endif\n" - "}\n" - "#endif\n" - }, {QR_OPENGL, 100, "drawflat_wall", "!!cvarv r_floorcolor\n" "!!cvarv r_wallcolor\n" @@ -1247,38 +1092,6 @@ struct sbuiltin_s "}\n" "#endif\n" - "#ifdef FRAGMENT_SHADER\n" - "uniform sampler2D s_t0;\n" /*tex_lightmap*/ - "varying vec2 lm;\n" - - "void main ()\n" - "{\n" - " gl_FragColor = fog4(col * texture2D(s_t0, lm));\n" - "}\n" - "#endif\n" - }, - {QR_OPENGL, 110, "drawflat_wall", - "!!cvarv r_floorcolor\n" - "!!cvarv r_wallcolor\n" - "!!permu FOG\n" - "#include \"sys/fog.h\"\n" - "varying vec4 col;\n" - "#ifdef VERTEX_SHADER\n" - "attribute vec3 v_normal;\n" - "attribute vec2 v_lmcoord;\n" - "varying vec2 lm;\n" - "uniform vec3 cvar_r_wallcolor;\n" - "uniform vec3 cvar_r_floorcolor;\n" - "uniform vec4 e_lmscale;\n" - - "void main ()\n" - "{\n" - " col = vec4(e_lmscale.rgb/255.0 * ((v_normal.z < 0.73)?cvar_r_wallcolor:cvar_r_floorcolor), e_lmscale.a);\n" - " lm = v_lmcoord;\n" - " gl_Position = ftetransform();\n" - "}\n" - "#endif\n" - "#ifdef FRAGMENT_SHADER\n" "uniform sampler2D s_t0;\n" /*tex_lightmap*/ "varying vec2 lm;\n" @@ -1318,146 +1131,6 @@ struct sbuiltin_s "}\n" "#endif\n" }, - {QR_OPENGL, 110, "defaultwarp", - "!!cvarf r_wateralpha\n" - "!!permu FOG\n" - "#include \"sys/fog.h\"\n" - "varying vec2 tc;\n" - "#ifdef VERTEX_SHADER\n" - "attribute vec2 v_texcoord;\n" - "void main ()\n" - "{\n" - " tc = v_texcoord.st;\n" - " gl_Position = ftetransform();\n" - "}\n" - "#endif\n" - - "#ifdef FRAGMENT_SHADER\n" - "uniform sampler2D s_t0;\n" - "uniform float e_time;\n" - "uniform float cvar_r_wateralpha;\n" - - "void main ()\n" - "{\n" - " vec2 ntc;\n" - " ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n" - " ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n" - " vec3 ts = vec3(texture2D(s_t0, ntc));\n" - - " gl_FragColor = fog4(vec4(ts, cvar_r_wateralpha));\n" - "}\n" - "#endif\n" - }, - {QR_OPENGL, 110, "underwaterwarp", - /* - inputs: - texcoords: edge points - coords: vertex coords (duh) - time - ampscale (cvar = r_waterwarp) - - use ifs instead of an edge map? - */ - "!!cvarf r_waterwarp\n" - "#ifdef VERTEX_SHADER\n" - "attribute vec2 v_texcoord;\n" - "varying vec2 v_stc;\n" - "varying vec2 v_warp;\n" - "varying vec2 v_edge;\n" - "uniform float e_time;\n" - "void main ()\n" - "{\n" - "gl_Position = ftetransform();\n" - "v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0;\n" - "v_warp.s = e_time * 0.25 + v_texcoord.s;\n" - "v_warp.t = e_time * 0.25 + v_texcoord.t;\n" - "v_edge = v_texcoord.xy;\n" - "}\n" - "#endif\n" - "#ifdef FRAGMENT_SHADER\n" - "varying vec2 v_stc;\n" - "varying vec2 v_warp;\n" - "varying vec2 v_edge;\n" - "uniform sampler2D s_t0;/*$currentrender*/\n" - "uniform sampler2D s_t1;/*warp image*/\n" - "uniform sampler2D s_t2;/*edge image*/\n" - "uniform vec3 e_rendertexturescale;\n" - "uniform float cvar_r_waterwarp;\n" - "void main ()\n" - "{\n" - "float amptemp;\n" - "vec3 edge;\n" - "edge = texture2D( s_t2, v_edge ).rgb;\n" - "amptemp = (0.010 / 0.625) * cvar_r_waterwarp * edge.x;\n" - "vec3 offset;\n" - "offset = texture2D( s_t1, v_warp ).rgb;\n" - "offset.x = (offset.x - 0.5) * 2.0;\n" - "offset.y = (offset.y - 0.5) * 2.0;\n" - "vec2 temp;\n" - "temp.x = v_stc.x + offset.x * amptemp;\n" - "temp.y = v_stc.y + offset.y * amptemp;\n" - "gl_FragColor = texture2D( s_t0, temp*e_rendertexturescale.st );\n" - "}\n" - "#endif\n" - }, - {QR_OPENGL, 110, "postproc_panorama", - "!!cvarf ffov\n" - "#ifdef VERTEX_SHADER\n" - "attribute vec2 v_texcoord;\n" - "varying vec2 texcoord;\n" - "void main()\n" - "{\n" - "texcoord = v_texcoord.xy;\n" - "gl_Position = ftetransform();\n" - "}\n" - "#endif\n" - "#ifdef FRAGMENT_SHADER\n" - "uniform samplerCube s_t0;\n" - "varying vec2 texcoord;\n" - "uniform float cvar_ffov;\n" - "void main()\n" - "{\n" - "vec3 tc; \n" - "float ang; \n" - "ang = texcoord.x*-radians(cvar_ffov); \n" - "tc.x = sin(ang); \n" - "tc.y = -texcoord.y; \n" - "tc.z = cos(ang); \n" - "gl_FragColor = textureCube(s_t0, tc);\n" - "}\n" - "#endif\n" - - }, - {QR_OPENGL, 110, "postproc_fisheye", - "!!cvarf ffov\n" - "#ifdef VERTEX_SHADER\n" - "attribute vec2 v_texcoord;\n" - "varying vec2 texcoord;\n" - "void main()\n" - "{\n" - "texcoord = v_texcoord.xy;\n" - "gl_Position = ftetransform();\n" - "}\n" - "#endif\n" - "#ifdef FRAGMENT_SHADER\n" - "uniform samplerCube s_t0;\n" - "varying vec2 texcoord;\n" - "uniform float cvar_ffov;\n" - "void main()\n" - "{\n" - "vec3 tc; \n" - "vec2 d; \n" - "vec2 ang; \n" - "d = texcoord; \n" - "ang.x = sqrt(d.x*d.x+d.y*d.y)*radians(cvar_ffov); \n" - "ang.y = -atan(d.y, d.x); \n" - "tc.x = sin(ang.x) * cos(ang.y); \n" - "tc.y = sin(ang.x) * sin(ang.y); \n" - "tc.z = cos(ang.x); \n" - "gl_FragColor = textureCube(s_t0, tc);\n" - "}\n" - "#endif\n" - }, /*defautsky projects the texture in order to match q1 skies, along with two separate layers scrolling at separate speeds*/ {QR_OPENGL/*ES*/, 100, "defaultsky", "#ifdef VERTEX_SHADER\n" @@ -1498,43 +1171,6 @@ struct sbuiltin_s "}\n" "#endif\n" }, - {QR_OPENGL, 110, "defaultsky", - "#ifdef VERTEX_SHADER\n" - "varying vec3 pos;\n" - - "void main ()\n" - "{\n" - " pos = v_position.xyz;\n" - " gl_Position = ftetransform();\n" - "}\n" - "#endif\n" - - "#ifdef FRAGMENT_SHADER\n" - "uniform float e_time;\n" - "uniform vec3 e_eyepos;\n" - "varying vec3 pos;\n" - "uniform sampler2D s_t0;\n" - "uniform sampler2D s_t1;\n" - - "void main ()\n" - "{\n" - " vec2 tccoord;\n" - - " vec3 dir = pos - e_eyepos;\n" - - " dir.z *= 3.0;\n" - " dir.xy /= 0.5*length(dir);\n" - - " tccoord = (dir.xy + e_time*0.03125);\n" - " vec3 solid = vec3(texture2D(s_t0, tccoord));\n" - - " tccoord = (dir.xy + e_time*0.0625);\n" - " vec4 clouds = texture2D(s_t1, tccoord);\n" - - " gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n" - "}\n" - "#endif\n" - }, /*draws a model. there's lots of extra stuff for light shading calcs and upper/lower textures*/ {QR_OPENGL/*ES*/, 100, "defaultskin", "!!permu FULLBRIGHT\n" @@ -1598,560 +1234,6 @@ struct sbuiltin_s "}\n" "#endif\n" }, - {QR_OPENGL, 110, "defaultskin", - "!!permu FULLBRIGHT\n" - "!!permu UPPERLOWER\n" - "!!permu FRAMEBLEND\n" - "!!permu SKELETAL\n" - "!!permu FOG\n" - "varying vec2 tc;\n" - "varying vec3 light;\n" - "#ifdef VERTEX_SHADER\n" - "#include \"sys/skeletal.h\"\n" - "attribute vec2 v_texcoord;\n" - - "uniform vec3 e_light_dir;\n" - "uniform vec3 e_light_mul;\n" - "uniform vec3 e_light_ambient;\n" - "void main ()\n" - "{\n" - " vec3 n;\n" - " gl_Position = skeletaltransform_n(n);\n" - " light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul);\n" - " tc = v_texcoord;\n" - "}\n" - "#endif\n" - - "#ifdef FRAGMENT_SHADER\n" - "#include \"sys/fog.h\"\n" - "uniform sampler2D s_t0;\n" /*tex_diffuse*/ - "#ifdef LOWER\n" - "uniform sampler2D s_t1;\n" /*tex_lower*/ - "uniform vec3 e_lowercolour;\n" - "#endif\n" - "#ifdef UPPER\n" - "uniform sampler2D s_t2;\n" /*tex_upper*/ - "uniform vec3 e_uppercolour;\n" - "#endif\n" - "#ifdef FULLBRIGHT\n" - "uniform sampler2D s_t3;\n" /*tex_fullbright*/ - "#endif\n" - "uniform vec4 e_colourident;\n" - - "void main ()\n" - "{\n" - " vec4 col, sp;\n" - " col = texture2D(s_t0, tc);\n" - "#ifdef UPPER\n" - " vec4 uc = texture2D(s_t2, tc);\n" - " col.rgb = mix(col.rgb, uc.rgb*e_uppercolour, uc.a);\n" - "#endif\n" - "#ifdef LOWER\n" - " vec4 lc = texture2D(s_t1, tc);\n" - " col.rgb = mix(col.rgb, lc.rgb*e_lowercolour, lc.a);\n" - "#endif\n" - " col.rgb *= light;\n" - "#ifdef FULLBRIGHT\n" - " vec4 fb = texture2D(s_t3, tc);\n" - " col.rgb = mix(col.rgb, fb.rgb, fb.a);\n" - "#endif\n" - " gl_FragColor = fog4(col * e_colourident);\n" - "}\n" - "#endif\n" - }, - {QR_OPENGL, 110, "lpp_depthnorm", - "!!permu BUMP\n" - "!!permu SKELETAL\n" - "varying vec3 norm, tang, bitang;\n" - "#if defined(BUMP)\n" - "varying vec2 tc;\n" - "#endif\n" - "#ifdef VERTEX_SHADER\n" - "#include \"sys/skeletal.h\"\n" - "attribute vec2 v_texcoord;\n" - "void main()\n" - "{\n" - "#if defined(BUMP)\n" - "gl_Position = skeletaltransform_nst(norm, tang, bitang);\n" - "tc = v_texcoord;\n" - "#else\n" - "gl_Position = skeletaltransform_n(norm);\n" - "#endif\n" - "}\n" - "#endif\n" - "#ifdef FRAGMENT_SHADER\n" - "#if defined(BUMP)\n" - "uniform sampler2D s_t0;\n" - "#endif\n" - "void main()\n" - "{\n" - "vec3 onorm;\n" - "#if defined(BUMP)\n" - /*transform by the normalmap*/ - "vec3 bm = 2.0*texture2D(s_t0, tc).xyz - 1.0;\n" - "onorm = normalize(bm.x * tang + bm.y * bitang + bm.z * norm);\n" - "#else\n" - "onorm = norm;\n" - "#endif\n" - "gl_FragColor = vec4(onorm.xyz, gl_FragCoord.z / gl_FragCoord.w);\n" - "}\n" - "#endif\n" - }, - {QR_OPENGL, 110, "lpp_light", - "varying vec4 tf;\n" - "#ifdef VERTEX_SHADER\n" - "void main()\n" - "{\n" - "tf = ftetransform(); gl_Position = tf;\n" - "}\n" - "#endif\n" - "#ifdef FRAGMENT_SHADER\n" - "uniform sampler2D s_t0;\n" - "uniform vec3 l_lightposition;\n" - "uniform mat4 m_invviewprojection;\n" - - "uniform vec3 l_lightcolour;\n" - "uniform float l_lightradius;\n" - - "vec3 calcLightWorldPos(vec2 screenPos, float depth)\n" - "{\n" - "vec4 pos;\n" - - "pos.x = screenPos.x;\n" - "pos.y = screenPos.y;\n" - "pos.z = depth;\n" - "pos.w = 1.0;\n" - "pos = m_invviewprojection * pos;\n" - "return pos.xyz / pos.w;\n" - "}\n" - - "void main ()\n" - "{\n" - "vec3 lightColour = l_lightcolour.rgb;\n" - "float lightIntensity = 1.0;\n" - "float lightAttenuation = l_lightradius;\n" // fixme: just use the light radius for now, use better near/far att math separately once working - "float radiusFar = l_lightradius;\n" - "float radiusNear = l_lightradius*0.5;\n" - - "vec2 fc;\n" - "fc = tf.xy / tf.w;\n" - "vec4 data = texture2D(s_t0, (1.0 + fc) / 2.0);\n" - "float depth = data.a;\n" - "vec3 norm = data.xyz;\n" - - /* calc where the wall that generated this sample came from */ - "vec3 worldPos = calcLightWorldPos(fc, depth);\n" - - /*calc diffuse lighting term*/ - "vec3 lightDir = l_lightposition - worldPos;\n" - "float zdiff = 1.0 - clamp(length(lightDir) / lightAttenuation, 0.0, 1.0);\n" - "float atten = (radiusFar * zdiff) / (radiusFar - radiusNear);\n" - "atten = pow(atten, 2.0);\n" - "lightDir = normalize(lightDir);\n" - - "float nDotL = dot(norm, lightDir) * atten;\n" - - "float lightDiffuse = max(0.0, nDotL);\n" - - /*calc specular term*/ - // todo: specular term in its own buffer for full coloured specular - - "gl_FragColor = vec4(lightDiffuse * (lightColour * lightIntensity), 1.0);\n" -// gl_FragColor = vec4(normalize(lightDir), 0.0); - "}\n" - "#endif\n" - }, - {QR_OPENGL, 110, "lpp_wall", - "varying vec2 tc, lm;\n" - "varying vec4 tf;\n" - "#ifdef VERTEX_SHADER\n" - "attribute vec2 v_texcoord;\n" - "attribute vec2 v_lmcoord;\n" - - "void main ()\n" - "{\n" - "tc = v_texcoord;\n" - "lm = v_lmcoord;\n" - "gl_Position = tf = ftetransform();\n" - "}\n" - "#endif\n" - - "#ifdef FRAGMENT_SHADER\n" - "uniform sampler2D s_t0;\n" /*lpp lighting*/ - "uniform sampler2D s_t1;\n" /*tex_diffuse*/ - "uniform sampler2D s_t2;\n" /*tex_lightmap*/ - //"uniform sampler2D s_t3;\n" /*tex_normalmap*/ - //"uniform sampler2D s_t4;\n" /*tex_deluxmap*/ - //"uniform sampler2D s_t5;\n" /*tex_fullbright*/ - "uniform vec4 e_lmscale;\n" - - "void main ()\n" - "{\n" - //"gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * e_lmscale;\n" - - "vec2 nst;\n" - "nst = tf.xy / tf.w;\n" - "nst = (1.0 + nst) / 2.0;\n" - "vec4 l = texture2D(s_t0, nst)*5.0;\n" - "vec4 c = texture2D(s_t1, tc);\n" - "vec3 lmsamp = texture2D(s_t2, lm).rgb*lmscale;\n" - "vec3 diff = l.rgb;\n" - "vec3 chrom = diff / (0.001 + dot(diff, vec3(0.3, 0.59, 0.11)));\n" - "vec3 spec = chrom * l.a;\n" - - "gl_FragColor = vec4((diff + lmsamp) * c.xyz, 1.0);\n" // + 0.6 * spec, 1.0); - "}\n" - "#endif\n" - }, - - {QR_OPENGL, 110, "colourtint", - "varying vec4 tf;\n" - "#ifdef VERTEX_SHADER\n" - "void main ()\n" - "{\n" - "gl_Position = tf = vec4(v_position.xy,-1.0, 1.0);\n" - "}\n" - "#endif\n" - - "#ifdef FRAGMENT_SHADER\n" - "uniform sampler2D s_t0;\n" - "uniform sampler3D s_t1;\n" - "void main()\n" - "{\n" - "vec2 fc;\n" - "fc = tf.xy / tf.w;\n" - "vec3 raw = texture2D(s_t0, (1.0 + fc) / 2.0).rgb;\n" - - //scale+bias the sample to not clamp out at the edges - "#define LUTSIZE 16.0\n" - "vec3 scale = vec3((LUTSIZE-1.0)/LUTSIZE);\n" - "vec3 bias = vec3(1.0/(2.0*LUTSIZE));\n" - - "gl_FragColor = texture3D(s_t1, raw * scale + bias);\n" - - "}\n" - "#endif\n" - }, - - {QR_OPENGL, 110, "crepuscular_rays", - /*yoinked from http://fabiensanglard.net/lightScattering/index.php*/ - "!!cvarf crep_decay\n" - "!!cvarf crep_density\n" - "!!cvarf crep_weight\n" - - "varying vec2 tc;\n" - "#ifdef VERTEX_SHADER\n" - "attribute vec2 v_texcoord;\n" - "void main ()\n" - "{\n" - "tc = v_texcoord;\n" - "gl_Position = v_position;\n" - "}\n" - "#endif\n" - - "#ifdef FRAGMENT_SHADER\n" - "const float crep_decay = 0.94;\n" - "const float crep_density = 0.5;\n" - "const float crep_weight = 0.2;\n" - "uniform vec3 l_lightcolour;\n" - "uniform vec3 l_lightscreen;\n" - "uniform sampler2D s_t0;\n" - "const int NUM_SAMPLES = 100;\n" - - "void main()\n" - "{\n" - // "gl_FragColor = texture2D(s_t0, tc.st);\n" - "vec2 deltaTextCoord = vec2( tc.st - l_lightscreen.xy );\n" - "vec2 textCoo = tc.st;\n" - "deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * crep_density;\n" - "float illuminationDecay = 1.0;\n" - - "for(int i=0; i < NUM_SAMPLES ; i++)\n" - "{\n" - "textCoo -= deltaTextCoord;\n" - "vec4 sample = texture2D(s_t0, textCoo);\n" - "sample *= illuminationDecay * crep_weight;\n" - "gl_FragColor += sample;\n" - "illuminationDecay *= crep_decay;\n" - "}\n" - "gl_FragColor *= vec4(l_lightcolour, 1.0);\n" - "}\n" - "#endif\n" - }, - {QR_OPENGL, 110, "crepuscular_opaque", - "#ifdef VERTEX_SHADER\n" - "void main ()\n" - "{\n" - "gl_Position = ftetransform();\n" - "}\n" - "#endif\n" - "#ifdef FRAGMENT_SHADER\n" - "void main()\n" - "{\n" - "gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n" - "}\n" - "#endif\n" - }, - {QR_OPENGL, 110, "crepuscular_sky", - "#ifdef VERTEX_SHADER\n" - "varying vec3 pos;\n" - - "void main ()\n" - "{\n" - " pos = v_position.xyz;\n" - " gl_Position = ftetransform();\n" - "}\n" - "#endif\n" - - "#ifdef FRAGMENT_SHADER\n" - "uniform float e_time;\n" - "uniform vec3 e_eyepos;\n" - "varying vec3 pos;\n" - "uniform sampler2D s_t0;\n" - "uniform sampler2D s_t1;\n" - - "void main ()\n" - "{\n" - " vec2 tccoord;\n" - - " vec3 dir = pos - e_eyepos;\n" - - " dir.z *= 3.0;\n" - " dir.xy /= 0.5*length(dir);\n" - - " tccoord = (dir.xy + e_time*0.03125);\n" - " vec3 solid = vec3(texture2D(s_t0, tccoord));\n" - - " tccoord = (dir.xy + e_time*0.0625);\n" - " vec4 clouds = texture2D(s_t1, tccoord);\n" - - " gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n" - "}\n" - "#endif\n" - }, - {QR_OPENGL, 110, "rtlight", - /* - texture units: - s0=diffuse, s1=normal, s2=specular, s3=shadowmap - custom modifiers: - PCF(shadowmap) - CUBE(projected cubemap) - */ - "!!permu BUMP\n" - "!!permu SPECULAR\n" - "!!permu OFFSETMAPPING\n" - "!!permu SKELETAL\n" - "!!permu FOG\n" - - "!!cvarf r_glsl_offsetmapping_scale\n" - "varying vec2 tcbase;\n" - "varying vec3 lightvector;\n" - "#if defined(SPECULAR) || defined(OFFSETMAPPING)\n" - "varying vec3 eyevector;\n" - "#endif\n" - "#if defined(PCF) || defined(CUBE)\n" - "varying vec4 vshadowcoord;\n" - "uniform mat4 l_projmatrix;\n" - "#endif\n" - - "#ifdef VERTEX_SHADER\n" - "#include \"sys/skeletal.h\"\n" - - "uniform vec3 l_lightposition;\n" - "attribute vec2 v_texcoord;\n" - - "#if defined(SPECULAR) || defined(OFFSETMAPPING)\n" - "uniform vec3 e_eyepos;\n" - "#endif\n" - - "void main ()\n" - "{\n" - "vec3 n, s, t, w;\n" - "gl_Position = skeletaltransform_wnst(w,n,s,t);\n" - - "tcbase = v_texcoord; //pass the texture coords straight through\n" - - "vec3 lightminusvertex = l_lightposition - w.xyz;\n" - "lightvector.x = dot(lightminusvertex, s.xyz);\n" - "lightvector.y = dot(lightminusvertex, t.xyz);\n" - "lightvector.z = dot(lightminusvertex, n.xyz);\n" - - "#if defined(SPECULAR)||defined(OFFSETMAPPING)\n" - "vec3 eyeminusvertex = e_eyepos - w.xyz;\n" - "eyevector.x = dot(eyeminusvertex, s.xyz);\n" - "eyevector.y = -dot(eyeminusvertex, t.xyz);\n" - "eyevector.z = dot(eyeminusvertex, n.xyz);\n" - "#endif\n" - "#if defined(PCF) || defined(SPOT) || defined(PROJECTION) || defined(CUBE)\n" - "vshadowcoord = l_projmatrix*vec4(w.xyz, 1.0);\n" - "#endif\n" - "}\n" - "#endif\n" - -/*this is full 4*4 PCF, with an added attempt at prenumbra*/ -/*the offset consts are 1/(imagesize*2) */ -#define PCF16P(f) "\ - float xPixelOffset = (1.0+shadowcoord.b/l_lightradius)/texx;\ - float yPixelOffset = (1.0+shadowcoord.b/l_lightradius)/texy;\ - float s = 0.0;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ -\ - s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(-0.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ -\ - s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(0.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ -\ - s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, 0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(1.5 * xPixelOffset * shadowcoord.w, 1.1 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ -\ - colorscale *= s/5.0;\n\ - " - -/*this is pcf 3*3*/ -/*the offset consts are 1/(imagesize*2) */ -#define PCF9(f) "\ - const float xPixelOffset = 1.0/texx;\ - const float yPixelOffset = 1.0/texy;\ - float s = 0.0;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ -\ - s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ -\ - s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - colorscale *= s/9.0;\n\ - " - -/*this is a lazy form of pcf. take 5 samples in an x*/ -/*the offset consts are 1/(imagesize*2) */ -#define PCF5(f) "\ - float xPixelOffset = 1.0/texx;\ - float yPixelOffset = 1.0/texy;\ - float s = 0.0;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - s += "f"Proj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ - colorscale *= s/5.0;\n\ - " - -/*this is unfiltered*/ -#define PCF1(f) "\ - colorscale *= "f"Proj(shadowmap, shadowcoord).r;\n" - - "#ifdef FRAGMENT_SHADER\n" - "#include \"sys/fog.h\"\n" - "uniform sampler2D s_t0;\n"/*base texture*/ - "#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)\n" - "uniform sampler2D s_t1;\n"/*normalmap/height texture*/ - "#endif\n" - "#ifdef SPECULAR\n" - "uniform sampler2D s_t2;\n"/*specularmap texture*/ - "#endif\n" - "#ifdef CUBE\n" - "uniform samplerCube s_t3;\n"/*projected texture*/ - "#endif\n" - "#ifdef PCF\n" - "#ifdef CUBE\n" - "uniform samplerCubeShadow s_t7;\n" - "#else\n" - "uniform sampler2DShadow s_t7;\n" - "#endif\n" - "#endif\n" - - - "uniform float l_lightradius;\n" - "uniform vec3 l_lightcolour;\n" - "uniform vec3 l_lightcolourscale;\n" - - "#ifdef OFFSETMAPPING\n" - "#include \"sys/offsetmapping.h\"\n" - "#endif\n" - - "void main ()\n" - "{\n" - "#ifdef OFFSETMAPPING\n" - "vec2 tcoffsetmap = offsetmap(s_t1, tcbase, eyevector);\n" - "#define tcbase tcoffsetmap\n" - "#endif\n" - - - "vec3 bases = vec3(texture2D(s_t0, tcbase));\n" - - "#if defined(BUMP) || defined(SPECULAR)\n" - "vec3 bumps = vec3(texture2D(s_t1, tcbase)) - 0.5;\n" - "#endif\n" - "#ifdef SPECULAR\n" - "vec4 specs = texture2D(s_t2, tcbase);\n" - "#endif\n" - - "vec3 nl = normalize(lightvector);\n" - "float colorscale = max(1.0 - dot(lightvector, lightvector)/(l_lightradius*l_lightradius), 0.0);\n" - - "vec3 diff;\n" - "#ifdef BUMP\n" - "diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(2.0*bumps, nl), 0.0));\n" - "#else\n" - "diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));\n" - "#endif\n" - "#ifdef SPECULAR\n" - "vec3 halfdir = normalize(lightvector - normalize(eyevector));\n" - "float spec = pow(max(dot(halfdir, bumps), 0.0), 1.0 + 32.0 * specs.a);\n" - "diff += spec * specs.rgb * l_lightcolourscale.z;\n" - "#endif\n" - - "#ifdef CUBE\n" - "diff *= textureCube(s_t3, vshadowcoord.xyz).rgb;\n" - "#endif\n" - - "#ifdef PCF\n" - "#if defined(SPOT)\n" - "const float texx = 512.0;\n" - "const float texy = 512.0;\n" - "vec4 shadowcoord = vshadowcoord;\n" - "#else\n" - "const float texx = 512.0;\n" - "const float texy = 512.0;\n" - "vec4 shadowcoord;\n" - "shadowcoord.zw = vshadowcoord.zw;\n" - "shadowcoord.xy = vshadowcoord.xy;\n" - "#endif\n" - "#ifdef CUBE\n" - PCF9("shadowCube") /*valid are 1,5,9*/ - "#else\n" - PCF9("shadow2D") /*valid are 1,5,9*/ - "#endif\n" - "#endif\n" - "#if defined(SPOT)\n" - /*Actually, this isn't correct*/ - "if (shadowcoord.w < 0.0) discard;\n" - "vec2 spot = ((shadowcoord.st)/shadowcoord.w - 0.5)*2.0;colorscale*=1.0-(dot(spot,spot));\n" - "#endif\n" - "#if defined(PROJECTION)\n" - "l_lightcolour *= texture2d(s_t3, shadowcoord);\n" - "#endif\n" - - "gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);\n" - "}\n" - "#endif\n" - }, - #endif #ifdef D3DQUAKE {QR_DIRECT3D, 9, "rtlight", @@ -3104,6 +2186,18 @@ static qboolean ShaderPass_MapGen (shader_t *shader, shaderpass_t *pass, char *t pass->texgen = T_GEN_SOURCEDEPTH; pass->tcgen = TC_GEN_BASE; //FIXME: moo! } + else if (!Q_stricmp (tname, "$reflection")) + { + shader->flags |= SHADER_HASREFLECT; + pass->texgen = T_GEN_REFLECTION; + pass->tcgen = TC_GEN_BASE; //FIXME: moo! + } + else if (!Q_stricmp (tname, "$refraction")) + { + shader->flags |= SHADER_HASREFRACT; + pass->texgen = T_GEN_REFRACTION; + pass->tcgen = TC_GEN_BASE; //FIXME: moo! + } else return false; return true; @@ -5212,7 +4306,7 @@ void Shader_DefaultBSPQ1(char *shortname, shader_t *s, const void *args) "{\n" "map $diffuse\n" "tcgen base\n" - "alphamask\n" + "alphamask\n" "}\n" "if $lightmap\n" "[\n" diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 0fd67b188..894e7e628 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -66,8 +66,10 @@ void Sh_Shutdown(void) typedef struct { unsigned int count; unsigned int max; + texture_t *tex; + vbo_t *vbo; mesh_t **s; -} shadowmeshsurfs_t; +} shadowmeshbatch_t; typedef struct shadowmesh_s { qboolean surfonly; unsigned int numindicies; @@ -79,8 +81,8 @@ typedef struct shadowmesh_s { vecV_t *verts; //we also have a list of all the surfaces that this light lights. - unsigned int numsurftextures; - shadowmeshsurfs_t *litsurfs; + unsigned int numbatches; + shadowmeshbatch_t *batches; unsigned int leafbytes; unsigned char *litleaves; @@ -216,17 +218,17 @@ static void SHM_Shadow_Cache_Surface(msurface_t *surf) { int i; - i = surf->texinfo->texture->wtexno; + i = surf->sbatch->shadowbatch; if (i < 0) return; - if (sh_shmesh->litsurfs[i].count == sh_shmesh->litsurfs[i].max) + if (sh_shmesh->batches[i].count == sh_shmesh->batches[i].max) { - sh_shmesh->litsurfs[i].max += 64; - sh_shmesh->litsurfs[i].s = BZ_Realloc(sh_shmesh->litsurfs[i].s, sizeof(void*)*(sh_shmesh->litsurfs[i].max)); + sh_shmesh->batches[i].max += 64; + sh_shmesh->batches[i].s = BZ_Realloc(sh_shmesh->batches[i].s, sizeof(void*)*(sh_shmesh->batches[i].max)); } - sh_shmesh->litsurfs[i].s[sh_shmesh->litsurfs[i].count] = surf->mesh; - sh_shmesh->litsurfs[i].count++; + sh_shmesh->batches[i].s[sh_shmesh->batches[i].count] = surf->mesh; + sh_shmesh->batches[i].count++; } static void SHM_Shadow_Cache_Leaf(mleaf_t *leaf) @@ -240,9 +242,9 @@ static void SHM_Shadow_Cache_Leaf(mleaf_t *leaf) void SH_FreeShadowMesh(shadowmesh_t *sm) { unsigned int i; - for (i = 0; i < sm->numsurftextures; i++) - Z_Free(sm->litsurfs[i].s); - Z_Free(sm->litsurfs); + for (i = 0; i < sm->numbatches; i++) + Z_Free(sm->batches[i].s); + Z_Free(sm->batches); Z_Free(sm->indicies); Z_Free(sm->verts); @@ -270,6 +272,46 @@ void SH_FreeShadowMesh(shadowmesh_t *sm) Z_Free(sm); } +static void SH_CalcShadowBatches(model_t *mod) +{ + int s; + batch_t *b; + batch_t *l = NULL; + int sb; + + l = NULL; + for (s = 0; s < SHADER_SORT_COUNT; s++) + { + for (b = mod->batches[s]; b; b = b->next) + { + if (!l || l->vbo != b->vbo || l->texture != b->texture) + { + b->shadowbatch = mod->numshadowbatches++; + l = b; + } + else + b->shadowbatch = l->shadowbatch; + } + } + + l = NULL; + sb = 0; + mod->shadowbatches = BZ_Malloc(sizeof(*mod->shadowbatches)*mod->numshadowbatches); + for (s = 0; s < SHADER_SORT_COUNT; s++) + { + for (b = mod->batches[s]; b; b = b->next) + { + if (!l || l->vbo != b->vbo || l->texture != b->texture) + { + mod->shadowbatches[sb].tex = b->texture; + mod->shadowbatches[sb].vbo = b->vbo; + sb++; + l = b; + } + } + } +} + static void SHM_BeginShadowMesh(dlight_t *dl, qboolean surfonly) { unsigned int i; @@ -314,21 +356,26 @@ static void SHM_BeginShadowMesh(dlight_t *dl, qboolean surfonly) sh_shmesh->numindicies = 0; sh_shmesh->surfonly = surfonly; - if (sh_shmesh->numsurftextures != cl.worldmodel->numtextures) + if (!cl.worldmodel->numshadowbatches) { - if (sh_shmesh->litsurfs) - { - for (i = 0; i < sh_shmesh->numsurftextures; i++) - Z_Free(sh_shmesh->litsurfs[i].s); - Z_Free(sh_shmesh->litsurfs); - } - sh_shmesh->litsurfs = Z_Malloc(sizeof(shadowmeshsurfs_t)*cl.worldmodel->numtextures); - sh_shmesh->numsurftextures=cl.worldmodel->numtextures; + SH_CalcShadowBatches(cl.worldmodel); } - else + + if (sh_shmesh->numbatches != cl.worldmodel->numshadowbatches) { - for (i = 0; i < sh_shmesh->numsurftextures; i++) - sh_shmesh->litsurfs[i].count = 0; + if (sh_shmesh->batches) + { + for (i = 0; i < sh_shmesh->numbatches; i++) + Z_Free(sh_shmesh->batches[i].s); + Z_Free(sh_shmesh->batches); + } + sh_shmesh->batches = Z_Malloc(sizeof(shadowmeshbatch_t)*cl.worldmodel->numshadowbatches); + sh_shmesh->numbatches=cl.worldmodel->numshadowbatches; + } + + for (i = 0; i < sh_shmesh->numbatches; i++) + { + sh_shmesh->batches[i].count = 0; } } static struct shadowmesh_s *SHM_FinishShadowMesh(dlight_t *dl) @@ -1040,7 +1087,7 @@ static void SHM_ComposeVolume_Soup(vecV_t *points, int numpoints, index_t *idx, /*call this function after generating litsurfs meshes*/ static void SHM_ComposeVolume_BruteForce(dlight_t *dl) { - shadowmeshsurfs_t *sms; + shadowmeshbatch_t *sms; unsigned int tno; unsigned int sno; int i, e; @@ -1050,9 +1097,9 @@ static void SHM_ComposeVolume_BruteForce(dlight_t *dl) cv.numpoints = 0; cv.numtris = 0; - for (tno = 0; tno < sh_shmesh->numsurftextures; tno++) + for (tno = 0; tno < sh_shmesh->numbatches; tno++) { - sms = &sh_shmesh->litsurfs[tno]; + sms = &sh_shmesh->batches[tno]; if (!sms->count) continue; if ((cl.worldmodel->textures[tno]->shader->flags & (SHADER_BLEND|SHADER_NODRAW))) @@ -1791,9 +1838,6 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float p vec3_t t1,t2; int smsize = SHADOWMAP_SIZE; - int tno; - mesh_t *m; - texture_t *tex; // qglDepthRange(0, 1); @@ -1844,7 +1888,7 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float p R_SetFrustum(proj, mvm); - if (smesh) +/* if (smesh) for (tno = 0; tno < smesh->numsurftextures; tno++) { m = NULL; @@ -1853,7 +1897,7 @@ static void Sh_GenShadowFace(dlight_t *l, shadowmesh_t *smesh, int face, float p tex = cl.worldmodel->textures[tno]; BE_DrawMesh_List(tex->shader, smesh->litsurfs[tno].count, smesh->litsurfs[tno].s, &tex->vbo, &tex->shader->defaulttextures, 0); } - +*/ BE_SelectMode(BEM_DEPTHONLY); /*shadow meshes are always drawn as an external view*/ oxv = r_refdef.externalview; @@ -2138,14 +2182,14 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour) sm = &sh_tempshmesh; if (sm) { - for (tno = 0; tno < sm->numsurftextures; tno++) + for (tno = 0; tno < sm->numbatches; tno++) { - if (!sm->litsurfs[tno].count) + if (!sm->batches[tno].count) continue; - tex = cl.worldmodel->textures[tno]; + tex = cl.worldmodel->shadowbatches[tno].tex; if (tex->shader->flags & SHADER_NODLIGHT) continue; - BE_DrawMesh_List(tex->shader, sm->litsurfs[tno].count, sm->litsurfs[tno].s, &tex->vbo, &tex->shader->defaulttextures, 0); + BE_DrawMesh_List(tex->shader, sm->batches[tno].count, sm->batches[tno].s, cl.worldmodel->shadowbatches[tno].vbo, &tex->shader->defaulttextures, 0); } switch(qrenderer) @@ -2787,6 +2831,20 @@ void Sh_DrawCrepuscularLight(dlight_t *dl, float *colours, batch_t **batches) #endif } +void Sh_PurgeShadowMeshes(void) +{ + dlight_t *dl; + int i; + for (dl = cl_dlights, i=0; iworldshadowmesh) + { + SH_FreeShadowMesh(dl->worldshadowmesh); + dl->worldshadowmesh = NULL; + } + } +} + void Sh_PreGenerateLights(void) { unsigned int ignoreflags; @@ -2823,6 +2881,16 @@ void Sh_PreGenerateLights(void) } } +void Com_ParseVector(char *str, vec3_t out) +{ + str = COM_Parse(str); + out[0] = atof(com_token); + str = COM_Parse(str); + out[1] = atof(com_token); + str = COM_Parse(str); + out[2] = atof(com_token); +} + void Sh_DrawLights(qbyte *vis, batch_t **mbatches) { vec3_t colour; @@ -2831,6 +2899,7 @@ void Sh_DrawLights(qbyte *vis, batch_t **mbatches) unsigned int ignoreflags; extern cvar_t r_shadow_realtime_world, r_shadow_realtime_dlight; extern cvar_t r_shadow_realtime_world_shadows, r_shadow_realtime_dlight_shadows; + extern cvar_t r_sun_dir, r_sun_colour; if (!r_shadow_realtime_world.ival && !r_shadow_realtime_dlight.ival) { @@ -2914,6 +2983,39 @@ void Sh_DrawLights(qbyte *vis, batch_t **mbatches) } } + if (1) + { + dlight_t sun = {0}; + vec3_t sundir; + float dot; + Com_ParseVector(r_sun_dir.string, sundir); + Com_ParseVector(r_sun_colour.string, colour); + + //fade it out if we're looking at an angle parallel to it (to avoid nasty visible graduations or backwards rays!) + dot = DotProduct(vpn, sundir); + dot = 1-dot; + dot *= dot; + dot = 1-dot; + VectorScale(colour, dot, colour); + + if (colour[0] > 0.001 || colour[1] > 0.001 || colour[2] > 0.001) + { + //only do this if we can see some sky surfaces. pointless otherwise + batch_t *b; + for (b = cl.worldmodel->batches[SHADER_SORT_SKY]; b; b = b->next) + { + if (b->meshes) + break; + } + if (b) + { + VectorNormalize(sundir); + VectorMA(r_origin, 1000, sundir, sun.origin); + Sh_DrawCrepuscularLight(&sun, colour, mbatches); + } + } + } + switch(qrenderer) { #ifdef GLQUAKE diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 4ce2ca536..ace20c281 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -814,9 +814,9 @@ static const char *glsl_hdrs[] = "wmat += m_bones[int(v_bone.y)] * v_weight.y;" "wmat += m_bones[int(v_bone.z)] * v_weight.z;" "wmat += m_bones[int(v_bone.w)] * v_weight.w;" - "n = vec4(v_normal.xyz, 1.0) * wmat;" - "t = vec4(v_svector.xyz, 1.0) * wmat;" - "b = vec4(v_tvector.xyz, 1.0) * wmat;" + "n = vec4(v_normal.xyz, 0.0) * wmat;" + "t = vec4(v_svector.xyz, 0.0) * wmat;" + "b = vec4(v_tvector.xyz, 0.0) * wmat;" "return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);" "}\n" "vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)" @@ -826,9 +826,9 @@ static const char *glsl_hdrs[] = "wmat += m_bones[int(v_bone.y)] * v_weight.y;" "wmat += m_bones[int(v_bone.z)] * v_weight.z;" "wmat += m_bones[int(v_bone.w)] * v_weight.w;" - "n = vec4(v_normal.xyz, 1.0) * wmat;" - "t = vec4(v_svector.xyz, 1.0) * wmat;" - "b = vec4(v_tvector.xyz, 1.0) * wmat;" + "n = vec4(v_normal.xyz, 0.0) * wmat;" + "t = vec4(v_svector.xyz, 0.0) * wmat;" + "b = vec4(v_tvector.xyz, 0.0) * wmat;" "w = vec4(v_position.xyz, 1.0) * wmat;" "return m_modelviewprojection * vec4(w, 1.0);" "}\n" @@ -839,7 +839,7 @@ static const char *glsl_hdrs[] = "wmat += m_bones[int(v_bone.y)] * v_weight.y;" "wmat += m_bones[int(v_bone.z)] * v_weight.z;" "wmat += m_bones[int(v_bone.w)] * v_weight.w;" - "n = vec4(v_normal.xyz, 1.0) * wmat;" + "n = vec4(v_normal.xyz, 0.0) * wmat;" "return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);" "}\n" "#else\n" @@ -1519,8 +1519,6 @@ rendererinfo_t openglrendererinfo = { GLR_NewMap, GLR_PreNewMap, - GLR_LightPoint, - Surf_AddStain, Surf_LessenStains, diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index ee93aabbf..4b9586864 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -2090,7 +2090,7 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette) Cvar_Hook(&_vid_wait_override, VID_Wait_Override_Callback); Cvar_Hook(&vid_wndalpha, VID_WndAlpha_Override_Callback); - Cmd_AddRemCommand("vid_recenter", GLVID_Recenter_f); + Cmd_AddCommand("vid_recenter", GLVID_Recenter_f); vid_initialized = true; vid_initializing = false; diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index 81385f0b7..48ffeb0fb 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -450,7 +450,7 @@ static void GL_SkyForceDepth(batch_t *batch) if (!cls.allow_skyboxes && batch->texture) //allow a little extra fps. { BE_SelectMode(BEM_DEPTHONLY); - BE_DrawMesh_List(batch->shader, batch->meshes-batch->firstmesh, batch->mesh+batch->firstmesh, &batch->texture->vbo, &batch->shader->defaulttextures, batch->flags); + BE_DrawMesh_List(batch->shader, batch->meshes-batch->firstmesh, batch->mesh+batch->firstmesh, batch->vbo, &batch->shader->defaulttextures, batch->flags); BE_SelectMode(BEM_STANDARD); /*skys only render in standard mode anyway, so this is safe*/ } } diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 9f587f59f..52be1c79b 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -305,6 +305,7 @@ qboolean R_CullBox (vec3_t mins, vec3_t maxs); qboolean R_CullEntityBox(entity_t *e, vec3_t modmins, vec3_t modmaxs); qboolean R_CullSphere (vec3_t origin, float radius); void Sh_PreGenerateLights(void); +void Sh_PurgeShadowMeshes(void); #ifdef GLQUAKE void R_TranslatePlayerSkin (int playernum); @@ -393,12 +394,10 @@ void R_DrawHLModel(entity_t *curent); // // gl_rlight.c // -void R_RenderDlights (void); void R_GenDlightBatches(batch_t *batches[]); void R_InitFlashblends(void); #ifdef GLQUAKE void GLR_MarkQ2Lights (dlight_t *light, int bit, mnode_t *node); -int GLR_LightPoint (vec3_t p); #endif void GLQ3_LightGrid(model_t *mod, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); void R_ReloadRTLights_f(void); diff --git a/engine/gl/ltface.c b/engine/gl/ltface.c index 5f5d0c55f..18885b644 100644 --- a/engine/gl/ltface.c +++ b/engine/gl/ltface.c @@ -919,10 +919,7 @@ void LightFace (int surfnum) wnorm[ch] = norm[c][ch]; } total *= rangescale; // scale before clamping -#ifdef UTILITY - if (total > *out) //sorry - for qw - total = *out; -#else +#ifndef UTILITY if (total > *rgbout) //sorry - for qw total = *rgbout; #endif diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index 32d9c2fba..73dc0d2a4 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -86,3 +86,874 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" }, #endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "colourtint", +//this glsl shader is useful for cubemapped post processing effects (see csaddon for an example) +"varying vec4 tf;\n" +"#ifdef VERTEX_SHADER\n" +"void main ()\n" +"{\n" +"gl_Position = tf = vec4(v_position.xy,-1.0, 1.0);\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform sampler2D s_t0;\n" +"uniform sampler3D s_t1;\n" +"void main()\n" +"{\n" +"vec2 fc;\n" +"fc = tf.xy / tf.w;\n" +"vec3 raw = texture2D(s_t0, (1.0 + fc) / 2.0).rgb;\n" +"#define LUTSIZE 16.0\n" +"vec3 scale = vec3((LUTSIZE-1.0)/LUTSIZE);\n" +"vec3 bias = vec3(1.0/(2.0*LUTSIZE));\n" +"gl_FragColor = texture3D(s_t1, raw * scale + bias);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "crepuscular_opaque", +//opaque surfaces are drawn to the render target to mask out skies +"#ifdef VERTEX_SHADER\n" +"void main ()\n" +"{\n" +"gl_Position = ftetransform();\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"void main()\n" +"{\n" +"gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "crepuscular_rays", +"!!cvarf crep_decay\n" +"!!cvarf crep_density\n" +"!!cvarf crep_weight\n" + +//this is a post-processing shader, drawn in 2d +//there will be a render target containing sky surfaces drawn with crepuscular_sky, and everything else drawn with crepuscular_opaque (to mask out the sky) +//this shader then just smudges the sky out a bit as though its coming from the sun or whatever through the clouds. +//yoinked from http://fabiensanglard.net/lightScattering/index.php + +"varying vec2 tc;\n" +"#ifdef VERTEX_SHADER\n" +"attribute vec2 v_texcoord;\n" +"void main ()\n" +"{\n" +"tc = v_texcoord;\n" +"gl_Position = v_position;\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"const float crep_decay = 0.94;\n" +"const float crep_density = 0.5;\n" +"const float crep_weight = 0.2;\n" +"uniform vec3 l_lightcolour;\n" +"uniform vec3 l_lightscreen;\n" +"uniform sampler2D s_t0;\n" +"const int NUM_SAMPLES = 100;\n" +"void main()\n" +"{\n" +"vec2 deltaTextCoord = vec2(tc.st - l_lightscreen.xy);\n" +"vec2 textCoo = tc.st;\n" +"deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * crep_density;\n" +"float illuminationDecay = 1.0;\n" +"for(int i=0; i < NUM_SAMPLES ; i++)\n" +"{\n" +"textCoo -= deltaTextCoord;\n" +"vec4 sample = texture2D(s_t0, textCoo);\n" +"sample *= illuminationDecay * crep_weight;\n" +"gl_FragColor += sample;\n" +"illuminationDecay *= crep_decay;\n" +"}\n" +"gl_FragColor *= vec4(l_lightcolour, 1.0);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "crepuscular_sky", +//pretty much a regular sky shader +//though in reality we should render a sun circle in the middle. +//still, its kinda cool to have scrolling clouds masking out parts of the sun. + +"#ifdef VERTEX_SHADER\n" +"varying vec3 pos;\n" +"void main ()\n" +"{\n" +"pos = v_position.xyz;\n" +"gl_Position = ftetransform();\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform float e_time;\n" +"uniform vec3 e_eyepos;\n" +"varying vec3 pos;\n" +"uniform sampler2D s_t0;\n" +"uniform sampler2D s_t1;\n" +"void main ()\n" +"{\n" +"vec2 tccoord;\n" +"vec3 dir = pos - e_eyepos;\n" +"dir.z *= 3.0;\n" +"dir.xy /= 0.5*length(dir);\n" +"tccoord = (dir.xy + e_time*0.03125);\n" +"vec3 solid = vec3(texture2D(s_t0, tccoord));\n" +"tccoord = (dir.xy + e_time*0.0625);\n" +"vec4 clouds = texture2D(s_t1, tccoord);\n" +"gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "default2d", +//this shader is present for support for gles/gl3core contexts +//it is single-texture-with-vertex-colours, and doesn't do anything special. +//beware that a few things use this, including apparently fonts and bloom rescaling. +//its really not meant to do anything special. + +"#ifdef VERTEX_SHADER\n" +"attribute vec2 v_texcoord;\n" +"attribute vec4 v_colour;\n" +"varying vec2 tc;\n" +"varying vec4 vc;\n" +"void main ()\n" +"{\n" +"tc = v_texcoord;\n" +"vc = v_colour;\n" +"gl_Position = ftetransform();\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform sampler2D s_t0;\n" +"in vec2 tc;\n" +"varying vec4 vc;\n" +"void main ()\n" +"{\n" +"gl_FragColor = texture2D(s_t0, tc) * vc;\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "defaultadditivesprite", +"!!permu FOG\n" + +//meant to be used for additive stuff. presumably particles and sprites. though actually its only flashblend effects that use this at the time of writing. +//includes fog, apparently. + +"#include \"sys/fog.h\"\n" +"#ifdef VERTEX_SHADER\n" +"attribute vec2 v_texcoord;\n" +"attribute vec4 v_colour;\n" +"varying vec2 tc;\n" +"varying vec4 vc;\n" +"void main ()\n" +"{\n" +"tc = v_texcoord;\n" +"vc = v_colour;\n" +"gl_Position = ftetransform();\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform sampler2D s_t0;\n" +"varying vec2 tc;\n" +"varying vec4 vc;\n" +"uniform vec4 e_colourident;\n" +"void main ()\n" +"{\n" +"gl_FragColor = fog4additive(texture2D(s_t0, tc) * vc * e_colourident);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "defaultskin", +"!!permu FULLBRIGHT\n" +"!!permu UPPERLOWER\n" +"!!permu FRAMEBLEND\n" +"!!permu SKELETAL\n" +"!!permu FOG\n" + +//standard shader used for models. +//must support skeletal and 2-way vertex blending or Bad Things Will Happen. +//the vertex shader is responsible for calculating lighting values. + +"varying vec2 tc;\n" +"varying vec3 light;\n" +"#ifdef VERTEX_SHADER\n" +"#include \"sys/skeletal.h\"\n" +"attribute vec2 v_texcoord;\n" +"uniform vec3 e_light_dir;\n" +"uniform vec3 e_light_mul;\n" +"uniform vec3 e_light_ambient;\n" +"void main ()\n" +"{\n" +"vec3 n;\n" +"gl_Position = skeletaltransform_n(n);\n" +"light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul);\n" +"tc = v_texcoord;\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"#include \"sys/fog.h\"\n" +"uniform sampler2D s_t0;\n" +"#ifdef LOWER\n" +"uniform sampler2D s_t1;\n" +"uniform vec3 e_lowercolour;\n" +"#endif\n" +"#ifdef UPPER\n" +"uniform sampler2D s_t2;\n" +"uniform vec3 e_uppercolour;\n" +"#endif\n" +"#ifdef FULLBRIGHT\n" +"uniform sampler2D s_t3;\n" +"#endif\n" +"uniform vec4 e_colourident;\n" +"void main ()\n" +"{\n" +"vec4 col, sp;\n" +"col = texture2D(s_t0, tc);\n" +"#ifdef UPPER\n" +"vec4 uc = texture2D(s_t2, tc);\n" +"col.rgb = mix(col.rgb, uc.rgb*e_uppercolour, uc.a);\n" +"#endif\n" +"#ifdef LOWER\n" +"vec4 lc = texture2D(s_t1, tc);\n" +"col.rgb = mix(col.rgb, lc.rgb*e_lowercolour, lc.a);\n" +"#endif\n" +"col.rgb *= light;\n" +"#ifdef FULLBRIGHT\n" +"vec4 fb = texture2D(s_t3, tc);\n" +"col.rgb = mix(col.rgb, fb.rgb, fb.a);\n" +"#endif\n" +"gl_FragColor = fog4(col * e_colourident);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "defaultsky", +//regular sky shader for scrolling q1 skies +//the sky surfaces are thrown through this as-is. + +"#ifdef VERTEX_SHADER\n" +"varying vec3 pos;\n" +"void main ()\n" +"{\n" +"pos = v_position.xyz;\n" +"gl_Position = ftetransform();\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform float e_time;\n" +"uniform vec3 e_eyepos;\n" +"varying vec3 pos;\n" +"uniform sampler2D s_t0;\n" +"uniform sampler2D s_t1;\n" +"void main ()\n" +"{\n" +"vec2 tccoord;\n" +"vec3 dir = pos - e_eyepos;\n" +"dir.z *= 3.0;\n" +"dir.xy /= 0.5*length(dir);\n" +"tccoord = (dir.xy + e_time*0.03125);\n" +"vec3 solid = vec3(texture2D(s_t0, tccoord));\n" +"tccoord = (dir.xy + e_time*0.0625);\n" +"vec4 clouds = texture2D(s_t1, tccoord);\n" +"gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "defaultsprite", +"!!permu FOG\n" +//used by both particles and sprites. +//note the fog blending mode is all that differs from defaultadditivesprite + +"#include \"sys/fog.h\"\n" +"#ifdef VERTEX_SHADER\n" +"attribute vec2 v_texcoord;\n" +"attribute vec4 v_colour;\n" +"varying vec2 tc;\n" +"varying vec4 vc;\n" +"void main ()\n" +"{\n" +"tc = v_texcoord;\n" +"vc = v_colour;\n" +"gl_Position = ftetransform();\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform sampler2D s_t0;\n" +"varying vec2 tc;\n" +"varying vec4 vc;\n" +"uniform vec4 e_colourident;\n" +"void main ()\n" +"{\n" +"gl_FragColor = fog4blend(texture2D(s_t0, tc) * vc * e_colourident);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "defaultwall", +"!!permu OFFSETMAPPING\n" +"!!permu FULLBRIGHT\n" +"!!permu FOG\n" +"!!cvarf r_glsl_offsetmapping_scale\n" + +//this is what normally draws all of your walls, even with rtlights disabled +//note that the '286' preset uses drawflat_walls instead. + +"#include \"sys/fog.h\"\n" +"#if defined(OFFSETMAPPING)\n" +"varying vec3 eyevector;\n" +"#endif\n" +"#ifdef VERTEX_SHADER\n" +"attribute vec2 v_texcoord;\n" +"attribute vec2 v_lmcoord;\n" +"varying vec2 tc, lm;\n" +"#if defined(OFFSETMAPPING)\n" +"uniform vec3 e_eyepos;\n" +"attribute vec3 v_normal;\n" +"attribute vec3 v_svector;\n" +"attribute vec3 v_tvector;\n" +"#endif\n" +"void main ()\n" +"{\n" +"#if defined(OFFSETMAPPING)\n" +"vec3 eyeminusvertex = e_eyepos - v_position.xyz;\n" +"eyevector.x = dot(eyeminusvertex, v_svector.xyz);\n" +"eyevector.y = -dot(eyeminusvertex, v_tvector.xyz);\n" +"eyevector.z = dot(eyeminusvertex, v_normal.xyz);\n" +"#endif\n" +"tc = v_texcoord;\n" +"lm = v_lmcoord;\n" +"gl_Position = ftetransform();\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform sampler2D s_t0;\n" +"uniform sampler2D s_t1;\n" +"#ifdef OFFSETMAPPING\n" +"uniform sampler2D s_t2;\n" +"#endif\n" +"#ifdef FULLBRIGHT\n" +"uniform sampler2D s_t4;\n" +"#endif\n" +"varying vec2 tc, lm;\n" +"uniform vec4 e_lmscale;\n" +"uniform vec4 e_colourident;\n" +"#ifdef OFFSETMAPPING\n" +"#include \"sys/offsetmapping.h\"\n" +"#endif\n" +"void main ()\n" +"{\n" +"#ifdef OFFSETMAPPING\n" +"vec2 tcoffsetmap = offsetmap(s_t2, tc, eyevector);\n" +"#define tc tcoffsetmap\n" +"#endif\n" +"gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * e_lmscale;\n" +"#ifdef FULLBRIGHT\n" +"gl_FragColor.rgb += texture2D(s_t4, tc).rgb;\n" +"#endif\n" +"gl_FragColor = gl_FragColor * e_colourident;\n" +"#ifdef FOG\n" +"gl_FragColor = fog4(gl_FragColor);\n" +"#endif\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "defaultwarp", +"!!cvarf r_wateralpha\n" +"!!permu FOG\n" + +//this is the shader that's responsible for drawing default q1 turbulant water surfaces +//this is expected to be moderately fast. + +"#include \"sys/fog.h\"\n" +"varying vec2 tc;\n" +"#ifdef VERTEX_SHADER\n" +"attribute vec2 v_texcoord;\n" +"void main ()\n" +"{\n" +"tc = v_texcoord.st;\n" +"gl_Position = ftetransform();\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform sampler2D s_t0;\n" +"uniform float e_time;\n" +"uniform float cvar_r_wateralpha;\n" +"void main ()\n" +"{\n" +"vec2 ntc;\n" +"ntc.s = tc.s + sin(tc.t+e_time)*0.125;\n" +"ntc.t = tc.t + sin(tc.s+e_time)*0.125;\n" +"vec3 ts = vec3(texture2D(s_t0, ntc));\n" +"gl_FragColor = fog4(vec4(ts, cvar_r_wateralpha));\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "drawflat_wall", +"!!cvarv r_floorcolor\n" +"!!cvarv r_wallcolor\n" +"!!permu FOG\n" + +//this is for the '286' preset walls, and just draws lightmaps coloured based upon surface normals. + +"#include \"sys/fog.h\"\n" +"varying vec4 col;\n" +"#ifdef VERTEX_SHADER\n" +"attribute vec3 v_normal;\n" +"attribute vec2 v_lmcoord;\n" +"varying vec2 lm;\n" +"uniform vec3 cvar_r_wallcolor;\n" +"uniform vec3 cvar_r_floorcolor;\n" +"uniform vec4 e_lmscale;\n" +"void main ()\n" +"{\n" +"col = vec4(e_lmscale.rgb/255.0 * ((v_normal.z < 0.73)?cvar_r_wallcolor:cvar_r_floorcolor), e_lmscale.a);\n" +"lm = v_lmcoord;\n" +"gl_Position = ftetransform();\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform sampler2D s_t0;\n" +"varying vec2 lm;\n" +"void main ()\n" +"{\n" +"gl_FragColor = fog4(col * texture2D(s_t0, lm));\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "lpp_depthnorm", +"!!permu BUMP\n" +"!!permu SKELETAL\n" + +//light pre-pass rendering (defered lighting) +//this is the initial pass, that draws the surface normals and depth to the initial colour buffer + +"varying vec3 norm, tang, bitang;\n" +"#if defined(BUMP)\n" +"varying vec2 tc;\n" +"#endif\n" +"#ifdef VERTEX_SHADER\n" +"#include \"sys/skeletal.h\"\n" +"attribute vec2 v_texcoord;\n" +"void main()\n" +"{\n" +"#if defined(BUMP)\n" +"gl_Position = skeletaltransform_nst(norm, tang, bitang);\n" +"tc = v_texcoord;\n" +"#else\n" +"gl_Position = skeletaltransform_n(norm);\n" +"#endif\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"#if defined(BUMP)\n" +"uniform sampler2D s_t0;\n" +"#endif\n" +"void main()\n" +"{\n" +"vec3 onorm;\n" +"#if defined(BUMP)\n" +"vec3 bm = 2.0*texture2D(s_t0, tc).xyz - 1.0;\n" +"onorm = normalize(bm.x * tang + bm.y * bitang + bm.z * norm);\n" +"#else\n" +"onorm = norm;\n" +"#endif\n" +"gl_FragColor = vec4(onorm.xyz, gl_FragCoord.z / gl_FragCoord.w);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "lpp_light", +//this shader is a light shader. ideally drawn with a quad covering the entire region +//the output is contribution from this light (which will be additively blended) +//you can blame Electro for much of the maths in here. +//fixme: no fog + +"varying vec4 tf;\n" +"#ifdef VERTEX_SHADER\n" +"void main()\n" +"{\n" +"tf = ftetransform();\n" +"gl_Position = tf;\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform sampler2D s_t0;\n" +"uniform vec3 l_lightposition;\n" +"uniform mat4 m_invviewprojection;\n" +"uniform vec3 l_lightcolour;\n" +"uniform float l_lightradius;\n" +"vec3 calcLightWorldPos(vec2 screenPos, float depth)\n" +"{\n" +"vec4 pos;\n" +"pos.x = screenPos.x;\n" +"pos.y = screenPos.y;\n" +"pos.z = depth;\n" +"pos.w = 1.0;\n" +"pos = m_invviewprojection * pos;\n" +"return pos.xyz / pos.w;\n" +"}\n" +"void main ()\n" +"{\n" +"vec3 lightColour = l_lightcolour.rgb;\n" +"float lightIntensity = 1.0;\n" +"float lightAttenuation = l_lightradius; // fixme: just use the light radius for now, use better near/far att math separately once working\n" +"float radiusFar = l_lightradius;\n" +"float radiusNear = l_lightradius*0.5;\n" + +"vec2 fc;\n" +"fc = tf.xy / tf.w;\n" +"vec4 data = texture2D(s_t0, (1.0 + fc) / 2.0);\n" +"float depth = data.a;\n" +"vec3 norm = data.xyz;\n" + +/* calc where the wall that generated this sample came from */ +"vec3 worldPos = calcLightWorldPos(fc, depth);\n" + +/*calc diffuse lighting term*/ +"vec3 lightDir = l_lightposition - worldPos;\n" +"float zdiff = 1.0 - clamp(length(lightDir) / lightAttenuation, 0.0, 1.0);\n" +"float atten = (radiusFar * zdiff) / (radiusFar - radiusNear);\n" +"atten = pow(atten, 2.0);\n" +"lightDir = normalize(lightDir);\n" +"float nDotL = dot(norm, lightDir) * atten;\n" +"float lightDiffuse = max(0.0, nDotL);\n" + +"gl_FragColor = vec4(lightDiffuse * (lightColour * lightIntensity), 1.0);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "lpp_wall", +//the final defered lighting pass. +//the lighting values were written to some render target, which is fed into this shader, and now we draw all the wall textures with it. + +"varying vec2 tc, lm;\n" +"varying vec4 tf;\n" +"#ifdef VERTEX_SHADER\n" +"attribute vec2 v_texcoord;\n" +"attribute vec2 v_lmcoord;\n" +"void main ()\n" +"{\n" +"tc = v_texcoord;\n" +"lm = v_lmcoord;\n" +"gl_Position = tf = ftetransform();\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform sampler2D s_t0;\n" +"uniform sampler2D s_t1;\n" +"uniform sampler2D s_t2;\n" +"uniform vec4 e_lmscale;\n" +"void main ()\n" +"{\n" +"vec2 nst;\n" +"nst = tf.xy / tf.w;\n" +"nst = (1.0 + nst) / 2.0;\n" +"vec4 l = texture2D(s_t0, nst)*5.0;\n" +"vec4 c = texture2D(s_t1, tc);\n" +"vec3 lmsamp = texture2D(s_t2, lm).rgb*lmscale;\n" +"vec3 diff = l.rgb;\n" +"vec3 chrom = diff / (0.001 + dot(diff, vec3(0.3, 0.59, 0.11)));\n" +"vec3 spec = chrom * l.a;\n" +"gl_FragColor = vec4((diff + lmsamp) * c.xyz, 1.0);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "postproc_fisheye", +"!!cvarf ffov\n" + +//fisheye view rendering, for silly fovs that are still playable. + +"#ifdef VERTEX_SHADER\n" +"attribute vec2 v_texcoord;\n" +"varying vec2 texcoord;\n" +"void main()\n" +"{\n" +"texcoord = v_texcoord.xy;\n" +"gl_Position = ftetransform();\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform samplerCube s_t0;\n" +"varying vec2 texcoord;\n" +"uniform float cvar_ffov;\n" +"void main()\n" +"{\n" +"vec3 tc; \n" +"vec2 d; \n" +"vec2 ang; \n" +"d = texcoord; \n" +"ang.x = sqrt(d.x*d.x+d.y*d.y)*radians(cvar_ffov); \n" +"ang.y = -atan(d.y, d.x); \n" +"tc.x = sin(ang.x) * cos(ang.y); \n" +"tc.y = sin(ang.x) * sin(ang.y); \n" +"tc.z = cos(ang.x); \n" +"gl_FragColor = textureCube(s_t0, tc);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "postproc_panorama", +"!!cvarf ffov\n" + +//panoramic view rendering, for promo map shots or whatever. + +"#ifdef VERTEX_SHADER\n" +"attribute vec2 v_texcoord;\n" +"varying vec2 texcoord;\n" +"void main()\n" +"{\n" +"texcoord = v_texcoord.xy;\n" +"gl_Position = ftetransform();\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform samplerCube s_t0;\n" +"varying vec2 texcoord;\n" +"uniform float cvar_ffov;\n" +"void main()\n" +"{\n" +"vec3 tc; \n" +"float ang; \n" +"ang = texcoord.x*-radians(cvar_ffov); \n" +"tc.x = sin(ang); \n" +"tc.y = -texcoord.y; \n" +"tc.z = cos(ang); \n" +"gl_FragColor = textureCube(s_t0, tc);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "rtlight", +"!!permu BUMP\n" +"!!permu SPECULAR\n" +"!!permu OFFSETMAPPING\n" +"!!permu SKELETAL\n" +"!!permu FOG\n" +"!!cvarf r_glsl_offsetmapping_scale\n" + +//this is the main shader responsible for realtime dlights. + +//texture units: +//s0=diffuse, s1=normal, s2=specular, s3=shadowmap +//custom modifiers: +//PCF(shadowmap) +//CUBE(projected cubemap) + + +"varying vec2 tcbase;\n" +"varying vec3 lightvector;\n" +"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n" +"varying vec3 eyevector;\n" +"#endif\n" +"#if defined(PCF) || defined(CUBE)\n" +"varying vec4 vshadowcoord;\n" +"uniform mat4 l_projmatrix;\n" +"#endif\n" +"#ifdef VERTEX_SHADER\n" +"#include \"sys/skeletal.h\"\n" +"uniform vec3 l_lightposition;\n" +"attribute vec2 v_texcoord;\n" +"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n" +"uniform vec3 e_eyepos;\n" +"#endif\n" +"void main ()\n" +"{\n" +"vec3 n, s, t, w;\n" +"gl_Position = skeletaltransform_wnst(w,n,s,t);\n" +"tcbase = v_texcoord; //pass the texture coords straight through\n" +"vec3 lightminusvertex = l_lightposition - w.xyz;\n" +"lightvector.x = dot(lightminusvertex, s.xyz);\n" +"lightvector.y = dot(lightminusvertex, t.xyz);\n" +"lightvector.z = dot(lightminusvertex, n.xyz);\n" +"#if defined(SPECULAR)||defined(OFFSETMAPPING)\n" +"vec3 eyeminusvertex = e_eyepos - w.xyz;\n" +"eyevector.x = dot(eyeminusvertex, s.xyz);\n" +"eyevector.y = -dot(eyeminusvertex, t.xyz);\n" +"eyevector.z = dot(eyeminusvertex, n.xyz);\n" +"#endif\n" +"#if defined(PCF) || defined(SPOT) || defined(PROJECTION) || defined(CUBE)\n" +"vshadowcoord = l_projmatrix*vec4(w.xyz, 1.0);\n" +"#endif\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"#include \"sys/fog.h\"\n" +"uniform sampler2D s_t0;\n" +"#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING)\n" +"uniform sampler2D s_t1;\n" +"#endif\n" +"#ifdef SPECULAR\n" +"uniform sampler2D s_t2;\n" +"#endif\n" +"#ifdef CUBE\n" +"uniform samplerCube s_t3;\n" +"#endif\n" +"#ifdef PCF\n" +"#ifdef CUBE\n" +"uniform samplerCubeShadow s_t7;\n" +"#else\n" +"uniform sampler2DShadow s_t7;\n" +"#endif\n" +"#endif\n" +"uniform float l_lightradius;\n" +"uniform vec3 l_lightcolour;\n" +"uniform vec3 l_lightcolourscale;\n" +"#ifdef OFFSETMAPPING\n" +"#include \"sys/offsetmapping.h\"\n" +"#endif\n" +"void main ()\n" +"{\n" +"#ifdef OFFSETMAPPING\n" +"vec2 tcoffsetmap = offsetmap(s_t1, tcbase, eyevector);\n" +"#define tcbase tcoffsetmap\n" +"#endif\n" +"vec3 bases = vec3(texture2D(s_t0, tcbase));\n" +"#if defined(BUMP) || defined(SPECULAR)\n" +"vec3 bumps = vec3(texture2D(s_t1, tcbase)) - 0.5;\n" +"#endif\n" +"#ifdef SPECULAR\n" +"vec4 specs = texture2D(s_t2, tcbase);\n" +"#endif\n" +"vec3 nl = normalize(lightvector);\n" +"float colorscale = max(1.0 - dot(lightvector, lightvector)/(l_lightradius*l_lightradius), 0.0);\n" +"vec3 diff;\n" +"#ifdef BUMP\n" +"diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(2.0*bumps, nl), 0.0));\n" +"#else\n" +"diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0));\n" +"#endif\n" +"#ifdef SPECULAR\n" +"vec3 halfdir = normalize(lightvector - normalize(eyevector));\n" +"float spec = pow(max(dot(halfdir, bumps), 0.0), 1.0 + 32.0 * specs.a);\n" +"diff += spec * specs.rgb * l_lightcolourscale.z;\n" +"#endif\n" +"#ifdef CUBE\n" +"diff *= textureCube(s_t3, vshadowcoord.xyz).rgb;\n" +"#endif\n" +"#ifdef PCF\n" +"#if defined(SPOT)\n" +"const float texx = 512.0;\n" +"const float texy = 512.0;\n" +"vec4 shadowcoord = vshadowcoord;\n" +"#else\n" +"const float texx = 512.0;\n" +"const float texy = 512.0;\n" +"vec4 shadowcoord;\n" +"shadowcoord.zw = vshadowcoord.zw;\n" +"shadowcoord.xy = vshadowcoord.xy;\n" +"#endif\n" +"#ifdef CUBE\n" +"const float xPixelOffset = 1.0/texx; const float yPixelOffset = 1.0/texy; float s = 0.0;\n" +"s += shadowCubeProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadowCubeProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadowCubeProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadowCubeProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadowCubeProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadowCubeProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadowCubeProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadowCubeProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadowCubeProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"colorscale *= s/9.0;\n" +"#else\n" +"const float xPixelOffset = 1.0/texx; const float yPixelOffset = 1.0/texy; float s = 0.0;\n" +"s += shadow2DProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadow2DProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadow2DProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadow2DProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadow2DProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadow2DProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadow2DProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadow2DProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"s += shadow2DProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n" +"colorscale *= s/9.0;\n" +"#endif\n" +"#endif\n" +"#if defined(SPOT)\n" +"if (shadowcoord.w < 0.0) discard;\n" +"vec2 spot = ((shadowcoord.st)/shadowcoord.w - 0.5)*2.0;colorscale*=1.0-(dot(spot,spot));\n" +"#endif\n" +"#if defined(PROJECTION)\n" +"l_lightcolour *= texture2d(s_t3, shadowcoord);\n" +"#endif\n" +"gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);\n" +"}\n" +"#endif\n" +}, +#endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "underwaterwarp", +"!!cvarf r_waterwarp\n" + +//this is a post processing shader that is drawn fullscreen whenever the view is underwater. +//its generally expected to warp the view a little. + +"#ifdef VERTEX_SHADER\n" +"attribute vec2 v_texcoord;\n" +"varying vec2 v_stc;\n" +"varying vec2 v_warp;\n" +"varying vec2 v_edge;\n" +"uniform float e_time;\n" +"void main ()\n" +"{\n" +"gl_Position = ftetransform();\n" +"v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0;\n" +"v_warp.s = e_time * 0.25 + v_texcoord.s;\n" +"v_warp.t = e_time * 0.25 + v_texcoord.t;\n" +"v_edge = v_texcoord.xy;\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"varying vec2 v_stc;\n" +"varying vec2 v_warp;\n" +"varying vec2 v_edge;\n" +"uniform sampler2D s_t0;/*$currentrender*/\n" +"uniform sampler2D s_t1;/*warp image*/\n" +"uniform sampler2D s_t2;/*edge image*/\n" +"uniform vec3 e_rendertexturescale;\n" +"uniform float cvar_r_waterwarp;\n" +"void main ()\n" +"{\n" +"float amptemp;\n" +"vec3 edge;\n" +"edge = texture2D( s_t2, v_edge ).rgb;\n" +"amptemp = (0.010 / 0.625) * cvar_r_waterwarp * edge.x;\n" +"vec3 offset;\n" +"offset = texture2D( s_t1, v_warp ).rgb;\n" +"offset.x = (offset.x - 0.5) * 2.0;\n" +"offset.y = (offset.y - 0.5) * 2.0;\n" +"vec2 temp;\n" +"temp.x = v_stc.x + offset.x * amptemp;\n" +"temp.y = v_stc.y + offset.y * amptemp;\n" +"gl_FragColor = texture2D( s_t0, temp*e_rendertexturescale.st );\n" +"}\n" +"#endif\n" +}, +#endif diff --git a/engine/gl/shader.h b/engine/gl/shader.h index d38823e66..013055790 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -226,6 +226,9 @@ typedef struct shaderpass_s { T_GEN_SOURCECOLOUR, //used for render-to-texture targets T_GEN_SOURCEDEPTH, //used for render-to-texture targets + T_GEN_REFLECTION, //reflection image (mirror-as-fbo) + T_GEN_REFRACTION, //refraction image (portal-as-fbo) + T_GEN_SOURCECUBE, //used for render-to-texture targets T_GEN_VIDEOMAP, //use the media playback as an image source, updating each frame for which it is visible @@ -414,7 +417,9 @@ struct shader_s SHADER_NODLIGHT = 1 << 15, //from surfaceflags SHADER_HASLIGHTMAP = 1 << 16, SHADER_HASTOPBOTTOM = 1 << 17, - SHADER_STATICDATA = 1 << 18 //set if true: no deforms, no tcgen, rgbgen=identitylighting, alphagen=identity, tmu0=st + tmu1=lm(if available) for every pass, no norms + SHADER_STATICDATA = 1 << 18, //set if true: no deforms, no tcgen, rgbgen=identitylighting, alphagen=identity, tmu0=st + tmu1=lm(if available) for every pass, no norms + SHADER_HASREFLECT = 1 << 19, + SHADER_HASREFRACT = 1 << 20 } flags; program_t *prog; diff --git a/engine/qclib/hash.c b/engine/qclib/hash.c index 44ac211d3..1ad5229d5 100644 --- a/engine/qclib/hash.c +++ b/engine/qclib/hash.c @@ -69,6 +69,22 @@ void *Hash_GetInsensative(hashtable_t *table, const char *name) } return NULL; } +void *Hash_GetInsensativeBucket(hashtable_t *table, const char *name) +{ + unsigned int bucknum = Hash_KeyInsensative(name, table->numbuckets); + bucket_t *buck; + + buck = table->bucket[bucknum]; + + while(buck) + { + if (!stricmp(name, buck->key.string)) + return buck; + + buck = buck->next; + } + return NULL; +} void *Hash_GetKey(hashtable_t *table, unsigned int key) { unsigned int bucknum = key%table->numbuckets; @@ -237,32 +253,35 @@ void Hash_Remove(hashtable_t *table, const char *name) void Hash_RemoveData(hashtable_t *table, const char *name, void *data) { unsigned int bucknum = Hash_Key(name, table->numbuckets); - bucket_t *buck; + bucket_t **link, *buck; - buck = table->bucket[bucknum]; - - if (buck->data == data) - if (!STRCMP(name, buck->key.string)) + for (link = &table->bucket[bucknum]; *link; link = &(*link)->next) + { + buck = *link; + if (buck->data == data && !stricmp(name, buck->key.string)) { - table->bucket[bucknum] = buck->next; + *link = buck->next; return; } - - - while(buck->next) - { - if (buck->next->data == data) - if (!STRCMP(name, buck->next->key.string)) - { - buck->next = buck->next->next; - return; - } - - buck = buck->next; } return; } +void Hash_RemoveBucket(hashtable_t *table, const char *name, bucket_t *data) +{ + unsigned int bucknum = Hash_Key(name, table->numbuckets); + bucket_t **link, *buck; + for (link = &table->bucket[bucknum]; *link; link = &(*link)->next) + { + buck = *link; + if (buck == data && !stricmp(name, buck->key.string)) + { + *link = buck->next; + return; + } + } + return; +} void Hash_RemoveKey(hashtable_t *table, unsigned int key) { diff --git a/engine/qclib/hash.h b/engine/qclib/hash.h index e07c17d22..4344abf02 100644 --- a/engine/qclib/hash.h +++ b/engine/qclib/hash.h @@ -25,6 +25,7 @@ void Hash_InitTable(hashtable_t *table, unsigned int numbucks, void *mem); //mem unsigned int Hash_Key(const char *name, unsigned int modulus); void *Hash_Get(hashtable_t *table, const char *name); void *Hash_GetInsensative(hashtable_t *table, const char *name); +void *Hash_GetInsensativeBucket(hashtable_t *table, const char *name); void *Hash_GetKey(hashtable_t *table, unsigned int key); void *Hash_GetNext(hashtable_t *table, const char *name, void *old); void *Hash_GetNextInsensative(hashtable_t *table, const char *name, void *old); @@ -33,6 +34,7 @@ void *Hash_Add(hashtable_t *table, const char *name, void *data, bucket_t *buck) void *Hash_AddInsensative(hashtable_t *table, const char *name, void *data, bucket_t *buck); void Hash_Remove(hashtable_t *table, const char *name); void Hash_RemoveData(hashtable_t *table, const char *name, void *data); +void Hash_RemoveBucket(hashtable_t *table, const char *name, bucket_t *data); void Hash_RemoveKey(hashtable_t *table, unsigned int key); void *Hash_AddKey(hashtable_t *table, unsigned int key, void *data, bucket_t *buck); diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index 226025743..366986159 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -160,6 +160,38 @@ static void PF_fmem_unlink(progfuncs_t *pr, qcmemfreeblock_t *p) np->prev = p->prev; } } +static void PR_memvalidate (progfuncs_t *progfuncs) +{ + qcmemfreeblock_t *p; + qcmemusedblock_t *ub = NULL; + unsigned int b,l; + + b = prinst->mfreelist; + l = 0; + while (b) + { + if (b < 0 || b >= prinst->addressableused) + { + printf("PF_memalloc: memory corruption\n"); + PR_StackTrace(progfuncs); + return; + } + p = (qcmemfreeblock_t*)(progfuncs->stringtable + b); + + if (p->prev != l || + p->next && p->next < b + p->size || + p->next >= prinst->addressableused || + b + p->size >= prinst->addressableused || + p->prev >= b) + { + printf("PF_memalloc: memory corruption\n"); + PR_StackTrace(progfuncs); + return; + } + l = b; + b = p->next; + } +} static void *PR_memalloc (progfuncs_t *progfuncs, unsigned int size) { qcmemfreeblock_t *p, *np; @@ -220,6 +252,7 @@ static void *PR_memalloc (progfuncs_t *progfuncs, unsigned int size) } break; } + b = p->next; } /*assign more space*/ @@ -236,19 +269,23 @@ static void *PR_memalloc (progfuncs_t *progfuncs, unsigned int size) memset(ub, 0, size); ub->marker = MARKER; ub->size = size; + +// PR_memvalidate(progfuncs); + return ub+1; } static void PR_memfree (progfuncs_t *progfuncs, void *memptr) { qcmemusedblock_t *ub; - qcmemfreeblock_t *p, *np; - unsigned int l, ln; + qcmemfreeblock_t *p, *np, *pp; + unsigned int pa, na; //prev addr, next addr unsigned int size; unsigned int ptr = memptr?((char*)memptr - progfuncs->stringtable):0; /*freeing NULL is ignored*/ if (!ptr) return; +// PR_memvalidate(progfuncs); if (ptr < sizeof(qcmemusedblock_t) || ptr >= prinst->addressableused) { printf("PF_memfree: pointer invalid - out of range (%u >= %u)\n", ptr, prinst->addressableused); @@ -268,18 +305,18 @@ static void PR_memfree (progfuncs_t *progfuncs, void *memptr) ub->marker = 0; size = ub->size; - for (ln = prinst->mfreelist, l = 0; ;) + for (na = prinst->mfreelist, pa = 0; ;) { - if (ln < 0 || ln >= prinst->addressableused) + if (na < 0 || na >= prinst->addressableused) { printf("PF_memfree: memory corruption\n"); PR_StackTrace(progfuncs); return; } - if (!ln || ln >= ptr) + if (!na || na >= ptr) { - np = (qcmemfreeblock_t*)(progfuncs->stringtable + l); - if (l && l+np->size>ptr) + np = (qcmemfreeblock_t*)(progfuncs->stringtable + pa); + if (pa && pa+np->size>ptr) { printf("PF_memfree: double free\n"); PR_StackTrace(progfuncs); @@ -288,15 +325,17 @@ static void PR_memfree (progfuncs_t *progfuncs, void *memptr) /*generate the free block, now we know its proper values*/ p = (qcmemfreeblock_t*)(progfuncs->stringtable + ptr); - p->prev = l; - p->next = ln; + np = na?(qcmemfreeblock_t*)(progfuncs->stringtable + na):NULL; + pp = pa?(qcmemfreeblock_t*)(progfuncs->stringtable + pa):NULL; + + p->prev = pa; + p->next = na; p->size = size; /*update the next's previous*/ - if (p->next) + if (na) { - np = (qcmemfreeblock_t*)(progfuncs->stringtable + p->next); - np->prev = p->prev; + np->prev = ptr; /*extend this block and kill the next if they are adjacent*/ if (p->next == ptr + size) @@ -307,27 +346,29 @@ static void PR_memfree (progfuncs_t *progfuncs, void *memptr) } /*update the link to get here*/ - if (!l) + if (!pa) prinst->mfreelist = ptr; else { - np = (qcmemfreeblock_t*)(progfuncs->stringtable + l); - np->next = ptr; + pp->next = ptr; /*we're adjacent to the previous block, so merge them by killing the newly freed region*/ - if (l + np->size == ptr) + if (na && pa + np->size == ptr) { - np->size += size; - PF_fmem_unlink(progfuncs, p); + p->size += np->size; + PF_fmem_unlink(progfuncs, np); } + } break; } - l = ln; - p = (qcmemfreeblock_t*)(progfuncs->stringtable + l); - ln = p->next; + pa = na; + p = (qcmemfreeblock_t*)(progfuncs->stringtable + pa); + na = p->next; } + +// PR_memvalidate(progfuncs); } void PRAddressableFlush(progfuncs_t *progfuncs, int totalammount) diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index badefcac4..86d50d7fb 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -6719,7 +6719,7 @@ void QCC_PR_ParseAsm(void) QCC_PR_ParseError(ERR_BADOPCODE, "Bad op code name %s", pr_token); } -pbool QCC_FuncJumpsTo(int first, int last, int statement) +static pbool QCC_FuncJumpsTo(int first, int last, int statement) { int st; for (st = first; st < last; st++) @@ -6770,7 +6770,7 @@ pbool QCC_FuncJumpsTo(int first, int last, int statement) return false; } -pbool QCC_FuncJumpsToRange(int first, int last, int firstr, int lastr) +static pbool QCC_FuncJumpsToRange(int first, int last, int firstr, int lastr) { int st; for (st = first; st < last; st++) diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index 3c9e81e73..baf46f4a9 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -791,7 +791,13 @@ void NPP_NQFlush(void) else multicastpos = 0; if (bufferlen) + { + if (writedest->cursize + bufferlen > writedest->maxsize) + { + SV_FlushBroadcasts(); + } SZ_Write(writedest, buffer, bufferlen); + } if (multicastpos) { diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 2c05ac6cb..0a9f31000 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -1138,8 +1138,6 @@ void PR_Init(void) { int i; - PF_Common_RegisterCvars(); - Cmd_AddCommand ("breakpoint", PR_BreakPoint_f); Cmd_AddCommand ("decompile", PR_Decompile_f); Cmd_AddCommand ("compile", PR_Compile_f); @@ -4047,13 +4045,14 @@ PF_pointcontents */ static void QCBUILTIN PF_pointcontents (progfuncs_t *prinst, struct globalvars_s *pr_globals) { + world_t *w = prinst->parms->user; + float *v; int cont; v = G_VECTOR(OFS_PARM0); -// cont = SV_Move(v, vec3_origin, vec3_origin, v, MOVE_NOMONSTERS, NULL).contents; - cont = World_PointContents (&sv.world, v); + cont = World_PointContents(w, v); if (cont & FTECONTENTS_SOLID) G_FLOAT(OFS_RETURN) = Q1CONTENTS_SOLID; else if (cont & FTECONTENTS_SKY) @@ -8626,8 +8625,8 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"eprint", PF_eprint, 31, 31, 31, 0, "void(entity e)"},// debug print an entire entity {"walkmove", PF_walkmove, 32, 32, 32, 0, "float(float yaw, float dist)"}, {"tracearea", PF_traceboxh2, 0, 0, 33, 0, "void(vector v1, vector v2, vector mins, vector maxs, float nomonsters, entity ent)"}, - // {"qtest_flymove", NULL, 33}, // float(vector dir) flymove = #33; +//qbism super8's 'private'sound #33 {"droptofloor", PF_droptofloor, 34, 34, 34, 0, "float()"}, {"lightstyle", PF_lightstyle, 35, 35, 35, 0, "void(float lightstyle, string stylestring)"}, {"rint", PF_rint, 36, 36, 36, 0, "float(float)"}, @@ -9799,6 +9798,7 @@ void PR_DumpPlatform_f(void) #undef comfieldfunction {"physics_mode", "var float", QW|NQ|CS, 2}, + {"gamespeed", "float", CS}, {"TRUE", "const float", QW|NQ|CS, 1}, {"FALSE", "const float", QW|NQ|CS, 0}, @@ -10204,7 +10204,6 @@ void PR_DumpPlatform_f(void) VFS_CLOSE(f); - FS_FlushFSHash(); Con_Printf("Written \"%s\"\n", dbgfname); #endif } diff --git a/engine/server/savegame.c b/engine/server/savegame.c index f4849a270..60a5e3eb6 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -502,7 +502,8 @@ void LoadModelsAndSounds(vfsfile_t *f) *sv.strings.sound_precache[i] = 0; } -qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolean ignoreplayers) +/*ignoreplayers - says to not tell gamecode (a loadgame rather than a level change)*/ +qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolean isloadgame) { eval_t *eval, *e2; @@ -529,18 +530,25 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea levelcache_t *cache; - cache = svs.levcache; - while(cache) + if (isloadgame) { - if (!strcmp(cache->mapname, level)) - break; - - cache = cache->next; + gametype = svs.gametype; } - if (!cache) - return false; //not visited yet. Ignore the existing caches as fakes. + else + { + cache = svs.levcache; + while(cache) + { + if (!strcmp(cache->mapname, level)) + break; - gametype = cache->gametype; + cache = cache->next; + } + if (!cache) + return false; //not visited yet. Ignore the existing caches as fakes. + + gametype = cache->gametype; + } if (savename) Q_snprintfz (name, sizeof(name), "saves/%s/%s", savename, level); @@ -696,16 +704,22 @@ qboolean SV_LoadLevelCache(char *savename, char *level, char *startspot, qboolea for (i=0 ; ixv->playerclass; + if (ent) + svs.clients[i].playerclass = ent->xv->playerclass; + else + svs.clients[i].playerclass = 0; } - if (!ignoreplayers) + if (!isloadgame) { eval = PR_FindGlobal(svprogfuncs, "startspot", 0, NULL); if (eval) eval->_int = (int)PR_NewString(svprogfuncs, startspot, 0); @@ -836,7 +850,7 @@ void SV_SaveLevelCache(char *savedir, qboolean dontharmgame) if (!FS_NativePath(name, FS_GAMEONLY, syspath, sizeof(syspath))) return; ge->WriteLevel(syspath); - FS_FlushFSHash(); + FS_FlushFSHashReally(); return; } #endif @@ -926,8 +940,6 @@ void SV_SaveLevelCache(char *savedir, qboolean dontharmgame) svprogfuncs->parms->memfree(s); VFS_CLOSE (f); - - FS_FlushFSHash(); } #ifdef NEWSAVEFORMAT @@ -1049,8 +1061,6 @@ void SV_Savegame (char *savename) VFS_PRINTF (f, "%s\n", sv.name); VFS_CLOSE(f); - - FS_FlushFSHash(); } void SV_Savegame_f (void) @@ -1245,6 +1255,7 @@ void SV_Loadgame_f (void) VFS_CLOSE(f); + svs.gametype = gametype; SV_LoadLevelCache(savename, str, "", true); sv.allocated_client_slots = slots; sv.spawned_client_slots += loadzombies; diff --git a/engine/server/server.h b/engine/server/server.h index 5cb88e43e..352131593 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -1053,6 +1053,7 @@ void SV_Begin_Core(client_t *split); void VoteFlushAll(void); void SV_SetUpClientEdict (client_t *cl, edict_t *ent); void SV_UpdateToReliableMessages (void); +void SV_FlushBroadcasts (void); void SV_DarkPlacesDownloadChunk(client_t *cl, sizebuf_t *msg); void SV_New_f (void); diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 31c867819..fc7862b22 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -510,6 +510,10 @@ void SV_Map_f (void) } #ifndef SERVERONLY SCR_ImageName(level); + SCR_SetLoadingStage(LS_SERVER); + SCR_SetLoadingFile("finalize server"); +#else + #define SCR_SetLoadingFile(s) #endif COM_FlushFSCache(); @@ -630,12 +634,14 @@ void SV_Map_f (void) } SV_SendMessagesToAll (); + SCR_SetLoadingFile("spawnserver"); if (newunit || !startspot || cinematic || !SV_LoadLevelCache(NULL, level, startspot, false)) { if (waschangelevel && !startspot) startspot = ""; SV_SpawnServer (level, startspot, false, cinematic); } + SCR_SetLoadingFile("server spawned"); //SV_BroadcastCommand ("cmd new\n"); for (i=0, host_client = svs.clients ; istate != cs_spawned) continue; - // needs to reconnect - host_client->state = cs_connected; - if (dontsave) //level restart requires that stats can be reset continue; @@ -756,6 +753,9 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us current_loading_size+=10; //SCR_BeginLoadingPlaque(); SCR_ImageName(server); + SCR_SetLoadingFile("map"); +#else + #define SCR_SetLoadingFile(s) #endif Cvar_ApplyLatches(CVAR_LATCH); @@ -819,12 +819,14 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us current_loading_size+=10; // SCR_BeginLoadingPlaque(); SCR_ImageName(server); + SCR_SetLoadingFile("phs"); #endif SV_CalcPHS (); #ifndef SERVERONLY current_loading_size+=10; //SCR_BeginLoadingPlaque(); SCR_ImageName(server); + SCR_SetLoadingFile("gamecode"); #endif if (sv.world.worldmodel->fromgame == fg_doom) @@ -1020,6 +1022,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us current_loading_size+=10; //SCR_BeginLoadingPlaque(); SCR_ImageName(server); + SCR_SetLoadingFile("clients"); #endif for (i=0 ; imemsize/ (1024*1024.0)); diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index 1b7e06e3e..943652ff8 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -1435,9 +1435,10 @@ mvddest_t *SV_InitRecordFile (char *name) } } else + { FS_Remove(path, FS_GAMEONLY); - - FS_FlushFSHash(); + FS_FlushFSHashRemoved(); + } return dst; } diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index a06ed685e..e98ed80f3 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -1875,6 +1875,74 @@ client_t *SV_SplitClientDest(client_t *client, qbyte first, int size) return client; } } + +void SV_FlushBroadcasts (void) +{ + client_t *client; + int j; + // append the broadcast messages to each client messages + for (j=0, client = svs.clients ; jstate < cs_connected) + continue; // reliables go to all connected or spawned + if (client->controller) + continue; //splitscreen + + if (client->protocol == SCP_BAD) + continue; //botclient + +#ifdef Q2SERVER + if (ISQ2CLIENT(client)) + { + ClientReliableCheckBlock(client, sv.q2reliable_datagram.cursize); + ClientReliableWrite_SZ(client, sv.q2reliable_datagram.data, sv.q2reliable_datagram.cursize); + + if (client->state != cs_spawned) + continue; // datagrams only go to spawned + SZ_Write (&client->datagram + , sv.q2datagram.data + , sv.q2datagram.cursize); + } + else +#endif +#ifdef NQPROT + if (!ISQWCLIENT(client)) + { + if (client->pextknown) + { + ClientReliableCheckBlock(client, sv.nqreliable_datagram.cursize); + ClientReliableWrite_SZ(client, sv.nqreliable_datagram.data, sv.nqreliable_datagram.cursize); + } + if (client->state != cs_spawned) + continue; // datagrams only go to spawned + SZ_Write (&client->datagram + , sv.nqdatagram.data + , sv.nqdatagram.cursize); + } + else +#endif + { + ClientReliableCheckBlock(client, sv.reliable_datagram.cursize); + ClientReliableWrite_SZ(client, sv.reliable_datagram.data, sv.reliable_datagram.cursize); + + if (client->state != cs_spawned) + continue; // datagrams only go to spawned + SZ_Write (&client->datagram + , sv.datagram.data + , sv.datagram.cursize); + } + } + + SZ_Clear (&sv.reliable_datagram); + SZ_Clear (&sv.datagram); +#ifdef NQPROT + SZ_Clear (&sv.nqreliable_datagram); + SZ_Clear (&sv.nqdatagram); +#endif + SZ_Clear (&sv.q2reliable_datagram); + SZ_Clear (&sv.q2datagram); +} + /* ======================= SV_UpdateToReliableMessages @@ -2090,67 +2158,7 @@ void SV_UpdateToReliableMessages (void) SZ_Clear (&sv.q2datagram); #endif - // append the broadcast messages to each client messages - for (j=0, client = svs.clients ; jstate < cs_connected) - continue; // reliables go to all connected or spawned - if (client->controller) - continue; //splitscreen - - if (client->protocol == SCP_BAD) - continue; //botclient - -#ifdef Q2SERVER - if (ISQ2CLIENT(client)) - { - ClientReliableCheckBlock(client, sv.q2reliable_datagram.cursize); - ClientReliableWrite_SZ(client, sv.q2reliable_datagram.data, sv.q2reliable_datagram.cursize); - - if (client->state != cs_spawned) - continue; // datagrams only go to spawned - SZ_Write (&client->datagram - , sv.q2datagram.data - , sv.q2datagram.cursize); - } - else -#endif -#ifdef NQPROT - if (!ISQWCLIENT(client)) - { - if (client->pextknown) - { - ClientReliableCheckBlock(client, sv.nqreliable_datagram.cursize); - ClientReliableWrite_SZ(client, sv.nqreliable_datagram.data, sv.nqreliable_datagram.cursize); - } - if (client->state != cs_spawned) - continue; // datagrams only go to spawned - SZ_Write (&client->datagram - , sv.nqdatagram.data - , sv.nqdatagram.cursize); - } - else -#endif - { - ClientReliableCheckBlock(client, sv.reliable_datagram.cursize); - ClientReliableWrite_SZ(client, sv.reliable_datagram.data, sv.reliable_datagram.cursize); - - if (client->state != cs_spawned) - continue; // datagrams only go to spawned - SZ_Write (&client->datagram - , sv.datagram.data - , sv.datagram.cursize); - } - } - - SZ_Clear (&sv.reliable_datagram); - SZ_Clear (&sv.datagram); -#ifdef NQPROT - SZ_Clear (&sv.nqreliable_datagram); - SZ_Clear (&sv.nqdatagram); -#endif - SZ_Clear (&sv.q2reliable_datagram); - SZ_Clear (&sv.q2datagram); + SV_FlushBroadcasts(); } #ifdef _MSC_VER diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 78872eb58..7a1af9fe6 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -3946,6 +3946,8 @@ void Cmd_Give_f (void) case 'c': sv_player->v->ammo_cells = v; break; + default: + Con_Printf("give: unknown item\n"); } } else diff --git a/engine/shaders/generatebuiltinsl.c b/engine/shaders/generatebuiltinsl.c index 7a33130db..2ad5d19f7 100644 --- a/engine/shaders/generatebuiltinsl.c +++ b/engine/shaders/generatebuiltinsl.c @@ -6,6 +6,25 @@ char shaders[][64] = "bloom_blur", "bloom_filter", "bloom_final", + "colourtint", + "crepuscular_opaque", + "crepuscular_rays", + "crepuscular_sky", + "default2d", + "defaultadditivesprite", + "defaultskin", + "defaultsky", + "defaultsprite", + "defaultwall", + "defaultwarp", + "drawflat_wall", + "lpp_depthnorm", + "lpp_light", + "lpp_wall", + "postproc_fisheye", + "postproc_panorama", + "rtlight", + "underwaterwarp", "" }; diff --git a/engine/shaders/glsl/colourtint.glsl b/engine/shaders/glsl/colourtint.glsl new file mode 100644 index 000000000..b2d070571 --- /dev/null +++ b/engine/shaders/glsl/colourtint.glsl @@ -0,0 +1,22 @@ +//this glsl shader is useful for cubemapped post processing effects (see csaddon for an example) +varying vec4 tf; +#ifdef VERTEX_SHADER +void main () +{ + gl_Position = tf = vec4(v_position.xy,-1.0, 1.0); +} +#endif +#ifdef FRAGMENT_SHADER +uniform sampler2D s_t0; +uniform sampler3D s_t1; +void main() +{ + vec2 fc; + fc = tf.xy / tf.w; + vec3 raw = texture2D(s_t0, (1.0 + fc) / 2.0).rgb; +#define LUTSIZE 16.0 + vec3 scale = vec3((LUTSIZE-1.0)/LUTSIZE); + vec3 bias = vec3(1.0/(2.0*LUTSIZE)); + gl_FragColor = texture3D(s_t1, raw * scale + bias); +} +#endif diff --git a/engine/shaders/glsl/crepuscular_opaque.glsl b/engine/shaders/glsl/crepuscular_opaque.glsl new file mode 100644 index 000000000..eb7990a7d --- /dev/null +++ b/engine/shaders/glsl/crepuscular_opaque.glsl @@ -0,0 +1,13 @@ +//opaque surfaces are drawn to the render target to mask out skies +#ifdef VERTEX_SHADER +void main () +{ + gl_Position = ftetransform(); +} +#endif +#ifdef FRAGMENT_SHADER +void main() +{ + gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); +} +#endif diff --git a/engine/shaders/glsl/crepuscular_rays.glsl b/engine/shaders/glsl/crepuscular_rays.glsl new file mode 100644 index 000000000..8c47f490f --- /dev/null +++ b/engine/shaders/glsl/crepuscular_rays.glsl @@ -0,0 +1,43 @@ +!!cvarf crep_decay +!!cvarf crep_density +!!cvarf crep_weight + +//this is a post-processing shader, drawn in 2d +//there will be a render target containing sky surfaces drawn with crepuscular_sky, and everything else drawn with crepuscular_opaque (to mask out the sky) +//this shader then just smudges the sky out a bit as though its coming from the sun or whatever through the clouds. +//yoinked from http://fabiensanglard.net/lightScattering/index.php + +varying vec2 tc; +#ifdef VERTEX_SHADER +attribute vec2 v_texcoord; +void main () +{ + tc = v_texcoord; + gl_Position = v_position; +} +#endif +#ifdef FRAGMENT_SHADER +const float crep_decay = 0.94; +const float crep_density = 0.5; +const float crep_weight = 0.2; +uniform vec3 l_lightcolour; +uniform vec3 l_lightscreen; +uniform sampler2D s_t0; +const int NUM_SAMPLES = 100; +void main() +{ + vec2 deltaTextCoord = vec2(tc.st - l_lightscreen.xy); + vec2 textCoo = tc.st; + deltaTextCoord *= 1.0 / float(NUM_SAMPLES) * crep_density; + float illuminationDecay = 1.0; + for(int i=0; i < NUM_SAMPLES ; i++) + { + textCoo -= deltaTextCoord; + vec4 sample = texture2D(s_t0, textCoo); + sample *= illuminationDecay * crep_weight; + gl_FragColor += sample; + illuminationDecay *= crep_decay; + } + gl_FragColor *= vec4(l_lightcolour, 1.0); +} +#endif diff --git a/engine/shaders/glsl/crepuscular_sky.glsl b/engine/shaders/glsl/crepuscular_sky.glsl new file mode 100644 index 000000000..2fc49d2ca --- /dev/null +++ b/engine/shaders/glsl/crepuscular_sky.glsl @@ -0,0 +1,31 @@ +//pretty much a regular sky shader +//though in reality we should render a sun circle in the middle. +//still, its kinda cool to have scrolling clouds masking out parts of the sun. + +#ifdef VERTEX_SHADER +varying vec3 pos; +void main () +{ + pos = v_position.xyz; + gl_Position = ftetransform(); +} +#endif +#ifdef FRAGMENT_SHADER +uniform float e_time; +uniform vec3 e_eyepos; +varying vec3 pos; +uniform sampler2D s_t0; +uniform sampler2D s_t1; +void main () +{ + vec2 tccoord; + vec3 dir = pos - e_eyepos; + dir.z *= 3.0; + dir.xy /= 0.5*length(dir); + tccoord = (dir.xy + e_time*0.03125); + vec3 solid = vec3(texture2D(s_t0, tccoord)); + tccoord = (dir.xy + e_time*0.0625); + vec4 clouds = texture2D(s_t1, tccoord); + gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb); +} +#endif diff --git a/engine/shaders/glsl/default2d.glsl b/engine/shaders/glsl/default2d.glsl new file mode 100644 index 000000000..a3d874ca9 --- /dev/null +++ b/engine/shaders/glsl/default2d.glsl @@ -0,0 +1,26 @@ +//this shader is present for support for gles/gl3core contexts +//it is single-texture-with-vertex-colours, and doesn't do anything special. +//beware that a few things use this, including apparently fonts and bloom rescaling. +//its really not meant to do anything special. + +#ifdef VERTEX_SHADER +attribute vec2 v_texcoord; +attribute vec4 v_colour; +varying vec2 tc; +varying vec4 vc; +void main () +{ + tc = v_texcoord; + vc = v_colour; + gl_Position = ftetransform(); +} +#endif +#ifdef FRAGMENT_SHADER +uniform sampler2D s_t0; +in vec2 tc; +varying vec4 vc; +void main () +{ + gl_FragColor = texture2D(s_t0, tc) * vc; +} +#endif diff --git a/engine/shaders/glsl/defaultadditivesprite.glsl b/engine/shaders/glsl/defaultadditivesprite.glsl new file mode 100644 index 000000000..1ec33074a --- /dev/null +++ b/engine/shaders/glsl/defaultadditivesprite.glsl @@ -0,0 +1,28 @@ +!!permu FOG + +//meant to be used for additive stuff. presumably particles and sprites. though actually its only flashblend effects that use this at the time of writing. +//includes fog, apparently. + +#include "sys/fog.h" +#ifdef VERTEX_SHADER +attribute vec2 v_texcoord; +attribute vec4 v_colour; +varying vec2 tc; +varying vec4 vc; +void main () +{ + tc = v_texcoord; + vc = v_colour; + gl_Position = ftetransform(); +} +#endif +#ifdef FRAGMENT_SHADER +uniform sampler2D s_t0; +varying vec2 tc; +varying vec4 vc; +uniform vec4 e_colourident; +void main () +{ + gl_FragColor = fog4additive(texture2D(s_t0, tc) * vc * e_colourident); +} +#endif diff --git a/engine/shaders/glsl/defaultskin.glsl b/engine/shaders/glsl/defaultskin.glsl new file mode 100644 index 000000000..b60a07aa6 --- /dev/null +++ b/engine/shaders/glsl/defaultskin.glsl @@ -0,0 +1,61 @@ +!!permu FULLBRIGHT +!!permu UPPERLOWER +!!permu FRAMEBLEND +!!permu SKELETAL +!!permu FOG + +//standard shader used for models. +//must support skeletal and 2-way vertex blending or Bad Things Will Happen. +//the vertex shader is responsible for calculating lighting values. + +varying vec2 tc; +varying vec3 light; +#ifdef VERTEX_SHADER +#include "sys/skeletal.h" +attribute vec2 v_texcoord; +uniform vec3 e_light_dir; +uniform vec3 e_light_mul; +uniform vec3 e_light_ambient; +void main () +{ + vec3 n; + gl_Position = skeletaltransform_n(n); + light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul); + tc = v_texcoord; +} +#endif +#ifdef FRAGMENT_SHADER +#include "sys/fog.h" +uniform sampler2D s_t0; +#ifdef LOWER +uniform sampler2D s_t1; +uniform vec3 e_lowercolour; +#endif +#ifdef UPPER +uniform sampler2D s_t2; +uniform vec3 e_uppercolour; +#endif +#ifdef FULLBRIGHT +uniform sampler2D s_t3; +#endif +uniform vec4 e_colourident; +void main () +{ + vec4 col, sp; + col = texture2D(s_t0, tc); +#ifdef UPPER + vec4 uc = texture2D(s_t2, tc); + col.rgb = mix(col.rgb, uc.rgb*e_uppercolour, uc.a); +#endif +#ifdef LOWER + vec4 lc = texture2D(s_t1, tc); + col.rgb = mix(col.rgb, lc.rgb*e_lowercolour, lc.a); +#endif + col.rgb *= light; +#ifdef FULLBRIGHT + vec4 fb = texture2D(s_t3, tc); + col.rgb = mix(col.rgb, fb.rgb, fb.a); +#endif + gl_FragColor = fog4(col * e_colourident); +} +#endif diff --git a/engine/shaders/glsl/defaultsky.glsl b/engine/shaders/glsl/defaultsky.glsl new file mode 100644 index 000000000..63ea43e6c --- /dev/null +++ b/engine/shaders/glsl/defaultsky.glsl @@ -0,0 +1,30 @@ +//regular sky shader for scrolling q1 skies +//the sky surfaces are thrown through this as-is. + +#ifdef VERTEX_SHADER +varying vec3 pos; +void main () +{ + pos = v_position.xyz; + gl_Position = ftetransform(); +} +#endif +#ifdef FRAGMENT_SHADER +uniform float e_time; +uniform vec3 e_eyepos; +varying vec3 pos; +uniform sampler2D s_t0; +uniform sampler2D s_t1; +void main () +{ + vec2 tccoord; + vec3 dir = pos - e_eyepos; + dir.z *= 3.0; + dir.xy /= 0.5*length(dir); + tccoord = (dir.xy + e_time*0.03125); + vec3 solid = vec3(texture2D(s_t0, tccoord)); + tccoord = (dir.xy + e_time*0.0625); + vec4 clouds = texture2D(s_t1, tccoord); + gl_FragColor.rgb = (solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb); +} +#endif diff --git a/engine/shaders/glsl/defaultsprite.glsl b/engine/shaders/glsl/defaultsprite.glsl new file mode 100644 index 000000000..c9850e9ea --- /dev/null +++ b/engine/shaders/glsl/defaultsprite.glsl @@ -0,0 +1,27 @@ +!!permu FOG +//used by both particles and sprites. +//note the fog blending mode is all that differs from defaultadditivesprite + +#include "sys/fog.h" +#ifdef VERTEX_SHADER +attribute vec2 v_texcoord; +attribute vec4 v_colour; +varying vec2 tc; +varying vec4 vc; +void main () +{ + tc = v_texcoord; + vc = v_colour; + gl_Position = ftetransform(); +} +#endif +#ifdef FRAGMENT_SHADER +uniform sampler2D s_t0; +varying vec2 tc; +varying vec4 vc; +uniform vec4 e_colourident; +void main () +{ + gl_FragColor = fog4blend(texture2D(s_t0, tc) * vc * e_colourident); +} +#endif diff --git a/engine/shaders/glsl/defaultwall.glsl b/engine/shaders/glsl/defaultwall.glsl new file mode 100644 index 000000000..24385bcda --- /dev/null +++ b/engine/shaders/glsl/defaultwall.glsl @@ -0,0 +1,66 @@ +!!permu OFFSETMAPPING +!!permu FULLBRIGHT +!!permu FOG +!!cvarf r_glsl_offsetmapping_scale + +//this is what normally draws all of your walls, even with rtlights disabled +//note that the '286' preset uses drawflat_walls instead. + +#include "sys/fog.h" +#if defined(OFFSETMAPPING) +varying vec3 eyevector; +#endif +#ifdef VERTEX_SHADER +attribute vec2 v_texcoord; +attribute vec2 v_lmcoord; +varying vec2 tc, lm; +#if defined(OFFSETMAPPING) +uniform vec3 e_eyepos; +attribute vec3 v_normal; +attribute vec3 v_svector; +attribute vec3 v_tvector; +#endif +void main () +{ +#if defined(OFFSETMAPPING) + vec3 eyeminusvertex = e_eyepos - v_position.xyz; + eyevector.x = dot(eyeminusvertex, v_svector.xyz); + eyevector.y = -dot(eyeminusvertex, v_tvector.xyz); + eyevector.z = dot(eyeminusvertex, v_normal.xyz); +#endif + tc = v_texcoord; + lm = v_lmcoord; + gl_Position = ftetransform(); +} +#endif +#ifdef FRAGMENT_SHADER +uniform sampler2D s_t0; +uniform sampler2D s_t1; +#ifdef OFFSETMAPPING +uniform sampler2D s_t2; +#endif +#ifdef FULLBRIGHT +uniform sampler2D s_t4; +#endif +varying vec2 tc, lm; +uniform vec4 e_lmscale; +uniform vec4 e_colourident; +#ifdef OFFSETMAPPING +#include "sys/offsetmapping.h" +#endif +void main () +{ +#ifdef OFFSETMAPPING + vec2 tcoffsetmap = offsetmap(s_t2, tc, eyevector); +#define tc tcoffsetmap +#endif + gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * e_lmscale; +#ifdef FULLBRIGHT + gl_FragColor.rgb += texture2D(s_t4, tc).rgb; +#endif + gl_FragColor = gl_FragColor * e_colourident; +#ifdef FOG + gl_FragColor = fog4(gl_FragColor); +#endif +} +#endif diff --git a/engine/shaders/glsl/defaultwarp.glsl b/engine/shaders/glsl/defaultwarp.glsl new file mode 100644 index 000000000..c2005933c --- /dev/null +++ b/engine/shaders/glsl/defaultwarp.glsl @@ -0,0 +1,29 @@ +!!cvarf r_wateralpha +!!permu FOG + +//this is the shader that's responsible for drawing default q1 turbulant water surfaces +//this is expected to be moderately fast. + +#include "sys/fog.h" +varying vec2 tc; +#ifdef VERTEX_SHADER +attribute vec2 v_texcoord; +void main () +{ + tc = v_texcoord.st; + gl_Position = ftetransform(); +} +#endif +#ifdef FRAGMENT_SHADER +uniform sampler2D s_t0; +uniform float e_time; +uniform float cvar_r_wateralpha; +void main () +{ + vec2 ntc; + ntc.s = tc.s + sin(tc.t+e_time)*0.125; + ntc.t = tc.t + sin(tc.s+e_time)*0.125; + vec3 ts = vec3(texture2D(s_t0, ntc)); + gl_FragColor = fog4(vec4(ts, cvar_r_wateralpha)); +} +#endif diff --git a/engine/shaders/glsl/drawflat_wall.glsl b/engine/shaders/glsl/drawflat_wall.glsl new file mode 100644 index 000000000..94d665726 --- /dev/null +++ b/engine/shaders/glsl/drawflat_wall.glsl @@ -0,0 +1,30 @@ +!!cvarv r_floorcolor +!!cvarv r_wallcolor +!!permu FOG + +//this is for the '286' preset walls, and just draws lightmaps coloured based upon surface normals. + +#include "sys/fog.h" +varying vec4 col; +#ifdef VERTEX_SHADER +attribute vec3 v_normal; +attribute vec2 v_lmcoord; +varying vec2 lm; +uniform vec3 cvar_r_wallcolor; +uniform vec3 cvar_r_floorcolor; +uniform vec4 e_lmscale; +void main () +{ + col = vec4(e_lmscale.rgb/255.0 * ((v_normal.z < 0.73)?cvar_r_wallcolor:cvar_r_floorcolor), e_lmscale.a); + lm = v_lmcoord; + gl_Position = ftetransform(); +} +#endif +#ifdef FRAGMENT_SHADER +uniform sampler2D s_t0; +varying vec2 lm; +void main () +{ + gl_FragColor = fog4(col * texture2D(s_t0, lm)); +} +#endif diff --git a/engine/shaders/glsl/lpp_depthnorm.glsl b/engine/shaders/glsl/lpp_depthnorm.glsl new file mode 100644 index 000000000..bff3982f4 --- /dev/null +++ b/engine/shaders/glsl/lpp_depthnorm.glsl @@ -0,0 +1,39 @@ +!!permu BUMP +!!permu SKELETAL + +//light pre-pass rendering (defered lighting) +//this is the initial pass, that draws the surface normals and depth to the initial colour buffer + +varying vec3 norm, tang, bitang; +#if defined(BUMP) +varying vec2 tc; +#endif +#ifdef VERTEX_SHADER +#include "sys/skeletal.h" +attribute vec2 v_texcoord; +void main() +{ +#if defined(BUMP) + gl_Position = skeletaltransform_nst(norm, tang, bitang); + tc = v_texcoord; +#else + gl_Position = skeletaltransform_n(norm); +#endif +} +#endif +#ifdef FRAGMENT_SHADER +#if defined(BUMP) +uniform sampler2D s_t0; +#endif +void main() +{ + vec3 onorm; +#if defined(BUMP) + vec3 bm = 2.0*texture2D(s_t0, tc).xyz - 1.0; + onorm = normalize(bm.x * tang + bm.y * bitang + bm.z * norm); +#else + onorm = norm; +#endif + gl_FragColor = vec4(onorm.xyz, gl_FragCoord.z / gl_FragCoord.w); +} +#endif diff --git a/engine/shaders/glsl/lpp_light.glsl b/engine/shaders/glsl/lpp_light.glsl new file mode 100644 index 000000000..9b6cb796a --- /dev/null +++ b/engine/shaders/glsl/lpp_light.glsl @@ -0,0 +1,58 @@ +//this shader is a light shader. ideally drawn with a quad covering the entire region +//the output is contribution from this light (which will be additively blended) +//you can blame Electro for much of the maths in here. +//fixme: no fog + +varying vec4 tf; +#ifdef VERTEX_SHADER +void main() +{ + tf = ftetransform(); + gl_Position = tf; +} +#endif +#ifdef FRAGMENT_SHADER +uniform sampler2D s_t0; +uniform vec3 l_lightposition; +uniform mat4 m_invviewprojection; +uniform vec3 l_lightcolour; +uniform float l_lightradius; +vec3 calcLightWorldPos(vec2 screenPos, float depth) +{ + vec4 pos; + pos.x = screenPos.x; + pos.y = screenPos.y; + pos.z = depth; + pos.w = 1.0; + pos = m_invviewprojection * pos; + return pos.xyz / pos.w; +} +void main () +{ + vec3 lightColour = l_lightcolour.rgb; + float lightIntensity = 1.0; + float lightAttenuation = l_lightradius; // fixme: just use the light radius for now, use better near/far att math separately once working + float radiusFar = l_lightradius; + float radiusNear = l_lightradius*0.5; + + vec2 fc; + fc = tf.xy / tf.w; + vec4 data = texture2D(s_t0, (1.0 + fc) / 2.0); + float depth = data.a; + vec3 norm = data.xyz; + + /* calc where the wall that generated this sample came from */ + vec3 worldPos = calcLightWorldPos(fc, depth); + + /*calc diffuse lighting term*/ + vec3 lightDir = l_lightposition - worldPos; + float zdiff = 1.0 - clamp(length(lightDir) / lightAttenuation, 0.0, 1.0); + float atten = (radiusFar * zdiff) / (radiusFar - radiusNear); + atten = pow(atten, 2.0); + lightDir = normalize(lightDir); + float nDotL = dot(norm, lightDir) * atten; + float lightDiffuse = max(0.0, nDotL); + + gl_FragColor = vec4(lightDiffuse * (lightColour * lightIntensity), 1.0); +} +#endif diff --git a/engine/shaders/glsl/lpp_wall.glsl b/engine/shaders/glsl/lpp_wall.glsl new file mode 100644 index 000000000..556ce5eb3 --- /dev/null +++ b/engine/shaders/glsl/lpp_wall.glsl @@ -0,0 +1,34 @@ +//the final defered lighting pass. +//the lighting values were written to some render target, which is fed into this shader, and now we draw all the wall textures with it. + +varying vec2 tc, lm; +varying vec4 tf; +#ifdef VERTEX_SHADER +attribute vec2 v_texcoord; +attribute vec2 v_lmcoord; +void main () +{ + tc = v_texcoord; + lm = v_lmcoord; + gl_Position = tf = ftetransform(); +} +#endif +#ifdef FRAGMENT_SHADER +uniform sampler2D s_t0; +uniform sampler2D s_t1; +uniform sampler2D s_t2; +uniform vec4 e_lmscale; +void main () +{ + vec2 nst; + nst = tf.xy / tf.w; + nst = (1.0 + nst) / 2.0; + vec4 l = texture2D(s_t0, nst)*5.0; + vec4 c = texture2D(s_t1, tc); + vec3 lmsamp = texture2D(s_t2, lm).rgb*lmscale; + vec3 diff = l.rgb; + vec3 chrom = diff / (0.001 + dot(diff, vec3(0.3, 0.59, 0.11))); + vec3 spec = chrom * l.a; + gl_FragColor = vec4((diff + lmsamp) * c.xyz, 1.0); +} +#endif diff --git a/engine/shaders/glsl/postproc_fisheye.glsl b/engine/shaders/glsl/postproc_fisheye.glsl new file mode 100644 index 000000000..a5899a33d --- /dev/null +++ b/engine/shaders/glsl/postproc_fisheye.glsl @@ -0,0 +1,31 @@ +!!cvarf ffov + +//fisheye view rendering, for silly fovs that are still playable. + +#ifdef VERTEX_SHADER +attribute vec2 v_texcoord; +varying vec2 texcoord; +void main() +{ + texcoord = v_texcoord.xy; + gl_Position = ftetransform(); +} +#endif +#ifdef FRAGMENT_SHADER +uniform samplerCube s_t0; +varying vec2 texcoord; +uniform float cvar_ffov; +void main() +{ + vec3 tc; + vec2 d; + vec2 ang; + d = texcoord; + ang.x = sqrt(d.x*d.x+d.y*d.y)*radians(cvar_ffov); + ang.y = -atan(d.y, d.x); + tc.x = sin(ang.x) * cos(ang.y); + tc.y = sin(ang.x) * sin(ang.y); + tc.z = cos(ang.x); + gl_FragColor = textureCube(s_t0, tc); +} +#endif diff --git a/engine/shaders/glsl/postproc_panorama.glsl b/engine/shaders/glsl/postproc_panorama.glsl new file mode 100644 index 000000000..a898e9997 --- /dev/null +++ b/engine/shaders/glsl/postproc_panorama.glsl @@ -0,0 +1,28 @@ +!!cvarf ffov + +//panoramic view rendering, for promo map shots or whatever. + +#ifdef VERTEX_SHADER +attribute vec2 v_texcoord; +varying vec2 texcoord; +void main() +{ + texcoord = v_texcoord.xy; + gl_Position = ftetransform(); +} +#endif +#ifdef FRAGMENT_SHADER +uniform samplerCube s_t0; +varying vec2 texcoord; +uniform float cvar_ffov; +void main() +{ + vec3 tc; + float ang; + ang = texcoord.x*-radians(cvar_ffov); + tc.x = sin(ang); + tc.y = -texcoord.y; + tc.z = cos(ang); + gl_FragColor = textureCube(s_t0, tc); +} +#endif diff --git a/engine/shaders/glsl/rtlight.glsl b/engine/shaders/glsl/rtlight.glsl new file mode 100644 index 000000000..bf7ace9a7 --- /dev/null +++ b/engine/shaders/glsl/rtlight.glsl @@ -0,0 +1,154 @@ +!!permu BUMP +!!permu SPECULAR +!!permu OFFSETMAPPING +!!permu SKELETAL +!!permu FOG +!!cvarf r_glsl_offsetmapping_scale + +//this is the main shader responsible for realtime dlights. + +//texture units: +//s0=diffuse, s1=normal, s2=specular, s3=shadowmap +//custom modifiers: +//PCF(shadowmap) +//CUBE(projected cubemap) + + +varying vec2 tcbase; +varying vec3 lightvector; +#if defined(SPECULAR) || defined(OFFSETMAPPING) +varying vec3 eyevector; +#endif +#if defined(PCF) || defined(CUBE) +varying vec4 vshadowcoord; +uniform mat4 l_projmatrix; +#endif +#ifdef VERTEX_SHADER +#include "sys/skeletal.h" +uniform vec3 l_lightposition; +attribute vec2 v_texcoord; +#if defined(SPECULAR) || defined(OFFSETMAPPING) +uniform vec3 e_eyepos; +#endif +void main () +{ + vec3 n, s, t, w; + gl_Position = skeletaltransform_wnst(w,n,s,t); + tcbase = v_texcoord; //pass the texture coords straight through + vec3 lightminusvertex = l_lightposition - w.xyz; + lightvector.x = dot(lightminusvertex, s.xyz); + lightvector.y = dot(lightminusvertex, t.xyz); + lightvector.z = dot(lightminusvertex, n.xyz); +#if defined(SPECULAR)||defined(OFFSETMAPPING) + vec3 eyeminusvertex = e_eyepos - w.xyz; + eyevector.x = dot(eyeminusvertex, s.xyz); + eyevector.y = -dot(eyeminusvertex, t.xyz); + eyevector.z = dot(eyeminusvertex, n.xyz); +#endif +#if defined(PCF) || defined(SPOT) || defined(PROJECTION) || defined(CUBE) + vshadowcoord = l_projmatrix*vec4(w.xyz, 1.0); +#endif +} +#endif +#ifdef FRAGMENT_SHADER +#include "sys/fog.h" +uniform sampler2D s_t0; +#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING) +uniform sampler2D s_t1; +#endif +#ifdef SPECULAR +uniform sampler2D s_t2; +#endif +#ifdef CUBE +uniform samplerCube s_t3; +#endif +#ifdef PCF +#ifdef CUBE +uniform samplerCubeShadow s_t7; +#else +uniform sampler2DShadow s_t7; +#endif +#endif +uniform float l_lightradius; +uniform vec3 l_lightcolour; +uniform vec3 l_lightcolourscale; +#ifdef OFFSETMAPPING +#include "sys/offsetmapping.h" +#endif +void main () +{ +#ifdef OFFSETMAPPING + vec2 tcoffsetmap = offsetmap(s_t1, tcbase, eyevector); +#define tcbase tcoffsetmap +#endif + vec3 bases = vec3(texture2D(s_t0, tcbase)); +#if defined(BUMP) || defined(SPECULAR) + vec3 bumps = vec3(texture2D(s_t1, tcbase)) - 0.5; +#endif +#ifdef SPECULAR + vec4 specs = texture2D(s_t2, tcbase); +#endif + vec3 nl = normalize(lightvector); + float colorscale = max(1.0 - dot(lightvector, lightvector)/(l_lightradius*l_lightradius), 0.0); + vec3 diff; +#ifdef BUMP + diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(2.0*bumps, nl), 0.0)); +#else + diff = bases * (l_lightcolourscale.x + l_lightcolourscale.y * max(dot(vec3(0.0, 0.0, 1.0), nl), 0.0)); +#endif +#ifdef SPECULAR + vec3 halfdir = normalize(lightvector - normalize(eyevector)); + float spec = pow(max(dot(halfdir, bumps), 0.0), 1.0 + 32.0 * specs.a); + diff += spec * specs.rgb * l_lightcolourscale.z; +#endif +#ifdef CUBE + diff *= textureCube(s_t3, vshadowcoord.xyz).rgb; +#endif +#ifdef PCF + #if defined(SPOT) + const float texx = 512.0; + const float texy = 512.0; + vec4 shadowcoord = vshadowcoord; + #else + const float texx = 512.0; + const float texy = 512.0; + vec4 shadowcoord; + shadowcoord.zw = vshadowcoord.zw; + shadowcoord.xy = vshadowcoord.xy; + #endif + #ifdef CUBE + const float xPixelOffset = 1.0/texx; const float yPixelOffset = 1.0/texy; float s = 0.0; + s += shadowCubeProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadowCubeProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadowCubeProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadowCubeProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadowCubeProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadowCubeProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadowCubeProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadowCubeProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadowCubeProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + colorscale *= s/9.0; + #else + const float xPixelOffset = 1.0/texx; const float yPixelOffset = 1.0/texy; float s = 0.0; + s += shadow2DProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadow2DProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadow2DProj(s_t7, shadowcoord + vec4(-1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadow2DProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadow2DProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadow2DProj(s_t7, shadowcoord + vec4(0.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadow2DProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, -1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadow2DProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 0.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + s += shadow2DProj(s_t7, shadowcoord + vec4(1.0 * xPixelOffset * shadowcoord.w, 1.0 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r; + colorscale *= s/9.0; + #endif +#endif +#if defined(SPOT) + if (shadowcoord.w < 0.0) discard; + vec2 spot = ((shadowcoord.st)/shadowcoord.w - 0.5)*2.0;colorscale*=1.0-(dot(spot,spot)); +#endif +#if defined(PROJECTION) + l_lightcolour *= texture2d(s_t3, shadowcoord); +#endif + gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour); +} +#endif diff --git a/engine/shaders/glsl/underwaterwarp.glsl b/engine/shaders/glsl/underwaterwarp.glsl new file mode 100644 index 000000000..70c9a4427 --- /dev/null +++ b/engine/shaders/glsl/underwaterwarp.glsl @@ -0,0 +1,45 @@ +!!cvarf r_waterwarp + +//this is a post processing shader that is drawn fullscreen whenever the view is underwater. +//its generally expected to warp the view a little. + +#ifdef VERTEX_SHADER +attribute vec2 v_texcoord; +varying vec2 v_stc; +varying vec2 v_warp; +varying vec2 v_edge; +uniform float e_time; +void main () +{ +gl_Position = ftetransform(); +v_stc = (1.0+(gl_Position.xy / gl_Position.w))/2.0; +v_warp.s = e_time * 0.25 + v_texcoord.s; +v_warp.t = e_time * 0.25 + v_texcoord.t; +v_edge = v_texcoord.xy; +} +#endif +#ifdef FRAGMENT_SHADER +varying vec2 v_stc; +varying vec2 v_warp; +varying vec2 v_edge; +uniform sampler2D s_t0;/*$currentrender*/ +uniform sampler2D s_t1;/*warp image*/ +uniform sampler2D s_t2;/*edge image*/ +uniform vec3 e_rendertexturescale; +uniform float cvar_r_waterwarp; +void main () +{ +float amptemp; +vec3 edge; +edge = texture2D( s_t2, v_edge ).rgb; +amptemp = (0.010 / 0.625) * cvar_r_waterwarp * edge.x; +vec3 offset; +offset = texture2D( s_t1, v_warp ).rgb; +offset.x = (offset.x - 0.5) * 2.0; +offset.y = (offset.y - 0.5) * 2.0; +vec2 temp; +temp.x = v_stc.x + offset.x * amptemp; +temp.y = v_stc.y + offset.y * amptemp; +gl_FragColor = texture2D( s_t0, temp*e_rendertexturescale.st ); +} +#endif diff --git a/plugins/xsv/m_x.c b/plugins/xsv/m_x.c index 8dd9c6efb..fdd271a31 100644 --- a/plugins/xsv/m_x.c +++ b/plugins/xsv/m_x.c @@ -848,7 +848,7 @@ void XWindows_Startup(void) //initialise the server socket and do any initial se XS_CheckResourceSentinals(); - Menu_Control(MENU_GRAB); +// Menu_Control(MENU_GRAB); } extern int x_windowwithfocus; @@ -2018,7 +2018,7 @@ media_decoder_funcs_t decoderfuncs = int Plug_Init(int *args) { if (!Plug_Export("ExecuteCommand", Plug_ExecuteCommand) || - !Plug_Export("MenuEvent", Plug_MenuEvent) || +// !Plug_Export("MenuEvent", Plug_MenuEvent) || !Plug_Export("Tick", Plug_Tick)) { Con_Printf("XServer plugin failed\n");