From 6fda8bd977da55b23c9fee2cd00cf9e5b027fc81 Mon Sep 17 00:00:00 2001 From: Ivan Avdeev Date: Tue, 31 Oct 2023 12:43:16 -0400 Subject: [PATCH] vk: add a mechanism for exclusion of single surfaces from smoothing Uses `_xvk_smoothing_excluded` field. Surfaces can still be smoothed with a limited list of neightbours explicitly by being included in a smoothing group. Fixes #619 --- ref/vk/TODO.md | 4 ++- ref/vk/data/valve/luchiki/maps/c1a1b.patch | 4 +++ ref/vk/shaders/denoiser.comp | 4 ++- ref/vk/vk_brush.c | 25 ++++++++++++---- ref/vk/vk_mapents.c | 33 +++++++++++++++++++--- ref/vk/vk_mapents.h | 10 +++++-- 6 files changed, 66 insertions(+), 14 deletions(-) diff --git a/ref/vk/TODO.md b/ref/vk/TODO.md index 5b6a811028..a99db2cd65 100644 --- a/ref/vk/TODO.md +++ b/ref/vk/TODO.md @@ -5,7 +5,9 @@ - [x] single return/goto cleanup - [-] pass args via structs? -> not necessary - [-] collapse texture uploading into a single function -> not necessary, they are different enough -- [ ] merge materials PR +- [x] merge materials PR +- [x] studio gibs translucency +- [x] smoothing exclusion # 2023-10-30 E321 - [x] missing skybox diff --git a/ref/vk/data/valve/luchiki/maps/c1a1b.patch b/ref/vk/data/valve/luchiki/maps/c1a1b.patch index db5cfd8d6e..3d2f4aad9d 100644 --- a/ref/vk/data/valve/luchiki/maps/c1a1b.patch +++ b/ref/vk/data/valve/luchiki/maps/c1a1b.patch @@ -89,3 +89,7 @@ _xvk_smooth_entire_model "1" { //"_xvk_smoothing_threshold" "44" //workaround } + +{ +_xvk_smoothing_excluded "2120 2117 2118 1269 1267 2791 2792 2793" +} diff --git a/ref/vk/shaders/denoiser.comp b/ref/vk/shaders/denoiser.comp index 52918bcbf0..eed10fbfc3 100644 --- a/ref/vk/shaders/denoiser.comp +++ b/ref/vk/shaders/denoiser.comp @@ -241,8 +241,10 @@ void main() { //imageStore(out_dest, pix, vec4(.5 + geometry_normal * .5, 0.)); return; //const vec4 mat_rmxx = imageLoad(material_rmxx, pix); //imageStore(out_dest, pix, vec4((.5 + shading_normal * .5)*.8 + .2 * mat_rmxx.a , 0.)); return; + //imageStore(out_dest, pix, vec4(.5 + shading_normal * .5, 0.)); return; - vec3 normal = pix.x < res.x / 2 ? shading_normal : geometry_normal; + //vec3 normal = pix.x < res.x / 2 ? shading_normal : geometry_normal; + vec3 normal = shading_normal;// : geometry_normal; imageStore(out_dest, pix, vec4(.5 + normal * .5, 0.)); return; #endif diff --git a/ref/vk/vk_brush.c b/ref/vk/vk_brush.c index 0ef5893573..1c5fc49e11 100644 --- a/ref/vk/vk_brush.c +++ b/ref/vk/vk_brush.c @@ -848,21 +848,31 @@ static void getSurfaceNormal( const msurface_t *surf, vec3_t out_normal) { } static qboolean shouldSmoothLinkSurfaces(const model_t* mod, qboolean smooth_entire_model, int surf1, int surf2) { - //return Q_min(surf1, surf2) == 741 && Q_max(surf1, surf2) == 743; - // Filter explicit exclusion - for (int i = 0; i < g_map_entities.smoothing.excluded_count; i+=2) { - const int cand1 = g_map_entities.smoothing.excluded[i]; - const int cand2 = g_map_entities.smoothing.excluded[i+1]; + for (int i = 0; i < g_map_entities.smoothing.excluded_pairs_count; i+=2) { + const int cand1 = g_map_entities.smoothing.excluded_pairs[i]; + const int cand2 = g_map_entities.smoothing.excluded_pairs[i+1]; if ((cand1 == surf1 && cand2 == surf2) || (cand1 == surf2 && cand2 == surf1)) return false; } - if (smooth_entire_model) + qboolean excluded = false; + for (int i = 0; i < g_map_entities.smoothing.excluded_count; ++i) { + const int cand = g_map_entities.smoothing.excluded[i]; + if (cand == surf1 || cand == surf2) { + excluded = true; + break; + } + } + + if (smooth_entire_model && !excluded) return true; + // Smoothing groups have priority over individual exclusion. + // That way we can exclude a surface from smoothing with most of its neighbours, + // but still smooth it with some. for (int i = 0; i < g_map_entities.smoothing.groups_count; ++i) { const xvk_smoothing_group_t *g = g_map_entities.smoothing.groups + i; uint32_t bits = 0; @@ -880,6 +890,9 @@ static qboolean shouldSmoothLinkSurfaces(const model_t* mod, qboolean smooth_ent } } + if (excluded) + return false; + // Do not join surfaces with different textures. Assume they belong to different objects. { // Should we also check texture/material patches too to filter out pairs which originally had diff --git a/ref/vk/vk_mapents.c b/ref/vk/vk_mapents.c index 40d47e203e..cfbca3caec 100644 --- a/ref/vk/vk_mapents.c +++ b/ref/vk/vk_mapents.c @@ -581,18 +581,38 @@ static void patchEntity( const entity_props_t *props, uint32_t have_fields ) { } } -static void appendExludedPairs(const entity_props_t *props) { +static void appendExcludedPairs(const entity_props_t *props) { if (props->_xvk_smoothing_excluded_pairs.num % 2 != 0) { - ERR("vk_mapents: smoothing group exclusion list should be list of pairs -- divisible by 2; cutting the tail"); + ERR("vk_mapents: smoothing group exclusion pairs list should be list of pairs -- divisible by 2; cutting the tail"); } int count = props->_xvk_smoothing_excluded_pairs.num & ~1; + if (g_map_entities.smoothing.excluded_pairs_count + count > COUNTOF(g_map_entities.smoothing.excluded_pairs)) { + ERR("vk_mapents: smoothing exclusion pairs capacity exceeded, go complain in github issues"); + count = COUNTOF(g_map_entities.smoothing.excluded_pairs) - g_map_entities.smoothing.excluded_pairs_count; + } + + memcpy(g_map_entities.smoothing.excluded_pairs + g_map_entities.smoothing.excluded_pairs_count, props->_xvk_smoothing_excluded_pairs.values, count * sizeof(int)); + + g_map_entities.smoothing.excluded_pairs_count += count; +} + +static void appendExcludedSingles(const entity_props_t *props) { + int count = props->_xvk_smoothing_excluded.num; + if (g_map_entities.smoothing.excluded_count + count > COUNTOF(g_map_entities.smoothing.excluded)) { ERR("vk_mapents: smoothing exclusion group capacity exceeded, go complain in github issues"); count = COUNTOF(g_map_entities.smoothing.excluded) - g_map_entities.smoothing.excluded_count; } - memcpy(g_map_entities.smoothing.excluded + g_map_entities.smoothing.excluded_count, props->_xvk_smoothing_excluded_pairs.values, count * sizeof(int)); + memcpy(g_map_entities.smoothing.excluded + g_map_entities.smoothing.excluded_count, props->_xvk_smoothing_excluded.values, count * sizeof(int)); + + if (g_log_debug_bits & LOG_MODULE) { + DEBUG("Adding %d smoothing-excluded surfaces", props->_xvk_smoothing_excluded.num); + for (int i = 0; i < props->_xvk_smoothing_excluded.num; ++i) { + DEBUG("%d", props->_xvk_smoothing_excluded.values[i]); + } + } g_map_entities.smoothing.excluded_count += count; } @@ -670,7 +690,11 @@ static void parseEntities( char *string, qboolean is_patch ) { } if (have_fields & Field__xvk_smoothing_excluded_pairs) { - appendExludedPairs(&values); + appendExcludedPairs(&values); + } + + if (have_fields & Field__xvk_smoothing_excluded) { + appendExcludedSingles(&values); } if (have_fields & Field__xvk_smoothing_group) { @@ -798,6 +822,7 @@ void XVK_ParseMapEntities( void ) { g_map_entities.entity_count = 0; g_map_entities.func_any_count = 0; g_map_entities.smoothing.threshold = cosf(DEG2RAD(45.f)); + g_map_entities.smoothing.excluded_pairs_count = 0; g_map_entities.smoothing.excluded_count = 0; for (int i = 0; i < g_map_entities.smoothing.groups_count; ++i) g_map_entities.smoothing.groups[i].count = 0; diff --git a/ref/vk/vk_mapents.h b/ref/vk/vk_mapents.h index ed2a751db9..e05580823f 100644 --- a/ref/vk/vk_mapents.h +++ b/ref/vk/vk_mapents.h @@ -37,6 +37,7 @@ X(25, string, _xvk_map_material, String) \ X(26, int, rendermode, Int) \ X(27, int, _xvk_smooth_entire_model, Int) \ + X(28, int_array_t, _xvk_smoothing_excluded, IntArray) \ /* NOTE: not used X(23, int, renderamt, Int) \ @@ -162,15 +163,20 @@ typedef struct { float threshold; #define MAX_EXCLUDED_SMOOTHING_SURFACES_PAIRS 32 - int excluded[MAX_EXCLUDED_SMOOTHING_SURFACES_PAIRS * 2]; - int excluded_count; + int excluded_pairs[MAX_EXCLUDED_SMOOTHING_SURFACES_PAIRS * 2]; + int excluded_pairs_count; #define MAX_INCLUDED_SMOOTHING_GROUPS 32 int groups_count; xvk_smoothing_group_t groups[MAX_INCLUDED_SMOOTHING_GROUPS]; + +#define MAX_EXCLUDED_SMOOTHING_SURFACES 256 + int excluded_count; + int excluded[MAX_EXCLUDED_SMOOTHING_SURFACES]; } smoothing; } xvk_map_entities_t; +// TODO expose a bunch of things here as funtions, not as internal structures extern xvk_map_entities_t g_map_entities; enum { NoEnvironmentLights = -1, MoreThanOneEnvironmentLight = -2 };