mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-10 06:32:00 +00:00
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:
parent
d56226aac5
commit
fdd903e0a3
50 changed files with 2037 additions and 350 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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...
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -120,6 +120,8 @@ typedef struct {
|
|||
qboolean slidyslopes;
|
||||
int stepheight;
|
||||
|
||||
qbyte coordsize;
|
||||
|
||||
unsigned int flags;
|
||||
} movevars_t;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1703,6 +1703,10 @@ void VID_UnSetMode (void)
|
|||
}
|
||||
*opengldllname = 0;
|
||||
#endif
|
||||
|
||||
#ifdef GLQUAKE
|
||||
GL_ForgetPointers();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -379,6 +379,7 @@ void GLVID_DeInit (void)
|
|||
#endif
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
GL_ForgetPointers();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1112,6 +1112,7 @@ void GL_SelectProgram(int program);
|
|||
|
||||
|
||||
qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name));
|
||||
void GL_ForgetPointers(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
293
engine/shaders/hlsl9/defaultwall.hlsl
Normal file
293
engine/shaders/hlsl9/defaultwall.hlsl
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in a new issue