win: emulate gamepad thumb axis as buttons.

keys: add some extra key names for compat with DP+QS (primarily gamepad buttons).
keys: fix a few keys getting mistranslated between engine and qc scancodes.
engine menus: remove 16bpp from the video options menu on win8+, as win8 no longer supports anything but rgbx8.
pmove: coord size and rounding is now part of the pmove code itself. this fixes truncation issues.
r_clutter_density: fix crash from clutter comprising of boneless iqms.
gl: added cvars to disable immutable buffers or textures. hopefully these might be usable to work around the issue reported on various geforce 1080s
wav: convert ieee wav files to 16bit on load, in case someone tries giving us one of these.
vid_srgb: this cvar now uses -1 for the former gamma-only setting.
r_viewmodel_quake: new cvar (name comes from quakespasm) that can be used to disable the weird movement of the viewmodel when pitching up or down.
nquake: try to block nquake's frogbot's autoexec.cfg, as I keep getting complaints about it fucking over singleplayer games.
fs: added -netquake commandline argument that disables the use of the qw/ gamedir.
fog: disabled fog on aky surfaces, as it was bugging out in The Wastes.
vid: fix some vid_restart/vid_reload issues (which got much worse recently in my attempt to fix a different crash)
routing: first attempt at engine-side routing. feature is currently disabled.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5248 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2018-04-27 16:40:50 +00:00
parent d56226aac5
commit fdd903e0a3
50 changed files with 2037 additions and 350 deletions

View file

