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
This commit is contained in:
Ivan Avdeev 2023-10-31 12:43:16 -04:00 committed by Ivan Avdeev
parent 5698746f42
commit 6fda8bd977
6 changed files with 66 additions and 14 deletions

View File

@ -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

View File

@ -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"
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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 };