Added r_graphics cvar, so that you can finally turn graphics off/on like modern games (yay simplicity)... Doing so results in ascii-style rendering, just because.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5290 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2018-08-13 06:27:29 +00:00
parent c97fa33879
commit a7b696ef8c
11 changed files with 217 additions and 37 deletions

View File

@ -792,6 +792,8 @@ const char *presetexec[] =
"if cl_deadbodyfilter == 0 then seta cl_deadbodyfilter 1;" //as useful as 2 is, some mods use death frames for crouching etc.
"seta gl_simpleitems 1;"
"seta cl_fullpitch 1;seta maxpitch \"\";seta minpitch \"\";" //mimic quakespasm where possible.
"seta r_graphics 1;"
"seta r_renderscale 1;"
, // fast options
"gl_texturemode ln;"
@ -1176,7 +1178,7 @@ void M_Menu_Render_f (void)
static const char *logcentervalues[] = {"0", "1", "2", NULL};
menu_t *menu;
extern cvar_t r_novis, cl_item_bobbing, r_waterwarp, r_nolerp, r_noframegrouplerp, r_fastsky, gl_nocolors, gl_lerpimages, r_wateralpha, r_drawviewmodel, gl_cshiftenabled, r_hdr_irisadaptation, scr_logcenterprint;
extern cvar_t r_novis, cl_item_bobbing, r_waterwarp, r_nolerp, r_noframegrouplerp, r_fastsky, gl_nocolors, gl_lerpimages, r_wateralpha, r_drawviewmodel, gl_cshiftenabled, r_hdr_irisadaptation, scr_logcenterprint, r_fxaa, r_graphics;
#ifdef GLQUAKE
extern cvar_t r_bloom;
#endif
@ -1187,6 +1189,7 @@ void M_Menu_Render_f (void)
{
MB_REDTEXT("Rendering Options", true),
MB_TEXT("^Ue080^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue081^Ue082", true),
MB_CHECKBOXCVAR("Graphics", r_graphics, 0), //graphics on / off. Its a general dig at modern games not having any real options.
MB_CHECKBOXCVAR("Disable VIS", r_novis, 0),
MB_CHECKBOXCVAR("Fast Sky", r_fastsky, 0),
MB_CHECKBOXCVAR("Disable Model Lerp", r_nolerp, 0),
@ -1200,6 +1203,7 @@ void M_Menu_Render_f (void)
MB_CHECKBOXCVAR("Disable Colormap", gl_nocolors, 0),
#endif
MB_COMBOCVAR("Log Centerprints", scr_logcenterprint, logcenteropts, logcentervalues, "Display centerprints in the console also."),
MB_CHECKBOXCVAR("FXAA", r_fxaa, 0),
#ifdef GLQUAKE
MB_CHECKBOXCVAR("Bloom", r_bloom, 0),
#endif

View File

@ -195,8 +195,9 @@ cvar_t r_stainfadetime = CVAR ("r_stainfadetime", "1");
cvar_t r_stains = CVARFC("r_stains", IFMINIMAL("0","0"),
CVAR_ARCHIVE,
Cvar_Limiter_ZeroToOne_Callback);
cvar_t r_renderscale = CVARD("r_renderscale", "1", "Provides a way to enable subsampling or super-sampling");
cvar_t r_fxaa = CVARD("r_fxaa", "0", "Runs a post-procesing pass to strip the jaggies.");
cvar_t r_renderscale = CVARD("r_renderscale", "1", CVAR_ARCHIVE, "Provides a way to enable subsampling or super-sampling");
cvar_t r_fxaa = CVARD("r_fxaa", "0", CVAR_ARCHIVE, "Runs a post-procesing pass to strip the jaggies.");
cvar_t r_graphics = CVARFD("r_graphics", "1", CVAR_ARCHIVE, "Turning this off will result in ascii-style rendering.");
cvar_t r_postprocshader = CVARD("r_postprocshader", "", "Specifies a custom shader to use as a post-processing shader");
cvar_t r_wallcolour = CVARAF ("r_wallcolour", "128 128 128",
"r_wallcolor", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);//FIXME: broken
@ -890,6 +891,7 @@ void Renderer_Init(void)
Cvar_Register (&r_refractreflect_scale, GRAPHICALNICETIES);
Cvar_Register (&r_postprocshader, GRAPHICALNICETIES);
Cvar_Register (&r_fxaa, GRAPHICALNICETIES);
Cvar_Register (&r_graphics, GRAPHICALNICETIES);
Cvar_Register (&r_renderscale, GRAPHICALNICETIES);
Cvar_Register (&r_stereo_separation, GRAPHICALNICETIES);
Cvar_Register (&r_stereo_convergence, GRAPHICALNICETIES);

View File

@ -2702,6 +2702,24 @@ unsigned int unicode_charofsfrombyteofs(const char *str, unsigned int byteofs, q
}
return chars;
}
void unicode_strpad(char *out, size_t outsize, const char *in, qboolean leftalign, size_t minwidth, size_t maxwidth, qboolean markup)
{
if(com_parseutf8.ival <= 0 && !markup)
{
Q_snprintfz(out, outsize, "%*.*s", leftalign ? -(int) minwidth : (int) minwidth, (int) maxwidth, in);
}
else
{
size_t l = unicode_byteofsfromcharofs(in, maxwidth, markup);
size_t actual_width = unicode_charcount(in, l, markup);
int pad = (int)((actual_width >= minwidth) ? 0 : (minwidth - actual_width));
int prec = (int)l;
int lpad = leftalign ? 0 : pad;
int rpad = leftalign ? pad : 0;
Q_snprintfz(out, outsize, "%*s%.*s%*s", lpad, "", prec, in, rpad, "");
}
}
#if defined(FTE_TARGET_WEB) || defined(__DJGPP__)
//targets that don't support towupper/towlower...