@ -2169,8 +2169,8 @@ void CLQ1_AddOrientedHalfSphere(shader_t *shader, float radius, float gap, float
{
//use simple algo
//a series of cylinders that gets progressively narrower
int latsteps = 16;
int lngsteps = 16;
const int latsteps = 16;
const int lngsteps = 8;//16;
float cradius;
int v, i, j;
scenetris_t *t;
@ -2182,7 +2182,7 @@ void CLQ1_AddOrientedHalfSphere(shader_t *shader, float radius, float gap, float
return;
/*reuse the previous trigroup if its the same shader*/
if (cl_numstris && cl_stris[cl_numstris-1].shader == shader && cl_stris[cl_numstris-1].flags == flags)
if (cl_numstris && cl_stris[cl_numstris-1].shader == shader && cl_stris[cl_numstris-1].flags == flags && cl_stris[cl_numstris-1].numvert < MAX_INDICIES-(latsteps-1)*(lngsteps-1))
t = &cl_stris[cl_numstris-1];
else
{
@ -2244,19 +2244,19 @@ void CLQ1_AddOrientedHalfSphere(shader_t *shader, float radius, float gap, float
v = latsteps-1;
for (v = 0; v < latsteps-1; v++)
{
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+lngsteps + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+0 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+lngsteps+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+lngsteps + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+lngsteps + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+0 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+lngsteps+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+lngsteps + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + v*lngsteps + i;
}
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+0 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+0 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + v*lngsteps + i;
}
}
else
@ -2266,19 +2266,19 @@ void CLQ1_AddOrientedHalfSphere(shader_t *shader, float radius, float gap, float
v = latsteps-1;
for (v = 0; v < latsteps-1; v++)
{
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+0 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+lngsteps + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+lngsteps + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+lngsteps+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+0 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+lngsteps + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+lngsteps + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+lngsteps+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + v*lngsteps + i;
}
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+0 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+0 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + v*lngsteps + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + i;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + v*lngsteps + i;
}
}
@ -2287,6 +2287,12 @@ void CLQ1_AddOrientedHalfSphere(shader_t *shader, float radius, float gap, float
cl_numstrisvert += lngsteps*latsteps;
}
void CLQ1_AddOrientedSphere(shader_t *shader, float radius, float *matrix, float r, float g, float b, float a)
{
CLQ1_AddOrientedHalfSphere(shader, radius, 0, matrix, r, g, b, a);
CLQ1_AddOrientedHalfSphere(shader, -radius, 0, matrix, r, g, b, a);
}
void CLQ1_AddOrientedCylinder(shader_t *shader, float radius, float height, qboolean capsule, float *matrix, float r, float g, float b, float a)
{
int sides = 16;
@ -2357,31 +2363,31 @@ void CLQ1_AddOrientedCylinder(shader_t *shader, float radius, float height, qboo
}
for (v = 0; v < sides-1; v++)
{
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+2 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+0 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+3 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+2 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+2 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+0 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+3 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+2 + v*2;
}
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+0;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+0 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+0;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+0;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+0 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1 + v*2;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+0;
if (!capsule)
{
for (v = 4; v < sides*2; v+=2)
{
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+v;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+(v-2);
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+0;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+v;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+(v-2);
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+0;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+1;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+(v-2)+1;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert+v+1;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+1;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+(v-2)+1;
cl_strisidx[cl_numstrisidx++] = cl_numstrisvert-t->firstvert+v+1;
}
}

View file

@ -2169,6 +2169,7 @@ void CL_CheckServerInfo(void)
s = Info_ValueForKey(cl.serverinfo, "pm_flyfriction");
movevars.flyfriction = *s?Q_atof(s):4;
}
movevars.coordsize = cls.netchan.netprim.coordsize;
// Initialize cl.maxpitch & cl.minpitch
if (cls.protocol == CP_QUAKEWORLD || cls.protocol == CP_NETQUAKE)

View file

@ -722,6 +722,7 @@ static qintptr_t VARGS Plug_GetNetworkInfo(void *offset, quintptr_t mask, const
}
#undef has
#ifdef QUAKEHUD
static qintptr_t VARGS Plug_GetTrackerOwnFrags(void *offset, quintptr_t mask, const qintptr_t *arg)
{
int ret;
@ -734,6 +735,7 @@ static qintptr_t VARGS Plug_GetTrackerOwnFrags(void *offset, quintptr_t mask, co
VM_FLOAT(ret) = Stats_GetLastOwnFrag(seat, outptr, outlen);
return ret;
}
#endif
static qintptr_t VARGS Plug_GetLocationName(void *offset, quintptr_t mask, const qintptr_t *arg)
{
@ -1297,6 +1299,7 @@ void Plug_Client_Init(void)
#ifdef QUAKEHUD
Plug_RegisterBuiltin("GetTeamInfo", Plug_GetTeamInfo, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("GetWeaponStats", Plug_GetWeaponStats, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("GetTrackerOwnFrags", Plug_GetTrackerOwnFrags, PLUG_BIF_NEEDSRENDERER);
#endif
Plug_RegisterBuiltin("GetLocationName", Plug_GetLocationName, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("GetPlayerInfo", Plug_GetPlayerInfo, PLUG_BIF_NEEDSRENDERER);
@ -1305,7 +1308,6 @@ void Plug_Client_Init(void)
Plug_RegisterBuiltin("GetServerInfo", Plug_GetServerInfo, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("SetUserInfo", Plug_SetUserInfo, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("GetNetworkInfo", Plug_GetNetworkInfo, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("GetTrackerOwnFrags", Plug_GetTrackerOwnFrags, PLUG_BIF_NEEDSRENDERER);
Plug_RegisterBuiltin("S_RawAudio", Plug_S_RawAudio, PLUG_BIF_NEEDSRENDERER);

View file

@ -1879,9 +1879,18 @@ void INS_Commands (void)
K_GP_X,
K_GP_Y,
//not part of xinput specs, but appended by us from analog triggers
//not part of xinput specs, but used to treat the various axis as buttons.
K_GP_LEFT_THUMB_UP,
K_GP_LEFT_THUMB_DOWN,
K_GP_LEFT_THUMB_LEFT,
K_GP_LEFT_THUMB_RIGHT,
K_GP_RIGHT_THUMB_UP,
K_GP_RIGHT_THUMB_DOWN,
K_GP_RIGHT_THUMB_LEFT,
K_GP_RIGHT_THUMB_RIGHT,
K_GP_LEFT_TRIGGER,
K_GP_RIGHT_TRIGGER
K_GP_RIGHT_TRIGGER,
};
static const int mmjbuttons[32] =
{
@ -2061,10 +2070,28 @@ static qboolean INS_ReadJoystick (struct wjoy_s *joy)
joy->devstate = DS_PRESENT;
joy->buttonstate = xistate.Gamepad.wButtons & 0xffff;
if (xistate.Gamepad.sThumbLY < -16364)
joy->buttonstate |= 0x00010000;
if (xistate.Gamepad.sThumbLY > 16364)
joy->buttonstate |= 0x00020000;
if (xistate.Gamepad.sThumbLX < -16364)
joy->buttonstate |= 0x00040000;
if (xistate.Gamepad.sThumbLX > 16364)
joy->buttonstate |= 0x00080000;
if (xistate.Gamepad.sThumbRY < -16364)
joy->buttonstate |= 0x00100000;
if (xistate.Gamepad.sThumbRY > 16364)
joy->buttonstate |= 0x00200000;
if (xistate.Gamepad.sThumbRX < -16364)
joy->buttonstate |= 0x00400000;
if (xistate.Gamepad.sThumbRX > 16364)
joy->buttonstate |= 0x00800000;
if (xistate.Gamepad.bLeftTrigger >= 128)
joy->buttonstate |= 0x10000;
joy->buttonstate |= 0x01000000;
if (xistate.Gamepad.bRightTrigger >= 128)
joy->buttonstate |= 0x20000;
joy->buttonstate |= 0x02000000;
if (joy->devid != DEVID_UNSET)
{

View file

@ -184,6 +184,12 @@ keyname_t keynames[] =
{"KP_7", K_KP_HOME},
{"KP_8", K_KP_UPARROW},
{"KP_9", K_KP_PGUP},
//dp compat
{"KP_PERIOD", K_KP_DEL},
{"KP_DIVIDE", K_KP_SLASH},
{"NUMLOCK", K_KP_NUMLOCK},
{"MOUSE1", K_MOUSE1},
{"MOUSE2", K_MOUSE2},
@ -198,8 +204,14 @@ keyname_t keynames[] =
{"MWHEELUP", K_MWHEELUP},
{"MWHEELDOWN", K_MWHEELDOWN},
{"LWIN", K_LWIN},
{"RWIN", K_RWIN},
{"LWIN", K_LWIN}, //windows name
{"RWIN", K_RWIN}, //windows name
{"WIN", K_WIN}, //depricated
{"RCOMMAND",K_RWIN}, //mac name
{"LCOMMAND",K_LWIN}, //mac name
{"COMMAND", K_WIN}, //quakespasm(mac) compat
{"LMETA", K_LWIN}, //linux name
{"RMETA", K_RWIN}, //linux name
{"APP", K_APP},
{"MENU", K_APP},
{"SEARCH", K_SEARCH},
@ -253,6 +265,7 @@ keyname_t keynames[] =
{"SEMICOLON", ';'}, // because a raw semicolon seperates commands
{"PLUS", '+'}, // because "shift++" is inferior to shift+plus
{"MINUS", '-'}, // because "shift+-" is inferior to shift+minus
{"TILDE", '~'},
{"BACKQUOTE", '`'},
@ -277,6 +290,62 @@ keyname_t keynames[] =
{"GP_GUIDE", K_GP_GUIDE},
{"GP_UNKNOWN", K_GP_UNKNOWN},
//names for playstation controllers
{"GP_CROSS", K_GP_A},
{"GP_CIRCLE", K_GP_B},
{"GP_SQUARE", K_GP_X},
{"GP_TRIANGLE", K_GP_Y},
//axis->button emulation
{"GP_LTHUMB_UP", K_GP_LEFT_THUMB_UP},
{"GP_LTHUMB_DOWN", K_GP_LEFT_THUMB_DOWN},
{"GP_LTHUMB_LEFT", K_GP_LEFT_THUMB_LEFT},
{"GP_LTHUMB_RIGHT", K_GP_LEFT_THUMB_RIGHT},
{"GP_RTHUMB_UP", K_GP_RIGHT_THUMB_UP},
{"GP_RTHUMB_DOWN", K_GP_RIGHT_THUMB_DOWN},
{"GP_RTHUMB_LEFT", K_GP_RIGHT_THUMB_LEFT},
{"GP_RTHUMB_RIGHT", K_GP_RIGHT_THUMB_RIGHT},
#ifndef QUAKETC
//dp compat
{"X360_DPAD_UP", K_GP_DPAD_UP},
{"X360_DPAD_DOWN", K_GP_DPAD_DOWN},
{"X360_DPAD_LEFT", K_GP_DPAD_LEFT},
{"X360_DPAD_RIGHT", K_GP_DPAD_RIGHT},
{"X360_START", K_GP_START},
{"X360_BACK", K_GP_BACK},
{"X360_LEFT_THUMB", K_GP_LEFT_THUMB},
{"X360_RIGHT_THUMB", K_GP_RIGHT_THUMB},
{"X360_LEFT_SHOULDER", K_GP_LEFT_SHOULDER},
{"X360_RIGHT_SHOULDER", K_GP_RIGHT_SHOULDER},
{"X360_A", K_GP_A},
{"X360_B", K_GP_B},
{"X360_X", K_GP_X},
{"X360_Y", K_GP_Y},
{"X360_LEFT_TRIGGER", K_GP_LEFT_TRIGGER},
{"X360_RIGHT_TRIGGER", K_GP_RIGHT_TRIGGER},
{"X360_LEFT_THUMB_UP", K_GP_LEFT_THUMB_UP},
{"X360_LEFT_THUMB_DOWN", K_GP_LEFT_THUMB_DOWN},
{"X360_LEFT_THUMB_LEFT", K_GP_LEFT_THUMB_LEFT},
{"X360_LEFT_THUMB_RIGHT", K_GP_LEFT_THUMB_RIGHT},
{"X360_RIGHT_THUMB_UP", K_GP_RIGHT_THUMB_UP},
{"X360_RIGHT_THUMB_DOWN", K_GP_RIGHT_THUMB_DOWN},
{"X360_RIGHT_THUMB_LEFT", K_GP_RIGHT_THUMB_LEFT},
{"X360_RIGHT_THUMB_RIGHT", K_GP_RIGHT_THUMB_RIGHT},
//quakespasm compat
{"LTHUMB", K_GP_LEFT_THUMB},
{"RTHUMB", K_GP_RIGHT_THUMB},
{"LSHOULDER", K_GP_LEFT_SHOULDER},
{"RSHOULDER", K_GP_RIGHT_SHOULDER},
{"ABUTTON", K_GP_A},
{"BBUTTON", K_GP_B},
{"XBUTTON", K_GP_X},
{"YBUTTON", K_GP_Y},
{"LTRIGGER", K_GP_LEFT_TRIGGER},
{"RTRIGGER", K_GP_RIGHT_TRIGGER},
#endif
{NULL, 0}
};
@ -1000,9 +1069,11 @@ void Key_DefaultLinkClicked(console_t *con, char *text, char *info)
}
}
void Key_ConsoleRelease(console_t *con, int key, int unicode)
void Key_ConsoleRelease(console_t *con, int key, unsigned int unicode)
{
char *buffer;
if (key < 0)
key = 0;
if (key == K_MOUSE1 && con->buttonsdown == CB_SELECT)
{
@ -1438,14 +1509,14 @@ Key_Console
Interactive line editing and console scrollback
====================
*/
qboolean Key_Console (console_t *con, unsigned int unicode, int key)
qboolean Key_Console (console_t *con, int key, unsigned int unicode)
{
qboolean ctrl = keydown[K_LCTRL] || keydown[K_RCTRL];
qboolean shift = keydown[K_LSHIFT] || keydown[K_RSHIFT];
int rkey = key;
//weirdness for the keypad.
if ((unicode >= '0' && unicode <= '9') || unicode == '.')
if ((unicode >= '0' && unicode <= '9') || unicode == '.' || key < 0)
key = 0;
if (con->redirect)
@ -1906,7 +1977,7 @@ static char *Key_KeynumToStringRaw (int keynum)
keyname_t *kn;
static char tinystr[2];
if (keynum == -1)
if (keynum < 0)
return "<KEY NOT FOUND>";
if (keynum > 32 && keynum < 127 && keynum != '\'' && keynum != '\"')
{ // printable ascii
@ -2694,7 +2765,7 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down
{
con->mousecursor[0] = mousecursor_x - ((con->flags & CONF_ISWINDOW)?con->wnd_x+8:0);
con->mousecursor[1] = mousecursor_y - ((con->flags & CONF_ISWINDOW)?con->wnd_y:0);
if (Key_Console (con, unicode, key))
if (Key_Console (con, key, unicode))
return;
}
else
@ -2792,7 +2863,8 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down
//csqc key codes may even have no standard keycode so cannot easily be bound from qc.
switch(key)
{
//left+right alts got split
//left+right alts/etc got split
//the generic name maps to the left key, so the right key needs to try the left
case K_RALT:
bkey = K_LALT;
break;
@ -2802,6 +2874,9 @@ void Key_Event (unsigned int devid, int key, unsigned int unicode, qboolean down
case K_RSHIFT:
bkey = K_LSHIFT;
break;
case K_RWIN:
bkey = K_LWIN;
break;
//gamepad buttons should get fallbacks out of the box, even if they're not initially listed on the binds menu.
//these may be redefined later...

View file

@ -202,6 +202,20 @@ K_GP_DPAD_LEFT = 253,
K_GP_DPAD_RIGHT = 254,
K_GP_UNKNOWN = 255,
//axis->button emulation. for weird people.
K_GP_LEFT_THUMB_UP,
K_GP_LEFT_THUMB_DOWN,
K_GP_LEFT_THUMB_LEFT,
K_GP_LEFT_THUMB_RIGHT,
K_GP_RIGHT_THUMB_UP,
K_GP_RIGHT_THUMB_DOWN,
K_GP_RIGHT_THUMB_LEFT,
K_GP_RIGHT_THUMB_RIGHT,
K_JOY_UP,
K_JOY_DOWN,
K_JOY_LEFT,
K_JOY_RIGHT,
K_MM_BROWSER_BACK,
K_MM_BROWSER_FAVORITES,
K_MM_BROWSER_FORWARD,
@ -220,6 +234,7 @@ K_MAX
#define KEY_MODIFIER_SHIFT (1<<0)
#define KEY_MODIFIER_ALT (1<<1)
#define KEY_MODIFIER_CTRL (1<<2)
//#define KEY_MODIFIER_META (1<<?) do we want?
#define KEY_MODIFIER_ALTBINDMAP (1<<3)
#define KEY_MODIFIERSTATES (1<<4)
@ -227,6 +242,7 @@ K_MAX
#define K_SHIFT K_LSHIFT
#define K_CTRL K_LCTRL
#define K_ALT K_LALT
#define K_WIN K_LWIN
typedef enum //highest has priority
{
@ -284,6 +300,9 @@ void Key_Unbindall_f (void); //aka: Key_Shutdown
void Key_ConsoleReplace(const char *instext);
void Key_DefaultLinkClicked(console_t *con, char *text, char *info);
qboolean Key_Console (console_t *con, int key, unsigned int unicode);
void Key_ConsoleRelease(console_t *con, int key, unsigned int unicode);
struct console_s;
qboolean Key_GetConsoleSelectionBox(struct console_s *con, int *sx, int *sy, int *ex, int *ey);
qboolean Key_MouseShouldBeFree(void);

View file

@ -372,9 +372,11 @@ void PM_ValidatePackage(package_t *p)
char buf[8];
searchpathfuncs_t *archive;
#ifdef PACKAGE_Q1PAK
if (!Q_strcasecmp(COM_FileExtension(n, buf, sizeof(buf)), "pak"))
archive = FSPAK_LoadArchive(pf, NULL, n, n, NULL);
else
#endif
{
#ifdef AVAIL_ZLIB //assume zip/pk3/pk4/apk/etc
archive = FSZIP_LoadArchive(pf, NULL, n, n, NULL);

View file

@ -784,6 +784,7 @@ const char *presetexec[] =
"seta cl_nolerp 1;"
"seta r_lerpmuzzlehack 0;"
"seta v_gunkick 0;"
"seta v_viewmodel_quake 0;"
"seta cl_rollangle 0;"
"seta cl_bob 0;"
"seta cl_sbar 0;"
@ -843,6 +844,7 @@ const char *presetexec[] =
"gl_texturemode2d n.l;" //yeah, 2d too.
"r_nolerp 1;"
"cl_sbar 1;"
"v_viewmodel_quake 1;"
"gl_affinemodels 1;"
"r_softwarebanding 1;" //ugly software banding.
"r_part_classic_square 1;" //blocky baby!
@ -868,6 +870,7 @@ const char *presetexec[] =
"gl_texturemode ln;"
"gl_texturemode2d l;"
"cl_sbar 0;"
"v_viewmodel_quake 0;" //don't move the gun around weirdly.
"sv_nqplayerphysics 0;"
"cl_demoreel 0;"
"r_loadlit 1;"
@ -2591,7 +2594,7 @@ void M_Menu_Video_f (void)
extern cvar_t v_contrast, vid_conwidth, vid_conheight;
// extern cvar_t vid_width, vid_height, vid_preservegamma, vid_hardwaregamma, vid_desktopgamma;
extern cvar_t vid_desktopsettings, vid_conautoscale;
extern cvar_t vid_bpp, vid_refreshrate, vid_multisample;
extern cvar_t vid_bpp, vid_refreshrate, vid_multisample, vid_srgb;
static const char *gammamodeopts[] = {
"Off",
@ -2610,6 +2613,16 @@ void M_Menu_Video_f (void)
NULL
};
static const char *srgbopts[] = {
"Non-Linear",
"sRGB-Aware (PBR)",
"Linear (HDR)",
"Linearised", //-1
NULL
};
static const char *srgbvalues[] = { "0", "1", "2", "-1", NULL};
#ifdef ANDROID
extern cvar_t sys_orientation;
static const char *orientationopts[] = {
@ -2719,10 +2732,17 @@ void M_Menu_Video_f (void)
static const char *bppopts[] =
{
"16-bit",
"32-bit",
"24-bit",
NULL
};
static const char *bppvalues[] = {"16", "32", NULL};
static const char *bppvalues[] = {"16", "24", NULL};
#ifdef _WIN32
extern int qwinvermaj, qwinvermin;
//on win8+, hide the 16bpp option - windows would just reject it.
int bppbias = ((qwinvermaj == 6 && qwinvermin >= 2) || qwinvermaj>6)?1:0;
#else
const int bppbias = 0;
#endif
static const char *refreshopts[] =
{
@ -2821,7 +2841,7 @@ void M_Menu_Video_f (void)
MB_COMBORETURN("Size", resaspects[2], reschoices[2], info->ressize[2], "Select resolution for display."),
MB_SPACING(-8),
MB_COMBORETURN("Size", resaspects[3], reschoices[3], info->ressize[3], "Select resolution for display."),
MB_COMBOCVARRETURN("Color Depth", vid_bpp, bppopts, bppvalues, info->bppfixed, vid_bpp.description),
MB_COMBOCVARRETURN("Color Depth", vid_bpp, bppopts+bppbias, bppvalues+bppbias, info->bppfixed, vid_bpp.description),
MB_COMBOCVARRETURN("Refresh Rate", vid_refreshrate, refreshopts, refreshvalues, info->hzfixed, vid_refreshrate.description),
MB_SPACING(-24), // really hacky...
// custom entries
@ -2852,6 +2872,7 @@ void M_Menu_Video_f (void)
MB_SLIDER("View Size", scr_viewsize, 30, 120, 10, NULL),
MB_COMBOCVAR("Gamma Mode", v_gamma, gammamodeopts, gammamodevalues, "Controls how gamma is applied"),
MB_SLIDER("Gamma", v_gamma, 1.5, 0.25, -0.05, NULL),
MB_COMBOCVAR("Gamma Mode", vid_srgb, srgbopts, srgbvalues, "Controls the colour space to try to use."),
MB_SLIDER("Contrast", v_contrast, 0.8, 3, 0.05, NULL),
MB_END()
};

View file

@ -148,21 +148,45 @@ int MP_TranslateFTEtoQCCodes(int code)
case K_GP_BACK: return 821;
case K_GP_LEFT_THUMB: return 822;
case K_GP_RIGHT_THUMB: return 823;
case K_GP_LEFT_SHOULDER:return 824;
case K_GP_RIGHT_SHOULDER:return 825;
case K_GP_LEFT_SHOULDER: return 824;
case K_GP_RIGHT_SHOULDER: return 825;
case K_GP_A: return 826;
case K_GP_B: return 827;
case K_GP_X: return 828;
case K_GP_Y: return 829;
case K_GP_LEFT_TRIGGER: return 830;
case K_GP_RIGHT_TRIGGER:return 831;
case K_GP_RIGHT_TRIGGER: return 831;
case K_GP_LEFT_THUMB_UP: return 832;
case K_GP_LEFT_THUMB_DOWN: return 833;
case K_GP_LEFT_THUMB_LEFT: return 834;
case K_GP_LEFT_THUMB_RIGHT: return 835;
case K_GP_RIGHT_THUMB_UP: return 836;
case K_GP_RIGHT_THUMB_DOWN: return 837;
case K_GP_RIGHT_THUMB_LEFT: return 838;
case K_GP_RIGHT_THUMB_RIGHT:return 839;
case K_JOY_UP: return 840;
case K_JOY_DOWN: return 841;
case K_JOY_LEFT: return 842;
case K_JOY_RIGHT: return 843;
case K_VOLUP: return -code;
case K_VOLDOWN: return -code;
case K_APP: return -code;
case K_F13:
case K_F14:
case K_F15:
case K_POWER:
case K_LWIN:
case K_RWIN:
case K_VOLUP:
case K_VOLDOWN:
case K_APP:
case K_SEARCH: return -code;
default: return code;
default:
if (code < 0) //negative values are 'qc-native' keys, for stuff that the api lacks.
return -code;
if (code >= 0 && code < 128) //ascii codes identical
return code;
return -code; //unknown key.
}
}
@ -308,18 +332,24 @@ int MP_TranslateQCtoFTECodes(int code)
case 829: return K_GP_Y;
case 830: return K_GP_LEFT_TRIGGER;
case 831: return K_GP_RIGHT_TRIGGER;
// case 832: return K_GP_LEFT_THUMB_UP;
// case 833: return K_GP_LEFT_THUMB_DOWN;
// case 834: return K_GP_LEFT_THUMB_LEFT;
// case 835: return K_GP_LEFT_THUMB_RIGHT;
// case 836: return K_GP_RIGHT_THUMB_UP;
// case 837: return K_GP_RIGHT_THUMB_DOWN;
// case 838: return K_GP_RIGHT_THUMB_LEFT;
// case 839: return K_GP_RIGHT_THUMB_RIGHT;
case 832: return K_GP_LEFT_THUMB_UP;
case 833: return K_GP_LEFT_THUMB_DOWN;
case 834: return K_GP_LEFT_THUMB_LEFT;
case 835: return K_GP_LEFT_THUMB_RIGHT;
case 836: return K_GP_RIGHT_THUMB_UP;
case 837: return K_GP_RIGHT_THUMB_DOWN;
case 838: return K_GP_RIGHT_THUMB_LEFT;
case 839: return K_GP_RIGHT_THUMB_RIGHT;
case 840: return K_JOY_UP;
case 841: return K_JOY_DOWN;
case 842: return K_JOY_LEFT;
case 843: return K_JOY_RIGHT;
default:
if (code < 0) //negative values are 'fte-native' keys, for stuff that the api lacks.
return -code;
if (code >= 0 && code < 128)
return code;
return -code; //these keys are not supported in fte. use negatives so that they can be correctly mapped back to qc codes if the need arises. no part of the engine will recognise them.
}
}
@ -328,15 +358,21 @@ void QCBUILTIN PF_cl_findkeysforcommand (pubprogfuncs_t *prinst, struct globalva
{
const char *cmdname = PR_GetStringOfs(prinst, OFS_PARM0);
int bindmap = (prinst->callargc > 1)?G_FLOAT(OFS_PARM1):0;
int keynums[2];
int keynums[16];
char keyname[512];
size_t u;
M_FindKeysForCommand(bindmap, 0, cmdname, keynums, NULL, countof(keynums));
keyname[0] = '\0';
Q_strncatz (keyname, va(" \'%i\'", MP_TranslateFTEtoQCCodes(keynums[0])), sizeof(keyname));
Q_strncatz (keyname, va(" \'%i\'", MP_TranslateFTEtoQCCodes(keynums[1])), sizeof(keyname));
for (u = 0; u < countof(keynums); u++)
{
if (keynums[u] >= 0)
keynums[u] = MP_TranslateFTEtoQCCodes(keynums[u]);
else if (u >= 2) //would ideally be 0, but nexuiz would bug out then.
break;
Q_strncatz (keyname, va(" \'%i\'", keynums[u]), sizeof(keyname));
}
RETURN_TSTRING(keyname);
}

View file

@ -6192,6 +6192,10 @@ static struct {
{"brush_findinvolume", PF_brush_findinvolume, 0},
#endif
#ifdef ENGINE_ROUTING
{"route_calculate", PF_route_calculate, 0},
#endif
{"touchtriggers", PF_touchtriggers, 279},//void() touchtriggers = #279;
{"skel_ragupdate", PF_skel_ragedit, 281},// (FTE_QC_RAGDOLL)
{"skel_mmap", PF_skel_mmap, 282},// (FTE_QC_RAGDOLL)
@ -7168,6 +7172,7 @@ qboolean CSQC_Init (qboolean anycsqc, qboolean csdatenabled, unsigned int checks
movevars.watersinkspeed = 60;//*pm_watersinkspeed.string?pm_watersinkspeed.value:60;
movevars.flyfriction = 4;//*pm_flyfriction.string?pm_flyfriction.value:4;
movevars.stepheight = PM_DEFAULTSTEPHEIGHT;
movevars.coordsize = 4;
}
for (i = 0; i < sizeof(csqc_builtin)/sizeof(csqc_builtin[0]); i++)

View file

@ -1097,8 +1097,6 @@ void QCBUILTIN PF_SubConDraw (pubprogfuncs_t *prinst, struct globalvars_s *pr_gl
Con_DrawOneConsole(con, con->flags & CONF_KEYFOCUSED, PR_CL_ChooseFont(world->g.drawfont, fontsize, fontsize), pos[0], pos[1], size[0], size[1], 0);
}
qboolean Key_Console (console_t *con, unsigned int unicode, int key);
void Key_ConsoleRelease (console_t *con, unsigned int unicode, int key);
void QCBUILTIN PF_SubConInput (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
const char *conname = PR_GetStringOfs(prinst, OFS_PARM0);
@ -1117,7 +1115,7 @@ void QCBUILTIN PF_SubConInput (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
if ((pa && qcinput_scan != pa) || (pb && pb != qcinput_unicode))
G_FLOAT(OFS_RETURN) = 0;
else
G_FLOAT(OFS_RETURN) = Key_Console(con, pb, MP_TranslateQCtoFTECodes(pa));
G_FLOAT(OFS_RETURN) = Key_Console(con, MP_TranslateQCtoFTECodes(pa), pb);
break;
case CSIE_KEYUP:
//scan, char

View file

@ -210,7 +210,10 @@ static void R_Clutter_Insert_Mesh(clutter_build_ctx_t *ctx, model_t *mod, float
while(inf)
{
galiasskin_t *skins = inf->ofsskins;
if (inf->numanimations >= 1)
re.framestate.g[FS_REG].frame[0] = randanim%inf->numanimations;
else
re.framestate.g[FS_REG].frame[0] = 0;
if (skins->numframes)
{
unsigned int frame = randskin%skins->numframes;

View file

@ -132,8 +132,8 @@ cvar_t r_fastsky = CVARF ("r_fastsky", "0",
CVAR_ARCHIVE);
cvar_t r_fastskycolour = CVARF ("r_fastskycolour", "0",
CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM);
cvar_t r_fb_bmodels = CVARAF("r_fb_bmodels", "1",
"gl_fb_bmodels", CVAR_SEMICHEAT|CVAR_RENDERERLATCH);
cvar_t r_fb_bmodels = CVARAFD("r_fb_bmodels", "1",
"gl_fb_bmodels", CVAR_SEMICHEAT|CVAR_RENDERERLATCH, "Enables loading lumas on the map, as well as any external bsp models.");
cvar_t r_fb_models = CVARAFD ("r_fb_models", "1",
"gl_fb_models", CVAR_SEMICHEAT, "Enables the use of lumas on models. Note that if ruleset_allow_fbmodels is enabled, then all models are unconditionally fullbright in deathmatch, because cheaters would set up their models like that anyway, hurrah for beating them at their own game. QuakeWorld players suck.");
cvar_t r_skin_overlays = CVARF ("r_skin_overlays", "1",
@ -278,10 +278,10 @@ cvar_t vid_multisample = CVARFD ("vid_multisample", "0",
cvar_t vid_refreshrate = CVARF ("vid_displayfrequency", "0",
CVAR_ARCHIVE | CVAR_VIDEOLATCH);
cvar_t vid_srgb = CVARFD ("vid_srgb", "0",
CVAR_ARCHIVE, "0: Off. Colour blending will be wrong.\n1: Only the framebuffer should use sRGB colourspace, textures and colours will be assumed to be linear. This has the effect of brightening the screen.\n2: Use sRGB extensions/support to ensure that the sh");
CVAR_ARCHIVE, "-1: Only the framebuffer should use sRGB colourspace, textures and colours will be assumed to be linear. This has the effect of just brightening the screen according to a gamma ramp of about 2.2 (or .45 in quake's backwards gamma terms).\n0: Off. Colour blending will be wrong, you're likely to see obvious banding.\n1: Use sRGB extensions/support to ensure that the lighting aproximately matches real-world lighting (required for PBR).\n2: Attempt to use a linear floating-point framebuffer, which should enable monitor support for HDR.\nNote that driver behaviour varies by a disturbing amount, and much of the documentation conflicts with itself (the term 'linear' is awkward when the eye's perception of linear is non-linear).");
cvar_t vid_wndalpha = CVARD ("vid_wndalpha", "1", "When running windowed, specifies the window's transparency level.");
#if defined(_WIN32) && defined(MULTITHREAD)
cvar_t vid_winthread = CVARFD ("vid_winthread", "", CVAR_ARCHIVE|CVAR_VIDEOLATCH, "When enabled, window messages will be handled by a separate thread. This allows the game to continue rendering when Microsoft Windows blocks while resizing etc.");
cvar_t vid_winthread = CVARFD ("vid_winthread", "", CVAR_ARCHIVE|CVAR_VIDEOLATCH, "When enabled, window messages will be handled by a separate thread. This allows the game to continue rendering when Microsoft Windows blocks while resizing, etc.");
#endif
//more readable defaults to match conwidth/conheight.
cvar_t vid_width = CVARFD ("vid_width", "0",
@ -333,6 +333,9 @@ cvar_t vid_gl_context_es = CVARD ("vid_gl_context_es", "0", "Requests an Op
cvar_t vid_gl_context_robustness = CVARD ("vid_gl_context_robustness", "1", "Attempt to enforce extra buffer protection in the gl driver, but can be slower with pre-gl3 hardware.");
cvar_t vid_gl_context_selfreset = CVARD ("vid_gl_context_selfreset", "1", "Upon hardware failure, have the engine create a new context instead of depending on the drivers to restore everything. This can help to avoid graphics drivers randomly killing your game, and can help reduce memory requirements.");
cvar_t vid_gl_context_noerror = CVARD ("vid_gl_context_noerror", "", "Disables OpenGL's error checks for a small performance speedup. May cause segfaults if stuff wasn't properly implemented/tested.");
cvar_t gl_immutable_textures = CVARD ("gl_immutable_textures", "1", "Controls whether to use immutable GPU memory allocations for OpenGL textures. This potentially means less work for the drivers and thus higher framerates.");
cvar_t gl_immutable_buffers = CVARD ("gl_immutable_buffers", "1", "Controls whether to use immutable GPU memory allocations for static OpenGL vertex buffers. This potentially means less work for the drivers and thus higher framerates.");
#endif
#if 1
@ -498,6 +501,9 @@ void GLRenderer_Init(void)
Cvar_Register (&vid_gl_context_selfreset, GLRENDEREROPTIONS);
Cvar_Register (&vid_gl_context_noerror, GLRENDEREROPTIONS);
Cvar_Register (&gl_immutable_textures, GLRENDEREROPTIONS);
Cvar_Register (&gl_immutable_buffers, GLRENDEREROPTIONS);
//renderer
Cvar_Register (&gl_affinemodels, GLRENDEREROPTIONS);
@ -974,6 +980,7 @@ void Renderer_Init(void)
Cvar_Register (&r_fb_bmodels, GRAPHICALNICETIES);
Cvar_Register (&r_fb_models, GRAPHICALNICETIES);
// Cvar_Register (&r_fullbrights, GRAPHICALNICETIES); //dpcompat: 1 if r_fb_bmodels&&r_fb_models
Cvar_Register (&r_skin_overlays, GRAPHICALNICETIES);
Cvar_Register (&r_globalskin_first, GRAPHICALNICETIES);
Cvar_Register (&r_globalskin_count, GRAPHICALNICETIES);
@ -1298,16 +1305,16 @@ void R_ShutdownRenderer(qboolean devicetoo)
Media_VideoRestarting();
//these functions need to be able to cope with vid_reload, so don't clear them.
//they also need to be able to cope with being re-execed in the case of failed startup.
if (R_DeInit)
{
TRACE(("dbg: R_ApplyRenderer: R_DeInit\n"));
R_DeInit();
R_DeInit = NULL;
}
if (Draw_Shutdown)
Draw_Shutdown();
Draw_Shutdown = NULL;
TRACE(("dbg: R_ApplyRenderer: SCR_DeInit\n"));
SCR_DeInit();
@ -1316,7 +1323,6 @@ void R_ShutdownRenderer(qboolean devicetoo)
{
TRACE(("dbg: R_ApplyRenderer: VID_DeInit\n"));
VID_DeInit();
VID_DeInit = NULL;
}
COM_FlushTempoaryPacks();

View file

@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
typedef struct
{
int format;
int rate;
int width;
int numchannels;
@ -717,6 +718,19 @@ static qboolean QDECL S_LoadDoomSound (sfx_t *s, qbyte *data, size_t datalen, in
}
#endif
void S_ShortedLittleFloats(void *p, size_t samples)
{
short *out = p;
float *in = p;
int t;
while(samples --> 0)
{
t = LittleFloat(*in++) * 32767;
t = bound(-32768, t, 32767);
*out++ = t;
}
}
static qboolean QDECL S_LoadWavSound (sfx_t *s, qbyte *data, size_t datalen, int sndspeed)
{
wavinfo_t info;
@ -732,10 +746,28 @@ static qboolean QDECL S_LoadWavSound (sfx_t *s, qbyte *data, size_t datalen, int
return false;
}
if (info.width == 1)
if (info.format == 1 && info.width == 1)
COM_CharBias(data + info.dataofs, info.samples*info.numchannels);
else if (info.width == 2)
else if (info.format == 1 && info.width == 2)
COM_SwapLittleShortBlock((short *)(data + info.dataofs), info.samples*info.numchannels);
else if (info.format == 3 && info.width == 4)
{
S_ShortedLittleFloats(data + info.dataofs, info.samples*info.numchannels);
info.width = 2;
}
else
{
s->loadstate = SLS_FAILED;
switch(info.format)
{
case 1:
case 3: Con_Printf ("%s has an unsupported width (%i bits).\n", s->name, info.width*8); break;
case 6: Con_Printf ("%s uses unsupported a-law format.\n", s->name); break;
case 7: Con_Printf ("%s uses unsupported mu-law format.\n", s->name); break;
default: Con_Printf ("%s has an unsupported format.\n", s->name); break;
}
return false;
}
return ResampleSfx (s, info.rate, info.numchannels, info.width, info.samples, info.loopstart, data + info.dataofs);
}
@ -1050,7 +1082,6 @@ static wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength)
{
wavinfo_t info;
int i;
int format;
int samples;
int chunklen;
wavctx_t ctx;
@ -1087,12 +1118,7 @@ static wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength)
return info;
}
ctx.data_p += 8;
format = GetLittleShort(&ctx);
if (format != 1)
{
Con_Printf("Microsoft PCM format only\n");
return info;
}
info.format = GetLittleShort(&ctx);
info.numchannels = GetLittleShort(&ctx);
info.rate = GetLittleLong(&ctx);

View file

@ -45,7 +45,7 @@ typedef struct {
int height;
int fullscreen; //0 = windowed. 1 = fullscreen (mode changes). 2 = borderless+maximized
qboolean stereo;
qboolean srgb;
int srgb; //<0 = gamma-only. 0 = no srgb at all, >0 full srgb, including textures and stuff
int bpp; //16, 24(aka 32), 30, and 48 are meaningful
int rate;
int wait; //-1 = default, 0 = off, 1 = on, 2 = every other
@ -125,9 +125,6 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette);
// the palette data will go away after the call, so it must be copied off if
// the video driver will need it again
void GLVID_Shutdown (void);
// Called at shutdown
void GLVID_Crashed(void);
void GLVID_Update (vrect_t *rects);

View file

@ -95,6 +95,7 @@ cvar_t v_ringcshift = CVAR("v_ringcshift", "1");
cvar_t v_pentcshift = CVAR("v_pentcshift", "1");
cvar_t v_gunkick = CVAR("v_gunkick", "0");
cvar_t v_gunkick_q2 = CVAR("v_gunkick_q2", "1");
cvar_t v_viewmodel_quake = CVARD("r_viewmodel_quake", "0", "Controls whether to use weird viewmodel movements from vanilla quake."); //name comes from MarkV.
cvar_t v_viewheight = CVAR("v_viewheight", "0");
cvar_t v_projectionmode = CVAR("v_projectionmode", "0");
@ -1002,7 +1003,7 @@ void V_CalcGunPositionAngle (playerview_t *pv, float bob)
// fudge position around to keep amount of weapon visible
// roughly equal with different FOV
//FIXME: should use y fov, not viewsize.
if (r_refdef.drawsbar) //no sbar = no viewsize cvar.
if (r_refdef.drawsbar && v_viewmodel_quake.ival) //no sbar = no viewsize cvar.
{
if (scr_viewsize.value == 110)
pv->vw_origin[2] += 1;

View file

@ -773,7 +773,9 @@ void Cmd_Exec_f (void)
}
#ifndef QUAKETC
//hack to try to work around nquake's b0rkedness
if (!strncmp(s, "// ", 3))
if (!strncmp(s, "// This is nQuake's Frogbot config", 33))
s = "echo Refusing to exec nQuake's Frogbot config"; //otherwise many people with nquake installed will be fucked over whenever they try playing singleplayer
else if (!strncmp(s, "// ", 3))
{
char *eol = strstr(s, "\n");
if (eol)
@ -4052,6 +4054,8 @@ void Cmd_Shutdown(void)
}
}
Cmd_Complete(NULL, false); //NULL frees any cached results without generating new ones.
while(cmd_functions)
{
c = cmd_functions;

View file

@ -3118,7 +3118,9 @@ const gamemode_info_t gamemode_info[] = {
//for quake, we also allow extracting all files from paks. some people think it loads faster that way or something.
#ifndef NOLEGACY
//cmdline switch exename protocol name(dpmaster) identifying file exec dir1 dir2 dir3 dir(fte) full name
{"-quake", "q1", "FTE-Quake DarkPlaces-Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1", "qw", "*fte"}, "Quake", "https://fte.triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
//two quakes - one without extra game dirs which should avoid fuckups from nquake's configs (which screw over cvars that every nq progs.dat depends upon but which the ezquake id1-only less-compatible gamecode ignores).
{"-quake", "qw", "FTE-Quake DarkPlaces-Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1", "qw", "*fte"}, "Quake", "https://fte.triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
{"-netquake", "q1", "FTE-Quake DarkPlaces-Quake", {"id1/pak0.pak", "id1/quake.rc"},QCFG, {"id1"}, "Quake", "https://fte.triptohell.info/downloadables.php" /*,"id1/pak0.pak|http://quakeservers.nquake.com/qsw106.zip|http://nquake.localghost.net/qsw106.zip|http://qw.quakephil.com/nquake/qsw106.zip|http://fnu.nquake.com/qsw106.zip"*/},
//quake's mission packs should not be favoured over the base game nor autodetected
//third part mods also tend to depend upon the mission packs for their huds, even if they don't use any other content.
//and q2 also has a rogue/pak0.pak file that we don't want to find and cause quake2 to look like dissolution of eternity

View file

@ -120,6 +120,8 @@ typedef struct {
qboolean slidyslopes;
int stepheight;
qbyte coordsize;
unsigned int flags;
} movevars_t;

View file

@ -92,6 +92,10 @@ void PF_Common_RegisterCvars(void)
#endif
WPhys_Init();
#ifdef ENGINE_ROUTING
PR_Route_Init();
#endif
}
qofs_t PR_ReadBytesString(char *str)
@ -6227,6 +6231,9 @@ void PR_Common_Shutdown(pubprogfuncs_t *progs, qboolean errored)
#endif
PR_fclose_progs(progs);
search_close_progs(progs, !errored);
#ifdef ENGINE_ROUTING
PR_Route_Shutdown (progs->parms->user);
#endif
#ifdef TEXTEDITOR
Editor_ProgsKilled(progs);
#endif

View file

@ -80,6 +80,14 @@ int MP_TranslateFTEtoQCCodes(int code);
int MP_TranslateQCtoFTECodes(int code);
qboolean WPhys_Push (world_t *w, wedict_t *pusher, vec3_t move, vec3_t amove);
#ifdef ENGINE_ROUTING
//sv_move.c routing
void QCBUILTIN PF_route_calculate (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void PR_Route_Shutdown (world_t *world);
void PR_Route_Visualise (void);
void PR_Route_Init (void);
#endif
//pr_cmds.c builtins that need to be moved to a common.
void VARGS PR_BIError(pubprogfuncs_t *progfuncs, char *format, ...) LIKEPRINTF(2);
void QCBUILTIN PF_print (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);

View file

@ -264,6 +264,10 @@ struct world_s
qboolean rbe_hasphysicsents;
rigidbodyengine_t *rbe;
#endif
#ifdef ENGINE_ROUTING
void *waypoints;
#endif
};
typedef struct world_s world_t;

View file

@ -672,18 +672,9 @@ static void D3D11BE_ApplyShaderBits(unsigned int bits, void **blendstatecache)
*/
}
if (delta & (SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY|SBITS_MISC_NODEPTHTEST|SBITS_MISC_DEPTHWRITE))
if (delta & (SBITS_DEPTHFUNC_BITS|SBITS_MISC_NODEPTHTEST|SBITS_MISC_DEPTHWRITE))
{
unsigned int key = 0;
if (bits & SBITS_MISC_DEPTHEQUALONLY)
key |= 1u<<0;
if (bits & SBITS_MISC_DEPTHCLOSERONLY)
key |= 1u<<1;
if (bits & SBITS_MISC_NODEPTHTEST)
key |= 1u<<2;
if (bits & SBITS_MISC_DEPTHWRITE)
key |= 1u<<3;
unsigned int key = (bits&(SBITS_DEPTHFUNC_BITS|SBITS_MISC_NODEPTHTEST|SBITS_MISC_DEPTHWRITE))>>16;
if (shaderstate.depthstates[key])
ID3D11DeviceContext_OMSetDepthStencilState(d3ddevctx, shaderstate.depthstates[key], 0);
else
@ -698,18 +689,21 @@ static void D3D11BE_ApplyShaderBits(unsigned int bits, void **blendstatecache)
else
depthdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
switch(bits & (SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY))
switch(bits & SBITS_DEPTHFUNC_BITS)
{
default:
case 0:
case SBITS_DEPTHFUNC_CLOSEREQUAL:
depthdesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;
break;
case SBITS_MISC_DEPTHEQUALONLY:
case SBITS_DEPTHFUNC_EQUAL:
depthdesc.DepthFunc = D3D11_COMPARISON_EQUAL;
break;
case SBITS_MISC_DEPTHCLOSERONLY:
case SBITS_DEPTHFUNC_CLOSER:
depthdesc.DepthFunc = D3D11_COMPARISON_LESS;
break;
case SBITS_DEPTHFUNC_FURTHER:
depthdesc.DepthFunc = D3D11_COMPARISON_GREATER;
break;
}
//make sure the stencil part is actually valid, even if we're not using it.

View file

@ -394,20 +394,23 @@ static void BE_ApplyShaderBits(unsigned int bits)
IDirect3DDevice8_SetRenderState(pD3DDev8, D3DRS_ZENABLE, TRUE);
}
if (delta & (SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY))
if (delta & SBITS_DEPTHFUNC_BITS)
{
switch(bits & (SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY))
switch(bits & SBITS_DEPTHFUNC_BITS)
{
default:
case 0:
case SBITS_DEPTHFUNC_CLOSEREQUAL:
IDirect3DDevice8_SetRenderState(pD3DDev8, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
break;
case SBITS_MISC_DEPTHEQUALONLY:
case SBITS_DEPTHFUNC_EQUAL:
IDirect3DDevice8_SetRenderState(pD3DDev8, D3DRS_ZFUNC, D3DCMP_EQUAL);
break;
case SBITS_MISC_DEPTHCLOSERONLY:
case SBITS_DEPTHFUNC_CLOSER:
IDirect3DDevice8_SetRenderState(pD3DDev8, D3DRS_ZFUNC, D3DCMP_LESS);
break;
case SBITS_DEPTHFUNC_FURTHER:
IDirect3DDevice8_SetRenderState(pD3DDev8, D3DRS_ZFUNC, D3DCMP_GREATER);
break;
}
}

View file

@ -464,20 +464,23 @@ static void BE_ApplyShaderBits(unsigned int bits)
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ZENABLE, TRUE);
}
if (delta & (SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY))
if (delta & SBITS_DEPTHFUNC_BITS)
{
switch(bits & (SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY))
switch(bits & SBITS_DEPTHFUNC_BITS)
{
default:
case 0:
case SBITS_DEPTHFUNC_CLOSEREQUAL:
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
break;
case SBITS_MISC_DEPTHEQUALONLY:
case SBITS_DEPTHFUNC_EQUAL:
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ZFUNC, D3DCMP_EQUAL);
break;
case SBITS_MISC_DEPTHCLOSERONLY:
case SBITS_DEPTHFUNC_CLOSER:
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ZFUNC, D3DCMP_LESS);
break;
case SBITS_DEPTHFUNC_FURTHER:
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ZFUNC, D3DCMP_GREATER);
break;
}
}
@ -2679,7 +2682,7 @@ static void BE_DrawMeshChain_Internal(void)
IDirect3DDevice9_SetTextureStageState(pD3DDev9, passno, D3DTSS_ALPHAARG1, D3DTA_CONSTANT);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, passno, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, passno, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
BE_ApplyShaderBits(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | (useshader->numpasses?SBITS_MISC_DEPTHEQUALONLY:0));
BE_ApplyShaderBits(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | (useshader->numpasses?SBITS_DEPTHFUNC_EQUAL:0));
allocvertexbuffer(shaderstate.dynst_buff[passno], shaderstate.dynst_size, &shaderstate.dynst_offs[passno], &map, vertcount*sizeof(vec2_t));
for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++)
@ -2754,7 +2757,7 @@ static void BE_DrawMeshChain_Internal(void)
IDirect3DDevice9_SetTextureStageState(pD3DDev9, passno, D3DTSS_ALPHAARG1, D3DTA_CONSTANT);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, passno, D3DTSS_ALPHAARG2, D3DTA_TEXTURE);
IDirect3DDevice9_SetTextureStageState(pD3DDev9, passno, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
BE_ApplyShaderBits(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | (useshader->numpasses?SBITS_MISC_DEPTHEQUALONLY:0));
BE_ApplyShaderBits(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | (useshader->numpasses?SBITS_DEPTHFUNC_EQUAL:0));
allocvertexbuffer(shaderstate.dynst_buff[passno], shaderstate.dynst_size, &shaderstate.dynst_offs[passno], &map, vertcount*sizeof(vec2_t));
for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++)
@ -3542,7 +3545,7 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist)
if (R_DrawSkyChain (batch))
continue;
}
else if (shaderstate.mode != BEM_FOG && shaderstate.mode != BEM_CREPUSCULAR && shaderstate.mode != BEM_WIREFRAME)
else if (/*shaderstate.mode != BEM_FOG &&*/ shaderstate.mode != BEM_CREPUSCULAR && shaderstate.mode != BEM_WIREFRAME)
continue;
}

View file

@ -2737,6 +2737,7 @@ static void BE_GenPolyBatches(batch_t **batches)
}
}
void R_HalfLife_GenerateBatches(entity_t *e, batch_t **batches);
void PR_Route_Visualise(void);
void BE_GenModelBatches(batch_t **batches, const dlight_t *dl, unsigned int bemode)
{
int i;
@ -2766,6 +2767,9 @@ void BE_GenModelBatches(batch_t **batches, const dlight_t *dl, unsigned int bemo
#ifndef CLIENTONLY
SV_AddDebugPolygons();
#endif
#ifdef ENGINE_ROUTING
PR_Route_Visualise();
#endif
//the alias cache is a backend thing that provides support for multiple entities using the same skeleton.
//thus it needs to be cleared so that it won't reuse the cache over multiple frames.

View file

@ -1036,7 +1036,7 @@ static void RevertToKnownState(void)
}
#endif
shaderstate.shaderbits &= ~(SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY|SBITS_MASK_BITS|SBITS_AFFINE);
shaderstate.shaderbits &= ~(SBITS_DEPTHFUNC_BITS|SBITS_MASK_BITS|SBITS_AFFINE);
shaderstate.shaderbits |= SBITS_MISC_DEPTHWRITE;
shaderstate.shaderbits &= ~(SBITS_BLEND_BITS);
@ -1528,27 +1528,13 @@ void GLBE_Shutdown(void)
//on vid_reload, the gl drivers might have various things bound that have since been destroyed/etc
//so reset that state to avoid any issues with state
/*shaderstate.sourcevbo = &shaderstate.dummyvbo;
memset(shaderstate.sourcevbo, 0, sizeof(*shaderstate.sourcevbo));
shaderstate.pendingcolourvbo = 0;
shaderstate.pendingcolourpointer = NULL;
shaderstate.pendingvertexvbo = 0;
shaderstate.pendingvertexpointer = NULL;
for (u = 0; u < SHADER_TMU_MAX; u++)
{
shaderstate.pendingtexcoordparts[u] = 0;
shaderstate.pendingtexcoordvbo[u] = 0;
shaderstate.pendingtexcoordpointer[u] = NULL;
}*/
if (sh_config.progs_supported)
BE_ApplyAttributes(0, (1u<<VATTR_LEG_FIRST)-1u);
if (!sh_config.progs_required)
BE_ApplyAttributes(0, (1u<<VATTR_LEG_VERTEX)|
(1u<<VATTR_LEG_COLOUR)|
(1u<<VATTR_LEG_ELEMENTS)|
((1u<<(VATTR_LEG_TMU0+be_maxpasses))-1));
BE_EnableShaderAttributes(0, 0);
GL_SelectVBO(0);
GL_SelectEBO(0);
for (u = 0; u < countof(shaderstate.currenttextures); u++)
GL_LazyBind(u, 0, r_nulltex);
GL_SelectTexture(0);
}
void GLBE_Init(void)
@ -2883,7 +2869,7 @@ static void BE_SendPassBlendDepthMask(unsigned int sbits)
#ifdef warningmsg
#pragma warningmsg("fixme: q3 doesn't seem to have this, why do we need it?")
#endif
sbits &= ~(SBITS_MISC_DEPTHWRITE|SBITS_MISC_DEPTHEQUALONLY);
sbits &= ~(SBITS_MISC_DEPTHWRITE|SBITS_DEPTHFUNC_BITS);
sbits |= SBITS_MISC_NODEPTHTEST;
}
if (shaderstate.flags & (BEF_FORCEADDITIVE|BEF_FORCETRANSPARENT|BEF_FORCENODEPTH|BEF_FORCEDEPTHTEST|BEF_FORCEDEPTHWRITE))
@ -2994,27 +2980,28 @@ static void BE_SendPassBlendDepthMask(unsigned int sbits)
else
qglDepthMask(GL_FALSE);
}
if (delta & (SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY))
if (delta & (SBITS_DEPTHFUNC_BITS))
{
extern int gldepthfunc;
switch (sbits & (SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY))
switch (sbits & SBITS_DEPTHFUNC_BITS)
{
case SBITS_MISC_DEPTHEQUALONLY:
case SBITS_DEPTHFUNC_EQUAL:
qglDepthFunc(GL_EQUAL);
break;
case SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY:
case SBITS_DEPTHFUNC_FURTHER:
if (gldepthfunc == GL_LEQUAL)
qglDepthFunc(GL_GREATER);
else
qglDepthFunc(GL_LESS);
break;
case SBITS_MISC_DEPTHCLOSERONLY:
case SBITS_DEPTHFUNC_CLOSER:
if (gldepthfunc == GL_LEQUAL)
qglDepthFunc(GL_LESS);
else
qglDepthFunc(GL_GREATER);
break;
default:
case SBITS_DEPTHFUNC_CLOSEREQUAL:
qglDepthFunc(gldepthfunc);
break;
}
@ -3959,7 +3946,7 @@ void GLBE_SelectMode(backendmode_t mode)
#endif
//we don't write or blend anything (maybe alpha test... but mneh)
BE_SendPassBlendDepthMask(SBITS_MISC_DEPTHCLOSERONLY | SBITS_MASK_BITS);
BE_SendPassBlendDepthMask(SBITS_DEPTHFUNC_CLOSER | SBITS_MASK_BITS);
GL_CullFace(0);
//don't change cull stuff, and
@ -4006,7 +3993,7 @@ void GLBE_SelectMode(backendmode_t mode)
if (!gl_config_nofixedfunc)
BE_SetPassBlendMode(0, PBM_MODULATE);
#endif
BE_SendPassBlendDepthMask(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | SBITS_MISC_DEPTHEQUALONLY);
BE_SendPassBlendDepthMask(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | SBITS_DEPTHFUNC_EQUAL);
break;
}
}
@ -4708,7 +4695,7 @@ static void DrawMeshes(void)
shaderstate.pendingcolourvbo = 0;
shaderstate.pendingcolourpointer = NULL;
BE_SetPassBlendMode(0, PBM_MODULATE);
BE_SendPassBlendDepthMask(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | (shaderstate.curshader->numpasses?SBITS_MISC_DEPTHEQUALONLY:0));
BE_SendPassBlendDepthMask(SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | (shaderstate.curshader->numpasses?SBITS_DEPTHFUNC_EQUAL:0));
GenerateTCFog(0, shaderstate.curbatch->fog);
BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR) | (1u<<VATTR_LEG_TMU0), 0);
@ -5126,7 +5113,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
if (R_DrawSkyChain(batch))
continue;
}
else if (shaderstate.mode != BEM_FOG && shaderstate.mode != BEM_CREPUSCULAR && shaderstate.mode != BEM_WIREFRAME)
else if (/*shaderstate.mode != BEM_FOG &&*/ shaderstate.mode != BEM_CREPUSCULAR && shaderstate.mode != BEM_WIREFRAME)
continue;
}

View file

@ -386,22 +386,17 @@ void GLDraw_Init (void)
if ((vid.flags & VID_SRGB_CAPABLE) && gl_config.arb_framebuffer_srgb)
{ //srgb-capable
if (!vid_srgb.ival)
{ //srgb not wanted...
{ //srgb framebuffer not wanted...
qglDisable(GL_FRAMEBUFFER_SRGB);
vid.flags &= ~VID_SRGB_FB_LINEAR;
}
else if (vid_srgb.ival > 1)
{ //full srgb wanted
qglEnable(GL_FRAMEBUFFER_SRGB);
vid.flags |= VID_SRGB_FB_LINEAR;
}
else
{ //srgb wanted only for the framebuffer, for gamma tricks.
{
vid.flags |= VID_SRGB_FB_LINEAR;
qglEnable(GL_FRAMEBUFFER_SRGB);
}
}
if ((vid.flags & VID_SRGB_FB) && vid_srgb.ival != 1)
if ((vid.flags & VID_SRGB_FB) && vid_srgb.ival >= 0)
vid.flags |= VID_SRGBAWARE;
else
vid.flags &= ~VID_SRGBAWARE;

View file

@ -2301,6 +2301,8 @@ qboolean Mod_LoadVertexNormals (model_t *loadmodel, qbyte *mod_base, lump_t *l)
float *out;
int i, count;
if (l)
{
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(vec3_t))
{
@ -2308,6 +2310,15 @@ qboolean Mod_LoadVertexNormals (model_t *loadmodel, qbyte *mod_base, lump_t *l)
return false;
}
count = l->filelen / sizeof(vec3_t);
}
else
{
in = Q1BSPX_FindLump("VERTEXNORMALS", &count);
if (in)
count /= sizeof(vec3_t);
else
count = 0;
}
if (count != loadmodel->numvertexes)
return false; //invalid number of verts there, can't use this.

View file

@ -77,12 +77,12 @@ qboolean GLSCR_UpdateScreen (void)
//vid_srgb can be changed between 0 and 1, but other values need texture reloads. do that without too much extra weirdness.
if ((vid.flags & VID_SRGB_CAPABLE) && gl_config.arb_framebuffer_srgb)
{ //srgb-capable
if (vid_srgb.ival > 1 && (vid.flags & VID_SRGBAWARE))
if (vid_srgb.ival > 0 && (vid.flags & VID_SRGBAWARE))
{ //full srgb wanted (and textures are loaded)
qglEnable(GL_FRAMEBUFFER_SRGB);
vid.flags |= VID_SRGB_FB_LINEAR;
}
else if (vid_srgb.ival==1 || (vid.flags & VID_SRGBAWARE))
else if (vid_srgb.ival < 0 || (vid.flags & VID_SRGBAWARE))
{ //srgb wanted only for the framebuffer, for gamma tricks.
qglEnable(GL_FRAMEBUFFER_SRGB);
vid.flags |= VID_SRGB_FB_LINEAR;

View file

@ -216,18 +216,20 @@ static float Shader_FloatArgument(shader_t *shader, char *arg)
#define HASH_SIZE 128
enum shaderparsemode_e
{
SPM_DEFAULT, /*quake3/fte internal*/
SPM_DOOM3,
};
#define SPF_DEFAULT 0u /*quake3/fte internal*/
#define SPF_PROGRAMIFY (1u<<0) /*quake3/fte internal*/
#define SPF_DOOM3 (1u<<1) /*any commands, args, etc, should be interpretted according to doom3's norms*/
static struct
typedef struct
{
enum shaderparsemode_e mode;
shader_t *s; //the shader we're parsing
shaderpass_t *pass; //the pass we're currently parsing
char *ptr; //the src file pointer we're at
const char *forcedshader;
unsigned int parseflags; //SPF_*
qboolean droppass;
qboolean forceprogramify;
//for dpwater compat, used to generate a program
int dpwatertype;
float reflectmin;
@ -244,7 +246,8 @@ static struct
float offsetmappingbias;
float specularexpscale; //*32 ish
float specularvalscale; //*1 ish
} parsestate;
} parsestate_t;
static parsestate_t parsestate; //FIXME
typedef struct shaderkey_s
{
@ -255,7 +258,8 @@ typedef struct shaderkey_s
typedef struct shadercachefile_s {
char *data;
size_t length;
enum shaderparsemode_e parsemode;
unsigned int parseflags;
char forcedshadername[64];
struct shadercachefile_s *next;
char name[1];
} shadercachefile_t;
@ -279,11 +283,11 @@ void *shader_active_hash_mem;
//static float r_skyheight;
char *Shader_Skip( char *ptr );
static qboolean Shader_Parsetok(shader_t *shader, shaderpass_t *pass, shaderkey_t *keys, char *token, char **ptr);
static qboolean Shader_Parsetok(parsestate_t *ps, shaderkey_t *keys, char *token);
static void Shader_ParseFunc(shader_t *shader, char **args, shaderfunc_t *func);
static void Shader_MakeCache(const char *path);
static qboolean Shader_LocateSource(char *name, char **buf, size_t *bufsize, size_t *offset, enum shaderparsemode_e *parsemode);
static void Shader_ReadShader(shader_t *s, char *shadersource, int parsemode);
static void Shader_MakeCache(const char *path, unsigned int parseflags);
static qboolean Shader_LocateSource(char *name, char **buf, size_t *bufsize, size_t *offset, shadercachefile_t **sourcefile);
static void Shader_ReadShader(shader_t *s, char *shadersource, shadercachefile_t *sourcefile);
static qboolean Shader_ParseShader(char *parsename, shader_t *s);
//===========================================================================
@ -794,7 +798,7 @@ texid_t R_LoadColourmapImage(void)
static texid_t Shader_FindImage ( char *name, int flags )
{
extern texid_t missing_texture_normal;
if (parsestate.mode == SPM_DOOM3)
if (parsestate.parseflags & SPF_DOOM3)
{
if (!Q_stricmp (name, "_default"))
return r_whiteimage; /*fixme*/
@ -2437,7 +2441,7 @@ static void Shader_DP_Camera(shader_t *shader, shaderpass_t *pass, char **ptr)
}
static void Shader_DP_Water(shader_t *shader, shaderpass_t *pass, char **ptr)
{
parsestate.forceprogramify = true;
parsestate.parseflags |= SPF_PROGRAMIFY;
parsestate.dpwatertype |= 3;
parsestate.reflectmin = Shader_ParseFloat(shader, ptr, 0);
@ -2450,7 +2454,7 @@ static void Shader_DP_Water(shader_t *shader, shaderpass_t *pass, char **ptr)
}
static void Shader_DP_Reflect(shader_t *shader, shaderpass_t *pass, char **ptr)
{
parsestate.forceprogramify = true;
parsestate.parseflags |= SPF_PROGRAMIFY;
parsestate.dpwatertype |= 1;
parsestate.reflectmin = 1;
@ -2460,7 +2464,7 @@ static void Shader_DP_Reflect(shader_t *shader, shaderpass_t *pass, char **ptr)
}
static void Shader_DP_Refract(shader_t *shader, shaderpass_t *pass, char **ptr)
{
parsestate.forceprogramify = true;
parsestate.parseflags |= SPF_PROGRAMIFY;
parsestate.dpwatertype |= 2;
parsestate.refractfactor = Shader_ParseFloat(shader, ptr, 0);
@ -3339,17 +3343,25 @@ static void Shaderpass_DepthFunc (shader_t *shader, shaderpass_t *pass, char **p
{
char *token;
pass->shaderbits &= ~(SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY);
pass->shaderbits &= ~(SBITS_DEPTHFUNC_BITS);
token = Shader_ParseString (ptr);
if (!Q_stricmp (token, "equal"))
pass->shaderbits |= SBITS_MISC_DEPTHEQUALONLY;
pass->shaderbits |= SBITS_DEPTHFUNC_EQUAL;
else if (!Q_stricmp (token, "lequal"))
; //default
pass->shaderbits |= SBITS_DEPTHFUNC_CLOSEREQUAL; //default
else if (!Q_stricmp (token, "less"))
pass->shaderbits |= SBITS_MISC_DEPTHCLOSERONLY;
pass->shaderbits |= SBITS_DEPTHFUNC_CLOSER;
else if (!Q_stricmp (token, "greater"))
pass->shaderbits |= SBITS_MISC_DEPTHCLOSERONLY|SBITS_MISC_DEPTHEQUALONLY;
pass->shaderbits |= SBITS_DEPTHFUNC_FURTHER;
// else if (!Q_stricmp (token, "gequal"))
// pass->shaderbits |= SBITS_DEPTHFUNC_FURTHEREQUAL;
// else if (!Q_stricmp (token, "nequal"))
// pass->shaderbits |= SBITS_DEPTHFUNC_NOTEQUAL;
// else if (!Q_stricmp (token, "never"))
// pass->shaderbits |= SBITS_DEPTHFUNC_NEVER;
// else if (!Q_stricmp (token, "always"))
// pass->shaderbits |= SBITS_DEPTHFUNC_ALWAYS;
else
Con_DPrintf("Invalid depth func %s\n", token);
}
@ -3799,7 +3811,12 @@ void Shader_Free (shader_t *shader)
int QDECL Shader_InitCallback (const char *name, qofs_t size, time_t mtime, void *param, searchpathfuncs_t *spath)
{
Shader_MakeCache(name);
Shader_MakeCache(name, SPF_DEFAULT);
return true;
}
int QDECL Shader_InitCallback_Doom3 (const char *name, qofs_t size, time_t mtime, void *param, searchpathfuncs_t *spath)
{
Shader_MakeCache(name, SPF_DOOM3);
return true;
}
@ -3879,7 +3896,7 @@ void Shader_FlushCache(void)
}
}
static void Shader_MakeCache(const char *path)
static void Shader_MakeCache(const char *path, unsigned int parseflags)
{
unsigned int key;
char *buf, *ptr, *token;
@ -3901,6 +3918,7 @@ static void Shader_MakeCache(const char *path)
strcpy(cachefile->name, path);
size = FS_LoadFile(path, (void **)&cachefile->data);
cachefile->length = size;
cachefile->parseflags = parseflags;
if (filelink)
filelink->next = cachefile;
else
@ -3923,6 +3941,59 @@ static void Shader_MakeCache(const char *path)
ptr = buf = cachefile->data;
size = cachefile->length;
//look for meta comments.
while (1)
{
//parse metas
while (*ptr == ' ' || *ptr == '\t')
ptr++;
if (ptr[0] == '\r' && ptr[1] == '\n')
ptr+=2; //blank line with dos ending
else if (ptr[0] == '\r' || ptr[0] == '\n')
ptr+=1; //blank line with mac or unix ending
else if (ptr[0] == '/' && ptr[1] == '/')
{
char *e = strchr(ptr, '\n');
if (e)
e++;
else
e = ptr + strlen(ptr);
ptr += 2;
while (*ptr == ' ' || *ptr == '\t')
ptr++;
if (!strncmp(ptr, "meta:", 5))
{
ptr+=5;
token = COM_ParseExt (&ptr, false, true);
if (!strcmp(token, "forceprogramify"))
{
cachefile->parseflags |= SPF_PROGRAMIFY;
token = COM_ParseExt (&ptr, false, true);
if (*token)
Q_strncpyz(cachefile->forcedshadername, token, sizeof(cachefile->forcedshadername));
}
else
Con_DPrintf("unknown shader meta term \"%s\" in %s\n", token, name);
while (*ptr == ' ' || *ptr == '\t')
ptr++;
if (*ptr != '\r' && *ptr != '\n')
{
while (*ptr && (*ptr != '\r' && *ptr != '\n'))
ptr++;
Con_DPrintf("junk after shader meta in %s\n", name);
}
}
ptr = e;
}
else
break; //the actual shader started.
}
//now scan the file looking for each individual shader.
do
{
if ( ptr - buf >= size )
@ -3954,7 +4025,7 @@ static void Shader_MakeCache(const char *path)
} while ( ptr );
}
static qboolean Shader_LocateSource(char *name, char **buf, size_t *bufsize, size_t *offset, enum shaderparsemode_e *parsemode)
static qboolean Shader_LocateSource(char *name, char **buf, size_t *bufsize, size_t *offset, shadercachefile_t **sourcefile)
{
unsigned int key;
shadercache_t *cache;
@ -3971,7 +4042,7 @@ static qboolean Shader_LocateSource(char *name, char **buf, size_t *bufsize, siz
*buf = cache->source->data;
*bufsize = cache->source->length;
*offset = cache->offset;
*parsemode = cache->source->parsemode;
*sourcefile = cache->source;
}
return true;
}
@ -4333,8 +4404,9 @@ static qboolean Shader_Conditional_Read(shader_t *shader, struct scondinfo_s *co
return true;
}
void Shader_Readpass (shader_t *shader, char **ptr)
void Shader_Readpass (parsestate_t *ps)
{
shader_t *shader = ps->s;
char *token;
shaderpass_t *pass;
static shader_t dummy;
@ -4368,21 +4440,23 @@ void Shader_Readpass (shader_t *shader, char **ptr)
if (shader->flags & SHADER_NOMIPMAPS)
pass->flags |= SHADER_PASS_NOMIPMAP;
while ( *ptr )
ps->pass = pass;
while ( ps->ptr )
{
token = COM_ParseExt (ptr, true, true);
token = COM_ParseExt (&ps->ptr, true, true);
if ( !token[0] )
{
continue;
}
else if (!Shader_Conditional_Read(shader, &cond, token, ptr))
else if (!Shader_Conditional_Read(shader, &cond, token, &ps->ptr))
{
if ( token[0] == '}' )
break;
else if (token[0] == '{')
Con_Printf("unexpected indentation in %s\n", shader->name);
else if ( Shader_Parsetok (shader, pass, shaderpasskeys, token, ptr) )
else if ( Shader_Parsetok (ps, shaderpasskeys, token) )
break;
}
}
@ -4479,11 +4553,12 @@ void Shader_Readpass (shader_t *shader, char **ptr)
shader->numpasses--;
}
shader->flags = oldflags;
return;
}
ps->pass = NULL;
}
static qboolean Shader_Parsetok (shader_t *shader, shaderpass_t *pass, shaderkey_t *keys, char *token, char **ptr)
//we've read the first token, now make sense of it and any args
static qboolean Shader_Parsetok(parsestate_t *ps, shaderkey_t *keys, char *token)
{
shaderkey_t *key;
char *prefix;
@ -4513,9 +4588,9 @@ static qboolean Shader_Parsetok (shader_t *shader, shaderpass_t *pass, shaderkey
if (!prefix || (prefix && key->prefix && !Q_strncasecmp(prefix, key->prefix, strlen(key->prefix))))
{
if (key->func)
key->func ( shader, pass, ptr );
key->func ( ps->s, ps->pass, &ps->ptr );
return ( ptr && *ptr && **ptr == '}' );
return (ps->ptr && *ps->ptr == '}' );
}
}
}
@ -4523,15 +4598,15 @@ static qboolean Shader_Parsetok (shader_t *shader, shaderpass_t *pass, shaderkey
if (!toolchainprefix) //we don't really give a damn about prefixes owned by various toolchains - they shouldn't affect us.
{
if (prefix)
Con_DPrintf("Unknown shader directive parsing %s: \"%s\"\n", shader->name, prefix);
Con_DPrintf("Unknown shader directive parsing %s: \"%s\"\n", ps->s->name, prefix);
else
Con_DPrintf("Unknown shader directive parsing %s: \"%s\"\n", shader->name, token);
Con_DPrintf("Unknown shader directive parsing %s: \"%s\"\n", ps->s->name, token);
}
// Next Line
while (ptr)
while (ps->ptr)
{
token = COM_ParseExt(ptr, false, true);
token = COM_ParseExt(&ps->ptr, false, true);
if ( !token[0] )
{
break;
@ -4563,7 +4638,7 @@ void Shader_SetPassFlush (shaderpass_t *pass, shaderpass_t *pass2)
return;
/*rgbgen must be identity too except if the later pass is identity_ligting, in which case all is well and we can switch the first pass to identity_lighting instead*/
if (pass2->rgbgen == RGB_GEN_IDENTITY_LIGHTING && pass2->blendmode == PBM_MODULATE && pass->rgbgen == RGB_GEN_IDENTITY)
if (pass2->rgbgen == RGB_GEN_IDENTITY_LIGHTING && (pass2->blendmode == PBM_OVERBRIGHT || pass2->blendmode == PBM_MODULATE) && pass->rgbgen == RGB_GEN_IDENTITY)
{
if (pass->blendmode == PBM_REPLACE)
pass->blendmode = PBM_REPLACELIGHT;
@ -4574,8 +4649,8 @@ void Shader_SetPassFlush (shaderpass_t *pass, shaderpass_t *pass2)
else if (pass2->rgbgen != RGB_GEN_IDENTITY || (pass->rgbgen != RGB_GEN_IDENTITY && pass->rgbgen != RGB_GEN_IDENTITY_LIGHTING))
return;
/*if its alphatest, don't merge with anything other than lightmap*/
if ((pass->shaderbits & SBITS_ATEST_BITS) && (!(pass2->shaderbits & SBITS_MISC_DEPTHEQUALONLY) || pass2->texgen != T_GEN_LIGHTMAP))
/*if its alphatest, don't merge with anything other than lightmap (although equal stuff can be merged)*/
if ((pass->shaderbits & SBITS_ATEST_BITS) && (((pass2->shaderbits & SBITS_DEPTHFUNC_BITS) != SBITS_DEPTHFUNC_EQUAL) || pass2->texgen != T_GEN_LIGHTMAP))
return;
if ((pass->shaderbits & SBITS_MASK_BITS) != (pass2->shaderbits & SBITS_MASK_BITS))
@ -4655,7 +4730,7 @@ const char *Shader_AlphaMaskProgArgs(shader_t *s)
void Shader_Programify (shader_t *s)
{
unsigned int reflectrefract = 0;
char *prog = NULL;
const char *prog = NULL;
const char *mask;
char args[1024];
qboolean eightbit = false;
@ -4699,7 +4774,9 @@ void Shader_Programify (shader_t *s)
return;*/
}
if (parsestate.dpwatertype)
if (parsestate.forcedshader)
prog = parsestate.forcedshader;
else if (parsestate.dpwatertype)
{
prog = va("altwater%s#USEMODS#FRESNEL_EXP=2.0"
//variable parts
@ -4717,7 +4794,7 @@ void Shader_Programify (shader_t *s)
parsestate.wateralpha
);
//clear out blending and force regular depth.
s->passes[0].shaderbits &= ~(SBITS_BLEND_BITS|SBITS_MISC_NODEPTHTEST|SBITS_MISC_DEPTHEQUALONLY|SBITS_MISC_DEPTHCLOSERONLY);
s->passes[0].shaderbits &= ~(SBITS_BLEND_BITS|SBITS_MISC_NODEPTHTEST|SBITS_DEPTHFUNC_BITS);
s->passes[0].shaderbits |= SBITS_MISC_DEPTHWRITE;
if (parsestate.dpwatertype & 1)
@ -4733,7 +4810,6 @@ void Shader_Programify (shader_t *s)
}
else if (modellighting)
{
pass = modellighting;
eightbit = r_softwarebanding && (qrenderer == QR_OPENGL) && sh_config.progs_supported;
if (eightbit)
prog = "defaultskin#EIGHTBIT";
@ -4742,7 +4818,6 @@ void Shader_Programify (shader_t *s)
}
else if (lightmap)
{
pass = modellighting;
eightbit = r_softwarebanding && (qrenderer == QR_OPENGL || qrenderer == QR_VULKAN) && sh_config.progs_supported;
if (eightbit)
prog = "defaultwall#EIGHTBIT";
@ -4750,14 +4825,20 @@ void Shader_Programify (shader_t *s)
prog = "defaultwall";
}
else if (vertexlighting)
{
if (r_forceprogramify.ival < 0)
prog = "defaultfill";
else
{
pass = vertexlighting;
prog = "default2d";
}
}
else
{
pass = NULL;
prog = "default2d";
if (r_forceprogramify.ival < 0)
prog = "defaultfill";
else
return;
}
@ -5231,7 +5312,7 @@ done:;
}
}
if (!s->prog && sh_config.progs_supported && (r_forceprogramify.ival || parsestate.forceprogramify))
if (!s->prog && sh_config.progs_supported && (r_forceprogramify.ival || (parsestate.parseflags & SPF_PROGRAMIFY)))
{
if (r_forceprogramify.ival >= 2)
{
@ -5239,7 +5320,7 @@ done:;
s->passes[0].numtcmods = 0; //DP sucks and doesn't use normalized texture coords *if* there's a shader specified. so lets ignore any extra scaling that this imposes.
if (s->passes[0].shaderbits & SBITS_ATEST_BITS) //mimic DP's limited alphafunc support
s->passes[0].shaderbits = (s->passes[0].shaderbits & ~SBITS_ATEST_BITS) | SBITS_ATEST_GE128;
s->passes[0].shaderbits &= ~SBITS_MISC_DEPTHEQUALONLY; //DP ignores this too.
s->passes[0].shaderbits &= ~SBITS_DEPTHFUNC_BITS; //DP ignores this too.
}
Shader_Programify(s);
}
@ -5867,7 +5948,7 @@ void Shader_DefaultScript(const char *shortname, shader_t *s, const void *args)
if (*f == '{')
{
f++;
Shader_ReadShader(s, (void*)f, SPM_DEFAULT);
Shader_ReadShader(s, (void*)f, 0);
}
};
@ -5934,30 +6015,15 @@ void Shader_DefaultBSPLM(const char *shortname, shader_t *s, const void *args)
"}\n"
);
}
if (!builtin && ((sh_config.progs_supported && (qrenderer == QR_OPENGL||qrenderer == QR_DIRECT3D9)) || sh_config.progs_required))
//d3d has no position-invariant. this results in all sorts of glitches, so try not to use it.
if (!builtin && ((sh_config.progs_supported && (qrenderer == QR_OPENGL/*||qrenderer == QR_DIRECT3D9*/)) || sh_config.progs_required))
{
builtin = (
"{\n"
"fte_program defaultwall\n"
"{\n"
//FIXME: these maps are a legacy thing, and could be removed if third-party glsl properly contains s_diffuse
"map $diffuse\n"
"}\n"
"{\n"
"map $lightmap\n"
"}\n"
"{\n"
"map $normalmap\n"
"}\n"
"{\n"
"map $deluxmap\n"
"}\n"
"{\n"
"map $fullbright\n"
"}\n"
"{\n"
"map $specular\n"
"}\n"
"}\n"
);
}
@ -6643,18 +6709,18 @@ void Shader_Default2D(const char *shortname, shader_t *s, const void *genargs)
}
}
static qboolean Shader_ReadShaderTerms(shader_t *s, char **shadersource, int parsemode, struct scondinfo_s *cond)
static qboolean Shader_ReadShaderTerms(parsestate_t *ps, struct scondinfo_s *cond)
{
char *token;
if (!*shadersource)
if (!ps->ptr)
return false;
token = COM_ParseExt (shadersource, true, true);
token = COM_ParseExt (&ps->ptr, true, true);
if ( !token[0] )
return true;
else if (!Shader_Conditional_Read(s, cond, token, shadersource))
else if (!Shader_Conditional_Read(ps->s, cond, token, &ps->ptr))
{
int i;
for (i = 0; shadermacros[i].name; i++)
@ -6666,9 +6732,9 @@ static qboolean Shader_ReadShaderTerms(shader_t *s, char **shadersource, int par
char *body;
char arg[SHADER_MACRO_ARGS][256];
//parse args until the end of the line
while (*shadersource)
while (ps->ptr)
{
token = COM_ParseExt(shadersource, false, true);
token = COM_ParseExt(&ps->ptr, false, true);
if ( !token[0] )
{
break;
@ -6680,30 +6746,37 @@ static qboolean Shader_ReadShaderTerms(shader_t *s, char **shadersource, int par
}
}
body = shadermacros[i].body;
Shader_ReadShaderTerms(s, &body, parsemode, cond);
Shader_ReadShaderTerms(ps, cond);
return true;
}
}
if (token[0] == '}')
return false;
else if (token[0] == '{')
Shader_Readpass(s, shadersource);
else if (Shader_Parsetok(s, NULL, shaderkeys, token, shadersource))
Shader_Readpass(ps);
else if (Shader_Parsetok(ps, shaderkeys, token))
return false;
}
return true;
}
//loads a shader string into an existing shader object, and finalises it and stuff
static void Shader_ReadShader(shader_t *s, char *shadersource, int parsemode)
static void Shader_ReadShader(shader_t *s, char *shadersource, shadercachefile_t *sourcefile)
{
struct scondinfo_s cond = {0};
char *shaderstart = shadersource;
memset(&parsestate, 0, sizeof(parsestate));
parsestate.mode = parsemode;
if (sourcefile)
{
parsestate.forcedshader = *sourcefile->forcedshadername?sourcefile->forcedshadername:NULL;
parsestate.parseflags = sourcefile->parseflags;
}
else
parsestate.parseflags = 0;
parsestate.specularexpscale = 1;
parsestate.specularvalscale = 1;
parsestate.ptr = shadersource;
parsestate.s = s;
if (!s->defaulttextures)
{
@ -6714,7 +6787,7 @@ static void Shader_ReadShader(shader_t *s, char *shadersource, int parsemode)
// set defaults
s->flags = SHADER_CULL_FRONT;
while (Shader_ReadShaderTerms(s, &shadersource, parsemode, &cond))
while (Shader_ReadShaderTerms(&parsestate, &cond))
{
}
@ -6728,11 +6801,11 @@ static void Shader_ReadShader(shader_t *s, char *shadersource, int parsemode)
//querying the shader body often requires generating the shader, which then gets parsed.
if (saveshaderbody)
{
size_t l = shadersource - shaderstart;
size_t l = parsestate.ptr?parsestate.ptr - shadersource:0;
Z_Free(*saveshaderbody);
*saveshaderbody = BZ_Malloc(l+1);
(*saveshaderbody)[l] = 0;
memcpy(*saveshaderbody, shaderstart, l);
memcpy(*saveshaderbody, shadersource, l);
saveshaderbody = NULL;
}
}
@ -6741,9 +6814,9 @@ static qboolean Shader_ParseShader(char *parsename, shader_t *s)
{
size_t offset = 0, length;
char *buf = NULL;
enum shaderparsemode_e parsemode = SPM_DEFAULT;
shadercachefile_t *sourcefile = NULL;
if (Shader_LocateSource(parsename, &buf, &length, &offset, &parsemode))
if (Shader_LocateSource(parsename, &buf, &length, &offset, &sourcefile))
{
// the shader is in the shader scripts
if (buf && offset < length )
@ -6761,7 +6834,7 @@ static qboolean Shader_ParseShader(char *parsename, shader_t *s)
Shader_Reset(s);
Shader_ReadShader(s, file, parsemode);
Shader_ReadShader(s, file, sourcefile);
return true;
}
@ -6931,6 +7004,7 @@ static char *Shader_DecomposePass(char *o, shaderpass_t *p, qboolean simple)
{
switch(p->rgbgen)
{
default: sprintf(o, "RGB_GEN_? "); break;
case RGB_GEN_ENTITY: sprintf(o, "RGB_GEN_ENTITY "); break;
case RGB_GEN_ONE_MINUS_ENTITY: sprintf(o, "RGB_GEN_ONE_MINUS_ENTITY "); break;
case RGB_GEN_VERTEX_LIGHTING: sprintf(o, "RGB_GEN_VERTEX_LIGHTING "); break;
@ -6938,7 +7012,6 @@ static char *Shader_DecomposePass(char *o, shaderpass_t *p, qboolean simple)
case RGB_GEN_ONE_MINUS_VERTEX: sprintf(o, "RGB_GEN_ONE_MINUS_VERTEX "); break;
case RGB_GEN_IDENTITY_LIGHTING: sprintf(o, "RGB_GEN_IDENTITY_LIGHTING "); break;
case RGB_GEN_IDENTITY_OVERBRIGHT: sprintf(o, "RGB_GEN_IDENTITY_OVERBRIGHT "); break;
default:
case RGB_GEN_IDENTITY: sprintf(o, "RGB_GEN_IDENTITY "); break;
case RGB_GEN_CONST: sprintf(o, "RGB_GEN_CONST "); break;
case RGB_GEN_ENTITY_LIGHTING_DIFFUSE: sprintf(o, "RGB_GEN_ENTITY_LIGHTING_DIFFUSE "); break;
@ -6946,15 +7019,41 @@ static char *Shader_DecomposePass(char *o, shaderpass_t *p, qboolean simple)
case RGB_GEN_WAVE: sprintf(o, "RGB_GEN_WAVE "); break;
case RGB_GEN_TOPCOLOR: sprintf(o, "RGB_GEN_TOPCOLOR "); break;
case RGB_GEN_BOTTOMCOLOR: sprintf(o, "RGB_GEN_BOTTOMCOLOR "); break;
case RGB_GEN_UNKNOWN: sprintf(o, "RGB_GEN_UNKNOWN "); break;
}
o+=strlen(o);
sprintf(o, "\n"); o+=strlen(o);
switch(p->alphagen)
{
default: sprintf(o, "ALPHA_GEN_? "); break;
case ALPHA_GEN_ENTITY: sprintf(o, "ALPHA_GEN_ENTITY "); break;
case ALPHA_GEN_WAVE: sprintf(o, "ALPHA_GEN_WAVE "); break;
case ALPHA_GEN_PORTAL: sprintf(o, "ALPHA_GEN_PORTAL "); break;
case ALPHA_GEN_SPECULAR: sprintf(o, "ALPHA_GEN_SPECULAR "); break;
case ALPHA_GEN_IDENTITY: sprintf(o, "ALPHA_GEN_IDENTITY "); break;
case ALPHA_GEN_VERTEX: sprintf(o, "ALPHA_GEN_VERTEX "); break;
case ALPHA_GEN_CONST: sprintf(o, "ALPHA_GEN_CONST "); break;
}
o+=strlen(o);
sprintf(o, "\n"); o+=strlen(o);
}
if (p->prog)
{
sprintf(o, "program\n");
o+=strlen(o);
}
if (p->shaderbits & SBITS_MISC_DEPTHWRITE) { sprintf(o, "SBITS_MISC_DEPTHWRITE\n"); o+=strlen(o); }
if (p->shaderbits & SBITS_MISC_NODEPTHTEST) { sprintf(o, "SBITS_MISC_NODEPTHTEST\n"); o+=strlen(o); }
if (p->shaderbits & SBITS_MISC_DEPTHEQUALONLY) { sprintf(o, "SBITS_MISC_DEPTHEQUALONLY\n"); o+=strlen(o); }
if (p->shaderbits & SBITS_MISC_DEPTHCLOSERONLY) { sprintf(o, "SBITS_MISC_DEPTHCLOSERONLY\n"); o+=strlen(o); }
else switch (p->shaderbits & SBITS_DEPTHFUNC_BITS)
{
case SBITS_DEPTHFUNC_EQUAL: sprintf(o, "depthfunc equal\n"); break;
case SBITS_DEPTHFUNC_CLOSER: sprintf(o, "depthfunc less\n"); break;
case SBITS_DEPTHFUNC_CLOSEREQUAL: sprintf(o, "depthfunc lequal\n"); break;
case SBITS_DEPTHFUNC_FURTHER: sprintf(o, "depthfunc greater\n"); break;
}
if (p->shaderbits & SBITS_TESSELLATION) { sprintf(o, "SBITS_TESSELLATION\n"); o+=strlen(o); }
if (p->shaderbits & SBITS_AFFINE) { sprintf(o, "SBITS_AFFINE\n"); o+=strlen(o); }
if (p->shaderbits & SBITS_MASK_BITS) { sprintf(o, "SBITS_MASK_BITS\n"); o+=strlen(o); }
@ -7005,35 +7104,76 @@ static char *Shader_DecomposePass(char *o, shaderpass_t *p, qboolean simple)
switch(p->shaderbits & SBITS_ATEST_BITS)
{
case SBITS_ATEST_NONE: break;
case SBITS_ATEST_GE128: sprintf(o, "SBITS_ATEST_GE128\n"); break;
case SBITS_ATEST_LT128: sprintf(o, "SBITS_ATEST_LT128\n"); break;
case SBITS_ATEST_GT0: sprintf(o, "SBITS_ATEST_GT0\n"); break;
}
o+=strlen(o);
return o;
}
static char *Shader_DecomposeSubPass(char *o, shaderpass_t *p, qboolean simple)
{
int i;
if (!simple)
{
switch(p->tcgen)
{
default: sprintf(o, "TC_GEN_? "); break;
case TC_GEN_BASE: sprintf(o, "TC_GEN_BASE "); break;
case TC_GEN_LIGHTMAP: sprintf(o, "TC_GEN_LIGHTMAP "); break;
case TC_GEN_ENVIRONMENT: sprintf(o, "TC_GEN_ENVIRONMENT "); break;
case TC_GEN_DOTPRODUCT: sprintf(o, "TC_GEN_DOTPRODUCT "); break;
case TC_GEN_VECTOR: sprintf(o, "TC_GEN_VECTOR "); break;
case TC_GEN_NORMAL: sprintf(o, "TC_GEN_NORMAL "); break;
case TC_GEN_SVECTOR: sprintf(o, "TC_GEN_SVECTOR "); break;
case TC_GEN_TVECTOR: sprintf(o, "TC_GEN_TVECTOR "); break;
case TC_GEN_SKYBOX: sprintf(o, "TC_GEN_SKYBOX "); break;
case TC_GEN_WOBBLESKY: sprintf(o, "TC_GEN_WOBBLESKY "); break;
case TC_GEN_REFLECT: sprintf(o, "TC_GEN_REFLECT "); break;
case TC_GEN_UNSPECIFIED: sprintf(o, "TC_GEN_UNSPECIFIED "); break;
}
o+=strlen(o);
sprintf(o, "\n"); o+=strlen(o);
for (i = 0; i < p->numtcmods; i++)
{
switch(p->tcmods[i].type)
{
default: sprintf(o, "TCMOD_GEN_? "); break;
case SHADER_TCMOD_NONE: sprintf(o, "SHADER_TCMOD_NONE "); break;
case SHADER_TCMOD_SCALE: sprintf(o, "SHADER_TCMOD_SCALE "); break;
case SHADER_TCMOD_SCROLL: sprintf(o, "SHADER_TCMOD_SCROLL "); break;
case SHADER_TCMOD_STRETCH: sprintf(o, "SHADER_TCMOD_STRETCH "); break;
case SHADER_TCMOD_ROTATE: sprintf(o, "SHADER_TCMOD_ROTATE "); break;
case SHADER_TCMOD_TRANSFORM: sprintf(o, "SHADER_TCMOD_TRANSFORM "); break;
case SHADER_TCMOD_TURB: sprintf(o, "SHADER_TCMOD_TURB "); break;
case SHADER_TCMOD_PAGE: sprintf(o, "SHADER_TCMOD_PAGE "); break;
}
o+=strlen(o);
sprintf(o, "\n"); o+=strlen(o);
}
switch(p->blendmode)
{
default:
case PBM_MODULATE: sprintf(o, "modulate "); break;
case PBM_OVERBRIGHT: sprintf(o, "overbright "); break;
case PBM_DECAL: sprintf(o, "decal "); break;
case PBM_ADD:sprintf(o, "add "); break;
case PBM_DOTPRODUCT: sprintf(o, "dotproduct "); break;
case PBM_REPLACE: sprintf(o, "replace "); break;
case PBM_REPLACELIGHT: sprintf(o, "replacelight "); break;
case PBM_MODULATE_PREV_COLOUR: sprintf(o, "modulate_prev "); break;
default: sprintf(o, "PBM_? "); break;
case PBM_MODULATE: sprintf(o, "PBM_MODULATE "); break;
case PBM_OVERBRIGHT: sprintf(o, "PBM_OVERBRIGHT "); break;
case PBM_DECAL: sprintf(o, "PBM_DECAL "); break;
case PBM_ADD: sprintf(o, "PBM_ADD "); break;
case PBM_DOTPRODUCT: sprintf(o, "PBM_DOTPRODUCT "); break;
case PBM_REPLACE: sprintf(o, "PBM_REPLACE "); break;
case PBM_REPLACELIGHT: sprintf(o, "PBM_REPLACELIGHT "); break;
case PBM_MODULATE_PREV_COLOUR: sprintf(o, "PBM_MODULATE_PREV_COLOUR "); break;
}
o+=strlen(o);
}
switch(p->texgen)
{
default:
default: sprintf(o, "T_GEN_? "); break;
case T_GEN_SINGLEMAP:
if (p->anim_frames[0])
{
@ -7096,6 +7236,7 @@ static char *Shader_DecomposeSubPass(char *o, shaderpass_t *p, qboolean simple)
case T_GEN_VIDEOMAP: sprintf(o, "videomap "); break;
case T_GEN_CUBEMAP: sprintf(o, "cubemap "); break;
case T_GEN_3DMAP: sprintf(o, "3dmap "); break;
case T_GEN_GBUFFERCASE: sprintf(o, "gbuffer%i ",p->texgen-T_GEN_GBUFFER0); break;
}
o+=strlen(o);
@ -7113,6 +7254,7 @@ char *Shader_Decompose(shader_t *s)
switch (s->sort)
{
default: sprintf(o, "sort %i\n", s->sort); break;
case SHADER_SORT_NONE: sprintf(o, "sort %i (SHADER_SORT_NONE)\n", s->sort); break;
case SHADER_SORT_RIPPLE: sprintf(o, "sort %i (SHADER_SORT_RIPPLE)\n", s->sort); break;
case SHADER_SORT_DEFERREDLIGHT: sprintf(o, "sort %i (SHADER_SORT_DEFERREDLIGHT)\n", s->sort); break;
@ -7126,7 +7268,6 @@ char *Shader_Decompose(shader_t *s)
case SHADER_SORT_BLEND: sprintf(o, "sort %i (SHADER_SORT_BLEND)\n", s->sort); break;
case SHADER_SORT_ADDITIVE: sprintf(o, "sort %i (SHADER_SORT_ADDITIVE)\n", s->sort); break;
case SHADER_SORT_NEAREST: sprintf(o, "sort %i (SHADER_SORT_NEAREST)\n", s->sort); break;
default: sprintf(o, "sort %i\n", s->sort); break;
}
o+=strlen(o);
@ -7149,7 +7290,7 @@ char *Shader_Decompose(shader_t *s)
o = Shader_DecomposePass(o, p, false);
for (j = 0; j < p->numMergedPasses; j++)
o = Shader_DecomposeSubPass(o, p+j, false);
o = Shader_DecomposeSubPass(o, p+j, !!p->prog);
sprintf(o, "}\n"); o+=strlen(o);
}
}
@ -7338,7 +7479,7 @@ void Shader_DoReload(void)
if (ruleset_allow_shaders.ival)
{
COM_EnumerateFiles("materials/*.mtr", Shader_InitCallback, NULL);
COM_EnumerateFiles("materials/*.mtr", Shader_InitCallback_Doom3, NULL);
COM_EnumerateFiles("shaders/*.shader", Shader_InitCallback, NULL);
COM_EnumerateFiles("scripts/*.shader", Shader_InitCallback, NULL);
COM_EnumerateFiles("scripts/*.rscript", Shader_InitCallback, NULL);

View file

@ -4,6 +4,10 @@
#include "gl_draw.h"
#include "shader.h"
extern cvar_t gl_immutable_textures;
extern cvar_t gl_immutable_buffers;
#ifndef GL_STATIC
//standard gles2 opengl calls.
void (APIENTRY *qglBlendFunc) (GLenum sfactor, GLenum dfactor);
@ -913,6 +917,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
#endif
{
if ((!gl_config.gles && gl_config.glversion >= 4.4) || GL_CheckExtension("GL_ARB_buffer_storage"))
if (gl_immutable_buffers.ival)
qglBufferStorage = (void *)getglext("glBufferStorage"); //no arb postfix even with the extension form of it.
}
@ -1129,16 +1134,16 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
else
gl_config.geometryshaders = false;
qglTexStorage2D = NULL;
qglTexStorage3D = NULL;
if ((!gl_config.gles && gl_config.glversion >= 4.2) ||
( gl_config.gles && gl_config.glversion >= 3.0))
{ //from gles3.0 or gl4.2 onwards
if (gl_immutable_textures.ival)
{
qglTexStorage2D = getglext("glTexStorage2D");
qglTexStorage3D = getglext("glTexStorage3D");
}
else
{
qglTexStorage2D = NULL;
qglTexStorage3D = NULL;
}
#ifdef GL_STATIC
@ -2743,6 +2748,293 @@ static void GLSlang_ProgAutoFields(program_t *prog, const char *progname, cvar_t
}
}
void GL_ForgetPointers(void)
{ //its at times like this that I wish I had put all of these into a struct.
//but GL_STATIC and webgl makes that sub-optimal. *sigh*
#ifndef GL_STATIC
qglBindTexture = NULL;
qglBlendFunc = NULL;
qglClear = NULL;
qglClearColor = NULL;
qglClearStencil = NULL;
qglColorMask = NULL;
qglCopyTexImage2D = NULL;
qglCopyTexSubImage2D= NULL;
qglCullFace = NULL;
qglDepthFunc = NULL;
qglDepthMask = NULL;
// qglDepthRangef = NULL;
qglDisable = NULL;
qglEnable = NULL;
qglFinish = NULL;
qglFlush = NULL;
qglGenTextures = NULL;
qglGetFloatv = NULL;
qglGetIntegerv = NULL;
qglGetString = NULL;
qglHint = NULL;
qglIsEnabled = NULL;
qglReadPixels = NULL;
qglTexImage2D = NULL;
qglTexSubImage2D = NULL;
qglTexParameteri = NULL;
qglTexParameterf = NULL;
qglTexParameteriv = NULL;
qglTexParameterfv = NULL;
qglViewport = NULL;
qglGetBooleanv = NULL;
qglGetError = NULL;
qglDeleteTextures = NULL;
qglDrawElements = NULL;
qglDrawArrays = NULL;
qglStencilOp = NULL;
qglStencilFunc = NULL;
qglScissor = NULL;
qglPolygonOffset = NULL;
#endif
#ifndef FTE_TARGET_WEB
qglAlphaFunc = NULL;
qglBegin = NULL;
qglClearDepth = NULL;
qglClipPlane = NULL;
// qglColor3f = NULL;
// qglColor3ub = NULL;
qglColor4f = NULL;
qglColor4fv = NULL;
// qglColor4ub = NULL;
// qglColor4ubv = NULL;
// qglDepthRange = NULL;
qglDrawBuffer = NULL;
qglDrawPixels = NULL;
qglEnd = NULL;
qglFrustum = NULL;
qglGetTexLevelParameteriv = NULL;
qglLoadIdentity = NULL;
qglLoadMatrixf = NULL;
qglNormal3f = NULL;
qglNormal3fv = NULL;
qglMatrixMode = NULL;
qglMultMatrixf = NULL;
// qglOrtho = NULL;
qglPolygonMode = NULL;
qglPopMatrix = NULL;
qglPushMatrix = NULL;
qglReadBuffer = NULL;
qglRotatef = NULL;
qglScalef = NULL;
qglShadeModel = NULL;
qglTexCoord1f = NULL;
qglTexCoord2f = NULL;
qglTexCoord2fv = NULL;
qglTexEnvf = NULL;
qglTexEnvfv = NULL;
qglTexEnvi = NULL;
qglTexGeni = NULL;
qglTexGenfv = NULL;
qglTexImage3D = NULL;
qglTexSubImage3D = NULL;
qglTranslatef = NULL;
qglVertex2f = NULL;
qglVertex3f = NULL;
qglVertex3fv = NULL;
#endif
//various vertex array stuff.
qglArrayElement = NULL;
qglVertexPointer = NULL;
qglNormalPointer = NULL;
qglTexCoordPointer = NULL;
qglColorPointer = NULL;
qglEnableClientState = NULL;
qglDisableClientState = NULL;
qglDrawRangeElements = NULL;
//fixme: definatly make non-core
qglPushAttrib = NULL;
qglPopAttrib = NULL;
//does this need to be non-core as well?
qglFogi = NULL;
qglFogf = NULL;
qglFogfv = NULL;
qglGetTexEnviv = NULL;
qglGetPointerv = NULL;
qglGetStringi = NULL;
//used by heightmaps
qglGenLists = NULL;
qglNewList = NULL;
qglEndList = NULL;
qglCallList = NULL;
#ifndef GL_STATIC
qglBindBufferARB = NULL;
#endif
gl_vendor = NULL;
gl_renderer = NULL;
gl_version = NULL;
gl_extensions = NULL;
gl_num_extensions = 0;
#ifndef qglActiveTextureARB
qglActiveTextureARB = NULL;
#endif
qglClientActiveTextureARB = NULL;
qglSelectTextureSGIS = NULL;
qglMTexCoord2fSGIS = NULL;
qglMultiTexCoord2fARB = NULL;
qglMultiTexCoord3fARB = NULL;
qglMTexCoord2fSGIS = NULL;
qglSelectTextureSGIS = NULL;
mtexid0 = 0;
#ifndef GL_STATIC
qglGenFramebuffersEXT = NULL;
qglDeleteFramebuffersEXT = NULL;
qglBindFramebufferEXT = NULL;
qglGenRenderbuffersEXT = NULL;
qglDeleteRenderbuffersEXT = NULL;
qglBindRenderbufferEXT = NULL;
qglRenderbufferStorageEXT = NULL;
qglFramebufferTexture2DEXT = NULL;
#endif
//no GL_EXT_stencil_two_side
qglActiveStencilFaceEXT = NULL;
//no truform. sorry.
qglPNTrianglesfATI = NULL;
qglPNTrianglesiATI = NULL;
//fragment programs
// qglProgramStringARB = NULL;
// qglGetProgramivARB = NULL;
// qglBindProgramARB = NULL;
// qglGenProgramsARB = NULL;
#ifndef GL_STATIC
qglStencilOpSeparateATI = NULL;
#endif
qglActiveStencilFaceEXT = NULL;
#ifndef GL_STATIC
qglCompressedTexImage2D = NULL;
qglCompressedTexImage3D = NULL;
qglCompressedTexSubImage2D = NULL;
qglCompressedTexSubImage3D = NULL;
qglGetCompressedTexImage = NULL;
#endif
qglDepthBoundsEXT = NULL;
qglPNTrianglesfATI = NULL;
qglPNTrianglesiATI = NULL;
qglPatchParameteriARB = NULL;
#ifndef GL_STATIC
qglBindTexture = NULL;
#endif
qglLockArraysEXT = NULL;
qglUnlockArraysEXT = NULL;
qglBufferStorage = NULL;
#if !defined(GL_STATIC)
qglGenBuffersARB = NULL;
qglDeleteBuffersARB = NULL;
qglBindBufferARB = NULL;
qglBufferDataARB = NULL;
qglBufferSubDataARB = NULL;
qglMapBufferARB = NULL;
qglUnmapBufferARB = NULL;
qglMapBufferRange = NULL;
qglCreateProgramObjectARB = NULL;
qglDeleteProgramObject_ = NULL;
qglDeleteShaderObject_ = NULL;
qglUseProgramObjectARB = NULL;
qglCreateShaderObjectARB = NULL;
qglGetProgramParameteriv_ = NULL;
qglGetShaderParameteriv_ = NULL;
qglAttachObjectARB = NULL;
qglGetProgramInfoLog_ = NULL;
qglGetShaderInfoLog_ = NULL;
qglShaderSourceARB = NULL;
qglCompileShaderARB = NULL;
qglLinkProgramARB = NULL;
qglBindAttribLocationARB = NULL;
qglGetAttribLocationARB = NULL;
qglVertexAttribPointer = NULL;
qglGetVertexAttribiv = NULL;
qglGetVertexAttribPointerv = NULL;
qglEnableVertexAttribArray = NULL;
qglDisableVertexAttribArray = NULL;
qglGetUniformLocationARB = NULL;
qglUniformMatrix4fvARB = NULL;
qglUniformMatrix3x4fv = NULL;
qglUniformMatrix4x3fv = NULL;
qglUniform4fARB = NULL;
qglUniform4fvARB = NULL;
qglUniform3fARB = NULL;
qglUniform3fvARB = NULL;
qglUniform2fvARB = NULL;
qglUniform1iARB = NULL;
qglUniform1fARB = NULL;
qglGetShaderSource = NULL;
#endif
qglGetProgramBinary = NULL;
qglProgramBinary = NULL;
qglGetGraphicsResetStatus = NULL; //its not allowed to crash us. probably will. grr. oh well.
qglGenVertexArrays = NULL;
qglBindVertexArray = NULL;
qglTexStorage2D = NULL;
qglTexStorage3D = NULL;
#ifndef GL_STATIC
qglGenFramebuffersEXT = NULL;
qglDeleteFramebuffersEXT = NULL;
qglBindFramebufferEXT = NULL;
qglGenRenderbuffersEXT = NULL;
qglDeleteRenderbuffersEXT = NULL;
qglBindRenderbufferEXT = NULL;
qglRenderbufferStorageEXT = NULL;
qglFramebufferTexture2DEXT = NULL;
qglFramebufferRenderbufferEXT = NULL;
qglCheckFramebufferStatusEXT = NULL;
qglGetFramebufferAttachmentParameteriv = NULL;
#endif
#ifdef DEBUG
qglDebugMessageControlARB = NULL;
qglDebugMessageInsertARB = NULL;
qglDebugMessageCallbackARB = NULL;
qglGetDebugMessageLogARB = NULL;
#endif
qglGenQueriesARB = NULL;
qglDeleteQueriesARB = NULL;
qglBeginQueryARB = NULL;
qglEndQueryARB = NULL;
qglGetQueryObjectuivARB = NULL;
qglGenVertexArrays = NULL;
qglBindVertexArray = NULL;
qglDrawBuffers = NULL;
qglLoadMatrixf = NULL;
qglPolygonMode = NULL;
qglShadeModel = NULL;
qglDrawBuffer = NULL;
memset(&sh_config, 0, sizeof(sh_config));
memset(&gl_config, 0, sizeof(gl_config));
}
//the vid routines have initialised a window, and now they are giving us a reference to some of of GetProcAddress to get pointers to the funcs.
qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
{

View file

@ -90,6 +90,8 @@ void GLVID_DeInit(void)
sys_context = EGL_NO_CONTEXT;
sys_surface = EGL_NO_SURFACE;
GL_ForgetPointers();
Sys_Printf("GLVID_DeInited\n");
}

View file

@ -2413,6 +2413,7 @@ void GLVID_Shutdown(void)
#ifdef USE_EGL
case PSL_EGL:
EGL_Shutdown();
GL_ForgetPointers();
break;
#endif
case PSL_GLX:
@ -2421,6 +2422,7 @@ void GLVID_Shutdown(void)
glx.DestroyContext(vid_dpy, ctx);
ctx = NULL;
}
GL_ForgetPointers();
break;
#endif
#ifdef VKQUAKE

View file

@ -111,6 +111,7 @@ qboolean GLVID_Init(rendererstate_t *info, unsigned char *palette)
void GLVID_DeInit(void)
{
killCocoa();
GL_ForgetPointers();
}
void GLVID_SetPalette (unsigned char *palette)

View file

@ -1703,6 +1703,10 @@ void VID_UnSetMode (void)
}
*opengldllname = 0;
#endif
#ifdef GLQUAKE
GL_ForgetPointers();
#endif
}

View file

@ -379,6 +379,7 @@ void GLVID_DeInit (void)
#endif
SDL_QuitSubSystem(SDL_INIT_VIDEO);
GL_ForgetPointers();
}

