From 31ced9384dd0fd51093d47f628244d165d890f33 Mon Sep 17 00:00:00 2001 From: Spoike Date: Fri, 28 Aug 2015 03:13:45 +0000 Subject: [PATCH] fix cl_maxfps as a q3 client. implement cfg_save_auto cvar, to replicated vanilla quake, ish. default off, obviously. support for Q2RDF_IRGOGGLES (in combination with Q2RF_IR_VISIBLE). untested. rework vectorvectors to be more predictable. v_right_z is now _much_ more commonly 0. fix potential sound-related lock-up/console spam. implement $colored_armor+$colored_powerup macros. if command now copes with ' quotes. fix crash on flushing q3bsps. fix black bits with r_renderscale+cl_sbar 1 implement emulation for legacy q3 shaders when glsl is required. this is primarily for webgl right now, but potentially also useful with any gles2 port (fixme: still need to tweak d3d11 backend to support this too). include scrollbar glyphs in the fallback font logic. this is primarily for download progress bars, especially with webgl. don't try applying gamma to screenshots when using glsl. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4976 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_input.c | 5 +- engine/client/cl_main.c | 4 + engine/client/clq2_ents.c | 14 +++ engine/client/keys.c | 169 +++++++++++++------------- engine/client/m_master.c | 2 +- engine/client/menu.c | 5 +- engine/client/pr_csqc.c | 9 +- engine/client/r_part.c | 1 + engine/client/snd_dma.c | 2 +- engine/client/zqtp.c | 101 ++++++++++++---- engine/common/cmd.c | 26 +++- engine/common/com_mesh.c | 2 + engine/common/gl_q2bsp.c | 1 + engine/common/mathlib.c | 21 ++-- engine/common/pr_bgcmd.c | 11 ++ engine/common/pr_common.h | 1 + engine/common/protocol.h | 1 + engine/dotnet2005/ftequake.vcproj | 2 +- engine/gl/gl_backend.c | 187 +++++++++++++++++++++++------ engine/gl/gl_font.c | 27 +++++ engine/gl/gl_model.h | 1 + engine/gl/gl_rmain.c | 18 ++- engine/gl/gl_screen.c | 29 +++-- engine/gl/gl_shader.c | 13 +- engine/gl/gl_vidcommon.c | 3 + engine/gl/r_bishaders.h | 91 ++++++++++---- engine/gl/shader.h | 5 + engine/server/pr_cmds.c | 11 -- engine/shaders/generatebuiltinsl.c | 1 + engine/web/gl_vidweb.c | 2 +- 30 files changed, 540 insertions(+), 225 deletions(-) diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index fd9a75f22..e43d08669 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -1145,9 +1145,12 @@ float CL_FilterTime (double time, float wantfps, qboolean ignoreserver) //now re { float fps, fpscap; - if (cls.timedemo || cls.protocol == CP_QUAKE3) + if (cls.timedemo) return -1; + if (cls.protocol == CP_QUAKE3) + ignoreserver = true; + /*ignore the server if we're playing demos, sending to the server only as replies, or if its meant to be disabled (netfps depending on where its called from)*/ if (cls.demoplayback != DPB_NONE || (cls.protocol != CP_QUAKEWORLD && cls.protocol != CP_NETQUAKE) || ignoreserver) { diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index a25486f26..ae1523664 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -1356,6 +1356,7 @@ CL_ClearState */ void CL_ClearState (void) { + extern cvar_t cfg_save_auto; int i, j; #ifndef CLIENTONLY #define serverrunning (sv.state != ss_dead) @@ -1501,6 +1502,9 @@ void CL_ClearState (void) cl.splitclients = 1; cl.autotrack_hint = -1; cl.autotrack_killer = -1; + + if (cfg_save_auto.ival && Cvar_UnsavedArchive()) + Cmd_ExecuteString("cfg_save\n", RESTRICT_LOCAL); } /* diff --git a/engine/client/clq2_ents.c b/engine/client/clq2_ents.c index 94ad86ebb..aefe9fb0f 100644 --- a/engine/client/clq2_ents.c +++ b/engine/client/clq2_ents.c @@ -1470,8 +1470,22 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) ent.framestate.g[FS_REG].lerpweight[0] = fwds; ent.framestate.g[FS_REG].lerpweight[1] = back; + if ((renderfx & Q2RF_IR_VISIBLE) && (r_refdef.flags & Q2RDF_IRGOGGLES)) + { + //IR googles make ir visible ents visible in pure red. + ent.shaderRGBAf[0] = 1; + ent.shaderRGBAf[1] = 0; + ent.shaderRGBAf[2] = 0; + //bypasses world lighting + ent.light_known = true; + VectorSet(ent.light_avg, 1, 1, 1); + VectorSet(ent.light_range, 0, 0, 0); + //(yes, its a bit shit. not even a post-process thing) + } + // add to refresh list V_AddEntity (&ent); + ent.light_known = false; // color shells generate a seperate entity for the main model diff --git a/engine/client/keys.c b/engine/client/keys.c index 8420b1a05..904f7f2e2 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -113,45 +113,46 @@ typedef struct keyname_t keynames[] = { - {"TAB", K_TAB}, - {"ENTER", K_ENTER}, - {"ESCAPE", K_ESCAPE}, - {"SPACE", K_SPACE}, - {"BACKSPACE", K_BACKSPACE}, - {"UPARROW", K_UPARROW}, - {"DOWNARROW", K_DOWNARROW}, - {"LEFTARROW", K_LEFTARROW}, - {"RIGHTARROW", K_RIGHTARROW}, + {"TAB", K_TAB}, + {"ENTER", K_ENTER}, + {"RETURN", K_ENTER}, + {"ESCAPE", K_ESCAPE}, + {"SPACE", K_SPACE}, + {"BACKSPACE", K_BACKSPACE}, + {"UPARROW", K_UPARROW}, + {"DOWNARROW", K_DOWNARROW}, + {"LEFTARROW", K_LEFTARROW}, + {"RIGHTARROW", K_RIGHTARROW}, - {"LALT", K_LALT}, - {"RALT", K_RALT}, - {"LCTRL", K_LCTRL}, - {"RCTRL", K_RCTRL}, - {"LSHIFT", K_LSHIFT}, - {"RSHIFT", K_RSHIFT}, - {"ALT", K_LALT}, //depricated name - {"CTRL", K_CTRL}, //depricated name - {"SHIFT", K_SHIFT}, //depricated name + {"LALT", K_LALT}, + {"RALT", K_RALT}, + {"LCTRL", K_LCTRL}, + {"RCTRL", K_RCTRL}, + {"LSHIFT", K_LSHIFT}, + {"RSHIFT", K_RSHIFT}, + {"ALT", K_ALT}, //depricated name + {"CTRL", K_CTRL}, //depricated name + {"SHIFT", K_SHIFT}, //depricated name - {"F1", K_F1}, - {"F2", K_F2}, - {"F3", K_F3}, - {"F4", K_F4}, - {"F5", K_F5}, - {"F6", K_F6}, - {"F7", K_F7}, - {"F8", K_F8}, - {"F9", K_F9}, - {"F10", K_F10}, - {"F11", K_F11}, - {"F12", K_F12}, + {"F1", K_F1}, + {"F2", K_F2}, + {"F3", K_F3}, + {"F4", K_F4}, + {"F5", K_F5}, + {"F6", K_F6}, + {"F7", K_F7}, + {"F8", K_F8}, + {"F9", K_F9}, + {"F10", K_F10}, + {"F11", K_F11}, + {"F12", K_F12}, - {"INS", K_INS}, - {"DEL", K_DEL}, - {"PGDN", K_PGDN}, - {"PGUP", K_PGUP}, - {"HOME", K_HOME}, - {"END", K_END}, + {"INS", K_INS}, + {"DEL", K_DEL}, + {"PGDN", K_PGDN}, + {"PGUP", K_PGUP}, + {"HOME", K_HOME}, + {"END", K_END}, {"KP_HOME", K_KP_HOME}, @@ -205,61 +206,61 @@ keyname_t keynames[] = {"VOLUP", K_VOLUP}, {"VOLDOWN", K_VOLDOWN}, - {"JOY1", K_JOY1}, - {"JOY2", K_JOY2}, - {"JOY3", K_JOY3}, - {"JOY4", K_JOY4}, + {"JOY1", K_JOY1}, + {"JOY2", K_JOY2}, + {"JOY3", K_JOY3}, + {"JOY4", K_JOY4}, - {"AUX1", K_AUX1}, - {"AUX2", K_AUX2}, - {"AUX3", K_AUX3}, - {"AUX4", K_AUX4}, - {"AUX5", K_AUX5}, - {"AUX6", K_AUX6}, - {"AUX7", K_AUX7}, - {"AUX8", K_AUX8}, - {"AUX9", K_AUX9}, - {"AUX10", K_AUX10}, - {"AUX11", K_AUX11}, - {"AUX12", K_AUX12}, - {"AUX13", K_AUX13}, - {"AUX14", K_AUX14}, - {"AUX15", K_AUX15}, - {"AUX16", K_AUX16}, - {"AUX17", K_AUX17}, - {"AUX18", K_AUX18}, - {"AUX19", K_AUX19}, - {"AUX20", K_AUX20}, - {"AUX21", K_AUX21}, - {"AUX22", K_AUX22}, - {"AUX23", K_AUX23}, - {"AUX24", K_AUX24}, - {"AUX25", K_AUX25}, - {"AUX26", K_AUX26}, - {"AUX27", K_AUX27}, - {"AUX28", K_AUX28}, - {"AUX29", K_AUX29}, - {"AUX30", K_AUX30}, - {"AUX31", K_AUX31}, - {"AUX32", K_AUX32}, + {"AUX1", K_AUX1}, + {"AUX2", K_AUX2}, + {"AUX3", K_AUX3}, + {"AUX4", K_AUX4}, + {"AUX5", K_AUX5}, + {"AUX6", K_AUX6}, + {"AUX7", K_AUX7}, + {"AUX8", K_AUX8}, + {"AUX9", K_AUX9}, + {"AUX10", K_AUX10}, + {"AUX11", K_AUX11}, + {"AUX12", K_AUX12}, + {"AUX13", K_AUX13}, + {"AUX14", K_AUX14}, + {"AUX15", K_AUX15}, + {"AUX16", K_AUX16}, + {"AUX17", K_AUX17}, + {"AUX18", K_AUX18}, + {"AUX19", K_AUX19}, + {"AUX20", K_AUX20}, + {"AUX21", K_AUX21}, + {"AUX22", K_AUX22}, + {"AUX23", K_AUX23}, + {"AUX24", K_AUX24}, + {"AUX25", K_AUX25}, + {"AUX26", K_AUX26}, + {"AUX27", K_AUX27}, + {"AUX28", K_AUX28}, + {"AUX29", K_AUX29}, + {"AUX30", K_AUX30}, + {"AUX31", K_AUX31}, + {"AUX32", K_AUX32}, - {"PAUSE", K_PAUSE}, + {"PAUSE", K_PAUSE}, - {"MWHEELUP", K_MWHEELUP}, - {"MWHEELDOWN", K_MWHEELDOWN}, + {"MWHEELUP", K_MWHEELUP}, + {"MWHEELDOWN", K_MWHEELDOWN}, - {"PRINTSCREEN", K_PRINTSCREEN}, - {"CAPSLOCK", K_CAPSLOCK}, - {"SCROLLLOCK", K_SCRLCK}, + {"PRINTSCREEN", K_PRINTSCREEN}, + {"CAPSLOCK", K_CAPSLOCK}, + {"SCROLLLOCK", K_SCRLCK}, - {"SEMICOLON", ';'}, // because a raw semicolon seperates commands - {"PLUS", '+'}, // because "shift++" is inferior to shift+plus + {"SEMICOLON", ';'}, // because a raw semicolon seperates commands + {"PLUS", '+'}, // because "shift++" is inferior to shift+plus - {"TILDE", '~'}, - {"BACKQUOTE", '`'}, - {"BACKSLASH", '\\'}, + {"TILDE", '~'}, + {"BACKQUOTE", '`'}, + {"BACKSLASH", '\\'}, - {NULL,0} + {NULL, 0} }; #if defined(CSQC_DAT) || defined(MENU_DAT) diff --git a/engine/client/m_master.c b/engine/client/m_master.c index 995b82a2f..2758c9759 100644 --- a/engine/client/m_master.c +++ b/engine/client/m_master.c @@ -574,7 +574,7 @@ static void SL_PostDraw (menu_t *menu) y += 8; } - Draw_FunStringWidth (lx, y, "^h(press k for keybind help)", w, false, false); + Draw_FunStringWidth (lx, y, "^h(left/rightarrow for different info)", w, false, false); } } else diff --git a/engine/client/menu.c b/engine/client/menu.c index 7a4b371ce..92603b97b 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -1017,11 +1017,12 @@ void M_Menu_Quit_f (void) menu_t *quitmenu; int i; int mode; - + extern cvar_t cfg_save_auto; char *arg = Cmd_Argv(1); + if (!strcmp(arg, "force")) mode = 0; - else if (!strcmp(arg, "forcesave")) + else if (!strcmp(arg, "forcesave") || cfg_save_auto.ival) { Cmd_ExecuteString("cfg_save", RESTRICT_LOCAL); mode = 0; diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 1da44d98c..1a182f20c 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -3456,13 +3456,6 @@ void QCBUILTIN PF_cl_ambientsound(pubprogfuncs_t *prinst, struct globalvars_s *p S_StaticSound (S_PrecacheSound (samp), pos, vol, attenuation); } -static void QCBUILTIN PF_cs_vectorvectors (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - VectorCopy(G_VECTOR(OFS_PARM0), csqcg.forward); - VectorNormalize(csqcg.forward); - VectorVectors(csqcg.forward, csqcg.right, csqcg.up); -} - static void QCBUILTIN PF_cs_lightstyle (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { int stnum = G_FLOAT(OFS_PARM0); @@ -5392,7 +5385,7 @@ static struct { {"te_lightning3", PF_cl_te_lightning3, 430}, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS) {"te_beam", PF_cl_te_beam, 431}, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS) - {"vectorvectors", PF_cs_vectorvectors, 432}, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS) + {"vectorvectors", PF_vectorvectors, 432}, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS) {"te_plasmaburn", PF_cl_te_plasmaburn, 433}, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN) {"getsurfacenumpoints", PF_getsurfacenumpoints, 434}, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) diff --git a/engine/client/r_part.c b/engine/client/r_part.c index ef55564a7..c0c74d55a 100644 --- a/engine/client/r_part.c +++ b/engine/client/r_part.c @@ -431,6 +431,7 @@ void R_Clutter_Emit(batch_t **batches) BE_VBO_Data(&vctx, cctx.soups[i].sdir, sizeof(cctx.soups[i].sdir[0])*cctx.soups[i].numverts, §->soups[sect->numsoups].vbo.svector); BE_VBO_Data(&vctx, cctx.soups[i].tdir, sizeof(cctx.soups[i].tdir[0])*cctx.soups[i].numverts, §->soups[sect->numsoups].vbo.tvector); BE_VBO_Finish(&vctx, cctx.soups[i].idx, sizeof(cctx.soups[i].idx[0])*cctx.soups[i].numidx, §->soups[sect->numsoups].vbo.indicies); + sect->soups[sect->numsoups].vbo.colours_bytes = false; sect->soups[sect->numsoups].mesh.numindexes = sect->soups[sect->numsoups].vbo.indexcount = cctx.soups[i].numidx; sect->soups[sect->numsoups].mesh.numvertexes = sect->soups[sect->numsoups].vbo.vertcount = cctx.soups[i].numverts; diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index d504de55e..c75f85940 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -2452,7 +2452,7 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f // pick a channel to play on target_chan = SND_PickChannel(sc, entnum, entchannel); if (!target_chan) - return; + break; S_UpdateSoundCard(sc, false, target_chan, entnum, entchannel, sfx, origin, fvol, attenuation, timeofs, pitchadj, flags); } diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 2f4c75773..81db9962b 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -1066,6 +1066,65 @@ char *Macro_CombinedHealth(void) return macro_buf; } +char *Macro_Coloured_Armour(void) +{ + if (cl.playerview[SP].stats[STAT_ITEMS] & IT_ARMOR3) + return "{^s^xe00%%a^r}"; + else if (cl.playerview[SP].stats[STAT_ITEMS] & IT_ARMOR2) + return "{^s^xff0%%a^r}"; + else if (cl.playerview[SP].stats[STAT_ITEMS] & IT_ARMOR1) + return "{^s^x0b0%%a^r}"; + else + return "{0}"; +} + +char *Macro_Coloured_Powerups(void) +{ + char *quad, *pent, *ring; + quad = (cl.playerview[SP].stats[STAT_ITEMS] & IT_QUAD) ?va("^x03f%s", tp_name_quad.string):""; + pent = (cl.playerview[SP].stats[STAT_ITEMS] & IT_INVULNERABILITY) ?va("^xe00%s", tp_name_pent.string):""; + ring = (cl.playerview[SP].stats[STAT_ITEMS] & IT_INVISIBILITY) ?va("^xff0%s", tp_name_ring.string):""; + + if (*quad || *pent || *ring) + { + Q_snprintfz (macro_buf, 32, "{^s%s%s%s^r}", quad, pent, ring); + return macro_buf; + } + else + return ""; +} +char *Macro_Coloured_Short_Powerups(void) +{ + char *quad, *pent, *ring; + quad = (cl.playerview[SP].stats[STAT_ITEMS] & IT_QUAD) ?"^x03fq":""; + pent = (cl.playerview[SP].stats[STAT_ITEMS] & IT_INVULNERABILITY) ?"^xe00p":""; + ring = (cl.playerview[SP].stats[STAT_ITEMS] & IT_INVISIBILITY) ?"^xff0r":""; + + if (*quad || *pent || *ring) + { + Q_snprintfz (macro_buf, 32, "{^s%s%s%s^r}", quad, pent, ring); + return macro_buf; + } + else + return ""; +} +char *Macro_LastIP(void) +{ + return "---"; +} +char *Macro_MP3Info(void) +{ + return "---"; +} +char *Macro_Match_Status(void) +{ + return "---"; +} +char *Macro_LastTrigger_Match(void) +{ + return "---"; +} + /* $matchname you can use to get the name of the match @@ -1132,19 +1191,19 @@ static void TP_InitMacros(void) Cmd_AddMacro("droploc", Macro_LastDrop, true); Cmd_AddMacro("droptime", Macro_LastDropTime, true); -// Cmd_AddMacro("matchstatus", Macro_Match_Status, false); -// Cmd_AddMacro("mp3info", , false); -// Cmd_AddMacro("triggermatch", Macro_LastTrigger_Match, false); + Cmd_AddMacro("matchstatus", Macro_Match_Status, false); + Cmd_AddMacro("mp3info", Macro_MP3Info, false); + Cmd_AddMacro("triggermatch", Macro_LastTrigger_Match, false); //new, fte only (at least when first implemented) Cmd_AddMacro("chealth", Macro_CombinedHealth, true); //added for ezquake compatability -// Cmd_AddMacro("lastip", Macro_LastIP, false); + Cmd_AddMacro("lastip", Macro_LastIP, false); Cmd_AddMacro("ping", Macro_Latency, false); -// Cmd_AddMacro("colored_armor", Macro_Coloured_Armour, true); //*shudder* -// Cmd_AddMacro("colored_powerups", Macro_Coloured_Powerups, true); -// Cmd_AddMacro("colored_short_powerups", Macro_Coloured_Short_Powerups, true); + Cmd_AddMacro("colored_armor", Macro_Coloured_Armour, true); //*shudder* + Cmd_AddMacro("colored_powerups", Macro_Coloured_Powerups, true); + Cmd_AddMacro("colored_short_powerups", Macro_Coloured_Short_Powerups, true); Cmd_AddMacro("gamedir", Macro_Gamedir, false); Cmd_AddMacro("lastloc", Macro_Last_Location, true); Cmd_AddMacro("lastpowerup", Macro_LastSeenPowerup, true); @@ -2614,7 +2673,10 @@ static void TP_FindModelNumbers (void) continue; for (j=0, item=tp_items ; jmodelname)) + { model2item[i] = item; + break; + } } } @@ -2945,7 +3007,7 @@ more: } qboolean R_CullSphere (vec3_t org, float radius); -static qboolean TP_IsItemVisible(item_vis_t *visitem) +static qboolean TP_IsItemVisible(item_vis_t *visitem) //BE sure that pmove.skipent is set correctly first { vec3_t end, v; trace_t trace; @@ -2956,8 +3018,6 @@ static qboolean TP_IsItemVisible(item_vis_t *visitem) if (R_CullSphere(visitem->entorg, visitem->radius)) return false; - pmove.skipent = -1; - VectorNegate (visitem->dir, v); VectorNormalize (v); VectorMA (visitem->entorg, visitem->radius, v, end); @@ -3119,6 +3179,7 @@ static void TP_FindPoint (void) player_info_t *info, *bestinfo = NULL; item_vis_t visitem; extern cvar_t v_viewheight; + int oldskip = pmove.skipent; if (vars.pointtime == realtime) return; @@ -3126,6 +3187,8 @@ static void TP_FindPoint (void) if (!cl.validsequence) goto nothing; + pmove.skipent = cl.playerview[SP].viewentity; + ang[0] = cl.playerview[SP].viewangles[0]; ang[1] = cl.playerview[SP].viewangles[1]; ang[2] = 0; AngleVectors (ang, visitem.forward, visitem.right, visitem.up); VectorCopy (cl.playerview[SP].simorg, visitem.vieworg); @@ -3149,12 +3212,9 @@ static void TP_FindPoint (void) // special check for armors if (item->itemflag == (it_ra|it_ya|it_ga)) { - switch (ent->skinnum) - { - case 0: if (!(pointflags_dmm & it_ga)) continue; - case 1: if (!(pointflags_dmm & it_ya)) continue; - default: if (!(pointflags_dmm & it_ra)) continue; - } + item += 1 + bound(0, ent->skinnum, 2); + if (!(item->itemflag & pointflags_dmm)) + continue; } VectorAdd (ent->origin, item->offset, visitem.entorg); @@ -3266,13 +3326,7 @@ static void TP_FindPoint (void) if (!bestitem->cvar) { - // armors are special - switch (bestent->skinnum) - { - case 0: p = tp_name_ga.string; break; - case 1: p = tp_name_ya.string; break; - default: p = tp_name_ra.string; - } + p = tp_name_nothing.string; } else { @@ -3291,6 +3345,7 @@ nothing: vars.pointtype = POINT_TYPE_ITEM; } vars.pointtime = realtime; + pmove.skipent = oldskip; } diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 26ca148b0..579f3cd33 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -48,7 +48,8 @@ typedef struct cmdalias_s cmdalias_t *cmd_alias; -cvar_t cfg_save_all = CVARFD("cfg_save_all", "", CVAR_ARCHIVE|CVAR_NOTFROMSERVER, "If 1, cfg_save ALWAYS saves all cvars. If 0, cfg_save only ever saves archived cvars. If empty, cfg_saves all cvars only when an explicit filename was given."); +cvar_t cfg_save_all = CVARFD("cfg_save_all", "", CVAR_ARCHIVE|CVAR_NOTFROMSERVER, "If 1, cfg_save ALWAYS saves all cvars. If 0, cfg_save only ever saves archived cvars. If empty, cfg_save saves all cvars only when an explicit filename was given (ie: when not used internally via quit menu options)."); +cvar_t cfg_save_auto = CVARFD("cfg_save_auto", "0", CVAR_ARCHIVE|CVAR_NOTFROMSERVER, "If 1, the config will automatically be saved and without prompts. If 0, you'll have to save your config manually (possibly via prompts from the quit menu)."); cvar_t cl_warncmd = CVARF("cl_warncmd", "1", CVAR_NOSAVE|CVAR_NORESET); cvar_t cl_aliasoverlap = CVARF("cl_aliasoverlap", "1", CVAR_NOTFROMSERVER); @@ -2396,7 +2397,27 @@ const char *If_Token(const char *func, const char **end) while(*func <= ' ' && *func) func++; - s = COM_ParseToken(func, IFPUNCT); + if (*func == '\'') + { + char *o = com_token; + func++; + while (*func) + { + if (*func == '\'') + { + func++; + break; + } + + if (o < com_token + sizeof(com_token)-1) + *o++ = *func; + func++; + } + *o = 0; + s = func; + } + else + s = COM_ParseToken(func, IFPUNCT); if (*com_token == '(') { @@ -3280,6 +3301,7 @@ void Cmd_Init (void) Cmd_AddCommand ("set", Cmd_set_f); Cmd_AddCommand ("setfl", Cmd_set_f); Cmd_AddCommand ("set_calc", Cmd_set_f); + Cmd_AddCommand ("set_tp", Cmd_set_f); Cmd_AddCommand ("seta", Cmd_set_f); Cmd_AddCommand ("seta_calc", Cmd_set_f); Cmd_AddCommand ("vstr", Cmd_Vstr_f); diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 48480d48a..802a6da10 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -1768,6 +1768,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in meshcache.vbo.svector = inf->vbo_skel_svector; meshcache.vbo.tvector = inf->vbo_skel_tvector; meshcache.vbo.colours[0] = inf->vborgba; + meshcache.vbo.colours_bytes = !!inf->ofs_rgbaub; memset(&meshcache.vbo.bonenums, 0, sizeof(meshcache.vbo.bonenums)); memset(&meshcache.vbo.boneweights, 0, sizeof(meshcache.vbo.boneweights)); meshcache.vbo.numbones = 0; @@ -1835,6 +1836,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in meshcache.vbo.svector = inf->vbo_skel_svector; meshcache.vbo.tvector = inf->vbo_skel_tvector; meshcache.vbo.colours[0] = inf->vborgba; + meshcache.vbo.colours_bytes = !!inf->ofs_rgbaub; meshcache.vbo.bonenums = inf->vbo_skel_bonenum; meshcache.vbo.boneweights = inf->vbo_skel_bweight; meshcache.vbo.numbones = inf->numbones; diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index be8f26555..db411c15d 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -4274,6 +4274,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole Q_snprintfz (name, sizeof(name), "*%i:%s", i, wmod->name); mod = Mod_FindName (name); *mod = *wmod; + mod->entities = NULL; mod->submodelof = wmod; Q_strncpyz(mod->name, name, sizeof(mod->name)); memset(&mod->memgroup, 0, sizeof(mod->memgroup)); diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 2f3f666a5..37f01cf13 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -269,25 +269,18 @@ if (sides == 0) void VVPerpendicularVector(vec3_t dst, const vec3_t src) { - if (!src[0]) + if (!src[0] && !src[1]) { - dst[0] = 1; - dst[1] = dst[2] = 0; - } - else if (!src[1]) - { - dst[1] = 1; + if (src[2]) + dst[1] = -1; + else + dst[1] = 0; dst[0] = dst[2] = 0; } - else if (!src[2]) - { - dst[2] = 1; - dst[0] = dst[1] = 0; - } else { - dst[0] = -src[1]; - dst[1] = src[0]; + dst[0] = src[1]; + dst[1] = -src[0]; dst[2] = 0; VectorNormalize(dst); } diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c index bc2c0d1bf..8fbef4a69 100644 --- a/engine/common/pr_bgcmd.c +++ b/engine/common/pr_bgcmd.c @@ -4480,6 +4480,17 @@ void QCBUILTIN PF_anglemod (pubprogfuncs_t *prinst, struct globalvars_s *pr_glob G_FLOAT(OFS_RETURN) = v; } +//void(vector dir) vectorvectors +//Writes new values for v_forward, v_up, and v_right based on the given forward vector +void QCBUILTIN PF_vectorvectors (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *world = prinst->parms->user; + + VectorCopy(G_VECTOR(OFS_PARM0), world->g.v_forward); + VectorNormalize(world->g.v_forward); + VectorVectors(world->g.v_forward, world->g.v_right, world->g.v_up); +} + //Maths functions //////////////////////////////////////////////////// /* diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index d9d94a758..897670c66 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -103,6 +103,7 @@ void QCBUILTIN PF_rint (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void QCBUILTIN PF_floor (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_ceil (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_anglemod (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); +void QCBUILTIN PF_vectorvectors (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_Tokenize (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_tokenizebyseparator (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); void QCBUILTIN PF_tokenize_console (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals); diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 44395c802..4643b976a 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -1216,6 +1216,7 @@ typedef struct q1usercmd_s #define RDF_WATERWARP (1u<<18) #define RDF_CUSTOMPOSTPROC (1u<<19) #define RDF_ANTIALIAS (1u<<20) //fxaa, or possibly even just fsaa +#define RDF_RENDERSCALE (1u<<21) #define RDF_ALLPOSTPROC (RDF_BLOOM|RDF_FISHEYE|RDF_WATERWARP|RDF_CUSTOMPOSTPROC|RDF_ANTIALIAS) //these flags require rendering to an fbo for the various different post-processing shaders. diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index 7e22c0dd6..9df993162 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -663,7 +663,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="../libs/speex,..\client,../libs/freetype2/include,../common,../server,../gl,../sw,../qclib,../libs,../libs/dxsdk7/include" - PreprocessorDefinitions="_DEBUG;GLQUAKE;WIN32;_WINDOWS;MULTITHREAD;BOTLIB_STATIC;USE_MSVCRT_DEBUG" + PreprocessorDefinitions="_DEBUG;GLQUAKE;WIN32;_WINDOWS;MULTITHREAD;BOTLIB_STATIC;USE_MSVCRT_DEBUG;GLSLONLY" BasicRuntimeChecks="3" SmallerTypeCheck="true" RuntimeLibrary="1" diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 05e22978d..0b2084ecf 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -94,6 +94,8 @@ struct { union programhandle_u allblackshader; int allblack_mvp; + program_t *programfixedemu[8]; + qboolean initeddepthnorm; const shader_t *depthnormshader; texid_t tex_normals; @@ -128,7 +130,6 @@ struct { batch_t dummybatch; vbo_t dummyvbo; - int colourarraytype; int currentvbo; int currentebo; int currentvao; @@ -139,6 +140,7 @@ struct { float modelmatrixinv[16]; float modelviewmatrix[16]; + int colourarraytype; vec4_t pendingcolourflat; int pendingcolourvbo; void *pendingcolourpointer; @@ -531,6 +533,7 @@ static void BE_ApplyAttributes(unsigned int bitstochange, unsigned int bitstoend { unsigned int i; +#ifndef GLSLONLY //legacy colour attribute (including flat shaded) if ((bitstochange) & (1u<colours[0].gl.addr) + if (!shaderstate.pendingcolourvbo && !shaderstate.pendingcolourpointer) { shaderstate.sha_attr &= ~(1u<colours[0].gl.vbo); - qglVertexAttribPointer(VATTR_COLOUR, 4, shaderstate.colourarraytype, ((shaderstate.colourarraytype==GL_FLOAT)?GL_FALSE:GL_TRUE), 0, shaderstate.sourcevbo->colours[0].gl.addr); + GL_SelectVBO(shaderstate.pendingcolourvbo); + qglVertexAttribPointer(VATTR_COLOUR, 4, shaderstate.colourarraytype, ((shaderstate.colourarraytype==GL_FLOAT)?GL_FALSE:GL_TRUE), 0, shaderstate.pendingcolourpointer); break; #if MAXRLIGHTMAPS > 1 case VATTR_COLOUR2: @@ -847,7 +851,7 @@ void GLBE_SetupVAO(vbo_t *vbo, unsigned int vaodynamic, unsigned int vaostatic) shaderstate.sourcevbo = vbo; shaderstate.pendingvertexvbo = shaderstate.sourcevbo->coord.gl.vbo; shaderstate.pendingvertexpointer = shaderstate.sourcevbo->coord.gl.addr; - shaderstate.colourarraytype = GL_FLOAT; + shaderstate.colourarraytype = shaderstate.sourcevbo->colours_bytes?GL_UNSIGNED_BYTE:GL_FLOAT; shaderstate.pendingtexcoordvbo[0] = shaderstate.sourcevbo->texcoord.gl.vbo; shaderstate.pendingtexcoordpointer[0] = shaderstate.sourcevbo->texcoord.gl.addr; shaderstate.pendingtexcoordparts[0] = 2; @@ -1424,7 +1428,7 @@ void GLBE_Init(void) memset(&shaderstate, 0, sizeof(shaderstate)); shaderstate.curentity = &r_worldentity; - be_maxpasses = gl_mtexarbable; + be_maxpasses = gl_config_nofixedfunc?1:gl_mtexarbable; gl_stencilbits = 0; if (gl_config.glversion >= 3.0 && gl_config_nofixedfunc) { @@ -1526,9 +1530,13 @@ void GLBE_Init(void) #define MAX_ARRAY_VERTS 65535 static vecV_t vertexarray[MAX_ARRAY_VERTS]; -#ifndef GLSLONLY +#if 1//ndef GLSLONLY static avec4_t coloursarray[MAX_ARRAY_VERTS]; +#ifdef FTE_TARGET_WEB +static float texcoordarray[1][MAX_ARRAY_VERTS*2]; +#else static float texcoordarray[SHADER_PASS_MAX][MAX_ARRAY_VERTS*2]; +#endif /*========================================== texture coord generation =====================================*/ @@ -2302,7 +2310,7 @@ static void GenerateVertexDeforms(const shader_t *shader) shaderstate.pendingvertexvbo = 0; } -#ifndef GLSLONLY +#if 1//ndef GLSLONLY /*======================================alpha ===============================*/ @@ -2419,10 +2427,11 @@ static void GenerateColourMods(const shaderpass_t *pass) mesh_t *meshlist; meshlist = shaderstate.meshes[0]; - if (pass->flags & SHADER_PASS_NOCOLORARRAY && qglColor4fv) + if (pass->flags & SHADER_PASS_NOCOLORARRAY) { colourgen(pass, 1, meshlist->colors4f_array[0], &shaderstate.pendingcolourflat, meshlist); alphagen(pass, 1, meshlist->colors4f_array[0], &shaderstate.pendingcolourflat, meshlist); + shaderstate.colourarraytype = 0; shaderstate.pendingcolourvbo = 0; shaderstate.pendingcolourpointer = NULL; } @@ -2435,6 +2444,7 @@ static void GenerateColourMods(const shaderpass_t *pass) { shaderstate.pendingcolourflat[0] = shaderstate.pendingcolourflat[1] = shaderstate.pendingcolourflat[2] = 0; alphagen(pass, 1, meshlist->colors4f_array[0], &shaderstate.pendingcolourflat, meshlist); + shaderstate.colourarraytype = 0; shaderstate.pendingcolourvbo = 0; shaderstate.pendingcolourpointer = NULL; return; @@ -2443,6 +2453,7 @@ static void GenerateColourMods(const shaderpass_t *pass) { shaderstate.pendingcolourflat[0] = shaderstate.pendingcolourflat[1] = shaderstate.pendingcolourflat[2] = 1; alphagen(pass, 1, meshlist->colors4f_array[0], &shaderstate.pendingcolourflat, meshlist); + shaderstate.colourarraytype = 0; shaderstate.pendingcolourvbo = 0; shaderstate.pendingcolourpointer = NULL; return; @@ -2451,6 +2462,7 @@ static void GenerateColourMods(const shaderpass_t *pass) { VectorCopy(shaderstate.curentity->light_avg, shaderstate.pendingcolourflat); shaderstate.pendingcolourflat[3] = shaderstate.curentity->shaderRGBAf[3]; + shaderstate.colourarraytype = 0; shaderstate.pendingcolourvbo = 0; shaderstate.pendingcolourpointer = NULL; return; @@ -2460,6 +2472,7 @@ static void GenerateColourMods(const shaderpass_t *pass) //if its vetex lighting, just use the vbo if (((pass->rgbgen == RGB_GEN_VERTEX_LIGHTING && shaderstate.identitylighting == 1) || pass->rgbgen == RGB_GEN_VERTEX_EXACT) && pass->alphagen == ALPHA_GEN_VERTEX) { + shaderstate.colourarraytype = shaderstate.sourcevbo->colours_bytes?GL_UNSIGNED_BYTE:GL_FLOAT; shaderstate.pendingcolourvbo = shaderstate.sourcevbo->colours[0].gl.vbo; shaderstate.pendingcolourpointer = shaderstate.sourcevbo->colours[0].gl.addr; return; @@ -3214,6 +3227,12 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm, case SP_E_COLOURS: qglUniform4fvARB(ph, 1, (GLfloat*)shaderstate.curentity->shaderRGBAf); break; + case SP_S_COLOUR: + if (shaderstate.colourarraytype) + qglUniform4fARB(ph, 1, 1, 1, 1); //invalid use + else + qglUniform4fvARB(ph, 1, (GLfloat*)shaderstate.pendingcolourflat); + break; case SP_E_COLOURSIDENT: if (shaderstate.flags & BEF_FORCECOLOURMOD) qglUniform4fvARB(ph, 1, (GLfloat*)shaderstate.curentity->shaderRGBAf); @@ -3383,9 +3402,8 @@ static void BE_Program_Set_Attributes(const program_t *prog, unsigned int perm, } } -static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pass) +static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pass, program_t *p) { - program_t *p = shader->prog; int i; int perm; @@ -3449,17 +3467,6 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas else #endif { -#ifndef GLSLONLY - if (0)//pass->numtcmods) - GenerateTCMods(pass, 0); - else -#endif - { - shaderstate.pendingtexcoordparts[0] = 2; - shaderstate.pendingtexcoordvbo[0] = shaderstate.sourcevbo->texcoord.gl.vbo; - shaderstate.pendingtexcoordpointer[0] = shaderstate.sourcevbo->texcoord.gl.addr; - } - for (i = 0; i < pass->numMergedPasses; i++) { Shader_BindTextureForPass(i, pass+i); @@ -4001,7 +4008,15 @@ static void DrawMeshes(void) if (!altshader) altshader = shaderstate.shader_light[shaderstate.lightmode]; if (altshader && altshader->prog) - BE_RenderMeshProgram(altshader, altshader->passes); + { + shaderstate.pendingcolourvbo = shaderstate.sourcevbo->colours[0].gl.vbo; + shaderstate.pendingcolourpointer = shaderstate.sourcevbo->colours[0].gl.addr; + shaderstate.colourarraytype = shaderstate.sourcevbo->colours_bytes?GL_UNSIGNED_BYTE:GL_FLOAT; + shaderstate.pendingtexcoordparts[0] = 2; + shaderstate.pendingtexcoordvbo[0] = shaderstate.sourcevbo->texcoord.gl.vbo; + shaderstate.pendingtexcoordpointer[0] = shaderstate.sourcevbo->texcoord.gl.addr; + BE_RenderMeshProgram(altshader, altshader->passes, altshader->prog); + } #ifndef GLSLONLY else BE_LegacyLighting(); @@ -4012,7 +4027,15 @@ static void DrawMeshes(void) if (!altshader) altshader = shaderstate.depthnormshader; if (altshader && altshader->prog) - BE_RenderMeshProgram(altshader, altshader->passes); + { + shaderstate.pendingcolourvbo = shaderstate.sourcevbo->colours[0].gl.vbo; + shaderstate.pendingcolourpointer = shaderstate.sourcevbo->colours[0].gl.addr; + shaderstate.colourarraytype = shaderstate.sourcevbo->colours_bytes?GL_UNSIGNED_BYTE:GL_FLOAT; + shaderstate.pendingtexcoordparts[0] = 2; + shaderstate.pendingtexcoordvbo[0] = shaderstate.sourcevbo->texcoord.gl.vbo; + shaderstate.pendingtexcoordpointer[0] = shaderstate.sourcevbo->texcoord.gl.addr; + BE_RenderMeshProgram(altshader, altshader->passes, altshader->prog); + } break; #endif case BEM_CREPUSCULAR: @@ -4023,7 +4046,15 @@ static void DrawMeshes(void) altshader = shaderstate.crepopaqueshader; if (altshader && altshader->prog) - BE_RenderMeshProgram(altshader, altshader->passes); + { + shaderstate.pendingcolourvbo = shaderstate.sourcevbo->colours[0].gl.vbo; + shaderstate.pendingcolourpointer = shaderstate.sourcevbo->colours[0].gl.addr; + shaderstate.colourarraytype = shaderstate.sourcevbo->colours_bytes?GL_UNSIGNED_BYTE:GL_FLOAT; + shaderstate.pendingtexcoordparts[0] = 2; + shaderstate.pendingtexcoordvbo[0] = shaderstate.sourcevbo->texcoord.gl.vbo; + shaderstate.pendingtexcoordpointer[0] = shaderstate.sourcevbo->texcoord.gl.addr; + BE_RenderMeshProgram(altshader, altshader->passes, altshader->prog); + } break; case BEM_DEPTHONLY: altshader = shaderstate.curshader->bemoverrides[bemoverride_depthonly]; @@ -4031,7 +4062,15 @@ static void DrawMeshes(void) altshader = shaderstate.depthonlyshader; if (altshader && altshader->prog) - BE_RenderMeshProgram(altshader, altshader->passes); + { + shaderstate.pendingcolourvbo = shaderstate.sourcevbo->colours[0].gl.vbo; + shaderstate.pendingcolourpointer = shaderstate.sourcevbo->colours[0].gl.addr; + shaderstate.colourarraytype = shaderstate.sourcevbo->colours_bytes?GL_UNSIGNED_BYTE:GL_FLOAT; + shaderstate.pendingtexcoordparts[0] = 2; + shaderstate.pendingtexcoordvbo[0] = shaderstate.sourcevbo->texcoord.gl.vbo; + shaderstate.pendingtexcoordpointer[0] = shaderstate.sourcevbo->texcoord.gl.addr; + BE_RenderMeshProgram(altshader, altshader->passes, altshader->prog); + } else { GL_DeSelectProgram(); @@ -4132,13 +4171,89 @@ static void DrawMeshes(void) default: if (shaderstate.curshader->prog) { - BE_RenderMeshProgram(shaderstate.curshader, shaderstate.curshader->passes); + shaderstate.pendingcolourvbo = shaderstate.sourcevbo->colours[0].gl.vbo; + shaderstate.pendingcolourpointer = shaderstate.sourcevbo->colours[0].gl.addr; + shaderstate.colourarraytype = shaderstate.sourcevbo->colours_bytes?GL_UNSIGNED_BYTE:GL_FLOAT; + + shaderstate.pendingtexcoordparts[0] = 2; + shaderstate.pendingtexcoordvbo[0] = shaderstate.sourcevbo->texcoord.gl.vbo; + shaderstate.pendingtexcoordpointer[0] = shaderstate.sourcevbo->texcoord.gl.addr; + + BE_RenderMeshProgram(shaderstate.curshader, shaderstate.curshader->passes, shaderstate.curshader->prog); } -#ifdef GLSLONLY - break; -#else else if (gl_config_nofixedfunc) + { +#ifdef FTE_TARGET_WEB + int maxverts = 0, m; + mesh_t *meshlist; + for (m = 0; m < shaderstate.meshcount; m++) + { + meshlist = shaderstate.meshes[m]; + if (maxverts < meshlist->vbofirstvert + meshlist->numvertexes) + maxverts = meshlist->vbofirstvert + meshlist->numvertexes; + } +#endif + + while (passno < shaderstate.curshader->numpasses) + { + int emumode; + p = &shaderstate.curshader->passes[passno]; + passno += p->numMergedPasses; + + emumode = 0; + emumode = (p->shaderbits & SBITS_ATEST_BITS) >> SBITS_ATEST_SHIFT; + + GenerateColourMods(p); + if (!shaderstate.colourarraytype) + { + emumode |= 4; + shaderstate.lastuniform = 0; //FIXME: s_colour uniform might be wrong. + } +#ifdef FTE_TARGET_WEB + else if (!shaderstate.pendingcolourvbo && shaderstate.pendingcolourpointer) + { + shaderstate.streamid = (shaderstate.streamid + 1) & (sizeof(shaderstate.streamvbo)/sizeof(shaderstate.streamvbo[0]) - 1); + GL_SelectVBO(shaderstate.pendingcolourvbo = shaderstate.streamvbo[shaderstate.streamid]); + switch(shaderstate.colourarraytype) + { + case GL_FLOAT: + qglBufferDataARB(GL_ARRAY_BUFFER_ARB, maxverts * sizeof(vec4_t), shaderstate.pendingcolourpointer, GL_STREAM_DRAW_ARB); + break; + case GL_UNSIGNED_BYTE: + qglBufferDataARB(GL_ARRAY_BUFFER_ARB, maxverts * sizeof(byte_vec4_t), shaderstate.pendingcolourpointer, GL_STREAM_DRAW_ARB); + break; + } + shaderstate.pendingcolourpointer = NULL; + } +#endif + + BE_GeneratePassTC(p, 0); +#ifdef FTE_TARGET_WEB + if (!shaderstate.pendingtexcoordvbo[0] && shaderstate.pendingtexcoordpointer[0]) + { + shaderstate.streamid = (shaderstate.streamid + 1) & (sizeof(shaderstate.streamvbo)/sizeof(shaderstate.streamvbo[0]) - 1); + GL_SelectVBO(shaderstate.pendingtexcoordvbo[0] = shaderstate.streamvbo[shaderstate.streamid]); + qglBufferDataARB(GL_ARRAY_BUFFER_ARB, maxverts * sizeof(float) * shaderstate.pendingtexcoordparts[0], shaderstate.pendingtexcoordpointer[0], GL_STREAM_DRAW_ARB); + shaderstate.pendingtexcoordpointer[0] = NULL; + } +#endif + + if (!shaderstate.programfixedemu[emumode]) + { + char *modes[] = { + "","#ALPHATEST=>0.0","#ALPHATEST=<0.5","#ALPHATEST=>=0.5", + "#UC","#ALPHATEST=>0.0#UC","#ALPHATEST=<0.5#UC","#ALPHATEST=>=0.5#UC" + }; + shaderstate.programfixedemu[emumode] = Shader_FindGeneric(va("fixedemu%s", modes[emumode]), QR_OPENGL); + if (!shaderstate.programfixedemu[emumode]) + break; + } + + BE_RenderMeshProgram(shaderstate.curshader, p, shaderstate.programfixedemu[emumode]); + } break; + } +#ifndef GLSLONLY else { GL_DeSelectProgram(); @@ -4247,7 +4362,7 @@ static qboolean BE_GenTempMeshVBO(vbo_t **vbo, mesh_t *m) shaderstate.dummyvbo.colours[0].gl.addr = (void*)len; shaderstate.dummyvbo.colours[0].gl.vbo = shaderstate.streamvbo[shaderstate.streamid]; len += sizeof(*m->colors4f_array[0]) * m->numvertexes; - shaderstate.colourarraytype = GL_FLOAT; + shaderstate.dummyvbo.colours_bytes = false; } else if (m->colors4b_array) { @@ -4255,13 +4370,13 @@ static qboolean BE_GenTempMeshVBO(vbo_t **vbo, mesh_t *m) shaderstate.dummyvbo.colours[0].gl.addr = (void*)len; shaderstate.dummyvbo.colours[0].gl.vbo = shaderstate.streamvbo[shaderstate.streamid]; len += sizeof(*m->colors4b_array) * m->numvertexes; - shaderstate.colourarraytype = GL_UNSIGNED_BYTE; + shaderstate.dummyvbo.colours_bytes = true; } else { shaderstate.dummyvbo.colours[0].gl.addr = NULL; shaderstate.dummyvbo.colours[0].gl.vbo = 0; - shaderstate.colourarraytype = GL_FLOAT; + shaderstate.dummyvbo.colours_bytes = false; } if (m->normals_array) @@ -4327,12 +4442,12 @@ static qboolean BE_GenTempMeshVBO(vbo_t **vbo, mesh_t *m) shaderstate.dummyvbo.tvector.gl.addr = m->tnormals_array; if (m->colors4f_array[0]) { - shaderstate.colourarraytype = GL_FLOAT; + shaderstate.dummyvbo.colours_bytes = false; shaderstate.dummyvbo.colours[0].gl.addr = m->colors4f_array[0]; } else { - shaderstate.colourarraytype = GL_UNSIGNED_BYTE; + shaderstate.dummyvbo.colours_bytes = true; shaderstate.dummyvbo.colours[0].gl.addr = m->colors4b_array; } shaderstate.dummyvbo.bonenums.gl.addr = m->bonenums; @@ -4381,7 +4496,6 @@ void GLBE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_ else { shaderstate.sourcevbo = vbo; - shaderstate.colourarraytype = GL_FLOAT; shaderstate.flags = beflags; if (shaderstate.curentity != &r_worldentity) GLBE_SelectEntity(&r_worldentity); @@ -4411,7 +4525,6 @@ void GLBE_SubmitBatch(batch_t *batch) if (batch->vbo) { shaderstate.sourcevbo = batch->vbo; - shaderstate.colourarraytype = GL_FLOAT; if (!batch->vbo->vao) batch->vbo->vao = shaderstate.streamvao[0]; diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index ef0f346f8..49dc2e105 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -1078,6 +1078,26 @@ qbyte default_conchar[/*11356*/] = #include "lhfont.h" }; +static void Font_CopyGlyph(int src, int dst, void *data) +{ + int glyphsize = 16; + int y; + int x; + char *srcptr = (char*)data + (src&15)*glyphsize*4 + (src>>4)*glyphsize*256*4; + char *dstptr = (char*)data + (dst&15)*glyphsize*4 + (dst>>4)*glyphsize*256*4; + for (y = 0; y < glyphsize; y++) + { + for (x = 0; x < glyphsize; x++) + { + dstptr[x*4+0] = srcptr[x*4+0]; + dstptr[x*4+1] = srcptr[x*4+1]; + dstptr[x*4+2] = srcptr[x*4+2]; + dstptr[x*4+3] = srcptr[x*4+3]; + } + dstptr += 256*4; + srcptr += 256*4; + } +} static texid_t Font_LoadFallbackConchars(void) { texid_t tex; @@ -1096,6 +1116,13 @@ static texid_t Font_LoadFallbackConchars(void) lump[i*4+1] = 255; lump[i*4+2] = 255; } + if (width == 256 && height == 256) + { //make up some scroll-bar/download-progress-bar chars, so that webgl doesn't look so buggy with the initial pak file(s). + Font_CopyGlyph('[', 128, lump); + Font_CopyGlyph('-', 129, lump); + Font_CopyGlyph(']', 130, lump); + Font_CopyGlyph('o', 131, lump); + } tex = R_LoadTexture32("charset", width, height, (void*)lump, IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA); BZ_Free(lump); return tex; diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index a033ab415..f6658dfde 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -268,6 +268,7 @@ typedef struct vbo_s vboarray_t svector; vboarray_t tvector; + qboolean colours_bytes; vboarray_t colours[MAXRLIGHTMAPS]; vboarray_t bonenums; diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index c0edf04e7..c4fdd63ab 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -410,7 +410,7 @@ void R_SetupGL (float stereooffset) // // set up viewpoint // - if (r_refdef.flags & (RDF_ALLPOSTPROC)) + if (r_refdef.flags & (RDF_ALLPOSTPROC|RDF_RENDERSCALE)) { //with fbo postprocessing, we disable all viewport. r_refdef.pxrect.x = 0; @@ -1156,11 +1156,9 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2], { qglMatrixMode(GL_PROJECTION); qglLoadMatrixf(r_refdef.m_projection); - - //portals to mask are relative to the old view still. - qglMatrixMode(GL_MODELVIEW); - qglLoadMatrixf(r_refdef.m_view); } + //portals to mask are relative to the old view still. + GLBE_SelectEntity(&r_worldentity); currententity = NULL; if (gl_config.arb_depth_clamp) qglEnable(GL_DEPTH_CLAMP_ARB); //ignore the near clip plane(ish), this means nearer portals can still mask further ones. @@ -1198,8 +1196,8 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2], r_refdef.flipcull &= ~SHADER_CULL_FLIP; if (r_refdef.m_projection[5]<0) r_refdef.flipcull ^= SHADER_CULL_FLIP; - GL_CullFace(0);//make sure flipcull takes effect + r_framecount++; //FIXME: just call Surf_DrawWorld instead? R_RenderScene(); // if (qglClipPlane) @@ -1229,10 +1227,8 @@ void GLR_DrawPortal(batch_t *batch, batch_t **blist, batch_t *depthmasklist[2], /*put GL back the way it was*/ qglMatrixMode(GL_PROJECTION); qglLoadMatrixf(r_refdef.m_projection); - - qglMatrixMode(GL_MODELVIEW); - qglLoadMatrixf(r_refdef.m_view); } + GLBE_SelectEntity(&r_worldentity); GL_CullFace(0);//make sure flipcull reversion takes effect @@ -1815,11 +1811,13 @@ void GLR_RenderView (void) } else if ((r_refdef.flags & (RDF_ALLPOSTPROC)) || renderscale != 1) { + r_refdef.flags |= RDF_RENDERSCALE; + //the game needs to be drawn to a texture for post processing if (1)//vid.framebuffer) { vid.fbpwidth = (r_refdef.vrect.width * r_refdef.pxrect.width) / vid.width; - vid.fbpheight = (r_refdef.vrect.height * r_refdef.pxrect.width) / vid.height; + vid.fbpheight = (r_refdef.vrect.height * r_refdef.pxrect.height) / vid.height; } else { diff --git a/engine/gl/gl_screen.c b/engine/gl/gl_screen.c index dce08e0e5..884e4fe1f 100644 --- a/engine/gl/gl_screen.c +++ b/engine/gl/gl_screen.c @@ -248,6 +248,7 @@ char *GLVID_GetRGBInfo(int *truewidth, int *trueheight, enum uploadfmt *fmt) extern qboolean gammaworks; int i, c; qbyte *ret; + extern qboolean r2d_canhwgamma; *truewidth = vid.fbpwidth; *trueheight = vid.fbpheight; @@ -310,15 +311,29 @@ char *GLVID_GetRGBInfo(int *truewidth, int *trueheight, enum uploadfmt *fmt) qglReadPixels (0, 0, (*truewidth), (*trueheight), GL_RGB, GL_UNSIGNED_BYTE, ret); } - if (gammaworks) + if (gammaworks && r2d_canhwgamma) { - c = (*truewidth)*(*trueheight)*3; - for (i=0 ; itexgen == T_GEN_LIGHTMAP && pass->tcgen == TC_GEN_LIGHTMAP) lightmap = pass; + + /*if (pass->numtcmods || (pass->shaderbits & SBITS_ATEST_BITS)) + return; + if (pass->texgen == T_GEN_LIGHTMAP && pass->tcgen == TC_GEN_LIGHTMAP) + ; + else if (pass->texgen != T_GEN_LIGHTMAP && pass->tcgen == TC_GEN_BASE) + ; + else*/ + return; } if (modellighting) diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index e074c94d9..fd444a0ae 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -1120,6 +1120,9 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) qglGetDebugMessageLogARB = NULL; } #endif + + if (!gl_config.gles && gl_config_nofixedfunc) + qglDisableClientState(GL_VERTEX_ARRAY); } static const char *glsl_hdrs[] = diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index b8045f290..973f6b2a4 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -2017,34 +2017,34 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#ifdef FRAGMENT_SHADER\n" "#include \"sys/fog.h\"\n" -"uniform sampler2D s_t0; //diffuse\n" +"uniform sampler2D s_diffuse; //diffuse\n" "#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n" -"uniform sampler2D s_t1; //normalmap\n" +"uniform sampler2D s_normalmap; //normalmap\n" "#endif\n" "#ifdef SPECULAR\n" -"uniform sampler2D s_t2; //specular\n" +"uniform sampler2D s_specular; //specular\n" "#endif\n" "#ifdef CUBE\n" -"uniform samplerCube s_t3; //projected cubemap\n" +"uniform samplerCube s_projectionmap; //projected cubemap\n" "#endif\n" "#ifdef PCF\n" "#ifdef CUBESHADOW\n" -"uniform samplerCubeShadow s_t4; //shadowmap\n" +"uniform samplerCubeShadow s_shadowmap; //shadowmap\n" "#else\n" "#if 0//def GL_ARB_texture_gather\n" -"uniform sampler2D s_t4;\n" +"uniform sampler2D s_shadowmap;\n" "#else\n" -"uniform sampler2DShadow s_t4;\n" +"uniform sampler2DShadow s_shadowmap;\n" "#endif\n" "#endif\n" "#endif\n" "#ifdef LOWER\n" -"uniform sampler2D s_t5; //pants colours\n" +"uniform sampler2D s_lower; //pants colours\n" "uniform vec3 e_lowercolour;\n" "#endif\n" "#ifdef UPPER\n" -"uniform sampler2D s_t6; //shirt colours\n" +"uniform sampler2D s_upper; //shirt colours\n" "uniform vec3 e_uppercolour;\n" "#endif\n" @@ -2068,7 +2068,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "return ((vtexprojcoord.xyz-vec3(0.0,0.0,0.015))/vtexprojcoord.w + vec3(1.0, 1.0, 1.0)) * vec3(0.5, 0.5, 0.5);\n" //#elif defined(CUBESHADOW) // vec3 shadowcoord = vshadowcoord.xyz / vshadowcoord.w; -// #define dosamp(x,y) shadowCube(s_t4, shadowcoord + vec2(x,y)*texscale.xy).r +// #define dosamp(x,y) shadowCube(s_shadowmap, shadowcoord + vec2(x,y)*texscale.xy).r "#else\n" //figure out which axis to use //texture is arranged thusly: @@ -2113,7 +2113,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#if 0//def GL_ARB_texture_gather\n" "vec2 ipart, fpart;\n" -"#define dosamp(x,y) textureGatherOffset(s_t4, ipart.xy, vec2(x,y)))\n" +"#define dosamp(x,y) textureGatherOffset(s_shadowmap, ipart.xy, vec2(x,y)))\n" "vec4 tl = step(shadowcoord.z, dosamp(-1.0, -1.0));\n" "vec4 bl = step(shadowcoord.z, dosamp(-1.0, 1.0));\n" "vec4 tr = step(shadowcoord.z, dosamp(1.0, -1.0));\n" @@ -2128,10 +2128,10 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#else\n" "#ifdef USE_ARB_SHADOW\n" //with arb_shadow, we can benefit from hardware acclerated pcf, for smoother shadows -"#define dosamp(x,y) shadow2D(s_t4, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r\n" +"#define dosamp(x,y) shadow2D(s_shadowmap, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r\n" "#else\n" //this will probably be a bit blocky. -"#define dosamp(x,y) float(texture2D(s_t4, shadowcoord.xy + (vec2(x,y)*l_shadowmapscale.xy)).r >= shadowcoord.z)\n" +"#define dosamp(x,y) float(texture2D(s_shadowmap, shadowcoord.xy + (vec2(x,y)*l_shadowmapscale.xy)).r >= shadowcoord.z)\n" "#endif\n" "float s = 0.0;\n" "#if r_glsl_pcf >= 1 && r_glsl_pcf < 5\n" @@ -2169,25 +2169,29 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "{\n" //read raw texture samples (offsetmapping munges the tex coords first) "#ifdef OFFSETMAPPING\n" -"vec2 tcoffsetmap = offsetmap(s_t1, tcbase, eyevector);\n" +"vec2 tcoffsetmap = offsetmap(s_normalmap, tcbase, eyevector);\n" "#define tcbase tcoffsetmap\n" "#endif\n" -"vec3 bases = vec3(texture2D(s_t0, tcbase));\n" +"#if defined(FLAT)\n" +"vec3 bases = vec3(1.0);\n" +"#else\n" +"vec3 bases = vec3(texture2D(s_diffuse, tcbase));\n" +"#endif\n" "#ifdef UPPER\n" -"vec4 uc = texture2D(s_t6, tcbase);\n" +"vec4 uc = texture2D(s_upper, tcbase);\n" "bases.rgb += uc.rgb*e_uppercolour*uc.a;\n" "#endif\n" "#ifdef LOWER\n" -"vec4 lc = texture2D(s_t5, tcbase);\n" +"vec4 lc = texture2D(s_lower, tcbase);\n" "bases.rgb += lc.rgb*e_lowercolour*lc.a;\n" "#endif\n" "#if defined(BUMP) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n" -"vec3 bumps = normalize(vec3(texture2D(s_t1, tcbase)) - 0.5);\n" +"vec3 bumps = normalize(vec3(texture2D(s_normalmap, tcbase)) - 0.5);\n" "#elif defined(REFLECTCUBEMASK)\n" "vec3 bumps = vec3(0.0,0.0,1.0);\n" "#endif\n" "#ifdef SPECULAR\n" -"vec4 specs = texture2D(s_t2, tcbase);\n" +"vec4 specs = texture2D(s_specular, tcbase);\n" "#endif\n" "float colorscale = max(1.0 - (dot(lightvector, lightvector)/(l_lightradius*l_lightradius)), 0.0);\n" @@ -2221,7 +2225,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#ifdef CUBE\n" /*filter the colour by the cubemap projection*/ -"diff *= textureCube(s_t3, vtexprojcoord.xyz).rgb;\n" +"diff *= textureCube(s_projectionmap, vtexprojcoord.xyz).rgb;\n" "#endif\n" "#if defined(SPOT)\n" @@ -2239,7 +2243,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#if defined(PROJECTION)\n" /*2d projection, not used*/ -// diff *= texture2d(s_t3, shadowcoord); +// diff *= texture2d(s_projectionmap, shadowcoord); "#endif\n" "gl_FragColor.rgb = fog3additive(diff*colorscale*l_lightcolour);\n" @@ -2914,3 +2918,48 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" }, #endif +#ifdef GLQUAKE +{QR_OPENGL, 110, "fixedemu", +//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" +"varying vec2 tc;\n" +"#ifndef UC\n" +"attribute vec4 v_colour;\n" +"varying vec4 vc;\n" +"#endif\n" +"void main ()\n" +"{\n" +"tc = v_texcoord;\n" +"#ifndef UC\n" +"vc = v_colour;\n" +"#endif\n" +"gl_Position = ftetransform();\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"uniform sampler2D s_t0;\n" +"varying vec2 tc;\n" +"#ifndef UC\n" +"varying vec4 vc;\n" +"#else\n" +"uniform vec4 s_colour;\n" +"#define vc s_colour\n" +"#endif\n" +"float e_time;\n" +"void main ()\n" +"{\n" +"vec4 fc = texture2D(s_t0, tc) * vc;\n" +"#ifdef ALPHATEST\n" +"if (!(fc.a ALPHATEST))\n" +"discard;\n" +"#endif\n" +"gl_FragColor = fc;\n" +"}\n" +"#endif\n" +}, +#endif diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 2d1666d22..fc793f7e4 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -153,6 +153,7 @@ enum SBITS_ATEST_LT128 = 0x00002000, SBITS_ATEST_GE128 = 0x00003000, #define SBITS_ATEST_BITS 0x0000f000 +#define SBITS_ATEST_SHIFT 12 SBITS_MISC_DEPTHWRITE = 0x00010000, SBITS_MISC_NODEPTHTEST = 0x00020000, @@ -401,6 +402,8 @@ typedef struct { SP_RENDERTEXTURESCALE, /*multiplier for currentrender->texcoord*/ SP_SOURCESIZE, /*size of $sourcecolour*/ + SP_S_COLOUR, + SP_LIGHTRADIUS, /*these light values are realtime lighting*/ SP_LIGHTCOLOUR, SP_LIGHTCOLOURSCALE, @@ -630,6 +633,8 @@ void Shader_WriteOutGenerics_f(void); void Shader_RemapShader_f(void); void Shader_ShowShader_f(void); +program_t *Shader_FindGeneric(char *name, int qrtype); + mfog_t *Mod_FogForOrigin(model_t *wmodel, vec3_t org); #define BEF_FORCEDEPTHWRITE 1 diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index b6bf2992d..5980e0465 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -6500,17 +6500,6 @@ static void QCBUILTIN PF_sv_findchainflags (pubprogfuncs_t *prinst, struct globa RETURN_EDICT(prinst, chain); } -//EXTENSION: DP_QC_VECTORVECTORS - -//void(vector dir) vectorvectors = #432 -//Writes new values for v_forward, v_up, and v_right based on the given forward vector -static void QCBUILTIN PF_vectorvectors (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - VectorCopy(G_VECTOR(OFS_PARM0), P_VEC(v_forward)); - VectorNormalize(P_VEC(v_forward)); - VectorVectors(P_VEC(v_forward), P_VEC(v_right), P_VEC(v_up)); -} - //EXTENSION: KRIMZON_SV_PARSECLIENTCOMMAND //void(entity e, string s) clientcommand = #440 diff --git a/engine/shaders/generatebuiltinsl.c b/engine/shaders/generatebuiltinsl.c index 59f424683..beb584aa7 100644 --- a/engine/shaders/generatebuiltinsl.c +++ b/engine/shaders/generatebuiltinsl.c @@ -34,6 +34,7 @@ char shaders[][64] = "underwaterwarp", "menutint", "terrain", + "fixedemu", "" }; diff --git a/engine/web/gl_vidweb.c b/engine/web/gl_vidweb.c index d09129bca..a4242464b 100644 --- a/engine/web/gl_vidweb.c +++ b/engine/web/gl_vidweb.c @@ -108,7 +108,7 @@ static unsigned int domkeytoshift(unsigned int code) static int DOM_KeyEvent(int devid, int down, int scan, int uni) { extern int shift_down; -// Con_Printf("Key %i %i:%c\n", scan, uni, (char)uni); +// Con_Printf("Key %s %i %i:%c\n", down?"down":"up", scan, uni, uni?(char)uni:' '); if (shift_down) { uni = domkeytoshift(scan);