View File

@ -422,6 +422,7 @@ unsigned int unicode_decode(int *error, const void *in, char **out, qboolean mar
size_t unicode_strtolower(const char *in, char *out, size_t outsize, qboolean markup);
size_t unicode_strtoupper(const char *in, char *out, size_t outsize, qboolean markup);
unsigned int unicode_charcount(const char *in, size_t buffersize, qboolean markup);
void unicode_strpad(char *out, size_t outsize, const char *in, qboolean leftalign, size_t minwidth, size_t maxwidth, qboolean markup);
char *COM_SkipPath (const char *pathname);
void QDECL COM_StripExtension (const char *in, char *out, int outlen);

View File

@ -5907,7 +5907,7 @@ nolength:
if(o < end - 1)
{
f = &formatbuf[1];
if(*s != 's' && *s != 'c')
if(*s != 's' && *s != 'c' && *s != 'S')
if(flags & PRINTF_ALTERNATE) *f++ = '#';
if(flags & PRINTF_ZEROPAD) *f++ = '0';
if(flags & PRINTF_LEFT) *f++ = '-';
@ -5932,7 +5932,7 @@ nolength:
switch(*s)
{
case 'd': case 'i':
case 'd': case 'i': case 'I':
if(precision < 0) // not set
Q_snprintfz(o, end - o, formatbuf, width, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg)));
else
@ -5970,44 +5970,65 @@ nolength:
o += strlen(o);
break;
case 'c':
//UTF-8-FIXME: figure it out yourself
// if(flags & PRINTF_ALTERNATE)
{
if((flags & PRINTF_ALTERNATE) || !VMUTF8)
{ //precision+width are in bytes
if(precision < 0) // not set
Q_snprintfz(o, end - o, formatbuf, width, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg)));
else
Q_snprintfz(o, end - o, formatbuf, width, precision, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg)));
o += strlen(o);
}
/* else
{
else
{ //precision+width are in chars
unsigned int c = (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg));
char charbuf16[16];
const char *buf = u8_encodech(c, NULL, charbuf16);
if(!buf)
buf = "";
char buf[16];
c = unicode_encode(buf, c, sizeof(buf), VMUTF8MARKUP);
buf[c] = 0;
if(precision < 0) // not set
precision = end - o - 1;
o += u8_strpad(o, end - o, buf, (flags & PRINTF_LEFT) != 0, width, precision);
unicode_strpad(o, end - o, buf, (flags & PRINTF_LEFT) != 0, width, precision, VMUTF8MARKUP);
o += strlen(o);
}
*/ break;
case 's':
//UTF-8-FIXME: figure it out yourself
// if(flags & PRINTF_ALTERNATE)
break;
case 'S':
{
char quotedbuf[65536]; //FIXME: no idea how big this actually needs to be.
const char *s = GETARG_STRING(thisarg);
s = COM_QuotedString(s, quotedbuf, sizeof(quotedbuf), false);
if((flags & PRINTF_ALTERNATE) || !VMUTF8)
{ //precision+width are in bytes
if(precision < 0) // not set
Q_snprintfz(o, end - o, formatbuf, width, s);
else
Q_snprintfz(o, end - o, formatbuf, width, precision, s);
o += strlen(o);
}
else
{ //precision+width are in chars
if(precision < 0) // not set
precision = end - o - 1;
unicode_strpad(o, end - o, s, (flags & PRINTF_LEFT) != 0, width, precision, VMUTF8MARKUP);
o += strlen(o);
}
}
break;
case 's':
if((flags & PRINTF_ALTERNATE) || !VMUTF8)
{ //precision+width are in bytes
if(precision < 0) // not set
Q_snprintfz(o, end - o, formatbuf, width, GETARG_STRING(thisarg));
else
Q_snprintfz(o, end - o, formatbuf, width, precision, GETARG_STRING(thisarg));
o += strlen(o);
}
/* else
{
else
{ //precision+width are in chars
if(precision < 0) // not set
precision = end - o - 1;
o += u8_strpad(o, end - o, GETARG_STRING(thisarg), (flags & PRINTF_LEFT) != 0, width, precision);
unicode_strpad(o, end - o, GETARG_STRING(thisarg), (flags & PRINTF_LEFT) != 0, width, precision, VMUTF8MARKUP);
o += strlen(o);
}
*/ break;
break;
default:
Con_Printf("PF_sprintf: invalid format string: %s\n", s0);
goto finished;