View file

@ -1112,6 +1112,7 @@ void GL_SelectProgram(int program);
qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name));
void GL_ForgetPointers(void);
#endif

View file

@ -6831,6 +6831,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
//!!samps diffuse lightmap specular normalmap fullbright reflectmask reflectcube paletted lightmap1 lightmap2 lightmap3
"!!samps diffuse fullbright lightmap\n"
"#undef SPECULAR\n"
//#include "sys/defs.h"
"#define vec4 float4\n"
"#define vec3 float3\n"
@ -6842,7 +6844,17 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"{\n"
"vec4 v_position : POSITION;\n"
"vec2 v_texcoord : TEXCOORD0;\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
"vec3 v_normal : NORMAL;\n"
"vec3 v_svector : TANGENT;\n"
"vec3 v_tvector : BINORMAL;\n"
"#endif\n"
"#ifdef VERTEXLIT\n"
"vec4 v_colour : COLOR0;\n"
"#else\n"
"vec2 v_lmcoord : TEXCOORD1;\n"
"#endif\n"
"};\n"
"struct v2f\n"
"{\n"
@ -6858,7 +6870,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"mat3 invsurface : TEXCOORD5;\n"
"#endif\n"
"#ifdef VERTEXLIT\n"
"vec2 tclm : TEXCOORD0;\n"
"#else\n"
"vec4 tclm : TEXCOORD0;\n"
"#endif\n"
"vec4 vc : COLOR0;\n"
"#ifndef VERTEXLIT\n"
"#ifdef LIGHTSTYLED\n"
@ -6994,11 +7010,10 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
//modulate that by the lightmap(s) including deluxemap(s)
"#ifdef VERTEXLIT\n"
"#error foobar\n"
"#ifdef LIGHTSTYLED\n"
"vec3 lightmaps = vc.rgb;\n"
"vec3 lightmaps = inp.vc.rgb;\n"
"#else\n"
"vec3 lightmaps = vc.rgb;\n"
"vec3 lightmaps = inp.vc.rgb;\n"
"#endif\n"
"#define delux vec3(0.0,0.0,1.0)\n"
"#else\n"

