fix a silly performance-sapping typo.

implemented identify+iplog stuff for nq users.
r_tessellation forces blinn tessellation on meshes. can also be specified manually.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5055 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2017-02-11 16:14:06 +00:00
parent f03a578eaa
commit 3061ed448f
28 changed files with 1544 additions and 384 deletions

View file

@ -88,6 +88,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define OS_STRING "win_msvc64"
#elif defined __MINGW64__
#define OS_STRING "win_mingw64"
#else
#define OS_STRING "win64"
#endif
#define ID_INLINE static __inline

View file

@ -27,12 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define MAX_TEAMIGNORELIST 4
#define FLOODLIST_SIZE 10
#define PLAYER_ID_NOMATCH -1
#define PLAYER_NAME_NOMATCH -2
#define PLAYER_NUM_NOMATCH -3
int Player_IdtoSlot (int id)
{
int j;
@ -45,7 +39,7 @@ int Player_IdtoSlot (int id)
return -1;
}
int Player_StringtoSlot(char *arg)
int Player_StringtoSlot(const char *arg)
{
int i, slot;

View file

@ -33,4 +33,10 @@ char Ignore_Check_Flood(player_info_t *sender, const char *s, int flags);
void Ignore_Flood_Add(player_info_t *sender, const char *s);
void Ignore_ResetFloodList(void);
#define PLAYER_ID_NOMATCH -1
#define PLAYER_NAME_NOMATCH -2
#define PLAYER_NUM_NOMATCH -3
int Player_StringtoSlot(const char *arg);
#endif

View file

@ -5852,6 +5852,7 @@ void Host_Shutdown(void)
#ifndef CLIENTONLY
SV_Shutdown();
#else
Log_ShutDown();
NET_Shutdown ();
FS_Shutdown();
#endif

View file

@ -1932,15 +1932,19 @@ int Master_CheckPollSockets(void)
info = Master_InfoForServer(&net_from);
if (selserver == info)
{
char playeraddrbuf[256];
int playernum = MSG_ReadByte();
char *playername = MSG_ReadString();
int playercolor = MSG_ReadLong();
int playerfrags = MSG_ReadLong();
int secsonserver = MSG_ReadLong();
//char *playeraddr = MSG_ReadString();
char *playeraddr = MSG_ReadStringBuffer(playeraddrbuf, sizeof(playeraddrbuf));
if (msg_badread)
continue;
//might as well
IPLog_Add(playeraddr, playername);
selectedserver.lastplayer = playernum+1;
memset(&info->moreinfo->players[playernum], 0, sizeof(info->moreinfo->players[playernum]));

View file

@ -309,9 +309,9 @@ cvar_t vid_gl_context_selfreset = CVARD ("vid_gl_context_selfreset", "1", "Upo
#endif
#if 1
cvar_t gl_ati_truform = CVAR ("gl_ati_truform", "0");
cvar_t r_tessellation = CVARAFD ("r_tessellation", "0", "gl_ati_truform", CVAR_SHADERSYSTEM, "Enables+controls the use of blinn tessellation on the fallback shader for meshes, equivelent to a shader with 'program defaultskin#TESS'. This will look stupid unless the meshes were actually designed for it and have suitable vertex normals.");
cvar_t gl_ati_truform_type = CVAR ("gl_ati_truform_type", "1");
cvar_t gl_ati_truform_tesselation = CVAR ("gl_ati_truform_tesselation", "3");
cvar_t r_tessellation_level = CVAR ("r_tessellation_level", "5");
cvar_t gl_blend2d = CVAR ("gl_blend2d", "1");
cvar_t gl_blendsprites = CVARD ("gl_blendsprites", "0", "Blend sprites instead of alpha testing them");
cvar_t r_deluxemapping_cvar = CVARAFD ("r_deluxemapping", "0", "r_glsl_deluxemapping",
@ -497,9 +497,9 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_dither, GRAPHICALNICETIES);
Cvar_Register (&r_fog_exp2, GLRENDEREROPTIONS);
Cvar_Register (&gl_ati_truform, GRAPHICALNICETIES);
Cvar_Register (&r_tessellation, GRAPHICALNICETIES);
Cvar_Register (&gl_ati_truform_type, GRAPHICALNICETIES);
Cvar_Register (&gl_ati_truform_tesselation, GRAPHICALNICETIES);
Cvar_Register (&r_tessellation_level, GRAPHICALNICETIES);
Cvar_Register (&gl_screenangle, GLRENDEREROPTIONS);

View file

@ -731,6 +731,7 @@ void Log_String (logtype_t lognum, char *s);
void Con_Log (char *s);
void Log_Logfile_f (void);
void Log_Init(void);
void Log_ShutDown(void);
void IPLog_Add(const char *ip, const char *name); //for associating player ip addresses with names.

View file

@ -4118,8 +4118,19 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
//light grid info
if (mod->lightgrid)
{
char gridsize[256], *key;
char val[64];
float maxs;
q3lightgridinfo_t *lg = mod->lightgrid;
key = (char*)Mod_ParseWorldspawnKey(mod, "gridsize", gridsize, sizeof(gridsize));
key = COM_ParseOut(key, val, sizeof(val));
lg->gridSize[0] = atof(val);
key = COM_ParseOut(key, val, sizeof(val));
lg->gridSize[1] = atof(val);
key = COM_ParseOut(key, val, sizeof(val));
lg->gridSize[2] = atof(val);
if ( lg->gridSize[0] < 1 || lg->gridSize[1] < 1 || lg->gridSize[2] < 1 )
{
lg->gridSize[0] = 64;

View file

@ -325,6 +325,52 @@ void SV_Fraglogfile_f (void)
}
*/
/*for fuck sake, why can people still not write simple files. proquake is writing binary files as text ones. this function is to try to deal with that fuckup*/
static size_t IPLog_Read_Fucked(qbyte *file, size_t *offset, size_t totalsize, qbyte *out, size_t outsize)
{
size_t read = 0;
while (outsize-- > 0 && *offset < totalsize)
{
if (file[*offset] == '\r' && *offset+1 < totalsize && file[*offset+1] == '\n')
{
out[read] = '\n';
*offset += 2;
read += 1;
}
else
{
out[read] = file[*offset];
*offset += 1;
read += 1;
}
}
return read;
}
/*need to make sure any 13 bytes followed by 10s don't bug out when read back in *sigh* */
static size_t IPLog_Write_Fucked(vfsfile_t *file, qbyte *out, size_t outsize)
{
qbyte tmp[64];
size_t write = 0;
size_t block = 0;
while (outsize-- > 0)
{
if (block >= sizeof(tmp)-4)
{
VFS_WRITE(file, tmp, block);
write += block;
block = 0;
}
if (*out == '\n')
tmp[block++] = '\r';
tmp[block++] = *out++;
}
if (block)
{
VFS_WRITE(file, tmp, block);
write += block;
}
return write;
}
static qboolean IPLog_Merge_File(const char *fname)
{
char ip[MAX_ADR_SIZE];
@ -333,18 +379,25 @@ static qboolean IPLog_Merge_File(const char *fname)
vfsfile_t *f;
if (!*fname)
fname = "iplog.txt";
f = FS_OpenVFS(fname, "rb", FS_PUBBASEGAMEONLY);
if (!f)
f = FS_OpenVFS(fname, "rb", FS_GAME);
if (!f)
return false;
if (!Q_strcasecmp(COM_FileExtension(fname, name, sizeof(name)), ".dat"))
if (!Q_strcasecmp(COM_FileExtension(fname, name, sizeof(name)), "dat"))
{ //we don't write this format because of it being limited to ipv4, as well as player name lengths
while (VFS_READ(f, line, 20) == 20)
{
Q_snprintfz(ip, sizeof(ip), "%i.%i.%i.%i", (qbyte)line[0], (qbyte)line[1], (qbyte)line[2], (qbyte)line[3]);
size_t l = VFS_GETLEN(f), offset = 0;
qbyte *ffs = malloc(l+1);
VFS_READ(f, ffs, l);
ffs[l] = 0;
while (IPLog_Read_Fucked(ffs, &offset, l, line, 20) == 20)
{ //yes, these addresses are weird.
Q_snprintfz(ip, sizeof(ip), "%i.%i.%i.xxx", (qbyte)line[2], (qbyte)line[1], (qbyte)line[0]);
memcpy(name, line+4, 20-4);
name[20-4] = 0;
IPLog_Add(ip, name);
}
free(ffs);
}
else
{
@ -360,47 +413,185 @@ static qboolean IPLog_Merge_File(const char *fname)
VFS_CLOSE(f);
return true;
}
struct iplog_entry
{
netadr_t adr;
netadr_t mask;
char name[1];
} **iplog_entries;
size_t iplog_num, iplog_max;
void IPLog_Add(const char *ipstr, const char *name)
{
size_t i;
netadr_t a, m;
while (*ipstr == ' ' || *ipstr == '\t')
ipstr++;
if (*ipstr != '[' && *ipstr < '0' && *ipstr > '9')
return;
if (*ipstr == '[')
ipstr++;
//some names are dodgy.
if (!*name
//|| !Q_strcasecmp(name, /*nq default*/"player") || !Q_strcasecmp(name, /*qw default*/"unnamed")
|| !strcmp(name, /*nq fallback*/"unconnected") || !strncmp(name, "BOT:", 4))
return;
memset(&a, 0, sizeof(a));
memset(&m, 0, sizeof(m));
if (!NET_StringToAdrMasked(ipstr, false, &a, &m))
return;
//might be x.y.z.w:port
//might be x.y.z.FUCKED
//might be x.y.z.0/24
//might be [::]:port
//might be [::]/bits
//or other ways to express an ip address
//note that ipv4 addresses should be converted to ipv6 ::ffff:x.y.z.w format for internal use or something, then this code only needs to deal with a single 128bit address format.
//ipv6 addresses generally only need 64bits to identify a user's home router, the other 64bits are generally 'just' to avoid nats.
//ignore ipx addresses, I doubt anyone will ever actually use it, and even if they do its just lans.
//FIXME: ignore private addresses?
//check for dupes
for (i = 0; i < iplog_num; i++)
{
if (!memcmp(&a, &iplog_entries[i]->adr, sizeof(netadr_t)) && !memcmp(&m, &iplog_entries[i]->mask, sizeof(netadr_t)) && !Q_strcasecmp(name, iplog_entries[i]->name))
return;
}
//looks like its new...
if (iplog_num == iplog_max)
Z_ReallocElements((void**)&iplog_entries, &iplog_max, iplog_max+64, sizeof(*iplog_entries));
iplog_entries[iplog_num] = BZ_Malloc(sizeof(struct iplog_entry) + strlen(name));
iplog_entries[iplog_num]->adr = a;
iplog_entries[iplog_num]->mask = m;
strcpy(iplog_entries[iplog_num]->name, name);
iplog_num++;
}
static void IPLog_Identify(netadr_t *adr, netadr_t *mask, char *fmt, ...)
{
va_list argptr;
qboolean found = false;
char line[256];
size_t i;
va_start(argptr, fmt);
vsnprintf(line, sizeof(line), fmt, argptr);
va_end(argptr);
Con_Printf("%s: ", line);
for (i = 0; i < iplog_num; i++)
{
if (NET_CompareAdrMasked(adr, &iplog_entries[i]->adr, mask?mask:&iplog_entries[i]->mask))
{
if (found)
Con_Printf(", ");
found=true;
Con_Printf("%s", iplog_entries[i]->name);
}
}
if (!found)
Con_Printf("<no matches>");
Con_Printf("\n");
}
#include "cl_ignore.h"
static void IPLog_Identify_f(void)
{
// const char *nameorip = Cmd_Argv(1);
Con_Printf("Not yet implemented\n");
const char *nameorip = Cmd_Argv(1);
netadr_t adr, mask;
char clean[256];
//if *, use a mask that includes all ips
//try to parse as an ip
//if server is active, walk players to see if there's a name match to get their address and guess an address mask
//else if client is active, walk players to see if there's a name match, to get their address+mask if known via nq hacks
//look for matches
if (NET_StringToAdrMasked (nameorip, false, &adr, &mask))
{ //try to parse as an ip
//treading carefully here, to avoid dns name lookups weirding everything out.
IPLog_Identify(&adr, &mask, "Identity of %s", NET_AdrToStringMasked(clean, sizeof(clean), &adr, &mask));
}
#ifndef CLIENTONLY
else if (sv.active)
{ //if server is active, walk players to see if there's a name match to get their address and guess an address mask
client_t *cl;
int clnum = -1;
while((cl = SV_GetClientForString(nameorip, &clnum)))
{
if (cl->realip_status)
{
IPLog_Identify(&cl->realip, NULL, "Identity of %s (real) [%s]", cl->name, NET_AdrToString(clean, sizeof(clean), &cl->realip));
IPLog_Identify(&cl->netchan.remote_address, NULL, "Identity of %s (proxy) [%s]", cl->name, NET_AdrToString(clean, sizeof(clean), &cl->realip));
}
else
IPLog_Identify(&cl->netchan.remote_address, NULL, "Identity of %s [%s]", cl->name, NET_AdrToString(clean, sizeof(clean), &cl->realip));
}
}
#endif
#ifndef SERVERONLY
else if (cls.state >= ca_connected)
{ //else if client is active, walk players to see if there's a name match, to get their address+mask if known via nq hacks
int slot;
netadr_t adr;
if ((slot = Player_StringtoSlot(nameorip)) < 0)
Con_Printf("%s: no player with userid %s\n", Cmd_Argv(0), nameorip);
else if (!*cl.players[slot].ip)
Con_Printf("%s: ip address of %s is not known\n", Cmd_Argv(0), cl.players[slot].name);
else
{
NET_StringToAdr(cl.players[slot].ip, 0, &adr);
IPLog_Identify(&adr, NULL, "Identity of %s [%s]", cl.players[slot].name, cl.players[slot].ip);
}
}
#endif
else
Con_Printf("%s: not connected, nor raw address\n", Cmd_Argv(0));
}
static qboolean IPLog_Dump(const char *fname)
{
size_t i;
vfsfile_t *f;
qbyte line[20];
if (!*fname)
fname = "iplog.txt";
f = FS_OpenVFS(fname, "wb", FS_PUBBASEGAMEONLY);
if (!f)
return false;
if (!Q_strcasecmp(COM_FileExtension(fname, line, sizeof(line)), "dat"))
{
for (i = 0; i < iplog_num; i++)
{
//this shitty format supports only ipv4.
if (iplog_entries[i]->adr.type != NA_IP)
continue;
line[0] = iplog_entries[i]->adr.address.ip[2];
line[1] = iplog_entries[i]->adr.address.ip[1];
line[2] = iplog_entries[i]->adr.address.ip[0];
line[3] = 0;
strncpy(line+4, iplog_entries[i]->name, sizeof(line)-4);
IPLog_Write_Fucked(f, line, sizeof(line)); //convert \n to \r\n, to avoid fucking up any formatting with binary data (inside the address part, so *.13.10.* won't corrupt the file)
}
}
else
{
VFS_PRINTF(f, "//generated by "FULLENGINENAME"\n");
for (i = 0; i < iplog_num; i++)
{
char ip[512];
char buf[1024];
char buf2[1024];
VFS_PRINTF(f, log_dosformat.value?"%s %s\r\n":"%s %s\n", COM_QuotedString(NET_AdrToStringMasked(ip, sizeof(ip), &iplog_entries[i]->adr, &iplog_entries[i]->mask), buf2, sizeof(buf2), false), COM_QuotedString(iplog_entries[i]->name, buf, sizeof(buf), false));
}
}
VFS_CLOSE(f);
return true;
}
static void IPLog_Dump_f(void)
{
char native[MAX_OSPATH];
const char *fname = Cmd_Argv(1);
if (!*fname)
fname = "iplog.txt";
#if 1
Con_Printf("Not yet implemented\n");
#else
vfsfile_t *f = FS_OpenVFS(fname, "wb", FS_GAMEONLY);
VFS_PRINTF(f, "//generated by "FULLENGINENAME"\n", foo->ip, foo->name);
for (foo = first; foo; foo = foo->next)
if (FS_NativePath(fname, FS_GAMEONLY, native, sizeof(native)))
Q_strncpyz(native, fname, sizeof(native));
IPLog_Merge_File(fname); //merge from the existing file, so that we're hopefully more robust if multiple processes are poking the same file.
if (!IPLog_Dump(fname))
Con_Printf("unable to write %s\n", fname);
else
{
char buf[1024];
VFS_PRINTF(f, "%s %s\n", foo->ip, COM_QuotedString(foo->name, buf, sizeof(buf), false));
Con_Printf("wrote %s\n", native);
}
VFS_CLOSE(f);
#endif
}
static void IPLog_Merge_f(void)
{
@ -408,6 +599,20 @@ static void IPLog_Merge_f(void)
if (!IPLog_Merge_File(fname))
Con_Printf("unable to read %s\n", fname);
}
void Log_ShutDown(void)
{
IPLog_Dump("iplog.txt");
// IPLog_Dump("iplog.dat");
while(iplog_num > 0)
{
iplog_num--;
BZ_Free(iplog_entries[iplog_num]);
}
BZ_Free(iplog_entries);
iplog_entries = NULL;
iplog_max = iplog_num = 0;
}
void Log_Init(void)
{
@ -433,6 +638,9 @@ void Log_Init(void)
Cmd_AddCommand("ipmerge", IPLog_Merge_f);
Cmd_AddCommand("ipdump", IPLog_Dump_f);
IPLog_Merge_File("iplog.txt");
IPLog_Merge_File("iplog.dat"); //legacy crap, for compat with proquake
// cmd line options, debug options
#ifdef CRAZYDEBUGGING
Cvar_ForceSet(&log_enable[LOG_CONSOLE], "1");

View file

@ -129,7 +129,7 @@ qboolean NET_IsClientLegal(netadr_t *adr);
qboolean NET_IsLoopBackAddress (netadr_t *adr);
qboolean NET_StringToAdrMasked (const char *s, netadr_t *a, netadr_t *amask);
qboolean NET_StringToAdrMasked (const char *s, qboolean allowdns, netadr_t *a, netadr_t *amask);
char *NET_AdrToStringMasked (char *s, int len, netadr_t *a, netadr_t *amask);
void NET_IntegerToMask (netadr_t *a, netadr_t *amask, int bits);
qboolean NET_CompareAdrMasked(netadr_t *a, netadr_t *b, netadr_t *mask);

View file

@ -1240,38 +1240,98 @@ void NET_IntegerToMask (netadr_t *a, netadr_t *amask, int bits)
}
}
// ParsePartialIPv4: check string to see if it is a partial IPv4 address and
// ParsePartialIP: check string to see if it is a partial IP address and
// return bits to mask and set netadr_t or 0 if not an address
int ParsePartialIPv4(const char *s, netadr_t *a)
int ParsePartialIP(const char *s, netadr_t *a)
{
const char *colon = NULL;
char *address = a->address.ip;
int bits = 8;
char *colon;
int bits;
if (!*s)
return 0;
memset (a, 0, sizeof(*a));
//multiple colons == ipv6
colon = strchr(s, ':');
if (colon && strchr(colon+1, ':'))
{
qbyte *address = a->address.ip6;
unsigned long tmp;
bits = 0;
//FIXME: check for ::ffff:a.b.c.d
//FIXME: check for xx::xx
if (s[0] == ':' && s[1] == ':' && !s[2])
{
s+=2;
bits = 1;
}
else while(*s)
{
tmp = strtoul(s, &colon, 16);
if (tmp > 0xffff)
return 0; //invalid
*address++ = (tmp>>8)&0xff;
*address++ = (tmp>>0)&0xff;
bits += 16;
if (bits == 128)
{
if (!*colon)
break;
return 0; //must have ended here
}
//double-colon ends it here. we can't parse xx::xx
//hopefully the last 64 bits or whatever will be irrelevant anyway, so such addresses won't be common
if (colon[0] == ':' && colon[1] == ':' && !colon[2])
break;
if (*colon == ':')
colon++;
else
return 0; //don't allow it if it just ended without a double-colon.
s = colon;
}
a->type = NA_IPV6;
a->port = 0;
}
else
{
char *address = a->address.ip;
int port = 0;
bits = 8;
while (*s)
{
if (*s == ':')
{
if (colon) // only 1 colon
port = strtoul(s+1, &address, 10);
if (*address) //if there was something other than a number there, give up now
return 0;
colon = s + 1;
break; //end-of-string
}
else if (*s == '.')
{
if (colon) // no colons before periods (probably invalid anyway)
return 0;
else if (bits >= 32) // only 32 bits in ipv4
if (bits >= 32) // only 32 bits in ipv4
return 0;
else if (*(s+1) == '.')
return 0;
else if (*(s+1) == '\0')
break; // don't add more bits to the mask for x.x., etc
bits += 8;
address++;
//many nq servers mask addresses with Xs.
if (s[1] == 'x' || s[1] == 'X')
{
s++;
while (*s == 'x' || *s == 'X' || *s == '.')
s++;
if (*s)
return 0;
break;
}
bits += 8;
}
else if (*s >= '0' && *s <= '9')
*address = ((*address)*10) + (*s-'0');
@ -1280,17 +1340,16 @@ int ParsePartialIPv4(const char *s, netadr_t *a)
s++;
}
a->type = NA_IP;
if (colon)
a->port = atoi(colon);
a->port = port;
}
return bits;
}
// NET_StringToAdrMasked: extension to NET_StringToAdr to handle IP addresses
// with masks or integers representing the bit masks
qboolean NET_StringToAdrMasked (const char *s, netadr_t *a, netadr_t *amask)
qboolean NET_StringToAdrMasked (const char *s, qboolean allowdns, netadr_t *a, netadr_t *amask)
{
char t[64];
char *spoint;
@ -1308,7 +1367,7 @@ qboolean NET_StringToAdrMasked (const char *s, netadr_t *a, netadr_t *amask)
i = sizeof(t);
Q_strncpyz(t, s, i);
if (!ParsePartialIPv4(t, a) && !NET_StringToAdr(t, 0, a))
if (!ParsePartialIP(t, a) && (!allowdns || !NET_StringToAdr(t, 0, a)))
return false;
spoint++;
@ -1327,7 +1386,7 @@ qboolean NET_StringToAdrMasked (const char *s, netadr_t *a, netadr_t *amask)
}
if (c == NULL) // we have an address so resolve it and return
return ParsePartialIPv4(spoint, amask) || NET_StringToAdr(spoint, 0, amask);
return ParsePartialIP(spoint, amask) || (allowdns && NET_StringToAdr(spoint, 0, amask));
// otherwise generate mask for given bits
i = atoi(spoint);
@ -1336,8 +1395,8 @@ qboolean NET_StringToAdrMasked (const char *s, netadr_t *a, netadr_t *amask)
else
{
// we don't have a slash, resolve and fill with a full mask
i = ParsePartialIPv4(s, a);
if (!i && !NET_StringToAdr(s, 0, a))
i = ParsePartialIP(s, a);
if (!i && (!allowdns || !NET_StringToAdr(s, 0, a)))
return false;
memset (amask, 0, sizeof(*amask));

View file

@ -1004,7 +1004,6 @@
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib wsock32.lib Advapi32.lib"
OutputFile="../../fteqwsv64.exe"
LinkIncremental="2"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="../libs/dxsdk7/lib"
IgnoreDefaultLibraryNames="libc.lib;msvcrt.lib"
@ -1079,7 +1078,7 @@
FavorSizeOrSpeed="1"
OmitFramePointers="true"
AdditionalIncludeDirectories="../libs/speex;..\client;../libs/freetype2/include;../common;../server;../gl;../sw;../qclib;../libs;../libs/dxsdk9/include;../libs/dxsdk7/include"
PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;GLQUAKE;D3DQUAKE;SWQUAKE;VKQUAKE"
PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS;GLQUAKE;D3D9QUAKE;D3D11QUAKE;SWQUAKE;VKQUAKE;USE_EGL"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@ -10579,6 +10578,14 @@
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|Win32"
ExcludedFromBuild="true"
@ -13145,6 +13152,14 @@
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug Dedicated Server|Win32"
ExcludedFromBuild="true"
@ -19851,6 +19866,7 @@
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|x64"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
@ -25208,7 +25224,6 @@
</FileConfiguration>
<FileConfiguration
Name="Release Dedicated Server|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"

View file

@ -26,7 +26,7 @@ void DumpGLState(void);
#endif
extern cvar_t gl_overbright;
extern cvar_t gl_ati_truform;
extern cvar_t r_tessellation;
extern cvar_t r_wireframe;
extern cvar_t r_refract_fbo;
extern cvar_t r_refractreflect_scale;
@ -2730,9 +2730,9 @@ static void BE_SendPassBlendDepthMask(unsigned int sbits)
(sbits&SBITS_MASK_ALPHA)?GL_FALSE:GL_TRUE
);
}
if ((delta & SBITS_TRUFORM) && qglPNTrianglesiATI)
if ((delta & SBITS_TESSELLATION) && qglPNTrianglesiATI)
{
if ((sbits & SBITS_TRUFORM) && gl_ati_truform.ival)
if ((sbits & SBITS_TESSELLATION) && r_tessellation.ival)
qglEnable(GL_PN_TRIANGLES_ATI);
else
qglDisable(GL_PN_TRIANGLES_ATI);

View file

@ -3258,7 +3258,7 @@ static int Mod_Batches_Generate(model_t *mod)
{
if (
batch->texture == surf->texinfo->texture &&
lbatch->shader == shader &&
batch->shader == shader &&
batch->lightmap[0] == lmmerge(surf->lightmaptexturenums[0]) &&
Vector4Compare(plane, batch->plane) &&
batch->firstmesh + surf->mesh->numvertexes <= MAX_INDICIES &&

View file

@ -71,9 +71,9 @@ extern cvar_t ffov;
extern cvar_t gl_motionblur;
extern cvar_t gl_motionblurscale;
extern cvar_t gl_ati_truform;
extern cvar_t r_tessellation;
extern cvar_t gl_ati_truform_type;
extern cvar_t gl_ati_truform_tesselation;
extern cvar_t r_tessellation_level;
extern cvar_t gl_blendsprites;
extern cvar_t r_portaldrawplanes;
@ -1990,7 +1990,7 @@ void GLR_RenderView (void)
qglPNTrianglesiATI(GL_PN_TRIANGLES_NORMAL_MODE_ATI, GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI);
qglPNTrianglesiATI(GL_PN_TRIANGLES_POINT_MODE_ATI, GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI);
}
qglPNTrianglesfATI(GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, gl_ati_truform_tesselation.value);
qglPNTrianglesfATI(GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, r_tessellation_level.value);
}
if (gl_finish.ival)

View file

@ -46,6 +46,7 @@ extern cvar_t r_glsl_offsetmapping_reliefmapping;
extern cvar_t r_fastturb, r_fastsky, r_skyboxname;
extern cvar_t r_drawflat;
extern cvar_t r_shaderblobs;
extern cvar_t r_tessellation;
//backend fills this in to say the max pass count
int be_maxpasses;
@ -1123,6 +1124,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
qboolean blobadded;
qboolean geom = false;
qboolean tess = false;
qboolean cantess = false;
char maxgpubones[128];
cvar_t *cvarrefs[64];
@ -1340,7 +1342,9 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
if (!permutationname[p])
{
//we 'recognise' ones that are force-defined, despite not being actual permutations.
if (strncmp("SPECULAR", script, end - script))
if (end - script == 4 && !strncmp("TESS", script, 4))
cantess = true;
else if (strncmp("SPECULAR", script, end - script))
if (strncmp("DELUXE", script, end - script))
if (strncmp("OFFSETMAPPING", script, end - script))
if (strncmp("RELIEFMAPPING", script, end - script))
@ -1384,6 +1388,9 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
script++;
};
if (qrenderer == qrtype && ver < 150)
tess = cantess = false; //GL_ARB_tessellation_shader requires glsl 150(gl3.2) (or glessl 3.1). nvidia complains about layouts if you try anyway
if (sh_config.pLoadBlob && blobfilename && *blobfilename)
blobfile = FS_OpenVFS(blobfilename, "w+b", FS_GAMEONLY);
else
@ -1448,6 +1455,9 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
prog->nofixedcompat = false;
if (nummodifiers < MAXMODIFIERS)
{
if (end-start == 4 && !Q_strncasecmp(start, "tess", 4))
tess |= cantess;
permutationdefines[nummodifiers] = d = BZ_Malloc(10 + end - start);
memcpy(d, "#define ", 8);
memcpy(d+8, start, end - start);
@ -1537,6 +1547,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
}
}
prog->tess = tess;
prog->supportedpermutations = ~nopermutation;
for (p = 0; p < PERMUTATIONS; p++)
{
@ -4723,8 +4734,8 @@ done:;
if (!s->bemoverrides[bemoverride_depthonly])
{
const char *mask = Shader_AlphaMaskProgArgs(s);
if (*mask)
s->bemoverrides[bemoverride_depthonly] = R_RegisterShader(va("depthonly%s", mask), SUF_NONE,
if (*mask || (s->prog&&s->prog->tess))
s->bemoverrides[bemoverride_depthonly] = R_RegisterShader(va("depthonly%s%s", mask, (s->prog&&s->prog->tess)?"#TESS":""), SUF_NONE,
"{\n"
"program depthonly\n"
"{\n"
@ -4734,6 +4745,35 @@ done:;
"}\n"
"}\n");
}
if (!s->bemoverrides[LSHADER_STANDARD] && (s->prog&&s->prog->tess))
{
int mode;
for (mode = 0; mode < LSHADER_MODES; mode++)
{
if ((mode & LSHADER_CUBE) && (mode & LSHADER_SPOT))
continue;
if (s->bemoverrides[mode])
continue;
s->bemoverrides[mode] = R_RegisterShader(va("rtlight%s%s%s%s#TESS",
(mode & LSHADER_SMAP)?"#PCF":"",
(mode & LSHADER_SPOT)?"#SPOT":"",
(mode & LSHADER_CUBE)?"#CUBE":"",
#ifdef GLQUAKE
(qrenderer == QR_OPENGL && gl_config.arb_shadow && (mode & (LSHADER_SMAP|LSHADER_SPOT)))?"#USE_ARB_SHADOW":""
#else
""
#endif
)
, s->usageflags,
"{\n"
"program rtlight\n"
"{\n"
"map $diffuse\n"
"blendfunc add\n"
"}\n"
"}\n");
}
}
if (!s->prog && sh_config.progs_supported && (r_forceprogramify.ival || parsestate.forceprogramify))
{
@ -5910,6 +5950,15 @@ void Shader_DefaultSkin(const char *shortname, shader_t *s, const void *args)
);
return;
}
if (r_tessellation.ival && sh_config.progs_supported)
{
Shader_DefaultScript(shortname, s,
"{\n"
"program defaultskin#TESS\n"
"}\n"
);
return;
}
Shader_DefaultScript(shortname, s,
"{\n"
@ -6400,7 +6449,7 @@ char *Shader_Decompose(shader_t *s)
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); }
if (p->shaderbits & SBITS_TRUFORM) { sprintf(o, "SBITS_TRUFORM\n"); o+=strlen(o); }
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); }

View file

@ -1217,92 +1217,91 @@ static const char *glsl_hdrs[] =
"sys/defs.h",
"#define DEFS_DEFINED\n"
"#ifdef VERTEX_SHADER\n"
// "attribute vec3 v_position1;\n" //defined elsewhere, depending on fixed function availability
// "attribute vec3 v_position2;\n"
"attribute vec4 v_colour;\n"
"attribute vec2 v_texcoord;\n"
"attribute vec2 v_lmcoord;\n"
"attribute vec3 v_normal;\n"
"attribute vec3 v_svector;\n"
"attribute vec3 v_tvector;\n"
"attribute vec4 v_bone;\n" //fixme: make ints
"attribute vec4 v_weight;\n"
// "attribute vec3 v_position1;" //defined elsewhere, depending on fixed function availability
// "attribute vec3 v_position2;"
"attribute vec4 v_colour;"
"attribute vec2 v_texcoord;"
"attribute vec2 v_lmcoord;"
"attribute vec3 v_normal;"
"attribute vec3 v_svector;"
"attribute vec3 v_tvector;"
"attribute vec4 v_bone;" //fixme: make ints
"attribute vec4 v_weight;"
#if MAXRLIGHTMAPS > 1
"#define v_lmcoord1 v_lmcoord\n"
"attribute vec2 v_lmcoord2;\n"
"attribute vec2 v_lmcoord3;\n"
"attribute vec2 v_lmcoord4;\n"
"#define v_colour1 v_colour\n"
"attribute vec4 v_colour2;\n"
"attribute vec4 v_colour3;\n"
"attribute vec4 v_colour4;\n"
"\n#define v_lmcoord1 v_lmcoord\n"
"attribute vec2 v_lmcoord2;"
"attribute vec2 v_lmcoord3;"
"attribute vec2 v_lmcoord4;"
"\n#define v_colour1 v_colour\n"
"attribute vec4 v_colour2;"
"attribute vec4 v_colour3;"
"attribute vec4 v_colour4;"
#endif
"#endif\n"
"\n#endif\n"
#ifndef NOLEGACY
"uniform sampler2D s_shadowmap;\n"
"uniform samplerCube s_projectionmap;\n"
"uniform sampler2D s_diffuse;\n"
"uniform sampler2D s_normalmap;\n"
"uniform sampler2D s_specular;\n"
"uniform sampler2D s_upper;\n"
"uniform sampler2D s_lower;\n"
"uniform sampler2D s_fullbright;\n"
"uniform sampler2D s_paletted;\n"
"uniform samplerCube s_reflectcube;\n"
"uniform sampler2D s_reflectmask;\n"
"uniform sampler2D s_lightmap;\n"
"uniform sampler2D s_deluxmap;\n"
"#define s_lightmap0 s_lightmap\n"
"uniform sampler2DShadow s_shadowmap;"
"uniform samplerCube s_projectionmap;"
"uniform sampler2D s_diffuse;"
"uniform sampler2D s_normalmap;"
"uniform sampler2D s_specular;"
"uniform sampler2D s_upper;"
"uniform sampler2D s_lower;"
"uniform sampler2D s_fullbright;"
"uniform sampler2D s_paletted;"
"uniform samplerCube s_reflectcube;"
"uniform sampler2D s_reflectmask;"
"uniform sampler2D s_lightmap;"
"uniform sampler2D s_deluxmap;"
"\n#define s_lightmap0 s_lightmap\n"
"#define s_deluxmap0 s_deluxmap\n"
#if MAXRLIGHTMAPS > 1
"uniform sampler2D s_lightmap1;\n"
"uniform sampler2D s_lightmap2;\n"
"uniform sampler2D s_lightmap3;\n"
"uniform sampler2D s_deluxmap1;\n"
"uniform sampler2D s_deluxmap2;\n"
"uniform sampler2D s_lightmap1;"
"uniform sampler2D s_lightmap2;"
"uniform sampler2D s_lightmap3;"
"uniform sampler2D s_deluxmap1;"
"uniform sampler2D s_deluxmap2;"
"uniform sampler2D s_deluxmap3;\n"
#endif
#endif
"#ifdef USEUBOS\n"
"layout(std140) uniform u_lightinfo\n"
"{\n"
"vec3 l_lightscreen;\n"
"float l_lightradius;\n"
"vec3 l_lightcolour;\n"
"{"
"vec3 l_lightscreen;"
"float l_lightradius;"
"vec3 l_lightcolour;"
"float l_pad1;\n"
"vec3 l_lightcolourscale;\n"
"float l_pad2;\n"
"vec3 l_lightposition;\n"
"float l_pad3;\n"
"mat4 l_cubematrix;\n"
"vec4 l_shadowmapproj;\n"
"vec2 l_shadowmapscale;\n"
"vec2 l_pad4;\n"
"\n"
"vec3 l_lightcolourscale;n"
"float l_pad2;"
"vec3 l_lightposition;"
"float l_pad3;"
"mat4 l_cubematrix;"
"vec4 l_shadowmapproj;"
"vec2 l_shadowmapscale;"
"vec2 l_pad4;"
"};\n"
"layout(std140) uniform u_entityinfo\n"
"{\n"
"vec2 e_vblend;\n"
"vec2 e_pad1;\n"
"vec3 e_glowmod;\n"
"float e_pad2;\n"
"vec3 e_origin;\n"
"float e_pad3;\n"
"vec4 colormod;\n"
"vec3 e_glowmod;\n"
"float e_pad4;\n"
"vec3 e_uppercolour;\n"
"float e_pad5;\n"
"vec3 e_lowercolour;\n"
"float e_pad6;\n"
"vec3 w_fogcolour;\n"
"float w_fogalpha;\n"
"vec3 e_light_dir;\n"
"float w_fogdensity;\n"
"vec3 e_light_mul;\n"
"float w_fogdepthbias;\n"
"vec3 e_light_ambient;\n"
"float e_time;\n"
"vec2 e_vblend;"
"vec2 e_pad1;"
"vec3 e_glowmod;"
"float e_pad2;"
"vec3 e_origin;"
"float e_pad3;"
"vec4 colormod;"
"vec3 e_glowmod;"
"float e_pad4;"
"vec3 e_uppercolour;"
"float e_pad5;"
"vec3 e_lowercolour;"
"float e_pad6;"
"vec3 w_fogcolour;"
"float w_fogalpha;"
"vec3 e_light_dir;"
"float w_fogdensity;"
"vec3 e_light_mul;"
"float w_fogdepthbias;"
"vec3 e_light_ambient;"
"float e_time;"
"};\n"
"#ifdef SKELETAL\n"
"layout(std140) unform u_bones\n"
@ -1315,11 +1314,13 @@ static const char *glsl_hdrs[] =
"};\n"
"#endif\n"
"#else\n"
"uniform mat4 m_model;\n"
"uniform mat4 m_view;\n"
"uniform mat4 m_modelview;\n"
"uniform mat4 m_model;"
"uniform mat4 m_view;"
"uniform mat4 m_modelview;"
"uniform mat4 m_projection;\n"
// "uniform mat4 m_modelviewprojection;\n"
"#ifndef VERTEX_SHADER\n"
"uniform mat4 m_modelviewprojection;\n"
"#endif\n"
"#ifdef SKELETAL\n" //skeletal permutation tends to require glsl 120
"#ifdef PACKEDBONES\n"
"uniform vec4 m_bones[3*MAX_GPU_BONES];\n"
@ -1327,11 +1328,11 @@ static const char *glsl_hdrs[] =
"uniform mat3x4 m_bones[MAX_GPU_BONES];\n"
"#endif\n"
"#endif\n"
"uniform mat4 m_invviewprojection;\n"
"uniform mat4 m_invmodelviewprojection;\n"
"uniform mat4 m_invviewprojection;"
"uniform mat4 m_invmodelviewprojection;"
/*viewer properties*/
"uniform vec3 v_eyepos;\n"
"uniform vec3 v_eyepos;"
"uniform vec4 w_fog[2];\n"
"#define w_fogcolour w_fog[0].rgb\n"
"#define w_fogalpha w_fog[0].a\n"
@ -1345,37 +1346,37 @@ static const char *glsl_hdrs[] =
"#else\n"
"uniform vec4 e_lmscale;\n"
"#endif\n"
"uniform vec3 e_origin;\n"
"uniform float e_time;\n"
"uniform vec3 e_eyepos;\n"
"uniform vec4 e_colour;\n"
"uniform vec4 e_colourident;\n"
"uniform vec3 e_glowmod;\n"
"uniform vec3 e_uppercolour;\n"
"uniform vec3 e_lowercolour;\n"
"uniform vec3 e_light_dir;\n"
"uniform vec3 e_light_mul;\n"
"uniform vec3 e_light_ambient;\n"
"uniform vec3 e_origin;"
"uniform float e_time;"
"uniform vec3 e_eyepos;"
"uniform vec4 e_colour;"
"uniform vec4 e_colourident;"
"uniform vec3 e_glowmod;"
"uniform vec3 e_uppercolour;"
"uniform vec3 e_lowercolour;"
"uniform vec3 e_light_dir;"
"uniform vec3 e_light_mul;"
"uniform vec3 e_light_ambient;"
/*rtlight properties, use with caution*/
"uniform vec2 l_lightscreen;\n"
"uniform float l_lightradius;\n"
"uniform vec3 l_lightcolour;\n"
"uniform vec3 l_lightposition;\n"
"uniform vec3 l_lightcolourscale;\n"
"uniform mat4 l_cubematrix;\n"
"uniform vec4 l_shadowmapproj;\n"
"uniform vec2 l_shadowmapscale;\n"
"uniform vec2 l_lightscreen;"
"uniform float l_lightradius;"
"uniform vec3 l_lightcolour;"
"uniform vec3 l_lightposition;"
"uniform vec3 l_lightcolourscale;"
"uniform mat4 l_cubematrix;"
"uniform vec4 l_shadowmapproj;"
"uniform vec2 l_shadowmapscale;"
"uniform vec2 e_rendertexturescale;\n"
"#endif\n"
,
"sys/skeletal.h",
"#ifndef DEFS_DEFINED\n"
"attribute vec3 v_normal;\n"
"attribute vec3 v_svector;\n"
"attribute vec3 v_tvector;\n"
"#endif\n"
"attribute vec3 v_normal;"
"attribute vec3 v_svector;"
"attribute vec3 v_tvector;"
"\n#endif\n"
"#ifdef SKELETAL\n"
"#ifndef DEFS_DEFINED\n"
"attribute vec4 v_bone;"
@ -1887,10 +1888,18 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
length[strings] = strlen(prstrings[strings]);
strings++;
}
if (ver >= 130) //gl3+ deprecated the varying keyword for geometry shaders to work properly
if (ver >= 130)
{
prstrings[strings] =
//gl3+ deprecated the varying keyword for geometry shaders to work properly
"#define varying in\n"
//it also deprecated the numerous texture functions. now only the 'texture' function exists, with overloads for each sampler type.
"#define texture2D texture\n"
"#define textureCube texture\n"
"#define shadow2D texture\n"
//gl_FragColor and gl_FragData got deprecated too
"out vec4 fte_fragdata;\n"
"#define gl_FragColor fte_fragdata\n"
;
length[strings] = strlen(prstrings[strings]);
strings++;
@ -1912,7 +1921,7 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
#ifdef NOLEGACY
const char *defaultsamplernames[] =
{
"uniform sampler2D s_shadowmap;\n",
"uniform sampler2DShadow s_shadowmap;\n",
"uniform samplerCube s_projectionmap;\n",
"uniform sampler2D s_diffuse;\n",
"uniform sampler2D s_normalmap;\n",
@ -1957,12 +1966,22 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
strings++;
break;
case GL_TESS_CONTROL_SHADER_ARB:
prstrings[strings] = "#define TESS_CONTROL_SHADER\n";
prstrings[strings] =
"#define TESS_CONTROL_SHADER\n"
"#if __VERSION__ < 400\n"
"#extension GL_ARB_tessellation_shader : enable\n"
"#endif\n";
//varyings are arrays, so don't bother defining that here.
length[strings] = strlen(prstrings[strings]);
strings++;
break;
case GL_TESS_EVALUATION_SHADER_ARB:
prstrings[strings] = "#define TESS_EVALUATION_SHADER\n";
prstrings[strings] =
"#define TESS_EVALUATION_SHADER\n"
"#if __VERSION__ < 400\n"
"#extension GL_ARB_tessellation_shader : enable\n"
"#endif\n"
"#define varying out\n";
length[strings] = strlen(prstrings[strings]);
strings++;
break;
@ -2084,7 +2103,7 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
//called after CreateShader. Checks for success.
//Splitting creation allows for both vertex+fragment shaders to be processed simultaneously if the driver threads glCompileShaderARB.
static GLhandleARB GLSlang_FinishShader(GLhandleARB shader, const char *name, GLenum shadertype, qboolean silent)
static GLhandleARB GLSlang_FinishShader(GLhandleARB shader, const char *name, GLenum shadertype, qboolean *silent)
{
GLint compiled;
int loglen;
@ -2096,12 +2115,13 @@ static GLhandleARB GLSlang_FinishShader(GLhandleARB shader, const char *name, GL
if(!compiled)
{
char *typedesc;
char str[8192];
char str[65536];
*str = 0;
qglGetShaderInfoLog_(shader, sizeof(str), NULL, str);
if (!silent)
if (!*silent)
{
*silent = true;
switch (shadertype)
{
case GL_FRAGMENT_SHADER_ARB:
@ -2168,7 +2188,7 @@ static GLhandleARB GLSlang_FinishShader(GLhandleARB shader, const char *name, GL
return shader;
}
GLhandleARB GLSlang_CreateProgramObject (const char *name, GLhandleARB vert, GLhandleARB cont, GLhandleARB eval, GLhandleARB geom, GLhandleARB frag, qboolean silent)
GLhandleARB GLSlang_CreateProgramObject (const char *name, GLhandleARB vert, GLhandleARB cont, GLhandleARB eval, GLhandleARB geom, GLhandleARB frag)
{
GLhandleARB program;
@ -2295,16 +2315,16 @@ union programhandle_u GLSlang_CreateProgram(program_t *prog, const char *name, i
cs = GLSlang_CreateShader(prog, name, ver, precompilerconstants, cont, GL_TESS_CONTROL_SHADER_ARB, silent);
es = GLSlang_CreateShader(prog, name, ver, precompilerconstants, eval, GL_TESS_EVALUATION_SHADER_ARB, silent);
fs = GLSlang_FinishShader(fs, name, GL_FRAGMENT_SHADER_ARB, silent);
gs = GLSlang_FinishShader(gs, name, GL_GEOMETRY_SHADER_ARB, silent);
vs = GLSlang_FinishShader(vs, name, GL_VERTEX_SHADER_ARB, silent);
cs = GLSlang_FinishShader(cs, name, GL_TESS_CONTROL_SHADER_ARB, silent);
es = GLSlang_FinishShader(es, name, GL_TESS_EVALUATION_SHADER_ARB, silent);
fs = GLSlang_FinishShader(fs, name, GL_FRAGMENT_SHADER_ARB, &silent);
gs = GLSlang_FinishShader(gs, name, GL_GEOMETRY_SHADER_ARB, &silent);
vs = GLSlang_FinishShader(vs, name, GL_VERTEX_SHADER_ARB, &silent);
cs = GLSlang_FinishShader(cs, name, GL_TESS_CONTROL_SHADER_ARB, &silent);
es = GLSlang_FinishShader(es, name, GL_TESS_EVALUATION_SHADER_ARB, &silent);
if (!vs || !fs)
ret.glsl.handle = 0;
else
ret.glsl.handle = GLSlang_CreateProgramObject(name, vs, cs, es, gs, fs, silent);
ret.glsl.handle = GLSlang_CreateProgramObject(name, vs, cs, es, gs, fs);
//delete ignores 0s.
if (vs) qglDeleteShaderObject_(vs);
if (gs) qglDeleteShaderObject_(gs);
@ -2314,6 +2334,7 @@ union programhandle_u GLSlang_CreateProgram(program_t *prog, const char *name, i
checkglerror();
ret.glsl.usetesselation = (cont || eval);
if (ret.glsl.handle && blobfile && qglGetProgramBinary)
{
GLuint ui;
@ -2335,8 +2356,6 @@ union programhandle_u GLSlang_CreateProgram(program_t *prog, const char *name, i
BZ_Free(blobdata);
}
ret.glsl.usetesselation = (cont || eval);
return ret;
}

View file

@ -1849,8 +1849,13 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "depthonly",
"!!ver 100 150\n"
"!!permu TESS\n"
"!!permu FRAMEBLEND\n"
"!!permu SKELETAL\n"
"!!cvardf r_tessellation=0\n"
"#include \"sys/defs.h\"\n"
//standard shader used for drawing shadowmap depth.
//also used for masking off portals and other things that want depth and no colour.
@ -1859,12 +1864,80 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#ifdef VERTEX_SHADER\n"
"#include \"sys/skeletal.h\"\n"
"#ifdef TESS\n"
"varying vec3 vertex;\n"
"varying vec3 normal;\n"
"#endif\n"
"void main ()\n"
"{\n"
"#ifdef TESS\n"
"skeletaltransform_n(normal);\n"
"vertex = v_position;\n"
"#else\n"
"gl_Position = skeletaltransform();\n"
"#endif\n"
"}\n"
"#endif\n"
"#if defined(TESS_CONTROL_SHADER)\n"
"layout(vertices = 3) out;\n"
"in vec3 vertex[];\n"
"out vec3 t_vertex[];\n"
"in vec3 normal[];\n"
"out vec3 t_normal[];\n"
"void main()\n"
"{\n"
//the control shader needs to pass stuff through
"#define id gl_InvocationID\n"
"t_vertex[id] = vertex[id];\n"
"t_normal[id] = normal[id];\n"
"gl_TessLevelOuter[0] = float(r_tessellation)+1.0;\n"
"gl_TessLevelOuter[1] = float(r_tessellation)+1.0;\n"
"gl_TessLevelOuter[2] = float(r_tessellation)+1.0;\n"
"gl_TessLevelInner[0] = float(r_tessellation)+1.0;\n"
"}\n"
"#endif\n"
"#if defined(TESS_EVALUATION_SHADER)\n"
"layout(triangles) in;\n"
"in vec3 t_vertex[];\n"
"in vec3 t_normal[];\n"
"#define LERP(a) (gl_TessCoord.x*a[0] + gl_TessCoord.y*a[1] + gl_TessCoord.z*a[2])\n"
"void main()\n"
"{\n"
"#define factor 1.0\n"
"vec3 w = LERP(t_vertex);\n"
"vec3 t0 = w - dot(w-t_vertex[0],t_normal[0])*t_normal[0];\n"
"vec3 t1 = w - dot(w-t_vertex[1],t_normal[1])*t_normal[1];\n"
"vec3 t2 = w - dot(w-t_vertex[2],t_normal[2])*t_normal[2];\n"
"w = w*(1.0-factor) + factor*(gl_TessCoord.x*t0+gl_TessCoord.y*t1+gl_TessCoord.z*t2);\n"
"gl_Position = m_modelviewprojection * vec4(w,1.0);\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"void main ()\n"
"{\n"
@ -2248,7 +2321,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultskin",
"!!ver 100 130\n"
"!!ver 100 150\n"
"!!permu TESS\n"
"!!permu FULLBRIGHT\n"
"!!permu UPPERLOWER\n"
"!!permu FRAMEBLEND\n"
@ -2258,6 +2332,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"!!cvarf r_glsl_offsetmapping_scale\n"
"!!cvarf gl_specular\n"
"!!cvardf gl_affinemodels=0\n"
"!!cvardf r_tessellation=0\n"
"#include \"sys/defs.h\"\n"
@ -2266,19 +2341,31 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
//the vertex shader is responsible for calculating lighting values.
"#if gl_affinemodels==1 && __VERSION__ >= 130\n"
"noperspective\n"
"#endif\n"
"varying vec2 tc;\n"
"varying vec3 light;\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n"
"varying vec3 eyevector;\n"
"#define affine noperspective\n"
"#else\n"
"#define affine\n"
"#endif\n"
"#ifdef VERTEX_SHADER\n"
"#include \"sys/skeletal.h\"\n"
"affine varying vec2 tc;\n"
"varying vec3 light;\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n"
"varying vec3 eyevector;\n"
"#endif\n"
"#ifdef TESS\n"
"varying vec3 vertex;\n"
"varying vec3 normal;\n"
"#endif\n"
"void main ()\n"
"{\n"
"#if defined(SPECULAR)||defined(OFFSETMAPPING)\n"
@ -2289,17 +2376,120 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"eyevector.y = dot(eyeminusvertex, t.xyz);\n"
"eyevector.z = dot(eyeminusvertex, n.xyz);\n"
"#else\n"
"vec3 n;\n"
"gl_Position = skeletaltransform_n(n);\n"
"vec3 n, s, t, w;\n"
"gl_Position = skeletaltransform_wnst(w,n,s,t);\n"
"#endif\n"
"tc = v_texcoord;\n"
"float d = dot(n,e_light_dir);\n"
"if (d < 0.0) //vertex shader. this might get ugly, but I don't really want to make it per vertex.\n"
"d = 0.0; //this avoids the dark side going below the ambient level.\n"
"light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul);\n"
"tc = v_texcoord;\n"
"#ifdef TESS\n"
"normal = n;\n"
"vertex = w;\n"
"#endif\n"
"}\n"
"#endif\n"
"#if defined(TESS_CONTROL_SHADER)\n"
"layout(vertices = 3) out;\n"
"in vec3 vertex[];\n"
"out vec3 t_vertex[];\n"
"in vec3 normal[];\n"
"out vec3 t_normal[];\n"
"affine in vec2 tc[];\n"
"affine out vec2 t_tc[];\n"
"in vec3 light[];\n"
"out vec3 t_light[];\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n"
"in vec3 eyevector[];\n"
"out vec3 t_eyevector[];\n"
"#endif\n"
"void main()\n"
"{\n"
//the control shader needs to pass stuff through
"#define id gl_InvocationID\n"
"t_vertex[id] = vertex[id];\n"
"t_normal[id] = normal[id];\n"
"t_tc[id] = tc[id];\n"
"t_light[id] = light[id];\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n"
"t_eyevector[id] = eyevector[id];\n"
"#endif\n"
"gl_TessLevelOuter[0] = float(r_tessellation)+1.0;\n"
"gl_TessLevelOuter[1] = float(r_tessellation)+1.0;\n"
"gl_TessLevelOuter[2] = float(r_tessellation)+1.0;\n"
"gl_TessLevelInner[0] = float(r_tessellation)+1.0;\n"
"}\n"
"#endif\n"
"#if defined(TESS_EVALUATION_SHADER)\n"
"layout(triangles) in;\n"
"in vec3 t_vertex[];\n"
"in vec3 t_normal[];\n"
"affine in vec2 t_tc[];\n"
"affine out vec2 tc;\n"
"in vec3 t_light[];\n"
"out vec3 light;\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n"
"in vec3 t_eyevector[];\n"
"out vec3 eyevector;\n"
"#endif\n"
"#define LERP(a) (gl_TessCoord.x*a[0] + gl_TessCoord.y*a[1] + gl_TessCoord.z*a[2])\n"
"void main()\n"
"{\n"
"#define factor 1.0\n"
"tc = LERP(t_tc);\n"
"vec3 w = LERP(t_vertex);\n"
"vec3 t0 = w - dot(w-t_vertex[0],t_normal[0])*t_normal[0];\n"
"vec3 t1 = w - dot(w-t_vertex[1],t_normal[1])*t_normal[1];\n"
"vec3 t2 = w - dot(w-t_vertex[2],t_normal[2])*t_normal[2];\n"
"w = w*(1.0-factor) + factor*(gl_TessCoord.x*t0+gl_TessCoord.y*t1+gl_TessCoord.z*t2);\n"
//FIXME: we should be recalcing these here, instead of just lerping them
"light = LERP(t_light);\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n"
"eyevector = LERP(t_eyevector);\n"
"#endif\n"
"gl_Position = m_modelviewprojection * vec4(w,1.0);\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"#include \"sys/fog.h\"\n"
@ -2317,9 +2507,10 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"uniform sampler2D s_colourmap;\n"
"#endif\n"
"#if __VERSION__ >= 130\n"
"#define gl_FragColor thecolour\n"
"out vec4 thecolour;\n"
"affine varying vec2 tc;\n"
"varying vec3 light;\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING)\n"
"varying vec3 eyevector;\n"
"#endif\n"
@ -4483,7 +4674,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "defaultwall",
"!!ver 100 120 // 130\n"
"!!ver 100 150\n"
"!!permu TESS\n"
"!!permu DELUXE\n"
"!!permu FULLBRIGHT\n"
"!!permu FOG\n"
@ -4493,19 +4685,16 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"!!permu REFLECTCUBEMASK\n"
"!!cvarf r_glsl_offsetmapping_scale\n"
"!!cvarf gl_specular\n"
"!!cvardf r_tessellation=0\n"
"#include \"sys/defs.h\"\n"
"#if __VERSION__ >= 130\n"
"#define texture2D texture\n"
"#define textureCube texture\n"
"#define gl_FragColor gl_FragData[0]\n"
"#endif\n"
//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\"\n"
"#if !defined(TESS_CONTROL_SHADER)\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
"varying vec3 eyevector;\n"
"#endif\n"
@ -4526,8 +4715,12 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"varying vec2 lm0;\n"
"#endif\n"
"#endif\n"
"#endif\n"
"#ifdef VERTEX_SHADER\n"
"#ifdef TESS\n"
"varying vec3 vertex, normal;\n"
"#endif\n"
"void main ()\n"
"{\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
@ -4558,10 +4751,151 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
"#endif\n"
"gl_Position = ftetransform();\n"
"#ifdef TESS\n"
"vertex = v_position;\n"
"normal = v_normal;\n"
"#endif\n"
"}\n"
"#endif\n"
"#if defined(TESS_CONTROL_SHADER)\n"
"layout(vertices = 3) out;\n"
"in vec3 vertex[];\n"
"out vec3 t_vertex[];\n"
"in vec3 normal[];\n"
"out vec3 t_normal[];\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
"in vec3 eyevector[];\n"
"out vec3 t_eyevector[];\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
"in mat3 invsurface[];\n"
"out mat3 t_invsurface[];\n"
"#endif\n"
"in vec2 tc[];\n"
"out vec2 t_tc[];\n"
"#ifdef VERTEXLIT\n"
"in vec4 vc[];\n"
"out vec4 t_vc[];\n"
"#else\n"
"in vec2 lm0[];\n"
"out vec2 t_lm0[];\n"
"#ifdef LIGHTSTYLED\n"
"in vec2 lm1[], lm2[], lm3[];\n"
"out vec2 t_lm1[], t_lm2[], t_lm3[];\n"
"#endif\n"
"#endif\n"
"void main()\n"
"{\n"
//the control shader needs to pass stuff through
"#define id gl_InvocationID\n"
"t_vertex[id] = vertex[id];\n"
"t_normal[id] = normal[id];\n"
"#ifdef REFLECTCUBEMASK\n"
"t_invsurface[id] = invsurface[id];\n"
"#endif\n"
"t_tc[id] = tc[id];\n"
"#ifdef VERTEXLIT\n"
"t_vc[id] = vc[id];\n"
"#else\n"
"t_lm0[id] = lm0[id];\n"
"#ifdef LIGHTSTYLED\n"
"t_lm1[id] = lm1[id];\n"
"t_lm2[id] = lm2[id];\n"
"t_lm3[id] = lm3[id];\n"
"#endif\n"
"#endif\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"t_eyevector[id] = eyevector[id];\n"
"#endif\n"
"gl_TessLevelOuter[0] = float(r_tessellation)+1.0;\n"
"gl_TessLevelOuter[1] = float(r_tessellation)+1.0;\n"
"gl_TessLevelOuter[2] = float(r_tessellation)+1.0;\n"
"gl_TessLevelInner[0] = float(r_tessellation)+1.0;\n"
"}\n"
"#endif\n"
"#if defined(TESS_EVALUATION_SHADER)\n"
"layout(triangles) in;\n"
"in vec3 t_vertex[];\n"
"in vec3 t_normal[];\n"
"#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)\n"
"in vec3 t_eyevector[];\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
"in mat3 t_invsurface[];\n"
"#endif\n"
"in vec2 t_tc[];\n"
"#ifdef VERTEXLIT\n"
"in vec4 t_vc[];\n"
"#else\n"
"#ifdef LIGHTSTYLED\n"
//we could use an offset, but that would still need to be per-surface which would break batches
//fixme: merge attributes?
"in vec2 t_lm0[], t_lm1[], t_lm2[], t_lm3[];\n"
"#else\n"
"in vec2 t_lm0[];\n"
"#endif\n"
"#endif\n"
"#define LERP(a) (gl_TessCoord.x*a[0] + gl_TessCoord.y*a[1] + gl_TessCoord.z*a[2])\n"
"void main()\n"
"{\n"
"#define factor 1.0\n"
"tc = LERP(t_tc);\n"
"#ifdef VERTEXLIT\n"
"vc = LERP(t_vc);\n"
"#else\n"
"lm0 = LERP(t_lm0);\n"
"#ifdef LIGHTSTYLED\n"
"lm1 = LERP(t_lm1);\n"
"lm2 = LERP(t_lm2);\n"
"lm3 = LERP(t_lm3);\n"
"#endif\n"
"#endif\n"
"vec3 w = LERP(t_vertex);\n"
"vec3 t0 = w - dot(w-t_vertex[0],t_normal[0])*t_normal[0];\n"
"vec3 t1 = w - dot(w-t_vertex[1],t_normal[1])*t_normal[1];\n"
"vec3 t2 = w - dot(w-t_vertex[2],t_normal[2])*t_normal[2];\n"
"w = w*(1.0-factor) + factor*(gl_TessCoord.x*t0+gl_TessCoord.y*t1+gl_TessCoord.z*t2);\n"
"#if defined(PCF) || defined(SPOT) || defined(CUBE)\n"
//for texture projections/shadowmapping on dlights
"vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0));\n"
"#endif\n"
//FIXME: we should be recalcing these here, instead of just lerping them
"#ifdef REFLECTCUBEMASK\n"
"invsurface = LERP(t_invsurface);\n"
"#endif\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"eyevector = LERP(t_eyevector);\n"
"#endif\n"
"gl_Position = m_modelviewprojection * vec4(w,1.0);\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
//samplers
@ -9302,6 +9636,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "rtlight",
"!!ver 100 150\n"
"!!permu TESS\n"
"!!permu BUMP\n"
"!!permu FRAMEBLEND\n"
"!!permu SKELETAL\n"
@ -9310,7 +9646,9 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"!!permu REFLECTCUBEMASK\n"
"!!cvarf r_glsl_offsetmapping_scale\n"
"!!cvardf r_glsl_pcf\n"
"!!cvardf r_tessellation=0\n"
"#include \"sys/defs.h\"\n"
"#ifndef USE_ARB_SHADOW\n"
//fall back on regular samplers if we must
@ -9352,7 +9690,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#undef OFFSETMAPPING\n"
"#endif\n"
"#if !defined(TESS_CONTROL_SHADER)\n"
"varying vec2 tcbase;\n"
"varying vec3 lightvector;\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
@ -9360,23 +9698,18 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
"varying mat3 invsurface;\n"
"uniform mat4 m_model;\n"
"#endif\n"
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
"varying vec4 vtexprojcoord;\n"
"#endif\n"
"#endif\n"
"#ifdef VERTEX_SHADER\n"
"#if defined(PCF) || defined(CUBE) || defined(SPOT)\n"
"uniform mat4 l_cubematrix;\n"
"#ifdef TESS\n"
"varying vec3 vertex, normal;\n"
"#endif\n"
"#include \"sys/skeletal.h\"\n"
"uniform vec3 l_lightposition;\n"
"attribute vec2 v_texcoord;\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"uniform vec3 e_eyepos;\n"
"#endif\n"
"void main ()\n"
"{\n"
"vec3 n, s, t, w;\n"
@ -9407,57 +9740,114 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
//for texture projections/shadowmapping on dlights
"vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0));\n"
"#endif\n"
"#ifdef TESS\n"
"vertex = w;\n"
"normal = n;\n"
"#endif\n"
"}\n"
"#endif\n"
"#if defined(TESS_CONTROL_SHADER)\n"
"layout(vertices = 3) out;\n"
"in vec3 vertex[];\n"
"out vec3 t_vertex[];\n"
"in vec3 normal[];\n"
"out vec3 t_normal[];\n"
"in vec2 tcbase[];\n"
"out vec2 t_tcbase[];\n"
"in vec3 lightvector[];\n"
"out vec3 t_lightvector[];\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"in vec3 eyevector[];\n"
"out vec3 t_eyevector[];\n"
"#endif\n"
"void main()\n"
"{\n"
//the control shader needs to pass stuff through
"#define id gl_InvocationID\n"
"t_vertex[id] = vertex[id];\n"
"t_normal[id] = normal[id];\n"
"t_tcbase[id] = tcbase[id];\n"
"t_lightvector[id] = lightvector[id];\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"t_eyevector[id] = eyevector[id];\n"
"#endif\n"
"gl_TessLevelOuter[0] = float(r_tessellation)+1.0;\n"
"gl_TessLevelOuter[1] = float(r_tessellation)+1.0;\n"
"gl_TessLevelOuter[2] = float(r_tessellation)+1.0;\n"
"gl_TessLevelInner[0] = float(r_tessellation)+1.0;\n"
"}\n"
"#endif\n"
"#if defined(TESS_EVALUATION_SHADER)\n"
"layout(triangles) in;\n"
"in vec3 t_vertex[];\n"
"in vec3 t_normal[];\n"
"in vec2 t_tcbase[];\n"
"in vec3 t_lightvector[];\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"in vec3 t_eyevector[];\n"
"#endif\n"
"#define LERP(a) (gl_TessCoord.x*a[0] + gl_TessCoord.y*a[1] + gl_TessCoord.z*a[2])\n"
"void main()\n"
"{\n"
"#define factor 1.0\n"
"tcbase = LERP(t_tcbase);\n"
"vec3 w = LERP(t_vertex);\n"
"vec3 t0 = w - dot(w-t_vertex[0],t_normal[0])*t_normal[0];\n"
"vec3 t1 = w - dot(w-t_vertex[1],t_normal[1])*t_normal[1];\n"
"vec3 t2 = w - dot(w-t_vertex[2],t_normal[2])*t_normal[2];\n"
"w = w*(1.0-factor) + factor*(gl_TessCoord.x*t0+gl_TessCoord.y*t1+gl_TessCoord.z*t2);\n"
"#if defined(PCF) || defined(SPOT) || defined(CUBE)\n"
//for texture projections/shadowmapping on dlights
"vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0));\n"
"#endif\n"
//FIXME: we should be recalcing these here, instead of just lerping them
"lightvector = LERP(t_lightvector);\n"
"#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"eyevector = LERP(t_eyevector);\n"
"#endif\n"
"gl_Position = m_modelviewprojection * vec4(w,1.0);\n"
"}\n"
"#endif\n"
"#ifdef FRAGMENT_SHADER\n"
"#include \"sys/fog.h\"\n"
"uniform sampler2D s_diffuse; //diffuse\n"
"#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)\n"
"uniform sampler2D s_normalmap; //normalmap\n"
"#endif\n"
"#ifdef SPECULAR\n"
"uniform sampler2D s_specular; //specular\n"
"#endif\n"
"#ifdef CUBE\n"
"uniform samplerCube s_projectionmap; //projected cubemap\n"
"#endif\n"
"#ifdef PCF\n"
"#ifdef CUBESHADOW\n"
"uniform samplerCubeShadow s_shadowmap; //shadowmap\n"
"#else\n"
"#if 0//def GL_ARB_texture_gather\n"
"uniform sampler2D s_shadowmap;\n"
"#else\n"
"uniform sampler2DShadow s_shadowmap;\n"
"#endif\n"
"#endif\n"
"#endif\n"
"#ifdef LOWER\n"
"uniform sampler2D s_lower; //pants colours\n"
"uniform vec3 e_lowercolour;\n"
"#endif\n"
"#ifdef UPPER\n"
"uniform sampler2D s_upper; //shirt colours\n"
"uniform vec3 e_uppercolour;\n"
"#endif\n"
"#ifdef REFLECTCUBEMASK\n"
"uniform sampler2D s_reflectmask;\n"
"uniform samplerCube s_reflectcube;\n"
"#endif\n"
"uniform float l_lightradius;\n"
"uniform vec3 l_lightcolour;\n"
"uniform vec3 l_lightcolourscale;\n"
"#ifdef PCF\n"
"uniform vec4 l_shadowmapproj; //light projection matrix info\n"
"uniform vec2 l_shadowmapscale; //xy are the texture scale, z is 1, w is the scale.\n"
"vec3 ShadowmapCoord(void)\n"
"{\n"
"#ifdef SPOT\n"
@ -9526,7 +9916,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#else\n"
"#ifdef USE_ARB_SHADOW\n"
//with arb_shadow, we can benefit from hardware acclerated pcf, for smoother shadows
"#define dosamp(x,y) shadow2D(s_shadowmap, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r\n"
"#define dosamp(x,y) shadow2D(s_shadowmap, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx))\n"
"#else\n"
//this will probably be a bit blocky.
"#define dosamp(x,y) float(texture2D(s_shadowmap, shadowcoord.xy + (vec2(x,y)*l_shadowmapscale.xy)).r >= shadowcoord.z)\n"

View file

@ -161,7 +161,7 @@ enum
SBITS_MISC_DEPTHCLOSERONLY = 0x00080000,
//#define SBITS_MISC_BITS 0x000f0000
SBITS_TRUFORM = 0x00100000,
SBITS_TESSELLATION = 0x00100000,
SBITS_AFFINE = 0x00200000,
//provided for the backend to hack about with
@ -441,6 +441,7 @@ typedef struct programshared_s
{
int refs;
qboolean nofixedcompat;
qboolean tess;
unsigned short numsamplers; //shader system can strip any passes above this
unsigned int defaulttextures; //diffuse etc

View file

@ -1067,6 +1067,7 @@ void SV_ArgumentOverrides(void);
int SV_CalcPing (client_t *cl, qboolean forcecalc);
void SV_FullClientUpdate (client_t *client, client_t *to);
void SV_GeneratePublicUserInfo(int pext, client_t *cl, char *info, int infolength);
char *SV_PlayerPublicAddress(client_t *cl);
int SV_ModelIndex (const char *name);

View file

@ -1219,7 +1219,7 @@ static void SV_FilterIP_f (void)
return;
}
if (!NET_StringToAdrMasked(Cmd_Argv(1), &proto.adr, &proto.adrmask))
if (!NET_StringToAdrMasked(Cmd_Argv(1), true, &proto.adr, &proto.adrmask))
{
Con_Printf("invalid address or mask\n");
return;
@ -1368,7 +1368,7 @@ static void SV_Unfilter_f (void)
Con_Printf("removing all filtered addresses\n");
all = true;
}
else if (!NET_StringToAdrMasked(Cmd_Argv(1), &unbanadr, &unbanmask))
else if (!NET_StringToAdrMasked(Cmd_Argv(1), true, &unbanadr, &unbanmask))
{
Con_Printf("invalid address or mask\n");
return;

View file

@ -248,6 +248,8 @@ void SV_Shutdown (void)
SV_GibFilterPurge();
Log_ShutDown();
NET_Shutdown ();
#ifdef PLUGINS
@ -1037,6 +1039,12 @@ CONNECTIONLESS COMMANDS
==============================================================================
*/
char *SV_PlayerPublicAddress(client_t *cl)
{ //returns a string containing the client's IP address, as permitted for viewing by other clients.
//if something useful is actually returned, it should be masked.
return "private";
}
#define STATUS_OLDSTYLE 0
#define STATUS_SERVERINFO 1
#define STATUS_PLAYERS 2
@ -1165,7 +1173,7 @@ void SVC_GetInfo (char *challenge, int fullstatus)
else
gamestatus = "";
COM_ParseOut(com_protocolname.string, protocolname, sizeof(protocolname));
COM_ParseOut(com_protocolname.string, protocolname, sizeof(protocolname)); //we can only report one, so report the first.
resp = response;
@ -1193,6 +1201,7 @@ void SVC_GetInfo (char *challenge, int fullstatus)
Info_SetValueForKey(resp, "clients", va("%d", numclients), sizeof(response) - (resp-response));
Info_SetValueForKey(resp, "sv_maxclients", maxclients.string, sizeof(response) - (resp-response));
Info_SetValueForKey(resp, "mapname", Info_ValueForKey(svs.info, "map"), sizeof(response) - (resp-response));
if (*gamestatus)
Info_SetValueForKey(resp, "qcstatus", gamestatus, sizeof(response) - (resp-response));
Info_SetValueForKey(resp, "challenge", challenge, sizeof(response) - (resp-response));
resp += strlen(resp);
@ -3770,7 +3779,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
MSG_WriteLong (&sb, cl->playercolor);
MSG_WriteLong (&sb, cl->old_frags);
MSG_WriteLong (&sb, realtime - cl->connection_started);
MSG_WriteString (&sb, ""); /*player's address, leave blank, don't spam that info as it can result in personal attacks exploits*/
MSG_WriteString (&sb, SV_PlayerPublicAddress(cl)); /*player's address, leave blank, don't spam that info as it can result in personal attacks exploits*/
}
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from);

View file

@ -5639,7 +5639,7 @@ static void SVNQ_Status_f(void)
if (!cl->state)
continue;
SV_PrintToClient(host_client, PRINT_HIGH, va("#%i\n", i+1));
SV_PrintToClient(host_client, PRINT_HIGH, va(" %s\n", "WITHHELD"));
SV_PrintToClient(host_client, PRINT_HIGH, va(" %s\n", SV_PlayerPublicAddress(cl)));
}
}

View file

@ -1,4 +1,5 @@
!!ver 100 130
!!ver 100 150
!!permu TESS
!!permu FULLBRIGHT
!!permu UPPERLOWER
!!permu FRAMEBLEND
@ -8,6 +9,7 @@
!!cvarf r_glsl_offsetmapping_scale
!!cvarf gl_specular
!!cvardf gl_affinemodels=0
!!cvardf r_tessellation=0
#include "sys/defs.h"
@ -16,19 +18,31 @@
//the vertex shader is responsible for calculating lighting values.
#if gl_affinemodels==1 && __VERSION__ >= 130
noperspective
#endif
varying vec2 tc;
varying vec3 light;
#if defined(SPECULAR) || defined(OFFSETMAPPING)
varying vec3 eyevector;
#define affine noperspective
#else
#define affine
#endif
#ifdef VERTEX_SHADER
#include "sys/skeletal.h"
affine varying vec2 tc;
varying vec3 light;
#if defined(SPECULAR) || defined(OFFSETMAPPING)
varying vec3 eyevector;
#endif
#ifdef TESS
varying vec3 vertex;
varying vec3 normal;
#endif
void main ()
{
#if defined(SPECULAR)||defined(OFFSETMAPPING)
@ -39,17 +53,120 @@ void main ()
eyevector.y = dot(eyeminusvertex, t.xyz);
eyevector.z = dot(eyeminusvertex, n.xyz);
#else
vec3 n;
gl_Position = skeletaltransform_n(n);
vec3 n, s, t, w;
gl_Position = skeletaltransform_wnst(w,n,s,t);
#endif
tc = v_texcoord;
float d = dot(n,e_light_dir);
if (d < 0.0) //vertex shader. this might get ugly, but I don't really want to make it per vertex.
d = 0.0; //this avoids the dark side going below the ambient level.
light = e_light_ambient + (dot(n,e_light_dir)*e_light_mul);
tc = v_texcoord;
#ifdef TESS
normal = n;
vertex = w;
#endif
}
#endif
#if defined(TESS_CONTROL_SHADER)
layout(vertices = 3) out;
in vec3 vertex[];
out vec3 t_vertex[];
in vec3 normal[];
out vec3 t_normal[];
affine in vec2 tc[];
affine out vec2 t_tc[];
in vec3 light[];
out vec3 t_light[];
#if defined(SPECULAR) || defined(OFFSETMAPPING)
in vec3 eyevector[];
out vec3 t_eyevector[];
#endif
void main()
{
//the control shader needs to pass stuff through
#define id gl_InvocationID
t_vertex[id] = vertex[id];
t_normal[id] = normal[id];
t_tc[id] = tc[id];
t_light[id] = light[id];
#if defined(SPECULAR) || defined(OFFSETMAPPING)
t_eyevector[id] = eyevector[id];
#endif
gl_TessLevelOuter[0] = float(r_tessellation)+1.0;
gl_TessLevelOuter[1] = float(r_tessellation)+1.0;
gl_TessLevelOuter[2] = float(r_tessellation)+1.0;
gl_TessLevelInner[0] = float(r_tessellation)+1.0;
}
#endif
#if defined(TESS_EVALUATION_SHADER)
layout(triangles) in;
in vec3 t_vertex[];
in vec3 t_normal[];
affine in vec2 t_tc[];
affine out vec2 tc;
in vec3 t_light[];
out vec3 light;
#if defined(SPECULAR) || defined(OFFSETMAPPING)
in vec3 t_eyevector[];
out vec3 eyevector;
#endif
#define LERP(a) (gl_TessCoord.x*a[0] + gl_TessCoord.y*a[1] + gl_TessCoord.z*a[2])
void main()
{
#define factor 1.0
tc = LERP(t_tc);
vec3 w = LERP(t_vertex);
vec3 t0 = w - dot(w-t_vertex[0],t_normal[0])*t_normal[0];
vec3 t1 = w - dot(w-t_vertex[1],t_normal[1])*t_normal[1];
vec3 t2 = w - dot(w-t_vertex[2],t_normal[2])*t_normal[2];
w = w*(1.0-factor) + factor*(gl_TessCoord.x*t0+gl_TessCoord.y*t1+gl_TessCoord.z*t2);
//FIXME: we should be recalcing these here, instead of just lerping them
light = LERP(t_light);
#if defined(SPECULAR) || defined(OFFSETMAPPING)
eyevector = LERP(t_eyevector);
#endif
gl_Position = m_modelviewprojection * vec4(w,1.0);
}
#endif
#ifdef FRAGMENT_SHADER
#include "sys/fog.h"
@ -67,9 +184,10 @@ uniform float cvar_gl_specular;
uniform sampler2D s_colourmap;
#endif
#if __VERSION__ >= 130
#define gl_FragColor thecolour
out vec4 thecolour;
affine varying vec2 tc;
varying vec3 light;
#if defined(SPECULAR) || defined(OFFSETMAPPING)
varying vec3 eyevector;
#endif

View file

@ -1,4 +1,5 @@
!!ver 100 120 // 130
!!ver 100 150
!!permu TESS
!!permu DELUXE
!!permu FULLBRIGHT
!!permu FOG
@ -8,19 +9,16 @@
!!permu REFLECTCUBEMASK
!!cvarf r_glsl_offsetmapping_scale
!!cvarf gl_specular
!!cvardf r_tessellation=0
#include "sys/defs.h"
#if __VERSION__ >= 130
#define texture2D texture
#define textureCube texture
#define gl_FragColor gl_FragData[0]
#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"
#if !defined(TESS_CONTROL_SHADER)
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
varying vec3 eyevector;
#endif
@ -41,8 +39,12 @@ varying vec2 tc;
varying vec2 lm0;
#endif
#endif
#endif
#ifdef VERTEX_SHADER
#ifdef TESS
varying vec3 vertex, normal;
#endif
void main ()
{
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
@ -73,10 +75,151 @@ void main ()
#endif
#endif
gl_Position = ftetransform();
#ifdef TESS
vertex = v_position;
normal = v_normal;
#endif
}
#endif
#if defined(TESS_CONTROL_SHADER)
layout(vertices = 3) out;
in vec3 vertex[];
out vec3 t_vertex[];
in vec3 normal[];
out vec3 t_normal[];
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
in vec3 eyevector[];
out vec3 t_eyevector[];
#endif
#ifdef REFLECTCUBEMASK
in mat3 invsurface[];
out mat3 t_invsurface[];
#endif
in vec2 tc[];
out vec2 t_tc[];
#ifdef VERTEXLIT
in vec4 vc[];
out vec4 t_vc[];
#else
in vec2 lm0[];
out vec2 t_lm0[];
#ifdef LIGHTSTYLED
in vec2 lm1[], lm2[], lm3[];
out vec2 t_lm1[], t_lm2[], t_lm3[];
#endif
#endif
void main()
{
//the control shader needs to pass stuff through
#define id gl_InvocationID
t_vertex[id] = vertex[id];
t_normal[id] = normal[id];
#ifdef REFLECTCUBEMASK
t_invsurface[id] = invsurface[id];
#endif
t_tc[id] = tc[id];
#ifdef VERTEXLIT
t_vc[id] = vc[id];
#else
t_lm0[id] = lm0[id];
#ifdef LIGHTSTYLED
t_lm1[id] = lm1[id];
t_lm2[id] = lm2[id];
t_lm3[id] = lm3[id];
#endif
#endif
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
t_eyevector[id] = eyevector[id];
#endif
gl_TessLevelOuter[0] = float(r_tessellation)+1.0;
gl_TessLevelOuter[1] = float(r_tessellation)+1.0;
gl_TessLevelOuter[2] = float(r_tessellation)+1.0;
gl_TessLevelInner[0] = float(r_tessellation)+1.0;
}
#endif
#if defined(TESS_EVALUATION_SHADER)
layout(triangles) in;
in vec3 t_vertex[];
in vec3 t_normal[];
#if defined(OFFSETMAPPING) || defined(SPECULAR) || defined(REFLECTCUBEMASK)
in vec3 t_eyevector[];
#endif
#ifdef REFLECTCUBEMASK
in mat3 t_invsurface[];
#endif
in vec2 t_tc[];
#ifdef VERTEXLIT
in vec4 t_vc[];
#else
#ifdef LIGHTSTYLED
//we could use an offset, but that would still need to be per-surface which would break batches
//fixme: merge attributes?
in vec2 t_lm0[], t_lm1[], t_lm2[], t_lm3[];
#else
in vec2 t_lm0[];
#endif
#endif
#define LERP(a) (gl_TessCoord.x*a[0] + gl_TessCoord.y*a[1] + gl_TessCoord.z*a[2])
void main()
{
#define factor 1.0
tc = LERP(t_tc);
#ifdef VERTEXLIT
vc = LERP(t_vc);
#else
lm0 = LERP(t_lm0);
#ifdef LIGHTSTYLED
lm1 = LERP(t_lm1);
lm2 = LERP(t_lm2);
lm3 = LERP(t_lm3);
#endif
#endif
vec3 w = LERP(t_vertex);
vec3 t0 = w - dot(w-t_vertex[0],t_normal[0])*t_normal[0];
vec3 t1 = w - dot(w-t_vertex[1],t_normal[1])*t_normal[1];
vec3 t2 = w - dot(w-t_vertex[2],t_normal[2])*t_normal[2];
w = w*(1.0-factor) + factor*(gl_TessCoord.x*t0+gl_TessCoord.y*t1+gl_TessCoord.z*t2);
#if defined(PCF) || defined(SPOT) || defined(CUBE)
//for texture projections/shadowmapping on dlights
vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0));
#endif
//FIXME: we should be recalcing these here, instead of just lerping them
#ifdef REFLECTCUBEMASK
invsurface = LERP(t_invsurface);
#endif
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
eyevector = LERP(t_eyevector);
#endif
gl_Position = m_modelviewprojection * vec4(w,1.0);
}
#endif
#ifdef FRAGMENT_SHADER
//samplers

View file

@ -1,5 +1,10 @@
!!ver 100 150
!!permu TESS
!!permu FRAMEBLEND
!!permu SKELETAL
!!cvardf r_tessellation=0
#include "sys/defs.h"
//standard shader used for drawing shadowmap depth.
//also used for masking off portals and other things that want depth and no colour.
@ -8,12 +13,80 @@
#ifdef VERTEX_SHADER
#include "sys/skeletal.h"
#ifdef TESS
varying vec3 vertex;
varying vec3 normal;
#endif
void main ()
{
#ifdef TESS
skeletaltransform_n(normal);
vertex = v_position;
#else
gl_Position = skeletaltransform();
#endif
}
#endif
#if defined(TESS_CONTROL_SHADER)
layout(vertices = 3) out;
in vec3 vertex[];
out vec3 t_vertex[];
in vec3 normal[];
out vec3 t_normal[];
void main()
{
//the control shader needs to pass stuff through
#define id gl_InvocationID
t_vertex[id] = vertex[id];
t_normal[id] = normal[id];
gl_TessLevelOuter[0] = float(r_tessellation)+1.0;
gl_TessLevelOuter[1] = float(r_tessellation)+1.0;
gl_TessLevelOuter[2] = float(r_tessellation)+1.0;
gl_TessLevelInner[0] = float(r_tessellation)+1.0;
}
#endif
#if defined(TESS_EVALUATION_SHADER)
layout(triangles) in;
in vec3 t_vertex[];
in vec3 t_normal[];
#define LERP(a) (gl_TessCoord.x*a[0] + gl_TessCoord.y*a[1] + gl_TessCoord.z*a[2])
void main()
{
#define factor 1.0
vec3 w = LERP(t_vertex);
vec3 t0 = w - dot(w-t_vertex[0],t_normal[0])*t_normal[0];
vec3 t1 = w - dot(w-t_vertex[1],t_normal[1])*t_normal[1];
vec3 t2 = w - dot(w-t_vertex[2],t_normal[2])*t_normal[2];
w = w*(1.0-factor) + factor*(gl_TessCoord.x*t0+gl_TessCoord.y*t1+gl_TessCoord.z*t2);
gl_Position = m_modelviewprojection * vec4(w,1.0);
}
#endif
#ifdef FRAGMENT_SHADER
void main ()
{

View file

@ -1,3 +1,5 @@
!!ver 100 150
!!permu TESS
!!permu BUMP
!!permu FRAMEBLEND
!!permu SKELETAL
@ -6,7 +8,9 @@
!!permu REFLECTCUBEMASK
!!cvarf r_glsl_offsetmapping_scale
!!cvardf r_glsl_pcf
!!cvardf r_tessellation=0
#include "sys/defs.h"
#ifndef USE_ARB_SHADOW
//fall back on regular samplers if we must
@ -48,7 +52,7 @@
#undef OFFSETMAPPING
#endif
#if !defined(TESS_CONTROL_SHADER)
varying vec2 tcbase;
varying vec3 lightvector;
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
@ -56,23 +60,18 @@ varying vec3 eyevector;
#endif
#ifdef REFLECTCUBEMASK
varying mat3 invsurface;
uniform mat4 m_model;
#endif
#if defined(PCF) || defined(CUBE) || defined(SPOT)
varying vec4 vtexprojcoord;
#endif
#endif
#ifdef VERTEX_SHADER
#if defined(PCF) || defined(CUBE) || defined(SPOT)
uniform mat4 l_cubematrix;
#ifdef TESS
varying vec3 vertex, normal;
#endif
#include "sys/skeletal.h"
uniform vec3 l_lightposition;
attribute vec2 v_texcoord;
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
uniform vec3 e_eyepos;
#endif
void main ()
{
vec3 n, s, t, w;
@ -103,57 +102,114 @@ void main ()
//for texture projections/shadowmapping on dlights
vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0));
#endif
#ifdef TESS
vertex = w;
normal = n;
#endif
}
#endif
#if defined(TESS_CONTROL_SHADER)
layout(vertices = 3) out;
in vec3 vertex[];
out vec3 t_vertex[];
in vec3 normal[];
out vec3 t_normal[];
in vec2 tcbase[];
out vec2 t_tcbase[];
in vec3 lightvector[];
out vec3 t_lightvector[];
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
in vec3 eyevector[];
out vec3 t_eyevector[];
#endif
void main()
{
//the control shader needs to pass stuff through
#define id gl_InvocationID
t_vertex[id] = vertex[id];
t_normal[id] = normal[id];
t_tcbase[id] = tcbase[id];
t_lightvector[id] = lightvector[id];
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
t_eyevector[id] = eyevector[id];
#endif
gl_TessLevelOuter[0] = float(r_tessellation)+1.0;
gl_TessLevelOuter[1] = float(r_tessellation)+1.0;
gl_TessLevelOuter[2] = float(r_tessellation)+1.0;
gl_TessLevelInner[0] = float(r_tessellation)+1.0;
}
#endif
#if defined(TESS_EVALUATION_SHADER)
layout(triangles) in;
in vec3 t_vertex[];
in vec3 t_normal[];
in vec2 t_tcbase[];
in vec3 t_lightvector[];
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
in vec3 t_eyevector[];
#endif
#define LERP(a) (gl_TessCoord.x*a[0] + gl_TessCoord.y*a[1] + gl_TessCoord.z*a[2])
void main()
{
#define factor 1.0
tcbase = LERP(t_tcbase);
vec3 w = LERP(t_vertex);
vec3 t0 = w - dot(w-t_vertex[0],t_normal[0])*t_normal[0];
vec3 t1 = w - dot(w-t_vertex[1],t_normal[1])*t_normal[1];
vec3 t2 = w - dot(w-t_vertex[2],t_normal[2])*t_normal[2];
w = w*(1.0-factor) + factor*(gl_TessCoord.x*t0+gl_TessCoord.y*t1+gl_TessCoord.z*t2);
#if defined(PCF) || defined(SPOT) || defined(CUBE)
//for texture projections/shadowmapping on dlights
vtexprojcoord = (l_cubematrix*vec4(w.xyz, 1.0));
#endif
//FIXME: we should be recalcing these here, instead of just lerping them
lightvector = LERP(t_lightvector);
#if defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
eyevector = LERP(t_eyevector);
#endif
gl_Position = m_modelviewprojection * vec4(w,1.0);
}
#endif
#ifdef FRAGMENT_SHADER
#include "sys/fog.h"
uniform sampler2D s_diffuse; //diffuse
#if defined(BUMP) || defined(SPECULAR) || defined(OFFSETMAPPING) || defined(REFLECTCUBEMASK)
uniform sampler2D s_normalmap; //normalmap
#endif
#ifdef SPECULAR
uniform sampler2D s_specular; //specular
#endif
#ifdef CUBE
uniform samplerCube s_projectionmap; //projected cubemap
#endif
#ifdef PCF
#ifdef CUBESHADOW
uniform samplerCubeShadow s_shadowmap; //shadowmap
#else
#if 0//def GL_ARB_texture_gather
uniform sampler2D s_shadowmap;
#else
uniform sampler2DShadow s_shadowmap;
#endif
#endif
#endif
#ifdef LOWER
uniform sampler2D s_lower; //pants colours
uniform vec3 e_lowercolour;
#endif
#ifdef UPPER
uniform sampler2D s_upper; //shirt colours
uniform vec3 e_uppercolour;
#endif
#ifdef REFLECTCUBEMASK
uniform sampler2D s_reflectmask;
uniform samplerCube s_reflectcube;
#endif
uniform float l_lightradius;
uniform vec3 l_lightcolour;
uniform vec3 l_lightcolourscale;
#ifdef PCF
uniform vec4 l_shadowmapproj; //light projection matrix info
uniform vec2 l_shadowmapscale; //xy are the texture scale, z is 1, w is the scale.
vec3 ShadowmapCoord(void)
{
#ifdef SPOT
@ -222,7 +278,7 @@ float ShadowmapFilter(void)
#else
#ifdef USE_ARB_SHADOW
//with arb_shadow, we can benefit from hardware acclerated pcf, for smoother shadows
#define dosamp(x,y) shadow2D(s_shadowmap, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx)).r
#define dosamp(x,y) shadow2D(s_shadowmap, shadowcoord.xyz + (vec3(x,y,0.0)*l_shadowmapscale.xyx))
#else
//this will probably be a bit blocky.
#define dosamp(x,y) float(texture2D(s_shadowmap, shadowcoord.xy + (vec2(x,y)*l_shadowmapscale.xy)).r >= shadowcoord.z)