View File

@ -56,7 +56,7 @@ cvar_t gl_dither = CVAR("gl_dither", "1");
extern cvar_t r_stereo_separation;
extern cvar_t r_stereo_convergence;
extern cvar_t r_stereo_method;
extern cvar_t r_postprocshader, r_fxaa;
extern cvar_t r_postprocshader, r_fxaa, r_graphics;
extern cvar_t r_hdr_framebuffer;
extern cvar_t gl_screenangle;
@ -1912,21 +1912,32 @@ void GLR_RenderView (void)
r_refdef.globalfog.density /= 64; //FIXME
}
if (!(r_refdef.flags & RDF_NOWORLDMODEL) && (*r_postprocshader.string))
if (!(r_refdef.flags & RDF_NOWORLDMODEL))
{
custompostproc = R_RegisterCustom(r_postprocshader.string, SUF_NONE, NULL, NULL);
if (r_fxaa.ival)
r_refdef.flags |= RDF_ANTIALIAS;
if (*r_postprocshader.string)
custompostproc = R_RegisterCustom(r_postprocshader.string, SUF_NONE, NULL, NULL);
else if (!r_graphics.ival)
custompostproc = R_RegisterShader("postproc_ascii", 0,
"{\n"
"program postproc_ascii\n"
"affine\n"
"{\n"
"map $sourcecolour\n"
"nodepthtest\n"
"}\n"
"}\n"
);
if (custompostproc)
r_refdef.flags |= RDF_CUSTOMPOSTPROC;
if (r_hdr_framebuffer.ival && !(vid.flags & VID_FP16)) //primary use of this cvar is to fix q3shader overbrights (so bright lightmaps can oversaturate then drop below 1 by modulation with the lightmap
forcedfb = true;
if (vid_hardwaregamma.ival == 4 && (v_gamma.value != 1 || v_contrast.value != 1 || v_brightness.value != 0))
r_refdef.flags |= RDF_SCENEGAMMA;
}
if (!(r_refdef.flags & RDF_NOWORLDMODEL) && r_fxaa.ival) //overlays will have problems.
r_refdef.flags |= RDF_ANTIALIAS;
if (!(r_refdef.flags & RDF_NOWORLDMODEL) && r_hdr_framebuffer.ival && !(vid.flags & VID_FP16)) //primary use of this cvar is to fix q3shader overbrights (so bright lightmaps can oversaturate then drop below 1 by modulation with the lightmap
forcedfb = true;
if (vid_hardwaregamma.ival == 4 && (v_gamma.value != 1 || v_contrast.value != 1 || v_brightness.value != 0))
r_refdef.flags |= RDF_SCENEGAMMA;
//disable stuff if its simply not supported.
if (dofbo || !gl_config.arb_shader_objects || !gl_config.ext_framebuffer_objects || !sh_config.texture_non_power_of_two_pic)
{

View File

@ -9802,6 +9802,68 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "postproc_ascii",
"!!cvardf r_glsl_ascii_mono=0\n"
"!!samps 1\n"
//derived from https://www.shadertoy.com/view/lssGDj
"#include \"sys/defs.h\"\n"
"varying vec2 texcoord;\n"
"#ifdef VERTEX_SHADER\n"
"void main()\n"
"{\n"
"texcoord = v_texcoord.xy;\n"
"texcoord.y = 1.0 - texcoord.y;\n"
"gl_Position = ftetransform();\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"uniform vec2 e_sourcesize;\n"
"float character(float n, vec2 p)\n"
"{\n"
"p = floor(p*vec2(4.0, -4.0) + 2.5);\n"
"if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)\n"
"{\n"
"if (int(mod(n/exp2(p.x + 5.0*p.y), 2.0)) == 1) return 1.0;\n"
"} \n"
"return 0.0;\n"
"}\n"
"void main(void)\n"
"{\n"
"vec2 uv = floor(texcoord.xy * e_sourcesize); //in pixels.\n"
"vec3 col = texture2D(s_t0, (floor(uv/8.0)*8.0+4.0)/e_sourcesize.xy).rgb; \n"
"float gray = 0.3 * col.r + 0.59 * col.g + 0.11 * col.b;\n"
"if (r_glsl_ascii_mono != 0)\n"
"gray = gray = pow(gray, 0.7); //quake is just too dark otherwise.\n"
"else\n"
"gray = gray = pow(gray, 0.45); //col*char is FAR too dark otherwise, and much of the colour will come from the col term anyway.\n"
"float n = 0.0; // space\n"
"if (gray > 0.1) n = 4096.0; // .\n"
"if (gray > 0.2) n = 65600.0; // :\n"
"if (gray > 0.3) n = 332772.0; // *\n"
"if (gray > 0.4) n = 15255086.0; // o \n"
"if (gray > 0.5) n = 23385164.0; // &\n"
"if (gray > 0.6) n = 15252014.0; // 8\n"
"if (gray > 0.7) n = 13199452.0; // @\n"
"if (gray > 0.8) n = 11512810.0; // #\n"
"vec2 p = mod(uv/4.0, 2.0) - vec2(1.0);\n"
"if (r_glsl_ascii_mono != 0)\n"
"col = vec3(character(n, p));\n"
"else\n"
"col = col*character(n, p); //note that this is kinda cheating.\n"
"gl_FragColor = vec4(col, 1.0);\n"
"}\n"
"#endif\n"
},
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "fxaa",
"!!samps 1\n"
"#include \"sys/defs.h\"\n"