View file

@ -158,10 +158,13 @@ enum
#define SBITS_ATEST_SHIFT 12
SBITS_MISC_DEPTHWRITE = 0x00010000,
SBITS_MISC_NODEPTHTEST = 0x00020000,
SBITS_MISC_DEPTHEQUALONLY = 0x00040000,
SBITS_MISC_DEPTHCLOSERONLY = 0x00080000,
//#define SBITS_MISC_BITS 0x000f0000
SBITS_MISC_NODEPTHTEST = 0x00020000, //strictly speaking, this is NOT the same as 'depthfunc always', which is unfortunate.
SBITS_DEPTHFUNC_CLOSEREQUAL = 0x00000000,
SBITS_DEPTHFUNC_EQUAL = 0x00040000,
SBITS_DEPTHFUNC_CLOSER = 0x00080000,
SBITS_DEPTHFUNC_FURTHER = 0x000c0000,
#define SBITS_DEPTHFUNC_BITS 0x000c0000
SBITS_TESSELLATION = 0x00100000,
SBITS_AFFINE = 0x00200000,
@ -974,5 +977,6 @@ void CLQ1_DrawLine(shader_t *shader, vec3_t v1, vec3_t v2, float r, float g, flo
void CLQ1_AddOrientedCube(shader_t *shader, vec3_t mins, vec3_t maxs, float *matrix, float r, float g, float b, float a);
void CL_DrawDebugPlane(float *normal, float dist, float r, float g, float b, qboolean enqueue);
void CLQ1_AddOrientedCylinder(shader_t *shader, float radius, float height, qboolean capsule, float *matrix, float r, float g, float b, float a);
void CLQ1_AddOrientedSphere(shader_t *shader, float radius, float *matrix, float r, float g, float b, float a);
void CLQ1_AddOrientedHalfSphere(shader_t *shader, float radius, float gap, float *matrix, float r, float g, float b, float a);
#endif

View file

@ -269,9 +269,7 @@ qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
// vid.pixelwidth = info->width;
// vid.pixelheight = info->height;
GL_Init(PPAPI_GetGLSymbol);
return true;
return GL_Init(PPAPI_GetGLSymbol);
}
void GLVID_Shutdown (void)
@ -282,6 +280,8 @@ void GLVID_Shutdown (void)
ppb_core->ReleaseResource(glcontext);
// glTerminatePPAPI();
GL_ForgetPointers();
}
void GLVID_DeInit (void)
{

View file

@ -9466,6 +9466,10 @@ static void QCBUILTIN PF_runclientphys(pubprogfuncs_t *prinst, struct globalvars
if (ent->xv->hasted)
movevars.maxspeed *= ent->xv->hasted;
#endif
if (client)
movevars.coordsize = client->netchan.netprim.coordsize;
else
movevars.coordsize = svs.netprim.coordsize;
pmove.numtouch = 0;
pmove.world = &sv.world;
@ -10423,6 +10427,14 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
// {"brush_transformselected",PF_brush_transformselected,0,0,0, 0, D("int(float modelid, int brushid, float *matrix)", "Transforms selected brushes by the given transform")},
#endif
#ifdef ENGINE_ROUTING
#define qcnodeslist \
"typedef struct\n{\n" \
"\tvector dest;\n" \
"\tint linkflags;\n"\
"} nodeslist_t;\n"
{"route_calculate", PF_route_calculate,0, 0, 0, 0, D(qcnodeslist "void(entity ent, vector dest, int denylinkflags, void(entity ent, vector dest, int numnodes, nodeslist_t *nodelist) callback)", "Begin calculating a route. The callback function will be called once the route has finished being calculated. The route must be memfreed once it is no longer needed. The route must be followed in reverse order (ie: the first node that must be reached is at index numnodes-1). If no route is available then the callback will be called with no nodes.")},
#endif
{"touchtriggers", PF_touchtriggers, 0, 0, 0, 279, D("void(optional entity ent, optional vector neworigin)", "Triggers a touch events between self and every SOLID_TRIGGER entity that it is in contact with. This should typically just be the triggers touch functions. Also optionally updates the origin of the moved entity.")},//
{"WriteFloat", PF_WriteFloat, 0, 0, 0, 280, "void(float buf, float fl)"},//
@ -10541,7 +10553,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"findfont", PF_Fixme, 0, 0, 0, 356, D("float(string s)", "Looks up a named font slot. Matches the actual font name as a last resort.")},//;
{"loadfont", PF_Fixme, 0, 0, 0, 357, D("float(string fontname, string fontmaps, string sizes, float slot, optional float fix_scale, optional float fix_voffset)", "too convoluted for me to even try to explain correct usage. Try drawfont = loadfont(\"\", \"cour\", \"16\", -1, 0, 0); to switch to the courier font (optimised for 16 virtual pixels high), if you have the freetype2 library in windows..")},
//358
{"sendevent", PF_Fixme, 0, 0, 0, 359, D("void(string evname, string evargs, ...)", "Invoke Cmd_evname_evargs in ssqc. evargs must be a string of initials refering to the types of the arguments to pass. v=vector, e=entity(.entnum field is sent), f=float, i=int. 6 arguments max - you can get more if you pack your floats into vectors.")},// (EXT_CSQC_1)
{"sendevent", PF_Fixme, 0, 0, 0, 359, D("void(string evname, string evargs, ...)", "Invoke CSEv_evname_evargs in ssqc. evargs must be a string of initials refering to the types of the arguments to pass. v=vector, e=entity(.entnum field is sent), f=float, i=int. 6 arguments max - you can get more if you pack your floats into vectors.")},// (EXT_CSQC_1)
{"readbyte", PF_Fixme, 0, 0, 0, 360, "float()"},// (EXT_CSQC)
{"readchar", PF_Fixme, 0, 0, 0, 361, "float()"},// (EXT_CSQC)

View file

@ -626,4 +626,645 @@ qboolean World_MoveToGoal (world_t *world, wedict_t *ent, float dist)
return true;
}
#ifdef ENGINE_ROUTING
cvar_t route_shownodes = CVAR("route_shownodes", "0");
#define LF_EDGE 0x00000001
#define LF_JUMP 0x00000002
#define LF_CROUCH 0x00000004
#define LF_TELEPORT 0x00000008
#define LF_USER 0x7fffff00
#define LF_DESTINATION 0x80000000 //You have reached your destination...
struct waypointnetwork_s
{
size_t refs;
size_t numwaypoints;
model_t *worldmodel;
struct resultnodes_s
{
vec3_t pos;
int linkflags;
} *displaynode;
int displaynodes;
struct waypoint_s
{
vec3_t org;
float radius; //used for picking the closest waypoint. aka proximity weight. also relaxes routes inside the area.
struct wpneighbour_s
{
int node;
float linkcost;//might be much lower in the case of teleports, or expensive if someone wanted it to be a lower priority link.
int linkflags; //LF_*
} *neighbour;
int neighbours;
} waypoints[1];
};
void WayNet_Done(struct waypointnetwork_s *net)
{
if (net)
if (0 == --net->refs)
{
Z_Free(net);
}
}
static qboolean WayNet_TokenizeLine(char **linestart)
{
char *end = *linestart;
if (!*end)
{ //clear it out...
Cmd_TokenizeString("", false, false);
return false;
}
for (; *end; end++)
{
if (*end == '\n')
{
*end++ = 0;
break;
}
}
Cmd_TokenizeString(*linestart, false, false);
*linestart = end;
return true;
}
static struct waypointnetwork_s *WayNet_Begin(void **ctxptr, model_t *worldmodel)
{
struct waypointnetwork_s *net = *ctxptr;
if (!net)
{
char *wf = NULL, *l, *e;
int numwaypoints, maxlinks, numlinks;
struct wpneighbour_s *nextlink;
if (!worldmodel)
return NULL;
if (!wf && !strncmp(worldmodel->name, "maps/", 5))
{
char n[MAX_QPATH];
COM_StripExtension(worldmodel->name+5, n, sizeof(n));
wf = FS_MallocFile(va("data/%s.way", n), FS_GAME, NULL);
}
if (!wf)
wf = FS_MallocFile(va("%s.way", worldmodel->name), FS_GAME, NULL);
l = wf;
//read the number of waypoints
WayNet_TokenizeLine(&l);
numwaypoints = atoi(Cmd_Argv(0));
//count lines and guess the link count.
for (e = l, maxlinks=0; *e; e++)
if (*e == '\n')
maxlinks++;
maxlinks -= numwaypoints;
net = Z_Malloc(sizeof(*net)-sizeof(net->waypoints) + (numwaypoints*sizeof(struct waypoint_s)) + (maxlinks*sizeof(struct wpneighbour_s)));
net->refs = 1;
net->worldmodel = worldmodel;
*ctxptr = net;
nextlink = (struct wpneighbour_s*)(net->waypoints+numwaypoints);
while (WayNet_TokenizeLine(&l) && net->numwaypoints < numwaypoints)
{
if (!Cmd_Argc())
continue; //a comment line?
net->waypoints[net->numwaypoints].org[0] = atof(Cmd_Argv(0));
net->waypoints[net->numwaypoints].org[1] = atof(Cmd_Argv(1));
net->waypoints[net->numwaypoints].org[2] = atof(Cmd_Argv(2));
net->waypoints[net->numwaypoints].radius = 64;//atof(Cmd_Argv(3));
numlinks = bound(0, atoi(Cmd_Argv(4)), maxlinks);
//make sure the links are valid, and clamp to avoid problems (even if we're then going to mis-parse.
net->waypoints[net->numwaypoints].neighbour = nextlink;
while (numlinks-- > 0 && WayNet_TokenizeLine(&l))
{
if (!Cmd_Argc())
continue; //a comment line?
nextlink[net->waypoints[net->numwaypoints].neighbours].node = atoi(Cmd_Argv(0));
nextlink[net->waypoints[net->numwaypoints].neighbours].linkcost = atof(Cmd_Argv(1));
nextlink[net->waypoints[net->numwaypoints].neighbours++].linkflags = atoi(Cmd_Argv(2));
}
maxlinks -= net->waypoints[net->numwaypoints].neighbours;
nextlink += net->waypoints[net->numwaypoints++].neighbours;
}
BZ_Free(wf);
}
net->refs++;
return net;
}
struct waydist_s
{
int node;
float sdist;
};
int QDECL WayNet_Prioritise(const void *a, const void *b)
{
const struct waydist_s *w1 = a, *w2 = b;
if (w1->sdist < w2->sdist)
return -1;
if (w1->sdist == w2->sdist)
return 0;
return 1;
}
int WayNet_FindNearestNode(struct waypointnetwork_s *net, vec3_t pos)
{
if (net && net->numwaypoints)
{
//we qsort the possible nodes, in an attempt to reduce traces.
struct waydist_s *sortedways = alloca(sizeof(*sortedways) * net->numwaypoints);
size_t u;
vec3_t disp;
float sradius;
trace_t tr;
for (u = 0; u < net->numwaypoints; u++)
{
sortedways[u].node = u;
VectorSubtract(net->waypoints[u].org, pos, disp);
sortedways[u].sdist = DotProduct(disp, disp);
sradius = net->waypoints[u].radius*net->waypoints[u].radius;
if (sortedways[u].sdist < sradius)
sortedways[u].sdist -= sradius; //if we're inside the waypoint's radius, push inwards resulting in negatives, so these are always highly prioritised
}
qsort(sortedways, net->numwaypoints, sizeof(struct waydist_s), WayNet_Prioritise);
//can't trace yet...
if (net->worldmodel->loadstate != MLS_LOADED)
return sortedways[0].node;
for (u = 0; u < net->numwaypoints; u++)
{
if (sortedways[u].sdist > 0)
{ //if we're outside the node, we need to do a trace to make sure we can actually reach it.
net->worldmodel->funcs.NativeTrace(net->worldmodel, 0, NULL, NULL, pos, net->waypoints[sortedways[u].node].org, vec3_origin, vec3_origin, false, MASK_WORLDSOLID, &tr);
if (tr.fraction < 1)
continue; //this node is blocked. just move on to the next.
}
return sortedways[u].node;
}
}
return -1;
}
struct routecalc_s
{
world_t *world;
int spawncount; //so we don't confuse stuff if the map gets restarted.
wedict_t *ed;
// float spawnid; //so the route fails if the ent is removed.
func_t callback;
vec3_t start;
vec3_t end;
int denylinkflags;
int startn;
int endn;
int numresultnodes;
struct resultnodes_s *resultnodes;
struct waypointnetwork_s *waynet;
};
//main thread
void Route_Calculated(void *ctx, void *data, size_t a, size_t b)
{
struct routecalc_s *route = data;
pubprogfuncs_t *prinst = route->world->progs;
//let the gamecode know the results
if (!route->callback)
{
BZ_Free(route->waynet->displaynode);
route->waynet->displaynode = BZ_Malloc(sizeof(struct resultnodes_s) * route->numresultnodes);
route->waynet->displaynodes = route->numresultnodes;
memcpy(route->waynet->displaynode, route->resultnodes, sizeof(struct resultnodes_s) * route->numresultnodes);
}
else if (route->callback && route->world->spawncount == route->spawncount/* && route->spawnid == route->ed->xv->uniquespawnid*/)
{
struct globalvars_s * pr_globals = PR_globals(prinst, PR_CURRENT);
struct resultnodes_s *ptr = prinst->AddressableAlloc(prinst, sizeof(struct resultnodes_s) * route->numresultnodes);
memcpy(ptr, route->resultnodes, sizeof(struct resultnodes_s) * route->numresultnodes);
G_INT(OFS_PARM0) = EDICT_TO_PROG(prinst, route->ed);
VectorCopy(route->end, G_VECTOR(OFS_PARM1));
G_INT(OFS_PARM2) = route->numresultnodes;
G_INT(OFS_PARM3) = (char*)ptr-prinst->stringtable;
PR_ExecuteProgram(prinst, route->callback);
}
//and we're done. destroy everything.
WayNet_Done(route->waynet);
Z_Free(route->resultnodes);
Z_Free(route);
}
//#define FLOODALL
#define COST_INFINITE FLT_MAX
static qboolean Route_Completed(struct routecalc_s *r, int *nodecamefrom)
{
size_t u;
struct waypointnetwork_s *n = r->waynet;
r->resultnodes = Z_Malloc(sizeof(*r->resultnodes)*(n->numwaypoints+1)*3);
r->numresultnodes = 0;
//target point is first. yay.
VectorCopy(r->end, r->resultnodes[0].pos);
r->resultnodes[0].linkflags = LF_DESTINATION;
r->numresultnodes++;
u = r->endn;
for (;;)
{
VectorCopy(n->waypoints[u].org, r->resultnodes[r->numresultnodes].pos);
r->resultnodes[r->numresultnodes].linkflags = 0;
r->numresultnodes++;
if (u == r->startn)
break;
u = nodecamefrom[u];
}
//and include the start point, because we can
VectorCopy(r->start, r->resultnodes[r->numresultnodes].pos);
r->resultnodes[r->numresultnodes].linkflags = 0;
r->numresultnodes++;
return true;
}
#if 1
static float Route_GuessCost(struct routecalc_s *r, float *fromorg)
{ //if we want to guarentee the shortest route, then we MUST always return a value <= to the actual cost here.
//unfortunately we don't know how many teleporters are between the two points.
//on the plus side, a little randomness here means we'll find alternative (longer) routes some times, which will reduce flash points and help flag carriers...
vec3_t disp;
VectorSubtract(r->end, fromorg, disp);
return sqrt(DotProduct(disp,disp));
}
static qboolean Route_Process(struct routecalc_s *r)
{
struct waypointnetwork_s *n = r->waynet;
int opennodes = 0;
int u, j;
float guesscost;
struct opennode_s {
int node;
float cost;
} *open = alloca(sizeof(*open)*n->numwaypoints);
float *nodecost = alloca(sizeof(*nodecost)*n->numwaypoints);
int *nodecamefrom = alloca(sizeof(*nodecamefrom)*n->numwaypoints);
for(u = 0; u < n->numwaypoints; u++)
nodecost[u] = COST_INFINITE;
if (r->startn >= 0)
{
nodecost[r->startn] = 0;
open[0].node = r->startn;
open[0].cost = 0;
opennodes++;
}
while(opennodes)
{
int nodeidx = open[--opennodes].node;
struct waypoint_s *wp = &n->waypoints[nodeidx];
#ifdef _DEBUG
if (nodeidx < 0 || nodeidx >= n->numwaypoints)
{
Con_Printf("Bad node index in open list\n");
return false;
}
#endif
if (nodeidx == r->endn)
{ //we found the end!
return Route_Completed(r, nodecamefrom);
}
for (u = 0; u < wp->neighbours; u++)
{
struct wpneighbour_s *l = &wp->neighbour[u];
int linkidx = l->node;
float realcost = nodecost[nodeidx] + l->linkcost;
#ifdef _DEBUG
if (linkidx < 0 || linkidx >= n->numwaypoints)
{
Con_Printf("Bad node link index in routing table\n");
return false;
}
#endif
if (realcost >= nodecost[linkidx])
continue;
nodecamefrom[linkidx] = nodeidx;
nodecost[linkidx] = realcost;
for (j = opennodes-1; j >= 0; j--)
{
if (open[j].node == linkidx)
break;
}
guesscost = realcost + Route_GuessCost(r, n->waypoints[linkidx].org);
if (j < 0)
{ //not already in the list
//tbh, we should probably just directly bubble in this loop instead of doing the memcpy (with its internal second loop).
for (j = opennodes-1; j >= 0; j--)
if (guesscost <= open[j].cost)
break;
j++;
//move them up
memmove(&open[j+1], &open[j], sizeof(*open)*(opennodes-j));
open[j].node = linkidx;
open[j].cost = guesscost;
opennodes++;
}
else if (guesscost < open[j].cost)
{ //if it got cheaper, be prepared to move the node towards the higher addresses (these will be checked first).
for (; j+1 < opennodes && open[j+1].cost > guesscost; j++)
open[j] = open[j+1];
//okay, so we can't keep going... this is our new slot!
open[j].node = linkidx;
open[j].cost = guesscost;
}
//otherwise it got more expensive, and we don't care about that
}
}
return false;
}
#else
static qboolean Route_Process(struct routecalc_s *r)
{
struct waypointnetwork_s *n = r->waynet;
int opennodes = 0;
int u, j;
//we use an open list in a desperate attempt to avoid recursing the entire network
int *open = alloca(sizeof(*open)*n->numwaypoints);
float *nodecost = alloca(sizeof(*nodecost)*n->numwaypoints);
int *nodecamefrom = alloca(sizeof(*nodecamefrom)*n->numwaypoints);
for(u = 0; u < n->numwaypoints; u++)
nodecost[u] = COST_INFINITE;
nodecost[r->startn] = 0;
open[opennodes++] = r->startn;
while(opennodes)
{
int nodeidx = open[--opennodes];
struct waypoint_s *wp = &n->waypoints[nodeidx];
// if (nodeidx < 0 || nodeidx >= n->numwaypoints)
// return false;
for (u = 0; u < wp->neighbours; u++)
{
struct wpneighbour_s *l = &wp->neighbour[u];
int linkidx = l->node;
float realcost = nodecost[nodeidx] + l->linkcost;
// if (linkidx < 0 || linkidx >= n->numwaypoints)
// return false;
if (realcost >= nodecost[linkidx])
continue;
nodecamefrom[linkidx] = nodeidx;
nodecost[linkidx] = realcost;
for (j = 0; j < opennodes; j++)
{
if (open[j] == linkidx)
break;
}
if (j == opennodes) //not already queued
open[opennodes++] = linkidx;
}
}
if (r->endn >= 0 && nodecost[r->endn] < COST_INFINITE)
{ //we found the end! we can build the route from end to start.
return Route_Completed(r, nodecamefrom);
}
return false;
}
#endif
//worker thread
void Route_Calculate(void *ctx, void *data, size_t a, size_t b)
{
struct routecalc_s *route = data;
//first thing is to find the start+end nodes.
if (route->waynet && route->startn >= 0 && route->endn >= 0 && Route_Process(route))
;
else
{
route->numresultnodes = 0;
route->resultnodes = Z_Malloc(sizeof(*route->resultnodes)*2);
VectorCopy(route->end, route->resultnodes[0].pos);
route->resultnodes[0].linkflags = LF_DESTINATION;
route->numresultnodes++;
VectorCopy(route->start, route->resultnodes[route->numresultnodes].pos);
route->resultnodes[route->numresultnodes].linkflags = 0;
route->numresultnodes++;
}
COM_AddWork(WG_MAIN, Route_Calculated, NULL, route, 0, 0);
}
/*
=============
PF_route_calculate
engine reads+caches the nodes from a file.
the route's nodes must be memfreed on completion.
the first node in the nodelist is the destination.
typedef struct {
vector dest;
int linkflags;
} nodeslist_t;
void(entity ent, vector dest, int denylinkflags, void(entity ent, vector dest, int numnodes, nodeslist_t *nodelist) callback) route_calculate = #0;
=============
*/
void QCBUILTIN PF_route_calculate (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
struct routecalc_s *route = Z_Malloc(sizeof(*route));
float *end;
route->world = prinst->parms->user;
route->spawncount = route->world->spawncount;
route->ed = G_WEDICT(prinst, OFS_PARM0);
// route->spawnid = route->ed->xv->uniquespawnid;
end = G_VECTOR(OFS_PARM1);
route->denylinkflags = G_INT(OFS_PARM2);
route->callback = G_INT(OFS_PARM3);
VectorCopy(route->ed->v->origin, route->start);
VectorCopy(end, route->end);
route->waynet = WayNet_Begin(&route->world->waypoints, route->world->worldmodel);
//tracelines use some sequence info to avoid retracing the same brush multiple times.
// this means that we can't reliably trace on worker threads (would break the main thread occasionally).
// so we have to do this here.
//FIXME: find a safe way to NOT do this here.
route->startn = WayNet_FindNearestNode(route->waynet, route->start);
route->endn = WayNet_FindNearestNode(route->waynet, route->end);
COM_AddWork(WG_LOADER, Route_Calculate, NULL, route, 0, 0);
}
#ifndef SERVERONLY
static void Route_Visualise_f(void)
{
extern world_t csqc_world;
vec3_t targ = {atof(Cmd_Argv(1)),atof(Cmd_Argv(2)),atof(Cmd_Argv(3))};
struct routecalc_s *route = Z_Malloc(sizeof(*route));
route->world = &csqc_world;
route->spawncount = route->world->spawncount;
route->ed = route->world->edicts;
// route->spawnid = route->ed->xv->uniquespawnid;
VectorCopy(r_refdef.vieworg, route->start);
VectorCopy(targ, route->end);
route->waynet = WayNet_Begin(&route->world->waypoints, route->world->worldmodel);
//tracelines use some sequence info to avoid retracing the same brush multiple times.
// this means that we can't reliably trace on worker threads (would break the main thread occasionally).
// so we have to do this here.
//FIXME: find a safe way to NOT do this here.
route->startn = WayNet_FindNearestNode(route->waynet, route->start);
route->endn = WayNet_FindNearestNode(route->waynet, route->end);
COM_AddWork(WG_LOADER, Route_Calculate, NULL, route, 0, 0);
}
#include "shader.h"
void PR_Route_Visualise (void)
{
extern world_t csqc_world;
world_t *w = &csqc_world;
struct waypointnetwork_s *wn;
size_t u;
wn = (w && (w->waypoints || route_shownodes.ival))?WayNet_Begin(&w->waypoints, w->worldmodel):NULL;
if (wn)
{
if (route_shownodes.ival)
{
float mat[12] = {1,0,0,0, 0,1,0,0, 0,0,1,0};
shader_t *shader_out = R_RegisterShader("waypointvolume_out", SUF_NONE,
"{\n"
"polygonoffset\n"
"nodepth\n"
"{\n"
"map $whiteimage\n"
"blendfunc add\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"}\n"
"}\n");
shader_t *shader_in = R_RegisterShader("waypointvolume_in", SUF_NONE,
"{\n"
"polygonoffset\n"
"cull disable\n"
"nodepth\n"
"{\n"
"map $whiteimage\n"
"blendfunc add\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"}\n"
"}\n");
float radius;
vec3_t dir;
//should probably use a different colour for the node you're inside.
for (u = 0; u < wn->numwaypoints; u++)
{
mat[3] = wn->waypoints[u].org[0];
mat[7] = wn->waypoints[u].org[1];
mat[11] = wn->waypoints[u].org[2];
radius = wn->waypoints[u].radius;
if (radius <= 0)
radius = 1; //waypoints shouldn't really have a radius of 0, but if they do we'll still want to draw something.
VectorSubtract(wn->waypoints[u].org, r_refdef.vieworg, dir);
if (DotProduct(dir,dir) < radius*radius)
CLQ1_AddOrientedSphere(shader_in, radius, mat, 0.0, 0.1, 0, 1);
else
CLQ1_AddOrientedSphere(shader_out, radius, mat, 0.2, 0.0, 0, 1);
}
for (u = 0; u < wn->numwaypoints; u++)
{
size_t n;
for (n = 0; n < wn->waypoints[u].neighbours; n++)
{
struct waypoint_s *r = wn->waypoints + wn->waypoints[u].neighbour[n].node;
CLQ1_DrawLine(shader_out, wn->waypoints[u].org, r->org, 0, 0, 1, 1);
}
}
}
if (wn->displaynodes)
{ //FIXME: we should probably use beams here
shader_t *shader_route = R_RegisterShader("waypointroute", SUF_NONE,
"{\n"
"polygonoffset\n"
"nodepth\n"
"{\n"
"map $whiteimage\n"
"blendfunc add\n"
"rgbgen vertex\n"
"alphagen vertex\n"
"}\n"
"}\n");
for (u = wn->displaynodes-1; u > 0; u--)
{
vec_t *start = wn->displaynode[u].pos;
vec_t *end = wn->displaynode[u-1].pos;
CLQ1_DrawLine(shader_route, start, end, 0.5, 0.5, 0.5, 1);
}
}
}
WayNet_Done(wn);
}
#endif
//destroys the routing waypoint cache.
void PR_Route_Shutdown (world_t *world)
{
WayNet_Done(world->waypoints);
world->waypoints = NULL;
}
static void Route_Reload_f(void)
{
#if !defined(SERVERONLY) && defined(CSQC_DAT)
extern world_t csqc_world;
PR_Route_Shutdown(&csqc_world);
#endif
#ifndef CLIENTONLY
PR_Route_Shutdown(&sv.world);
#endif
}
void PR_Route_Init (void)
{
#if !defined(SERVERONLY) && defined(CSQC_DAT)
Cvar_Register(&route_shownodes, NULL);
Cmd_AddCommand("route_visualise", Route_Visualise_f);
#endif
Cmd_AddCommand("route_reload", Route_Reload_f);
}
//route_force
//COM_WorkerPartialSync
#endif
#endif

