Parse gltf2's KHR_materials_transmission and KHR_materials_volume extensions, so eukara can figure out the glsl for it.

This commit is contained in:
Shpoike 2024-12-28 12:11:24 +00:00
parent 249ff8777b
commit 59c0c8857a
8 changed files with 159 additions and 26 deletions

View file

@ -388,6 +388,8 @@ typedef struct texnums_s {
texid_t reflectmask; //2d, defines how reflective it is (for cubemap reflections)
texid_t displacement; //2d, alternative to bump.a, eg R16[F] for offsetmapping or tessellation
texid_t occlusion; //2d, occlusion map... only red is used.
texid_t transmission; //2d, multiplier for transmissionfactor... only red is used.
texid_t thickness; //2d, multiplier for thicknessfactor... only green is used.
//the material's pushconstants. vulkan guarentees only 128 bytes. so 8 vec4s. note that lmscales should want 4 of them...
/*struct

View file

@ -1307,6 +1307,18 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass)
else
t = r_whiteimage;
break;
case T_GEN_TRANSMISSION:
if (shaderstate.curtexnums && TEXLOADED(shaderstate.curtexnums->transmission))
t = shaderstate.curtexnums->transmission;
else
t = r_whiteimage;
break;
case T_GEN_THICKNESS:
if (shaderstate.curtexnums && TEXLOADED(shaderstate.curtexnums->thickness))
t = shaderstate.curtexnums->thickness;
else
t = r_whiteimage;
break;
case T_GEN_SHADOWMAP:
t = shaderstate.curshadowmap;
break;

View file

@ -1415,6 +1415,8 @@ const struct sh_defaultsamplers_s sh_defaultsamplers[] =
{"s_reflectmask", 1u<<S_REFLECTMASK},
{"s_displacement", 1u<<S_DISPLACEMENT},
{"s_occlusion", 1u<<S_OCCLUSION},
{"s_transmission", 1u<<S_TRANSMISSION},
{"s_thickness", 1u<<S_THICKNESS},
{"s_lightmap", 1u<<S_LIGHTMAP0},
{"s_deluxemap", 1u<<S_DELUXEMAP0},
#if MAXRLIGHTMAPS > 1
@ -2627,7 +2629,7 @@ static void Shader_ReflectCube(parsestate_t *ps, const char **ptr)
static void Shader_ReflectMask(parsestate_t *ps, const char **ptr)
{
char *token = Shader_ParseSensString(ptr);
unsigned int flags = Shader_SetImageFlags (ps, ps->pass, &token, 0);
unsigned int flags = Shader_SetImageFlags (ps, ps->pass, &token, IF_NOSRGB);
ps->s->defaulttextures->reflectmask = Shader_FindImage(ps, token, flags);
}
@ -2675,6 +2677,18 @@ static void Shader_DisplacementMap(parsestate_t *ps, const char **ptr)
unsigned int flags = Shader_SetImageFlags (ps, ps->pass, &token, IF_NOSRGB);
ps->s->defaulttextures->displacement = Shader_FindImage(ps, token, flags);
}
static void Shader_TransmissionMap(parsestate_t *ps, const char **ptr)
{
char *token = Shader_ParseSensString(ptr);
unsigned int flags = Shader_SetImageFlags (ps, ps->pass, &token, IF_NOSRGB);
ps->s->defaulttextures->transmission = Shader_FindImage(ps, token, flags);
}
static void Shader_ThicknessMap(parsestate_t *ps, const char **ptr)
{
char *token = Shader_ParseSensString(ptr);
unsigned int flags = Shader_SetImageFlags (ps, ps->pass, &token, IF_NOSRGB);
ps->s->defaulttextures->thickness = Shader_FindImage(ps, token, flags);
}
static void Shaderpass_QF_Material(parsestate_t *ps, const char **ptr)
{ //qf_material BASETEXTURE NORMALMAP SPECULARMAP
@ -2835,6 +2849,23 @@ static void Shader_FactorEmit(parsestate_t *ps, const char **ptr)
shader->factors[MATERIAL_FACTOR_EMIT][2] = Shader_ParseFloat(shader, ptr, 1);
shader->factors[MATERIAL_FACTOR_EMIT][3] = Shader_ParseFloat(shader, ptr, 1);
}
static void Shader_FactorTransmission(parsestate_t *ps, const char **ptr)
{
shader_t *shader = ps->s;
shader->factors[MATERIAL_FACTOR_TRANSMISSION][0] = Shader_ParseFloat(shader, ptr, 1);
// shader->factors[MATERIAL_FACTOR_TRANSMISSION][1] = the volume distance;
shader->factors[MATERIAL_FACTOR_TRANSMISSION][2] = 0;
shader->factors[MATERIAL_FACTOR_TRANSMISSION][3] = 0;
}
static void Shader_FactorVolume(parsestate_t *ps, const char **ptr)
{
shader_t *shader = ps->s;
shader->factors[MATERIAL_FACTOR_VOLUME][0] = Shader_ParseFloat(shader, ptr, 1); //r
shader->factors[MATERIAL_FACTOR_VOLUME][1] = Shader_ParseFloat(shader, ptr, 1); //g
shader->factors[MATERIAL_FACTOR_VOLUME][2] = Shader_ParseFloat(shader, ptr, 1); //b
shader->factors[MATERIAL_FACTOR_VOLUME][3] = Shader_ParseFloat(shader, ptr, 1); //factor
shader->factors[MATERIAL_FACTOR_TRANSMISSION][1] = Shader_ParseFloat(shader, ptr, 1); //distance
}
static void Shader_BEMode(parsestate_t *ps, const char **ptr)
{
@ -2965,11 +2996,15 @@ static shaderkey_t shaderkeys[] =
{"lowermap", Shader_LowerMap, "fte"},
{"reflectmask", Shader_ReflectMask, "fte"},
{"displacementmap", Shader_DisplacementMap, "fte"},
{"transmissionmap", Shader_TransmissionMap, "fte"},
{"thicknessmap", Shader_ThicknessMap, "fte"},
{"portalfboscale", Shader_PortalFBOScale, "fte"}, //portal/mirror/refraction/reflection FBOs are resized by this scale
{"basefactor", Shader_FactorBase, "fte"}, //material scalers for glsl
{"specularfactor", Shader_FactorSpec, "fte"}, //material scalers for glsl
{"fullbrightfactor", Shader_FactorEmit, "fte"}, //material scalers for glsl
{"fte_transmissionfactor",Shader_FactorTransmission,"fte"}, //material scalers for glsl
{"fte_volumefactor", Shader_FactorVolume, "fte"}, //material scalers for glsl
//TODO: PBR textures...
// {"albedomap", Shader_DiffuseMap, "fte"}, //rgb(a)
@ -4775,16 +4810,18 @@ static void Shader_FixupProgPasses(parsestate_t *ps, shaderpass_t *pass)
{T_GEN_REFLECTMASK, 0}, //10
{T_GEN_DISPLACEMENT, SHADER_HASDISPLACEMENT},//11
{T_GEN_OCCLUSION, 0}, //12
{T_GEN_TRANSMISSION, 0}, //13
{T_GEN_THICKNESS, 0}, //14
// {T_GEN_REFLECTION, SHADER_HASREFLECT}, //
// {T_GEN_REFRACTION, SHADER_HASREFRACT}, //
// {T_GEN_REFRACTIONDEPTH, SHADER_HASREFRACTDEPTH},//
// {T_GEN_RIPPLEMAP, SHADER_HASRIPPLEMAP}, //
//batch
{T_GEN_LIGHTMAP, SHADER_HASLIGHTMAP}, //13
{T_GEN_DELUXMAP, 0}, //14
//more lightmaps //15,16,17
//mode deluxemaps //18,19,20
{T_GEN_LIGHTMAP, SHADER_HASLIGHTMAP}, //15
{T_GEN_DELUXMAP, 0}, //16
//more lightmaps //17,18,19
//mode deluxemaps //20,21,22
};
#ifdef HAVE_MEDIA_DECODER
@ -5976,16 +6013,18 @@ done:;
{T_GEN_REFLECTMASK, 0}, //10
{T_GEN_DISPLACEMENT, SHADER_HASDISPLACEMENT},//11
{T_GEN_OCCLUSION, 0}, //12
{T_GEN_TRANSMISSION, 0}, //13
{T_GEN_THICKNESS, 0}, //14
// {T_GEN_REFLECTION, SHADER_HASREFLECT}, //
// {T_GEN_REFRACTION, SHADER_HASREFRACT}, //
// {T_GEN_REFRACTIONDEPTH, SHADER_HASREFRACTDEPTH},//
// {T_GEN_RIPPLEMAP, SHADER_HASRIPPLEMAP}, //
//batch
{T_GEN_LIGHTMAP, SHADER_HASLIGHTMAP}, //13
{T_GEN_DELUXMAP, 0}, //14
//more lightmaps //15,16,17
//mode deluxemaps //18,19,20
{T_GEN_LIGHTMAP, SHADER_HASLIGHTMAP}, //15
{T_GEN_DELUXMAP, 0}, //16
//more lightmaps //17,18,19
//mode deluxemaps //20,21,22
};
#ifdef HAVE_MEDIA_DECODER
@ -8086,6 +8125,8 @@ static char *Shader_DecomposeSubPass(char *o, shader_t *s, shaderpass_t *p, qboo
case T_GEN_REFLECTMASK: Shader_DecomposeSubPassMap(o, s, "map $reflectmask", s->defaulttextures[0].reflectmask); break;
case T_GEN_DISPLACEMENT: Shader_DecomposeSubPassMap(o, s, "map $displacement", s->defaulttextures[0].displacement); break;
case T_GEN_OCCLUSION: Shader_DecomposeSubPassMap(o, s, "map $occlusion", s->defaulttextures[0].occlusion); break;
case T_GEN_TRANSMISSION: Shader_DecomposeSubPassMap(o, s, "map $transmission", s->defaulttextures[0].transmission); break;
case T_GEN_THICKNESS: Shader_DecomposeSubPassMap(o, s, "map $thickness", s->defaulttextures[0].thickness); break;
case T_GEN_CURRENTRENDER: sprintf(o, "map $currentrender "); break;
case T_GEN_SOURCECOLOUR: sprintf(o, "map $sourcecolour"); break;
case T_GEN_SOURCEDEPTH: sprintf(o, "map $sourcedepth"); break;

View file

@ -1491,14 +1491,24 @@ static const char *glsl_hdrs[] =
#endif
#endif
"#if defined(ORM) || defined(SG)\n"
"uniform vec4 factors[3];\n"
"uniform vec4 factors[5];\n"
"#define factor_base factors[0]\n"
"#define factor_spec factors[1]\n"
"#define factor_emit factors[2]\n"
"#define factor_transmission factors[3].r\n"
"#define factor_volume_distance factors[3].g\n"
// "#define factor_? factors[3].b\n"
// "#define factor_? factors[3].a\n"
"#define factor_volume_rgb factors[4].rgb\n"
"#define factor_volume_thickness factors[4].a\n"
"#else\n"
"#define factor_base vec4(1.0)\n"
"#define factor_spec vec4(1.0)\n"
"#define factor_emit vec4(1.0)\n"
/*"#define factor_transmission 0.0\n"
"#define factor_volume_distance 0.0\n"
"#define factor_volume_rgb vec3(1.0)\n"
"#define factor_volume_thickness 0.0\n"*/
"#endif\n"
"#ifdef USEUBOS\n"
"layout(std140) uniform u_lightinfo\n"

View file

@ -274,6 +274,8 @@ typedef struct shaderpass_s {
T_GEN_REFLECTMASK, //dpreflectcube mask
T_GEN_DISPLACEMENT, //displacement texture (probably half-float or something so higher precision than normalmap.a)
T_GEN_OCCLUSION, //occlusion mask (instead of baking it into the texture itself, required for correct pbr)
T_GEN_TRANSMISSION, //.r fancy opacity mask (still contributes its own colour over the top, for KHR_materials_transmission)
T_GEN_THICKNESS, //.g depth mask (could be replaced with raytracing, for KHR_materials_volume)
T_GEN_CURRENTRENDER,//copy the current screen to a texture, and draw that
@ -698,7 +700,9 @@ struct shader_s
#define MATERIAL_FACTOR_BASE 0
#define MATERIAL_FACTOR_SPEC 1
#define MATERIAL_FACTOR_EMIT 2
#define MATERIAL_FACTOR_COUNT 3
#define MATERIAL_FACTOR_TRANSMISSION 3
#define MATERIAL_FACTOR_VOLUME 4
#define MATERIAL_FACTOR_COUNT 5
vec4_t factors[MATERIAL_FACTOR_COUNT];
//arranged as a series of vec4s
@ -877,15 +881,17 @@ enum
S_REFLECTMASK = 10,
S_DISPLACEMENT = 11,
S_OCCLUSION = 12,
S_LIGHTMAP0 = 13,
S_DELUXEMAP0 = 14,
S_TRANSMISSION = 13,
S_THICKNESS = 14,
S_LIGHTMAP0 = 15,
S_DELUXEMAP0 = 16,
#if MAXRLIGHTMAPS > 1
S_LIGHTMAP1 = 15,
S_LIGHTMAP2 = 16,
S_LIGHTMAP3 = 17,
S_DELUXEMAP1 = 18,
S_DELUXEMAP2 = 19,
S_DELUXEMAP3 = 20,
S_LIGHTMAP1 = 17,
S_LIGHTMAP2 = 18,
S_LIGHTMAP3 = 19,
S_DELUXEMAP1 = 20,
S_DELUXEMAP2 = 21,
S_DELUXEMAP3 = 22,
#endif
};
extern const struct sh_defaultsamplers_s

View file

@ -14,6 +14,8 @@
!!samps !EIGHTBIT diffuse normalmap specular fullbright upper lower reflectmask reflectcube
!!samps =EIGHTBIT paletted 1
!!samps =OCCLUDE occlusion
!!samps =USE_TRANSMISSION transmission //only .r valid, multiplier for factor_transmission
!!samps =USE_VOLUME thickness //only .g valid, multiplier for factor_volume_thickness, combined with factor_volume_rgb+factor_volume_distance(average distance travelled in metres)
//!!permu VC // adds rgba vertex colour multipliers
//!!permu SPECULAR // auto-added when gl_specular>0
//!!permu OFFSETMAPPING // auto-added when r_glsl_offsetmapping is set

View file

@ -1588,10 +1588,14 @@ static texid_t SelectPassTexture(const shaderpass_t *pass)
return r_blackcubeimage; //FIXME
case T_GEN_REFLECTMASK:
return shaderstate.curtexnums->reflectmask;
case T_GEN_OCCLUSION:
return shaderstate.curtexnums->occlusion;
case T_GEN_DISPLACEMENT:
return shaderstate.curtexnums->displacement;
case T_GEN_OCCLUSION:
return shaderstate.curtexnums->occlusion;
case T_GEN_TRANSMISSION:
return shaderstate.curtexnums->transmission;
case T_GEN_THICKNESS:
return shaderstate.curtexnums->thickness;
case T_GEN_ANIMMAP:
return pass->anim_frames[(int)(pass->anim_fps * shaderstate.curtime) % pass->anim_numframes];
@ -3172,6 +3176,10 @@ static qboolean BE_SetupMeshProgram(program_t *p, shaderpass_t *pass, unsigned i
BE_SetupTextureDescriptor(shaderstate.curtexnums->displacement, r_whiteimage, set, descs, desc++, img++);
if (p->defaulttextures & (1u<<S_OCCLUSION))
BE_SetupTextureDescriptor(shaderstate.curtexnums->occlusion, r_whiteimage, set, descs, desc++, img++);
if (p->defaulttextures & (1u<<S_TRANSMISSION))
BE_SetupTextureDescriptor(shaderstate.curtexnums->transmission, r_whiteimage, set, descs, desc++, img++);
if (p->defaulttextures & (1u<<S_THICKNESS))
BE_SetupTextureDescriptor(shaderstate.curtexnums->thickness, r_whiteimage, set, descs, desc++, img++);
//batch
if (p->defaulttextures & (1u<<S_LIGHTMAP0))

View file

@ -1533,6 +1533,7 @@ static void GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, galiasskin_t *re
const char *t;
json_t *nam, *unlit, *pbrsg, *pbrmr, *blinn;
json_t *transmission, *volume;
nam = JSON_FindChild(mat, "name");
unlit = JSON_FindChild(mat, "extensions.KHR_materials_unlit");
@ -1540,6 +1541,22 @@ static void GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, galiasskin_t *re
pbrmr = JSON_FindChild(mat, "pbrMetallicRoughness");
blinn = JSON_FindChild(mat, "extensions.KHR_materials_cmnBlinnPhong");
transmission = JSON_FindChild(mat, "extensions.KHR_materials_transmission");
volume = JSON_FindChild(mat, "extensions.KHR_materials_volume");
if (volume && !transmission)
{
if (gltf->warnlimit --> 0)
Con_Printf(CON_WARNING"%s: KHR_materials_volume without KHR_materials_transmission\n", gltf->mod->name);
volume = NULL;
}
if (transmission && (unlit || pbrsg || blinn) && !pbrmr)
{
if (gltf->warnlimit --> 0)
Con_Printf(CON_WARNING"%s: KHR_materials_transmission without pbrMetallicRoughness\n", gltf->mod->name);
transmission = volume = NULL;
}
doubleSided = JSON_GetInteger(mat, "doubleSided", false);
alphaCutoff = JSON_GetFloat(mat, "alphaCutoff", 0.5);
t = JSON_GetString(mat, "alphaMode", tmp, sizeof(tmp), "OPAQUE");
@ -1757,10 +1774,30 @@ static void GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, galiasskin_t *re
else //else depend upon specularfactor
ret->frame->texnums.specular = modfuncs->GetTexture("$whiteimage", NULL, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA, NULL, NULL, 0, 0, TF_INVALID);
if (transmission)
{
n = JSON_FindChild(transmission, "transmissionTexture.index"); //.r = factor
if (n)
ret->frame->texnums.transmission = GLTF_LoadTexture(gltf, n, IF_NOSRGB);
else
ret->frame->texnums.transmission = modfuncs->GetTexture("$whiteimage", NULL, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA, NULL, NULL, 0, 0, TF_INVALID);
if (volume)
{
n = JSON_FindChild(volume, "thicknessTexture.index"); //.g = thicknessFactor
if (n)
ret->frame->texnums.transmission = GLTF_LoadTexture(gltf, n, IF_NOSRGB);
else
ret->frame->texnums.transmission = modfuncs->GetTexture("$whiteimage", NULL, IF_NOMIPMAP|IF_NOPICMIP|IF_NEAREST|IF_NOGAMMA, NULL, NULL, 0, 0, TF_INVALID);
}
}
#ifndef INFINITY //C99.
#define INFINITY (1.0/0.0)
#endif
Q_snprintf(shader, sizeof(shader),
"{\n"
"%s"//cull
"program defaultskin" "#ORM" "#VC" "#IOR=%.02f" "%s"/*occlude*/ "%s"/*alphatest*/ "\n"
"program defaultskin" "#ORM" "#VC" "#IOR=%.02f" "%s"/*occlude*/ "%s"/*transmission*/ "%s"/*volume*/ "%s"/*alphatest*/ "\n"
"{\n"
"map $diffuse\n"
"%s" //blend
@ -1769,11 +1806,16 @@ static void GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, galiasskin_t *re
"fte_basefactor %f %f %f %f\n"
"fte_specularfactor %f %f %f 1.0\n"
"fte_fullbrightfactor %f %f %f 1.0\n"
"fte_transmissionfactor %f\n"
"fte_volumefactor %f %f %f %f %f\n"
"bemode rtlight rtlight_orm\n"
"}\n",
doubleSided?"cull disable\n":"",
ior,
(!occ)?"#NOOCCLUDE":(strcmp(occname,mrtname)?"#OCCLUDE":""),
(transmission?"#USE_TRANSMISSION":""),
(volume?"#USE_VOLUME":""),
alphaCutoffmodifier,
(alphaMode==1)?"":(alphaMode==2)?"blendfunc blend\n":"",
vertexcolours?"rgbgen vertex\nalphagen vertex\n":"",
@ -1786,7 +1828,13 @@ static void GLTF_LoadMaterial(gltf_t *gltf, json_t *materialid, galiasskin_t *re
JSON_GetFloat(pbrmr, "roughnessFactor", 1),
JSON_GetFloat(mat, "emissiveFactor.0", 0),
JSON_GetFloat(mat, "emissiveFactor.1", 0),
JSON_GetFloat(mat, "emissiveFactor.2", 0)
JSON_GetFloat(mat, "emissiveFactor.2", 0),
JSON_GetFloat(transmission, "transmissionFactor", 0),
JSON_GetFloat(volume, "attenuationColor.0", 1),
JSON_GetFloat(volume, "attenuationColor.1", 1),
JSON_GetFloat(volume, "attenuationColor.2", 1),
JSON_GetFloat(volume, "thicknessFactor", 0),
JSON_GetFloat(volume, "attenuationDistance", INFINITY)
);
}
if (!ret->frame->texnums.bump)
@ -2970,14 +3018,18 @@ static qboolean GLTF_LoadModel(struct model_s *mod, char *json, size_t jsonsize,
{"KHR_materials_variants", true, false},
{"KHR_materials_ior", true, false},
{"KHR_materials_transmission", true, true}, //FIXME: requires glsl tweaks.
{"KHR_materials_volume", true, true}, //FOXME: requires glsl tweaks.
#ifdef HAVE_DRACO
{"KHR_draco_mesh_compression", true, false}, //probably fatal
#else
{"KHR_draco_mesh_compression", false, false}, //probably fatal
#endif
{"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.
{"KHR_texture_transform", false, true}, //requires glsl tweaks, per texmap. can't use tcmod if its only on the bumpmap etc.
{"KHR_materials_sheen", false, true}, //requires glsl tweaks, extra brdf layer in the middle for velvet.
{"KHR_materials_clearcoat", false, true}, //requires glsl tweaks, extra brdf layer over the top for varnish etc.
{NULL}
}, *extensions;
gltf_t gltf;