mirror of
https://github.com/nzp-team/fteqw.git
synced 2025-01-31 04:30:38 +00:00
add support for gltf's KHR_materials_variants (for selectable skins) and KHR_materials_ior extensions
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5927 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
df83d72837
commit
6cc5e1762b
3 changed files with 99 additions and 21 deletions
|
@ -318,7 +318,10 @@ void main ()
|
||||||
|
|
||||||
col *= factor_base;
|
col *= factor_base;
|
||||||
|
|
||||||
#define dielectricSpecular 0.04
|
#ifndef IOR
|
||||||
|
#define IOR 1.5 //Index Of Reflection.
|
||||||
|
#endif
|
||||||
|
#define dielectricSpecular pow(((IOR - 1.0)/(IOR + 1.0)),2.0)
|
||||||
#ifdef SPECULAR
|
#ifdef SPECULAR
|
||||||
vec4 specs = texture2D(s_specular, tc)*factor_spec;
|
vec4 specs = texture2D(s_specular, tc)*factor_spec;
|
||||||
#ifdef ORM
|
#ifdef ORM
|
||||||
|
|
|
@ -331,7 +331,10 @@ void main ()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// col *= factor_base;
|
// col *= factor_base;
|
||||||
#define dielectricSpecular 0.04
|
#ifndef IOR
|
||||||
|
#define IOR 1.5 //Index Of Reflection.
|
||||||
|
#endif
|
||||||
|
#define dielectricSpecular pow(((IOR - 1.0)/(IOR + 1.0)),2.0)
|
||||||
#ifdef SPECULAR
|
#ifdef SPECULAR
|
||||||
vec4 specs = texture2D(s_specular, tc);//*factor_spec;
|
vec4 specs = texture2D(s_specular, tc);//*factor_spec;
|
||||||
#ifdef ORM
|
#ifdef ORM
|
||||||
|
|
|
@ -713,6 +713,8 @@ typedef struct gltf_s
|
||||||
json_t *r;
|
json_t *r;
|
||||||
int ver;
|
int ver;
|
||||||
|
|
||||||
|
unsigned int variations;
|
||||||
|
|
||||||
int *bonemap;//[MAX_BONES]; //remap skinned bones. I hate that we have to do this.
|
int *bonemap;//[MAX_BONES]; //remap skinned bones. I hate that we have to do this.
|
||||||
struct gltfbone_s
|
struct gltfbone_s
|
||||||
{
|
{
|
||||||
|
@ -785,8 +787,21 @@ static json_t *GLTF_FindJSONID_First(struct gltf_s *gltf, const char *restype, j
|
||||||
return GLTF_FindJSONIDParent(gltf, JSON_FindChild(gltf->r, restype), id, idx);
|
return GLTF_FindJSONIDParent(gltf, JSON_FindChild(gltf->r, restype), id, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dehex(int i)
|
||||||
|
{
|
||||||
|
if (i >= '0' && i <= '9')
|
||||||
|
return (i-'0');
|
||||||
|
else if (i >= 'A' && i <= 'F')
|
||||||
|
return (i-'A'+10);
|
||||||
|
else if (i >= 'a' && i <= 'f')
|
||||||
|
return (i-'a'+10);
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void GLTF_RelativePath(const char *base, const char *relative, char *out, size_t outsize)
|
static void GLTF_RelativePath(const char *base, const char *relative, char *out, size_t outsize)
|
||||||
{
|
{
|
||||||
|
char *out_start = out;
|
||||||
size_t t;
|
size_t t;
|
||||||
const char *sep;
|
const char *sep;
|
||||||
const char *end = base;
|
const char *end = base;
|
||||||
|
@ -830,13 +845,27 @@ static void GLTF_RelativePath(const char *base, const char *relative, char *out,
|
||||||
out += t;
|
out += t;
|
||||||
outsize -= t;
|
outsize -= t;
|
||||||
|
|
||||||
//FIXME: uris should be percent-decoded here.
|
for (; *relative && outsize; outsize--)
|
||||||
t = strlen(relative);
|
{
|
||||||
if (t > outsize)
|
if (*relative == '%' && ((out-out_start>=7 && !strncmp(out_start, "http://", 7)) || (out-out_start>=8 && !strncmp(out_start, "https://", 8))))
|
||||||
t = outsize;
|
{
|
||||||
memcpy(out, relative, t);
|
int high, low;
|
||||||
out += t;
|
char b = *relative++;
|
||||||
outsize -= t;
|
high = dehex(relative[0]);
|
||||||
|
if (high >= 0)
|
||||||
|
{
|
||||||
|
low = dehex(relative[1]);
|
||||||
|
if (low >= 0 && (high || low))
|
||||||
|
{
|
||||||
|
relative += 2;
|
||||||
|
b = (high<<4) | low;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*out++ = b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*out++ = *relative++;
|
||||||
|
}
|
||||||
|
|
||||||
*out = 0;
|
*out = 0;
|
||||||
}
|
}
|
||||||
|
@ -1961,7 +1990,7 @@ static qboolean GLTF1_LoadMaterial(gltf_t *gltf, json_t *mat, texnums_t *texnums
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, qboolean vertexcolours)
|
static void GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, galiasskin_t *ret, qboolean vertexcolours)
|
||||||
{
|
{
|
||||||
qboolean doubleSided;
|
qboolean doubleSided;
|
||||||
int alphaMode;
|
int alphaMode;
|
||||||
|
@ -1970,7 +1999,6 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, qboolea
|
||||||
char alphaCutoffmodifier[128];
|
char alphaCutoffmodifier[128];
|
||||||
quintptr_t materialidx;
|
quintptr_t materialidx;
|
||||||
json_t *mat = GLTF_FindJSONID(gltf, "materials", materialid, &materialidx);
|
json_t *mat = GLTF_FindJSONID(gltf, "materials", materialid, &materialidx);
|
||||||
galiasskin_t *ret;
|
|
||||||
char tmp[64];
|
char tmp[64];
|
||||||
const char *t;
|
const char *t;
|
||||||
|
|
||||||
|
@ -1998,7 +2026,6 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, qboolea
|
||||||
Con_Printf(CON_WARNING"%s: unsupported alphaMode: %s\n", gltf->mod->name, t);
|
Con_Printf(CON_WARNING"%s: unsupported alphaMode: %s\n", gltf->mod->name, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = modfuncs->ZG_Malloc(&gltf->mod->memgroup, sizeof(*ret));
|
|
||||||
ret->numframes = 1;
|
ret->numframes = 1;
|
||||||
ret->skinspeed = 0.1;
|
ret->skinspeed = 0.1;
|
||||||
ret->frame = modfuncs->ZG_Malloc(&gltf->mod->memgroup, sizeof(*ret->frame));
|
ret->frame = modfuncs->ZG_Malloc(&gltf->mod->memgroup, sizeof(*ret->frame));
|
||||||
|
@ -2018,7 +2045,7 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, qboolea
|
||||||
skip = 0;
|
skip = 0;
|
||||||
if (mod_gltf_privatematerials->ival && !strchr(shader, '/'))
|
if (mod_gltf_privatematerials->ival && !strchr(shader, '/'))
|
||||||
{
|
{
|
||||||
Q_snprintf(ret->frame->shadername, sizeof(ret->frame->shadername), "%s", gltf->mod->name-skip);
|
Q_snprintf(ret->frame->shadername, sizeof(ret->frame->shadername), "%s/%u", gltf->mod->name-skip, (unsigned)materialidx);
|
||||||
Q_strncatz(ret->frame->shadername, "/", sizeof(ret->frame->shadername));
|
Q_strncatz(ret->frame->shadername, "/", sizeof(ret->frame->shadername));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2116,6 +2143,7 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, qboolea
|
||||||
else if (pbrsg)
|
else if (pbrsg)
|
||||||
{ //if this extension was used, then we can use rgb gloss instead of metalness stuff.
|
{ //if this extension was used, then we can use rgb gloss instead of metalness stuff.
|
||||||
json_t *occ = JSON_FindChild(mat, "occlusionTexture.index"); //.r
|
json_t *occ = JSON_FindChild(mat, "occlusionTexture.index"); //.r
|
||||||
|
float ior = JSON_GetFloat(mat, "extensions.KHR_materials_ior.ior", 1.5); //supposedly still relevant here
|
||||||
ret->frame->texnums.base = GLTF_LoadTexture(gltf, JSON_FindChild(pbrsg, "diffuseTexture.index"), 0);
|
ret->frame->texnums.base = GLTF_LoadTexture(gltf, JSON_FindChild(pbrsg, "diffuseTexture.index"), 0);
|
||||||
ret->frame->texnums.specular = GLTF_LoadTexture(gltf, JSON_FindChild(pbrsg, "specularGlossinessTexture.index"), 0);
|
ret->frame->texnums.specular = GLTF_LoadTexture(gltf, JSON_FindChild(pbrsg, "specularGlossinessTexture.index"), 0);
|
||||||
if (occ)
|
if (occ)
|
||||||
|
@ -2124,7 +2152,7 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, qboolea
|
||||||
Q_snprintf(shader, sizeof(shader),
|
Q_snprintf(shader, sizeof(shader),
|
||||||
"{\n"
|
"{\n"
|
||||||
"%s"//cull
|
"%s"//cull
|
||||||
"program defaultskin#SG#VC%s%s\n"
|
"program defaultskin" "#SG" "#VC" "#IOR=%.02f" "%s"/*occlude*/ "%s"/*alphacutoff*/ "\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"map $diffuse\n"
|
"map $diffuse\n"
|
||||||
"%s" //blend
|
"%s" //blend
|
||||||
|
@ -2136,6 +2164,7 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, qboolea
|
||||||
"bemode rtlight rtlight_sg\n"
|
"bemode rtlight rtlight_sg\n"
|
||||||
"}\n",
|
"}\n",
|
||||||
doubleSided?"cull disable\n":"",
|
doubleSided?"cull disable\n":"",
|
||||||
|
ior,
|
||||||
(occ)?"#OCCLUDE":"",
|
(occ)?"#OCCLUDE":"",
|
||||||
alphaCutoffmodifier,
|
alphaCutoffmodifier,
|
||||||
(alphaMode==1)?"":(alphaMode==2)?"blendfunc blend\n":"",
|
(alphaMode==1)?"":(alphaMode==2)?"blendfunc blend\n":"",
|
||||||
|
@ -2162,6 +2191,7 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, qboolea
|
||||||
json_t *n;
|
json_t *n;
|
||||||
char occname[MAX_QPATH];
|
char occname[MAX_QPATH];
|
||||||
char mrtname[MAX_QPATH];
|
char mrtname[MAX_QPATH];
|
||||||
|
float ior = JSON_GetFloat(mat, "extensions.KHR_materials_ior.ior", 1.5);
|
||||||
|
|
||||||
if (JSON_GetInteger(pbrmr, "baseColorTexture.texCoord", 0) != 0)
|
if (JSON_GetInteger(pbrmr, "baseColorTexture.texCoord", 0) != 0)
|
||||||
if (gltf->warnlimit --> 0)
|
if (gltf->warnlimit --> 0)
|
||||||
|
@ -2198,7 +2228,7 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, qboolea
|
||||||
Q_snprintf(shader, sizeof(shader),
|
Q_snprintf(shader, sizeof(shader),
|
||||||
"{\n"
|
"{\n"
|
||||||
"%s"//cull
|
"%s"//cull
|
||||||
"program defaultskin#ORM#VC%s%s\n"
|
"program defaultskin" "#ORM" "#VC" "#IOR=%.02f" "%s"/*occlude*/ "%s"/*alphatest*/ "\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"map $diffuse\n"
|
"map $diffuse\n"
|
||||||
"%s" //blend
|
"%s" //blend
|
||||||
|
@ -2210,6 +2240,7 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, qboolea
|
||||||
"bemode rtlight rtlight_orm\n"
|
"bemode rtlight rtlight_orm\n"
|
||||||
"}\n",
|
"}\n",
|
||||||
doubleSided?"cull disable\n":"",
|
doubleSided?"cull disable\n":"",
|
||||||
|
ior,
|
||||||
(!occ)?"#NOOCCLUDE":(strcmp(occname,mrtname)?"#OCCLUDE":""),
|
(!occ)?"#NOOCCLUDE":(strcmp(occname,mrtname)?"#OCCLUDE":""),
|
||||||
alphaCutoffmodifier,
|
alphaCutoffmodifier,
|
||||||
(alphaMode==1)?"":(alphaMode==2)?"blendfunc blend\n":"",
|
(alphaMode==1)?"":(alphaMode==2)?"blendfunc blend\n":"",
|
||||||
|
@ -2237,7 +2268,6 @@ static galiasskin_t *GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, qboolea
|
||||||
ret->frame->defaultshader = memcpy(modfuncs->ZG_Malloc(&gltf->mod->memgroup, strlen(shader)+1), shader, strlen(shader)+1);
|
ret->frame->defaultshader = memcpy(modfuncs->ZG_Malloc(&gltf->mod->memgroup, strlen(shader)+1), shader, strlen(shader)+1);
|
||||||
|
|
||||||
Q_strlcpy(ret->name, ret->frame->shadername, sizeof(ret->name));
|
Q_strlcpy(ret->name, ret->frame->shadername, sizeof(ret->name));
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
static const float *QDECL GLTF_AnimateMorphs(const galiasinfo_t *surf, const framestate_t *framestate);
|
static const float *QDECL GLTF_AnimateMorphs(const galiasinfo_t *surf, const framestate_t *framestate);
|
||||||
|
@ -2461,8 +2491,30 @@ static qboolean GLTF_ProcessMesh(gltf_t *gltf, json_t *meshid, int basebone, dou
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SERVERONLY
|
#ifndef SERVERONLY
|
||||||
surf->numskins = 1;
|
{
|
||||||
surf->ofsskins = GLTF_LoadMaterial(gltf, JSON_FindChild(prim, "material"), surf->ofs_rgbaub||surf->ofs_rgbaf);
|
json_t *mapping, *var;
|
||||||
|
surf->numskins = 1+gltf->variations;
|
||||||
|
surf->ofsskins = modfuncs->ZG_Malloc(&gltf->mod->memgroup, sizeof(*surf->ofsskins)*surf->numskins);
|
||||||
|
GLTF_LoadMaterial(gltf, JSON_FindChild(prim, "material"), surf->ofsskins, surf->ofs_rgbaub||surf->ofs_rgbaf);
|
||||||
|
for (i = 0; i < gltf->variations; i++)
|
||||||
|
surf->ofsskins[1+i] = surf->ofsskins[0]; //unspecified matches defaults...
|
||||||
|
|
||||||
|
for (mapping=JSON_FindIndexedChild(prim, "extensions.KHR_materials_variants.mappings", 0); mapping; mapping = mapping->sibling)
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
for(var = JSON_FindIndexedChild(mapping, "variants", 0); var; var = var->sibling)
|
||||||
|
{
|
||||||
|
j = 1+JSON_GetUInteger(var, NULL, ~0u);
|
||||||
|
if (j < 1 || j >= surf->numskins)
|
||||||
|
continue; //not valid.
|
||||||
|
if (!i)
|
||||||
|
GLTF_LoadMaterial(gltf, JSON_FindChild(mapping, "material"), &surf->ofsskins[j], surf->ofs_rgbaub||surf->ofs_rgbaf);
|
||||||
|
else
|
||||||
|
surf->ofsskins[j] = surf->ofsskins[i];
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!tang.data)
|
if (!tang.data)
|
||||||
|
@ -3164,17 +3216,22 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize,
|
||||||
{"KHR_materials_pbrSpecularGlossiness", true, false},
|
{"KHR_materials_pbrSpecularGlossiness", true, false},
|
||||||
// {"KHR_materials_cmnBlinnPhong", true, true},
|
// {"KHR_materials_cmnBlinnPhong", true, true},
|
||||||
{"KHR_materials_unlit", true, false},
|
{"KHR_materials_unlit", true, false},
|
||||||
{"KHR_texture_transform", false, true}, //probably not fatal
|
|
||||||
{"KHR_draco_mesh_compression", false, true}, //probably fatal
|
|
||||||
{"KHR_mesh_quantization", true, true},
|
{"KHR_mesh_quantization", true, true},
|
||||||
{"MSFT_texture_dds", true, false},
|
{"MSFT_texture_dds", true, false},
|
||||||
{"MSFT_packing_occlusionRoughnessMetallic", true, false},
|
{"MSFT_packing_occlusionRoughnessMetallic", true, false},
|
||||||
|
{"KHR_materials_variants", true, false},
|
||||||
|
{"KHR_materials_ior", true, false},
|
||||||
|
|
||||||
|
{"KHR_draco_mesh_compression", false, true}, //probably fatal
|
||||||
|
{"KHR_texture_transform", false, false}, //requires glsl tweaks, per texmap. can't use tcmod if its only on the bumpmap etc.
|
||||||
|
{"KHR_materials_sheen", false, false}, //requires glsl tweaks, extra brdf layer in the middle for velvet.
|
||||||
|
{"KHR_materials_clearcoat", false, false}, //requires glsl tweaks, extra brdf layer over the top for varnish etc.
|
||||||
{NULL}
|
{NULL}
|
||||||
}, *extensions;
|
}, *extensions;
|
||||||
gltf_t gltf;
|
gltf_t gltf;
|
||||||
int pos=0;
|
int pos=0;
|
||||||
quintptr_t j,k;
|
quintptr_t j,k;
|
||||||
json_t *scene, *n, *anim;
|
json_t *scene, *n, *anim, *var;
|
||||||
double rootmatrix[16];
|
double rootmatrix[16];
|
||||||
double gltfver;
|
double gltfver;
|
||||||
galiasinfo_t *surf;
|
galiasinfo_t *surf;
|
||||||
|
@ -3297,6 +3354,11 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize,
|
||||||
}
|
}
|
||||||
gltf.numbones = j;
|
gltf.numbones = j;
|
||||||
|
|
||||||
|
|
||||||
|
gltf.variations = 0;
|
||||||
|
for (var = JSON_FindIndexedChild(gltf.r, "extensions.KHR_materials_variants.variants", 0); var; var = var->sibling)
|
||||||
|
gltf.variations++;
|
||||||
|
|
||||||
JSON_FlagAsUsed(scene, "name");
|
JSON_FlagAsUsed(scene, "name");
|
||||||
GLTF_FlagExtras(scene);
|
GLTF_FlagExtras(scene);
|
||||||
for (j = 0; ; j++)
|
for (j = 0; ; j++)
|
||||||
|
@ -3469,6 +3531,16 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize,
|
||||||
surf->csurface.flags = 0;
|
surf->csurface.flags = 0;
|
||||||
surf->geomset = ~0; //invalid set = always visible. FIXME: set this according to scene numbers?
|
surf->geomset = ~0; //invalid set = always visible. FIXME: set this according to scene numbers?
|
||||||
surf->geomid = 0;
|
surf->geomid = 0;
|
||||||
|
|
||||||
|
#ifndef SERVERONLY
|
||||||
|
if (surf->numskins>1)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Q_snprintf(surf->ofsskins[0].name, sizeof(surf->ofsskins[0].name), "Default");
|
||||||
|
for (i = 1; i < surf->numskins; i++)
|
||||||
|
JSON_GetString(JSON_FindIndexedChild(gltf.r, "extensions.KHR_materials_variants.variants", i-1), "name", surf->ofsskins[i].name, sizeof(surf->ofsskins[i].name), surf->ofsskins[i].name);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorScale(mod->mins, mod_gltf_scale->value, mod->mins);
|
VectorScale(mod->mins, mod_gltf_scale->value, mod->mins);
|
||||||
|
|
Loading…
Reference in a new issue