View file

@ -6898,6 +6898,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
movevars.slidyslopes = (pm_slidyslopes.value!=0);
movevars.watersinkspeed = *pm_watersinkspeed.string?pm_watersinkspeed.value:60;
movevars.flyfriction = *pm_flyfriction.string?pm_flyfriction.value:4;
movevars.coordsize = host_client->netchan.netprim.coordsize;
for (i=0 ; i<3 ; i++)
{
@ -7144,6 +7145,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse)
movevars.slidyslopes = (pm_slidyslopes.value!=0);
movevars.watersinkspeed = *pm_watersinkspeed.string?pm_watersinkspeed.value:60;
movevars.flyfriction = *pm_flyfriction.string?pm_flyfriction.value:4;
movevars.coordsize = host_client->netchan.netprim.coordsize;
// should already be folded into host_client->maxspeed
// if (sv_player->xv->hasted)

View file

@ -0,0 +1,293 @@
//!!ver 100 150
//!!permu DELUXE
!!permu FULLBRIGHT
!!permu FOG
//!!permu LIGHTSTYLED
//!!permu BUMP
//!!permu SPECULAR
//!!permu REFLECTCUBEMASK
//!!cvarf r_glsl_offsetmapping_scale
//!!cvardf r_tessellation_level=5
//!!samps diffuse lightmap specular normalmap fullbright reflectmask reflectcube paletted lightmap1 lightmap2 lightmap3
!!samps diffuse fullbright lightmap
#undef SPECULAR
//#include "sys/defs.h"
#define vec4 float4
#define vec3 float3
#define vec2 float2
#define texture2D tex2D
#define mat3 float3x3
#define mat4 float4x4
struct a2v
{
vec4 v_position : POSITION;
vec2 v_texcoord : TEXCOORD0;
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
vec3 v_normal : NORMAL;
vec3 v_svector : TANGENT;
vec3 v_tvector : BINORMAL;
#endif
#ifdef VERTEXLIT
vec4 v_colour : COLOR0;
#else
vec2 v_lmcoord : TEXCOORD1;
#endif
};
struct v2f
{
#ifndef FRAGMENT_SHADER
vec4 pos: POSITION;
#endif
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK) || defined(FOG)
vec3 eyevector : TEXCOORD4;
#endif
#if defined(REFLECTCUBEMASK) || defined(BUMPMODELSPACE)
mat3 invsurface : TEXCOORD5;
#endif
#ifdef VERTEXLIT
vec2 tclm : TEXCOORD0;
#else
vec4 tclm : TEXCOORD0;
#endif
vec4 vc : COLOR0;
#ifndef VERTEXLIT
#ifdef LIGHTSTYLED
//we could use an offset, but that would still need to be per-surface which would break batches
//fixme: merge attributes?
vec2 lm1 : TEXCOORD1, lm2 : TEXCOORD2, lm3 : TEXCOORD3;
#endif
#endif
};
//this is what normally draws all of your walls, even with rtlights disabled
//note that the '286' preset uses drawflat_walls instead.
#include "sys/fog.h"
#ifdef VERTEX_SHADER
float4x4 m_modelviewprojection;
float4x4 m_modelview;
vec3 e_eyepos;
vec4 e_lmscale;
v2f main (a2v inp)
{
v2f outp;
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
vec3 eyeminusvertex = e_eyepos - inp.v_position.xyz;
outp.eyevector.x = dot(eyeminusvertex, inp.v_svector.xyz);
outp.eyevector.y = dot(eyeminusvertex, inp.v_tvector.xyz);
outp.eyevector.z = dot(eyeminusvertex, inp.v_normal.xyz);
#elif defined(FOG)
outp.eyevector = mul(m_modelview, inp.v_position);
#endif
#if defined(REFLECTCUBEMASK) || defined(BUMPMODELSPACE)
outp.invsurface[0] = inp.v_svector;
outp.invsurface[1] = inp.v_tvector;
outp.invsurface[2] = inp.v_normal;
#endif
outp.tclm.xy = inp.v_texcoord;
#ifdef FLOW
// outp.tclm.x += e_time * -0.5;
#endif
#ifdef VERTEXLIT
#ifdef LIGHTSTYLED
//FIXME, only one colour.
outp.vc = inp.v_colour * e_lmscale[0];
#else
outp.vc = inp.v_colour * e_lmscale;
#endif
#else
outp.vc = e_lmscale;
outp.tclm.zw = inp.v_lmcoord;
#ifdef LIGHTSTYLED
outp.lm1 = inp.v_lmcoord2;
outp.lm2 = inp.v_lmcoord3;
outp.lm3 = inp.v_lmcoord4;
#endif
#endif
outp.pos = mul(m_modelviewprojection, inp.v_position);
return outp;
}
#endif
#ifdef FRAGMENT_SHADER
sampler s_diffuse : register(s0);
//sampler s_normalmap;
//sampler s_specular;
//sampler s_upper;
//sampler s_lower;
sampler s_fullbright : register(s1);
//sampler s_paletted;
//sampler s_reflectcube;
//sampler s_reflectmask;
sampler s_lightmap : register(s2);
//sampler s_deluxmap;
//samplers
#define s_colourmap s_t0
//sampler2D s_colourmap;
//vec4 e_lmscale;
vec4 e_colourident;
#ifdef OFFSETMAPPING
#include "sys/offsetmapping.h"
#endif
vec4 main (v2f inp) : COLOR0
{
vec4 gl_FragColor;
#define tc (inp.tclm.xy)
#define lm0 (inp.tclm.zw)
//adjust texture coords for offsetmapping
#ifdef OFFSETMAPPING
vec2 tcoffsetmap = offsetmap(s_normalmap, tc, eyevector);
#define tc tcoffsetmap
#endif
#if defined(EIGHTBIT) && !defined(LIGHTSTYLED)
//optional: round the lightmap coords to ensure all pixels within a texel have different lighting values either. it just looks wrong otherwise.
//don't bother if its lightstyled, such cases will have unpredictable correlations anyway.
//FIXME: this rounding is likely not correct with respect to software rendering. oh well.
#if __VERSION__ >= 130
vec2 lmsize = vec2(textureSize(s_lightmap0, 0));
#else
#define lmsize vec2(128.0,2048.0)
#endif
#define texelstolightmap (16.0)
vec2 lmcoord0 = floor(lm0 * lmsize*texelstolightmap)/(lmsize*texelstolightmap);
#define lm0 lmcoord0
#endif
//yay, regular texture!
gl_FragColor = texture2D(s_diffuse, tc);
#if defined(BUMP) && (defined(DELUXE) || defined(SPECULAR) || defined(REFLECTCUBEMASK))
vec3 norm = normalize(texture2D(s_normalmap, tc).rgb - 0.5);
#elif defined(SPECULAR) || defined(DELUXE) || defined(REFLECTCUBEMASK)
vec3 norm = vec3(0, 0, 1); //specular lighting expects this to exist.
#endif
//modulate that by the lightmap(s) including deluxemap(s)
#ifdef VERTEXLIT
#ifdef LIGHTSTYLED
vec3 lightmaps = inp.vc.rgb;
#else
vec3 lightmaps = inp.vc.rgb;
#endif
#define delux vec3(0.0,0.0,1.0)
#else
#ifdef LIGHTSTYLED
#error foobar
#define delux vec3(0.0,0.0,1.0)
vec3 lightmaps;
#ifdef DELUXE
lightmaps = texture2D(s_lightmap0, lm0).rgb * e_lmscale[0].rgb * dot(norm, 2.0*texture2D(s_deluxmap0, lm0).rgb-0.5);
lightmaps += texture2D(s_lightmap1, lm1).rgb * e_lmscale[1].rgb * dot(norm, 2.0*texture2D(s_deluxmap1, lm1).rgb-0.5);
lightmaps += texture2D(s_lightmap2, lm2).rgb * e_lmscale[2].rgb * dot(norm, 2.0*texture2D(s_deluxmap2, lm2).rgb-0.5);
lightmaps += texture2D(s_lightmap3, lm3).rgb * e_lmscale[3].rgb * dot(norm, 2.0*texture2D(s_deluxmap3, lm3).rgb-0.5);
#else
lightmaps = texture2D(s_lightmap0, lm0).rgb * e_lmscale[0].rgb;
lightmaps += texture2D(s_lightmap1, lm1).rgb * e_lmscale[1].rgb;
lightmaps += texture2D(s_lightmap2, lm2).rgb * e_lmscale[2].rgb;
lightmaps += texture2D(s_lightmap3, lm3).rgb * e_lmscale[3].rgb;
#endif
#else
vec3 lightmaps = texture2D(s_lightmap, lm0).rgb;
//modulate by the bumpmap dot light
#ifdef DELUXE
#error foobar
vec3 delux = (texture2D(s_deluxmap, lm0).rgb-0.5);
#ifdef BUMPMODELSPACE
delux = normalize(delux*invsurface);
#else
lightmaps *= 2.0 / max(0.25, delux.z); //counter the darkening from deluxmaps
#endif
lightmaps *= dot(norm, delux);
#else
#define delux vec3(0.0,0.0,1.0)
#endif
#endif
lightmaps *= inp.vc.rgb;
#endif
//add in specular, if applicable.
#ifdef SPECULAR
vec4 specs = texture2D(s_specular, tc);
vec3 halfdir = normalize(normalize(eyevector) + delux); //this norm should be the deluxemap info instead
float spec = pow(max(dot(halfdir, norm), 0.0), FTE_SPECULAR_EXPONENT * specs.a);
spec *= FTE_SPECULAR_MULTIPLIER;
//NOTE: rtlights tend to have a *4 scaler here to over-emphasise the effect because it looks cool.
//As not all maps will have deluxemapping, and the double-cos from the light util makes everything far too dark anyway,
//we default to something that is not garish when the light value is directly infront of every single pixel.
//we can justify this difference due to the rtlight editor etc showing the *4.
gl_FragColor.rgb += spec * specs.rgb;
#endif
#ifdef REFLECTCUBEMASK
vec3 rtc = reflect(normalize(-eyevector), norm);
rtc = rtc.x*invsurface[0] + rtc.y*invsurface[1] + rtc.z*invsurface[2];
rtc = (m_model * vec4(rtc.xyz,0.0)).xyz;
gl_FragColor.rgb += texture2D(s_reflectmask, tc).rgb * textureCube(s_reflectcube, rtc).rgb;
#endif
#ifdef EIGHTBIT //FIXME: with this extra flag, half the permutations are redundant.
lightmaps *= 0.5; //counter the fact that the colourmap contains overbright values and logically ranges from 0 to 2 intead of to 1.
float pal = texture2D(s_paletted, tc).r; //the palette index. hopefully not interpolated.
lightmaps -= 1.0 / 128.0; //software rendering appears to round down, so make sure we favour the lower values instead of rounding to the nearest
gl_FragColor.r = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.r)).r; //do 3 lookups. this is to cope with lit files, would be a waste to not support those.
gl_FragColor.g = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.g)).g; //its not very softwarey, but re-palettizing is ugly.
gl_FragColor.b = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.b)).b; //without lits, it should be identical.
#else
//now we have our diffuse+specular terms, modulate by lightmap values.
gl_FragColor.rgb *= lightmaps.rgb;
//add on the fullbright
#ifdef FULLBRIGHT
vec4 fb = texture2D(s_fullbright, tc);
gl_FragColor.rgb += fb.rgb*fb.a;
#endif
#endif
//entity modifiers
gl_FragColor = gl_FragColor * e_colourident;
#if defined(MASK)
#if defined(MASKLT)
if (gl_FragColor.a < MASK)
discard;
#else
if (gl_FragColor.a >= MASK)
discard;
#endif
gl_FragColor.a = 1.0; //alpha blending AND alpha testing usually looks stupid, plus it screws up our fog.
#endif
//and finally hide it all if we're fogged.
#ifdef FOG
gl_FragColor = fog4(gl_FragColor, length(inp.eyevector));
#endif
return gl_FragColor;
}
#endif