View File

@ -4695,7 +4695,7 @@ nolength:
//always 8-bytes wide with 0 padding, always ints.
if (isfloat < 0) isfloat = 0;
}
else if (*s == 'i')
else if (*s == 'i' || *s == 'I')
{
//%i defaults to ints, not floats.
if(isfloat < 0) isfloat = 0;
@ -4714,7 +4714,7 @@ nolength:
switch(*s)
{
//fixme: should we validate char ranges?
case 'd': case 'i': case 'c':
case 'd': case 'i': case 'I': case 'c':
case 'o': case 'u': case 'x': case 'X': case 'p': case 'P':
case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
if (isfloat)
@ -4778,6 +4778,7 @@ nolength:
QCC_PR_ParseWarning(WARN_FORMATSTRING, "%s: %s requires intvector at arg %i", funcname, formatbuf, thisarg+1);
break;
case 's':
case 'S':
switch(ARGTYPE(thisarg))
{
case ev_string:

View File

@ -11010,7 +11010,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"getextresponse", PF_Fixme, 0, 0, 0, 624, "string()"},
{"netaddress_resolve",PF_netaddress_resolve,0, 0, 0, 625, "string(string dnsname, optional float defport)"},
{"getgamedirinfo", PF_Fixme, 0, 0, 0, 626, "string(float n, float prop)" STUB},
{"sprintf", PF_sprintf, 0, 0, 0, 627, "string(string fmt, ...)"},
{"sprintf", PF_sprintf, 0, 0, 0, 627, D("string(string fmt, ...)", "'prints' to a formatted temp-string. Mostly acts as in C, however %d assumes floats (fteqcc has arg checking. Use it.).\ntype conversions: l=arg is an int, h=arg is a float, and will work as a prefix for any float or int representation.\nfloat representations: d=decimal, e,E=exponent-notation, f,F=floating-point notation, g,G=terse float, c=char code, x,X=hex\nother representations: i=int, s=string, S=quoted and marked-up string, v=vector, p=pointer\nso %ld will accept an int arg, while %hi will expect a float arg.\nentities, fields, and functions will generally need to be printed as ints with %i.")},
{"getsurfacenumtriangles",PF_getsurfacenumtriangles,0,0,0, 628, "float(entity e, float s)"},
{"getsurfacetriangle",PF_getsurfacetriangle,0, 0, 0, 629, "vector(entity e, float s, float n)"},
// {"setkeybind", PF_Fixme, 0, 0, 0, 630, "float(float key, string bind, optional float bindmap)"},

View File

@ -36,6 +36,7 @@ char shaders[][64] =
"postproc_laea",
"postproc_stereographic",
"postproc_equirectangular",
"postproc_ascii",
"fxaa",
"underwaterwarp",
"menutint",

View File

@ -0,0 +1,59 @@
!!cvardf r_glsl_ascii_mono=0
!!samps 1
//derived from https://www.shadertoy.com/view/lssGDj
#include "sys/defs.h"
varying vec2 texcoord;
#ifdef VERTEX_SHADER
void main()
{
texcoord = v_texcoord.xy;
texcoord.y = 1.0 - texcoord.y;
gl_Position = ftetransform();
}
#endif
#ifdef FRAGMENT_SHADER
uniform vec2 e_sourcesize;
float character(float n, vec2 p)
{
p = floor(p*vec2(4.0, -4.0) + 2.5);
if (clamp(p.x, 0.0, 4.0) == p.x && clamp(p.y, 0.0, 4.0) == p.y)
{
if (int(mod(n/exp2(p.x + 5.0*p.y), 2.0)) == 1) return 1.0;
}
return 0.0;
}
void main(void)
{
vec2 uv = floor(texcoord.xy * e_sourcesize); //in pixels.
vec3 col = texture2D(s_t0, (floor(uv/8.0)*8.0+4.0)/e_sourcesize.xy).rgb;
float gray = 0.3 * col.r + 0.59 * col.g + 0.11 * col.b;
if (r_glsl_ascii_mono != 0.0)
gray = gray = pow(gray, 0.7); //quake is just too dark otherwise.
else
gray = gray = pow(gray, 0.45); //col*char is FAR too dark otherwise, and much of the colour will come from the col term anyway.
float n = 0.0; // space
if (gray > 0.1) n = 4096.0; // .
if (gray > 0.2) n = 65600.0; // :
if (gray > 0.3) n = 332772.0; // *
if (gray > 0.4) n = 15255086.0; // o
if (gray > 0.5) n = 23385164.0; // &
if (gray > 0.6) n = 15252014.0; // 8
if (gray > 0.7) n = 13199452.0; // @
if (gray > 0.8) n = 11512810.0; // #
vec2 p = mod(uv/4.0, 2.0) - vec2(1.0);
if (r_glsl_ascii_mono != 0.0)
col = vec3(character(n, p));
else
col = col*character(n, p); //note that this is kinda cheating.
gl_FragColor = vec4(col, 1.0);
}
#endif