From 257610c89f514c35b318c053922aaf792332ac0f Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 4 Aug 2015 15:16:24 +0000 Subject: [PATCH] add atlasing for wad images (batching means the entire regular hud can be a single draw call, assuming the ammo counts batch alongside show_fps). d3d9 renderer can now use all the model batching stuff I wrote for gl. fixed loading screens with d3d9 renderer. cl_deadbodyfilter cvar is now archived. autocam will avoid switching if the newly tracked player doesn't have anything interesting, etc. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4958 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/Makefile | 12 +- engine/client/cl_cam.c | 135 +++++++++++- engine/client/cl_main.c | 2 +- engine/client/cl_screen.c | 46 ++-- engine/client/m_options.c | 4 + engine/client/merged.h | 6 +- engine/client/pr_csqc.c | 18 +- engine/client/r_2d.c | 346 ++++++++++++++++++++++-------- engine/client/sbar.c | 244 +++++++++++---------- engine/client/wad.h | 41 ++-- engine/common/bothdefs.h | 4 +- engine/common/com_mesh.c | 5 +- engine/d3d/d3d_backend.c | 133 +++++++++++- engine/d3d/d3d_shader.c | 9 +- engine/d3d/vid_d3d.c | 10 +- engine/dotnet2005/ftequake.vcproj | 4 - engine/gl/gl_backend.c | 22 +- engine/gl/gl_font.c | 4 +- engine/gl/gl_model.c | 2 +- engine/gl/glquake.h | 3 +- engine/gl/r_bishaders.h | 82 +++++++ engine/qclib/qccgui.c | 4 + engine/server/sv_ents.c | 6 + engine/server/sv_user.c | 4 +- 24 files changed, 843 insertions(+), 303 deletions(-) diff --git a/engine/Makefile b/engine/Makefile index ff642af9b..0a44bf7f7 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -946,7 +946,7 @@ ifeq ($(FTE_TARGET),vc) CC=PATH="C:\Program Files (x86)\$(MSVCDIR)\Common7\IDE" "$(MSVCPATH)cl" $(SDKINC) $(MSVCINC) -D_CRT_SECURE_NO_WARNINGS DEBUG_CFLAGS ?= -Od $(CPUOPTIMIZATIONS) /fp:fast - PROFILE_CFLAGS = -O2 -Ot -Ox -GL $(CPUOPTIMISATIONS) /fp:fast + PROFILE_CFLAGS = -O2 -Ot -Ox -GL $(CPUOPTIMISATIONS) /fp:fast PROFILE_LDFLAGS = /LTCG:PGINSTRUMENT RELEASE_CFLAGS = -O2 -Ot -Ox -GL -GS- -Gr $(CPUOPTIMIZATIONS) /fp:fast RELEASE_LDFLAGS = /LTCG @@ -963,7 +963,7 @@ ifeq ($(FTE_TARGET),vc) BASE_CFLAGS:=$(WARNINGFLAGS) $(GNUC_FUNCS) -I$(shell cygpath -m $(CLIENT_DIR)) -I$(shell cygpath -m $(SERVER_DIR)) -I$(shell cygpath -m $(COMMON_DIR)) -I$(shell cygpath -m $(GL_DIR)) -I$(shell cygpath -m $(D3D_DIR)) -I$(shell cygpath -m $(PROGS_DIR)) -I. -I$(LIBS_DIR) -I$(LIBS_DIR)/dxsdk9/include -I$(LIBS_DIR)/dxsdk7/include $(SDL_INCLUDES) -I./libs/freetype2/include -I./libs/freetype2/include/freetype -I./libs/speex $(BOTLIB_CFLAGS) $(SVNREVISION) - SV_CFLAGS=$(SERVER_ONLY_CFLAGS) $(W32_CFLAGS) -DMULTITHREAD -DMSVCLIBSPATH="libs/" + SV_CFLAGS=$(SERVER_ONLY_CFLAGS) $(W32_CFLAGS) -DMULTITHREAD -DMSVCLIBPATH=libs/ SV_EXE_NAME=../fteqwsv$(BITS)$(EXEPOSTFIX) SV_DIR=sv_vc$(BITS) SV_OBJS=$(COMMON_OBJS) $(SERVER_OBJS) $(PROGS_OBJS) $(WINDOWSSERVERONLY_OBJS) fs_win32.o resources.o @@ -974,7 +974,7 @@ ifeq ($(FTE_TARGET),vc) GLB_DIR=gl_vc$(BITS) GLCL_DIR=glcl_vc$(BITS) GL_LDFLAGS=$(GLLDFLAGS) $(JPEGLIB) libs/libpng$(BITS).lib uuid.lib gdi32.lib ole32.lib /subsystem:windows - GL_CFLAGS=$(GLCFLAGS) $(W32_CFLAGS) -DMULTITHREAD $(SPEEXCFLAGS) -DMSVCLIBSPATH="libs/" + GL_CFLAGS=$(GLCFLAGS) $(W32_CFLAGS) -DMULTITHREAD $(SPEEXCFLAGS) -DMSVCLIBPATH=libs/ GLCL_OBJS=$(D3DGL_OBJS) $(GLQUAKE_OBJS) $(SPEEX_OBJS) gl_vidnt.o $(WINDOWS_OBJS) GL_OBJS= @@ -985,13 +985,13 @@ ifeq ($(FTE_TARGET),vc) D3D_EXE_NAME=../fted3dqw$(BITS)$(EXEPOSTFIX) D3DCL_EXE_NAME=../fted3dclqw$(BITS)$(EXEPOSTFIX) D3D_LDFLAGS=$(JPEGLIB) libs/libpng$(BITS).lib uuid.lib gdi32.lib ole32.lib /subsystem:windows - D3D_CFLAGS=$(D3DCFLAGS) $(W32_CFLAGS) $(DX7SDK) -DMULTITHREAD $(SPEEXCFLAGS) -DMSVCLIBSPATH="libs/" + D3D_CFLAGS=$(D3DCFLAGS) $(W32_CFLAGS) $(DX7SDK) -DMULTITHREAD $(SPEEXCFLAGS) -DMSVCLIBPATH=libs/ D3DB_DIR=d3d_vc$(BITS) D3DCL_DIR=d3dcl_vc$(BITS) M_EXE_NAME=../fteqw$(BITS)$(EXEPOSTFIX) MCL_OBJS=$(GL_OBJS) $(D3DGL_OBJS) $(D3DQUAKE_OBJS) $(GLQUAKE_OBJS) gl_vidnt.o $(SPEEX_OBJS) $(WINDOWS_OBJS) - M_CFLAGS=$(D3DCFLAGS) $(GLCFLAGS) $(W32_CFLAGS) $(D3DCFLAGS) -DMULTITHREAD $(SPEEXCFLAGS) -DMSVCLIBSPATH="libs/" + M_CFLAGS=$(D3DCFLAGS) $(GLCFLAGS) $(W32_CFLAGS) $(D3DCFLAGS) -DMULTITHREAD $(SPEEXCFLAGS) -DMSVCLIBPATH=libs/ MB_DIR=m_vc$(BITS) M_LDFLAGS=$(GLLDFLAGS) $(JPEGLIB) libs/libpng$(BITS).lib uuid.lib gdi32.lib ole32.lib /subsystem:windows endif @@ -1854,4 +1854,4 @@ INSTALL_DATA ?= ${INSTALL} -m 644 install: sv-rel gl-rel mingl-rel qcc-rel $(INSTALL_PROGRAM) $(RELEASE_DIR)fteqw $(DESTDIR)$(bindir)/fteqw $(INSTALL_PROGRAM) $(RELEASE_DIR)fteqwsv $(DESTDIR)$(bindir)/fteqwsv - $(INSTALL_PROGRAM) $(RELEASE_DIR)fteqcc $(DESTDIR)$(bindir)/fteqcc \ No newline at end of file + $(INSTALL_PROGRAM) $(RELEASE_DIR)fteqcc $(DESTDIR)$(bindir)/fteqcc diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index 5b2ae2ccd..4facaa541 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -109,6 +109,17 @@ static float CL_TrackScoreProp(player_info_t *pl, char rule, float *weights) float r; switch(rule) { + case '.': //currently being tracked. combine with currently alive or something + { + int i; + for (i = 0; i < cl.splitclients; i++) + { + //not valid if an earlier view is tracking it. + if (Cam_TrackNum(&cl.playerview[i]) == pl-cl.players) + return 1; + } + return 0; + } case 'a': //armour value return pl->statsf[STAT_ARMOR]; case 'h': @@ -144,11 +155,36 @@ static float CL_TrackScoreProp(player_info_t *pl, char rule, float *weights) return Stats_GetDeaths(pl - cl.players); case 'u': //userid return pl - cl.players; + case 'c': //'current run time' + case 'C': //'current run frags' + case 'd': //'current run teamfrags' + case 'I': //ssg grabs + case 'j': //ng grabs + case 'J': //sng grabs + case 'k': //gl grabs + case 'K': //gl lost + case 'l': //rl grabs + case 'L': //rl lost + case 'm': //lg grabs + case 'M': //lg lost + case 'n': //mh grabs + case 'N': //ga grabs + case 'o': //ya grabs + case 'O': //ra grabs + case 'v': //average run time + case 'V': //average run frags + case 'w': //average run teamfrags + case 'x': //ring grabs + case 'X': //ring losts + case 'y': //quad grabs + case 'Y': //quad losts + case 'z': //pent grabs default: return 0; } } -#define PRI_TOP 2 +#define PRI_TOP 3 +#define PRI_LOGIC 3 #define PRI_ADD 2 #define PRI_MUL 1 #define PRI_VAL 0 @@ -160,6 +196,11 @@ static float CL_TrackScore(player_info_t *pl, char **rule, float *weights, int p s++; if (!pri) { + if (*s == '!') + { + s++; + l = !CL_TrackScore(pl, &s, weights, pri); + } if (*s == '(') { l = CL_TrackScore(pl, &s, weights, PRI_TOP); @@ -225,6 +266,79 @@ static float CL_TrackScore(player_info_t *pl, char **rule, float *weights, int p continue; } } + else if (pri == PRI_LOGIC) + { + if (*s == '|' && s[1] == '|') + { + s+=2; + r = CL_TrackScore(pl, &s, weights, pri-1); + l = l||r; + continue; + } + else if (*s == '&' && s[1] == '&') + { + s+=2; + r = CL_TrackScore(pl, &s, weights, pri-1); + l = l&&r; + continue; + } + else if (*s == '&') + { + s++; + r = CL_TrackScore(pl, &s, weights, pri-1); + l = (int)l&(int)r; + continue; + } + else if (*s == '|') + { + s++; + r = CL_TrackScore(pl, &s, weights, pri-1); + l = (int)l|(int)r; + continue; + } + else if (*s == '>' && s[1] == '=') + { + s+=2; + r = CL_TrackScore(pl, &s, weights, pri-1); + l = l>=r; + continue; + } + else if (*s == '<' && s[1] == '=') + { + s+=2; + r = CL_TrackScore(pl, &s, weights, pri-1); + l = l<=r; + continue; + } + else if (*s == '>') + { + s+=1; + r = CL_TrackScore(pl, &s, weights, pri-1); + l = l>r; + continue; + } + else if (*s == '<') + { + s+=1; + r = CL_TrackScore(pl, &s, weights, pri-1); + l = l>r; + continue; + } + else if (*s == '!' && s[1] == '=') + { + s+=2; + r = CL_TrackScore(pl, &s, weights, pri-1); + l = l!=r; + continue; + } + else if (*s == '=' && s[1] == '=') + { + s+=2; + r = CL_TrackScore(pl, &s, weights, pri-1); + l = l!=r; + continue; + } + } break; } *rule = s; @@ -253,6 +367,11 @@ static int CL_FindHighTrack(int seat, char *rule) player_info_t *s; float weights[14]; char *p; + qboolean instant; + + instant = (rule && *rule == '!'); + if (instant) + rule++; if (rule && *rule == '[') { @@ -346,6 +465,20 @@ static int CL_FindHighTrack(int seat, char *rule) } } } + + if (j != -1 && CL_MayTrack(seat, cl.playerview[seat].cam_spec_track) && !instant) + { + i = cl.playerview[seat].cam_spec_track; + //extra hacks to prevent 'random' switching mid-game + if ((cl.players[j].stats[STAT_ITEMS] ^ cl.players[i].stats[STAT_ITEMS]) & (IT_INVULNERABILITY|IT_QUAD)) + ; //don't block if the players have different powerups + else if ((cl.players[j].stats[STAT_ITEMS] & (IT_ROCKET_LAUNCHER|IT_LIGHTNING)) && !(cl.players[i].stats[STAT_ITEMS] & (IT_ROCKET_LAUNCHER|IT_LIGHTNING))) + ; //don't block the switch if the new player has a decent weapon, and the guy we're tracking does not. + else if ((cl.players[j].stats[STAT_ITEMS] & (IT_ROCKET_LAUNCHER|IT_INVULNERABILITY))==(IT_ROCKET_LAUNCHER|IT_INVULNERABILITY) && (cl.players[i].stats[STAT_ITEMS] & (IT_ROCKET_LAUNCHER|IT_LIGHTNING)) != (IT_ROCKET_LAUNCHER|IT_INVULNERABILITY)) + ; //don't block if we're switching to someone with pent+rl from someone that does not. + else + return cl.playerview[seat].cam_spec_track; + } return j; } diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 34174261e..49c1d7981 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -139,7 +139,7 @@ cvar_t cl_r2g = CVARFD("cl_r2g", "0", CVAR_ARCHIVE, "Uses progs/grenade.mdl cvar_t r_powerupglow = CVAR("r_powerupglow", "1"); cvar_t v_powerupshell = CVARF("v_powerupshell", "0", CVAR_ARCHIVE); cvar_t cl_gibfilter = CVARF("cl_gibfilter", "0", CVAR_ARCHIVE); -cvar_t cl_deadbodyfilter = CVAR("cl_deadbodyfilter", "0"); +cvar_t cl_deadbodyfilter = CVARF("cl_deadbodyfilter", "0", CVAR_ARCHIVE); cvar_t cl_gunx = CVAR("cl_gunx", "0"); cvar_t cl_guny = CVAR("cl_guny", "0"); diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 047a0c96e..edaa19a22 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -478,30 +478,6 @@ void SCR_CPrint_f(void) SCR_CenterPrint(0, Cmd_Args(), true); } -void SCR_EraseCenterString (void) -{ - cprint_t *p; - int pnum; - int y; - - if (cl.splitclients>1) - return; //no viewsize with split - - for (pnum = 0; pnum < cl.splitclients; pnum++) - { - p = &scr_centerprint[pnum]; - - if (p->erase_center++ > vid.numpages) - { - p->erase_lines = 0; - continue; - } - - y = vid.height>>1; - R2D_TileClear (0, y, vid.width, min(8*p->erase_lines, vid.height - y - 1)); - } -} - #define MAX_CPRINT_LINES 128 void SCR_DrawCenterString (vrect_t *rect, cprint_t *p, struct font_s *font) { @@ -1864,8 +1840,7 @@ void SCR_ImageName (char *mapname) strcpy(levelshotname, "levelshots/"); COM_FileBase(mapname, levelshotname + strlen(levelshotname), sizeof(levelshotname)-strlen(levelshotname)); -#ifdef GLQUAKE - if (qrenderer == QR_OPENGL) + if (qrenderer) { if (!R_GetShaderSizes(R2D_SafeCachePic (levelshotname), NULL, NULL, true)) { @@ -1881,18 +1856,21 @@ void SCR_ImageName (char *mapname) scr_disabled_for_loading = false; scr_drawloading = true; - GL_BeginRendering (); - SCR_DrawLoading(false); - SCR_SetUpToDrawConsole(); - if (Key_Dest_Has(kdm_console) || !*levelshotname) - SCR_DrawConsole(!!*levelshotname); - GL_EndRendering(); +#ifdef GLQUAKE + if (qrenderer == QR_OPENGL) + { + GL_BeginRendering (); + SCR_DrawLoading(false); + SCR_SetUpToDrawConsole(); + if (Key_Dest_Has(kdm_console) || !*levelshotname) + SCR_DrawConsole(!!*levelshotname); + GL_EndRendering(); + } +#endif scr_drawloading = false; scr_disabled_time = Sys_DoubleTime(); //realtime tends to change... Hmmm.... scr_disabled_for_loading = true; - -#endif } diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 107f5451d..e4816c1f2 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -723,6 +723,8 @@ const char *presetexec[] = "seta cl_sbar 0;" "seta sv_nqplayerphysics 0;" //server settings in a preset might be bad. "seta cl_demoreel 0;" + "seta cl_gibfilter 1;" + "if cl_deadbodyfilter == 0 then seta cl_deadbodyfilter 1;" //as useful as 2 is, some mods use death frames for crouching etc. , // fast options "gl_texturemode ln;" @@ -761,6 +763,8 @@ const char *presetexec[] = "sv_nqplayerphysics 1;" //gb wanted this "cl_demoreel 1;" //yup, arcadey //"d_mipcap \"0 3\";" //logically correct, but will fuck up on ATI drivers if increased mid-map, because ATI will just ignore any levels that are not currently enabled. + "seta cl_gibfilter 0;" + "seta cl_deadbodyfilter 0;" , // normal (faithful) options, but with content replacement thrown in #ifdef MINIMAL diff --git a/engine/client/merged.h b/engine/client/merged.h index 8ebab7238..a52f2b2d7 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -67,6 +67,10 @@ typedef struct { extern r_qrenderer_t qrenderer; extern char *q_renderername; +apic_t *R2D_LoadAtlasedPic(const char *name); +void R2D_ImageAtlas(float x, float y, float w, float h, float s1, float t1, float s2, float t2, apic_t *pic); +#define R2D_ScalePicAtlas(x,y,w,h,p) R2D_ImageAtlas(x,y,w,h,0,0,1,1,p) + mpic_t *R2D_SafeCachePic (const char *path); mpic_t *R2D_SafePicFromWad (const char *name); void R2D_DrawCrosshair (void); @@ -106,7 +110,6 @@ extern void SCR_BeginLoadingPlaque (void); extern void SCR_EndLoadingPlaque (void); extern void SCR_DrawConsole (qboolean noback); extern void SCR_SetUpToDrawConsole (void); -extern void SCR_EraseCenterString (void); extern void SCR_CenterPrint (int pnum, char *str, qboolean skipgamecode); void R_DrawTextField(int x, int y, int w, int h, const char *text, unsigned int defaultmask, unsigned int fieldflags, struct font_s *font, vec2_t fontscale); @@ -319,6 +322,7 @@ typedef struct size_t maxsize; size_t pos; int vboid[2]; + void *vboptr[2]; void *fallback; } vbobctx_t; diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index c15ad317d..821ce9ac4 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -1848,6 +1848,8 @@ void R2D_PolyBlend (void); void R_DrawNameTags(void); static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { + qboolean scissored; + if (R2D_Flush) R2D_Flush(); csqc_poly_shader = NULL; @@ -1870,6 +1872,7 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars R2D_PolyBlend (); R_DrawNameTags(); + if (r_refdef.grect.x || r_refdef.grect.y || r_refdef.grect.width != vid.fbvwidth || r_refdef.grect.height != vid.fbvheight) { srect_t srect; srect.x = (float)r_refdef.grect.x / vid.fbvwidth; @@ -1880,7 +1883,10 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars srect.dmax = 99999; srect.y = (1-srect.y) - srect.height; BE_Scissor(&srect); + scissored = true; } + else + scissored = false; if (r_refdef.drawsbar) { @@ -1902,7 +1908,13 @@ static void QCBUILTIN PF_R_RenderScene(pubprogfuncs_t *prinst, struct globalvars if (r_refdef.drawcrosshair) R2D_DrawCrosshair(); - BE_Scissor(NULL); + if (scissored) + { + if (R2D_Flush) + R2D_Flush(); + + BE_Scissor(NULL); + } } static void QCBUILTIN PF_cs_getstati(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -6713,10 +6725,10 @@ qboolean CSQC_DrawView(void) else PR_ExecuteProgram(csqcprogs, csqcg.f_updateview); - if (R2D_Flush) - R2D_Flush(); if (*r_refdef.rt_destcolour[0].texname) { + if (R2D_Flush) + R2D_Flush(); Q_strncpyz(r_refdef.rt_destcolour[0].texname, "", sizeof(r_refdef.rt_destcolour[0].texname)); BE_RenderToTextureUpdate2d(true); } diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index ea2375ce4..ee751d410 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -3,6 +3,9 @@ #include "shader.h" #include "gl_draw.h" +#define WIN32_BLOATED +#include "glquake.h" + qboolean r2d_canhwgamma; //says the video code has successfully activated hardware gamma texid_t missing_texture; texid_t missing_texture_gloss; @@ -27,13 +30,26 @@ shader_t *shader_gammacb; shader_t *shader_polyblend; shader_t *shader_menutint; +#define DRAW_QUADS 128 +static shader_t *draw_active_shader; +static avec4_t draw_active_colour; static mesh_t draw_mesh; -static vecV_t draw_mesh_xyz[4]; -vec2_t draw_mesh_st[4]; -static avec4_t draw_mesh_colors[4]; -index_t r_quad_indexes[6] = {0, 1, 2, 2, 3, 0}; -unsigned int r2d_be_flags; +static vecV_t draw_mesh_xyz[DRAW_QUADS]; +vec2_t draw_mesh_st[DRAW_QUADS]; +static avec4_t draw_mesh_colors[DRAW_QUADS]; +index_t r_quad_indexes[DRAW_QUADS*6]; +unsigned int r2d_be_flags; +struct +{ + lmalloc_t allocation; + qboolean dirty; + int lastid; + unsigned int *data; + shader_t *shader; + texid_t tex; + apic_t *pics; +} atlas; extern cvar_t scr_conalpha; extern cvar_t gl_conback; @@ -135,6 +151,16 @@ void R2D_Shutdown(void) #if defined(MENU_DAT) || defined(CSQC_DAT) PR_ReloadFonts(false); #endif + + while(atlas.pics) + { + apic_t *a = atlas.pics; + atlas.pics = a->next; + Z_Free(a); + } + + Z_Free(atlas.data); + memset(&atlas, 0, sizeof(atlas)); } /* @@ -145,7 +171,7 @@ void R2D_Init(void) { unsigned int nonorm[4*4]; unsigned int nogloss[4*4]; - int i; + int i, j; unsigned int glossval; unsigned int normval; extern cvar_t gl_specular_fallback, gl_specular_fallbackexp, gl_texturemode; @@ -162,6 +188,16 @@ void R2D_Init(void) draw_mesh.colors4f_array[0] = draw_mesh_colors; draw_mesh.indexes = r_quad_indexes; + for (i = 0, j = 0; i < countof(r_quad_indexes); i += 6, j += 4) + { + r_quad_indexes[i+0] = j+0; + r_quad_indexes[i+1] = j+1; + r_quad_indexes[i+2] = j+2; + r_quad_indexes[i+3] = j+2; + r_quad_indexes[i+4] = j+3; + r_quad_indexes[i+5] = j+0; + } + Font_Init(); @@ -353,6 +389,12 @@ void R2D_Init(void) R2D_Font_Changed(); R_NetgraphInit(); + + atlas.lastid = -1; + atlas.shader = NULL; + atlas.data = NULL; + atlas.dirty = false; + Mod_LightmapAllocInit(&atlas.allocation, false, min(512, sh_config.texture_maxsize), min(512, sh_config.texture_maxsize), 0); } mpic_t *R2D_SafeCachePic (const char *path) @@ -375,28 +417,170 @@ mpic_t *R2D_SafePicFromWad (const char *name) return s; } +apic_t *R2D_LoadAtlasedPic(const char *name) +{ + apic_t *apic = Z_Malloc(sizeof(*apic)); + qpic_t *qp; + int x,y; + qbyte *indata = NULL; + int atlasid; + + if (!gl_load24bit.ival) + { + qp = W_SafeGetLumpName(name); + if (qp) + { + apic->width = qp->width; + apic->height = qp->height; + indata = qp->data; + } + } + + if (!indata || apic->width > atlas.allocation.width || apic->height > atlas.allocation.height) + atlasid = -1; //can happen on voodoo cards + else + Mod_LightmapAllocBlock(&atlas.allocation, apic->width+2, apic->height+2, &apic->x, &apic->y, &atlasid); + + if (atlasid >= 0) + { + unsigned int *out; + apic->x += 1; + apic->y += 1; + + //FIXME: extend the atlas height instead, and keep going with a single atlas? + if (atlasid != atlas.lastid) + { + atlas.lastid = atlasid; + if (atlas.dirty) + Image_Upload(atlas.tex, TF_BGRA32, atlas.data, NULL, atlas.allocation.width, atlas.allocation.height, IF_NOMIPMAP); + atlas.tex = r_nulltex; + atlas.shader = NULL; + atlas.dirty = false; + if (atlas.data) //clear atlas data instead of reallocating it. + memset(atlas.data, 0, sizeof(*atlas.data) * atlas.allocation.width * atlas.allocation.height); + } + + if (!atlas.tex) + atlas.tex = Image_CreateTexture(va("fte_atlas%i", atlasid), NULL, IF_NOMIPMAP); + if (!atlas.shader) + { + atlas.shader = R_RegisterShader(va("fte_atlas%i", atlasid), SUF_NONE, + "{\n" + "affine\n" + "program default2d\n" + "{\n" + "map $diffuse\n" + "rgbgen vertex\n" + "alphagen vertex\n" + "blendfunc gl_one gl_one_minus_src_alpha\n" + "}\n" + "}\n" + ); + atlas.shader->defaulttextures->base = atlas.tex; + } + + if (!atlas.data) + atlas.data = Z_Malloc(sizeof(*atlas.data) * atlas.allocation.width * atlas.allocation.height); + + out = atlas.data; + out += apic->x; + out += apic->y * atlas.allocation.width; + apic->atlas = atlas.shader; + + //pad above. extra casts because 64bit msvc is RETARDED. + out[-1 - (qintptr_t)atlas.allocation.width] = (indata[0] == 255)?0:d_8to24bgrtable[indata[0]]; //pad left + for (x = 0; x < apic->width; x++) + out[x-(qintptr_t)atlas.allocation.width] = (indata[x] == 255)?0:d_8to24bgrtable[indata[x]]; + out[x - (qintptr_t)atlas.allocation.width] = (indata[x-1] == 255)?0:d_8to24bgrtable[indata[x-1]]; //pad right + for (y = 0; y < apic->height; y++) + { + out[-1] = (indata[0] == 255)?0:d_8to24bgrtable[indata[0]]; //pad left + for (x = 0; x < apic->width; x++) + out[x] = (indata[x] == 255)?0:d_8to24bgrtable[indata[x]]; + out[x] = (indata[x-1] == 255)?0:d_8to24bgrtable[indata[x-1]]; //pad right + indata += x; + out += atlas.allocation.width; + } + //pad below + out[-1] = (indata[0] == 255)?0:d_8to24bgrtable[indata[0]]; //pad left + for (x = 0; x < apic->width; x++) + out[x] = (indata[x] == 255)?0:d_8to24bgrtable[indata[x]]; + out[x] = (indata[x-1] == 255)?0:d_8to24bgrtable[indata[x-1]]; //pad right + + //pinch inwards, for linear sampling + apic->sl = (apic->x+0.5)/(float)atlas.allocation.width; + apic->sh = (apic->width-1.0)/(float)atlas.allocation.width; + + apic->tl = (apic->y+0.5)/(float)atlas.allocation.height; + apic->th = (apic->height-1.0)/(float)atlas.allocation.height; + + atlas.dirty = true; + + apic->next = atlas.pics; + atlas.pics = apic; + } + else if (1) + { + apic->atlas = R_RegisterPic(va("gfx/%s", name)); + apic->sl = 0; + apic->sh = 1; + apic->tl = 0; + apic->th = 1; + + apic->next = atlas.pics; + atlas.pics = apic; + } + else + { + Z_Free(apic); + return NULL; + } + return apic; +} void R2D_ImageColours(float r, float g, float b, float a) { - draw_mesh_colors[0][0] = r; - draw_mesh_colors[0][1] = g; - draw_mesh_colors[0][2] = b; - draw_mesh_colors[0][3] = a; - Vector4Copy(draw_mesh_colors[0], draw_mesh_colors[1]); - Vector4Copy(draw_mesh_colors[0], draw_mesh_colors[2]); - Vector4Copy(draw_mesh_colors[0], draw_mesh_colors[3]); + draw_active_colour[0] = r; + draw_active_colour[1] = g; + draw_active_colour[2] = b; + draw_active_colour[3] = a; } void R2D_ImagePaletteColour(unsigned int i, float a) { - draw_mesh_colors[0][0] = host_basepal[i*3+0]/255.0; - draw_mesh_colors[0][1] = host_basepal[i*3+1]/255.0; - draw_mesh_colors[0][2] = host_basepal[i*3+2]/255.0; - draw_mesh_colors[0][3] = a; - Vector4Copy(draw_mesh_colors[0], draw_mesh_colors[1]); - Vector4Copy(draw_mesh_colors[0], draw_mesh_colors[2]); - Vector4Copy(draw_mesh_colors[0], draw_mesh_colors[3]); + draw_active_colour[0] = host_basepal[i*3+0]/255.0; + draw_active_colour[1] = host_basepal[i*3+1]/255.0; + draw_active_colour[2] = host_basepal[i*3+2]/255.0; + draw_active_colour[3] = a; } +//awkward and weird to use +void R2D_ImageAtlas(float x, float y, float w, float h, float s1, float t1, float s2, float t2, apic_t *pic) +{ + float newsl, newsh, newtl, newth; + if (!pic) + return; + if (atlas.dirty) + { + Image_Upload(atlas.tex, TF_BGRA32, atlas.data, NULL, atlas.allocation.width, atlas.allocation.height, IF_NOMIPMAP); + atlas.dirty = false; + } + + newsl = pic->sl + s1 * pic->sh; + newsh = newsl + (s2-s1) * pic->sh; + + newtl = pic->tl + t1 * pic->th; + newth = newtl + (t2-t1) * pic->th; + + R2D_Image(x, y, w, h, newsl, newtl, newsh, newth, pic->atlas); +} + +void R2D_ImageFlush(void) +{ + BE_DrawMesh_Single(draw_active_shader, &draw_mesh, NULL, r2d_be_flags); + + R2D_Flush = NULL; + draw_active_shader = NULL; +} //awkward and weird to use void R2D_Image(float x, float y, float w, float h, float s1, float t1, float s2, float t2, mpic_t *pic) { @@ -413,30 +597,36 @@ void R2D_Image(float x, float y, float w, float h, float s1, float t1, float s2, return; } - if (R2D_Flush) - R2D_Flush(); + if (draw_active_shader != pic || draw_mesh.numvertexes+4 > DRAW_QUADS) + { + if (R2D_Flush) + R2D_Flush(); - draw_mesh_xyz[0][0] = x; - draw_mesh_xyz[0][1] = y; - draw_mesh_st[0][0] = s1; - draw_mesh_st[0][1] = t1; + draw_active_shader = pic; + R2D_Flush = R2D_ImageFlush; - draw_mesh_xyz[1][0] = x+w; - draw_mesh_xyz[1][1] = y; - draw_mesh_st[1][0] = s2; - draw_mesh_st[1][1] = t1; + draw_mesh.numindexes = 0; + draw_mesh.numvertexes = 0; + } - draw_mesh_xyz[2][0] = x+w; - draw_mesh_xyz[2][1] = y+h; - draw_mesh_st[2][0] = s2; - draw_mesh_st[2][1] = t2; + Vector2Set(draw_mesh_xyz[draw_mesh.numvertexes+0], x, y); + Vector2Set(draw_mesh_st[draw_mesh.numvertexes+0], s1, t1); + Vector4Copy(draw_active_colour, draw_mesh_colors[draw_mesh.numvertexes+0]); - draw_mesh_xyz[3][0] = x; - draw_mesh_xyz[3][1] = y+h; - draw_mesh_st[3][0] = s1; - draw_mesh_st[3][1] = t2; + Vector2Set(draw_mesh_xyz[draw_mesh.numvertexes+1], x+w, y); + Vector2Set(draw_mesh_st[draw_mesh.numvertexes+1], s2, t1); + Vector4Copy(draw_active_colour, draw_mesh_colors[draw_mesh.numvertexes+1]); - BE_DrawMesh_Single(pic, &draw_mesh, NULL, r2d_be_flags); + Vector2Set(draw_mesh_xyz[draw_mesh.numvertexes+2], x+w, y+h); + Vector2Set(draw_mesh_st[draw_mesh.numvertexes+2], s2, t2); + Vector4Copy(draw_active_colour, draw_mesh_colors[draw_mesh.numvertexes+2]); + + Vector2Set(draw_mesh_xyz[draw_mesh.numvertexes+3], x, y+h); + Vector2Set(draw_mesh_st[draw_mesh.numvertexes+3], s1, t2); + Vector4Copy(draw_active_colour, draw_mesh_colors[draw_mesh.numvertexes+3]); + + draw_mesh.numvertexes += 4; + draw_mesh.numindexes += 6; } void R2D_Image2dQuad(vec2_t points[], vec2_t texcoords[], mpic_t *pic) { @@ -468,25 +658,37 @@ void R2D_Image2dQuad(vec2_t points[], vec2_t texcoords[], mpic_t *pic) /*draws a block of the current colour on the screen*/ void R2D_FillBlock(float x, float y, float w, float h) { - if (R2D_Flush) - R2D_Flush(); - - draw_mesh_xyz[0][0] = x; - draw_mesh_xyz[0][1] = y; - - draw_mesh_xyz[1][0] = x+w; - draw_mesh_xyz[1][1] = y; - - draw_mesh_xyz[2][0] = x+w; - draw_mesh_xyz[2][1] = y+h; - - draw_mesh_xyz[3][0] = x; - draw_mesh_xyz[3][1] = y+h; - - if (draw_mesh_colors[0][3] != 1) - BE_DrawMesh_Single(shader_draw_fill_trans, &draw_mesh, NULL, r2d_be_flags); + mpic_t *pic; + if (draw_active_colour[3] != 1) + pic = shader_draw_fill_trans; else - BE_DrawMesh_Single(shader_draw_fill, &draw_mesh, NULL, r2d_be_flags); + pic = shader_draw_fill; + if (draw_active_shader != pic || draw_mesh.numvertexes+4 > DRAW_QUADS) + { + if (R2D_Flush) + R2D_Flush(); + + draw_active_shader = pic; + R2D_Flush = R2D_ImageFlush; + + draw_mesh.numindexes = 0; + draw_mesh.numvertexes = 0; + } + + Vector2Set(draw_mesh_xyz[draw_mesh.numvertexes+0], x, y); + Vector4Copy(draw_active_colour, draw_mesh_colors[draw_mesh.numvertexes+0]); + + Vector2Set(draw_mesh_xyz[draw_mesh.numvertexes+1], x+w, y); + Vector4Copy(draw_active_colour, draw_mesh_colors[draw_mesh.numvertexes+1]); + + Vector2Set(draw_mesh_xyz[draw_mesh.numvertexes+2], x+w, y+h); + Vector4Copy(draw_active_colour, draw_mesh_colors[draw_mesh.numvertexes+2]); + + Vector2Set(draw_mesh_xyz[draw_mesh.numvertexes+3], x, y+h); + Vector4Copy(draw_active_colour, draw_mesh_colors[draw_mesh.numvertexes+3]); + + draw_mesh.numvertexes += 4; + draw_mesh.numindexes += 6; } void R2D_Line(float x1, float y1, float x2, float y2, shader_t *shader) @@ -502,7 +704,7 @@ void R2D_Line(float x1, float y1, float x2, float y2, shader_t *shader) if (!shader) { - if (draw_mesh_colors[0][3] != 1) + if (draw_active_colour[3] != 1) shader = shader_draw_fill_trans; else shader = shader_draw_fill; @@ -511,8 +713,6 @@ void R2D_Line(float x1, float y1, float x2, float y2, shader_t *shader) draw_mesh.numvertexes = 2; draw_mesh.numindexes = 2; BE_DrawMesh_Single(shader, &draw_mesh, NULL, BEF_LINES); - draw_mesh.numvertexes = 4; - draw_mesh.numindexes = 6; } void R2D_ScalePic (float x, float y, float width, float height, mpic_t *pic) @@ -647,30 +847,7 @@ void R2D_TileClear (float x, float y, float w, float h) R2D_ImageColours(1,1,1,1); - if (R2D_Flush) - R2D_Flush(); - - draw_mesh_xyz[0][0] = x; - draw_mesh_xyz[0][1] = y; - draw_mesh_st[0][0] = newsl; - draw_mesh_st[0][1] = newtl; - - draw_mesh_xyz[1][0] = x+w; - draw_mesh_xyz[1][1] = y; - draw_mesh_st[1][0] = newsh; - draw_mesh_st[1][1] = newtl; - - draw_mesh_xyz[2][0] = x+w; - draw_mesh_xyz[2][1] = y+h; - draw_mesh_st[2][0] = newsh; - draw_mesh_st[2][1] = newth; - - draw_mesh_xyz[3][0] = x; - draw_mesh_xyz[3][1] = y+h; - draw_mesh_st[3][0] = newsl; - draw_mesh_st[3][1] = newth; - - BE_DrawMesh_Single(draw_backtile, &draw_mesh, NULL, r2d_be_flags); + R2D_Image(x, y, w, h, newsl, newtl, newsh, newth, draw_backtile); } void QDECL R2D_Conback_Callback(struct cvar_s *var, char *oldvalue) @@ -702,7 +879,6 @@ void QDECL R2D_Conback_Callback(struct cvar_s *var, char *oldvalue) } #if defined(_WIN32) && !defined(FTE_SDL) && !defined(WINRT) -#include qboolean R2D_Font_WasAdded(char *buffer, char *fontfilename) { char *match; diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 10fb598cb..c8c86b7f4 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -80,39 +80,39 @@ int sb_updates; // if >= vid.numpages, no update needed qboolean sbar_parsingteamstatuses; //so we don't eat it if its not displayed #define STAT_MINUS 10 // num frame for '-' stats digit -mpic_t *sb_nums[2][11]; -mpic_t *sb_colon, *sb_slash; -mpic_t *sb_ibar; -mpic_t *sb_sbar; -mpic_t *sb_scorebar; +static apic_t *sb_nums[2][11]; +static apic_t *sb_colon, *sb_slash; +static apic_t *sb_ibar; +static apic_t *sb_sbar; +static apic_t *sb_scorebar; -mpic_t *sb_weapons[7][8]; // 0 is active, 1 is owned, 2-5 are flashes -mpic_t *sb_ammo[4]; -mpic_t *sb_sigil[4]; -mpic_t *sb_armor[3]; -mpic_t *sb_items[32]; +static apic_t *sb_weapons[7][8]; // 0 is active, 1 is owned, 2-5 are flashes +static apic_t *sb_ammo[4]; +static apic_t *sb_sigil[4]; +static apic_t *sb_armor[3]; +static apic_t *sb_items[32]; -mpic_t *sb_faces[7][2]; // 0 is gibbed, 1 is dead, 2-6 are alive +static apic_t *sb_faces[7][2]; // 0 is gibbed, 1 is dead, 2-6 are alive // 0 is static, 1 is temporary animation -mpic_t *sb_face_invis; -mpic_t *sb_face_quad; -mpic_t *sb_face_invuln; -mpic_t *sb_face_invis_invuln; +static apic_t *sb_face_invis; +static apic_t *sb_face_quad; +static apic_t *sb_face_invuln; +static apic_t *sb_face_invis_invuln; //rogue pictures. -qboolean sbar_rogue; -mpic_t *rsb_invbar[2]; -mpic_t *rsb_weapons[5]; -mpic_t *rsb_items[2]; -mpic_t *rsb_ammo[3]; -mpic_t *rsb_teambord; +static qboolean sbar_rogue; +static apic_t *rsb_invbar[2]; +static apic_t *rsb_weapons[5]; +static apic_t *rsb_items[2]; +static apic_t *rsb_ammo[3]; +static apic_t *rsb_teambord; //all must be found for any to be used. //hipnotic pictures and stuff -qboolean sbar_hipnotic; -mpic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes -int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT}; -mpic_t *hsb_items[2]; +static qboolean sbar_hipnotic; +static apic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes +static int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT}; +static apic_t *hsb_items[2]; //end hipnotic qboolean sb_showscores; @@ -878,12 +878,12 @@ Sbar_Init static qboolean sbar_loaded; -mpic_t *Sbar_PicFromWad(char *name) +static apic_t *Sbar_PicFromWad(char *name) { - mpic_t *ret; + apic_t *ret; char savedname[MAX_QPATH]; Q_strncpyz(savedname, name, sizeof(savedname)); - ret = R2D_SafePicFromWad(savedname); + ret = R2D_LoadAtlasedPic(savedname); if (ret) return ret; @@ -1092,7 +1092,11 @@ void Sbar_Init (void) Sbar_DrawPic ============= */ -void Sbar_DrawPic (float x, float y, float w, float h, mpic_t *pic) +static void Sbar_DrawPic (float x, float y, float w, float h, apic_t *pic) +{ + R2D_ImageAtlas(sbar_rect.x + x /* + ((sbar_rect.width - 320)>>1) */, sbar_rect.y + y + (sbar_rect.height-SBAR_HEIGHT), w, h, 0, 0, 1, 1, pic); +} +static void Sbar_DrawMPic (float x, float y, float w, float h, mpic_t *pic) { R2D_ScalePic(sbar_rect.x + x /* + ((sbar_rect.width - 320)>>1) */, sbar_rect.y + y + (sbar_rect.height-SBAR_HEIGHT), w, h, pic); } @@ -1104,9 +1108,17 @@ Sbar_DrawSubPic JACK: Draws a portion of the picture in the status bar. */ -void Sbar_DrawSubPic(float x, float y, float width, float height, mpic_t *pic, int srcx, int srcy, int srcwidth, int srcheight) +static void Sbar_DrawSubPic(float x, float y, float width, float height, apic_t *pic, int srcx, int srcy, int srcwidth, int srcheight) { - R2D_SubPic (sbar_rect.x + x, sbar_rect.y + y+(sbar_rect.height-SBAR_HEIGHT), width, height, pic, srcx, srcy, srcwidth, srcheight); + float newsl, newtl, newsh, newth; + + newsl = (srcx)/(float)srcwidth; + newsh = newsl + (width)/(float)srcwidth; + + newtl = (srcy)/(float)srcheight; + newth = newtl + (height)/(float)srcheight; + + R2D_ImageAtlas (sbar_rect.x + x, sbar_rect.y + y+(sbar_rect.height-SBAR_HEIGHT), width, height, newsl, newtl, newsh, newth, pic); } /* @@ -1737,29 +1749,6 @@ void Sbar_DrawInventory (playerview_t *pv) } } -// ammo counts - if (headsup) - { - for (i=0 ; i<4 ; i++) - Sbar_DrawSubPic((hudswap) ? sbar_rect_left : (sbar_rect.width-42), -24 - (4-i)*11, 42, 11, sb_ibar, 3+(i*48), 0, 320, 24); - } - for (i=0 ; i<4 ; i++) - { - snprintf (num, sizeof(num), "%3i", pv->stats[STAT_SHELLS+i] ); - numc[0] = CON_WHITEMASK|0xe000|((num[0]!=' ')?(num[0] + 18-'0'):' '); - numc[1] = CON_WHITEMASK|0xe000|((num[1]!=' ')?(num[1] + 18-'0'):' '); - numc[2] = CON_WHITEMASK|0xe000|((num[2]!=' ')?(num[2] + 18-'0'):' '); - numc[3] = 0; - if (headsup) - { - Sbar_DrawExpandedString((hudswap) ? sbar_rect_left+3 : (sbar_rect.width-39), -24 - (4-i)*11, numc); - } - else - { - Sbar_DrawExpandedString((6*i+1)*8 - 2, -24, numc); - } - } - flashon = 0; // items for (i=(sbar_hipnotic?2:0) ; i<6 ; i++) @@ -1831,6 +1820,29 @@ void Sbar_DrawInventory (playerview_t *pv) } } } + + // ammo counts + if (headsup) + { + for (i=0 ; i<4 ; i++) + Sbar_DrawSubPic((hudswap) ? sbar_rect_left : (sbar_rect.width-42), -24 - (4-i)*11, 42, 11, sb_ibar, 3+(i*48), 0, 320, 24); + } + for (i=0 ; i<4 ; i++) + { + snprintf (num, sizeof(num), "%3i", pv->stats[STAT_SHELLS+i] ); + numc[0] = CON_WHITEMASK|0xe000|((num[0]!=' ')?(num[0] + 18-'0'):' '); + numc[1] = CON_WHITEMASK|0xe000|((num[1]!=' ')?(num[1] + 18-'0'):' '); + numc[2] = CON_WHITEMASK|0xe000|((num[2]!=' ')?(num[2] + 18-'0'):' '); + numc[3] = 0; + if (headsup) + { + Sbar_DrawExpandedString((hudswap) ? sbar_rect_left+3 : (sbar_rect.width-39), -24 - (4-i)*11, numc); + } + else + { + Sbar_DrawExpandedString((6*i+1)*8 - 2, -24, numc); + } + } } static qboolean PointInBox(float px, float py, float x, float y, float w, float h) @@ -2021,7 +2033,7 @@ void Sbar_DrawNormal (playerview_t *pv) if (pv->stats[STAT_ITEMS] & IT_INVULNERABILITY) { Sbar_DrawNum (24, 0, 666, 3, 1); - Sbar_DrawPic (0, 0, 24, 24, draw_disc); + Sbar_DrawMPic (0, 0, 24, 24, draw_disc); } else { @@ -2140,11 +2152,19 @@ void Sbar_DrawScoreboard (void) for (pnum = 0; pnum < cl.splitclients; pnum++) { - if (cl.playerview[pnum].stats[STAT_HEALTH] <= 0) + if (cl.spectator) + { + int t = cl.playerview[pnum].cam_spec_track; + if (t < 0) + continue; + if (cl.players[t].statsf[STAT_HEALTH] <= 0) + deadcount++; + } + else if (cl.playerview[pnum].statsf[STAT_HEALTH] <= 0) deadcount++; } - if (deadcount == cl.splitclients && !cl.spectator) + if (deadcount == cl.splitclients)// && !cl.spectator) { if (cl.teamplay > 0 && !sb_showscores) Sbar_TeamOverlay(); @@ -2192,14 +2212,14 @@ static void Sbar_Hexen2DrawActiveStuff(playerview_t *pv) static void Sbar_Hexen2DrawItem(playerview_t *pv, float x, float y, int itemnum) { int num; - Sbar_DrawPic(x, y, 29, 28, R2D_SafeCachePic(va("gfx/arti%02d.lmp", itemnum))); + Sbar_DrawMPic(x, y, 29, 28, R2D_SafeCachePic(va("gfx/arti%02d.lmp", itemnum))); num = pv->stats[STAT_H2_CNT_TORCH+itemnum]; if(num > 0) { if (num >= 10) - Sbar_DrawPic(x+20, y+21, 4, 6, R2D_SafeCachePic(va("gfx/artinum%d.lmp", num/10))); - Sbar_DrawPic(x+20+4, y+21, 4, 6, R2D_SafeCachePic(va("gfx/artinum%d.lmp", num%10))); + Sbar_DrawMPic(x+20, y+21, 4, 6, R2D_SafeCachePic(va("gfx/artinum%d.lmp", num/10))); + Sbar_DrawMPic(x+20+4, y+21, 4, 6, R2D_SafeCachePic(va("gfx/artinum%d.lmp", num%10))); } } @@ -2239,7 +2259,7 @@ static void Sbar_Hexen2DrawInventory(playerview_t *pv) continue; if (i == pv->sb_hexen2_cur_item) - Sbar_DrawPic(x+9, y-12, 11, 11, R2D_SafeCachePic("gfx/artisel.lmp")); + Sbar_DrawMPic(x+9, y-12, 11, 11, R2D_SafeCachePic("gfx/artisel.lmp")); Sbar_Hexen2DrawItem(pv, x, y, i); x -= 33; } @@ -2250,7 +2270,7 @@ static void Sbar_Hexen2DrawInventory(playerview_t *pv) if (i != pv->sb_hexen2_cur_item && !pv->stats[STAT_H2_CNT_TORCH+i]) continue; if (i == pv->sb_hexen2_cur_item) - Sbar_DrawPic(x+9, y-12, 11, 11, R2D_SafeCachePic("gfx/artisel.lmp")); + Sbar_DrawMPic(x+9, y-12, 11, 11, R2D_SafeCachePic("gfx/artisel.lmp")); Sbar_Hexen2DrawItem(pv, x, y, i); x+=33; } @@ -2298,8 +2318,8 @@ static void Sbar_Hexen2DrawExtra (playerview_t *pv) //adjust it so there's space sbar_rect.y -= 46+98-SBAR_HEIGHT; - Sbar_DrawPic(0, 46, 160, 98, R2D_SafeCachePic("gfx/btmbar1.lmp")); - Sbar_DrawPic(160, 46, 160, 98, R2D_SafeCachePic("gfx/btmbar2.lmp")); + Sbar_DrawMPic(0, 46, 160, 98, R2D_SafeCachePic("gfx/btmbar1.lmp")); + Sbar_DrawMPic(160, 46, 160, 98, R2D_SafeCachePic("gfx/btmbar2.lmp")); Sbar_DrawTinyString (11, 48, pclassname[pclass]); @@ -2332,7 +2352,7 @@ static void Sbar_Hexen2DrawExtra (playerview_t *pv) { if (pv->stats[STAT_H2_ARMOUR1+i] > 0) { - Sbar_DrawPic (164+i*40, 115, 28, 19, R2D_SafeCachePic(va("gfx/armor%d.lmp", i+1))); + Sbar_DrawMPic (164+i*40, 115, 28, 19, R2D_SafeCachePic(va("gfx/armor%d.lmp", i+1))); Sbar_DrawTinyStringf (168+i*40, 136, "+%d", pv->stats[STAT_H2_ARMOUR1+i]); } } @@ -2340,14 +2360,14 @@ static void Sbar_Hexen2DrawExtra (playerview_t *pv) { if (pv->stats[STAT_H2_FLIGHT_T+i] > 0) { - Sbar_DrawPic (ringpos[i], 119, 32, 22, R2D_SafeCachePic(va("gfx/ring_f.lmp"))); + Sbar_DrawMPic (ringpos[i], 119, 32, 22, R2D_SafeCachePic(va("gfx/ring_f.lmp"))); val = pv->stats[STAT_H2_FLIGHT_T+i]; if (val > 100) val = 100; if (val < 0) val = 0; - Sbar_DrawPic(ringpos[i]+29 - (int)(26 * (val/(float)100)),142, 26, 1, R2D_SafeCachePic("gfx/ringhlth.lmp")); - Sbar_DrawPic(ringpos[i]+29, 142, 26, 1, R2D_SafeCachePic("gfx/rhlthcvr.lmp")); + Sbar_DrawMPic(ringpos[i]+29 - (int)(26 * (val/(float)100)),142, 26, 1, R2D_SafeCachePic("gfx/ringhlth.lmp")); + Sbar_DrawMPic(ringpos[i]+29, 142, 26, 1, R2D_SafeCachePic("gfx/rhlthcvr.lmp")); } } @@ -2356,12 +2376,12 @@ static void Sbar_Hexen2DrawExtra (playerview_t *pv) { if (pv->statsstr[STAT_H2_PUZZLE1+i] && *pv->statsstr[STAT_H2_PUZZLE1+i]) { - Sbar_DrawPic (194+(slot%4)*31, slot<4?51:82, 26, 26, R2D_SafeCachePic(va("gfx/puzzle/%s.lmp", pv->statsstr[STAT_H2_PUZZLE1+i]))); + Sbar_DrawMPic (194+(slot%4)*31, slot<4?51:82, 26, 26, R2D_SafeCachePic(va("gfx/puzzle/%s.lmp", pv->statsstr[STAT_H2_PUZZLE1+i]))); slot++; } } - Sbar_DrawPic(134, 50, 49, 56, R2D_SafeCachePic(va("gfx/cport%d.lmp", pclass))); + Sbar_DrawMPic(134, 50, 49, 56, R2D_SafeCachePic(va("gfx/cport%d.lmp", pclass))); } static int Sbar_Hexen2ArmourValue(playerview_t *pv) @@ -2402,11 +2422,11 @@ static void Sbar_Hexen2DrawBasic(playerview_t *pv) { int chainpos; int val, maxval; - Sbar_DrawPic(0, 0, 160, 46, R2D_SafeCachePic("gfx/topbar1.lmp")); - Sbar_DrawPic(160, 0, 160, 46, R2D_SafeCachePic("gfx/topbar2.lmp")); - Sbar_DrawPic(0, -23, 51, 23, R2D_SafeCachePic("gfx/topbumpl.lmp")); - Sbar_DrawPic(138, -8, 39, 8, R2D_SafeCachePic("gfx/topbumpm.lmp")); - Sbar_DrawPic(269, -23, 51, 23, R2D_SafeCachePic("gfx/topbumpr.lmp")); + Sbar_DrawMPic(0, 0, 160, 46, R2D_SafeCachePic("gfx/topbar1.lmp")); + Sbar_DrawMPic(160, 0, 160, 46, R2D_SafeCachePic("gfx/topbar2.lmp")); + Sbar_DrawMPic(0, -23, 51, 23, R2D_SafeCachePic("gfx/topbumpl.lmp")); + Sbar_DrawMPic(138, -8, 39, 8, R2D_SafeCachePic("gfx/topbumpm.lmp")); + Sbar_DrawMPic(269, -23, 51, 23, R2D_SafeCachePic("gfx/topbumpr.lmp")); //mana1 maxval = pv->stats[STAT_H2_MAXMANA]; @@ -2415,8 +2435,8 @@ static void Sbar_Hexen2DrawBasic(playerview_t *pv) Sbar_DrawTinyStringf(201, 22, "%03d", val); if(val) { - Sbar_DrawPic(190, 26-(int)((val*18.0)/(float)maxval+0.5), 3, 19, R2D_SafeCachePic("gfx/bmana.lmp")); - Sbar_DrawPic(190, 27, 3, 19, R2D_SafeCachePic("gfx/bmanacov.lmp")); + Sbar_DrawMPic(190, 26-(int)((val*18.0)/(float)maxval+0.5), 3, 19, R2D_SafeCachePic("gfx/bmana.lmp")); + Sbar_DrawMPic(190, 27, 3, 19, R2D_SafeCachePic("gfx/bmanacov.lmp")); } //mana2 @@ -2426,8 +2446,8 @@ static void Sbar_Hexen2DrawBasic(playerview_t *pv) Sbar_DrawTinyStringf(243, 22, "%03d", val); if(val) { - Sbar_DrawPic(232, 26-(int)((val*18.0)/(float)maxval+0.5), 3, 19, R2D_SafeCachePic("gfx/gmana.lmp")); - Sbar_DrawPic(232, 27, 3, 19, R2D_SafeCachePic("gfx/gmanacov.lmp")); + Sbar_DrawMPic(232, 26-(int)((val*18.0)/(float)maxval+0.5), 3, 19, R2D_SafeCachePic("gfx/gmana.lmp")); + Sbar_DrawMPic(232, 27, 3, 19, R2D_SafeCachePic("gfx/gmanacov.lmp")); } @@ -2445,10 +2465,10 @@ static void Sbar_Hexen2DrawBasic(playerview_t *pv) chainpos = (195.0f*pv->stats[STAT_HEALTH]) / pv->stats[STAT_H2_MAXHEALTH]; if (chainpos < 0) chainpos = 0; - Sbar_DrawPic(45+((int)chainpos&7), 38, 222, 5, R2D_SafeCachePic("gfx/hpchain.lmp")); - Sbar_DrawPic(45+(int)chainpos, 36, 35, 9, R2D_SafeCachePic("gfx/hpgem.lmp")); - Sbar_DrawPic(43, 36, 10, 10, R2D_SafeCachePic("gfx/chnlcov.lmp")); - Sbar_DrawPic(267, 36, 10, 10, R2D_SafeCachePic("gfx/chnrcov.lmp")); + Sbar_DrawMPic(45+((int)chainpos&7), 38, 222, 5, R2D_SafeCachePic("gfx/hpchain.lmp")); + Sbar_DrawMPic(45+(int)chainpos, 36, 35, 9, R2D_SafeCachePic("gfx/hpgem.lmp")); + Sbar_DrawMPic(43, 36, 10, 10, R2D_SafeCachePic("gfx/chnlcov.lmp")); + Sbar_DrawMPic(267, 36, 10, 10, R2D_SafeCachePic("gfx/chnrcov.lmp")); Sbar_Hexen2DrawItem(pv, 144, 3, pv->sb_hexen2_cur_item); @@ -2458,8 +2478,8 @@ static void Sbar_Hexen2DrawMinimal(playerview_t *pv) { int y; y = -16; - Sbar_DrawPic(3, y, 31, 17, R2D_SafeCachePic("gfx/bmmana.lmp")); - Sbar_DrawPic(3, y+18, 31, 17, R2D_SafeCachePic("gfx/gmmana.lmp")); + Sbar_DrawMPic(3, y, 31, 17, R2D_SafeCachePic("gfx/bmmana.lmp")); + Sbar_DrawMPic(3, y+18, 31, 17, R2D_SafeCachePic("gfx/gmmana.lmp")); Sbar_DrawTinyStringf(10, y+6, "%03d", pv->stats[STAT_H2_BLUEMANA]); Sbar_DrawTinyStringf(10, y+18+6, "%03d", pv->stats[STAT_H2_GREENMANA]); @@ -2726,6 +2746,16 @@ void Sbar_Draw (playerview_t *pv) sb_updates++; + if (cl_sbar.value == 1 || scr_viewsize.value<100) + { + if (sbar_rect.x>r_refdef.grect.x) + { // left + R2D_TileClear (r_refdef.grect.x, r_refdef.grect.y+sbar_rect.height - sb_lines, sbar_rect.x - r_refdef.grect.x, sb_lines); + } + if (sbar_rect.x + 320 <= r_refdef.grect.x + sbar_rect.width && !headsup) + R2D_TileClear (sbar_rect.x + 320, r_refdef.grect.y+sbar_rect.height - sb_lines, sbar_rect.width - (320), sb_lines); + } + #ifdef HEXEN2 if (sbar_hexen2) { @@ -2763,17 +2793,6 @@ void Sbar_Draw (playerview_t *pv) else { //standard quake(world) hud. - // top line - if (sb_lines > 24) - { - if (!cl.spectator || pv->cam_state == CAM_WALLCAM || pv->cam_state == CAM_EYECAM) - Sbar_DrawInventory (pv); - else if (cl_sbar.ival) - Sbar_DrawPic (0, -24, 320, 24, sb_scorebar); //make sure we don't get HoM - if ((!headsup || sbar_rect.width<512) && cl.deathmatch) - Sbar_DrawFrags (pv); - } - // main area if (sb_lines > 0) { @@ -2824,6 +2843,17 @@ void Sbar_Draw (playerview_t *pv) Sbar_DrawNormal (pv); } + // top line + if (sb_lines > 24) + { + if (!cl.spectator || pv->cam_state == CAM_WALLCAM || pv->cam_state == CAM_EYECAM) + Sbar_DrawInventory (pv); + else if (cl_sbar.ival) + Sbar_DrawPic (0, -24, 320, 24, sb_scorebar); //make sure we don't get HoM + if ((!headsup || sbar_rect.width<512) && cl.deathmatch) + Sbar_DrawFrags (pv); + } + if (minidmoverlay) Sbar_MiniDeathmatchOverlay (pv); @@ -2832,16 +2862,6 @@ void Sbar_Draw (playerview_t *pv) R2D_ImageColours (1, 1, 1, 1); } - if (cl_sbar.value == 1 || scr_viewsize.value<100) - { - if (sbar_rect.x>r_refdef.grect.x) - { // left - R2D_TileClear (r_refdef.grect.x, r_refdef.grect.y+sbar_rect.height - sb_lines, sbar_rect.x - r_refdef.grect.x, sb_lines); - } - if (sbar_rect.x + 320 <= r_refdef.grect.x + sbar_rect.width && !headsup) - R2D_TileClear (sbar_rect.x + 320, r_refdef.grect.y+sbar_rect.height - sb_lines, sbar_rect.width - (320), sb_lines); - } - if (sb_lines > 24) Sbar_Voice(-32); else if (sb_lines > 0) @@ -2890,7 +2910,7 @@ void Sbar_IntermissionNumber (float x, float y, int num, int digits, int color, else frame = *ptr -'0'; - R2D_ScalePic (x,y, 16, 24, sb_nums[color][frame]); + R2D_ScalePicAtlas (x,y, 16, 24, sb_nums[color][frame]); x += 24; ptr++; } @@ -3721,17 +3741,17 @@ void Sbar_CoopIntermission (void) dig = cl.completed_time/60; Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 230 - 24*4, (sbar_rect.height - 200)/2 + 64, dig, 4, 0, false); num = cl.completed_time - dig*60; - R2D_ScalePic ((sbar_rect.width - 320)/2 + 230,(sbar_rect.height - 200)/2 + 64, 16, 24, sb_colon); - R2D_ScalePic ((sbar_rect.width - 320)/2 + 254,(sbar_rect.height - 200)/2 + 64, 16, 26, sb_nums[0][num/10]); - R2D_ScalePic ((sbar_rect.width - 320)/2 + 278,(sbar_rect.height - 200)/2 + 64, 16, 24, sb_nums[0][num%10]); + R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 230,(sbar_rect.height - 200)/2 + 64, 16, 24, sb_colon); + R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 254,(sbar_rect.height - 200)/2 + 64, 16, 26, sb_nums[0][num/10]); + R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 278,(sbar_rect.height - 200)/2 + 64, 16, 24, sb_nums[0][num%10]); //it is assumed that secrits/monsters are going to be constant for any player... Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 230 - 24*4, (sbar_rect.height - 200)/2 + 104, cl.playerview[pnum].stats[STAT_SECRETS], 4, 0, false); - R2D_ScalePic ((sbar_rect.width - 320)/2 + 230, (sbar_rect.height - 200)/2 + 104, 16, 24, sb_slash); + R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 230, (sbar_rect.height - 200)/2 + 104, 16, 24, sb_slash); Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 254, (sbar_rect.height - 200)/2 + 104, cl.playerview[pnum].stats[STAT_TOTALSECRETS], 4, 0, true); Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 230 - 24*4, (sbar_rect.height - 200)/2 + 144, cl.playerview[pnum].stats[STAT_MONSTERS], 4, 0, false); - R2D_ScalePic ((sbar_rect.width - 320)/2 + 230,(sbar_rect.height - 200)/2 + 144, 16, 24, sb_slash); + R2D_ScalePicAtlas ((sbar_rect.width - 320)/2 + 230,(sbar_rect.height - 200)/2 + 144, 16, 24, sb_slash); Sbar_IntermissionNumber ((sbar_rect.width - 320)/2 + 254, (sbar_rect.height - 200)/2 + 144, cl.playerview[pnum].stats[STAT_TOTALMONSTERS], 4, 0, true); } /* diff --git a/engine/client/wad.h b/engine/client/wad.h index 1aeffca38..dc172c544 100644 --- a/engine/client/wad.h +++ b/engine/client/wad.h @@ -43,36 +43,23 @@ typedef struct qbyte data[4]; // variably sized } qpic_t; -#ifdef GLQUAKE -typedef struct -{ - int texnum; - float sl, tl, sh, th; -} glpic_t; -#endif - -/* -//this is what's actually used. -#define MPIC_ALPHA 1 -typedef struct //use this so we don't have to go slow over pics, and don't have to shift too much data around. -{ - unsigned int width; //keeps alignment (which is handy in 32bit modes) - unsigned short height; - qbyte flags; - qbyte pad; - - union { - int dummy; -#ifdef GLQUAKE - glpic_t gl; -#endif - } d; - struct shader_s *shader; -} mpic_t; -*/ typedef struct shader_s shader_t; #define mpic_t shader_t +//atlased images within some larger atlas +//must not be tiled etc +typedef struct apic_s +{ + mpic_t *atlas; + float sl, tl, sh, th; + unsigned short x; + unsigned short y; + unsigned short width; + unsigned short height; + + struct apic_s *next; +} apic_t; + extern mpic_t *draw_disc; // also used on sbar diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index 1c19b3c08..117cd003a 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -62,7 +62,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "config.h" #else #ifndef MSVCLIBSPATH - #if _MSC_VER == 1200 + #ifdef MSVCLIBPATH + #define MSVCLIBSPATH STRINGIFY(MSVCLIBPATH) + #elif _MSC_VER == 1200 #define MSVCLIBSPATH "../libs/vc6-libs/" #else #define MSVCLIBSPATH "../libs/" diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 068ee3f7c..c4849cbac 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -1922,7 +1922,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in lerpcutoff = inf->lerpcutoff * r_lerpmuzzlehack.value; #ifndef SERVERONLY - if (qrenderer != QR_OPENGL || Sh_StencilShadowsActive() || e->fatness || lerpcutoff) + if (/*qrenderer != QR_OPENGL ||*/ Sh_StencilShadowsActive() || e->fatness || lerpcutoff) { mesh->xyz2_array = NULL; mesh->xyz_blendw[0] = 1; @@ -1982,6 +1982,9 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in } } + meshcache.vbo.vao = 0; + meshcache.vbo.vaodynamic = ~0; + meshcache.vbo.vaoenabled = 0; meshcache.acoords1 = mesh->xyz_array; meshcache.acoords2 = mesh->xyz2_array; meshcache.anorm = mesh->normals_array; diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index 9f1bdc055..4de4e974c 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -242,7 +242,8 @@ enum D3D_VDEC_ST3 = 1<<4, D3D_VDEC_NORM = 1<<5, D3D_VDEC_SKEL = 1<<6, - D3D_VDEC_MAX = 1<<7, + D3D_VDEC_POS2 = 1<<7, + D3D_VDEC_MAX = 1<<8, }; #define STRM_VERT 0 @@ -256,7 +257,8 @@ enum #define STRM_NORMT 8 #define STRM_BONENUM 9 #define STRM_BONEWEIGHT 10 -#define STRM_MAX 11 +#define STRM_VERT2 11 +#define STRM_MAX 12 static IDirect3DVertexDeclaration9 *vertexdecls[D3D_VDEC_MAX]; static void BE_ApplyTMUState(unsigned int tu, unsigned int flags) @@ -524,6 +526,17 @@ void D3D9BE_Reset(qboolean before) decl[elements].UsageIndex = 0; elements++; + if (i & D3D_VDEC_POS2) + { + decl[elements].Stream = STRM_VERT2; + decl[elements].Offset = 0; + decl[elements].Type = D3DDECLTYPE_FLOAT3; + decl[elements].Method = D3DDECLMETHOD_DEFAULT; + decl[elements].Usage = D3DDECLUSAGE_POSITION; + decl[elements].UsageIndex = 1; + elements++; + } + if (i & D3D_VDEC_COL4B) { decl[elements].Stream = STRM_COL; @@ -1700,8 +1713,42 @@ static void BE_SubmitMeshChain(unsigned int vertbase, unsigned int firstvert, un RQuantAdd(RQUANT_PRIMITIVEINDICIES, idxcount); } +static void R_FetchPlayerColour(unsigned int cv, vec3_t rgb) +{ + int i; + + if (cv >= 16) + { + rgb[0] = (((cv&0xff0000)>>16)**((unsigned char*)&d_8to24rgbtable[15]+0)) / (256.0*256); + rgb[1] = (((cv&0x00ff00)>>8)**((unsigned char*)&d_8to24rgbtable[15]+1)) / (256.0*256); + rgb[2] = (((cv&0x0000ff)>>0)**((unsigned char*)&d_8to24rgbtable[15]+2)) / (256.0*256); + return; + } + i = cv; + if (i >= 8) + { + i<<=4; + } + else + { + i<<=4; + i+=15; + } + i*=3; + rgb[0] = host_basepal[i+0] / 255.0; + rgb[1] = host_basepal[i+1] / 255.0; + rgb[2] = host_basepal[i+2] / 255.0; +/* if (!gammaworks) + { + *retred = gammatable[*retred]; + *retgreen = gammatable[*retgreen]; + *retblue = gammatable[*retblue]; + }*/ +} + static void BE_ApplyUniforms(program_t *prog, int permu) { + vec4_t param4; int h; int i; IDirect3DDevice9_SetVertexShader(pD3DDev9, prog->permu[permu].handle.hlsl.vert); @@ -1709,6 +1756,8 @@ static void BE_ApplyUniforms(program_t *prog, int permu) for (i = 0; i < prog->numparams; i++) { h = prog->permu[permu].parm[i]; + if (h == -1) + continue; switch (prog->parm[i].type) { case SP_M_PROJECTION: @@ -1720,6 +1769,10 @@ static void BE_ApplyUniforms(program_t *prog, int permu) case SP_M_MODEL: IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, h, shaderstate.m_model, 4); break; + case SP_E_VBLEND: + IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, h, shaderstate.meshlist[0]->xyz_blendw, 2); + break; + case SP_V_EYEPOS: IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, r_origin, 1); @@ -1783,15 +1836,22 @@ static void BE_ApplyUniforms(program_t *prog, int permu) break; case SP_E_COLOURSIDENT: if (shaderstate.flags & BEF_FORCECOLOURMOD) + IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, shaderstate.curentity->shaderRGBAf, 1); + else { vec4_t tmp = {1, 1, 1, shaderstate.curentity->shaderRGBAf[3]}; IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, tmp, 1); } - else - IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, shaderstate.curentity->shaderRGBAf, 1); break; + case SP_E_TOPCOLOURS: + R_FetchPlayerColour(shaderstate.curentity->topcolour, param4); + IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, param4, 3); + break; case SP_E_BOTTOMCOLOURS: + R_FetchPlayerColour(shaderstate.curentity->bottomcolour, param4); + IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, h, param4, 3); + break; case SP_M_ENTBONES: case SP_M_MODELVIEW: @@ -1835,7 +1895,10 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertbase, unsigned in if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].handle.hlsl.vert) perm |= PERMUTATION_FOG; if (p->permu[perm|PERMUTATION_FRAMEBLEND].handle.hlsl.vert && shaderstate.batchvbo && shaderstate.batchvbo->coord2.d3d.buff) + { perm |= PERMUTATION_FRAMEBLEND; + vdec |= D3D_VDEC_POS2; + } // if (p->permu[perm|PERMUTATION_DELUXE].handle.hlsl.vert && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe) // perm |= PERMUTATION_DELUXE; if (shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].handle.hlsl.vert) @@ -1904,7 +1967,12 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertbase, unsigned in if (vdec & D3D_VDEC_ST0) { if (shaderstate.batchvbo) - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.batchvbo->texcoord.d3d.buff, shaderstate.batchvbo->texcoord.d3d.offs, sizeof(vbovdata_t))); + { + if (shaderstate.batchvbo && !shaderstate.batchvbo->vaodynamic) + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.batchvbo->texcoord.d3d.buff, shaderstate.batchvbo->texcoord.d3d.offs, sizeof(vbovdata_t))); + else + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.batchvbo->texcoord.d3d.buff, shaderstate.batchvbo->texcoord.d3d.offs, sizeof(vec2_t))); + } else { int mno; @@ -1950,9 +2018,18 @@ static void BE_RenderMeshProgram(shader_t *s, unsigned int vertbase, unsigned in { if (shaderstate.batchvbo) { - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORM, shaderstate.batchvbo->normals.d3d.buff, shaderstate.batchvbo->normals.d3d.offs, sizeof(vbovdata_t))); - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORMS, shaderstate.batchvbo->svector.d3d.buff, shaderstate.batchvbo->svector.d3d.offs, sizeof(vbovdata_t))); - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORMT, shaderstate.batchvbo->tvector.d3d.buff, shaderstate.batchvbo->tvector.d3d.offs, sizeof(vbovdata_t))); + if (shaderstate.batchvbo && !shaderstate.batchvbo->vaodynamic) + { + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORM, shaderstate.batchvbo->normals.d3d.buff, shaderstate.batchvbo->normals.d3d.offs, sizeof(vbovdata_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORMS, shaderstate.batchvbo->svector.d3d.buff, shaderstate.batchvbo->svector.d3d.offs, sizeof(vbovdata_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORMT, shaderstate.batchvbo->tvector.d3d.buff, shaderstate.batchvbo->tvector.d3d.offs, sizeof(vbovdata_t))); + } + else + { + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORM, shaderstate.batchvbo->normals.d3d.buff, shaderstate.batchvbo->normals.d3d.offs, sizeof(vec3_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORMS, shaderstate.batchvbo->svector.d3d.buff, shaderstate.batchvbo->svector.d3d.offs, sizeof(vec3_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_NORMT, shaderstate.batchvbo->tvector.d3d.buff, shaderstate.batchvbo->tvector.d3d.offs, sizeof(vec3_t))); + } } else if (shaderstate.meshlist[0]->normals_array && shaderstate.meshlist[0]->snormals_array && shaderstate.meshlist[0]->tnormals_array) { @@ -2090,9 +2167,16 @@ static void BE_DrawMeshChain_Internal(void) } /*vertex buffers are common to all passes*/ - if (shaderstate.batchvbo) + if (shaderstate.batchvbo && !shaderstate.batchvbo->vaodynamic) { d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, shaderstate.batchvbo->coord.d3d.buff, shaderstate.batchvbo->coord.d3d.offs, sizeof(vbovdata_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT2, shaderstate.batchvbo->coord2.d3d.buff, shaderstate.batchvbo->coord2.d3d.offs, sizeof(vbovdata_t))); + vertfirst = 0; + } + else if (shaderstate.batchvbo) + { + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, shaderstate.batchvbo->coord.d3d.buff, shaderstate.batchvbo->coord.d3d.offs, sizeof(vecV_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT2, shaderstate.batchvbo->coord2.d3d.buff, shaderstate.batchvbo->coord2.d3d.offs, sizeof(vecV_t))); vertfirst = 0; } else @@ -2112,6 +2196,7 @@ static void BE_DrawMeshChain_Internal(void) } d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynxyz_buff)); d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, shaderstate.dynxyz_buff, shaderstate.dynxyz_offs - vertcount*sizeof(vecV_t), sizeof(vecV_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT2, NULL, 0, sizeof(vecV_t))); } /*index buffers are also common (note that we may still need to stream these when dealing with bsp geometry, to cope with gaps. this is faster than using multiple draw calls.)*/ @@ -2310,6 +2395,7 @@ static void D3D9BE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t * IDirect3DDevice9_CreateVertexBuffer(pD3DDev9, sizeof(*vbovdata) * maxvboverts, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &vbuff, NULL); vbovdata = NULL; + vbo->vaodynamic = 0; vbo->coord.d3d.buff = vbuff; vbo->coord.d3d.offs = (quintptr_t)&vbovdata->coord; vbo->texcoord.d3d.buff = vbuff; @@ -3324,15 +3410,44 @@ void D3D9BE_DrawWorld (qboolean drawworld, qbyte *vis) } void D3D9BE_VBO_Begin(vbobctx_t *ctx, size_t maxsize) { + IDirect3DVertexBuffer9 *buf; + IDirect3DDevice9_CreateVertexBuffer(pD3DDev9, maxsize, D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &buf, NULL); + ctx->vboptr[0] = buf; + + IDirect3DVertexBuffer9_Lock(buf, 0, maxsize, &ctx->fallback, D3DLOCK_DISCARD); + + ctx->pos = 0; } void D3D9BE_VBO_Data(vbobctx_t *ctx, void *data, size_t size, vboarray_t *varray) { + IDirect3DVertexBuffer9 *buf = ctx->vboptr[0]; + memcpy((char*)ctx->fallback + ctx->pos, data, size); + varray->d3d.buff = buf; + varray->d3d.offs = ctx->pos; + ctx->pos += size; } void D3D9BE_VBO_Finish(vbobctx_t *ctx, void *edata, size_t esize, vboarray_t *earray) { + IDirect3DIndexBuffer9 *buf; + IDirect3DVertexBuffer9 *vbuf = ctx->vboptr[0]; + IDirect3DVertexBuffer9_Unlock(vbuf); + ctx->fallback = NULL; + + IDirect3DDevice9_CreateIndexBuffer(pD3DDev9, esize, 0, D3DFMT_QINDEX, D3DPOOL_MANAGED, &buf, NULL); + ctx->vboptr[1] = buf; + IDirect3DIndexBuffer9_Lock(buf, 0, esize, &ctx->fallback, D3DLOCK_DISCARD); + memcpy(ctx->fallback, edata, esize); + IDirect3DIndexBuffer9_Unlock(buf); + ctx->fallback = NULL; + + earray->d3d.buff = buf; + earray->d3d.offs = 0; } void D3D9BE_VBO_Destroy(vboarray_t *vearray) { + IUnknown *ebuf = vearray->d3d.buff; + if (ebuf) + ebuf->lpVtbl->Release(ebuf); } void D3D9BE_Scissor(srect_t *srect) diff --git a/engine/d3d/d3d_shader.c b/engine/d3d/d3d_shader.c index b98a40c1e..cb5cb3359 100644 --- a/engine/d3d/d3d_shader.c +++ b/engine/d3d/d3d_shader.c @@ -146,6 +146,8 @@ static qboolean D3D9Shader_CreateProgram (program_t *prog, const char *sname, un D3DXMACRO defines[64]; LPD3DXBUFFER code = NULL, errors = NULL; qboolean success = false; + char defbuf[2048]; + char *defbufe; if (geom || tcs || tes) { @@ -174,10 +176,11 @@ static qboolean D3D9Shader_CreateProgram (program_t *prog, const char *sname, un defines[consts].Definition = __DATE__; consts++; - for (; *precompilerconstants; precompilerconstants++) + for (defbufe = defbuf; *precompilerconstants; precompilerconstants++) { - defines[consts].Name = NULL; - defines[consts].Definition = NULL; + defines[consts].Definition = COM_ParseOut(*precompilerconstants+7, defbufe, defbuf+sizeof(defbuf) - defbufe-1); + defines[consts].Name = defbufe; + defbufe += strlen(defbufe)+1; consts++; } diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index 5ee0ddac0..f9e70cb04 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -702,11 +702,13 @@ static qboolean D3D9_VID_Init(rendererstate_t *info, unsigned char *palette) ShowWindow(mainwindow, SW_NORMAL); - IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); + IDirect3DDevice9_Clear(pD3DDev9, 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); IDirect3DDevice9_BeginScene(pD3DDev9); IDirect3DDevice9_EndScene(pD3DDev9); IDirect3DDevice9_Present(pD3DDev9, NULL, NULL, NULL, NULL); + D3D9_Set2D(); + // pD3DX->lpVtbl->GetBufferSize((void*)pD3DX, &width, &height); @@ -1011,6 +1013,8 @@ static void (D3D9_SCR_UpdateScreen) (void) noworld = false; nohud = false; + D3D9_Set2D(); + #ifdef VM_CG if (CG_Refresh()) nohud = true; @@ -1031,10 +1035,6 @@ static void (D3D9_SCR_UpdateScreen) (void) } } - if (R2D_Flush) - R2D_Flush(); - D3D9_Set2D(); - R2D_BrightenScreen(); scr_con_forcedraw = false; diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index d3a774ad4..7e22c0dd6 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -1811,10 +1811,6 @@ FloatingPointModel="2" UsePrecompiledHeader="2" PrecompiledHeaderThrough="quakedef.h" - PrecompiledHeaderFile=".\ftequake___Win32_GLRelease/ftequake.pch" - AssemblerListingLocation=".\ftequake___Win32_GLRelease/" - ObjectFile=".\ftequake___Win32_GLRelease/" - ProgramDataBaseFileName=".\ftequake___Win32_GLRelease/" BrowseInformation="1" WarningLevel="3" SuppressStartupBanner="true" diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index da348276c..31ad582ac 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -680,6 +680,12 @@ static void BE_ApplyAttributes(unsigned int bitstochange, unsigned int bitstoend break; #endif case VATTR_TEXCOORD: + if (!shaderstate.pendingtexcoordvbo[0] && !shaderstate.pendingtexcoordpointer[0]) + { + shaderstate.sha_attr &= ~(1u<coord.gl.vbo; shaderstate.pendingvertexpointer = shaderstate.sourcevbo->coord.gl.addr; shaderstate.colourarraytype = GL_FLOAT; + shaderstate.pendingtexcoordvbo[0] = shaderstate.sourcevbo->texcoord.gl.vbo; + shaderstate.pendingtexcoordpointer[0] = shaderstate.sourcevbo->texcoord.gl.addr; + shaderstate.pendingtexcoordparts[0] = 2; shaderstate.currentvao = vbo->vao; qglBindVertexArray(vbo->vao); @@ -1496,12 +1505,12 @@ void GLBE_Init(void) R_InitFlashblends(); + memset(&shaderstate.streamvbo, 0, sizeof(shaderstate.streamvbo)); + memset(&shaderstate.streamebo, 0, sizeof(shaderstate.streamebo)); + memset(&shaderstate.streamvao, 0, sizeof(shaderstate.streamvao)); //only do this where we have to. if (qglBufferDataARB && gl_config_nofixedfunc) { - memset(&shaderstate.streamvbo, 0, sizeof(shaderstate.streamvbo)); - memset(&shaderstate.streamebo, 0, sizeof(shaderstate.streamebo)); - memset(&shaderstate.streamvao, 0, sizeof(shaderstate.streamvao)); qglGenBuffersARB(sizeof(shaderstate.streamvbo)/sizeof(shaderstate.streamvbo[0]), shaderstate.streamvbo); qglGenBuffersARB(sizeof(shaderstate.streamebo)/sizeof(shaderstate.streamebo[0]), shaderstate.streamebo); if (qglGenVertexArrays) @@ -3438,7 +3447,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas #endif { #ifndef GLSLONLY - if (pass->numtcmods) + if (0)//pass->numtcmods) GenerateTCMods(pass, 0); else #endif @@ -4387,6 +4396,11 @@ void GLBE_SubmitBatch(batch_t *batch) { shaderstate.sourcevbo = batch->vbo; shaderstate.colourarraytype = GL_FLOAT; + + if (!batch->vbo->vao) + batch->vbo->vao = shaderstate.streamvao[0]; + batch->vbo->vaodynamic = ~0; + batch->vbo->vaoenabled = 0; } else { diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 34460fb60..9a21fbdeb 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -1523,7 +1523,7 @@ void Font_Free(struct font_s *f) //maps a given virtual screen coord to a pixel coord, which matches the font's height/width values void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py) { - if (R2D_Flush && curfont != font) + if (R2D_Flush && (R2D_Flush != Font_Flush || curfont != font)) R2D_Flush(); R2D_Flush = Font_Flush; @@ -1544,7 +1544,7 @@ void Font_Transform(float vx, float vy, int *px, int *py) } void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx, float szy, float *px, float *py) { - if (R2D_Flush && curfont != font) + if (R2D_Flush && (R2D_Flush != Font_Flush || curfont != font)) R2D_Flush(); R2D_Flush = Font_Flush; diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 48f5ccbb2..0db1280cf 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -3202,7 +3202,7 @@ static void Mod_Batches_AllocLightmaps(model_t *mod) } samps /= 4; samps = sqrt(samps); - if (j > 128) + if (j > 128 || !r_dynamic.ival) samps *= 2; mod->lightmaps.width = bound(j, samps, LMBLOCK_SIZE_MAX); mod->lightmaps.height = bound(j, samps, LMBLOCK_SIZE_MAX); diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 5efd4d652..0664cbfd7 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -29,9 +29,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif #ifdef _WIN32 +#ifndef WIN32_BLOATED #define WIN32_LEAN_AND_MEAN +#endif #include -#include #if defined(WINAPI_FAMILY) && !defined(WINRT) #if WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index 2177e90c4..b8045f290 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -637,6 +637,88 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND "#endif\n" }, #endif +#ifdef D3D9QUAKE +{QR_DIRECT3D9, 9, "defaultskin", +"!!permu FRAMEBLEND\n" +"!!permu UPPERLOWER\n" +"struct a2v\n" +"{\n" +"float3 pos: POSITION0;\n" +"#ifdef FRAMEBLEND\n" +"float3 pos2: POSITION1;\n" +"#endif\n" +"float2 tc: TEXCOORD0;\n" +"float3 normal: NORMAL;\n" +"};\n" +"struct v2f\n" +"{\n" +"#ifndef FRAGMENT_SHADER\n" +"float4 pos: POSITION;\n" +"#endif\n" +"float2 tc: TEXCOORD0;\n" +"float3 light: TEXCOORD1;\n" +"};\n" + +//#include + +"#ifdef VERTEX_SHADER\n" +"float3 e_light_dir;\n" +"float3 e_light_mul;\n" +"float3 e_light_ambient;\n" +"float2 e_vblend;\n" +"float4x4 m_model;\n" +"float4x4 m_view;\n" +"float4x4 m_projection;\n" +"v2f main (a2v inp)\n" +"{\n" +"v2f outp;\n" +"float4 pos;\n" +"#ifdef FRAMEBLEND\n" +"pos = float4(e_vblend.x*inp.pos + e_vblend.y*inp.pos2, 1);\n" +"#else\n" +"pos = float4(inp.pos, 1);\n" +"#endif\n" +"outp.pos = mul(m_model, pos);\n" +"outp.pos = mul(m_view, outp.pos);\n" +"outp.pos = mul(m_projection, outp.pos);\n" + +"float d = dot(inp.normal, e_light_dir);\n" +"outp.light = e_light_ambient + (d * e_light_mul);\n" +"outp.tc = inp.tc.xy;\n" +"return outp;\n" +"}\n" +"#endif\n" +"#ifdef FRAGMENT_SHADER\n" +"float4 e_colourident;\n" +"float3 e_uppercolour;\n" +"float3 e_lowercolour;\n" +"sampler s_diffuse; /*diffuse*/\n" +"sampler s_upper; /*upper*/\n" +"sampler s_lower; /*lower*/\n" +"sampler s_fullbright; /*fullbright*/\n" +"float4 main (v2f inp) : SV_TARGET\n" +"{\n" +"float4 col;\n" +"col = tex2D(s_diffuse, inp.tc);\n" +"#ifdef UPPER\n" +"float4 uc = tex2D(s_upper, inp.tc);\n" +"col.rgb += uc.rgb*e_uppercolour * uc.a;\n" +"#endif\n" +"#ifdef LOWER\n" +"float4 lc = tex2D(s_lower, inp.tc);\n" +"col.rgb += lc.rgb*e_lowercolour * lc.a;\n" +"#endif\n" +"col.rgb *= inp.light;\n" +"#ifdef FULLBRIGHT\n" +"float4 fb = tex2D(s_fullbright, inp.tc);\n" +"col.rgb = mix(col.rgb, fb.rgb, fb.a);\n" +"#endif\n" +"return col * e_colourident;\n" +// return fog4(col * e_colourident); +"}\n" +"#endif\n" +}, +#endif #ifdef D3D11QUAKE {QR_DIRECT3D11, 11, "defaultskin", "struct a2v\n" diff --git a/engine/qclib/qccgui.c b/engine/qclib/qccgui.c index 5a0ca083e..00c076802 100644 --- a/engine/qclib/qccgui.c +++ b/engine/qclib/qccgui.c @@ -986,6 +986,10 @@ HWND CreateAnEditControl(HWND parent, pbool *scintillaokay) c = buf; while(*c == ' ' || *c == '\t') c++; + if (c[0] == '#') + continue; + if (c[0] == '/' && c[1] == '/') + continue; msg = strtoul(c, &c, 0); while(*c == ' ' || *c == '\t') c++; diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 5f9d4415f..244d6bfe8 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -2768,6 +2768,12 @@ void SV_GibFilterInit(void) SV_GibFilterAdd("progs/gib2.mdl", -1, -1, false); SV_GibFilterAdd("progs/gib3.mdl", -1, -1, false); SV_GibFilterAdd("progs/h_player.mdl", -1, -1, false); +// SV_GibFilterAdd("progs/player.mdl", 49, 49, false); +// SV_GibFilterAdd("progs/player.mdl", 60, 60, false); +// SV_GibFilterAdd("progs/player.mdl", 69, 69, false); +// SV_GibFilterAdd("progs/player.mdl", 84, 84, false); +// SV_GibFilterAdd("progs/player.mdl", 93, 93, false); +// SV_GibFilterAdd("progs/player.mdl", 102, 102, false); return; } while(file) diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 081b9626c..65342f7f7 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -249,7 +249,7 @@ void SV_New_f (void) if (dpcompat_nopreparse.ival && progstype != PROG_QW) { SV_PrintToClient(host_client, PRINT_HIGH, "This server now has network preparsing disabled, and thus only supports NetQuake clients\n"); - Con_Printf("%s was not using NQ protocols\n"); + Con_Printf("%s was not using NQ protocols\n", host_client->name); host_client->drop = true; return; } @@ -475,7 +475,7 @@ void SVNQ_New_f (void) if (dpcompat_nopreparse.ival && progstype == PROG_QW) { SV_PrintToClient(host_client, PRINT_HIGH, "This server now has network preparsing disabled, and thus only supports QuakeWorld clients\n"); - Con_Printf("%s was not using QW protocols\n"); + Con_Printf("%s was not using QW protocols\n", host_client->name); host_client->drop = true; return; }