diff --git a/inc/common/files.h b/inc/common/files.h index 26a92027a..3a351ee51 100644 --- a/inc/common/files.h +++ b/inc/common/files.h @@ -87,6 +87,8 @@ typedef struct file_info_s { #define FS_Mallocz(size) Z_TagMallocz(size, TAG_FILESYSTEM) #define FS_CopyString(string) Z_TagCopyString(string, TAG_FILESYSTEM) #define FS_LoadFile(path, buf) FS_LoadFileEx(path, buf, 0, TAG_FILESYSTEM) +#define FS_LoadFileFlags(path, buf, flags) \ + FS_LoadFileEx(path, buf, (flags), TAG_FILESYSTEM) #define FS_FreeFile(buf) Z_Free(buf) // just regular malloc for now diff --git a/inc/refresh/refresh.h b/inc/refresh/refresh.h index 7dcb3c790..744de5ea0 100644 --- a/inc/refresh/refresh.h +++ b/inc/refresh/refresh.h @@ -202,7 +202,12 @@ typedef enum { IF_REPEAT = (1 << 6), IF_NEAREST = (1 << 7), IF_OPAQUE = (1 << 8), - IF_SRGB = (1 << 9) + IF_SRGB = (1 << 9), + + // Image source indicator/requirement flags + IF_SRC_BASE = (0x1 << 16), + IF_SRC_GAME = (0x2 << 16), + IF_SRC_MASK = (0x3 << 16), } imageflags_t; typedef enum { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8aff22993..c7b7761fc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -489,15 +489,15 @@ TARGET_INCLUDE_DIRECTORIES(server PRIVATE "${ZLIB_INCLUDE_DIRS}") # Use dynamic zlib for steam runtime if (CONFIG_LINUX_STEAM_RUNTIME_SUPPORT) TARGET_LINK_LIBRARIES(client SDL2main SDL2-static z) - TARGET_LINK_LIBRARIES(server SDL2main SDL2-static z) + TARGET_LINK_LIBRARIES(server z) else() TARGET_LINK_LIBRARIES(client SDL2main SDL2-static zlibstatic) - TARGET_LINK_LIBRARIES(server SDL2main SDL2-static zlibstatic) + TARGET_LINK_LIBRARIES(server zlibstatic) endif() SET_TARGET_PROPERTIES(client PROPERTIES - OUTPUT_NAME "q2rtx" + OUTPUT_NAME "q2rtx${BINARY_POSTFIX}" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}" RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_SOURCE_DIR}" RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_SOURCE_DIR}" @@ -508,7 +508,7 @@ SET_TARGET_PROPERTIES(client SET_TARGET_PROPERTIES(server PROPERTIES - OUTPUT_NAME "q2rtxded" + OUTPUT_NAME "q2rtxded${BINARY_POSTFIX}" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}" RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_SOURCE_DIR}" RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_SOURCE_DIR}" @@ -543,6 +543,32 @@ IF(IS_64_BIT) ) ENDIF() +include(ProcessorCount) + +if(WIN32 AND IS_64_BIT) + set(X86_BUILD_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/build_x86") + file(MAKE_DIRECTORY "${X86_BUILD_DIRECTORY}") + set(OUTPUT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/config_x86_out.txt") + set(ERROR_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/config_x86_err.txt") + execute_process(COMMAND "${CMAKE_COMMAND}" "${CMAKE_SOURCE_DIR}" "-G" "${CMAKE_GENERATOR}" "-A" "Win32" "-DBINARY_POSTFIX=_x86" + WORKING_DIRECTORY "${X86_BUILD_DIRECTORY}" + OUTPUT_FILE "${OUTPUT_FILE_NAME}" + ERROR_FILE "${ERROR_FILE_NAME}" + RESULT_VARIABLE CONFIG_RESULT) + if(NOT CONFIG_RESULT EQUAL 0) + message(WARNING "Configuring X86 dedicated server failed with exit code ${CONFIG_RESULT}") + message(STATUS " Please see ${OUTPUT_FILE_NAME} and ${ERROR_FILE_NAME} for output") + else() + ProcessorCount(N) + if(N GREATER 0) + set(PARALLEL_ARGS "-j" "${N}") + endif() + add_custom_target(server_x86 ALL + COMMAND "${CMAKE_COMMAND}" "--build" "${X86_BUILD_DIRECTORY}" "--target" "server" "--config" "$" ${PARALLEL_ARGS} + COMMENT "Build X86 dedicated server") + endif() +endif() + IF(CONFIG_LINUX_PACKAGING_SUPPORT) # Put the real game binary in /usr/share so we can have a wrapper in /usr/bin INSTALL(TARGETS client DESTINATION share/quake2rtx/bin COMPONENT shareware) diff --git a/src/client/ui/playermodels.c b/src/client/ui/playermodels.c index 301c20f01..59f6a01f7 100644 --- a/src/client/ui/playermodels.c +++ b/src/client/ui/playermodels.c @@ -36,7 +36,7 @@ static qboolean IconOfSkinExists(char *skin, char **pcxfiles, int npcxfiles) Q_strlcat(scratch, "_i.pcx", sizeof(scratch)); for (i = 0; i < npcxfiles; i++) { - if (strcmp(pcxfiles[i], scratch) == 0) + if (stricmp(pcxfiles[i], scratch) == 0) return qtrue; } diff --git a/src/common/bsp.c b/src/common/bsp.c index a33b69c95..6b52798a8 100644 --- a/src/common/bsp.c +++ b/src/common/bsp.c @@ -1188,11 +1188,7 @@ qerror_t BSP_Load(const char *name, bsp_t **bsp_p) if (!BSP_LoadPatchedPVS(bsp)) { - if (dedicated->integer) - Com_WPrintf("WARNING: Pathced PVS file for %s unavailable. Some entities may disappear.\n" - "Load the map with the RTX renderer once to generate the patched PVS file.\n", bsp->name); - else - BSP_BuildPvsMatrix(bsp); + BSP_BuildPvsMatrix(bsp); } else { diff --git a/src/common/files.c b/src/common/files.c index 0670bbf2c..98a9b6892 100644 --- a/src/common/files.c +++ b/src/common/files.c @@ -3690,13 +3690,15 @@ static void fs_game_changed(cvar_t *self) // otherwise, restart the filesystem CL_RestartFilesystem(qfalse); - // FIXME: if baseq2/autoexec.cfg exists DO NOT exec default.cfg and config.cfg. - // this assumes user prefers to do configuration via autoexec.cfg and doesn't - // want settings and binds messed up whenever gamedir changes after startup. - if (!FS_FileExistsEx(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_BASE)) { - Com_AddConfigFile(COM_DEFAULT_CFG, FS_PATH_GAME); - Com_AddConfigFile(COM_Q2RTX_CFG, 0); - Com_AddConfigFile(COM_CONFIG_CFG, FS_TYPE_REAL | FS_PATH_GAME); + Com_AddConfigFile(COM_DEFAULT_CFG, FS_PATH_GAME); + Com_AddConfigFile(COM_Q2RTX_CFG, 0); + Com_AddConfigFile(COM_CONFIG_CFG, FS_TYPE_REAL | FS_PATH_GAME); + + // If baseq2/autoexec.cfg exists exec it again after default.cfg and config.cfg. + // Assumes user prefers to do configuration via autoexec.cfg and hopefully + // settings and binds will be restored to their preference whenever gamedir changes after startup. + if(Q_stricmp(s, BASEGAME) && FS_FileExistsEx(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_BASE)) { + Com_AddConfigFile(COM_AUTOEXEC_CFG, FS_TYPE_REAL | FS_PATH_BASE); } // exec autoexec.cfg (must be a real file within the game directory) diff --git a/src/refresh/images.c b/src/refresh/images.c index 1e66a9fa4..a9034fd0c 100644 --- a/src/refresh/images.c +++ b/src/refresh/images.c @@ -785,14 +785,20 @@ static image_t *lookup_image(const char *name, return NULL; } -static int _try_image_format(imageformat_t fmt, image_t *image, byte **pic) +#define TRY_IMAGE_SRC_GAME 1 +#define TRY_IMAGE_SRC_BASE 0 + +static int _try_image_format(imageformat_t fmt, image_t *image, int try_src, byte **pic) { byte *data; ssize_t len; qerror_t ret; // load the file - len = FS_LoadFile(image->name, (void **)&data); + int fs_flags = 0; + if (try_src > 0) + fs_flags = try_src == TRY_IMAGE_SRC_GAME ? FS_PATH_GAME : FS_PATH_BASE; + len = FS_LoadFileFlags(image->name, (void **)&data, fs_flags); if (!data) { return len; } @@ -812,16 +818,16 @@ static int _try_image_format(imageformat_t fmt, image_t *image, byte **pic) return ret < 0 ? ret : fmt; } -static int try_image_format(imageformat_t fmt, image_t *image, byte **pic) +static int try_image_format(imageformat_t fmt, image_t *image, int try_src, byte **pic) { // replace the extension memcpy(image->name + image->baselen + 1, img_loaders[fmt].ext, 4); - return _try_image_format(fmt, image, pic); + return _try_image_format(fmt, image, try_src, pic); } // tries to load the image with a different extension -static int try_other_formats(imageformat_t orig, image_t *image, byte **pic) +static int try_other_formats(imageformat_t orig, image_t *image, int try_src, byte **pic) { imageformat_t fmt; qerror_t ret; @@ -834,7 +840,7 @@ static int try_other_formats(imageformat_t orig, image_t *image, byte **pic) continue; // don't retry twice } - ret = try_image_format(fmt, image, pic); + ret = try_image_format(fmt, image, try_src, pic); if (ret != Q_ERR_NOENT) { return ret; // found something } @@ -846,7 +852,7 @@ static int try_other_formats(imageformat_t orig, image_t *image, byte **pic) return Q_ERR_NOENT; // don't retry twice } - return try_image_format(fmt, image, pic); + return try_image_format(fmt, image, try_src, pic); } static void get_image_dimensions(imageformat_t fmt, image_t *image) @@ -957,11 +963,23 @@ load_img(const char *name, image_t *image) // load the pic from disk pic = NULL; - // first try with original extension - ret = _try_image_format(fmt, image, &pic); - if (ret == Q_ERR_NOENT) { - // retry with remaining extensions - ret = try_other_formats(fmt, image, &pic); + // Always prefer images from the game dir, even if format might be 'inferior' + for (int try_location = Q_stricmp(fs_game->string, BASEGAME) ? TRY_IMAGE_SRC_GAME : TRY_IMAGE_SRC_BASE; + try_location >= TRY_IMAGE_SRC_BASE; + try_location--) + { + int location_flag = try_location == TRY_IMAGE_SRC_GAME ? IF_SRC_GAME : IF_SRC_MASK; + if(((image->flags & IF_SRC_MASK) != 0) && ((image->flags & IF_SRC_MASK) != location_flag)) + continue; + + // first try with original extension + ret = _try_image_format(fmt, image, try_location, &pic); + if (ret == Q_ERR_NOENT) { + // retry with remaining extensions + ret = try_other_formats(fmt, image, try_location, &pic); + } + if (ret >= 0) + break; } // if we are replacing 8-bit texture with a higher resolution 32-bit @@ -1029,80 +1047,101 @@ static qerror_t find_or_load_image(const char *name, size_t len, if (!vid_rtx->integer && (type != IT_PIC)) override_textures = 0; - for (int use_override = override_textures; use_override >= 0; use_override--) - { - // fill in some basic info - if (use_override) - { - const char* last_slash = strrchr(name, '/'); - if (!last_slash) - last_slash = name; - else - last_slash += 1; - - strcpy(image->name, "overrides/"); - strcat(image->name, last_slash); - image->baselen = strlen(image->name) - 4; - } - else - { - memcpy(image->name, name, len + 1); - image->baselen = len - 4; - } - image->type = type; - image->flags = flags; - image->registration_sequence = registration_sequence; - - // find out original extension - for (fmt = 0; fmt < IM_MAX; fmt++) { - if (!Q_stricmp(image->name + image->baselen + 1, img_loaders[fmt].ext)) { - break; - } - } + // Always prefer images from the game dir, even if format might be 'inferior' + for (int try_location = Q_stricmp(fs_game->string, BASEGAME) ? TRY_IMAGE_SRC_GAME : TRY_IMAGE_SRC_BASE; + try_location >= TRY_IMAGE_SRC_BASE; + try_location--) + { + int location_flag = try_location == TRY_IMAGE_SRC_GAME ? IF_SRC_GAME : IF_SRC_MASK; + if(((flags & IF_SRC_MASK) != 0) && ((flags & IF_SRC_MASK) != location_flag)) + continue; - // load the pic from disk - pic = NULL; + for (int use_override = override_textures; use_override >= 0; use_override--) + { + // fill in some basic info + if (use_override) + { + const char *last_slash = strrchr(name, '/'); + if (!last_slash) + last_slash = name; + else + last_slash += 1; - if (fmt == IM_MAX) { - // unknown extension, but give it a chance to load anyway - ret = try_other_formats(IM_MAX, image, &pic); - if (ret == Q_ERR_NOENT) { - // not found, change error to invalid path - ret = Q_ERR_INVALID_PATH; - } - } - else if (override_textures) { - // forcibly replace the extension - ret = try_other_formats(IM_MAX, image, &pic); - } - else { - // first try with original extension - ret = _try_image_format(fmt, image, &pic); - if (ret == Q_ERR_NOENT) { - // retry with remaining extensions - ret = try_other_formats(fmt, image, &pic); - } - } + strcpy(image->name, "overrides/"); + strcat(image->name, last_slash); + image->baselen = strlen(image->name) - 4; + } + else + { + memcpy(image->name, name, len + 1); + image->baselen = len - 4; + } + image->type = type; + image->flags = flags | location_flag; + image->registration_sequence = registration_sequence; + + // find out original extension + for (fmt = 0; fmt < IM_MAX; fmt++) + { + if (!Q_stricmp(image->name + image->baselen + 1, img_loaders[fmt].ext)) + { + break; + } + } - // record last modified time (skips reload when invoking IMG_ReloadAll) - image->last_modified = 0; - FS_LastModified(image->name, &image->last_modified); + // load the pic from disk + pic = NULL; + + if (fmt == IM_MAX) + { + // unknown extension, but give it a chance to load anyway + ret = try_other_formats(IM_MAX, image, try_location, &pic); + if (ret == Q_ERR_NOENT) + { + // not found, change error to invalid path + ret = Q_ERR_INVALID_PATH; + } + } + else if (override_textures) + { + // forcibly replace the extension + ret = try_other_formats(IM_MAX, image, try_location, &pic); + } + else + { + // first try with original extension + ret = _try_image_format(fmt, image, try_location, &pic); + if (ret == Q_ERR_NOENT) + { + // retry with remaining extensions + ret = try_other_formats(fmt, image, try_location, &pic); + } + } - if (use_override) - { - memcpy(image->name, name, len + 1); - image->baselen = len - 4; - } + // record last modified time (skips reload when invoking IMG_ReloadAll) + image->last_modified = 0; + FS_LastModified(image->name, &image->last_modified); - // if we are replacing 8-bit texture with a higher resolution 32-bit - // texture, we need to recover original image dimensions - if (fmt <= IM_WAL && ret > IM_WAL) { - get_image_dimensions(fmt, image); - } + if (use_override) + { + memcpy(image->name, name, len + 1); + image->baselen = len - 4; + } - if(ret >= 0) - break; - } + // if we are replacing 8-bit texture with a higher resolution 32-bit + // texture, we need to recover original image dimensions + if (fmt <= IM_WAL && ret > IM_WAL) + { + get_image_dimensions(fmt, image); + } + + if (ret >= 0) + break; + } + + if (ret >= 0) + break; + } if (ret < 0) { memset(image, 0, sizeof(*image)); diff --git a/src/refresh/models.c b/src/refresh/models.c index 6eaccee6c..6ff7d429b 100644 --- a/src/refresh/models.c +++ b/src/refresh/models.c @@ -302,6 +302,9 @@ static qerror_t MOD_LoadSP2(model_t *model, const void *rawdata, size_t length) return Q_ERR_SUCCESS; } +#define TRY_MODEL_SRC_GAME 1 +#define TRY_MODEL_SRC_BASE 0 + qhandle_t R_RegisterModel(const char *name) { char normalized[MAX_QPATH]; @@ -344,15 +347,31 @@ qhandle_t R_RegisterModel(const char *name) goto done; } - char* extension = normalized + namelen - 4; - if (namelen > 4 && (strcmp(extension, ".md2") == 0) && vid_rtx->integer) - { - memcpy(extension, ".md3", 4); + // Always prefer models from the game dir, even if format might be 'inferior' + for (int try_location = Q_stricmp(fs_game->string, BASEGAME) ? TRY_MODEL_SRC_GAME : TRY_MODEL_SRC_BASE; + try_location >= TRY_MODEL_SRC_BASE; + try_location--) + { + int fs_flags = 0; + if (try_location > 0) + fs_flags = try_location == TRY_MODEL_SRC_GAME ? FS_PATH_GAME : FS_PATH_BASE; - filelen = FS_LoadFile(normalized, (void **)&rawdata); + char* extension = normalized + namelen - 4; + if (namelen > 4 && (strcmp(extension, ".md2") == 0) && vid_rtx->integer) + { + memcpy(extension, ".md3", 4); - memcpy(extension, ".md2", 4); - } + filelen = FS_LoadFileFlags(normalized, (void **)&rawdata, fs_flags); + + memcpy(extension, ".md2", 4); + } + if (!rawdata) + { + filelen = FS_LoadFileFlags(normalized, (void **)&rawdata, fs_flags); + } + if (rawdata) + break; + } if (!rawdata) { diff --git a/src/refresh/vkpt/bsp_mesh.c b/src/refresh/vkpt/bsp_mesh.c index f325502fa..722d1d69e 100644 --- a/src/refresh/vkpt/bsp_mesh.c +++ b/src/refresh/vkpt/bsp_mesh.c @@ -300,9 +300,10 @@ get_triangle_off_center(const float* positions, float* center, float* anti_cente CrossProduct(e1, e2, normal); float length = VectorNormalize(normal); - // Offset the center by one normal to make sure that the point is + // Offset the center by a fraction of the normal to make sure that the point is // inside a BSP leaf and not on a boundary plane. + VectorScale(normal, 0.0001, normal); VectorAdd(center, normal, center); if (anti_center) @@ -1792,37 +1793,21 @@ bsp_mesh_register_textures(bsp_t *bsp) if (!mat) Com_EPrintf("error finding material '%s'\n", buffer); - image_t* image_diffuse = IMG_Find(buffer, IT_WALL, flags | IF_SRGB); - image_t* image_normals = NULL; - image_t* image_emissive = NULL; + vkpt_material_images_t images; + vkpt_load_material_images(&images, buffer, IT_WALL, flags); - if (image_diffuse != R_NOTEXTURE) + if (images.normals && !images.normals->processing_complete) { - // attempt loading the second texture - Q_concat(buffer, sizeof(buffer), "textures/", info->name, "_n.tga", NULL); - FS_NormalizePath(buffer, buffer); - image_normals = IMG_Find(buffer, IT_WALL, flags); - if (image_normals == R_NOTEXTURE) image_normals = NULL; - - if (image_normals && !image_normals->processing_complete) - { - vkpt_normalize_normal_map(image_normals); - } - - // attempt loading the emissive texture - Q_concat(buffer, sizeof(buffer), "textures/", info->name, "_light.tga", NULL); - FS_NormalizePath(buffer, buffer); - image_emissive = IMG_Find(buffer, IT_WALL, flags | IF_SRGB); - if (image_emissive == R_NOTEXTURE) image_emissive = NULL; - - if (image_emissive && !image_emissive->processing_complete && (mat->emissive_scale > 0.f) && ((mat->flags & MATERIAL_FLAG_LIGHT) != 0 || MAT_IsKind(mat->flags, MATERIAL_KIND_LAVA))) - { - vkpt_extract_emissive_texture_info(image_emissive); - } + vkpt_normalize_normal_map(images.normals); + } + + if (images.emissive && !images.emissive->processing_complete && (mat->emissive_scale > 0.f) && ((mat->flags & MATERIAL_FLAG_LIGHT) != 0 || MAT_IsKind(mat->flags, MATERIAL_KIND_LAVA))) + { + vkpt_extract_emissive_texture_info(images.emissive); } // finish registration - MAT_RegisterPBRMaterial(mat, image_diffuse, image_normals, image_emissive); + MAT_RegisterPBRMaterial(mat, images.diffuse, images.normals, images.emissive); info->material = mat; } diff --git a/src/refresh/vkpt/models.c b/src/refresh/vkpt/models.c index a5d716b03..aa06413bc 100644 --- a/src/refresh/vkpt/models.c +++ b/src/refresh/vkpt/models.c @@ -258,32 +258,10 @@ qerror_t MOD_LoadMD2_RTX(model_t *model, const void *rawdata, size_t length) if (!mat) Com_EPrintf("error finding material '%s'\n", skinname); - image_t* image_diffuse = IMG_Find(skinname, IT_SKIN, IF_SRGB); - image_t* image_normals = NULL; - image_t* image_emissive = NULL; + vkpt_material_images_t images; + vkpt_load_material_images(&images, skinname, IT_SKIN, IF_NONE); - if (image_diffuse != R_NOTEXTURE) - { - // attempt loading the normals texture - if (!Q_strlcpy(skinname, src_skin, strlen(src_skin) - 3)) - return Q_ERR_STRING_TRUNCATED; - - Q_concat(skinname, sizeof(skinname), skinname, "_n.tga", NULL); - FS_NormalizePath(skinname, skinname); - image_normals = IMG_Find(skinname, IT_SKIN, IF_NONE); - if (image_normals == R_NOTEXTURE) image_normals = NULL; - - // attempt loading the emissive texture - if (!Q_strlcpy(skinname, src_skin, strlen(src_skin) - 3)) - return Q_ERR_STRING_TRUNCATED; - - Q_concat(skinname, sizeof(skinname), skinname, "_light.tga", NULL); - FS_NormalizePath(skinname, skinname); - image_emissive = IMG_Find(skinname, IT_SKIN, IF_SRGB); - if (image_emissive == R_NOTEXTURE) image_emissive = NULL; - } - - MAT_RegisterPBRMaterial(mat, image_diffuse, image_normals, image_emissive); + MAT_RegisterPBRMaterial(mat, images.diffuse, images.normals, images.emissive); dst_mesh->materials[i] = mat; @@ -468,32 +446,10 @@ static qerror_t MOD_LoadMD3Mesh(model_t *model, maliasmesh_t *mesh, if (!mat) Com_EPrintf("error finding material '%s'\n", skinname); - image_t* image_diffuse = IMG_Find(skinname, IT_SKIN, IF_SRGB); - image_t* image_normals = NULL; - image_t* image_emissive = NULL; - - if (image_diffuse != R_NOTEXTURE) - { - // attempt loading the normals texture - if (!Q_strlcpy(skinname, src_skin->name, strlen(src_skin->name) - 3)) - return Q_ERR_STRING_TRUNCATED; - - Q_concat(skinname, sizeof(skinname), skinname, "_n.tga", NULL); - FS_NormalizePath(skinname, skinname); - image_normals = IMG_Find(skinname, IT_SKIN, IF_NONE); - if (image_normals == R_NOTEXTURE) image_normals = NULL; - - // attempt loading the emissive texture - if (!Q_strlcpy(skinname, src_skin->name, strlen(src_skin->name) - 3)) - return Q_ERR_STRING_TRUNCATED; - - Q_concat(skinname, sizeof(skinname), skinname, "_light.tga", NULL); - FS_NormalizePath(skinname, skinname); - image_emissive = IMG_Find(skinname, IT_SKIN, IF_SRGB); - if (image_emissive == R_NOTEXTURE) image_emissive = NULL; - } + vkpt_material_images_t images; + vkpt_load_material_images(&images, skinname, IT_SKIN, IF_NONE); - MAT_RegisterPBRMaterial(mat, image_diffuse, image_normals, image_emissive); + MAT_RegisterPBRMaterial(mat, images.diffuse, images.normals, images.emissive); mesh->materials[i] = mat; } diff --git a/src/refresh/vkpt/textures.c b/src/refresh/vkpt/textures.c index 87604ad42..8269e28d4 100644 --- a/src/refresh/vkpt/textures.c +++ b/src/refresh/vkpt/textures.c @@ -94,25 +94,9 @@ void vkpt_textures_prefetch() if (!line) continue; - image_t const * img1 = IMG_Find(line, IT_SKIN, IF_PERMANENT | IF_SRGB); - char other_name[MAX_QPATH]; - - // attempt loading a matching normal map - if (!Q_strlcpy(other_name, line, strlen(line) - 3)) - continue; - Q_concat(other_name, sizeof(other_name), other_name, "_n.tga", NULL); - FS_NormalizePath(other_name, other_name); - image_t const * img2 = IMG_Find(other_name, IT_SKIN, IF_PERMANENT); - /* if (img2 != R_NOTEXTURE) - Com_Printf("Prefetched '%s' (%d)\n", other_name, (int)(img2 - r_images)); */ - - // attempt loading a matching emissive map - if (!Q_strlcpy(other_name, line, strlen(line) - 3)) - continue; - Q_concat(other_name, sizeof(other_name), other_name, "_light.tga", NULL); - FS_NormalizePath(other_name, other_name); - image_t const * img3 = IMG_Find(other_name, IT_SKIN, IF_PERMANENT | IF_SRGB); + vkpt_material_images_t images; + vkpt_load_material_images(&images, line, IT_SKIN, IF_PERMANENT); } // Com_Printf("Loaded '%s'\n", filename); FS_FreeFile(buffer); @@ -630,6 +614,34 @@ vkpt_normalize_normal_map(image_t *image) image->processing_complete = qtrue; } +void vkpt_load_material_images(vkpt_material_images_t* images, const char *diffuse_path, imagetype_t type, imageflags_t flags) +{ + images->diffuse = IMG_Find(diffuse_path, type, flags | IF_SRGB); + images->normals = NULL; + images->emissive = NULL; + + if (images->diffuse != R_NOTEXTURE) + { + int src_flag = images->diffuse->flags & IF_SRC_MASK; + char other_name[MAX_QPATH]; + + // attempt loading a matching normal map + size_t diffuse_name_len = Q_strlcpy(other_name, diffuse_path, q_countof(other_name)); + other_name[diffuse_name_len - 4] = 0; + Q_strlcat(other_name, "_n.tga", q_countof(other_name)); + FS_NormalizePath(other_name, other_name); + images->normals = IMG_Find(other_name, type, flags | src_flag); + if (images->normals == R_NOTEXTURE) images->normals = NULL; + + // attempt loading the emissive texture + other_name[diffuse_name_len - 4] = 0; + Q_strlcat(other_name, "_light.tga", q_countof(other_name)); + FS_NormalizePath(other_name, other_name); + images->emissive = IMG_Find(other_name, type, flags | src_flag | IF_SRGB); + if (images->emissive == R_NOTEXTURE) images->emissive = NULL; + } +} + void IMG_Load_RTX(image_t *image, byte *pic) { diff --git a/src/refresh/vkpt/vkpt.h b/src/refresh/vkpt/vkpt.h index 57b1ef3af..e7aa5958b 100644 --- a/src/refresh/vkpt/vkpt.h +++ b/src/refresh/vkpt/vkpt.h @@ -528,6 +528,13 @@ void vkpt_extract_emissive_texture_info(image_t *image); void vkpt_textures_prefetch(); void vkpt_init_light_textures(); +typedef struct vkpt_material_images_s { + image_t *diffuse; + image_t *normals; + image_t *emissive; +} vkpt_material_images_t; +void vkpt_load_material_images(vkpt_material_images_t* images, const char *diffuse_path, imagetype_t type, imageflags_t flags); + VkCommandBuffer vkpt_begin_command_buffer(cmd_buf_group_t* group); void vkpt_free_command_buffers(cmd_buf_group_t* group); void vkpt_reset_command_buffers(cmd_buf_group_t* group);