mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-10 14:42:13 +00:00
Basic vmt support. Requisite GLSL files are still separate.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6114 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
0f8ea71841
commit
462f3e4a20
4 changed files with 536 additions and 1 deletions
|
@ -1215,6 +1215,7 @@ IF(FTE_PLUG_HL2)
|
||||||
plugins/hl2/fs_vpk.c
|
plugins/hl2/fs_vpk.c
|
||||||
plugins/hl2/img_vtf.c
|
plugins/hl2/img_vtf.c
|
||||||
plugins/hl2/mod_hl2.c
|
plugins/hl2/mod_hl2.c
|
||||||
|
plugins/hl2/mat_vmt.c
|
||||||
)
|
)
|
||||||
SET_TARGET_PROPERTIES(plug_hl2 PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;MULTITHREAD;${FTE_LIB_DEFINES}")
|
SET_TARGET_PROPERTIES(plug_hl2 PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;MULTITHREAD;${FTE_LIB_DEFINES}")
|
||||||
TARGET_LINK_LIBRARIES(plug_hl2 ${SYS_LIBS} ${ZLIB_LIBRARIES})
|
TARGET_LINK_LIBRARIES(plug_hl2 ${SYS_LIBS} ${ZLIB_LIBRARIES})
|
||||||
|
|
|
@ -415,7 +415,7 @@ $(PLUG_PREFIX)openssl$(PLUG_NATIVE_EXT): net_ssl_openssl.c plugin.c
|
||||||
|
|
||||||
#####################
|
#####################
|
||||||
#for compat with half-life 2's file formats
|
#for compat with half-life 2's file formats
|
||||||
$(PLUG_PREFIX)hl2$(PLUG_NATIVE_EXT): hl2/fs_vpk.c hl2/img_vtf.c hl2/mod_hl2.c hl2/hl2.c plugin.c
|
$(PLUG_PREFIX)hl2$(PLUG_NATIVE_EXT): hl2/fs_vpk.c hl2/img_vtf.c hl2/mod_hl2.c hl2/mat_vmt.c hl2/hl2.c plugin.c
|
||||||
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -DMULTITHREAD -o $@ -shared $(PLUG_CFLAGS) $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
|
$(CC) $(BASE_CFLAGS) $(CFLAGS) -DFTEPLUGIN -DMULTITHREAD -o $@ -shared $(PLUG_CFLAGS) $^ $(PLUG_DEFFILE) $(PLUG_LDFLAGS)
|
||||||
#NATIVE_PLUGINS+=hl2
|
#NATIVE_PLUGINS+=hl2
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,14 @@
|
||||||
qboolean VPK_Init(void);
|
qboolean VPK_Init(void);
|
||||||
qboolean VTF_Init(void);
|
qboolean VTF_Init(void);
|
||||||
qboolean MDL_Init(void);
|
qboolean MDL_Init(void);
|
||||||
|
qboolean VMT_Init(void);
|
||||||
|
|
||||||
qboolean Plug_Init(void)
|
qboolean Plug_Init(void)
|
||||||
{
|
{
|
||||||
if (!VPK_Init())
|
if (!VPK_Init())
|
||||||
return false;
|
return false;
|
||||||
VTF_Init();
|
VTF_Init();
|
||||||
|
VMT_Init();
|
||||||
MDL_Init();
|
MDL_Init();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
532
plugins/hl2/mat_vmt.c
Normal file
532
plugins/hl2/mat_vmt.c
Normal file
|
@ -0,0 +1,532 @@
|
||||||
|
#include "../plugin.h"
|
||||||
|
#include "shader.h"
|
||||||
|
static plugfsfuncs_t *fsfuncs;
|
||||||
|
|
||||||
|
typedef struct shaderparsestate_s parsestate_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char **savefile;
|
||||||
|
char *sourcefile;
|
||||||
|
char type[MAX_QPATH];
|
||||||
|
char normalmap[MAX_QPATH];
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
char name[MAX_QPATH];
|
||||||
|
} tex[5];
|
||||||
|
char envmap[MAX_QPATH];
|
||||||
|
char envmapmask[MAX_QPATH];
|
||||||
|
char envfrombase;
|
||||||
|
char halflambert;
|
||||||
|
|
||||||
|
float alphatestref;
|
||||||
|
char *blendfunc;
|
||||||
|
qboolean alphatest;
|
||||||
|
qboolean culldisable;
|
||||||
|
qboolean ignorez;
|
||||||
|
char *replaceblock;
|
||||||
|
} vmtstate_t;
|
||||||
|
|
||||||
|
|
||||||
|
static void VARGS Q_strlcatfz (char *dest, size_t *offset, size_t size, const char *fmt, ...) LIKEPRINTF(4);
|
||||||
|
static void VARGS Q_strlcatfz (char *dest, size_t *offset, size_t size, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
|
||||||
|
dest += *offset;
|
||||||
|
size -= *offset;
|
||||||
|
|
||||||
|
va_start (argptr, fmt);
|
||||||
|
Q_vsnprintfz(dest, size, fmt, argptr);
|
||||||
|
va_end (argptr);
|
||||||
|
*offset += strlen(dest);
|
||||||
|
}
|
||||||
|
static void Q_StrCat(char **ptr, const char *append)
|
||||||
|
{
|
||||||
|
size_t oldlen = *ptr?strlen(*ptr):0;
|
||||||
|
size_t newlen = strlen(append);
|
||||||
|
char *newptr = plugfuncs->Malloc(oldlen+newlen+1);
|
||||||
|
memcpy(newptr, *ptr, oldlen);
|
||||||
|
memcpy(newptr+oldlen, append, newlen);
|
||||||
|
newptr[oldlen+newlen] = 0;
|
||||||
|
plugfuncs->Free(*ptr);
|
||||||
|
*ptr = newptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//case comparisons are specific to ascii only, so this should be 'safe' for utf-8 strings too.
|
||||||
|
int Q_strncasecmp (const char *s1, const char *s2, int n)
|
||||||
|
{
|
||||||
|
int c1, c2;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
c1 = *s1++;
|
||||||
|
c2 = *s2++;
|
||||||
|
|
||||||
|
if (!n--)
|
||||||
|
return 0; // strings are equal until end point
|
||||||
|
|
||||||
|
if (c1 != c2)
|
||||||
|
{
|
||||||
|
if (c1 >= 'a' && c1 <= 'z')
|
||||||
|
c1 -= ('a' - 'A');
|
||||||
|
if (c2 >= 'a' && c2 <= 'z')
|
||||||
|
c2 -= ('a' - 'A');
|
||||||
|
if (c1 != c2)
|
||||||
|
{ // strings not equal
|
||||||
|
if (c1 > c2)
|
||||||
|
return 1; // strings not equal
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!c1)
|
||||||
|
return 0; // strings are equal
|
||||||
|
// s1++;
|
||||||
|
// s2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int Q_strcasecmp (const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
return Q_strncasecmp (s1, s2, 0x7fffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static qboolean VMT_ReadVMT(const char *materialname, vmtstate_t *st); //this is made more complicated on account of includes allowing recursion
|
||||||
|
static char *VMT_ParseBlock(const char *fname, vmtstate_t *st, char *line)
|
||||||
|
{ //assumes the open { was already parsed, but will parse the close.
|
||||||
|
char *replace = NULL;
|
||||||
|
com_tokentype_t ttype;
|
||||||
|
char key[MAX_OSPATH];
|
||||||
|
char value[MAX_OSPATH];
|
||||||
|
char *qmark;
|
||||||
|
qboolean cond;
|
||||||
|
for(;line;)
|
||||||
|
{
|
||||||
|
line = cmdfuncs->ParseToken(line, key, sizeof(key), &ttype);
|
||||||
|
if (ttype == TTP_RAWTOKEN && !strcmp(key, "}"))
|
||||||
|
break; //end-of-block
|
||||||
|
line = cmdfuncs->ParseToken(line, value, sizeof(value), &ttype);
|
||||||
|
if (ttype == TTP_RAWTOKEN && !strcmp(value, "{"))
|
||||||
|
{ //sub block. we don't go into details here.
|
||||||
|
if (!Q_strcasecmp(key, "replace"))
|
||||||
|
replace = line;
|
||||||
|
else
|
||||||
|
Con_DPrintf("%s: Unknown block \"%s\"\n", fname, key);
|
||||||
|
line = VMT_ParseBlock(fname, NULL, line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((qmark = strchr(key, '?')))
|
||||||
|
{
|
||||||
|
*qmark++ = 0;
|
||||||
|
if (!Q_strcasecmp(key, "srgb"))
|
||||||
|
cond = false;//!!(vid.flags & VID_SRGBAWARE);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Con_DPrintf("%s: Unknown vmt conditional \"%s\"\n", fname, key);
|
||||||
|
cond = false;
|
||||||
|
}
|
||||||
|
if (!cond)
|
||||||
|
{
|
||||||
|
*key = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
memmove(key, qmark, strlen(qmark)+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*key || !st)
|
||||||
|
;
|
||||||
|
else if (!Q_strcasecmp(key, "include"))
|
||||||
|
{
|
||||||
|
if (!VMT_ReadVMT(value, st))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if (!Q_strcasecmp(key, "$basetexture") || !Q_strcasecmp(key, "$hdrbasetexture")) //fixme: hdr version should probably override the other. order matters.
|
||||||
|
Q_strlcpy(st->tex[0].name, value, sizeof(st->tex[0].name));
|
||||||
|
else if (!Q_strcasecmp(key, "$hdrcompressedtexture")) //named texture is R8G8B8E8 and needs to be decompressed manually... should probably just use e5bgr9 but we don't have a way to transcode it here.
|
||||||
|
;
|
||||||
|
else if (!Q_strcasecmp(key, "$basetexturetransform"))
|
||||||
|
;
|
||||||
|
else if (!Q_strcasecmp(key, "$bumpmap")) // same as normalmap ~eukara
|
||||||
|
{
|
||||||
|
Q_strlcpy(st->normalmap, value, sizeof(st->normalmap));
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
}
|
||||||
|
else if (!Q_strcasecmp(key, "$ssbump"))
|
||||||
|
;
|
||||||
|
else if (!Q_strcasecmp(key, "$ssbumpmathfix"))
|
||||||
|
;
|
||||||
|
else if (!Q_strcasecmp(key, "$basetexture2") || !strcmp(key, "$texture2"))
|
||||||
|
Q_strlcpy(st->tex[1].name, value, sizeof(st->tex[1].name));
|
||||||
|
else if (!Q_strcasecmp(key, "$basetexturetransform2"))
|
||||||
|
;
|
||||||
|
else if (!Q_strcasecmp(key, "$surfaceprop"))
|
||||||
|
;
|
||||||
|
|
||||||
|
else if (!Q_strcasecmp(key, "$ignorez"))
|
||||||
|
st->ignorez = !!atoi(value);
|
||||||
|
else if (!Q_strcasecmp(key, "$nocull") && (!strcmp(value, "1")||!strcmp(value, "0")))
|
||||||
|
st->culldisable = atoi(value);
|
||||||
|
else if (!Q_strcasecmp(key, "$alphatest") && (!strcmp(value, "1")||!strcmp(value, "0")))
|
||||||
|
st->alphatest = atoi(value);
|
||||||
|
else if (!Q_strcasecmp(key, "$alphatestreference"))
|
||||||
|
st->alphatestref = atof(value);
|
||||||
|
else if (!Q_strcasecmp(key, "$alphafunc"))
|
||||||
|
{
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
}
|
||||||
|
else if (!Q_strcasecmp(key, "$alpha"))
|
||||||
|
{
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
}
|
||||||
|
else if (!Q_strcasecmp(key, "$translucent"))
|
||||||
|
{
|
||||||
|
if (atoi(value))
|
||||||
|
st->blendfunc = "src_alpha one_minus_src_alpha\n";
|
||||||
|
}
|
||||||
|
else if (!Q_strcasecmp(key, "$additive"))
|
||||||
|
{
|
||||||
|
if (atoi(value))
|
||||||
|
st->blendfunc = "src_one one_minus_src_alpha\n";
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
}
|
||||||
|
else if (!Q_strcasecmp(key, "$halflambert"))
|
||||||
|
st->halflambert = 1;
|
||||||
|
else if (!Q_strcasecmp(key, "$color"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$vertexcolor"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$vertexalpha"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$decal"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$decalscale"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$decalsize"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$envmap"))
|
||||||
|
Q_strlcpy(st->envmap, value, sizeof(st->envmap));
|
||||||
|
else if (!Q_strcasecmp(key, "$envmapmask"))
|
||||||
|
Q_strlcpy(st->envmapmask, value, sizeof(st->envmapmask));
|
||||||
|
else if (!Q_strcasecmp(key, "$envmapcontrast"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$envmaptint"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$envmapsaturation"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$basealphaenvmapmask"))
|
||||||
|
st->envfrombase=1;
|
||||||
|
else if (!Q_strcasecmp(key, "$normalmapalphaenvmapmask"))
|
||||||
|
st->envfrombase=0;
|
||||||
|
else if (!Q_strcasecmp(key, "$crackmaterial"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$selfillum"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$selfillummask"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$selfillumtint"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$nofog"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$nomip"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$nodecal"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$detail"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$detailscale"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$detailtint"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$detailblendfactor"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$detailblendmode"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
|
||||||
|
else if (!Q_strcasecmp(key, "$surfaceprop2"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$AllowAlphaToCoverage"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$blendmodulatetexture"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
|
||||||
|
//water/reflection stuff
|
||||||
|
else if (!Q_strcasecmp(key, "$refracttinttexture"))
|
||||||
|
Q_strlcpy(st->tex[0].name, value, sizeof(st->tex[0].name));
|
||||||
|
else if (!Q_strcasecmp(key, "$refracttexture"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$refractamount"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$refracttint"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$reflecttexture"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$reflectamount"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$reflecttint"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$fresnelpower"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$minreflectivity"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$maxreflectivity"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$normalmap"))
|
||||||
|
{
|
||||||
|
Q_strlcpy(st->normalmap, value, sizeof(st->normalmap));
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
}
|
||||||
|
else if (!Q_strcasecmp(key, "$bumpframe"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$fogenable"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$fogcolor"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$fogstart"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$fogend"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$abovewater"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$underwateroverlay"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$reflectentities"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$scale"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$bottommaterial"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$scroll1"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
else if (!Q_strcasecmp(key, "$scroll2"))
|
||||||
|
Con_DPrintf("%s: %s \"%s\"\n", fname, key, value);
|
||||||
|
|
||||||
|
else if (*key == '%')
|
||||||
|
; //editor lines
|
||||||
|
else
|
||||||
|
Con_DPrintf("%s: Unknown field \"%s\"\n", fname, key);
|
||||||
|
}
|
||||||
|
if (replace)
|
||||||
|
VMT_ParseBlock(fname, st, replace);
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
static void Shader_GenerateFromVMT(parsestate_t *ps, vmtstate_t *st, const char *shortname, void (*LoadMaterialString)(parsestate_t *ps, const char *script))
|
||||||
|
{
|
||||||
|
size_t offset = 0;
|
||||||
|
char script[8192];
|
||||||
|
char *progargs = "";
|
||||||
|
|
||||||
|
if (!*st->tex[0].name) //fill in a default...
|
||||||
|
Q_strlcpy(st->tex[0].name, shortname, sizeof(st->tex[0].name));
|
||||||
|
|
||||||
|
if (st->alphatest)
|
||||||
|
progargs = "#MASK=0.5#MASKLT"; //alphamask has to be handled by glsl (when glsl is used)
|
||||||
|
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\n");
|
||||||
|
if (!Q_strcasecmp(st->type, "WorldVertexTransition"))
|
||||||
|
{ //attempt to do terrain blending
|
||||||
|
Q_strlcpy(st->type, "vmt_transition#TWOWAY", sizeof(st->type));
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tprogram \"%s%s\"\n", st->type, progargs);
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tuppermap \"%s%s.vtf\"\n", strcmp(st->tex[1].name, "materials/")?"materials/":"", st->tex[1].name);
|
||||||
|
}
|
||||||
|
else if (!Q_strcasecmp(st->type, "Decal"))
|
||||||
|
{
|
||||||
|
Q_strlcpy(st->type, "vmt_vertexlit", sizeof(st->type));
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tprogram \"%s%s\"\n", st->type, progargs);
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tpolygonOffset 1\n");
|
||||||
|
}
|
||||||
|
else if (!Q_strcasecmp(st->type, "DecalModulate"))
|
||||||
|
{
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script),
|
||||||
|
"\t{\n"
|
||||||
|
"\t\tprogram \"vmt_vertexlit%s\"\n"
|
||||||
|
"\t\tblendFunc gl_dst_color gl_one_minus_src_alpha\n"
|
||||||
|
"\t}\n", progargs);
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tpolygonOffset 1\n");
|
||||||
|
}
|
||||||
|
else if (!Q_strcasecmp(st->type, "Water"))
|
||||||
|
{
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script),
|
||||||
|
"\t{\n"
|
||||||
|
"\t\tprogram \"vmt_water%s\"\n"
|
||||||
|
"\t\tmap $refraction\n"
|
||||||
|
"\t\tmap $reflection\n"
|
||||||
|
"\t}\n", progargs);
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tnormalmap \"%s%s.vtf\"\n", strcmp(st->normalmap, "materials/")?"materials/":"", st->normalmap);
|
||||||
|
}
|
||||||
|
else if (!Q_strcasecmp(st->type, "Refract"))
|
||||||
|
{
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script),
|
||||||
|
"\t{\n"
|
||||||
|
"\t\tprogram \"vmt_refract%s\"\n"
|
||||||
|
"\t\tmap $refraction\n"
|
||||||
|
"\t}\n", progargs);
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tnormalmap \"%s%s.vtf\"\n", strcmp(st->normalmap, "materials/")?"materials/":"", st->normalmap);
|
||||||
|
}
|
||||||
|
else if (!Q_strcasecmp(st->type, "VertexlitGeneric"))
|
||||||
|
{
|
||||||
|
if (*st->envmap && st->envfrombase)
|
||||||
|
{
|
||||||
|
if (st->halflambert)
|
||||||
|
Q_strlcpy(st->type, "vmt_vertexlit#ENVFROMBASE#HALFLAMBERT", sizeof(st->type));
|
||||||
|
else
|
||||||
|
Q_strlcpy(st->type, "vmt_vertexlit#ENVFROMBASE", sizeof(st->type));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (st->halflambert)
|
||||||
|
Q_strlcpy(st->type, "vmt_vertexlit#HALFLAMBERT", sizeof(st->type));
|
||||||
|
else
|
||||||
|
Q_strlcpy(st->type, "vmt_vertexlit", sizeof(st->type));
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tprogram \"%s%s\"\n", st->type, progargs);
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
|
||||||
|
|
||||||
|
if (*st->normalmap)
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tnormalmap \"%s%s.vtf\"\n", strcmp(st->normalmap, "materials/")?"materials/":"", st->normalmap);
|
||||||
|
}
|
||||||
|
else if (!Q_strcasecmp(st->type, "LightmappedGeneric"))
|
||||||
|
{
|
||||||
|
/* reflectmask from diffuse map alpha */
|
||||||
|
if (*st->envmap && st->envfrombase)
|
||||||
|
Q_strlcpy(st->type, "vmt_lightmapped#ENVFROMBASE", sizeof(st->type));
|
||||||
|
else if (*st->envmap && *st->envmapmask) /* dedicated reflectmask */
|
||||||
|
Q_strlcpy(st->type, "vmt_lightmapped#ENVFROMMASK", sizeof(st->type));
|
||||||
|
else /* take from normalmap */
|
||||||
|
Q_strlcpy(st->type, "vmt_lightmapped", sizeof(st->type));
|
||||||
|
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tprogram \"%s%s\"\n", st->type, progargs);
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
|
||||||
|
|
||||||
|
if (*st->normalmap)
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tnormalmap \"%s%s.vtf\"\n", strcmp(st->normalmap, "materials/")?"materials/":"", st->normalmap);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* render-target camera/monitor - eukara*/
|
||||||
|
if (!Q_strcasecmp(st->tex[0].name, "_rt_Camera"))
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script),
|
||||||
|
"\t{\n"
|
||||||
|
"\t\tmap $rt:base\n"
|
||||||
|
"\t}\n"/*, progargs*/);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* the default should just be unlit, let's not make any assumptions - eukara*/
|
||||||
|
Q_strlcpy(st->type, "vmt_unlit", sizeof(st->type));
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tprogram \"%s%s\"\n", st->type, progargs);
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tdiffusemap \"%s%s.vtf\"\n", strcmp(st->tex[0].name, "materials/")?"materials/":"", st->tex[0].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*st->envmapmask)
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\treflectmask \"%s%s.vtf\"\n", strcmp(st->envmapmask, "materials/")?"materials/":"", st->envmapmask);
|
||||||
|
if (*st->envmap && strcmp(st->envmap, "env_cubemap"))
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\treflectcube \"%s%s.vtf\"\n", strcmp(st->envmap, "materials/")?"materials/":"", st->envmap);
|
||||||
|
if (st->alphatest)
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\talphatest ge128\n");
|
||||||
|
if (st->culldisable)
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tcull disable\n");
|
||||||
|
if (st->ignorez)
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tnodepth\n");
|
||||||
|
if (st->blendfunc)
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "\tprogblendfunc %s\n", st->blendfunc);
|
||||||
|
|
||||||
|
Q_strlcatfz(script, &offset, sizeof(script), "}\n");
|
||||||
|
|
||||||
|
LoadMaterialString(ps, script);
|
||||||
|
|
||||||
|
if (st->sourcefile)
|
||||||
|
{ //cat the original file on there...
|
||||||
|
if (st->savefile)
|
||||||
|
{
|
||||||
|
char *winsucks; //strip any '\r' chars in there that like to show as ugly glyphs.
|
||||||
|
for (winsucks = st->sourcefile; *winsucks; winsucks++)
|
||||||
|
if (*winsucks=='\r')
|
||||||
|
*winsucks = ' ';
|
||||||
|
|
||||||
|
Q_StrCat(st->savefile, "\n/*\n");
|
||||||
|
Q_StrCat(st->savefile, st->sourcefile);
|
||||||
|
Q_StrCat(st->savefile, "*/");
|
||||||
|
}
|
||||||
|
plugfuncs->Free(st->sourcefile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static qboolean VMT_ReadVMT(const char *fname, vmtstate_t *st)
|
||||||
|
{
|
||||||
|
char *line, *file = NULL;
|
||||||
|
com_tokentype_t ttype;
|
||||||
|
char token[MAX_QPATH];
|
||||||
|
char *prefix="", *postfix="";
|
||||||
|
|
||||||
|
//don't dupe the mandatory materials/ prefix
|
||||||
|
if (strncmp(fname, "materials/", 10))
|
||||||
|
prefix = "materials/";
|
||||||
|
if (strcmp(fsfuncs->GetExtension(fname, NULL), ".vmt"))
|
||||||
|
postfix = ".vmt";
|
||||||
|
Q_snprintfz(token, sizeof(token), "%s%s%s", prefix, fname, postfix);
|
||||||
|
|
||||||
|
file = fsfuncs->LoadFile(token, NULL);
|
||||||
|
if (file)
|
||||||
|
{
|
||||||
|
if (st->savefile)
|
||||||
|
{
|
||||||
|
if (st->sourcefile)
|
||||||
|
{
|
||||||
|
Q_StrCat(&st->sourcefile, fname);
|
||||||
|
Q_StrCat(&st->sourcefile, ":\n");
|
||||||
|
Q_StrCat(&st->sourcefile, file);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Q_StrCat(&st->sourcefile, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
line = file;
|
||||||
|
line = cmdfuncs->ParseToken(line, st->type, sizeof(st->type), &ttype);
|
||||||
|
line = cmdfuncs->ParseToken(line, token, sizeof(token), &ttype);
|
||||||
|
if (!strcmp(token, "{"))
|
||||||
|
{
|
||||||
|
line = VMT_ParseBlock(fname, st, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
plugfuncs->Free(file);
|
||||||
|
return !!line;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
static qboolean Shader_LoadVMT(parsestate_t *ps, const char *filename, void (*LoadMaterialString)(parsestate_t *ps, const char *script))
|
||||||
|
{
|
||||||
|
vmtstate_t st;
|
||||||
|
memset(&st, 0, sizeof(st));
|
||||||
|
st.savefile = NULL;//ps->saveshaderbody;
|
||||||
|
if (!VMT_ReadVMT(filename, &st))
|
||||||
|
{
|
||||||
|
if (st.sourcefile)
|
||||||
|
plugfuncs->Free(st.sourcefile);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader_GenerateFromVMT(ps, &st, filename, LoadMaterialString);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static plugmaterialloaderfuncs_t vmtfuncs =
|
||||||
|
{
|
||||||
|
"HL2 VMT",
|
||||||
|
Shader_LoadVMT,
|
||||||
|
};
|
||||||
|
|
||||||
|
qboolean VMT_Init(void)
|
||||||
|
{
|
||||||
|
fsfuncs = plugfuncs->GetEngineInterface(plugfsfuncs_name, sizeof(*fsfuncs));
|
||||||
|
if (!fsfuncs)
|
||||||
|
return false;
|
||||||
|
return plugfuncs->ExportInterface(plugmaterialloaderfuncs_name, &vmtfuncs, sizeof(vmtfuncs));
|
||||||
|
}
|
Loading…
Reference in a new issue