2011-12-23 03:19:50 +00:00
|
|
|
/*
|
|
|
|
glsl_draw.c
|
|
|
|
|
|
|
|
2D drawing support for GLSL
|
|
|
|
|
|
|
|
Copyright (C) 2011 Bill Currie <bill@taniwha.org>
|
|
|
|
|
|
|
|
Author: Bill Currie <bill@taniwha.org>
|
|
|
|
Date: 2011/12/23
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to:
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2011-12-26 11:33:40 +00:00
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
# include <string.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
# include <strings.h>
|
|
|
|
#endif
|
|
|
|
|
2011-12-27 08:59:58 +00:00
|
|
|
#include "QF/cvar.h"
|
2011-12-23 03:19:50 +00:00
|
|
|
#include "QF/draw.h"
|
2011-12-25 10:42:39 +00:00
|
|
|
#include "QF/dstring.h"
|
2011-12-31 11:36:24 +00:00
|
|
|
#include "QF/hash.h"
|
2022-12-05 16:18:01 +00:00
|
|
|
#include "QF/image.h"
|
2011-12-26 11:33:40 +00:00
|
|
|
#include "QF/quakefs.h"
|
2011-12-25 10:42:39 +00:00
|
|
|
#include "QF/sys.h"
|
2011-12-25 23:12:05 +00:00
|
|
|
#include "QF/vid.h"
|
2022-12-07 06:11:08 +00:00
|
|
|
#include "QF/ui/font.h"
|
2021-07-10 09:04:34 +00:00
|
|
|
#include "QF/ui/view.h"
|
2011-12-25 10:42:39 +00:00
|
|
|
|
2011-12-26 07:08:55 +00:00
|
|
|
#include "QF/GLSL/defines.h"
|
|
|
|
#include "QF/GLSL/funcs.h"
|
2012-02-22 12:53:17 +00:00
|
|
|
#include "QF/GLSL/qf_draw.h"
|
2011-12-26 09:34:51 +00:00
|
|
|
#include "QF/GLSL/qf_textures.h"
|
2011-12-26 07:08:55 +00:00
|
|
|
#include "QF/GLSL/qf_vid.h"
|
2011-12-25 10:42:39 +00:00
|
|
|
|
2012-02-14 08:28:09 +00:00
|
|
|
#include "r_internal.h"
|
2011-12-23 03:19:50 +00:00
|
|
|
|
2011-12-31 11:36:24 +00:00
|
|
|
typedef struct cachepic_s {
|
|
|
|
struct cachepic_s *next;
|
|
|
|
char *name;
|
|
|
|
qpic_t *pic;
|
|
|
|
} cachepic_t;
|
2011-12-26 11:33:40 +00:00
|
|
|
|
2012-07-03 04:38:35 +00:00
|
|
|
typedef struct {
|
|
|
|
float xyst[4];
|
|
|
|
float color[4];
|
|
|
|
} drawvert_t;
|
|
|
|
|
2022-12-05 16:18:01 +00:00
|
|
|
typedef struct glslfont_s {
|
2022-12-07 06:11:08 +00:00
|
|
|
font_t *font;
|
2022-12-05 16:18:01 +00:00
|
|
|
GLuint texid;
|
|
|
|
} glslfont_t;
|
|
|
|
|
|
|
|
typedef struct glfontset_s
|
|
|
|
DARRAY_TYPE (glslfont_t) glslfontset_t;
|
|
|
|
|
|
|
|
static glslfontset_t glsl_fonts = DARRAY_STATIC_INIT (16);
|
|
|
|
|
2014-01-28 04:10:56 +00:00
|
|
|
static const char *twod_vert_effects[] =
|
|
|
|
{
|
|
|
|
"QuakeForge.Vertex.2d",
|
|
|
|
0
|
|
|
|
};
|
2011-12-26 11:33:40 +00:00
|
|
|
|
2014-01-28 04:10:56 +00:00
|
|
|
static const char *twod_frag_effects[] =
|
|
|
|
{
|
|
|
|
"QuakeForge.Fragment.palette",
|
|
|
|
"QuakeForge.Fragment.2d",
|
|
|
|
0
|
|
|
|
};
|
2011-12-25 06:53:12 +00:00
|
|
|
|
2022-12-05 16:18:01 +00:00
|
|
|
static const char *twod_alpha_frag_effects[] =
|
|
|
|
{
|
|
|
|
"QuakeForge.Fragment.2d.alpha",
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2011-12-26 08:42:23 +00:00
|
|
|
static float proj_matrix[16];
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
int program;
|
2012-07-03 04:38:35 +00:00
|
|
|
shaderparam_t texture;
|
2011-12-26 08:42:23 +00:00
|
|
|
shaderparam_t palette;
|
|
|
|
shaderparam_t matrix;
|
|
|
|
shaderparam_t vertex;
|
2011-12-28 00:04:26 +00:00
|
|
|
shaderparam_t color;
|
2012-07-03 04:38:35 +00:00
|
|
|
} quake_2d = {
|
2022-12-05 16:18:01 +00:00
|
|
|
.texture = {"texture", 1},
|
|
|
|
.palette = {"palette", 1},
|
|
|
|
.matrix = {"mvp_mat", 1},
|
|
|
|
.vertex = {"vertex", 0},
|
|
|
|
.color = {"vcolor", 0},
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
int program;
|
|
|
|
shaderparam_t texture;
|
|
|
|
shaderparam_t matrix;
|
|
|
|
shaderparam_t vertex;
|
|
|
|
shaderparam_t color;
|
|
|
|
} alpha_2d = {
|
|
|
|
.texture = {"texture", 1},
|
|
|
|
.matrix = {"mvp_mat", 1},
|
|
|
|
.vertex = {"vertex", 0},
|
|
|
|
.color = {"vcolor", 0},
|
2011-12-26 11:33:40 +00:00
|
|
|
};
|
|
|
|
|
2012-07-03 04:38:35 +00:00
|
|
|
static scrap_t *draw_scrap; // hold all 2d images
|
2011-12-29 02:25:27 +00:00
|
|
|
static byte white_block[8 * 8];
|
2012-07-03 05:45:16 +00:00
|
|
|
static dstring_t *draw_queue;
|
2022-12-05 16:18:01 +00:00
|
|
|
static dstring_t *glyph_queue;
|
2022-05-28 09:14:26 +00:00
|
|
|
static dstring_t *line_queue;
|
2012-07-03 04:38:35 +00:00
|
|
|
static qpic_t *conchars;
|
2011-12-26 11:33:40 +00:00
|
|
|
static int conback_texture;
|
2011-12-27 08:59:58 +00:00
|
|
|
static qpic_t *crosshair_pic;
|
2011-12-29 02:25:27 +00:00
|
|
|
static qpic_t *white_pic;
|
2012-07-09 06:11:03 +00:00
|
|
|
static qpic_t *backtile_pic;
|
2011-12-31 11:36:24 +00:00
|
|
|
static hashtab_t *pic_cache;
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
static int glsl_conback_texnum;
|
2022-11-13 13:23:56 +00:00
|
|
|
static int glsl_2d_scale = 1;
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
static cvar_t glsl_conback_texnum_cvar = {
|
|
|
|
.name = "glsl_conback_texnum",
|
|
|
|
.description =
|
|
|
|
"bind conback to this texture for debugging",
|
|
|
|
.default_value = "0",
|
|
|
|
.flags = CVAR_NONE,
|
|
|
|
.value = { .type = &cexpr_int, .value = &glsl_conback_texnum },
|
|
|
|
};
|
2011-12-26 11:33:40 +00:00
|
|
|
|
|
|
|
static qpic_t *
|
|
|
|
make_glpic (const char *name, qpic_t *p)
|
|
|
|
{
|
|
|
|
qpic_t *pic = 0;
|
|
|
|
|
|
|
|
if (p) {
|
2022-11-18 15:41:52 +00:00
|
|
|
pic = malloc (sizeof (qpic_t) + sizeof (subpic_t *));
|
2012-07-03 04:38:35 +00:00
|
|
|
pic->width = p->width;
|
|
|
|
pic->height = p->height;
|
2022-11-18 15:41:52 +00:00
|
|
|
subpic_t *sp = GLSL_ScrapSubpic (draw_scrap, pic->width, pic->height);
|
|
|
|
*(subpic_t **) pic->data = sp;
|
|
|
|
GLSL_SubpicUpdate (sp, p->data, 1);
|
2011-12-26 11:33:40 +00:00
|
|
|
}
|
|
|
|
return pic;
|
|
|
|
}
|
|
|
|
|
2011-12-31 11:36:24 +00:00
|
|
|
static void
|
|
|
|
pic_free (qpic_t *pic)
|
|
|
|
{
|
2022-11-18 15:41:52 +00:00
|
|
|
subpic_t *subpic = *(subpic_t **) pic->data;
|
2011-12-31 11:36:24 +00:00
|
|
|
|
2022-11-18 15:41:52 +00:00
|
|
|
GLSL_SubpicDelete (subpic);
|
2011-12-31 11:36:24 +00:00
|
|
|
free (pic);
|
|
|
|
}
|
|
|
|
|
|
|
|
//FIXME nicer allocator
|
|
|
|
static cachepic_t *
|
|
|
|
new_cachepic (const char *name, qpic_t *pic)
|
|
|
|
{
|
|
|
|
cachepic_t *cp;
|
|
|
|
|
|
|
|
cp = malloc (sizeof (cachepic_t));
|
|
|
|
cp->name = strdup (name);
|
|
|
|
cp->pic = pic;
|
|
|
|
return cp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
2012-07-18 13:34:37 +00:00
|
|
|
cachepic_getkey (const void *_cp, void *unused)
|
2011-12-31 11:36:24 +00:00
|
|
|
{
|
|
|
|
return ((cachepic_t *) _cp)->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cachepic_free (void *_cp, void *unused)
|
|
|
|
{
|
|
|
|
cachepic_t *cp = (cachepic_t *) _cp;
|
|
|
|
pic_free (cp->pic);
|
|
|
|
free (cp->name);
|
|
|
|
free (cp);
|
|
|
|
}
|
|
|
|
|
2011-12-29 02:25:27 +00:00
|
|
|
static qpic_t *
|
|
|
|
pic_data (const char *name, int w, int h, const byte *data)
|
|
|
|
{
|
|
|
|
qpic_t *pic;
|
|
|
|
qpic_t *glpic;
|
|
|
|
|
|
|
|
pic = malloc (field_offset (qpic_t, data[w * h]));
|
|
|
|
pic->width = w;
|
|
|
|
pic->height = h;
|
|
|
|
memcpy (pic->data, data, pic->width * pic->height);
|
|
|
|
glpic = make_glpic (name, pic);
|
|
|
|
free (pic);
|
|
|
|
return glpic;
|
|
|
|
}
|
|
|
|
|
2011-12-26 11:33:40 +00:00
|
|
|
static void
|
2012-02-06 10:32:30 +00:00
|
|
|
make_quad (qpic_t *pic, float x, float y, int w, int h,
|
2012-07-03 04:38:35 +00:00
|
|
|
int srcx, int srcy, int srcw, int srch, drawvert_t verts[6],
|
|
|
|
float *color)
|
2011-12-26 11:33:40 +00:00
|
|
|
{
|
2022-11-18 15:41:52 +00:00
|
|
|
subpic_t *sp = *(subpic_t **) pic->data;
|
2011-12-26 11:33:40 +00:00
|
|
|
float sl, sh, tl, th;
|
|
|
|
|
2012-07-03 04:38:35 +00:00
|
|
|
srcx += sp->rect->x;
|
|
|
|
srcy += sp->rect->y;
|
2012-12-12 12:34:37 +00:00
|
|
|
sl = (srcx) * sp->size;
|
|
|
|
sh = sl + (srcw) * sp->size;
|
|
|
|
tl = (srcy) * sp->size;
|
|
|
|
th = tl + (srch) * sp->size;
|
2012-07-03 04:38:35 +00:00
|
|
|
|
|
|
|
verts[0].xyst[0] = x;
|
|
|
|
verts[0].xyst[1] = y;
|
|
|
|
verts[0].xyst[2] = sl;
|
|
|
|
verts[0].xyst[3] = tl;
|
|
|
|
|
|
|
|
verts[1].xyst[0] = x + w;
|
|
|
|
verts[1].xyst[1] = y;
|
|
|
|
verts[1].xyst[2] = sh;
|
|
|
|
verts[1].xyst[3] = tl;
|
|
|
|
|
|
|
|
verts[2].xyst[0] = x + w;
|
|
|
|
verts[2].xyst[1] = y + h;
|
|
|
|
verts[2].xyst[2] = sh;
|
|
|
|
verts[2].xyst[3] = th;
|
|
|
|
|
|
|
|
verts[3].xyst[0] = x;
|
|
|
|
verts[3].xyst[1] = y;
|
|
|
|
verts[3].xyst[2] = sl;
|
|
|
|
verts[3].xyst[3] = tl;
|
|
|
|
|
|
|
|
verts[4].xyst[0] = x + w;
|
|
|
|
verts[4].xyst[1] = y + h;
|
|
|
|
verts[4].xyst[2] = sh;
|
|
|
|
verts[4].xyst[3] = th;
|
|
|
|
|
|
|
|
verts[5].xyst[0] = x;
|
|
|
|
verts[5].xyst[1] = y + h;
|
|
|
|
verts[5].xyst[2] = sl;
|
|
|
|
verts[5].xyst[3] = th;
|
|
|
|
|
|
|
|
QuatCopy (color, verts[0].color);
|
|
|
|
QuatCopy (color, verts[1].color);
|
|
|
|
QuatCopy (color, verts[2].color);
|
|
|
|
QuatCopy (color, verts[3].color);
|
|
|
|
QuatCopy (color, verts[4].color);
|
|
|
|
QuatCopy (color, verts[5].color);
|
2011-12-26 11:33:40 +00:00
|
|
|
}
|
2011-12-23 03:19:50 +00:00
|
|
|
|
2011-12-27 08:59:58 +00:00
|
|
|
static void
|
2012-02-06 10:32:30 +00:00
|
|
|
draw_pic (float x, float y, int w, int h, qpic_t *pic,
|
2011-12-29 02:25:27 +00:00
|
|
|
int srcx, int srcy, int srcw, int srch,
|
2011-12-28 00:04:26 +00:00
|
|
|
float *color)
|
2011-12-27 08:59:58 +00:00
|
|
|
{
|
2012-07-03 04:38:35 +00:00
|
|
|
drawvert_t verts[6];
|
|
|
|
void *v;
|
|
|
|
int size = sizeof (verts);
|
2011-12-27 08:59:58 +00:00
|
|
|
|
2012-07-03 04:38:35 +00:00
|
|
|
make_quad (pic, x, y, w, h, srcx, srcy, srcw, srch, verts, color);
|
2012-07-03 05:45:16 +00:00
|
|
|
draw_queue->size += size;
|
|
|
|
dstring_adjust (draw_queue);
|
|
|
|
v = draw_queue->str + draw_queue->size - size;
|
2012-07-03 04:38:35 +00:00
|
|
|
memcpy (v, verts, size);
|
2011-12-27 08:59:58 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
qpic_t *
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_MakePic (int width, int height, const byte *data)
|
2012-02-01 08:46:15 +00:00
|
|
|
{
|
|
|
|
return pic_data (0, width, height, data);
|
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_DestroyPic (qpic_t *pic)
|
2012-02-01 08:46:15 +00:00
|
|
|
{
|
|
|
|
pic_free (pic);
|
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
qpic_t *
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_PicFromWad (const char *name)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2011-12-26 11:33:40 +00:00
|
|
|
return make_glpic (name, W_GetLumpName (name));
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
qpic_t *
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_CachePic (const char *path, qboolean alpha)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2011-12-26 11:33:40 +00:00
|
|
|
qpic_t *p, *pic;
|
2011-12-31 11:36:24 +00:00
|
|
|
cachepic_t *cpic;
|
2011-12-26 11:33:40 +00:00
|
|
|
|
2011-12-31 11:36:24 +00:00
|
|
|
if ((cpic = Hash_Find (pic_cache, path)))
|
|
|
|
return cpic->pic;
|
2011-12-26 11:33:40 +00:00
|
|
|
if (strlen (path) < 4 || strcmp (path + strlen (path) - 4, ".lmp")
|
2014-01-23 02:57:57 +00:00
|
|
|
|| !(p = (qpic_t *) QFS_LoadFile (QFS_FOpenFile (path), 0))) {
|
2011-12-26 11:33:40 +00:00
|
|
|
//FIXME load a null texture
|
|
|
|
Sys_Error ("Draw_CachePic: failed to load %s", path);
|
|
|
|
}
|
|
|
|
|
|
|
|
pic = make_glpic (path, p);
|
|
|
|
free (p);
|
2011-12-31 11:36:24 +00:00
|
|
|
cpic = new_cachepic (path, pic);
|
|
|
|
Hash_Add (pic_cache, cpic);
|
2011-12-26 11:33:40 +00:00
|
|
|
return pic;
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_UncachePic (const char *path)
|
2012-02-01 07:55:35 +00:00
|
|
|
{
|
|
|
|
Hash_Free (pic_cache, Hash_Del (pic_cache, path));
|
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_TextBox (int x, int y, int width, int lines, byte alpha)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2011-12-29 08:51:31 +00:00
|
|
|
static quat_t color = { 1, 1, 1, 0 };
|
|
|
|
qpic_t *p;
|
|
|
|
int cx, cy, n;
|
|
|
|
#define draw(px,py,pp) \
|
|
|
|
draw_pic (px, py, pp->width, pp->height, pp, \
|
|
|
|
0, 0, pp->width, pp->height, color)
|
|
|
|
|
|
|
|
color[3] = alpha / 255.0;
|
|
|
|
// draw left side
|
|
|
|
cx = x;
|
|
|
|
cy = y;
|
2012-02-22 07:32:34 +00:00
|
|
|
p = glsl_Draw_CachePic ("gfx/box_tl.lmp", true);
|
2011-12-29 08:51:31 +00:00
|
|
|
draw (cx, cy, p);
|
2012-02-22 07:32:34 +00:00
|
|
|
p = glsl_Draw_CachePic ("gfx/box_ml.lmp", true);
|
2011-12-29 08:51:31 +00:00
|
|
|
for (n = 0; n < lines; n++) {
|
|
|
|
cy += 8;
|
|
|
|
draw (cx, cy, p);
|
|
|
|
}
|
2012-02-22 07:32:34 +00:00
|
|
|
p = glsl_Draw_CachePic ("gfx/box_bl.lmp", true);
|
2011-12-29 08:51:31 +00:00
|
|
|
draw (cx, cy + 8, p);
|
|
|
|
|
|
|
|
// draw middle
|
|
|
|
cx += 8;
|
|
|
|
while (width > 0) {
|
|
|
|
cy = y;
|
2012-02-22 07:32:34 +00:00
|
|
|
p = glsl_Draw_CachePic ("gfx/box_tm.lmp", true);
|
2011-12-29 08:51:31 +00:00
|
|
|
draw (cx, cy, p);
|
2012-02-22 07:32:34 +00:00
|
|
|
p = glsl_Draw_CachePic ("gfx/box_mm.lmp", true);
|
2011-12-29 08:51:31 +00:00
|
|
|
for (n = 0; n < lines; n++) {
|
|
|
|
cy += 8;
|
|
|
|
if (n == 1)
|
2012-02-22 07:32:34 +00:00
|
|
|
p = glsl_Draw_CachePic ("gfx/box_mm2.lmp", true);
|
2011-12-29 08:51:31 +00:00
|
|
|
draw (cx, cy, p);
|
|
|
|
}
|
2012-02-22 07:32:34 +00:00
|
|
|
p = glsl_Draw_CachePic ("gfx/box_bm.lmp", true);
|
2011-12-29 08:51:31 +00:00
|
|
|
draw (cx, cy + 8, p);
|
|
|
|
width -= 2;
|
|
|
|
cx += 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw right side
|
|
|
|
cy = y;
|
2012-02-22 07:32:34 +00:00
|
|
|
p = glsl_Draw_CachePic ("gfx/box_tr.lmp", true);
|
2011-12-29 08:51:31 +00:00
|
|
|
draw (cx, cy, p);
|
2012-02-22 07:32:34 +00:00
|
|
|
p = glsl_Draw_CachePic ("gfx/box_mr.lmp", true);
|
2011-12-29 08:51:31 +00:00
|
|
|
for (n = 0; n < lines; n++) {
|
|
|
|
cy += 8;
|
|
|
|
draw (cx, cy, p);
|
|
|
|
}
|
2012-02-22 07:32:34 +00:00
|
|
|
p = glsl_Draw_CachePic ("gfx/box_br.lmp", true);
|
2011-12-29 08:51:31 +00:00
|
|
|
draw (cx, cy + 8, p);
|
|
|
|
#undef draw
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
2011-12-31 11:36:24 +00:00
|
|
|
static void
|
2022-06-04 07:06:04 +00:00
|
|
|
Draw_ClearCache (int phase, void *data)
|
2011-12-31 11:36:24 +00:00
|
|
|
{
|
|
|
|
if (phase)
|
|
|
|
return;
|
|
|
|
Hash_FlushTable (pic_cache);
|
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_Init (void)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2014-01-28 04:10:56 +00:00
|
|
|
shader_t *vert_shader, *frag_shader;
|
2011-12-25 10:42:39 +00:00
|
|
|
int i;
|
2011-12-26 08:42:23 +00:00
|
|
|
int frag, vert;
|
2011-12-26 11:33:40 +00:00
|
|
|
qpic_t *pic;
|
2011-12-25 10:42:39 +00:00
|
|
|
|
2020-03-25 06:43:16 +00:00
|
|
|
pic_cache = Hash_NewTable (127, cachepic_getkey, cachepic_free, 0, 0);
|
2022-06-04 07:06:04 +00:00
|
|
|
QFS_GamedirCallback (Draw_ClearCache, 0);
|
2011-12-28 12:45:20 +00:00
|
|
|
//FIXME temporary work around for the timing of cvar creation and palette
|
|
|
|
//loading
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
//crosshaircolor->callback (crosshaircolor);
|
2011-12-28 12:45:20 +00:00
|
|
|
|
2012-07-03 05:45:16 +00:00
|
|
|
draw_queue = dstring_new ();
|
2022-05-28 09:14:26 +00:00
|
|
|
line_queue = dstring_new ();
|
2022-12-05 16:18:01 +00:00
|
|
|
glyph_queue = dstring_new ();
|
2012-07-03 04:38:35 +00:00
|
|
|
|
2014-01-28 04:10:56 +00:00
|
|
|
vert_shader = GLSL_BuildShader (twod_vert_effects);
|
|
|
|
frag_shader = GLSL_BuildShader (twod_frag_effects);
|
|
|
|
vert = GLSL_CompileShader ("quakeico.vert", vert_shader,
|
2012-02-17 09:57:13 +00:00
|
|
|
GL_VERTEX_SHADER);
|
2014-01-28 04:10:56 +00:00
|
|
|
frag = GLSL_CompileShader ("quake2d.frag", frag_shader,
|
2012-02-17 09:57:13 +00:00
|
|
|
GL_FRAGMENT_SHADER);
|
2012-07-03 04:38:35 +00:00
|
|
|
quake_2d.program = GLSL_LinkProgram ("quake2d", vert, frag);
|
|
|
|
GLSL_ResolveShaderParam (quake_2d.program, &quake_2d.texture);
|
|
|
|
GLSL_ResolveShaderParam (quake_2d.program, &quake_2d.palette);
|
|
|
|
GLSL_ResolveShaderParam (quake_2d.program, &quake_2d.matrix);
|
|
|
|
GLSL_ResolveShaderParam (quake_2d.program, &quake_2d.vertex);
|
|
|
|
GLSL_ResolveShaderParam (quake_2d.program, &quake_2d.color);
|
2014-01-28 04:10:56 +00:00
|
|
|
GLSL_FreeShader (vert_shader);
|
|
|
|
GLSL_FreeShader (frag_shader);
|
2012-02-17 09:57:13 +00:00
|
|
|
|
2022-12-05 16:18:01 +00:00
|
|
|
vert_shader = GLSL_BuildShader (twod_vert_effects);
|
|
|
|
frag_shader = GLSL_BuildShader (twod_alpha_frag_effects);
|
|
|
|
vert = GLSL_CompileShader ("quakeico.vert", vert_shader,
|
|
|
|
GL_VERTEX_SHADER);
|
|
|
|
frag = GLSL_CompileShader ("alpha2d.frag", frag_shader,
|
|
|
|
GL_FRAGMENT_SHADER);
|
|
|
|
alpha_2d.program = GLSL_LinkProgram ("alpha2d", vert, frag);
|
|
|
|
GLSL_ResolveShaderParam (alpha_2d.program, &alpha_2d.texture);
|
|
|
|
GLSL_ResolveShaderParam (alpha_2d.program, &alpha_2d.matrix);
|
|
|
|
GLSL_ResolveShaderParam (alpha_2d.program, &alpha_2d.vertex);
|
|
|
|
GLSL_ResolveShaderParam (alpha_2d.program, &alpha_2d.color);
|
|
|
|
GLSL_FreeShader (vert_shader);
|
|
|
|
GLSL_FreeShader (frag_shader);
|
|
|
|
|
2012-07-03 04:38:35 +00:00
|
|
|
draw_scrap = GLSL_CreateScrap (2048, GL_LUMINANCE, 0);
|
2011-12-26 11:33:40 +00:00
|
|
|
|
2011-12-25 10:42:39 +00:00
|
|
|
draw_chars = W_GetLumpName ("conchars");
|
2022-05-09 07:30:05 +00:00
|
|
|
if (draw_chars) {
|
|
|
|
for (i = 0; i < 256 * 64; i++) {
|
|
|
|
if (draw_chars[i] == 0) {
|
|
|
|
draw_chars[i] = 255; // proper transparent color
|
|
|
|
}
|
|
|
|
}
|
|
|
|
conchars = pic_data ("conchars", 128, 128, draw_chars);
|
|
|
|
} else {
|
|
|
|
qpic_t *charspic = Draw_Font8x8Pic ();
|
|
|
|
conchars = pic_data ("conchars", charspic->width,
|
|
|
|
charspic->height, charspic->data);
|
|
|
|
free (charspic);
|
|
|
|
}
|
2011-12-26 11:33:40 +00:00
|
|
|
|
2014-01-23 02:57:57 +00:00
|
|
|
pic = (qpic_t *) QFS_LoadFile (QFS_FOpenFile ("gfx/conback.lmp"), 0);
|
2011-12-26 11:33:40 +00:00
|
|
|
if (pic) {
|
|
|
|
SwapPic (pic);
|
2012-02-17 09:57:13 +00:00
|
|
|
conback_texture = GLSL_LoadQuakeTexture ("conback",
|
2011-12-26 11:33:40 +00:00
|
|
|
pic->width, pic->height,
|
|
|
|
pic->data);
|
|
|
|
free (pic);
|
|
|
|
}
|
2011-12-27 08:59:58 +00:00
|
|
|
|
|
|
|
pic = Draw_CrosshairPic ();
|
|
|
|
crosshair_pic = make_glpic ("crosshair", pic);
|
|
|
|
free (pic);
|
2011-12-29 02:25:27 +00:00
|
|
|
|
|
|
|
memset (white_block, 0xfe, sizeof (white_block));
|
|
|
|
white_pic = pic_data ("white_block", 8, 8, white_block);
|
2011-12-29 09:15:15 +00:00
|
|
|
|
2012-07-09 06:11:03 +00:00
|
|
|
backtile_pic = glsl_Draw_PicFromWad ("backtile");
|
2022-09-22 01:33:32 +00:00
|
|
|
if (!backtile_pic) {
|
|
|
|
backtile_pic = white_pic;
|
|
|
|
}
|
2012-07-02 11:01:28 +00:00
|
|
|
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
Cvar_Register (&glsl_conback_texnum_cvar, 0, 0);
|
2011-12-25 10:42:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
queue_character (int x, int y, byte chr)
|
|
|
|
{
|
2012-07-03 04:38:35 +00:00
|
|
|
quat_t color = {1, 1, 1, 1};
|
|
|
|
int cx, cy;
|
2011-12-25 10:42:39 +00:00
|
|
|
|
2012-07-03 04:38:35 +00:00
|
|
|
cx = chr % 16;
|
|
|
|
cy = chr / 16;
|
|
|
|
draw_pic (x, y, 8, 8, conchars, cx * 8, cy * 8, 8, 8, color);
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
2011-12-25 23:12:05 +00:00
|
|
|
static void
|
2012-07-03 04:38:35 +00:00
|
|
|
flush_2d (void)
|
2011-12-25 23:12:05 +00:00
|
|
|
{
|
2012-07-03 04:38:35 +00:00
|
|
|
GLSL_ScrapFlush (draw_scrap);
|
2022-05-28 09:14:26 +00:00
|
|
|
|
2012-07-03 04:38:35 +00:00
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, GLSL_ScrapTexture (draw_scrap));
|
2022-05-28 09:14:26 +00:00
|
|
|
if (draw_queue->size) {
|
|
|
|
qfeglVertexAttribPointer (quake_2d.vertex.location, 4, GL_FLOAT,
|
|
|
|
0, 32, draw_queue->str);
|
|
|
|
qfeglVertexAttribPointer (quake_2d.color.location, 4, GL_FLOAT,
|
|
|
|
0, 32, draw_queue->str + 16);
|
|
|
|
|
|
|
|
qfeglDrawArrays (GL_TRIANGLES, 0, draw_queue->size / 32);
|
|
|
|
}
|
|
|
|
if (line_queue->size) {
|
|
|
|
qfeglVertexAttribPointer (quake_2d.vertex.location, 4, GL_FLOAT,
|
|
|
|
0, 32, line_queue->str);
|
|
|
|
qfeglVertexAttribPointer (quake_2d.color.location, 4, GL_FLOAT,
|
|
|
|
0, 32, line_queue->str + 16);
|
2011-12-26 01:16:16 +00:00
|
|
|
|
2022-05-28 09:14:26 +00:00
|
|
|
qfeglDrawArrays (GL_LINES, 0, line_queue->size / 32);
|
|
|
|
}
|
2012-07-03 05:45:16 +00:00
|
|
|
draw_queue->size = 0;
|
2022-05-28 09:14:26 +00:00
|
|
|
line_queue->size = 0;
|
2011-12-25 23:12:05 +00:00
|
|
|
}
|
|
|
|
|
2022-09-15 05:24:33 +00:00
|
|
|
void
|
|
|
|
glsl_Draw_CharBuffer (int x, int y, draw_charbuffer_t *buffer)
|
|
|
|
{
|
|
|
|
const byte *line = (byte *) buffer->chars;
|
|
|
|
int width = buffer->width;
|
|
|
|
int height = buffer->height;
|
|
|
|
while (height-- > 0) {
|
|
|
|
for (int i = 0; i < width; i++) {
|
|
|
|
glsl_Draw_Character (x + i * 8, y, line[i]);
|
|
|
|
}
|
|
|
|
line += width;
|
|
|
|
y += 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_Character (int x, int y, unsigned int chr)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2011-12-25 23:12:05 +00:00
|
|
|
chr &= 255;
|
|
|
|
|
|
|
|
if (chr == 32)
|
|
|
|
return; // space
|
|
|
|
if (y <= -8)
|
|
|
|
return; // totally off screen
|
|
|
|
|
|
|
|
queue_character (x, y, chr);
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_String (int x, int y, const char *str)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2011-12-25 23:12:05 +00:00
|
|
|
byte chr;
|
|
|
|
|
|
|
|
if (!str || !str[0])
|
|
|
|
return; // totally off screen
|
|
|
|
if (y <= -8)
|
|
|
|
return; // totally off screen
|
|
|
|
|
|
|
|
while (*str) {
|
|
|
|
if ((chr = *str++) != 32)
|
|
|
|
queue_character (x, y, chr);
|
|
|
|
x += 8;
|
|
|
|
}
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_nString (int x, int y, const char *str, int count)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2011-12-25 23:12:05 +00:00
|
|
|
byte chr;
|
|
|
|
|
|
|
|
if (!str || !str[0])
|
|
|
|
return; // totally off screen
|
|
|
|
if (y <= -8)
|
|
|
|
return; // totally off screen
|
|
|
|
|
|
|
|
while (count-- && *str) {
|
|
|
|
if ((chr = *str++) != 32)
|
|
|
|
queue_character (x, y, chr);
|
|
|
|
x += 8;
|
|
|
|
}
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_AltString (int x, int y, const char *str)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2011-12-26 11:33:40 +00:00
|
|
|
byte chr;
|
|
|
|
|
|
|
|
if (!str || !str[0])
|
|
|
|
return;
|
|
|
|
if (y <= -8)
|
|
|
|
return; // totally off screen
|
|
|
|
|
|
|
|
while (*str) {
|
|
|
|
if ((chr = *str++ | 0x80) != (0x80 | 32)) { // Don't render spaces
|
|
|
|
queue_character (x, y, chr);
|
|
|
|
}
|
|
|
|
x += 8;
|
|
|
|
}
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
2011-12-27 08:59:58 +00:00
|
|
|
static void
|
2012-12-12 10:36:18 +00:00
|
|
|
draw_crosshair_plus (int ch, int x, int y)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_Character (x - 4, y - 4, '+');
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
2011-12-27 08:59:58 +00:00
|
|
|
static void
|
2012-12-12 10:36:18 +00:00
|
|
|
draw_crosshair_pic (int ch, int x, int y)
|
|
|
|
{
|
|
|
|
static const int pos[CROSSHAIR_COUNT][4] = {
|
|
|
|
{0, 0, CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT},
|
|
|
|
{CROSSHAIR_WIDTH, 0, CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT},
|
|
|
|
{0, CROSSHAIR_HEIGHT, CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT},
|
|
|
|
{CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT, CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT},
|
|
|
|
};
|
|
|
|
const int *p = pos[ch - 1];
|
|
|
|
|
2022-11-19 15:50:59 +00:00
|
|
|
draw_pic (x - CROSSHAIR_WIDTH / 2 + 1, y - CROSSHAIR_HEIGHT / 2 + 1,
|
|
|
|
CROSSHAIR_WIDTH, CROSSHAIR_HEIGHT, crosshair_pic,
|
2012-12-12 10:36:18 +00:00
|
|
|
p[0], p[1], p[2], p[3], crosshair_color);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void (*crosshair_func[]) (int ch, int x, int y) = {
|
|
|
|
draw_crosshair_plus,
|
|
|
|
draw_crosshair_pic,
|
|
|
|
draw_crosshair_pic,
|
|
|
|
draw_crosshair_pic,
|
|
|
|
draw_crosshair_pic,
|
|
|
|
};
|
2011-12-23 03:19:50 +00:00
|
|
|
|
2012-12-12 10:36:18 +00:00
|
|
|
void
|
|
|
|
glsl_Draw_CrosshairAt (int ch, int x, int y)
|
2011-12-26 11:33:40 +00:00
|
|
|
{
|
2012-12-12 10:36:18 +00:00
|
|
|
unsigned c = ch - 1;
|
2011-12-26 11:33:40 +00:00
|
|
|
|
2012-12-12 10:36:18 +00:00
|
|
|
if (c >= sizeof (crosshair_func) / sizeof (crosshair_func[0]))
|
|
|
|
return;
|
2011-12-26 11:33:40 +00:00
|
|
|
|
2012-12-12 10:36:18 +00:00
|
|
|
crosshair_func[c] (c, x, y);
|
2011-12-27 08:59:58 +00:00
|
|
|
}
|
2011-12-26 11:33:40 +00:00
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_Crosshair (void)
|
2011-12-27 08:59:58 +00:00
|
|
|
{
|
|
|
|
int x, y;
|
2022-11-18 02:23:32 +00:00
|
|
|
int s = 2 * glsl_2d_scale;
|
2011-12-26 11:33:40 +00:00
|
|
|
|
2022-11-18 02:23:32 +00:00
|
|
|
x = vid.width / s + cl_crossx;
|
|
|
|
y = vid.height / s + cl_crossy;
|
2011-12-26 11:33:40 +00:00
|
|
|
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
glsl_Draw_CrosshairAt (crosshair, x, y);
|
2011-12-26 11:33:40 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_Pic (int x, int y, qpic_t *pic)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2011-12-28 00:04:26 +00:00
|
|
|
static quat_t color = { 1, 1, 1, 1};
|
2011-12-29 02:25:27 +00:00
|
|
|
draw_pic (x, y, pic->width, pic->height, pic,
|
|
|
|
0, 0, pic->width, pic->height, color);
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_Picf (float x, float y, qpic_t *pic)
|
2012-02-06 10:32:30 +00:00
|
|
|
{
|
|
|
|
static quat_t color = { 1, 1, 1, 1};
|
|
|
|
draw_pic (x, y, pic->width, pic->height, pic,
|
|
|
|
0, 0, pic->width, pic->height, color);
|
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width,
|
|
|
|
int height)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2011-12-28 00:04:26 +00:00
|
|
|
static quat_t color = { 1, 1, 1, 1};
|
2011-12-29 02:25:27 +00:00
|
|
|
draw_pic (x, y, width, height, pic, srcx, srcy, width, height, color);
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_ConsoleBackground (int lines, byte alpha)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2022-11-13 13:23:56 +00:00
|
|
|
int s = glsl_2d_scale;
|
|
|
|
float ofs = (vid.height - s * lines) / (float) vid.height;
|
2012-07-03 04:38:35 +00:00
|
|
|
quat_t color = {1, 1, 1, bound (0, alpha, 255) / 255.0};
|
|
|
|
drawvert_t verts[] = {
|
2022-11-13 13:23:56 +00:00
|
|
|
{{ 0, 0, 0, ofs}},
|
|
|
|
{{vid.width / s, 0, 1, ofs}},
|
|
|
|
{{vid.width / s, lines, 1, 1}},
|
|
|
|
{{ 0, 0, 0, ofs}},
|
|
|
|
{{vid.width / s, lines, 1, 1}},
|
|
|
|
{{ 0, lines, 0, 1}},
|
2011-12-26 11:33:40 +00:00
|
|
|
};
|
|
|
|
|
2012-02-22 12:53:17 +00:00
|
|
|
GLSL_FlushText (); // Flush text that should be rendered before the console
|
2011-12-29 09:23:09 +00:00
|
|
|
|
2012-07-03 04:38:35 +00:00
|
|
|
QuatCopy (color, verts[0].color);
|
|
|
|
QuatCopy (color, verts[1].color);
|
|
|
|
QuatCopy (color, verts[2].color);
|
|
|
|
QuatCopy (color, verts[3].color);
|
|
|
|
QuatCopy (color, verts[4].color);
|
|
|
|
QuatCopy (color, verts[5].color);
|
2011-12-26 11:33:40 +00:00
|
|
|
|
[cvar] Make cvars properly typed
This is an extremely extensive patch as it hits every cvar, and every
usage of the cvars. Cvars no longer store the value they control,
instead, they use a cexpr value object to reference the value and
specify the value's type (currently, a null type is used for strings).
Non-string cvars are passed through cexpr, allowing expressions in the
cvars' settings. Also, cvars have returned to an enhanced version of the
original (id quake) registration scheme.
As a minor benefit, relevant code having direct access to the
cvar-controlled variables is probably a slight optimization as it
removed a pointer dereference, and the variables can be located for data
locality.
The static cvar descriptors are made private as an additional safety
layer, though there's nothing stopping external modification via
Cvar_FindVar (which is needed for adding listeners).
While not used yet (partly due to working out the design), cvars can
have a validation function.
Registering a cvar allows a primary listener (and its data) to be
specified: it will always be called first when the cvar is modified. The
combination of proper listeners and direct access to the controlled
variable greatly simplifies the more complex cvar interactions as much
less null checking is required, and there's no need for one cvar's
callback to call another's.
nq-x11 is known to work at least well enough for the demos. More testing
will come.
2022-04-23 03:22:45 +00:00
|
|
|
if (glsl_conback_texnum)
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, glsl_conback_texnum);
|
2012-07-02 11:01:28 +00:00
|
|
|
else
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, conback_texture);
|
2011-12-26 11:33:40 +00:00
|
|
|
|
2012-07-03 04:38:35 +00:00
|
|
|
qfeglVertexAttribPointer (quake_2d.vertex.location, 4, GL_FLOAT,
|
|
|
|
0, sizeof (drawvert_t), &verts[0].xyst);
|
|
|
|
qfeglVertexAttribPointer (quake_2d.color.location, 4, GL_FLOAT,
|
|
|
|
0, sizeof (drawvert_t), &verts[0].color);
|
2011-12-26 11:33:40 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglDrawArrays (GL_TRIANGLES, 0, 6);
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_TileClear (int x, int y, int w, int h)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2012-07-09 06:56:51 +00:00
|
|
|
static quat_t color = { 1, 1, 1, 1 };
|
2012-07-09 06:11:03 +00:00
|
|
|
vrect_t *tile_rect = VRect_New (x, y, w, h);
|
|
|
|
vrect_t *sub = VRect_New (0, 0, 0, 0); // filled in later;
|
2022-11-18 15:41:52 +00:00
|
|
|
subpic_t *sp = *(subpic_t **) backtile_pic->data;
|
2012-07-09 06:11:03 +00:00
|
|
|
int sub_sx, sub_sy, sub_ex, sub_ey;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
sub_sx = x / sp->width;
|
|
|
|
sub_sy = y / sp->height;
|
|
|
|
sub_ex = (x + w + sp->width - 1) / sp->width;
|
|
|
|
sub_ey = (y + h + sp->height - 1) / sp->height;
|
|
|
|
for (j = sub_sy; j < sub_ey; j++) {
|
|
|
|
for (i = sub_sx; i < sub_ex; i++) {
|
|
|
|
vrect_t *t = sub;
|
|
|
|
|
|
|
|
sub->x = i * sp->width;
|
|
|
|
sub->y = j * sp->height;
|
|
|
|
sub->width = sp->width;
|
|
|
|
sub->height = sp->height;
|
|
|
|
sub = VRect_Intersect (sub, tile_rect);
|
|
|
|
VRect_Delete (t);
|
|
|
|
draw_pic (sub->x, sub->y, sub->width, sub->height, backtile_pic,
|
2012-07-09 06:56:51 +00:00
|
|
|
sub->x % sp->width, sub->y % sp->height,
|
|
|
|
sub->width, sub->height, color);
|
2012-07-09 06:11:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
VRect_Delete (sub);
|
|
|
|
VRect_Delete (tile_rect);
|
|
|
|
flush_2d ();
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_Fill (int x, int y, int w, int h, int c)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2011-12-29 02:25:27 +00:00
|
|
|
quat_t color;
|
|
|
|
|
|
|
|
VectorScale (vid.palette + c * 3, 1.0f/255.0f, color);
|
|
|
|
color[3] = 1.0;
|
|
|
|
draw_pic (x, y, w, h, white_pic, 0, 0, 8, 8, color);
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
|
|
|
|
2022-05-28 09:14:26 +00:00
|
|
|
void
|
|
|
|
glsl_Draw_Line (int x0, int y0, int x1, int y1, int c)
|
|
|
|
{
|
2022-11-18 15:41:52 +00:00
|
|
|
subpic_t *sp = *(subpic_t **) white_pic->data;
|
2022-05-28 09:14:26 +00:00
|
|
|
float sl = sp->rect->x * sp->size;
|
|
|
|
float sh = sp->rect->x * sp->size;
|
|
|
|
float tl = sp->rect->y * sp->size;
|
|
|
|
float th = sp->rect->y * sp->size;
|
|
|
|
|
|
|
|
quat_t color = { VectorExpand (vid.palette + c * 3), 255 };
|
|
|
|
QuatScale (color, 1/255.0, color);
|
|
|
|
drawvert_t verts[2] = {
|
|
|
|
{ .xyst = { x0, y0, sl, tl }, .color = { QuatExpand (color) }, },
|
|
|
|
{ .xyst = { x1, y1, sh, th }, .color = { QuatExpand (color) }, },
|
|
|
|
};
|
|
|
|
|
|
|
|
void *v;
|
|
|
|
int size = sizeof (verts);
|
|
|
|
|
|
|
|
line_queue->size += size;
|
|
|
|
dstring_adjust (line_queue);
|
|
|
|
v = line_queue->str + line_queue->size - size;
|
|
|
|
memcpy (v, verts, size);
|
|
|
|
}
|
|
|
|
|
2022-12-02 01:51:41 +00:00
|
|
|
void
|
|
|
|
glsl_LineGraph (int x, int y, int *h_vals, int count, int height)
|
|
|
|
{
|
|
|
|
static int colors[] = { 0xd0, 0x4f, 0x6f };
|
|
|
|
|
|
|
|
while (count-- > 0) {
|
|
|
|
int h = *h_vals++;
|
|
|
|
int c = h < 9998 || h > 10000 ? 0xfe : colors[h - 9998];
|
|
|
|
h = min (h, height);
|
|
|
|
glsl_Draw_Line (x, y, x, y - h, c);
|
|
|
|
x++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-28 11:45:14 +00:00
|
|
|
static inline void
|
|
|
|
draw_blendscreen (quat_t color)
|
|
|
|
{
|
2022-09-21 08:31:18 +00:00
|
|
|
draw_pic (0, 0, vid.width, vid.height, white_pic, 0, 0, 8, 8, color);
|
2012-01-28 11:45:14 +00:00
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_FadeScreen (void)
|
2011-12-23 03:19:50 +00:00
|
|
|
{
|
2011-12-29 08:51:31 +00:00
|
|
|
static quat_t color = { 0, 0, 0, 0.7 };
|
|
|
|
|
2012-02-22 12:53:17 +00:00
|
|
|
GLSL_FlushText (); // Flush text that should be rendered before the menu
|
2012-01-28 11:45:14 +00:00
|
|
|
draw_blendscreen (color);
|
2011-12-23 03:19:50 +00:00
|
|
|
}
|
2011-12-25 10:42:39 +00:00
|
|
|
|
2011-12-25 23:12:05 +00:00
|
|
|
static void
|
|
|
|
ortho_mat (float *proj, float xmin, float xmax, float ymin, float ymax,
|
|
|
|
float znear, float zfar)
|
|
|
|
{
|
2012-01-13 10:46:52 +00:00
|
|
|
proj[0] = 2 / (xmax - xmin);
|
2011-12-25 23:12:05 +00:00
|
|
|
proj[4] = 0;
|
|
|
|
proj[8] = 0;
|
2012-01-13 10:46:52 +00:00
|
|
|
proj[12] = -(xmax + xmin) / (xmax - xmin);
|
2011-12-25 23:12:05 +00:00
|
|
|
|
|
|
|
proj[1] = 0;
|
2012-01-13 10:46:52 +00:00
|
|
|
proj[5] = 2 / (ymax - ymin);
|
2011-12-25 23:12:05 +00:00
|
|
|
proj[9] = 0;
|
2012-01-13 10:46:52 +00:00
|
|
|
proj[13] = -(ymax + ymin) / (ymax - ymin);
|
2011-12-25 23:12:05 +00:00
|
|
|
|
|
|
|
proj[2] = 0;
|
|
|
|
proj[6] = 0;
|
2012-01-13 10:46:52 +00:00
|
|
|
proj[10] = -2 / (zfar - znear);
|
|
|
|
proj[14] = -(zfar + znear) / (zfar - znear);
|
2011-12-25 23:12:05 +00:00
|
|
|
|
|
|
|
proj[3] = 0;
|
|
|
|
proj[7] = 0;
|
|
|
|
proj[11] = 0;
|
|
|
|
proj[15] = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_2d (int width, int height)
|
|
|
|
{
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglViewport (0, 0, vid.width, vid.height);
|
2011-12-25 23:12:05 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglDisable (GL_DEPTH_TEST);
|
|
|
|
qfeglDisable (GL_CULL_FACE);
|
2011-12-25 23:12:05 +00:00
|
|
|
|
2022-11-19 16:17:09 +00:00
|
|
|
ortho_mat (proj_matrix, 0, width, height, 0, -99999, 99999);
|
2012-07-03 04:38:35 +00:00
|
|
|
|
|
|
|
qfeglUseProgram (quake_2d.program);
|
|
|
|
qfeglEnableVertexAttribArray (quake_2d.vertex.location);
|
|
|
|
qfeglEnableVertexAttribArray (quake_2d.color.location);
|
|
|
|
|
|
|
|
qfeglUniformMatrix4fv (quake_2d.matrix.location, 1, false, proj_matrix);
|
|
|
|
|
|
|
|
qfeglUniform1i (quake_2d.palette.location, 1);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 1);
|
|
|
|
qfeglEnable (GL_TEXTURE_2D);
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, glsl_palette);
|
|
|
|
|
|
|
|
qfeglUniform1i (quake_2d.texture.location, 0);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 0);
|
|
|
|
qfeglEnable (GL_TEXTURE_2D);
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, GLSL_ScrapTexture (draw_scrap));
|
2011-12-25 23:12:05 +00:00
|
|
|
}
|
|
|
|
|
2011-12-25 10:42:39 +00:00
|
|
|
void
|
2012-02-22 12:53:17 +00:00
|
|
|
GLSL_Set2D (void)
|
2011-12-25 22:59:36 +00:00
|
|
|
{
|
2011-12-25 23:12:05 +00:00
|
|
|
set_2d (vid.width, vid.height);
|
2011-12-25 22:59:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-02-22 12:53:17 +00:00
|
|
|
GLSL_Set2DScaled (void)
|
2011-12-25 22:59:36 +00:00
|
|
|
{
|
2022-11-13 13:23:56 +00:00
|
|
|
set_2d (vid.width / glsl_2d_scale, vid.height / glsl_2d_scale);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
glsl_Draw_SetScale (int scale)
|
|
|
|
{
|
|
|
|
glsl_2d_scale = scale;
|
2011-12-25 22:59:36 +00:00
|
|
|
}
|
|
|
|
|
2012-07-03 04:38:35 +00:00
|
|
|
void
|
|
|
|
GLSL_End2D (void)
|
|
|
|
{
|
|
|
|
qfeglDisableVertexAttribArray (quake_2d.vertex.location);
|
|
|
|
qfeglDisableVertexAttribArray (quake_2d.color.location);
|
|
|
|
}
|
|
|
|
|
2011-12-25 22:59:36 +00:00
|
|
|
void
|
2012-02-22 12:53:17 +00:00
|
|
|
GLSL_DrawReset (void)
|
2011-12-25 10:42:39 +00:00
|
|
|
{
|
2012-07-03 05:45:16 +00:00
|
|
|
draw_queue->size = 0;
|
2022-05-28 09:14:26 +00:00
|
|
|
line_queue->size = 0;
|
2011-12-25 10:42:39 +00:00
|
|
|
}
|
2011-12-25 22:59:36 +00:00
|
|
|
|
|
|
|
void
|
2012-02-22 12:53:17 +00:00
|
|
|
GLSL_FlushText (void)
|
2011-12-25 22:59:36 +00:00
|
|
|
{
|
2022-05-28 09:14:26 +00:00
|
|
|
if (draw_queue->size || line_queue->size)
|
2012-07-03 04:38:35 +00:00
|
|
|
flush_2d ();
|
2011-12-25 22:59:36 +00:00
|
|
|
}
|
2012-01-28 11:45:14 +00:00
|
|
|
|
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_Draw_BlendScreen (quat_t color)
|
2012-01-28 11:45:14 +00:00
|
|
|
{
|
|
|
|
if (!color[3])
|
|
|
|
return;
|
|
|
|
draw_blendscreen (color);
|
|
|
|
}
|
2022-08-31 10:23:30 +00:00
|
|
|
|
2022-10-02 23:58:27 +00:00
|
|
|
int
|
2022-12-07 06:11:08 +00:00
|
|
|
glsl_Draw_AddFont (font_t *rfont)
|
2022-08-31 10:23:30 +00:00
|
|
|
{
|
2022-12-05 16:18:01 +00:00
|
|
|
int fontid = glsl_fonts.size;
|
|
|
|
DARRAY_OPEN_AT (&glsl_fonts, fontid, 1);
|
|
|
|
glslfont_t *font = &glsl_fonts.a[fontid];
|
|
|
|
|
|
|
|
font->font = rfont;
|
|
|
|
tex_t tex = {
|
|
|
|
.width = rfont->scrap.width,
|
|
|
|
.height = rfont->scrap.height,
|
|
|
|
.format = tex_a,
|
|
|
|
.loaded = 1,
|
|
|
|
.data = rfont->scrap_bitmap,
|
|
|
|
};
|
|
|
|
font->texid = GLSL_LoadTex ("", 1, &tex);
|
|
|
|
return fontid;
|
|
|
|
}
|
2022-12-08 06:33:50 +00:00
|
|
|
#if 0
|
2022-12-05 16:18:01 +00:00
|
|
|
typedef struct {
|
|
|
|
vrect_t *glyph_rects;
|
|
|
|
dstring_t *batch;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
float color[4];
|
|
|
|
} glslrgctx_t;
|
|
|
|
|
|
|
|
static void
|
|
|
|
glsl_render_glyph (uint32_t glyphid, int x, int y, void *_rgctx)
|
|
|
|
{
|
|
|
|
glslrgctx_t *rgctx = _rgctx;
|
|
|
|
vrect_t *rect = &rgctx->glyph_rects[glyphid];
|
|
|
|
dstring_t *batch = rgctx->batch;
|
|
|
|
|
2022-12-10 09:55:08 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
void
|
|
|
|
glsl_Draw_Glyph (int x, int y, int fontid, int glyphid, int c)
|
|
|
|
{
|
|
|
|
if (fontid < 0 || (unsigned) fontid > glsl_fonts.size) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
glslfont_t *font = &glsl_fonts.a[fontid];
|
|
|
|
font_t *rfont = font->font;
|
|
|
|
vrect_t *rect = &rfont->glyph_rects[glyphid];
|
|
|
|
|
|
|
|
dstring_t *batch = glyph_queue;
|
|
|
|
int size = 6 * sizeof (drawvert_t);
|
2022-12-05 16:18:01 +00:00
|
|
|
batch->size += size;
|
|
|
|
dstring_adjust (batch);
|
|
|
|
drawvert_t *verts = (drawvert_t *) (batch->str + batch->size - size);
|
|
|
|
|
|
|
|
float w = rect->width;
|
|
|
|
float h = rect->height;
|
|
|
|
float u = rect->x;
|
|
|
|
float v = rect->y;
|
2022-12-10 09:55:08 +00:00
|
|
|
float s = 1.0 / rfont->scrap.width;
|
|
|
|
float t = 1.0 / rfont->scrap.height;
|
2022-12-05 16:18:01 +00:00
|
|
|
|
|
|
|
verts[0] = (drawvert_t) {
|
|
|
|
.xyst = { x, y, u * s, v * t },
|
|
|
|
};
|
|
|
|
verts[1] = (drawvert_t) {
|
|
|
|
.xyst = { x + w, y, (u + w) * s, v * t },
|
|
|
|
};
|
|
|
|
verts[2] = (drawvert_t) {
|
|
|
|
.xyst = { x + w, y + h, (u + w) * s, (v + h) * t },
|
|
|
|
};
|
|
|
|
verts[3] = (drawvert_t) {
|
|
|
|
.xyst = { x, y, u * s, v * t },
|
|
|
|
};
|
|
|
|
verts[4] = (drawvert_t) {
|
|
|
|
.xyst = { x + w, y + h, (u + w) * s, (v + h) * t },
|
|
|
|
};
|
|
|
|
verts[5] = (drawvert_t) {
|
|
|
|
.xyst = { x, y + h, u * s, (v + h) * t },
|
|
|
|
};
|
|
|
|
|
2022-12-10 09:55:08 +00:00
|
|
|
quat_t color = { VectorExpand (vid.palette + c * 3), 255 };
|
|
|
|
QuatScale (color, 1.0f/255.0f, color);
|
|
|
|
QuatCopy (color, verts[0].color);
|
|
|
|
QuatCopy (color, verts[1].color);
|
|
|
|
QuatCopy (color, verts[2].color);
|
|
|
|
QuatCopy (color, verts[3].color);
|
|
|
|
QuatCopy (color, verts[4].color);
|
|
|
|
QuatCopy (color, verts[5].color);
|
2022-12-05 16:18:01 +00:00
|
|
|
|
|
|
|
qfeglUseProgram (alpha_2d.program);
|
|
|
|
qfeglEnableVertexAttribArray (alpha_2d.vertex.location);
|
|
|
|
qfeglEnableVertexAttribArray (alpha_2d.color.location);
|
|
|
|
qfeglUniformMatrix4fv (alpha_2d.matrix.location, 1, false, proj_matrix);
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, font->texid);
|
|
|
|
qfeglBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
if (glyph_queue->size) {
|
|
|
|
qfeglVertexAttribPointer (alpha_2d.vertex.location, 4, GL_FLOAT,
|
|
|
|
0, 32, glyph_queue->str);
|
|
|
|
qfeglVertexAttribPointer (alpha_2d.color.location, 4, GL_FLOAT,
|
|
|
|
0, 32, glyph_queue->str + 16);
|
|
|
|
|
|
|
|
qfeglDrawArrays (GL_TRIANGLES, 0, glyph_queue->size / 32);
|
|
|
|
}
|
|
|
|
glyph_queue->size = 0;
|
|
|
|
qfeglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
qfeglUseProgram (quake_2d.program);
|
2022-09-02 02:38:09 +00:00
|
|
|
}
|