View file

@ -2672,6 +2672,7 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
VkPipelineColorBlendAttachmentState att_state[1];
VkGraphicsPipelineCreateInfo pipeCreateInfo = {VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO};
VkPipelineShaderStageCreateInfo shaderStages[2] = {{0}};
VkPipelineRasterizationStateRasterizationOrderAMD ro = {VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD}; //long enough names for you?
struct specdata_s
{
int alphamode;
@ -2802,18 +2803,39 @@ static void BE_CreatePipeline(program_t *p, unsigned int shaderflags, unsigned i
else
rs.depthBiasEnable = VK_FALSE;
if (vk.amd_rasterization_order)
{
unsigned int b = blendflags & SBITS_BLEND_BITS;
//we potentially allow a little z-fighting if they're equal. a single batch shouldn't really have such primitives.
//must be no blending, or additive blending.
switch(blendflags & SBITS_DEPTHFUNC_BITS)
{
case SBITS_DEPTHFUNC_EQUAL:
break;
default:
if ((blendflags&(SBITS_MISC_NODEPTHTEST|SBITS_MISC_DEPTHWRITE)) == SBITS_MISC_DEPTHWRITE &&
(!b || b == (SBITS_SRCBLEND_ONE|SBITS_DSTBLEND_ZERO) || b == SBITS_DSTBLEND_ONE))
{
rs.pNext = &ro;
ro.rasterizationOrder = VK_RASTERIZATION_ORDER_RELAXED_AMD;
}
}
}
ms.pSampleMask = NULL;
ms.rasterizationSamples = vk.multisamplebits;
// ms.sampleShadingEnable = VK_TRUE; //call the fragment shader multiple times, instead of just once per final pixel
// ms.minSampleShading = 0.25;
ds.depthTestEnable = (blendflags&SBITS_MISC_NODEPTHTEST)?VK_FALSE:VK_TRUE;
ds.depthWriteEnable = (blendflags&SBITS_MISC_DEPTHWRITE)?VK_TRUE:VK_FALSE;
if (blendflags & SBITS_MISC_DEPTHEQUALONLY)
ds.depthCompareOp = VK_COMPARE_OP_EQUAL;
else if (blendflags & SBITS_MISC_DEPTHCLOSERONLY)
ds.depthCompareOp = VK_COMPARE_OP_LESS;
else
ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
switch(blendflags & SBITS_DEPTHFUNC_BITS)
{
default:
case SBITS_DEPTHFUNC_CLOSEREQUAL: ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; break;
case SBITS_DEPTHFUNC_EQUAL: ds.depthCompareOp = VK_COMPARE_OP_EQUAL; break;
case SBITS_DEPTHFUNC_CLOSER: ds.depthCompareOp = VK_COMPARE_OP_LESS; break;
case SBITS_DEPTHFUNC_FURTHER: ds.depthCompareOp = VK_COMPARE_OP_GREATER; break;
}
ds.depthBoundsTestEnable = VK_FALSE;
ds.back.failOp = VK_STENCIL_OP_KEEP;
ds.back.passOp = VK_STENCIL_OP_KEEP;
@ -3016,7 +3038,7 @@ static void BE_BindPipeline(program_t *p, unsigned int shaderflags, unsigned int
struct pipeline_s *pipe;
blendflags &= 0
| SBITS_SRCBLEND_BITS | SBITS_DSTBLEND_BITS | SBITS_MASK_BITS | SBITS_ATEST_BITS
| SBITS_MISC_DEPTHWRITE | SBITS_MISC_NODEPTHTEST | SBITS_MISC_DEPTHEQUALONLY | SBITS_MISC_DEPTHCLOSERONLY
| SBITS_MISC_DEPTHWRITE | SBITS_MISC_NODEPTHTEST | SBITS_DEPTHFUNC_BITS
| SBITS_LINES
;
shaderflags &= 0

View file

@ -15,6 +15,7 @@ extern cvar_t vk_nv_glsl_shader;
extern cvar_t vk_nv_dedicated_allocation;
extern cvar_t vk_khr_dedicated_allocation;
extern cvar_t vk_khr_push_descriptor;
extern cvar_t vk_amd_rasterization_order;
extern cvar_t vid_srgb, vid_vsync, vid_triplebuffer, r_stereo_method, vid_multisample, vid_bpp;
void R2D_Console_Resize(void);
@ -426,7 +427,7 @@ static qboolean VK_CreateSwapChain(void)
{ //using vulkan's presentation engine.
int BOOST_UNORM, BOOST_SNORM, BOOST_SRGB, BOOST_UFLOAT, BOOST_SFLOAT;
if (vid_srgb.ival > 2)
if (vid_srgb.ival > 1)
{ //favour float formats, then srgb, then unorms
BOOST_UNORM = 0;
BOOST_SNORM = 0;
@ -602,7 +603,7 @@ static qboolean VK_CreateSwapChain(void)
if (swapinfo.imageFormat == VK_FORMAT_UNDEFINED)
{ //if we found this format then it means the drivers don't really give a damn. pick a real format.
if (vid_srgb.ival > 2 && swapinfo.imageColorSpace == VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT)
if (vid_srgb.ival > 1 && swapinfo.imageColorSpace == VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT)
swapinfo.imageFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
else if (vid_srgb.ival)
swapinfo.imageFormat = VK_FORMAT_R8G8B8A8_SRGB;
@ -3803,15 +3804,16 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
cvar_t *var;
qboolean def;
qboolean *superseeded; //if this is set then the extension will not be enabled after all
const char *neededfor;
const char *warningtext; //printed if the extension is requested but not supported by the device
qboolean supported;
} knowndevexts[] =
{
{&vk.khr_swapchain, VK_KHR_SWAPCHAIN_EXTENSION_NAME, NULL, true, NULL, " Nothing will be drawn!"},
{&vk.nv_glsl_shader, VK_NV_GLSL_SHADER_EXTENSION_NAME, &vk_nv_glsl_shader, false, NULL, " Direct use of glsl is not supported."},
{&vk.nv_dedicated_allocation, VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME, &vk_nv_dedicated_allocation, true, &vk.khr_dedicated_allocation, ""},
{&vk.khr_dedicated_allocation, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, &vk_khr_dedicated_allocation, true, NULL, ""},
{&vk.khr_push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, &vk_khr_push_descriptor, true, NULL, ""},
{&vk.nv_dedicated_allocation, VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME, &vk_nv_dedicated_allocation, true, &vk.khr_dedicated_allocation, NULL},
{&vk.khr_dedicated_allocation, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, &vk_khr_dedicated_allocation, true, NULL, NULL},
{&vk.khr_push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, &vk_khr_push_descriptor, true, NULL, NULL},
{&vk.amd_rasterization_order, VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME, &vk_amd_rasterization_order, false, NULL, NULL},
};
size_t e;
@ -4200,7 +4202,7 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
devextensions[numdevextensions++] = knowndevexts[e].name;
}
else if (knowndevexts[e].var->ival)
Con_Printf("unable to enable %s extension.%s\n", knowndevexts[e].name, knowndevexts[e].neededfor);
Con_Printf("unable to enable %s extension.%s\n", knowndevexts[e].name, knowndevexts[e].warningtext?knowndevexts[e].warningtext:"");
else if (knowndevexts[e].supported)
Con_DPrintf("Ignoring %s.\n", knowndevexts[e].name);
else

View file

@ -257,6 +257,7 @@ extern struct vulkaninfo_s
qboolean nv_dedicated_allocation; //nvidia-specific extension that provides hints that there's no memory aliasing going on.
qboolean khr_dedicated_allocation; //standardised version of the above where the driver decides whether a resource is worth a dedicated allocation.
qboolean khr_push_descriptor; //more efficient descriptor streaming
qboolean amd_rasterization_order; //allows primitives to draw in any order
VkInstance instance;
VkDevice device;

View file

@ -304,6 +304,8 @@ void GLVID_DeInit (void)
vid.activeapp = false;
emscriptenfte_setupcanvas(-1, -1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
GL_ForgetPointers();
}

View file

@ -891,7 +891,7 @@ static void HTTPSV_GeneratePlugin(cluster_t *cluster, oproxy_t *dest)
"function playdemo(d)\n"
"{\n"
"getplug().mapsrc = \"http://bigfoot.morphos-team.net/misc/quakemaps/\";\n"
// "getplug().mapsrc = \"http://bigfoot.morphos-team.net/misc/quakemaps/\";\n"
"getplug().stream = \"file:\"+d+\"@"
;
Net_ProxySend(cluster, dest, html, strlen(html));