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);