From cb630bde49a46b3a1fd00ecfa95aad0f8432b919 Mon Sep 17 00:00:00 2001 From: ac-stef Date: Sun, 4 Sep 2016 17:44:22 +0200 Subject: [PATCH] add per-map overrides to disable graphics features The mapper has now the choice to disable several graphics features on the client (for his map only, of course). The overrides are stored in the map header. mapoverride_nowaterreflect If "1", water reflection is disabled. Useful, when odd water colours are used to emulate other liquids that are not supposed to be that reflective. mapoverride_limitwaveheight If "1", waveheight is capped at 0.1 max. Useful for small water areas (like puddles), where higher waves would look weird. mapoverride_nostencilshadows If "1", stencil shadows are disabled. On clients, where stencil shadows are otherwise enabled, blob shadows are used instead. If shadows are disabled anyway, they stay disabled. Useful for dim maps, where hard shadows make no sense. The player is free to ignore any of those overrides: ignoreoverride_nowaterreflect If "1", mapoverride_nowaterreflect is ignored and regular client settings are used. ignoreoverride_limitwaveheight If "1", mapoverride_limitwaveheight is ignored, and "waveheight" is used unchanged. ignoreoverride_nostencilshadows If "1", mapoverride_nostencilshadows is ignored. DOCREF mapoverride_nowaterreflect ignoreoverride_nowaterreflect DOCREF mapoverride_limitwaveheight ignoreoverride_limitwaveheight DOCREF mapoverride_nostencilshadows ignoreoverride_nostencilshadows --- config/menus_edit.cfg | 4 ++++ config/menus_settings.cfg | 3 +++ source/src/cube.h | 2 +- source/src/rendergl.cpp | 19 ++++++++++++++----- source/src/rendermodel.cpp | 4 ++-- source/src/water.cpp | 10 ++++++++-- source/src/world.h | 8 +++++++- source/src/worldio.cpp | 14 ++++++++++++++ 8 files changed, 53 insertions(+), 11 deletions(-) diff --git a/config/menus_edit.cfg b/config/menus_edit.cfg index 88498683..ba4b8b1a 100644 --- a/config/menus_edit.cfg +++ b/config/menus_edit.cfg @@ -181,6 +181,10 @@ menuinit [ menuitem "" -1 menuitemtextinput (concatword "Ambient light (0..255 or 0xrrggbb, default 0):\t") (if (< $ambient 256) $ambient (concatword "0x" (h0 6 $ambient))) [ambient $arg1] menuitem "" -1 + menuitemcheckbox "Map override: Disable water reflection" "$mapoverride_nowaterreflect" [ mapoverride_nowaterreflect $arg1 ] + menuitemcheckbox "Map override: Limit water waveheight" "$mapoverride_limitwaveheight" [ mapoverride_limitwaveheight $arg1 ] + menuitemcheckbox "Map override: Disable stencil shadows" "$mapoverride_nostencilshadows" [ mapoverride_nostencilshadows $arg1 ] + menuitem "" -1 push n (getnotexture) if (! (strlen $n)) [n = ] menuitem (concatword "Notexture:\t\t\t\t" (pop n)) [showmenu "Set notexture"] diff --git a/config/menus_settings.cfg b/config/menus_settings.cfg index 0a3508bd..f4f84e50 100644 --- a/config/menus_settings.cfg +++ b/config/menus_settings.cfg @@ -396,6 +396,9 @@ const setshadowq [ menuitemcheckbox [Dynamic lights: ] "$dynlight" [ dynlight $arg1 ] menuitemcheckbox [Bulletholes: ] "$bullethole" [ bullethole $arg1 ] menuitemcheckbox [Scorch: ] "$scorch" [ scorch $arg1 ] +menuitemcheckbox "Ignore map override: Disable water reflection" "$ignoreoverride_nowaterreflect" [ ignoreoverride_nowaterreflect $arg1 ] +menuitemcheckbox "Ignore map override: Limit water waveheight" "$ignoreoverride_limitwaveheight" [ ignoreoverride_limitwaveheight $arg1 ] +menuitemcheckbox "Ignore map override: Disable stencil shadows" "$ignoreoverride_nostencilshadows" [ ignoreoverride_nostencilshadows $arg1 ] menuitem [Enable 0.93 FOV compatiblity...] [ fovcompat; sleep 100 fovcompatmenu ] menuitem [] -1 menuitem [FPS Range...] [ showmenu [FPS Range] ] diff --git a/source/src/cube.h b/source/src/cube.h index 89ef675c..8e2d8e56 100644 --- a/source/src/cube.h +++ b/source/src/cube.h @@ -49,7 +49,7 @@ extern int xtraverts; extern float fovy, aspect; extern int farplane; extern bool minimap, reflecting, refracting; -extern int stenciling, stencilshadow; +extern int stenciling, stencilshadow, effective_stencilshadow; extern bool intermission; extern int arenaintermission; extern hashtable mapinfo; diff --git a/source/src/rendergl.cpp b/source/src/rendergl.cpp index 7a1bdf3b..f98d1bf7 100644 --- a/source/src/rendergl.cpp +++ b/source/src/rendergl.cpp @@ -1016,8 +1016,17 @@ void readdepth(int w, int h, vec &pos) pos = vec(world.x, world.y, world.z).div(world.w); } +VARP(ignoreoverride_nowaterreflect, 0, 0, 1); +VARP(ignoreoverride_nostencilshadows, 0, 0, 1); + +int effective_stencilshadow = 0; + void gl_drawframe(int w, int h, float changelod, float curfps) { + extern int mapoverride_nostencilshadows, mapoverride_nowaterreflect; + effective_stencilshadow = mapoverride_nostencilshadows && !ignoreoverride_nostencilshadows ? 0 : stencilshadow; + bool effective_waterreflect = waterreflect && (!mapoverride_nowaterreflect || ignoreoverride_nowaterreflect); + dodynlights(); drawminimap(w, h); @@ -1055,7 +1064,7 @@ void gl_drawframe(int w, int h, float changelod, float curfps) transplayer(); readmatrices(); - if(!underwater && waterreflect) + if(!underwater && effective_waterreflect) { extern int wx1; if(wx1>=0) @@ -1066,8 +1075,8 @@ void gl_drawframe(int w, int h, float changelod, float curfps) } } - if(stencilshadow && hasstencil && stencilbits >= 8) glClearStencil((hasSTS || hasST2) && !hasSTW ? 128 : 0); - glClear((outsidemap(camera1) ? GL_COLOR_BUFFER_BIT : 0) | GL_DEPTH_BUFFER_BIT | (stencilshadow && hasstencil && stencilbits >= 8 ? GL_STENCIL_BUFFER_BIT : 0)); + if(effective_stencilshadow && hasstencil && stencilbits >= 8) glClearStencil((hasSTS || hasST2) && !hasSTW ? 128 : 0); + glClear((outsidemap(camera1) ? GL_COLOR_BUFFER_BIT : 0) | GL_DEPTH_BUFFER_BIT | (effective_stencilshadow && hasstencil && stencilbits >= 8 ? GL_STENCIL_BUFFER_BIT : 0)); glEnable(GL_TEXTURE_2D); @@ -1105,7 +1114,7 @@ void gl_drawframe(int w, int h, float changelod, float curfps) rendermapmodels(); endmodelbatches(); - if(stencilshadow && hasstencil && stencilbits >= 8) drawstencilshadows(); + if(effective_stencilshadow && hasstencil && stencilbits >= 8) drawstencilshadows(); startmodelbatches(); renderentities(); @@ -1133,7 +1142,7 @@ void gl_drawframe(int w, int h, float changelod, float curfps) render_particles(curtime, PT_DECAL_MASK); - int nquads = renderwater(hf, !waterreflect || underwater ? 0 : reflecttex, !waterreflect || !waterrefract || underwater ? 0 : refracttex); + int nquads = renderwater(hf, !effective_waterreflect || underwater ? 0 : reflecttex, !effective_waterreflect || !waterrefract || underwater ? 0 : refracttex); render_particles(curtime, ~PT_DECAL_MASK); diff --git a/source/src/rendermodel.cpp b/source/src/rendermodel.cpp index cd019fd4..df31ecd1 100644 --- a/source/src/rendermodel.cpp +++ b/source/src/rendermodel.cpp @@ -671,7 +671,7 @@ void endmodelbatches(bool flush) } renderbatchedmodel(b.m, bm); } - if(dynshadow && b.m->hasshadows() && (!reflecting || refracting) && (!stencilshadow || !hasstencil || stencilbits < 8)) + if(dynshadow && b.m->hasshadows() && (!reflecting || refracting) && (!effective_stencilshadow || !hasstencil || stencilbits < 8)) { loopvj(b.batched) { @@ -780,7 +780,7 @@ void rendermodel(const char *mdl, int anim, int tex, float rad, const vec &o, fl if(!OUTBORD(x, y)) { sqr *s = S(x, y); - if(!(anim&ANIM_TRANSLUCENT) && dynshadow && m->hasshadows() && (!reflecting || refracting) && (!stencilshadow || !hasstencil || stencilbits < 8)) + if(!(anim&ANIM_TRANSLUCENT) && dynshadow && m->hasshadows() && (!reflecting || refracting) && (!effective_stencilshadow || !hasstencil || stencilbits < 8)) { vec center(o.x, o.y, s->floor); if(s->type==FHF) center.z -= s->vdelta/4.0f; diff --git a/source/src/water.cpp b/source/src/water.cpp index 129da005..78c8f011 100644 --- a/source/src/water.cpp +++ b/source/src/water.cpp @@ -34,7 +34,10 @@ void setwatercolor(const char *r, const char *g, const char *b, const char *a) } COMMANDN(watercolour, setwatercolor, "ssss"); + FVAR(waveheight, 0, 0.3f, 1.0f); +VARP(ignoreoverride_limitwaveheight, 0, 0, 1); +float effective_waveheight = 0.3f; void getwatercolour() { @@ -69,7 +72,7 @@ COMMAND(setwatercolour, "si"); float angle = v1*v2*0.1f/(2*M_PI) + t; \ float s = angle - int(angle) - 0.5f; \ s *= 8 - fabs(s)*16; \ - float h = waveheight*0.5f*s; \ + float h = effective_waveheight*0.5f*s; \ varray::attrib(v1, v2, v3+h); \ body; \ } @@ -81,7 +84,7 @@ COMMAND(setwatercolour, "si"); }) #define VERTWT(vertwt, defbody, body) \ VERTWC(vertwt, defbody, { \ - float duv = waveheight*0.5f*v; \ + float duv = effective_waveheight*0.5f*v; \ body; \ }) @@ -192,6 +195,9 @@ int renderwater(float hf, GLuint reflecttex, GLuint refracttex) { if(wx1<0) return nquads; + extern int mapoverride_limitwaveheight; + effective_waveheight = mapoverride_limitwaveheight && !ignoreoverride_limitwaveheight ? 0.1f : waveheight; + wx1 -= wx1%watersubdiv; wy1 -= wy1%watersubdiv; diff --git a/source/src/world.h b/source/src/world.h index ce779caa..39c2c2b8 100644 --- a/source/src/world.h +++ b/source/src/world.h @@ -55,7 +55,13 @@ enum INVISIBLE = 1<<2 }; -enum { MHF_AUTOMAPCONFIG = 1<<0 }; +enum +{ + MHF_AUTOMAPCONFIG = 1<<0, // autogenerate map-config during map save + MHF_DISABLEWATERREFLECT = 1 << 8, // force waterreflect to zero + MHF_LIMITWATERWAVEHEIGHT = 1 << 9, // limit waveheight to 0.1 + MHF_DISABLESTENCILSHADOWS = 1 << 10 // force stencilshadow to 0 +}; #define MAPVERSION 10 // default map format version to be written (bump if map format changes, see worldio.cpp) diff --git a/source/src/worldio.cpp b/source/src/worldio.cpp index 34e4e0b8..9ca3452a 100644 --- a/source/src/worldio.cpp +++ b/source/src/worldio.cpp @@ -775,6 +775,17 @@ int maploaded = 0; VAR(curmaprevision, 1, 0, 0); COMMANDF(getmaptimestamp, "s", (char *fmt) { result(hdr.timestamp ? timestring((time_t)hdr.timestamp, *fmt != 'U', *fmt == 'U' ? fmt + 1 : fmt) : "no timestamp stored"); }); +void changemapflag(int val, int mask) +{ + int old = hdr.flags; + if(val) hdr.flags |= mask; + else hdr.flags &= ~mask; + if(editmode && old != hdr.flags) unsavededits++; +} +VARF(mapoverride_nowaterreflect, 0, 0, 1, changemapflag(mapoverride_nowaterreflect, MHF_DISABLEWATERREFLECT)); +VARF(mapoverride_limitwaveheight, 0, 0, 1, changemapflag(mapoverride_limitwaveheight, MHF_LIMITWATERWAVEHEIGHT)); +VARF(mapoverride_nostencilshadows, 0, 0, 1, changemapflag(mapoverride_nostencilshadows, MHF_DISABLESTENCILSHADOWS)); + extern char *mlayout; extern int Mv, Ma, Hhits; extern float Mh; @@ -852,6 +863,9 @@ int load_world(char *mname) // still supports all map formats that have e } if(hdr.version < 10) hdr.waterlevel *= WATERLEVELSCALING; setfvar("waterlevel", float(hdr.waterlevel) / WATERLEVELSCALING); + mapoverride_nowaterreflect = (hdr.flags & MHF_DISABLEWATERREFLECT) ? 1 : 0; + mapoverride_limitwaveheight = (hdr.flags & MHF_LIMITWATERWAVEHEIGHT) ? 1 : 0; + mapoverride_nostencilshadows = (hdr.flags & MHF_DISABLESTENCILSHADOWS) ? 1 : 0; // read and convert all entities persistent_entity *tempents = new persistent_entity[hdr.numents];