mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-10 06:32:00 +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/img_vtf.c
|
||||
plugins/hl2/mod_hl2.c
|
||||
plugins/hl2/mat_vmt.c
|
||||
)
|
||||
SET_TARGET_PROPERTIES(plug_hl2 PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN;MULTITHREAD;${FTE_LIB_DEFINES}")
|
||||
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
|
||||
$(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)
|
||||
#NATIVE_PLUGINS+=hl2
|
||||
|
||||
|
|
|
@ -2,12 +2,14 @@
|
|||
qboolean VPK_Init(void);
|
||||
qboolean VTF_Init(void);
|
||||
qboolean MDL_Init(void);
|
||||
qboolean VMT_Init(void);
|
||||
|
||||
qboolean Plug_Init(void)
|
||||
{
|
||||
if (!VPK_Init())
|
||||
return false;
|
||||
VTF_Init();
|
||||
VMT_Init();
|
||||
MDL_Init();
|
||||
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