diff --git a/ref_vk/vk_light.c b/ref_vk/vk_light.c index df8326a2..dbf523d5 100644 --- a/ref_vk/vk_light.c +++ b/ref_vk/vk_light.c @@ -95,19 +95,6 @@ static struct { } g_lights_bsp = {0}; -static int lookupTextureF( 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_FindTexture(buffer); - gEngine.Con_Reportf("Looked up texture %s -> %d\n", buffer, tex_id); - return tex_id; -} - static void loadRadData( const model_t *map, const char *fmt, ... ) { fs_offset_t size; char *data; @@ -183,19 +170,21 @@ static void loadRadData( const model_t *map, const char *fmt, ... ) { texture_name += 1; } + // FIXME replace this with findTexturesNamedLike from vk_materials.c + // Try bsp texture first - tex_id = lookupTextureF("#%s:%s.mip", map->name, texture_name); + tex_id = XVK_TextureLookupF("#%s:%s.mip", map->name, texture_name); // Try wad texture if bsp is not there if (!tex_id && wad_name) { - tex_id = lookupTextureF("%s.wad/%s.mip", wad_name, texture_name); + tex_id = XVK_TextureLookupF("%s.wad/%s.mip", wad_name, texture_name); } if (!tex_id) { const char *wad = g_map_entities.wadlist; for (; *wad;) { const char *const wad_end = Q_strchr(wad, ';'); - tex_id = lookupTextureF("%.*s/%s.mip", wad_end - wad, wad, texture_name); + tex_id = XVK_TextureLookupF("%.*s/%s.mip", wad_end - wad, wad, texture_name); if (tex_id) break; wad = wad_end + 1; diff --git a/ref_vk/vk_materials.c b/ref_vk/vk_materials.c index 43678f63..556badb3 100644 --- a/ref_vk/vk_materials.c +++ b/ref_vk/vk_materials.c @@ -1,25 +1,146 @@ #include "vk_materials.h" #include "vk_textures.h" +#include "vk_mapents.h" #include "vk_const.h" static struct { xvk_material_t materials[MAX_TEXTURES]; } g_materials; +static int findTextureNamedLike( const char *texture_name ) { + const model_t *map = gEngine.pfnGetModelByIndex( 1 ); + string texname; + int tex_id; + + // Try bsp texture first + tex_id = XVK_TextureLookupF("#%s:%s.mip", map->name, texture_name); + + if (!tex_id) { + const char *wad = g_map_entities.wadlist; + for (; *wad;) { + const char *const wad_end = Q_strchr(wad, ';'); + tex_id = XVK_TextureLookupF("%.*s/%s.mip", wad_end - wad, wad, texture_name); + if (tex_id) + break; + wad = wad_end + 1; + } + } + + 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); + return tex_id ? tex_id : -1; +} + +static void loadMaterialsFromFile( const char *filename ) { + fs_offset_t size; + const char *const path_begin = filename; + const char *path_end = Q_strrchr(filename, '/'); + byte *data = gEngine.COM_LoadFile( filename, 0, false ); + char *pos = data; + xvk_material_t current_material = { + .base_color = -1, + .metalness = tglob.blackTexture, + .roughness = tglob.whiteTexture, + .normalmap = tglob.grayTexture, + }; + int current_material_index = -1; + + if ( !data ) + return; + + if ( !path_end ) + path_end = path_begin; + else + path_end++; + + for (;;) { + char key[1024]; + char value[1024]; + + pos = COM_ParseFile(pos, key, sizeof(key)); + ASSERT(Q_strlen(key) < sizeof(key)); + if (!pos) + break; + + if (key[0] == '{') { + current_material = (xvk_material_t){ + .base_color = -1, + .metalness = tglob.blackTexture, + .roughness = tglob.whiteTexture, + .normalmap = tglob.grayTexture, + }; + continue; + } + + if (key[0] == '}') { + if (current_material_index >= 0 && current_material.base_color >= 0) { + g_materials.materials[current_material_index] = current_material; + } + continue; + } + + pos = COM_ParseFile(pos, value, sizeof(value)); + if (!pos) + break; + + 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 = tglob.grayTexture; + } + } 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); + } + } + + Mem_Free( data ); +} + void XVK_ReloadMaterials( void ) { for (int i = 0; i < MAX_TEXTURES; ++i) { xvk_material_t *const mat = g_materials.materials + i; const vk_texture_t *const tex = findTexture( i ); - if (tex) { - mat->base_color = i; - mat->metalness = tglob.blackTexture; - mat->roughness = tglob.whiteTexture; - mat->normalmap = tglob.blackTexture; - } else { + if (!tex) { mat->base_color = -1; + continue; } + + mat->base_color = i; + mat->metalness = tglob.blackTexture; + mat->roughness = tglob.whiteTexture; + mat->normalmap = tglob.grayTexture; } + + loadMaterialsFromFile( "pbr/materials.mat" ); + // TODO map-specific } xvk_material_t* XVK_GetMaterialForTextureIndex( int tex_index ) { diff --git a/ref_vk/vk_scene.c b/ref_vk/vk_scene.c index 3fc09598..714d75b6 100644 --- a/ref_vk/vk_scene.c +++ b/ref_vk/vk_scene.c @@ -108,11 +108,8 @@ void R_NewMap( void ) VK_LightsNewMap(); - if (vk_core.rtx) { + if (vk_core.rtx) VK_RayNewMap(); - XVK_ReloadMaterials(); - } - // RTX map loading requires command buffer for building blases if (vk_core.rtx) @@ -146,6 +143,7 @@ void R_NewMap( void ) // After we've loaded map brush model, we can proceed with loading static surface lights VK_LightsLoadMapStaticLights(); + XVK_ReloadMaterials(); // requires wadlist from entities, which are parsed in lights loading routine .... if (vk_core.rtx) { diff --git a/ref_vk/vk_textures.c b/ref_vk/vk_textures.c index f741fc2e..8086f7e6 100644 --- a/ref_vk/vk_textures.c +++ b/ref_vk/vk_textures.c @@ -878,3 +878,16 @@ void VK_ImageDestroy(vk_image_t *img) { freeDeviceMemory(&img->devmem); *img = (vk_image_t){0}; } + +int XVK_TextureLookupF( 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_FindTexture(buffer); + gEngine.Con_Reportf("Looked up texture %s -> %d\n", buffer, tex_id); + return tex_id; +} diff --git a/ref_vk/vk_textures.h b/ref_vk/vk_textures.h index be7c45f5..21987b82 100644 --- a/ref_vk/vk_textures.h +++ b/ref_vk/vk_textures.h @@ -63,6 +63,8 @@ int VK_CreateTextureArray( const char *name, int width, int height, int depth, void VK_FreeTexture( unsigned int texnum ); int VK_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ); +int XVK_TextureLookupF( const char *fmt, ...); + #define VK_LoadTextureInternal( name, pic, flags ) VK_LoadTextureFromBuffer( name, pic, flags, false ) typedef struct {