2012-01-08 01:29:38 +00:00
|
|
|
/*
|
|
|
|
glsl_bsp.c
|
|
|
|
|
|
|
|
GLSL bsps
|
|
|
|
|
|
|
|
Copyright (C) 2012 Bill Currie <bill@taniwha.org>
|
|
|
|
|
|
|
|
Author: Bill Currie <bill@taniwha.org>
|
|
|
|
Date: 2012/1/7
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
# include <string.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
# include <strings.h>
|
|
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
2013-01-22 05:09:41 +00:00
|
|
|
#include "qfalloca.h"
|
|
|
|
|
2012-01-08 11:39:36 +00:00
|
|
|
#include "QF/cvar.h"
|
2012-01-08 08:45:44 +00:00
|
|
|
#include "QF/dstring.h"
|
2012-01-12 02:05:34 +00:00
|
|
|
#include "QF/image.h"
|
2012-01-08 01:29:38 +00:00
|
|
|
#include "QF/render.h"
|
|
|
|
#include "QF/sys.h"
|
2012-01-12 02:05:34 +00:00
|
|
|
#include "QF/va.h"
|
2012-01-08 01:29:38 +00:00
|
|
|
|
2021-07-24 05:19:52 +00:00
|
|
|
#include "QF/scene/entity.h"
|
|
|
|
|
2012-01-08 01:29:38 +00:00
|
|
|
#include "QF/GLSL/defines.h"
|
|
|
|
#include "QF/GLSL/funcs.h"
|
|
|
|
#include "QF/GLSL/qf_bsp.h"
|
2012-01-09 07:46:20 +00:00
|
|
|
#include "QF/GLSL/qf_lightmap.h"
|
2012-01-08 08:45:44 +00:00
|
|
|
#include "QF/GLSL/qf_textures.h"
|
2012-01-08 11:39:36 +00:00
|
|
|
#include "QF/GLSL/qf_vid.h"
|
2012-01-08 01:29:38 +00:00
|
|
|
|
2012-02-14 08:28:09 +00:00
|
|
|
#include "r_internal.h"
|
2012-01-08 01:29:38 +00:00
|
|
|
|
2012-01-08 08:45:44 +00:00
|
|
|
typedef struct {
|
|
|
|
GLushort count;
|
|
|
|
GLushort indices[1];
|
|
|
|
} glslpoly_t;
|
|
|
|
|
2012-01-08 01:29:38 +00:00
|
|
|
#define ALLOC_CHUNK 64
|
|
|
|
|
2012-02-17 09:57:13 +00:00
|
|
|
static instsurf_t *waterchain = NULL;
|
|
|
|
static instsurf_t **waterchain_tail = &waterchain;
|
|
|
|
static instsurf_t *sky_chain;
|
|
|
|
static instsurf_t **sky_chain_tail = &sky_chain;
|
2012-01-08 01:29:38 +00:00
|
|
|
|
2021-01-19 04:05:39 +00:00
|
|
|
static glsltex_t **r_texture_chains;
|
2012-01-08 01:29:38 +00:00
|
|
|
static int r_num_texture_chains;
|
|
|
|
static int max_texture_chains;
|
|
|
|
|
|
|
|
// for world and non-instance models
|
|
|
|
static instsurf_t *static_instsurfs;
|
|
|
|
static instsurf_t **static_instsurfs_tail = &static_instsurfs;
|
|
|
|
static instsurf_t *free_static_instsurfs;
|
|
|
|
|
|
|
|
// for instance models
|
|
|
|
static elechain_t *elechains;
|
|
|
|
static elechain_t **elechains_tail = &elechains;
|
|
|
|
static elechain_t *free_elechains;
|
2012-01-08 08:45:44 +00:00
|
|
|
static elements_t *elementss;
|
|
|
|
static elements_t **elementss_tail = &elementss;
|
|
|
|
static elements_t *free_elementss;
|
2012-01-08 01:29:38 +00:00
|
|
|
static instsurf_t *instsurfs;
|
|
|
|
static instsurf_t **instsurfs_tail = &instsurfs;
|
|
|
|
static instsurf_t *free_instsurfs;
|
|
|
|
|
2012-01-08 11:39:36 +00:00
|
|
|
static GLuint bsp_vbo;
|
2021-03-09 14:52:40 +00:00
|
|
|
static mat4f_t bsp_vp;
|
2012-01-08 11:39:36 +00:00
|
|
|
|
2012-01-12 02:05:34 +00:00
|
|
|
static GLuint skybox_tex;
|
|
|
|
static qboolean skybox_loaded;
|
2012-01-12 12:23:39 +00:00
|
|
|
static quat_t sky_rotation[2];
|
|
|
|
static quat_t sky_velocity;
|
2012-09-12 10:06:07 +00:00
|
|
|
static quat_t sky_fix;
|
2012-01-12 12:23:39 +00:00
|
|
|
static double sky_time;
|
2012-01-12 02:05:34 +00:00
|
|
|
|
2012-01-29 07:56:50 +00:00
|
|
|
static quat_t default_color = { 1, 1, 1, 1 };
|
2012-06-29 13:13:20 +00:00
|
|
|
static quat_t last_color;
|
2022-05-05 12:22:44 +00:00
|
|
|
static glsltex_t glsl_notexture = { };
|
2012-01-29 07:56:50 +00:00
|
|
|
|
2013-06-07 08:12:44 +00:00
|
|
|
static const char *bsp_vert_effects[] =
|
|
|
|
{
|
|
|
|
"QuakeForge.Vertex.bsp",
|
|
|
|
0
|
|
|
|
};
|
2012-01-08 11:39:36 +00:00
|
|
|
|
2013-06-07 08:12:44 +00:00
|
|
|
static const char *bsp_lit_effects[] =
|
|
|
|
{
|
|
|
|
"QuakeForge.Fragment.fog",
|
2013-06-07 10:08:58 +00:00
|
|
|
"QuakeForge.env.warp.nop",
|
2013-06-07 08:12:44 +00:00
|
|
|
"QuakeForge.Fragment.colormap",
|
|
|
|
"QuakeForge.Fragment.bsp.lit",
|
|
|
|
0
|
|
|
|
};
|
2012-01-10 11:50:47 +00:00
|
|
|
|
2013-06-07 08:12:44 +00:00
|
|
|
static const char *bsp_turb_effects[] =
|
|
|
|
{
|
2013-06-07 10:08:58 +00:00
|
|
|
"QuakeForge.Math.const",
|
2013-06-07 08:12:44 +00:00
|
|
|
"QuakeForge.Fragment.fog",
|
2014-01-28 04:00:28 +00:00
|
|
|
"QuakeForge.Fragment.palette",
|
2013-06-07 10:08:58 +00:00
|
|
|
"QuakeForge.env.warp.turb",
|
|
|
|
"QuakeForge.Fragment.bsp.unlit",
|
2013-06-07 08:12:44 +00:00
|
|
|
0
|
|
|
|
};
|
2012-01-11 07:02:20 +00:00
|
|
|
|
2013-06-07 08:12:44 +00:00
|
|
|
static const char *bsp_sky_cube_effects[] =
|
|
|
|
{
|
|
|
|
"QuakeForge.Fragment.fog",
|
|
|
|
"QuakeForge.env.sky.cube",
|
|
|
|
"QuakeForge.Fragment.bsp.sky",
|
|
|
|
0
|
|
|
|
};
|
2012-01-11 07:02:20 +00:00
|
|
|
|
2013-06-07 08:12:44 +00:00
|
|
|
static const char *bsp_sky_id_effects[] =
|
|
|
|
{
|
|
|
|
"QuakeForge.Fragment.fog",
|
2014-01-28 04:00:28 +00:00
|
|
|
"QuakeForge.Fragment.palette",
|
2013-06-07 08:12:44 +00:00
|
|
|
"QuakeForge.env.sky.id",
|
|
|
|
"QuakeForge.Fragment.bsp.sky",
|
|
|
|
0
|
|
|
|
};
|
2012-01-12 02:05:34 +00:00
|
|
|
|
2012-01-08 11:39:36 +00:00
|
|
|
static struct {
|
|
|
|
int program;
|
|
|
|
shaderparam_t mvp_matrix;
|
|
|
|
shaderparam_t tlst;
|
|
|
|
shaderparam_t vertex;
|
|
|
|
shaderparam_t colormap;
|
|
|
|
shaderparam_t texture;
|
|
|
|
shaderparam_t lightmap;
|
2012-01-28 12:20:34 +00:00
|
|
|
shaderparam_t color;
|
2012-01-29 01:27:28 +00:00
|
|
|
shaderparam_t fog;
|
2012-01-08 11:39:36 +00:00
|
|
|
} quake_bsp = {
|
|
|
|
0,
|
|
|
|
{"mvp_mat", 1},
|
|
|
|
{"tlst", 0},
|
|
|
|
{"vertex", 0},
|
|
|
|
{"colormap", 1},
|
|
|
|
{"texture", 1},
|
|
|
|
{"lightmap", 1},
|
2012-01-28 12:20:34 +00:00
|
|
|
{"vcolor", 0},
|
2012-01-29 01:27:28 +00:00
|
|
|
{"fog", 1},
|
2012-01-08 11:39:36 +00:00
|
|
|
};
|
|
|
|
|
2012-01-10 11:50:47 +00:00
|
|
|
static struct {
|
|
|
|
int program;
|
|
|
|
shaderparam_t mvp_matrix;
|
|
|
|
shaderparam_t tlst;
|
|
|
|
shaderparam_t vertex;
|
|
|
|
shaderparam_t palette;
|
|
|
|
shaderparam_t texture;
|
2013-06-07 08:12:44 +00:00
|
|
|
shaderparam_t time;
|
2012-01-28 12:20:34 +00:00
|
|
|
shaderparam_t color;
|
2012-01-29 01:27:28 +00:00
|
|
|
shaderparam_t fog;
|
2012-01-10 11:50:47 +00:00
|
|
|
} quake_turb = {
|
|
|
|
0,
|
|
|
|
{"mvp_mat", 1},
|
|
|
|
{"tlst", 0},
|
|
|
|
{"vertex", 0},
|
|
|
|
{"palette", 1},
|
|
|
|
{"texture", 1},
|
2013-06-07 08:12:44 +00:00
|
|
|
{"time", 1},
|
2012-01-28 12:20:34 +00:00
|
|
|
{"vcolor", 0},
|
2012-01-29 01:27:28 +00:00
|
|
|
{"fog", 1},
|
2012-01-10 11:50:47 +00:00
|
|
|
};
|
|
|
|
|
2012-01-11 07:02:20 +00:00
|
|
|
static struct {
|
|
|
|
int program;
|
|
|
|
shaderparam_t mvp_matrix;
|
2012-01-12 12:23:39 +00:00
|
|
|
shaderparam_t sky_matrix;
|
2012-01-11 07:02:20 +00:00
|
|
|
shaderparam_t vertex;
|
|
|
|
shaderparam_t palette;
|
|
|
|
shaderparam_t solid;
|
|
|
|
shaderparam_t trans;
|
2013-06-07 08:12:44 +00:00
|
|
|
shaderparam_t time;
|
2012-01-29 01:27:28 +00:00
|
|
|
shaderparam_t fog;
|
2012-01-11 07:02:20 +00:00
|
|
|
} quake_skyid = {
|
|
|
|
0,
|
|
|
|
{"mvp_mat", 1},
|
2012-01-12 12:23:39 +00:00
|
|
|
{"sky_mat", 1},
|
2012-01-11 07:02:20 +00:00
|
|
|
{"vertex", 0},
|
|
|
|
{"palette", 1},
|
|
|
|
{"solid", 1},
|
|
|
|
{"trans", 1},
|
2013-06-07 08:12:44 +00:00
|
|
|
{"time", 1},
|
2012-01-29 01:27:28 +00:00
|
|
|
{"fog", 1},
|
2012-01-11 07:02:20 +00:00
|
|
|
};
|
|
|
|
|
2012-01-12 02:05:34 +00:00
|
|
|
static struct {
|
|
|
|
int program;
|
|
|
|
shaderparam_t mvp_matrix;
|
2012-01-12 12:23:39 +00:00
|
|
|
shaderparam_t sky_matrix;
|
2012-01-12 02:05:34 +00:00
|
|
|
shaderparam_t vertex;
|
|
|
|
shaderparam_t sky;
|
2012-01-29 01:27:28 +00:00
|
|
|
shaderparam_t fog;
|
2012-01-12 02:05:34 +00:00
|
|
|
} quake_skybox = {
|
|
|
|
0,
|
|
|
|
{"mvp_mat", 1},
|
2012-01-12 12:23:39 +00:00
|
|
|
{"sky_mat", 1},
|
2012-01-12 02:05:34 +00:00
|
|
|
{"vertex", 0},
|
|
|
|
{"sky", 1},
|
2012-01-29 01:27:28 +00:00
|
|
|
{"fog", 1},
|
2012-01-12 02:05:34 +00:00
|
|
|
};
|
|
|
|
|
2012-01-12 08:34:29 +00:00
|
|
|
static struct {
|
|
|
|
shaderparam_t *mvp_matrix;
|
2012-01-12 12:23:39 +00:00
|
|
|
shaderparam_t *sky_matrix;
|
2012-01-12 08:34:29 +00:00
|
|
|
shaderparam_t *vertex;
|
2012-01-29 01:27:28 +00:00
|
|
|
shaderparam_t *fog;
|
2012-01-12 08:34:29 +00:00
|
|
|
} sky_params;
|
|
|
|
|
2021-07-22 06:39:28 +00:00
|
|
|
typedef struct glslbspctx_s {
|
|
|
|
mod_brush_t *brush;
|
[scene] Make entity_t just an entity id for ECS
This puts the hierarchy (transform) reference, animation, visibility,
renderer, active, and old_origin data in separate components. There are
a few bugs (crashes on grenade explosions in gl/glsl/vulkan, immediately
in sw, reasons known, missing brush models in vulkan).
While quake doesn't really need an ECS, the direction I want to take QF
does, and it does seem to have improved memory bandwidth a little
(uncertain). However, there's a lot more work to go (especially fixing
the above bugs), but this seems to be a good start.
2022-10-23 01:32:09 +00:00
|
|
|
animation_t *animation;
|
|
|
|
vec4f_t *transform;
|
2021-07-22 06:39:28 +00:00
|
|
|
float *color;
|
|
|
|
} glslbspctx_t;
|
|
|
|
|
|
|
|
|
2012-01-08 01:29:38 +00:00
|
|
|
#define CHAIN_SURF_F2B(surf,chain) \
|
2021-07-13 07:02:47 +00:00
|
|
|
({ \
|
2012-01-08 01:29:38 +00:00
|
|
|
instsurf_t *inst = (surf)->instsurf; \
|
2012-02-01 21:01:19 +00:00
|
|
|
if (__builtin_expect(!inst, 1)) \
|
2021-07-13 07:02:47 +00:00
|
|
|
inst = get_instsurf (); \
|
2012-01-08 01:29:38 +00:00
|
|
|
inst->surface = (surf); \
|
|
|
|
*(chain##_tail) = inst; \
|
|
|
|
(chain##_tail) = &inst->tex_chain; \
|
|
|
|
*(chain##_tail) = 0; \
|
2021-07-13 07:02:47 +00:00
|
|
|
inst; \
|
|
|
|
})
|
2012-01-08 01:29:38 +00:00
|
|
|
|
|
|
|
#define CHAIN_SURF_B2F(surf,chain) \
|
2021-07-13 07:02:47 +00:00
|
|
|
({ \
|
2012-01-08 01:29:38 +00:00
|
|
|
instsurf_t *inst = (surf)->instsurf; \
|
2012-02-01 21:01:19 +00:00
|
|
|
if (__builtin_expect(!inst, 1)) \
|
2021-07-13 07:02:47 +00:00
|
|
|
inst = get_instsurf (); \
|
2012-01-08 01:29:38 +00:00
|
|
|
inst->surface = (surf); \
|
|
|
|
inst->tex_chain = (chain); \
|
|
|
|
(chain) = inst; \
|
2021-07-13 07:02:47 +00:00
|
|
|
inst; \
|
|
|
|
})
|
2012-01-08 01:29:38 +00:00
|
|
|
|
|
|
|
#define GET_RELEASE(type,name) \
|
|
|
|
static inline type * \
|
|
|
|
get_##name (void) \
|
|
|
|
{ \
|
|
|
|
type *ele; \
|
|
|
|
if (!free_##name##s) { \
|
|
|
|
int i; \
|
|
|
|
free_##name##s = calloc (ALLOC_CHUNK, sizeof (type)); \
|
|
|
|
for (i = 0; i < ALLOC_CHUNK - 1; i++) \
|
|
|
|
free_##name##s[i]._next = &free_##name##s[i + 1]; \
|
|
|
|
} \
|
|
|
|
ele = free_##name##s; \
|
|
|
|
free_##name##s = ele->_next; \
|
|
|
|
ele->_next = 0; \
|
|
|
|
*name##s_tail = ele; \
|
|
|
|
name##s_tail = &ele->_next; \
|
|
|
|
return ele; \
|
|
|
|
} \
|
|
|
|
static inline void \
|
|
|
|
release_##name##s (void) \
|
|
|
|
{ \
|
|
|
|
if (name##s) { \
|
|
|
|
*name##s_tail = free_##name##s; \
|
|
|
|
free_##name##s = name##s; \
|
|
|
|
name##s = 0; \
|
|
|
|
name##s_tail = &name##s; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
GET_RELEASE (elechain_t, elechain)
|
2012-01-08 08:45:44 +00:00
|
|
|
GET_RELEASE (elements_t, elements)
|
2012-01-08 01:29:38 +00:00
|
|
|
GET_RELEASE (instsurf_t, static_instsurf)
|
|
|
|
GET_RELEASE (instsurf_t, instsurf)
|
|
|
|
|
2022-03-14 05:31:23 +00:00
|
|
|
static void
|
2021-01-19 04:05:39 +00:00
|
|
|
glsl_R_AddTexture (texture_t *tx)
|
2012-01-08 01:29:38 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
if (r_num_texture_chains == max_texture_chains) {
|
|
|
|
max_texture_chains += 64;
|
|
|
|
r_texture_chains = realloc (r_texture_chains,
|
2021-01-19 04:05:39 +00:00
|
|
|
max_texture_chains * sizeof (glsltex_t *));
|
2012-01-08 01:29:38 +00:00
|
|
|
for (i = r_num_texture_chains; i < max_texture_chains; i++)
|
|
|
|
r_texture_chains[i] = 0;
|
|
|
|
}
|
2021-01-19 04:05:39 +00:00
|
|
|
glsltex_t *tex = tx->render;
|
2012-01-08 01:29:38 +00:00
|
|
|
r_texture_chains[r_num_texture_chains++] = tex;
|
2012-01-08 08:45:44 +00:00
|
|
|
tex->tex_chain = 0;
|
2012-01-08 01:29:38 +00:00
|
|
|
tex->tex_chain_tail = &tex->tex_chain;
|
2012-01-08 08:45:44 +00:00
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
2012-01-08 01:29:38 +00:00
|
|
|
}
|
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
static void
|
|
|
|
glsl_R_InitSurfaceChains (mod_brush_t *brush)
|
2012-01-08 01:29:38 +00:00
|
|
|
{
|
|
|
|
release_static_instsurfs ();
|
|
|
|
release_instsurfs ();
|
|
|
|
|
2021-08-01 12:54:05 +00:00
|
|
|
for (unsigned i = 0; i < brush->nummodelsurfaces; i++) {
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->surfaces[i].instsurf = get_static_instsurf ();
|
|
|
|
brush->surfaces[i].instsurf->surface = &brush->surfaces[i];
|
2012-01-08 08:45:44 +00:00
|
|
|
}
|
2012-01-08 01:29:38 +00:00
|
|
|
}
|
|
|
|
|
2012-01-09 12:16:08 +00:00
|
|
|
static inline void
|
2021-01-19 04:05:39 +00:00
|
|
|
clear_tex_chain (glsltex_t *tex)
|
2012-01-09 12:16:08 +00:00
|
|
|
{
|
|
|
|
tex->tex_chain = 0;
|
|
|
|
tex->tex_chain_tail = &tex->tex_chain;
|
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
|
|
|
}
|
|
|
|
|
2012-01-08 01:29:38 +00:00
|
|
|
static void
|
|
|
|
clear_texture_chains (void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < r_num_texture_chains; i++) {
|
2012-01-09 12:16:08 +00:00
|
|
|
if (!r_texture_chains[i])
|
2012-01-08 01:29:38 +00:00
|
|
|
continue;
|
2012-01-09 12:16:08 +00:00
|
|
|
clear_tex_chain (r_texture_chains[i]);
|
2012-01-08 01:29:38 +00:00
|
|
|
}
|
2021-01-19 04:05:39 +00:00
|
|
|
clear_tex_chain (r_notexture_mip->render);
|
2012-01-08 08:45:44 +00:00
|
|
|
release_elechains ();
|
|
|
|
release_elementss ();
|
2012-01-08 01:29:38 +00:00
|
|
|
release_instsurfs ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_R_ClearElements (void)
|
2012-01-08 01:29:38 +00:00
|
|
|
{
|
|
|
|
release_elechains ();
|
2012-01-08 08:45:44 +00:00
|
|
|
release_elementss ();
|
2012-01-08 01:29:38 +00:00
|
|
|
}
|
|
|
|
|
2012-01-27 12:48:25 +00:00
|
|
|
static void
|
2021-07-22 06:39:28 +00:00
|
|
|
update_lightmap (glslbspctx_t *bctx, msurface_t *surf)
|
2012-01-27 12:48:25 +00:00
|
|
|
{
|
|
|
|
int maps;
|
2021-01-07 13:47:58 +00:00
|
|
|
|
2012-01-27 12:48:25 +00:00
|
|
|
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++)
|
|
|
|
if (d_lightstylevalue[surf->styles[maps]] != surf->cached_light[maps])
|
|
|
|
goto dynamic;
|
|
|
|
|
|
|
|
if ((surf->dlightframe == r_framecount) || surf->cached_dlight) {
|
|
|
|
dynamic:
|
[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 (r_dynamic)
|
[scene] Make entity_t just an entity id for ECS
This puts the hierarchy (transform) reference, animation, visibility,
renderer, active, and old_origin data in separate components. There are
a few bugs (crashes on grenade explosions in gl/glsl/vulkan, immediately
in sw, reasons known, missing brush models in vulkan).
While quake doesn't really need an ECS, the direction I want to take QF
does, and it does seem to have improved memory bandwidth a little
(uncertain). However, there's a lot more work to go (especially fixing
the above bugs), but this seems to be a good start.
2022-10-23 01:32:09 +00:00
|
|
|
glsl_R_BuildLightMap (bctx->transform, bctx->brush, surf);
|
2012-01-27 12:48:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-08 01:29:38 +00:00
|
|
|
static inline void
|
2021-07-22 06:39:28 +00:00
|
|
|
chain_surface (glslbspctx_t *bctx, msurface_t *surf)
|
2012-01-08 01:29:38 +00:00
|
|
|
{
|
2012-01-09 13:20:29 +00:00
|
|
|
instsurf_t *is;
|
|
|
|
|
2012-01-31 09:08:06 +00:00
|
|
|
if (surf->flags & SURF_DRAWSKY) {
|
2021-07-13 07:02:47 +00:00
|
|
|
is = CHAIN_SURF_F2B (surf, sky_chain);
|
2021-07-22 06:39:28 +00:00
|
|
|
} else if ((surf->flags & SURF_DRAWTURB)
|
|
|
|
|| (bctx->color && bctx->color[3] < 1.0)) {
|
2021-07-13 07:02:47 +00:00
|
|
|
is = CHAIN_SURF_B2F (surf, waterchain);
|
2012-01-08 01:29:38 +00:00
|
|
|
} else {
|
2021-01-19 04:05:39 +00:00
|
|
|
texture_t *tx;
|
|
|
|
glsltex_t *tex;
|
2012-01-08 01:29:38 +00:00
|
|
|
|
|
|
|
if (!surf->texinfo->texture->anim_total)
|
2021-01-19 04:05:39 +00:00
|
|
|
tx = surf->texinfo->texture;
|
2012-01-08 01:29:38 +00:00
|
|
|
else
|
2022-10-25 10:36:09 +00:00
|
|
|
tx = R_TextureAnimation (bctx->animation->frame, surf);
|
2021-01-19 04:05:39 +00:00
|
|
|
tex = tx->render;
|
2021-07-13 07:02:47 +00:00
|
|
|
is = CHAIN_SURF_F2B (surf, tex->tex_chain);
|
2012-01-08 01:29:38 +00:00
|
|
|
|
2021-07-22 06:39:28 +00:00
|
|
|
update_lightmap (bctx, surf);
|
2012-01-08 01:29:38 +00:00
|
|
|
}
|
2021-07-22 06:39:28 +00:00
|
|
|
is->transform = bctx->transform;
|
|
|
|
is->color = bctx->color;
|
2012-01-08 01:29:38 +00:00
|
|
|
}
|
|
|
|
|
2012-01-08 08:45:44 +00:00
|
|
|
static void
|
2021-02-01 10:31:11 +00:00
|
|
|
register_textures (mod_brush_t *brush)
|
2012-01-08 08:45:44 +00:00
|
|
|
{
|
|
|
|
texture_t *tex;
|
|
|
|
|
2021-08-01 12:54:05 +00:00
|
|
|
for (unsigned i = 0; i < brush->numtextures; i++) {
|
2021-02-01 10:31:11 +00:00
|
|
|
tex = brush->textures[i];
|
2012-01-08 08:45:44 +00:00
|
|
|
if (!tex)
|
|
|
|
continue;
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_R_AddTexture (tex);
|
2012-01-08 08:45:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-14 05:31:23 +00:00
|
|
|
static void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_R_ClearTextures (void)
|
2012-01-09 01:16:54 +00:00
|
|
|
{
|
|
|
|
r_num_texture_chains = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_R_RegisterTextures (model_t **models, int num_models)
|
2012-01-09 01:16:54 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
model_t *m;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush;
|
2012-01-09 01:16:54 +00:00
|
|
|
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_R_ClearTextures ();
|
2022-03-14 06:27:43 +00:00
|
|
|
glsl_R_InitSurfaceChains (&r_refdef.worldmodel->brush);
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_R_AddTexture (r_notexture_mip);
|
2022-03-14 06:27:43 +00:00
|
|
|
register_textures (&r_refdef.worldmodel->brush);
|
2012-01-09 01:16:54 +00:00
|
|
|
for (i = 0; i < num_models; i++) {
|
|
|
|
m = models[i];
|
|
|
|
if (!m)
|
|
|
|
continue;
|
|
|
|
// sub-models are done as part of the main model
|
2021-02-01 05:39:00 +00:00
|
|
|
if (*m->path == '*')
|
2012-01-09 01:16:54 +00:00
|
|
|
continue;
|
|
|
|
// world has already been done, not interested in non-brush models
|
2022-03-14 06:27:43 +00:00
|
|
|
if (m == r_refdef.worldmodel || m->type != mod_brush)
|
2012-01-09 01:16:54 +00:00
|
|
|
continue;
|
2021-02-01 10:31:11 +00:00
|
|
|
brush = &m->brush;
|
|
|
|
brush->numsubmodels = 1; // no support for submodels in non-world model
|
|
|
|
register_textures (brush);
|
2012-01-09 01:16:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-08 08:45:44 +00:00
|
|
|
static elechain_t *
|
2021-07-13 13:59:51 +00:00
|
|
|
add_elechain (glsltex_t *tex, int model_index)
|
2012-01-08 08:45:44 +00:00
|
|
|
{
|
|
|
|
elechain_t *ec;
|
|
|
|
|
2012-01-09 12:16:08 +00:00
|
|
|
ec = get_elechain ();
|
|
|
|
ec->elements = get_elements ();
|
2021-07-13 13:59:51 +00:00
|
|
|
ec->model_index = model_index;
|
2012-01-08 08:45:44 +00:00
|
|
|
ec->transform = 0;
|
2012-01-29 07:56:50 +00:00
|
|
|
ec->color = 0;
|
2012-01-08 08:45:44 +00:00
|
|
|
*tex->elechain_tail = ec;
|
|
|
|
tex->elechain_tail = &ec->next;
|
|
|
|
return ec;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-07-15 12:38:12 +00:00
|
|
|
build_surf_displist (model_t **models, msurface_t *surf, int base,
|
2012-01-08 08:45:44 +00:00
|
|
|
dstring_t *vert_list)
|
|
|
|
{
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush;
|
2021-07-15 12:38:12 +00:00
|
|
|
if (surf->model_index < 0) {
|
|
|
|
brush = &models[-surf->model_index - 1]->brush;
|
2012-01-08 08:45:44 +00:00
|
|
|
} else {
|
2022-03-14 06:27:43 +00:00
|
|
|
brush = &r_refdef.worldmodel->brush;
|
2012-01-08 08:45:44 +00:00
|
|
|
}
|
2022-05-11 10:22:17 +00:00
|
|
|
mvertex_t *vertices = brush->vertexes;
|
|
|
|
medge_t *edges = brush->edges;
|
|
|
|
int *surfedges = brush->surfedges;
|
|
|
|
|
|
|
|
// create triangle soup for the polygon (this was written targeting
|
|
|
|
// GLES 2, which didn't have primitive restart)
|
|
|
|
int numverts = surf->numedges;
|
|
|
|
int numtris = numverts - 2;
|
|
|
|
int numindices = numtris * 3;
|
|
|
|
glslpoly_t *poly = malloc (field_offset (glslpoly_t, indices[numindices]));
|
2012-01-08 08:45:44 +00:00
|
|
|
poly->count = numindices;
|
2022-05-11 10:22:17 +00:00
|
|
|
for (int i = 0, ind = 0; i < numtris; i++) {
|
|
|
|
// pretend we can use a triangle fan
|
|
|
|
poly->indices[ind++] = base;
|
|
|
|
poly->indices[ind++] = base + i + 1;
|
|
|
|
poly->indices[ind++] = base + i + 2;
|
2012-01-08 08:45:44 +00:00
|
|
|
}
|
2021-07-15 12:38:12 +00:00
|
|
|
surf->polys = (glpoly_t *) poly;
|
2012-01-08 08:45:44 +00:00
|
|
|
|
2022-05-11 10:22:17 +00:00
|
|
|
bspvert_t *verts = alloca (numverts * sizeof (bspvert_t));
|
2021-07-15 12:38:12 +00:00
|
|
|
mtexinfo_t *texinfo = surf->texinfo;
|
2022-05-11 10:22:17 +00:00
|
|
|
for (int i = 0; i < numverts; i++) {
|
|
|
|
vec_t *vec;
|
|
|
|
int index = surfedges[surf->firstedge + i];
|
|
|
|
if (index > 0) {
|
|
|
|
// forward edge
|
2012-01-08 08:45:44 +00:00
|
|
|
vec = vertices[edges[index].v[0]].position;
|
2022-05-11 10:22:17 +00:00
|
|
|
} else {
|
|
|
|
// reverse edge
|
2012-01-08 08:45:44 +00:00
|
|
|
vec = vertices[edges[-index].v[1]].position;
|
2022-05-11 10:22:17 +00:00
|
|
|
}
|
2012-01-08 08:45:44 +00:00
|
|
|
VectorCopy (vec, verts[i].vertex);
|
2022-05-11 10:22:17 +00:00
|
|
|
verts[i].vertex[3] = 1; // homogeneous coord
|
|
|
|
|
|
|
|
vec2f_t st = {
|
|
|
|
DotProduct (vec, texinfo->vecs[0]) + texinfo->vecs[0][3],
|
|
|
|
DotProduct (vec, texinfo->vecs[1]) + texinfo->vecs[1][3],
|
|
|
|
};
|
|
|
|
verts[i].tlst[0] = st[0] / texinfo->texture->width;
|
|
|
|
verts[i].tlst[1] = st[1] / texinfo->texture->height;
|
|
|
|
|
|
|
|
if (surf->lightpic) {
|
|
|
|
//lightmap texture coordinates
|
|
|
|
//every lit surface has its own lighmap at a 1/16 resolution
|
|
|
|
//(ie, 16 albedo pixels for every lightmap pixel)
|
|
|
|
const vrect_t *rect = surf->lightpic->rect;
|
|
|
|
vec2f_t lmorg = (vec2f_t) { VEC2_EXP (&rect->x) } * 16 + 8;
|
|
|
|
vec2f_t texorg = { VEC2_EXP (surf->texturemins) };
|
|
|
|
st = ((st - texorg + lmorg) / 16) * surf->lightpic->size;
|
|
|
|
verts[i].tlst[2] = st[0];
|
|
|
|
verts[i].tlst[3] = st[1];
|
|
|
|
} else {
|
|
|
|
// no lightmap for this surface (probably sky or water), so
|
|
|
|
// make the lightmap texture polygone degenerate
|
2012-01-08 08:45:44 +00:00
|
|
|
verts[i].tlst[2] = 0;
|
|
|
|
verts[i].tlst[3] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dstring_append (vert_list, (char *) verts, numverts * sizeof (bspvert_t));
|
|
|
|
}
|
|
|
|
|
2012-01-08 01:29:38 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_R_BuildDisplayLists (model_t **models, int num_models)
|
2012-01-08 01:29:38 +00:00
|
|
|
{
|
2012-01-08 08:45:44 +00:00
|
|
|
int vertex_index_base;
|
2012-01-08 01:29:38 +00:00
|
|
|
model_t *m;
|
2012-01-08 08:45:44 +00:00
|
|
|
dmodel_t *dm;
|
2012-01-08 01:29:38 +00:00
|
|
|
msurface_t *surf;
|
2012-01-08 08:45:44 +00:00
|
|
|
dstring_t *vertices;
|
2021-02-01 10:31:11 +00:00
|
|
|
mod_brush_t *brush;
|
2012-01-08 01:29:38 +00:00
|
|
|
|
2018-10-12 05:33:55 +00:00
|
|
|
QuatSet (0, 0, sqrt(0.5), sqrt(0.5), sky_fix); // proper skies
|
|
|
|
QuatSet (0, 0, 0, 1, sky_rotation[0]);
|
2012-09-12 10:06:07 +00:00
|
|
|
QuatCopy (sky_rotation[0], sky_rotation[1]);
|
2012-01-21 08:18:29 +00:00
|
|
|
QuatSet (0, 0, 0, 0, sky_velocity);
|
2012-01-12 12:23:39 +00:00
|
|
|
QuatExp (sky_velocity, sky_velocity);
|
2012-02-14 08:28:09 +00:00
|
|
|
sky_time = vr_data.realtime;
|
2012-01-12 12:23:39 +00:00
|
|
|
|
2012-01-08 01:29:38 +00:00
|
|
|
// now run through all surfaces, chaining them to their textures, thus
|
|
|
|
// effectively sorting the surfaces by texture (without worrying about
|
|
|
|
// surface order on the same texture chain).
|
2021-08-01 12:54:05 +00:00
|
|
|
for (int i = 0; i < num_models; i++) {
|
2012-01-08 01:29:38 +00:00
|
|
|
m = models[i];
|
|
|
|
if (!m)
|
|
|
|
continue;
|
|
|
|
// sub-models are done as part of the main model
|
2021-02-01 10:31:11 +00:00
|
|
|
if (*m->path == '*' || m->type != mod_brush)
|
2012-01-08 01:29:38 +00:00
|
|
|
continue;
|
2021-02-01 10:31:11 +00:00
|
|
|
brush = &m->brush;
|
2012-01-08 01:29:38 +00:00
|
|
|
// non-bsp models don't have surfaces.
|
2021-02-01 10:31:11 +00:00
|
|
|
dm = brush->submodels;
|
2021-08-01 12:54:05 +00:00
|
|
|
for (uint32_t j = 0; j < brush->numsurfaces; j++) {
|
2021-01-19 04:05:39 +00:00
|
|
|
glsltex_t *tex;
|
2012-01-08 08:45:44 +00:00
|
|
|
if (j == dm->firstface + dm->numfaces) {
|
|
|
|
dm++;
|
2021-08-02 05:02:41 +00:00
|
|
|
if (dm == brush->submodels + brush->numsubmodels) {
|
2012-01-08 08:45:44 +00:00
|
|
|
// limit the surfaces
|
|
|
|
// probably never hit
|
|
|
|
Sys_Printf ("R_BuildDisplayLists: too many surfaces\n");
|
2021-02-01 10:31:11 +00:00
|
|
|
brush->numsurfaces = j;
|
2012-01-08 08:45:44 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-02-01 10:31:11 +00:00
|
|
|
surf = brush->surfaces + j;
|
2021-07-13 13:59:51 +00:00
|
|
|
surf->model_index = dm - brush->submodels;
|
2022-03-14 06:27:43 +00:00
|
|
|
if (!surf->model_index && m != r_refdef.worldmodel)
|
2021-07-13 13:59:51 +00:00
|
|
|
surf->model_index = -1 - i; // instanced model
|
2021-01-19 04:05:39 +00:00
|
|
|
tex = surf->texinfo->texture->render;
|
2012-01-08 01:29:38 +00:00
|
|
|
CHAIN_SURF_F2B (surf, tex->tex_chain);
|
2012-01-08 08:45:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// All vertices from all brush models go into one giant vbo.
|
|
|
|
vertices = dstring_new ();
|
|
|
|
vertex_index_base = 0;
|
|
|
|
// All usable surfaces have been chained to the (base) texture they use.
|
|
|
|
// Run through the textures, using their chains to build display maps.
|
|
|
|
// For animated textures, if a surface is on one texture of the group, it
|
|
|
|
// will be on all.
|
2021-08-01 12:54:05 +00:00
|
|
|
for (int i = 0; i < r_num_texture_chains; i++) {
|
2021-01-19 04:05:39 +00:00
|
|
|
glsltex_t *tex;
|
2012-01-08 08:45:44 +00:00
|
|
|
instsurf_t *is;
|
|
|
|
elechain_t *ec = 0;
|
|
|
|
elements_t *el = 0;
|
|
|
|
|
|
|
|
tex = r_texture_chains[i];
|
|
|
|
|
|
|
|
for (is = tex->tex_chain; is; is = is->tex_chain) {
|
|
|
|
msurface_t *surf = is->surface;
|
|
|
|
if (!tex->elechain) {
|
2021-07-13 13:59:51 +00:00
|
|
|
ec = add_elechain (tex, surf->model_index);
|
2012-01-08 08:45:44 +00:00
|
|
|
el = ec->elements;
|
2013-01-22 04:27:39 +00:00
|
|
|
el->base = (byte *) (intptr_t) vertices->size;
|
2012-01-08 08:45:44 +00:00
|
|
|
vertex_index_base = 0;
|
|
|
|
}
|
2021-07-13 13:59:51 +00:00
|
|
|
if (surf->model_index != ec->model_index) { // next sub-model
|
|
|
|
ec = add_elechain (tex, surf->model_index);
|
2012-01-08 08:45:44 +00:00
|
|
|
el = ec->elements;
|
2013-01-22 04:27:39 +00:00
|
|
|
el->base = (byte *) (intptr_t) vertices->size;
|
2012-01-08 08:45:44 +00:00
|
|
|
vertex_index_base = 0;
|
|
|
|
}
|
|
|
|
if (vertex_index_base + surf->numedges > 65535) {
|
|
|
|
// elements index overflow
|
2012-01-09 12:16:08 +00:00
|
|
|
el->next = get_elements ();
|
2012-01-08 08:45:44 +00:00
|
|
|
el = el->next;
|
2013-01-22 04:27:39 +00:00
|
|
|
el->base = (byte *) (intptr_t) vertices->size;
|
2012-01-08 08:45:44 +00:00
|
|
|
vertex_index_base = 0;
|
|
|
|
}
|
|
|
|
// we don't use it now, but pre-initializing the list won't hurt
|
|
|
|
if (!el->list)
|
|
|
|
el->list = dstring_new ();
|
|
|
|
dstring_clear (el->list);
|
|
|
|
|
2012-01-09 13:20:29 +00:00
|
|
|
surf->base = el->base;
|
2012-01-08 08:45:44 +00:00
|
|
|
build_surf_displist (models, surf, vertex_index_base, vertices);
|
|
|
|
vertex_index_base += surf->numedges;
|
2012-01-08 01:29:38 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-08 08:45:44 +00:00
|
|
|
clear_texture_chains ();
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_glsl, "R_BuildDisplayLists: %ld verts total\n",
|
2013-01-22 04:27:39 +00:00
|
|
|
(long) (vertices->size / sizeof (bspvert_t)));
|
2012-01-08 11:39:36 +00:00
|
|
|
if (!bsp_vbo)
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglGenBuffers (1, &bsp_vbo);
|
|
|
|
qfeglBindBuffer (GL_ARRAY_BUFFER, bsp_vbo);
|
|
|
|
qfeglBufferData (GL_ARRAY_BUFFER, vertices->size, vertices->str,
|
2012-01-08 11:39:36 +00:00
|
|
|
GL_STATIC_DRAW);
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglBindBuffer (GL_ARRAY_BUFFER, 0);
|
2012-01-08 11:39:36 +00:00
|
|
|
dstring_delete (vertices);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
[scene] Make entity_t just an entity id for ECS
This puts the hierarchy (transform) reference, animation, visibility,
renderer, active, and old_origin data in separate components. There are
a few bugs (crashes on grenade explosions in gl/glsl/vulkan, immediately
in sw, reasons known, missing brush models in vulkan).
While quake doesn't really need an ECS, the direction I want to take QF
does, and it does seem to have improved memory bandwidth a little
(uncertain). However, there's a lot more work to go (especially fixing
the above bugs), but this seems to be a good start.
2022-10-23 01:32:09 +00:00
|
|
|
R_DrawBrushModel (entity_t e)
|
2012-01-08 11:39:36 +00:00
|
|
|
{
|
|
|
|
float dot, radius;
|
|
|
|
unsigned k;
|
2022-10-25 03:53:30 +00:00
|
|
|
renderer_t *renderer = Ent_GetComponent (e.id, scene_renderer, e.reg);
|
[scene] Make entity_t just an entity id for ECS
This puts the hierarchy (transform) reference, animation, visibility,
renderer, active, and old_origin data in separate components. There are
a few bugs (crashes on grenade explosions in gl/glsl/vulkan, immediately
in sw, reasons known, missing brush models in vulkan).
While quake doesn't really need an ECS, the direction I want to take QF
does, and it does seem to have improved memory bandwidth a little
(uncertain). However, there's a lot more work to go (especially fixing
the above bugs), but this seems to be a good start.
2022-10-23 01:32:09 +00:00
|
|
|
model_t *model = renderer->model;
|
2021-07-22 06:39:28 +00:00
|
|
|
mod_brush_t *brush = &model->brush;
|
2012-01-08 11:39:36 +00:00
|
|
|
plane_t *plane;
|
|
|
|
msurface_t *surf;
|
|
|
|
qboolean rotated;
|
2021-03-19 11:18:45 +00:00
|
|
|
vec3_t mins, maxs;
|
|
|
|
vec4f_t org;
|
2021-07-22 06:39:28 +00:00
|
|
|
glslbspctx_t bctx = {
|
|
|
|
brush,
|
2022-10-25 03:53:30 +00:00
|
|
|
Ent_GetComponent (e.id, scene_animation, e.reg),
|
[scene] Make entity_t just an entity id for ECS
This puts the hierarchy (transform) reference, animation, visibility,
renderer, active, and old_origin data in separate components. There are
a few bugs (crashes on grenade explosions in gl/glsl/vulkan, immediately
in sw, reasons known, missing brush models in vulkan).
While quake doesn't really need an ECS, the direction I want to take QF
does, and it does seem to have improved memory bandwidth a little
(uncertain). However, there's a lot more work to go (especially fixing
the above bugs), but this seems to be a good start.
2022-10-23 01:32:09 +00:00
|
|
|
renderer->full_transform,
|
|
|
|
renderer->colormod,
|
2021-07-22 06:39:28 +00:00
|
|
|
};
|
2012-01-08 11:39:36 +00:00
|
|
|
|
2021-03-09 14:52:40 +00:00
|
|
|
mat4f_t mat;
|
2022-10-25 03:53:30 +00:00
|
|
|
transform_t transform = Entity_Transform (e);
|
[scene] Make entity_t just an entity id for ECS
This puts the hierarchy (transform) reference, animation, visibility,
renderer, active, and old_origin data in separate components. There are
a few bugs (crashes on grenade explosions in gl/glsl/vulkan, immediately
in sw, reasons known, missing brush models in vulkan).
While quake doesn't really need an ECS, the direction I want to take QF
does, and it does seem to have improved memory bandwidth a little
(uncertain). However, there's a lot more work to go (especially fixing
the above bugs), but this seems to be a good start.
2022-10-23 01:32:09 +00:00
|
|
|
Transform_GetWorldMatrix (transform, mat);
|
|
|
|
memcpy (renderer->full_transform, mat, sizeof (mat));//FIXME
|
2021-03-09 14:52:40 +00:00
|
|
|
if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) {
|
2012-01-08 11:39:36 +00:00
|
|
|
rotated = true;
|
|
|
|
radius = model->radius;
|
2022-03-30 15:07:20 +00:00
|
|
|
if (R_CullSphere (r_refdef.frustum, (vec_t*)&mat[3], radius)) { // FIXME
|
2012-01-08 11:39:36 +00:00
|
|
|
return;
|
2021-03-19 11:18:45 +00:00
|
|
|
}
|
2012-01-08 11:39:36 +00:00
|
|
|
} else {
|
|
|
|
rotated = false;
|
2021-03-19 11:18:45 +00:00
|
|
|
VectorAdd (mat[3], model->mins, mins);
|
|
|
|
VectorAdd (mat[3], model->maxs, maxs);
|
2022-03-19 03:33:12 +00:00
|
|
|
if (R_CullBox (r_refdef.frustum, mins, maxs))
|
2012-01-08 11:39:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
[renderer] Clean up use of vup/vright/vpn
This moves the common camera setup code out of the individual drivers,
and completely removes vup/vright/vpn from the non-software renderers.
This has highlighted the craziness around AngleVectors with it putting
+X forward, -Y right and +Z up. The main issue with this is it requires
a 90 degree pre-rotation about the Z axis to get the camera pointing in
the right direction, and that's for the native sw renderer (vulkan needs
a 90 degree pre-rotation about X, and gl and glsl need to invert an
axis, too), though at least it's just a matrix swizzle and vector
negation. However, it does mean the camera matrices can't be used
directly.
Also rename vpn to vfwd (still abbreviated, but fwd is much clearer in
meaning (to me, at least) than pn (plane normal, I guess, but which
way?)).
2022-03-14 00:34:24 +00:00
|
|
|
org = r_refdef.frame.position - mat[3];
|
2012-01-08 11:39:36 +00:00
|
|
|
if (rotated) {
|
2021-03-19 11:18:45 +00:00
|
|
|
vec4f_t temp = org;
|
2012-01-08 11:39:36 +00:00
|
|
|
|
2021-03-09 14:52:40 +00:00
|
|
|
org[0] = dotf (temp, mat[0])[0];
|
|
|
|
org[1] = dotf (temp, mat[1])[0];
|
|
|
|
org[2] = dotf (temp, mat[2])[0];
|
2012-01-08 11:39:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// calculate dynamic lighting for bmodel if it's not an instanced model
|
[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 (brush->firstmodelsurface != 0 && r_dlight_lightmap) {
|
2012-01-08 11:39:36 +00:00
|
|
|
for (k = 0; k < r_maxdlights; k++) {
|
2012-02-14 08:28:09 +00:00
|
|
|
if ((r_dlights[k].die < vr_data.realtime)
|
|
|
|
|| (!r_dlights[k].radius))
|
2012-01-08 11:39:36 +00:00
|
|
|
continue;
|
|
|
|
|
2022-05-22 02:18:32 +00:00
|
|
|
vec4f_t lightorigin;
|
2021-03-19 11:18:45 +00:00
|
|
|
VectorSubtract (r_dlights[k].origin, mat[3], lightorigin);
|
2022-05-22 02:18:32 +00:00
|
|
|
lightorigin[3] = 1;
|
2021-02-01 10:31:11 +00:00
|
|
|
R_RecursiveMarkLights (brush, lightorigin, &r_dlights[k], k,
|
2022-05-22 02:18:32 +00:00
|
|
|
brush->hulls[0].firstclipnode);
|
2012-01-08 11:39:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-01 10:31:11 +00:00
|
|
|
surf = &brush->surfaces[brush->firstmodelsurface];
|
2012-01-08 11:39:36 +00:00
|
|
|
|
2021-08-01 12:54:05 +00:00
|
|
|
for (unsigned i = 0; i < brush->nummodelsurfaces; i++, surf++) {
|
2012-01-09 12:16:08 +00:00
|
|
|
// find the node side on which we are
|
2012-01-08 11:39:36 +00:00
|
|
|
plane = surf->plane;
|
|
|
|
|
|
|
|
dot = PlaneDiff (org, plane);
|
|
|
|
|
|
|
|
// enqueue the polygon
|
|
|
|
if (((surf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON))
|
|
|
|
|| (!(surf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) {
|
2021-07-22 06:39:28 +00:00
|
|
|
chain_surface (&bctx, surf);
|
2012-01-08 11:39:36 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-08 01:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
visit_leaf (mleaf_t *leaf)
|
|
|
|
{
|
|
|
|
// deal with model fragments in this leaf
|
|
|
|
if (leaf->efrags)
|
|
|
|
R_StoreEfrags (leaf->efrags);
|
|
|
|
}
|
|
|
|
|
2022-05-13 13:00:03 +00:00
|
|
|
// 1 = back side, 0 = front side
|
2012-01-08 01:29:38 +00:00
|
|
|
static inline int
|
|
|
|
get_side (mnode_t *node)
|
|
|
|
{
|
2012-01-09 12:16:08 +00:00
|
|
|
// find the node side on which we are
|
[renderer] Clean up use of vup/vright/vpn
This moves the common camera setup code out of the individual drivers,
and completely removes vup/vright/vpn from the non-software renderers.
This has highlighted the craziness around AngleVectors with it putting
+X forward, -Y right and +Z up. The main issue with this is it requires
a 90 degree pre-rotation about the Z axis to get the camera pointing in
the right direction, and that's for the native sw renderer (vulkan needs
a 90 degree pre-rotation about X, and gl and glsl need to invert an
axis, too), though at least it's just a matrix swizzle and vector
negation. However, it does mean the camera matrices can't be used
directly.
Also rename vpn to vfwd (still abbreviated, but fwd is much clearer in
meaning (to me, at least) than pn (plane normal, I guess, but which
way?)).
2022-03-14 00:34:24 +00:00
|
|
|
vec4f_t org = r_refdef.frame.position;
|
2012-01-08 01:29:38 +00:00
|
|
|
|
2022-05-22 02:18:32 +00:00
|
|
|
return dotf (org, node->plane)[0] < 0;
|
2012-01-08 01:29:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
2021-07-22 06:39:28 +00:00
|
|
|
visit_node (glslbspctx_t *bctx, mnode_t *node, int side)
|
2012-01-08 01:29:38 +00:00
|
|
|
{
|
|
|
|
int c;
|
|
|
|
msurface_t *surf;
|
|
|
|
|
|
|
|
// sneaky hack for side = side ? SURF_PLANEBACK : 0;
|
2022-05-13 13:00:03 +00:00
|
|
|
// seems to be microscopically faster even on modern hardware
|
|
|
|
side = (-side) & SURF_PLANEBACK;
|
|
|
|
// chain any visible surfaces on the node that face the camera.
|
|
|
|
// not all nodes have any surfaces to draw (purely a split plane)
|
2012-01-08 01:29:38 +00:00
|
|
|
if ((c = node->numsurfaces)) {
|
2022-05-22 07:31:24 +00:00
|
|
|
int surf_id = node->firstsurface;
|
|
|
|
surf = bctx->brush->surfaces + surf_id;
|
|
|
|
for (; c; c--, surf++, surf_id++) {
|
|
|
|
if (r_face_visframes[surf_id] != r_visframecount)
|
2012-01-08 01:29:38 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// side is either 0 or SURF_PLANEBACK
|
2022-05-13 13:00:03 +00:00
|
|
|
// if side and the surface facing differ, then the camera is
|
|
|
|
// on backside of the surface
|
2012-01-08 01:29:38 +00:00
|
|
|
if (side ^ (surf->flags & SURF_PLANEBACK))
|
|
|
|
continue; // wrong side
|
|
|
|
|
2021-07-22 06:39:28 +00:00
|
|
|
chain_surface (bctx, surf);
|
2012-01-08 01:29:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int
|
2022-05-22 02:18:32 +00:00
|
|
|
test_node (glslbspctx_t *bctx, int node_id)
|
2012-01-08 01:29:38 +00:00
|
|
|
{
|
2022-05-22 02:18:32 +00:00
|
|
|
if (node_id < 0)
|
2012-01-08 01:29:38 +00:00
|
|
|
return 0;
|
2022-05-22 02:18:32 +00:00
|
|
|
if (r_node_visframes[node_id] != r_visframecount)
|
2012-01-08 01:29:38 +00:00
|
|
|
return 0;
|
2022-05-22 02:18:32 +00:00
|
|
|
mnode_t *node = bctx->brush->nodes + node_id;
|
2022-03-19 03:33:12 +00:00
|
|
|
if (R_CullBox (r_refdef.frustum, node->minmaxs, node->minmaxs + 3))
|
2012-01-08 01:29:38 +00:00
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-07-22 06:39:28 +00:00
|
|
|
R_VisitWorldNodes (glslbspctx_t *bctx)
|
2012-01-08 01:29:38 +00:00
|
|
|
{
|
2012-11-28 12:29:03 +00:00
|
|
|
typedef struct {
|
2022-05-22 02:18:32 +00:00
|
|
|
int node_id;
|
2012-01-08 01:29:38 +00:00
|
|
|
int side;
|
2012-11-28 12:29:03 +00:00
|
|
|
} rstack_t;
|
2021-07-22 06:39:28 +00:00
|
|
|
mod_brush_t *brush = bctx->brush;
|
2012-11-28 12:29:03 +00:00
|
|
|
rstack_t *node_ptr;
|
|
|
|
rstack_t *node_stack;
|
2022-05-22 02:18:32 +00:00
|
|
|
int node_id;
|
|
|
|
int front;
|
2012-01-08 01:29:38 +00:00
|
|
|
int side;
|
|
|
|
|
2022-05-22 02:18:32 +00:00
|
|
|
node_id = 0;
|
2012-11-28 12:29:03 +00:00
|
|
|
// +2 for paranoia
|
2021-02-01 10:31:11 +00:00
|
|
|
node_stack = alloca ((brush->depth + 2) * sizeof (rstack_t));
|
2012-01-08 01:29:38 +00:00
|
|
|
node_ptr = node_stack;
|
|
|
|
|
|
|
|
while (1) {
|
2022-05-22 02:18:32 +00:00
|
|
|
while (test_node (bctx, node_id)) {
|
|
|
|
mnode_t *node = bctx->brush->nodes + node_id;
|
2012-01-08 01:29:38 +00:00
|
|
|
side = get_side (node);
|
|
|
|
front = node->children[side];
|
2022-05-22 02:18:32 +00:00
|
|
|
if (test_node (bctx, front)) {
|
|
|
|
node_ptr->node_id = node_id;
|
2012-01-08 01:29:38 +00:00
|
|
|
node_ptr->side = side;
|
|
|
|
node_ptr++;
|
2022-05-22 02:18:32 +00:00
|
|
|
node_id = front;
|
2012-01-08 01:29:38 +00:00
|
|
|
continue;
|
|
|
|
}
|
2022-05-22 02:18:32 +00:00
|
|
|
if (front < 0) {
|
|
|
|
mleaf_t *leaf = bctx->brush->leafs + ~front;
|
|
|
|
if (leaf->contents != CONTENTS_SOLID) {
|
|
|
|
visit_leaf (leaf);
|
|
|
|
}
|
|
|
|
}
|
2021-07-22 06:39:28 +00:00
|
|
|
visit_node (bctx, node, side);
|
2022-05-22 02:18:32 +00:00
|
|
|
node_id = node->children[side ^ 1];
|
|
|
|
}
|
|
|
|
if (node_id < 0) {
|
|
|
|
mleaf_t *leaf = bctx->brush->leafs + ~node_id;
|
|
|
|
if (leaf->contents != CONTENTS_SOLID) {
|
|
|
|
visit_leaf (leaf);
|
|
|
|
}
|
2012-01-08 01:29:38 +00:00
|
|
|
}
|
|
|
|
if (node_ptr != node_stack) {
|
|
|
|
node_ptr--;
|
2022-05-22 02:18:32 +00:00
|
|
|
node_id = node_ptr->node_id;
|
2012-01-08 01:29:38 +00:00
|
|
|
side = node_ptr->side;
|
2022-05-22 02:18:32 +00:00
|
|
|
mnode_t *node = bctx->brush->nodes + node_id;
|
2021-07-22 06:39:28 +00:00
|
|
|
visit_node (bctx, node, side);
|
2022-05-22 02:18:32 +00:00
|
|
|
node_id = node->children[side ^ 1];
|
2012-01-08 01:29:38 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-08 11:39:36 +00:00
|
|
|
static void
|
2012-01-29 07:56:50 +00:00
|
|
|
draw_elechain (elechain_t *ec, int matloc, int vertloc, int tlstloc,
|
|
|
|
int colloc)
|
2012-01-08 11:39:36 +00:00
|
|
|
{
|
[scene] Make entity_t just an entity id for ECS
This puts the hierarchy (transform) reference, animation, visibility,
renderer, active, and old_origin data in separate components. There are
a few bugs (crashes on grenade explosions in gl/glsl/vulkan, immediately
in sw, reasons known, missing brush models in vulkan).
While quake doesn't really need an ECS, the direction I want to take QF
does, and it does seem to have improved memory bandwidth a little
(uncertain). However, there's a lot more work to go (especially fixing
the above bugs), but this seems to be a good start.
2022-10-23 01:32:09 +00:00
|
|
|
mat4f_t mat;
|
2012-01-08 11:39:36 +00:00
|
|
|
elements_t *el;
|
2012-01-08 13:09:51 +00:00
|
|
|
int count;
|
2012-01-29 07:56:50 +00:00
|
|
|
float *color;
|
|
|
|
|
2012-06-29 13:13:20 +00:00
|
|
|
if (colloc >= 0) {
|
|
|
|
color = ec->color;
|
2012-01-29 07:56:50 +00:00
|
|
|
if (!color)
|
|
|
|
color = default_color;
|
2012-06-29 13:13:20 +00:00
|
|
|
if (!QuatCompare (color, last_color)) {
|
|
|
|
QuatCopy (color, last_color);
|
|
|
|
qfeglVertexAttrib4fv (quake_bsp.color.location, color);
|
|
|
|
}
|
2012-01-29 07:56:50 +00:00
|
|
|
}
|
2012-07-10 23:12:57 +00:00
|
|
|
if (ec->transform) {
|
[scene] Make entity_t just an entity id for ECS
This puts the hierarchy (transform) reference, animation, visibility,
renderer, active, and old_origin data in separate components. There are
a few bugs (crashes on grenade explosions in gl/glsl/vulkan, immediately
in sw, reasons known, missing brush models in vulkan).
While quake doesn't really need an ECS, the direction I want to take QF
does, and it does seem to have improved memory bandwidth a little
(uncertain). However, there's a lot more work to go (especially fixing
the above bugs), but this seems to be a good start.
2022-10-23 01:32:09 +00:00
|
|
|
mmulf (mat, bsp_vp, ec->transform);
|
|
|
|
qfeglUniformMatrix4fv (matloc, 1, false, (vec_t*)&mat[0]);//FIXME
|
2012-07-10 23:12:57 +00:00
|
|
|
} else {
|
2022-03-30 15:07:20 +00:00
|
|
|
qfeglUniformMatrix4fv (matloc, 1, false, (vec_t*)&bsp_vp[0]);//FIXME
|
2012-01-08 11:39:36 +00:00
|
|
|
}
|
|
|
|
for (el = ec->elements; el; el = el->next) {
|
2012-01-08 13:09:51 +00:00
|
|
|
if (!el->list->size)
|
|
|
|
continue;
|
|
|
|
count = el->list->size / sizeof (GLushort);
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglVertexAttribPointer (vertloc, 4, GL_FLOAT,
|
2012-01-08 11:39:36 +00:00
|
|
|
0, sizeof (bspvert_t),
|
|
|
|
el->base + field_offset (bspvert_t, vertex));
|
2012-01-11 12:26:12 +00:00
|
|
|
if (tlstloc >= 0)
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglVertexAttribPointer (tlstloc, 4, GL_FLOAT,
|
2012-01-11 12:26:12 +00:00
|
|
|
0, sizeof (bspvert_t),
|
|
|
|
el->base + field_offset (bspvert_t,tlst));
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglDrawElements (GL_TRIANGLES, count,
|
2012-01-08 13:09:51 +00:00
|
|
|
GL_UNSIGNED_SHORT, el->list->str);
|
|
|
|
dstring_clear (el->list);
|
2012-01-08 11:39:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bsp_begin (void)
|
|
|
|
{
|
2012-01-29 01:27:28 +00:00
|
|
|
quat_t fog;
|
|
|
|
|
2012-01-30 11:31:37 +00:00
|
|
|
default_color[3] = 1;
|
2012-06-29 13:13:20 +00:00
|
|
|
QuatCopy (default_color, last_color);
|
|
|
|
qfeglVertexAttrib4fv (quake_bsp.color.location, default_color);
|
2012-01-29 07:56:50 +00:00
|
|
|
|
2021-03-09 14:52:40 +00:00
|
|
|
mmulf (bsp_vp, glsl_projection, glsl_view);
|
2012-01-08 11:39:36 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUseProgram (quake_bsp.program);
|
|
|
|
qfeglEnableVertexAttribArray (quake_bsp.vertex.location);
|
|
|
|
qfeglEnableVertexAttribArray (quake_bsp.tlst.location);
|
|
|
|
qfeglDisableVertexAttribArray (quake_bsp.color.location);
|
2012-01-28 12:20:34 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglVertexAttrib4fv (quake_bsp.color.location, default_color);
|
2012-01-08 11:39:36 +00:00
|
|
|
|
2022-03-07 17:10:47 +00:00
|
|
|
Fog_GetColor (fog);
|
|
|
|
fog[3] = Fog_GetDensity () / 64.0;
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUniform4fv (quake_bsp.fog.location, 1, fog);
|
2012-01-29 01:27:28 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUniform1i (quake_bsp.colormap.location, 2);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 2);
|
|
|
|
qfeglEnable (GL_TEXTURE_2D);
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, glsl_colormap);
|
2012-01-08 11:39:36 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUniform1i (quake_bsp.lightmap.location, 1);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 1);
|
|
|
|
qfeglEnable (GL_TEXTURE_2D);
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, glsl_R_LightmapTexture ());
|
2012-01-08 11:39:36 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUniform1i (quake_bsp.texture.location, 0);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 0);
|
|
|
|
qfeglEnable (GL_TEXTURE_2D);
|
2012-01-08 11:39:36 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglBindBuffer (GL_ARRAY_BUFFER, bsp_vbo);
|
2012-01-08 11:39:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
bsp_end (void)
|
|
|
|
{
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglDisableVertexAttribArray (quake_bsp.vertex.location);
|
|
|
|
qfeglDisableVertexAttribArray (quake_bsp.tlst.location);
|
2012-01-08 11:39:36 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 0);
|
|
|
|
qfeglDisable (GL_TEXTURE_2D);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 1);
|
|
|
|
qfeglDisable (GL_TEXTURE_2D);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 2);
|
|
|
|
qfeglDisable (GL_TEXTURE_2D);
|
2012-01-10 11:50:47 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglBindBuffer (GL_ARRAY_BUFFER, 0);
|
2012-01-10 11:50:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
turb_begin (void)
|
|
|
|
{
|
2012-01-29 01:27:28 +00:00
|
|
|
quat_t fog;
|
2012-01-28 12:20:34 +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
|
|
|
default_color[3] = bound (0, r_wateralpha, 1);
|
2012-06-29 13:13:20 +00:00
|
|
|
QuatCopy (default_color, last_color);
|
|
|
|
qfeglVertexAttrib4fv (quake_bsp.color.location, default_color);
|
2012-01-29 07:56:50 +00:00
|
|
|
|
2021-03-09 14:52:40 +00:00
|
|
|
mmulf (bsp_vp, glsl_projection, glsl_view);
|
2012-01-10 11:50:47 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUseProgram (quake_turb.program);
|
|
|
|
qfeglEnableVertexAttribArray (quake_turb.vertex.location);
|
|
|
|
qfeglEnableVertexAttribArray (quake_turb.tlst.location);
|
|
|
|
qfeglDisableVertexAttribArray (quake_turb.color.location);
|
2012-01-28 12:20:34 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglVertexAttrib4fv (quake_turb.color.location, default_color);
|
2012-01-10 11:50:47 +00:00
|
|
|
|
2022-03-07 17:10:47 +00:00
|
|
|
Fog_GetColor (fog);
|
|
|
|
fog[3] = Fog_GetDensity () / 64.0;
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUniform4fv (quake_turb.fog.location, 1, fog);
|
2012-01-29 01:27:28 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUniform1i (quake_turb.palette.location, 1);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 1);
|
|
|
|
qfeglEnable (GL_TEXTURE_2D);
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, glsl_palette);
|
2012-01-10 11:50:47 +00:00
|
|
|
|
2013-06-07 08:12:44 +00:00
|
|
|
qfeglUniform1f (quake_turb.time.location, vr_data.realtime);
|
2012-01-10 11:50:47 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUniform1i (quake_turb.texture.location, 0);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 0);
|
|
|
|
qfeglEnable (GL_TEXTURE_2D);
|
2012-01-10 11:50:47 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglBindBuffer (GL_ARRAY_BUFFER, bsp_vbo);
|
2012-01-10 11:50:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
turb_end (void)
|
|
|
|
{
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglDisableVertexAttribArray (quake_turb.vertex.location);
|
|
|
|
qfeglDisableVertexAttribArray (quake_turb.tlst.location);
|
2012-01-10 11:50:47 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 0);
|
|
|
|
qfeglDisable (GL_TEXTURE_2D);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 1);
|
|
|
|
qfeglDisable (GL_TEXTURE_2D);
|
2012-01-10 11:50:47 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglBindBuffer (GL_ARRAY_BUFFER, 0);
|
2012-01-10 11:50:47 +00:00
|
|
|
}
|
|
|
|
|
2012-01-12 12:23:39 +00:00
|
|
|
static void
|
|
|
|
spin (mat4_t mat)
|
|
|
|
{
|
|
|
|
quat_t q;
|
|
|
|
mat4_t m;
|
|
|
|
float blend;
|
|
|
|
|
2012-02-14 08:28:09 +00:00
|
|
|
while (vr_data.realtime - sky_time > 1) {
|
2012-01-12 12:23:39 +00:00
|
|
|
QuatCopy (sky_rotation[1], sky_rotation[0]);
|
|
|
|
QuatMult (sky_velocity, sky_rotation[0], sky_rotation[1]);
|
|
|
|
sky_time += 1;
|
|
|
|
}
|
2012-02-14 08:28:09 +00:00
|
|
|
blend = bound (0, (vr_data.realtime - sky_time), 1);
|
2012-01-12 12:23:39 +00:00
|
|
|
|
|
|
|
QuatBlend (sky_rotation[0], sky_rotation[1], blend, q);
|
2012-09-12 10:06:07 +00:00
|
|
|
QuatMult (sky_fix, q, q);
|
2012-01-12 12:23:39 +00:00
|
|
|
Mat4Identity (mat);
|
[renderer] Clean up use of vup/vright/vpn
This moves the common camera setup code out of the individual drivers,
and completely removes vup/vright/vpn from the non-software renderers.
This has highlighted the craziness around AngleVectors with it putting
+X forward, -Y right and +Z up. The main issue with this is it requires
a 90 degree pre-rotation about the Z axis to get the camera pointing in
the right direction, and that's for the native sw renderer (vulkan needs
a 90 degree pre-rotation about X, and gl and glsl need to invert an
axis, too), though at least it's just a matrix swizzle and vector
negation. However, it does mean the camera matrices can't be used
directly.
Also rename vpn to vfwd (still abbreviated, but fwd is much clearer in
meaning (to me, at least) than pn (plane normal, I guess, but which
way?)).
2022-03-14 00:34:24 +00:00
|
|
|
VectorNegate (r_refdef.frame.position, mat + 12);
|
2012-01-12 12:23:39 +00:00
|
|
|
QuatToMatrix (q, m, 1, 1);
|
|
|
|
Mat4Mult (m, mat, mat);
|
|
|
|
}
|
|
|
|
|
2012-01-11 12:26:12 +00:00
|
|
|
static void
|
2012-01-12 08:34:29 +00:00
|
|
|
sky_begin (void)
|
2012-01-11 12:26:12 +00:00
|
|
|
{
|
2012-01-12 12:23:39 +00:00
|
|
|
mat4_t mat;
|
2012-01-29 01:27:28 +00:00
|
|
|
quat_t fog;
|
2012-01-12 12:23:39 +00:00
|
|
|
|
2012-01-30 12:02:13 +00:00
|
|
|
default_color[3] = 1;
|
2012-06-29 13:13:20 +00:00
|
|
|
QuatCopy (default_color, last_color);
|
|
|
|
qfeglVertexAttrib4fv (quake_bsp.color.location, default_color);
|
2012-01-29 07:56:50 +00:00
|
|
|
|
2021-03-09 14:52:40 +00:00
|
|
|
mmulf (bsp_vp, glsl_projection, glsl_view);
|
2012-01-11 12:26:12 +00:00
|
|
|
|
2012-01-12 08:34:29 +00:00
|
|
|
if (skybox_loaded) {
|
|
|
|
sky_params.mvp_matrix = &quake_skybox.mvp_matrix;
|
|
|
|
sky_params.vertex = &quake_skybox.vertex;
|
2012-01-12 12:23:39 +00:00
|
|
|
sky_params.sky_matrix = &quake_skybox.sky_matrix;
|
2012-01-29 01:27:28 +00:00
|
|
|
sky_params.fog = &quake_skybox.fog;
|
2012-01-11 12:26:12 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUseProgram (quake_skybox.program);
|
|
|
|
qfeglEnableVertexAttribArray (quake_skybox.vertex.location);
|
2012-01-11 12:26:12 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUniform1i (quake_skybox.sky.location, 0);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 0);
|
|
|
|
qfeglEnable (GL_TEXTURE_CUBE_MAP);
|
|
|
|
qfeglBindTexture (GL_TEXTURE_CUBE_MAP, skybox_tex);
|
2012-01-12 08:34:29 +00:00
|
|
|
} else {
|
|
|
|
sky_params.mvp_matrix = &quake_skyid.mvp_matrix;
|
2012-01-12 12:23:39 +00:00
|
|
|
sky_params.sky_matrix = &quake_skyid.sky_matrix;
|
2012-01-12 08:34:29 +00:00
|
|
|
sky_params.vertex = &quake_skyid.vertex;
|
2012-01-29 01:27:28 +00:00
|
|
|
sky_params.fog = &quake_skyid.fog;
|
2012-01-11 12:26:12 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUseProgram (quake_skyid.program);
|
|
|
|
qfeglEnableVertexAttribArray (quake_skyid.vertex.location);
|
2012-01-11 12:26:12 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUniform1i (quake_skyid.palette.location, 2);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 2);
|
|
|
|
qfeglEnable (GL_TEXTURE_2D);
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, glsl_palette);
|
2012-01-12 02:05:34 +00:00
|
|
|
|
2013-06-07 08:12:44 +00:00
|
|
|
qfeglUniform1f (quake_skyid.time.location, vr_data.realtime);
|
2012-01-12 02:05:34 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUniform1i (quake_skyid.trans.location, 0);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 0);
|
|
|
|
qfeglEnable (GL_TEXTURE_2D);
|
2012-01-12 02:05:34 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUniform1i (quake_skyid.solid.location, 1);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 1);
|
|
|
|
qfeglEnable (GL_TEXTURE_2D);
|
2012-01-12 08:34:29 +00:00
|
|
|
}
|
2012-01-12 02:05:34 +00:00
|
|
|
|
2022-03-07 17:10:47 +00:00
|
|
|
Fog_GetColor (fog);
|
|
|
|
fog[3] = Fog_GetDensity () / 64.0;
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUniform4fv (sky_params.fog->location, 1, fog);
|
2012-01-29 01:27:28 +00:00
|
|
|
|
2012-01-12 12:23:39 +00:00
|
|
|
spin (mat);
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglUniformMatrix4fv (sky_params.sky_matrix->location, 1, false, mat);
|
2012-01-12 12:23:39 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglBindBuffer (GL_ARRAY_BUFFER, bsp_vbo);
|
2012-01-12 02:05:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-01-12 08:34:29 +00:00
|
|
|
sky_end (void)
|
2012-01-12 02:05:34 +00:00
|
|
|
{
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglDisableVertexAttribArray (sky_params.vertex->location);
|
2012-01-12 02:05:34 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 0);
|
|
|
|
qfeglDisable (GL_TEXTURE_2D);
|
|
|
|
qfeglDisable (GL_TEXTURE_CUBE_MAP);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 1);
|
|
|
|
qfeglDisable (GL_TEXTURE_2D);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 2);
|
|
|
|
qfeglDisable (GL_TEXTURE_2D);
|
2012-01-12 02:05:34 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglBindBuffer (GL_ARRAY_BUFFER, 0);
|
2012-01-12 02:05:34 +00:00
|
|
|
}
|
|
|
|
|
2012-01-10 11:50:47 +00:00
|
|
|
static inline void
|
2021-01-19 04:05:39 +00:00
|
|
|
add_surf_elements (glsltex_t *tex, instsurf_t *is,
|
2012-01-10 11:50:47 +00:00
|
|
|
elechain_t **ec, elements_t **el)
|
|
|
|
{
|
|
|
|
msurface_t *surf = is->surface;
|
|
|
|
glslpoly_t *poly = (glslpoly_t *) surf->polys;
|
|
|
|
|
|
|
|
if (!tex->elechain) {
|
2021-07-13 13:59:51 +00:00
|
|
|
(*ec) = add_elechain (tex, surf->model_index);
|
2012-01-10 11:50:47 +00:00
|
|
|
(*ec)->transform = is->transform;
|
2012-01-29 07:56:50 +00:00
|
|
|
(*ec)->color = is->color;
|
2012-01-10 11:50:47 +00:00
|
|
|
(*el) = (*ec)->elements;
|
|
|
|
(*el)->base = surf->base;
|
|
|
|
if (!(*el)->list)
|
|
|
|
(*el)->list = dstring_new ();
|
|
|
|
dstring_clear ((*el)->list);
|
|
|
|
}
|
2012-01-29 07:56:50 +00:00
|
|
|
if (is->transform != (*ec)->transform || is->color != (*ec)->color) {
|
2021-07-13 13:59:51 +00:00
|
|
|
(*ec) = add_elechain (tex, surf->model_index);
|
2012-01-10 11:50:47 +00:00
|
|
|
(*ec)->transform = is->transform;
|
2012-01-29 07:56:50 +00:00
|
|
|
(*ec)->color = is->color;
|
2012-01-10 11:50:47 +00:00
|
|
|
(*el) = (*ec)->elements;
|
|
|
|
(*el)->base = surf->base;
|
|
|
|
if (!(*el)->list)
|
|
|
|
(*el)->list = dstring_new ();
|
|
|
|
dstring_clear ((*el)->list);
|
|
|
|
}
|
|
|
|
if (surf->base != (*el)->base) {
|
|
|
|
(*el)->next = get_elements ();
|
|
|
|
(*el) = (*el)->next;
|
|
|
|
(*el)->base = surf->base;
|
|
|
|
if (!(*el)->list)
|
|
|
|
(*el)->list = dstring_new ();
|
|
|
|
dstring_clear ((*el)->list);
|
|
|
|
}
|
|
|
|
dstring_append ((*el)->list, (char *) poly->indices,
|
|
|
|
poly->count * sizeof (poly->indices[0]));
|
2012-01-08 11:39:36 +00:00
|
|
|
}
|
|
|
|
|
2012-01-09 12:16:08 +00:00
|
|
|
static void
|
2021-01-19 04:05:39 +00:00
|
|
|
build_tex_elechain (glsltex_t *tex)
|
2012-01-09 12:16:08 +00:00
|
|
|
{
|
|
|
|
instsurf_t *is;
|
|
|
|
elechain_t *ec = 0;
|
|
|
|
elements_t *el = 0;
|
|
|
|
|
|
|
|
for (is = tex->tex_chain; is; is = is->tex_chain) {
|
2012-01-10 11:50:47 +00:00
|
|
|
add_surf_elements (tex, is, &ec, &el);
|
2012-01-09 12:16:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-08 01:29:38 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_R_DrawWorld (void)
|
2012-01-08 01:29:38 +00:00
|
|
|
{
|
[scene] Make entity_t just an entity id for ECS
This puts the hierarchy (transform) reference, animation, visibility,
renderer, active, and old_origin data in separate components. There are
a few bugs (crashes on grenade explosions in gl/glsl/vulkan, immediately
in sw, reasons known, missing brush models in vulkan).
While quake doesn't really need an ECS, the direction I want to take QF
does, and it does seem to have improved memory bandwidth a little
(uncertain). However, there's a lot more work to go (especially fixing
the above bugs), but this seems to be a good start.
2022-10-23 01:32:09 +00:00
|
|
|
animation_t animation = {};
|
2021-07-22 06:39:28 +00:00
|
|
|
glslbspctx_t bctx = { };
|
2012-01-08 11:39:36 +00:00
|
|
|
int i;
|
2012-01-08 01:29:38 +00:00
|
|
|
|
2012-01-10 11:50:47 +00:00
|
|
|
clear_texture_chains (); // do this first for water and skys
|
|
|
|
|
[scene] Make entity_t just an entity id for ECS
This puts the hierarchy (transform) reference, animation, visibility,
renderer, active, and old_origin data in separate components. There are
a few bugs (crashes on grenade explosions in gl/glsl/vulkan, immediately
in sw, reasons known, missing brush models in vulkan).
While quake doesn't really need an ECS, the direction I want to take QF
does, and it does seem to have improved memory bandwidth a little
(uncertain). However, there's a lot more work to go (especially fixing
the above bugs), but this seems to be a good start.
2022-10-23 01:32:09 +00:00
|
|
|
bctx.brush = &r_refdef.worldmodel->brush;
|
|
|
|
bctx.animation = &animation;
|
2012-01-08 01:29:38 +00:00
|
|
|
|
2021-07-22 06:39:28 +00:00
|
|
|
R_VisitWorldNodes (&bctx);
|
[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 (r_drawentities) {
|
2022-03-04 16:48:10 +00:00
|
|
|
for (size_t i = 0; i < r_ent_queue->ent_queues[mod_brush].size; i++) {
|
[scene] Make entity_t just an entity id for ECS
This puts the hierarchy (transform) reference, animation, visibility,
renderer, active, and old_origin data in separate components. There are
a few bugs (crashes on grenade explosions in gl/glsl/vulkan, immediately
in sw, reasons known, missing brush models in vulkan).
While quake doesn't really need an ECS, the direction I want to take QF
does, and it does seem to have improved memory bandwidth a little
(uncertain). However, there's a lot more work to go (especially fixing
the above bugs), but this seems to be a good start.
2022-10-23 01:32:09 +00:00
|
|
|
entity_t ent = r_ent_queue->ent_queues[mod_brush].a[i];
|
2012-01-08 11:39:36 +00:00
|
|
|
R_DrawBrushModel (ent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-02 11:01:28 +00:00
|
|
|
glsl_R_FlushLightmaps ();
|
2012-01-08 11:39:36 +00:00
|
|
|
bsp_begin ();
|
2012-06-29 13:13:20 +00:00
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 0);
|
2012-01-08 11:39:36 +00:00
|
|
|
for (i = 0; i < r_num_texture_chains; i++) {
|
2021-01-19 04:05:39 +00:00
|
|
|
glsltex_t *tex;
|
2012-01-08 11:39:36 +00:00
|
|
|
elechain_t *ec = 0;
|
|
|
|
|
|
|
|
tex = r_texture_chains[i];
|
|
|
|
|
2012-01-09 12:16:08 +00:00
|
|
|
build_tex_elechain (tex);
|
|
|
|
|
2012-06-29 13:13:20 +00:00
|
|
|
if (tex->elechain)
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum);
|
|
|
|
|
2012-01-08 11:39:36 +00:00
|
|
|
for (ec = tex->elechain; ec; ec = ec->next) {
|
2012-01-11 12:26:12 +00:00
|
|
|
draw_elechain (ec, quake_bsp.mvp_matrix.location,
|
|
|
|
quake_bsp.vertex.location,
|
2012-01-29 07:56:50 +00:00
|
|
|
quake_bsp.tlst.location,
|
|
|
|
quake_bsp.color.location);
|
2012-01-08 11:39:36 +00:00
|
|
|
}
|
2013-01-06 11:05:59 +00:00
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
2012-01-08 11:39:36 +00:00
|
|
|
}
|
|
|
|
bsp_end ();
|
2012-01-10 11:50:47 +00:00
|
|
|
}
|
2012-01-08 01:29:38 +00:00
|
|
|
|
2012-01-10 11:50:47 +00:00
|
|
|
void
|
2022-03-14 05:31:23 +00:00
|
|
|
glsl_R_DrawWaterSurfaces (void)
|
2012-01-10 11:50:47 +00:00
|
|
|
{
|
|
|
|
instsurf_t *is;
|
|
|
|
msurface_t *surf;
|
2021-01-19 04:05:39 +00:00
|
|
|
glsltex_t *tex = 0;
|
2012-01-10 11:50:47 +00:00
|
|
|
elechain_t *ec = 0;
|
|
|
|
elements_t *el = 0;
|
|
|
|
|
|
|
|
if (!waterchain)
|
|
|
|
return;
|
|
|
|
|
|
|
|
turb_begin ();
|
|
|
|
for (is = waterchain; is; is = is->tex_chain) {
|
|
|
|
surf = is->surface;
|
2021-01-19 04:05:39 +00:00
|
|
|
if (tex != surf->texinfo->texture->render) {
|
2012-01-10 11:50:47 +00:00
|
|
|
if (tex) {
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum);
|
2012-01-10 11:50:47 +00:00
|
|
|
for (ec = tex->elechain; ec; ec = ec->next)
|
2012-01-11 12:26:12 +00:00
|
|
|
draw_elechain (ec, quake_turb.mvp_matrix.location,
|
|
|
|
quake_turb.vertex.location,
|
2012-01-29 07:56:50 +00:00
|
|
|
quake_turb.tlst.location,
|
|
|
|
quake_turb.color.location);
|
2012-01-10 11:50:47 +00:00
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
|
|
|
}
|
2021-01-19 04:05:39 +00:00
|
|
|
tex = surf->texinfo->texture->render;
|
2012-01-10 11:50:47 +00:00
|
|
|
}
|
|
|
|
add_surf_elements (tex, is, &ec, &el);
|
|
|
|
}
|
|
|
|
if (tex) {
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, tex->gl_texturenum);
|
2012-01-10 11:50:47 +00:00
|
|
|
for (ec = tex->elechain; ec; ec = ec->next)
|
2012-01-11 12:26:12 +00:00
|
|
|
draw_elechain (ec, quake_turb.mvp_matrix.location,
|
|
|
|
quake_turb.vertex.location,
|
2012-01-29 07:56:50 +00:00
|
|
|
quake_turb.tlst.location,
|
|
|
|
quake_turb.color.location);
|
2012-01-10 11:50:47 +00:00
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
|
|
|
}
|
|
|
|
turb_end ();
|
|
|
|
|
|
|
|
waterchain = 0;
|
|
|
|
waterchain_tail = &waterchain;
|
2012-01-08 01:29:38 +00:00
|
|
|
}
|
2012-01-08 11:39:36 +00:00
|
|
|
|
2012-01-11 12:26:12 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_R_DrawSky (void)
|
2012-01-11 12:26:12 +00:00
|
|
|
{
|
|
|
|
instsurf_t *is;
|
|
|
|
msurface_t *surf;
|
2021-01-19 04:05:39 +00:00
|
|
|
glsltex_t *tex = 0;
|
2012-01-11 12:26:12 +00:00
|
|
|
elechain_t *ec = 0;
|
|
|
|
elements_t *el = 0;
|
|
|
|
|
|
|
|
if (!sky_chain)
|
|
|
|
return;
|
|
|
|
|
2012-01-12 08:34:29 +00:00
|
|
|
sky_begin ();
|
2012-01-11 12:26:12 +00:00
|
|
|
for (is = sky_chain; is; is = is->tex_chain) {
|
|
|
|
surf = is->surface;
|
2021-01-19 04:05:39 +00:00
|
|
|
if (tex != surf->texinfo->texture->render) {
|
2012-01-11 12:26:12 +00:00
|
|
|
if (tex) {
|
2012-01-12 02:05:34 +00:00
|
|
|
if (!skybox_loaded) {
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 0);
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, tex->sky_tex[0]);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 1);
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, tex->sky_tex[1]);
|
2012-01-12 02:05:34 +00:00
|
|
|
}
|
2012-01-11 12:26:12 +00:00
|
|
|
for (ec = tex->elechain; ec; ec = ec->next)
|
2012-01-12 08:34:29 +00:00
|
|
|
draw_elechain (ec, sky_params.mvp_matrix->location,
|
2012-01-29 07:56:50 +00:00
|
|
|
sky_params.vertex->location, -1, -1);
|
2012-01-11 12:26:12 +00:00
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
|
|
|
}
|
2021-01-19 04:05:39 +00:00
|
|
|
tex = surf->texinfo->texture->render;
|
2012-01-11 12:26:12 +00:00
|
|
|
}
|
|
|
|
add_surf_elements (tex, is, &ec, &el);
|
|
|
|
}
|
|
|
|
if (tex) {
|
2012-01-12 02:05:34 +00:00
|
|
|
if (!skybox_loaded) {
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 0);
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, tex->sky_tex[0]);
|
|
|
|
qfeglActiveTexture (GL_TEXTURE0 + 1);
|
|
|
|
qfeglBindTexture (GL_TEXTURE_2D, tex->sky_tex[1]);
|
2012-01-12 02:05:34 +00:00
|
|
|
}
|
2012-01-11 12:26:12 +00:00
|
|
|
for (ec = tex->elechain; ec; ec = ec->next)
|
2012-01-12 08:34:29 +00:00
|
|
|
draw_elechain (ec, sky_params.mvp_matrix->location,
|
2012-01-29 07:56:50 +00:00
|
|
|
sky_params.vertex->location, -1, -1);
|
2012-01-11 12:26:12 +00:00
|
|
|
tex->elechain = 0;
|
|
|
|
tex->elechain_tail = &tex->elechain;
|
|
|
|
}
|
2012-01-12 08:34:29 +00:00
|
|
|
sky_end ();
|
2012-01-11 12:26:12 +00:00
|
|
|
|
|
|
|
sky_chain = 0;
|
|
|
|
sky_chain_tail = &sky_chain;
|
|
|
|
}
|
|
|
|
|
2012-01-10 11:50:47 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_R_InitBsp (void)
|
2012-01-08 11:39:36 +00:00
|
|
|
{
|
2013-06-07 08:12:44 +00:00
|
|
|
shader_t *vert_shader, *frag_shader;
|
2012-01-08 11:39:36 +00:00
|
|
|
int vert;
|
|
|
|
int frag;
|
|
|
|
|
2022-05-05 12:22:44 +00:00
|
|
|
r_notexture_mip->render = &glsl_notexture;
|
|
|
|
|
2013-06-07 08:12:44 +00:00
|
|
|
vert_shader = GLSL_BuildShader (bsp_vert_effects);
|
|
|
|
frag_shader = GLSL_BuildShader (bsp_lit_effects);
|
|
|
|
vert = GLSL_CompileShader ("quakebsp.vert", vert_shader,
|
2012-02-17 09:57:13 +00:00
|
|
|
GL_VERTEX_SHADER);
|
2013-06-07 08:12:44 +00:00
|
|
|
frag = GLSL_CompileShader ("quakebsp.frag", frag_shader,
|
2012-02-17 09:57:13 +00:00
|
|
|
GL_FRAGMENT_SHADER);
|
|
|
|
quake_bsp.program = GLSL_LinkProgram ("quakebsp", vert, frag);
|
|
|
|
GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.mvp_matrix);
|
|
|
|
GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.tlst);
|
|
|
|
GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.vertex);
|
|
|
|
GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.colormap);
|
|
|
|
GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.texture);
|
|
|
|
GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.lightmap);
|
|
|
|
GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.color);
|
|
|
|
GLSL_ResolveShaderParam (quake_bsp.program, &quake_bsp.fog);
|
2013-06-07 08:12:44 +00:00
|
|
|
GLSL_FreeShader (vert_shader);
|
|
|
|
GLSL_FreeShader (frag_shader);
|
2012-02-17 09:57:13 +00:00
|
|
|
|
2013-06-07 08:12:44 +00:00
|
|
|
frag_shader = GLSL_BuildShader (bsp_turb_effects);
|
|
|
|
frag = GLSL_CompileShader ("quaketrb.frag", frag_shader,
|
2012-02-17 09:57:13 +00:00
|
|
|
GL_FRAGMENT_SHADER);
|
|
|
|
quake_turb.program = GLSL_LinkProgram ("quaketrb", vert, frag);
|
|
|
|
GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.mvp_matrix);
|
|
|
|
GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.tlst);
|
|
|
|
GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.vertex);
|
|
|
|
GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.palette);
|
|
|
|
GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.texture);
|
2013-06-07 08:12:44 +00:00
|
|
|
GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.time);
|
2012-02-17 09:57:13 +00:00
|
|
|
GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.color);
|
|
|
|
GLSL_ResolveShaderParam (quake_turb.program, &quake_turb.fog);
|
2013-06-07 08:12:44 +00:00
|
|
|
GLSL_FreeShader (frag_shader);
|
2012-02-17 09:57:13 +00:00
|
|
|
|
2013-06-07 08:12:44 +00:00
|
|
|
frag_shader = GLSL_BuildShader (bsp_sky_id_effects);
|
|
|
|
frag = GLSL_CompileShader ("quakeski.frag", frag_shader,
|
2012-02-17 09:57:13 +00:00
|
|
|
GL_FRAGMENT_SHADER);
|
|
|
|
quake_skyid.program = GLSL_LinkProgram ("quakeskyid", vert, frag);
|
|
|
|
GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.mvp_matrix);
|
|
|
|
GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.sky_matrix);
|
|
|
|
GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.vertex);
|
|
|
|
GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.palette);
|
|
|
|
GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.solid);
|
|
|
|
GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.trans);
|
2013-06-07 08:12:44 +00:00
|
|
|
GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.time);
|
2012-02-17 09:57:13 +00:00
|
|
|
GLSL_ResolveShaderParam (quake_skyid.program, &quake_skyid.fog);
|
2013-06-07 08:12:44 +00:00
|
|
|
GLSL_FreeShader (frag_shader);
|
2012-02-17 09:57:13 +00:00
|
|
|
|
2013-06-07 08:12:44 +00:00
|
|
|
frag_shader = GLSL_BuildShader (bsp_sky_cube_effects);
|
|
|
|
frag = GLSL_CompileShader ("quakeskb.frag", frag_shader,
|
2012-02-17 09:57:13 +00:00
|
|
|
GL_FRAGMENT_SHADER);
|
|
|
|
quake_skybox.program = GLSL_LinkProgram ("quakeskybox", vert, frag);
|
|
|
|
GLSL_ResolveShaderParam (quake_skybox.program, &quake_skybox.mvp_matrix);
|
|
|
|
GLSL_ResolveShaderParam (quake_skybox.program, &quake_skybox.sky_matrix);
|
|
|
|
GLSL_ResolveShaderParam (quake_skybox.program, &quake_skybox.vertex);
|
|
|
|
GLSL_ResolveShaderParam (quake_skybox.program, &quake_skybox.sky);
|
|
|
|
GLSL_ResolveShaderParam (quake_skybox.program, &quake_skybox.fog);
|
2013-06-07 08:12:44 +00:00
|
|
|
GLSL_FreeShader (frag_shader);
|
2012-01-12 02:05:34 +00:00
|
|
|
}
|
|
|
|
|
2018-10-09 03:35:01 +00:00
|
|
|
static inline __attribute__((const)) int
|
2012-02-16 11:47:38 +00:00
|
|
|
is_pow2 (unsigned x)
|
|
|
|
{
|
|
|
|
int count;
|
|
|
|
|
|
|
|
for (count = 0; x; x >>= 1)
|
|
|
|
if (x & 1)
|
|
|
|
count++;
|
|
|
|
return count == 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: this expects the destination tex_t to be set up: memory allocated
|
|
|
|
// and dimentions/format etc already set. the size of the rect to be copied
|
|
|
|
// is taken from dst. Also, dst->format and src->format must be the same, and
|
|
|
|
// either 3 or 4, or bad things will happen. Also, no clipping is done, so if
|
|
|
|
// x < 0 or y < 0 or x + dst->width > src->width
|
|
|
|
// or y + dst->height > src->height, bad things will happen.
|
|
|
|
static void
|
|
|
|
copy_sub_tex (tex_t *src, int x, int y, tex_t *dst)
|
|
|
|
{
|
|
|
|
int dstbytes;
|
|
|
|
int srcbytes;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
srcbytes = src->width * src->format;
|
|
|
|
dstbytes = dst->width * dst->format;
|
|
|
|
|
|
|
|
x *= src->format;
|
|
|
|
for (i = 0; i < dst->height; i++)
|
|
|
|
memcpy (dst->data + i * dstbytes, src->data + (i + y) * srcbytes + x,
|
|
|
|
dstbytes);
|
|
|
|
}
|
|
|
|
|
2012-02-18 13:28:42 +00:00
|
|
|
void
|
2012-02-22 07:32:34 +00:00
|
|
|
glsl_R_LoadSkys (const char *sky)
|
2012-01-12 02:05:34 +00:00
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
int i;
|
2012-02-16 11:47:38 +00:00
|
|
|
tex_t *tex;
|
2012-01-12 06:13:19 +00:00
|
|
|
// NOTE: quake's world and GL's world are rotated relative to each other
|
|
|
|
// quake has x right, y in, z up. gl has x right, y up, z out
|
2012-09-12 10:06:07 +00:00
|
|
|
// quake order: +x -x +z -z +y -y
|
|
|
|
// gl order: +x -x +y -y +z -z
|
|
|
|
// fizquake orger: -y +y +z -z +x -x
|
|
|
|
// to get from quake order to fitzquake order, all that's needed is
|
|
|
|
// a -90 degree rotation on the (quake) z-axis. This is taken care of in
|
|
|
|
// the sky_matrix setup code.
|
|
|
|
// However, from the player's perspective, skymaps have lf and rt
|
2022-03-24 06:53:46 +00:00
|
|
|
// swapped, but everything makes sense if looking at the cube from outside
|
2012-09-12 10:06:07 +00:00
|
|
|
// along the positive y axis, with the front of the cube being the nearest
|
|
|
|
// face. This matches nicely with Blender's default cube in front (num-1)
|
|
|
|
// view.
|
2012-09-12 06:19:20 +00:00
|
|
|
static const char *sky_suffix[] = { "ft", "bk", "up", "dn", "rt", "lf"};
|
2012-02-16 11:47:38 +00:00
|
|
|
static int sky_coords[][2] = {
|
|
|
|
{2, 0}, // front
|
|
|
|
{0, 0}, // back
|
|
|
|
{1, 1}, // up
|
|
|
|
{0, 1}, // down
|
2012-09-12 06:19:20 +00:00
|
|
|
{2, 1}, // left
|
|
|
|
{1, 0}, // right
|
2012-01-12 02:05:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if (!sky || !*sky)
|
[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
|
|
|
sky = r_skyname;
|
2012-01-12 02:05:34 +00:00
|
|
|
|
|
|
|
if (!*sky || !strcasecmp (sky, "none")) {
|
|
|
|
skybox_loaded = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!skybox_tex)
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglGenTextures (1, &skybox_tex);
|
2012-01-12 02:05:34 +00:00
|
|
|
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglBindTexture (GL_TEXTURE_CUBE_MAP, skybox_tex);
|
2012-01-12 02:05:34 +00:00
|
|
|
|
2012-02-16 11:47:38 +00:00
|
|
|
//blender envmap
|
|
|
|
// bk rt ft
|
|
|
|
// dn up lt
|
2021-01-31 07:01:20 +00:00
|
|
|
tex = LoadImage (name = va (0, "env/%s_map", sky), 1);
|
2012-02-16 11:47:38 +00:00
|
|
|
if (tex && tex->format >= 3 && tex->height * 3 == tex->width * 2
|
|
|
|
&& is_pow2 (tex->height)) {
|
|
|
|
tex_t *sub;
|
|
|
|
int size = tex->height / 2;
|
|
|
|
|
|
|
|
skybox_loaded = true;
|
2021-01-24 15:54:41 +00:00
|
|
|
sub = malloc (sizeof (tex_t) + size * size * tex->format);
|
|
|
|
sub->data = (byte *) (sub + 1);
|
2012-02-16 11:47:38 +00:00
|
|
|
sub->width = size;
|
|
|
|
sub->height = size;
|
|
|
|
sub->format = tex->format;
|
|
|
|
sub->palette = tex->palette;
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
|
|
int x, y;
|
|
|
|
x = sky_coords[i][0] * size;
|
|
|
|
y = sky_coords[i][1] * size;
|
|
|
|
copy_sub_tex (tex, x, y, sub);
|
2012-09-12 06:19:20 +00:00
|
|
|
qfeglTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0,
|
2012-02-16 11:47:38 +00:00
|
|
|
sub->format == 3 ? GL_RGB : GL_RGBA,
|
|
|
|
sub->width, sub->height, 0,
|
|
|
|
sub->format == 3 ? GL_RGB : GL_RGBA,
|
|
|
|
GL_UNSIGNED_BYTE, sub->data);
|
|
|
|
}
|
|
|
|
free (sub);
|
|
|
|
} else {
|
|
|
|
skybox_loaded = true;
|
|
|
|
for (i = 0; i < 6; i++) {
|
2021-01-31 07:01:20 +00:00
|
|
|
tex = LoadImage (name = va (0, "env/%s%s", sky, sky_suffix[i]), 1);
|
2012-02-16 11:47:38 +00:00
|
|
|
if (!tex || tex->format < 3) { // FIXME pcx support
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_glsl, "Couldn't load %s\n", name);
|
2012-02-16 11:47:38 +00:00
|
|
|
// also look in gfx/env, where Darkplaces looks for skies
|
2021-01-31 07:01:20 +00:00
|
|
|
tex = LoadImage (name = va (0, "gfx/env/%s%s", sky,
|
2021-01-19 01:15:57 +00:00
|
|
|
sky_suffix[i]), 1);
|
2012-02-16 11:47:38 +00:00
|
|
|
if (!tex || tex->format < 3) { // FIXME pcx support
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_glsl, "Couldn't load %s\n", name);
|
2012-02-16 11:47:38 +00:00
|
|
|
skybox_loaded = false;
|
|
|
|
continue;
|
|
|
|
}
|
2012-01-12 02:05:34 +00:00
|
|
|
}
|
2021-03-29 10:58:00 +00:00
|
|
|
Sys_MaskPrintf (SYS_glsl, "Loaded %s\n", name);
|
2012-09-12 06:19:20 +00:00
|
|
|
qfeglTexImage2D (GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0,
|
2012-02-16 11:47:38 +00:00
|
|
|
tex->format == 3 ? GL_RGB : GL_RGBA,
|
|
|
|
tex->width, tex->height, 0,
|
|
|
|
tex->format == 3 ? GL_RGB : GL_RGBA,
|
|
|
|
GL_UNSIGNED_BYTE, tex->data);
|
2012-01-12 02:05:34 +00:00
|
|
|
}
|
|
|
|
}
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,
|
2012-01-12 02:05:34 +00:00
|
|
|
GL_CLAMP_TO_EDGE);
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,
|
2012-01-12 02:05:34 +00:00
|
|
|
GL_CLAMP_TO_EDGE);
|
2012-02-22 07:48:57 +00:00
|
|
|
qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
qfeglTexParameteri (GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
qfeglGenerateMipmap (GL_TEXTURE_CUBE_MAP);
|
2012-01-08 11:39:36 +00:00
|
|
|
}
|