mat: load materials from multiple sources; abs paths

- look for materials in:
  - pbr/materials.mat
  - pbr/models/materials.mat
  - pbr/wadname.wad/materials.mat
  - pbr/maps/mapname.bsp/materials.mat

- all paths are relative to their materials.mat, except for ones that begin with '/', which are relative to `pbr` dir

pbr dir should be placed in modname dir, e.g. 'valve'

#155
This commit is contained in:
Ivan 'provod' Avdeev 2021-11-25 13:51:39 -08:00
parent 405a9ecbb4
commit 1624f4620a
1 changed files with 62 additions and 31 deletions

View File

@ -33,17 +33,10 @@ static int findTextureNamedLike( const char *texture_name ) {
return tex_id ? tex_id : -1;
}
static int loadTextureF( const char *fmt, ... ) {
int tex_id = 0;
char buffer[1024];
va_list argptr;
va_start( argptr, fmt );
vsnprintf( buffer, sizeof buffer, fmt, argptr );
va_end( argptr );
tex_id = VK_LoadTexture( buffer, NULL, 0, 0);
gEngine.Con_Reportf("Loading texture %s => %d\n", buffer, tex_id);
static int loadTexture( const char *filename ) {
const int tex_id = VK_LoadTexture( filename, NULL, 0, 0);
gEngine.Con_Reportf("Loading texture %s => %d\n", filename, tex_id);
return tex_id ? tex_id : -1;
}
@ -61,6 +54,8 @@ static void loadMaterialsFromFile( const char *filename ) {
};
int current_material_index = -1;
gEngine.Con_Reportf("Loading materials from %s\n", filename);
if ( !data )
return;
@ -104,33 +99,55 @@ static void loadMaterialsFromFile( const char *filename ) {
if (Q_stricmp(key, "for") == 0) {
current_material_index = findTextureNamedLike(value);
} else if (Q_stricmp(key, "basecolor_map") == 0) {
if ((current_material.base_color = loadTextureF("%.*s%s", path_end - path_begin, path_begin, value)) < 0) {
gEngine.Con_Printf(S_ERROR "Failed to load basecolor_map texture %s\n", value);
}
} else if (Q_stricmp(key, "normal_map") == 0) {
if ((current_material.normalmap = loadTextureF("%.*s%s", path_end - path_begin, path_begin, value)) < 0) {
gEngine.Con_Printf(S_ERROR "Failed to load normal_map texture %s\n", value);
current_material.normalmap = 0;
}
} else if (Q_stricmp(key, "metal_map") == 0) {
if ((current_material.metalness = loadTextureF("%.*s%s", path_end - path_begin, path_begin, value)) < 0) {
gEngine.Con_Printf(S_ERROR "Failed to load metal_map texture %s\n", value);
current_material.metalness = tglob.blackTexture;
}
} else if (Q_stricmp(key, "roughness_map") == 0) {
if ((current_material.roughness = loadTextureF("%.*s%s", path_end - path_begin, path_begin, value)) < 0) {
gEngine.Con_Printf(S_ERROR "Failed to load roughness_map texture %s\n", value);
current_material.roughness = tglob.whiteTexture;
}
} else {
gEngine.Con_Printf(S_ERROR "Unknown material key %s\n", key);
char texture_path[256];
int *tex_id_dest;
int tex_id = loadTexture(texture_path);
if (Q_stricmp(key, "basecolor_map") == 0) {
tex_id_dest = &current_material.base_color;
} else if (Q_stricmp(key, "normal_map") == 0) {
tex_id_dest = &current_material.normalmap;
} else if (Q_stricmp(key, "metal_map") == 0) {
tex_id_dest = &current_material.metalness;
} else if (Q_stricmp(key, "roughness_map") == 0) {
tex_id_dest = &current_material.roughness;
} else {
gEngine.Con_Printf(S_ERROR "Unknown material key %s\n", key);
continue;
}
if (value[0] == '/') {
// Path relative to valve/pbr dir
Q_snprintf(texture_path, sizeof(texture_path), "pbr%s", value);
} else {
// Path relative to current material.mat file
Q_snprintf(texture_path, sizeof(texture_path), "%.*s%s", path_end - path_begin, path_begin, value);
}
tex_id = loadTexture(texture_path);
if (tex_id < 0) {
gEngine.Con_Printf(S_ERROR "Failed to load texture \"%s\" for key \"%s\"\n", value, key);
continue;
}
*tex_id_dest = tex_id;
}
}
Mem_Free( data );
}
static void loadMaterialsFromFileF( const char *fmt, ... ) {
char buffer[256];
va_list argptr;
va_start( argptr, fmt );
vsnprintf( buffer, sizeof buffer, fmt, argptr );
va_end( argptr );
loadMaterialsFromFile( buffer );
}
void XVK_ReloadMaterials( void ) {
for (int i = 0; i < MAX_TEXTURES; ++i) {
xvk_material_t *const mat = g_materials.materials + i;
@ -149,7 +166,21 @@ void XVK_ReloadMaterials( void ) {
}
loadMaterialsFromFile( "pbr/materials.mat" );
// TODO map-specific
loadMaterialsFromFile( "pbr/models/materials.mat" );
{
const char *wad = g_map_entities.wadlist;
for (; *wad;) {
const char *const wad_end = Q_strchr(wad, ';');
loadMaterialsFromFileF("pbr/%.*s/materials.mat", wad_end - wad, wad);
wad = wad_end + 1;
}
}
{
const model_t *map = gEngine.pfnGetModelByIndex( 1 );
loadMaterialsFromFileF("pbr/%s/materials.mat", map->name);
}
}
xvk_material_t* XVK_GetMaterialForTextureIndex( int tex_index ) {