From 83a31973c26a88dee25be9515f76ff5a95b911b4 Mon Sep 17 00:00:00 2001 From: Denis Pauk Date: Mon, 16 Oct 2023 00:35:33 +0300 Subject: [PATCH] Add transparent with alpha test surface support Based on surface flag from kmquake2 and rerelease documatation https://github.com/id-Software/quake2-rerelease-dll#surf_alphatest-bit-25 --- doc/100_tested_maps.md | 1 - src/client/refresh/files/light.c | 2 +- src/client/refresh/gl1/gl1_model.c | 4 ++-- src/client/refresh/gl1/gl1_surf.c | 11 +++++++---- src/client/refresh/gl3/gl3_light.c | 2 +- src/client/refresh/gl3/gl3_model.c | 4 ++-- src/client/refresh/gl3/gl3_surf.c | 10 +++++++--- src/client/refresh/gl4/gl4_light.c | 2 +- src/client/refresh/gl4/gl4_model.c | 4 ++-- src/client/refresh/gl4/gl4_surf.c | 11 ++++++++--- src/client/refresh/soft/sw_bsp.c | 2 +- src/client/refresh/soft/sw_poly.c | 4 ++-- src/client/refresh/soft/sw_rast.c | 4 ++-- src/client/refresh/soft/sw_surf.c | 30 ++++++++++++++++++++++-------- src/client/refresh/vk/vk_model.c | 4 ++-- src/client/refresh/vk/vk_surf.c | 12 ++++++++---- src/common/header/files.h | 1 + src/common/header/shared.h | 3 +++ 18 files changed, 72 insertions(+), 39 deletions(-) diff --git a/doc/100_tested_maps.md b/doc/100_tested_maps.md index d7ea1f51..533a9c0c 100644 --- a/doc/100_tested_maps.md +++ b/doc/100_tested_maps.md @@ -10,7 +10,6 @@ ## Quake2 ReRelease Notes: - * mgu5m1: gl1,vk: non transparent flowers * mgu5m2: server code: Too many models 256 (226 inline models) | map | gl1.4 | gl3/gles3 | gl4.6 | vk | soft | diff --git a/src/client/refresh/files/light.c b/src/client/refresh/files/light.c index e85909fa..5f64918a 100644 --- a/src/client/refresh/files/light.c +++ b/src/client/refresh/files/light.c @@ -502,7 +502,7 @@ R_BuildLightMap(const msurface_t *surf, byte *dest, int stride, const byte *dest float *bl; if (surf->texinfo->flags & - (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)) + (SURF_SKY | SURF_TRANSPARENT | SURF_WARP)) { Com_Error(ERR_DROP, "%s called for non-lit surface", __func__); } diff --git a/src/client/refresh/gl1/gl1_model.c b/src/client/refresh/gl1/gl1_model.c index 68c07059..2b19719a 100644 --- a/src/client/refresh/gl1/gl1_model.c +++ b/src/client/refresh/gl1/gl1_model.c @@ -450,7 +450,7 @@ Mod_LoadFaces(model_t *loadmodel, const byte *mod_base, const lump_t *l, } /* create lightmaps and polygons */ - if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP))) + if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANSPARENT | SURF_WARP))) { LM_CreateSurfaceLightmap(out); } @@ -576,7 +576,7 @@ Mod_LoadQFaces(model_t *loadmodel, const byte *mod_base, const lump_t *l, } /* create lightmaps and polygons */ - if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP))) + if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANSPARENT | SURF_WARP))) { LM_CreateSurfaceLightmap(out); } diff --git a/src/client/refresh/gl1/gl1_surf.c b/src/client/refresh/gl1/gl1_surf.c index 983dcf13..160e4a5c 100644 --- a/src/client/refresh/gl1/gl1_surf.c +++ b/src/client/refresh/gl1/gl1_surf.c @@ -489,8 +489,7 @@ R_RenderBrushPoly(entity_t *currententity, msurface_t *fa) if (r_dynamic->value) { if (!(fa->texinfo->flags & - (SURF_SKY | SURF_TRANS33 | - SURF_TRANS66 | SURF_WARP))) + (SURF_SKY | SURF_TRANSPARENT | SURF_WARP))) { is_dynamic = true; } @@ -573,6 +572,10 @@ R_DrawAlphaSurfaces(void) { glColor4f(intens, intens, intens, 0.66); } + else if (s->texinfo->flags & SURF_ALPHATEST) + { + glColor4f(intens, intens, intens, 0.99); + } else { glColor4f(intens, intens, intens, 1); @@ -672,7 +675,7 @@ R_DrawInlineBModel(entity_t *currententity, const model_t *currentmodel) if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - if (psurf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66)) + if (psurf->texinfo->flags & SURF_TRANSPARENT) { /* add to the translucent chain */ psurf->texturechain = r_alpha_surfaces; @@ -897,7 +900,7 @@ R_RecursiveWorldNode(entity_t *currententity, mnode_t *node) /* just adds to visible sky bounds */ RE_AddSkySurface(surf); } - else if (surf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66)) + else if (surf->texinfo->flags & SURF_TRANSPARENT) { /* add to the translucent chain */ surf->texturechain = r_alpha_surfaces; diff --git a/src/client/refresh/gl3/gl3_light.c b/src/client/refresh/gl3/gl3_light.c index 372b9137..60202f8f 100644 --- a/src/client/refresh/gl3/gl3_light.c +++ b/src/client/refresh/gl3/gl3_light.c @@ -78,7 +78,7 @@ GL3_BuildLightMap(msurface_t *surf, int offsetInLMbuf, int stride) byte *lightmap; if (surf->texinfo->flags & - (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)) + (SURF_SKY | SURF_TRANSPARENT | SURF_WARP)) { Com_Error(ERR_DROP, "GL3_BuildLightMap called for non-lit surface"); } diff --git a/src/client/refresh/gl3/gl3_model.c b/src/client/refresh/gl3/gl3_model.c index 3864f850..220f9e73 100644 --- a/src/client/refresh/gl3/gl3_model.c +++ b/src/client/refresh/gl3/gl3_model.c @@ -430,7 +430,7 @@ Mod_LoadFaces(gl3model_t *loadmodel, const byte *mod_base, const lump_t *l, } /* create lightmaps and polygons */ - if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP))) + if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANSPARENT | SURF_WARP))) { GL3_LM_CreateSurfaceLightmap(out); } @@ -539,7 +539,7 @@ Mod_LoadQFaces(gl3model_t *loadmodel, const byte *mod_base, const lump_t *l, } /* create lightmaps and polygons */ - if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP))) + if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANSPARENT | SURF_WARP))) { GL3_LM_CreateSurfaceLightmap(out); } diff --git a/src/client/refresh/gl3/gl3_surf.c b/src/client/refresh/gl3/gl3_surf.c index e2a63edb..432e3ee9 100644 --- a/src/client/refresh/gl3/gl3_surf.c +++ b/src/client/refresh/gl3/gl3_surf.c @@ -370,6 +370,10 @@ GL3_DrawAlphaSurfaces(void) { alpha = 0.666f; } + else if (s->texinfo->flags & SURF_ALPHATEST) + { + alpha = 0.999f; + } if(alpha != gl3state.uni3DData.alpha) { gl3state.uni3DData.alpha = alpha; @@ -446,7 +450,7 @@ RenderLightmappedPoly(entity_t *currententity, msurface_t *surf) hmm_vec4 lmScales[MAX_LIGHTMAPS_PER_SURFACE] = {0}; lmScales[0] = HMM_Vec4(1.0f, 1.0f, 1.0f, 1.0f); - assert((surf->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)) == 0 + assert((surf->texinfo->flags & (SURF_SKY | SURF_TRANSPARENT | SURF_WARP)) == 0 && "RenderLightMappedPoly mustn't be called with transparent, sky or warping surfaces!"); // Any dynamic lights on this surface? @@ -512,7 +516,7 @@ DrawInlineBModel(entity_t *currententity, gl3model_t *currentmodel) if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - if (psurf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66)) + if (psurf->texinfo->flags & SURF_TRANSPARENT) { /* add to the translucent chain */ psurf->texturechain = gl3_alpha_surfaces; @@ -725,7 +729,7 @@ RecursiveWorldNode(entity_t *currententity, mnode_t *node) /* just adds to visible sky bounds */ RE_AddSkySurface(surf); } - else if (surf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66)) + else if (surf->texinfo->flags & SURF_TRANSPARENT) { /* add to the translucent chain */ surf->texturechain = gl3_alpha_surfaces; diff --git a/src/client/refresh/gl4/gl4_light.c b/src/client/refresh/gl4/gl4_light.c index 0e5dee21..78a45e17 100644 --- a/src/client/refresh/gl4/gl4_light.c +++ b/src/client/refresh/gl4/gl4_light.c @@ -78,7 +78,7 @@ GL4_BuildLightMap(msurface_t *surf, int offsetInLMbuf, int stride) byte *lightmap; if (surf->texinfo->flags & - (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)) + (SURF_SKY | SURF_TRANSPARENT | SURF_WARP)) { Com_Error(ERR_DROP, "GL4_BuildLightMap called for non-lit surface"); } diff --git a/src/client/refresh/gl4/gl4_model.c b/src/client/refresh/gl4/gl4_model.c index 3c00b7fa..5c4bb77d 100644 --- a/src/client/refresh/gl4/gl4_model.c +++ b/src/client/refresh/gl4/gl4_model.c @@ -428,7 +428,7 @@ Mod_LoadFaces(gl4model_t *loadmodel, const byte *mod_base, const lump_t *l, } /* create lightmaps and polygons */ - if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP))) + if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANSPARENT | SURF_WARP))) { GL4_LM_CreateSurfaceLightmap(out); } @@ -537,7 +537,7 @@ Mod_LoadQFaces(gl4model_t *loadmodel, const byte *mod_base, const lump_t *l, } /* create lightmaps and polygons */ - if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP))) + if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANSPARENT | SURF_WARP))) { GL4_LM_CreateSurfaceLightmap(out); } diff --git a/src/client/refresh/gl4/gl4_surf.c b/src/client/refresh/gl4/gl4_surf.c index fe8653ea..6785003c 100644 --- a/src/client/refresh/gl4/gl4_surf.c +++ b/src/client/refresh/gl4/gl4_surf.c @@ -370,6 +370,11 @@ GL4_DrawAlphaSurfaces(void) { alpha = 0.666f; } + else if (s->texinfo->flags & SURF_ALPHATEST) + { + alpha = 0.999f; + } + if(alpha != gl4state.uni3DData.alpha) { gl4state.uni3DData.alpha = alpha; @@ -446,7 +451,7 @@ RenderLightmappedPoly(entity_t *currententity, msurface_t *surf) hmm_vec4 lmScales[MAX_LIGHTMAPS_PER_SURFACE] = {0}; lmScales[0] = HMM_Vec4(1.0f, 1.0f, 1.0f, 1.0f); - assert((surf->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP)) == 0 + assert((surf->texinfo->flags & (SURF_SKY | SURF_TRANSPARENT | SURF_WARP)) == 0 && "RenderLightMappedPoly mustn't be called with transparent, sky or warping surfaces!"); // Any dynamic lights on this surface? @@ -511,7 +516,7 @@ DrawInlineBModel(entity_t *currententity, gl4model_t *currentmodel) if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - if (psurf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66)) + if (psurf->texinfo->flags & SURF_TRANSPARENT) { /* add to the translucent chain */ psurf->texturechain = gl4_alpha_surfaces; @@ -724,7 +729,7 @@ RecursiveWorldNode(entity_t *currententity, mnode_t *node) /* just adds to visible sky bounds */ GL4_AddSkySurface(surf); } - else if (surf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66)) + else if (surf->texinfo->flags & SURF_TRANSPARENT) { /* add to the translucent chain */ surf->texturechain = gl4_alpha_surfaces; diff --git a/src/client/refresh/soft/sw_bsp.c b/src/client/refresh/soft/sw_bsp.c index 78d8aa97..c4af85cb 100644 --- a/src/client/refresh/soft/sw_bsp.c +++ b/src/client/refresh/soft/sw_bsp.c @@ -394,7 +394,7 @@ R_DrawSolidClippedSubmodelPolygons(entity_t *currententity, const model_t *curre pbedge[j-1].pnext = NULL; // mark end of edges - if ( !( psurf->texinfo->flags & ( SURF_TRANS66 | SURF_TRANS33 ) )) + if ( !( psurf->texinfo->flags & SURF_TRANSPARENT )) { // FIXME: Fan broken in borehole // teleport: 1231.000000 770.250000 -579.375000 diff --git a/src/client/refresh/soft/sw_poly.c b/src/client/refresh/soft/sw_poly.c index 4d22de84..dcfb8fde 100644 --- a/src/client/refresh/soft/sw_poly.c +++ b/src/client/refresh/soft/sw_poly.c @@ -1236,9 +1236,9 @@ R_DrawAlphaSurfaces(const entity_t *currententity) // pass down all the texinfo flags, not just SURF_WARP. if (s->texinfo->flags & SURF_TRANS66) - R_ClipAndDrawPoly( 0.60f, (s->texinfo->flags & (SURF_WARP|SURF_FLOWING)), true ); + R_ClipAndDrawPoly( 0.60f, (s->texinfo->flags & (SURF_WARP | SURF_FLOWING)), true ); else - R_ClipAndDrawPoly( 0.30f, (s->texinfo->flags & (SURF_WARP|SURF_FLOWING)), true ); + R_ClipAndDrawPoly( 0.30f, (s->texinfo->flags & (SURF_WARP | SURF_FLOWING)), true ); s = s->nextalphasurface; } diff --git a/src/client/refresh/soft/sw_rast.c b/src/client/refresh/soft/sw_rast.c index f905182f..621dcb70 100644 --- a/src/client/refresh/soft/sw_rast.c +++ b/src/client/refresh/soft/sw_rast.c @@ -532,7 +532,7 @@ R_RenderFace (entity_t *currententity, const model_t *currentmodel, msurface_t * qboolean r_nearzionly; // translucent surfaces are not drawn by the edge renderer - if (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) + if (fa->texinfo->flags & SURF_TRANSPARENT) { fa->nextalphasurface = r_alpha_surfaces; r_alpha_surfaces = fa; @@ -756,7 +756,7 @@ R_RenderBmodelFace(entity_t *currententity, bedge_t *pedges, msurface_t *psurf, qboolean makeleftedge, makerightedge; qboolean r_nearzionly; - if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) + if (psurf->texinfo->flags & SURF_TRANSPARENT) { psurf->nextalphasurface = r_alpha_surfaces; r_alpha_surfaces = psurf; diff --git a/src/client/refresh/soft/sw_surf.c b/src/client/refresh/soft/sw_surf.c index 03fb569c..46aad825 100644 --- a/src/client/refresh/soft/sw_surf.c +++ b/src/client/refresh/soft/sw_surf.c @@ -261,18 +261,22 @@ void R_InitCaches (void) { int size; - // calculate size to allocate int pix; + // surface cache size at 320X240 size = 1024*768; pix = vid_buffer_width*vid_buffer_height; if (pix > 64000) - size += (pix-64000)*3; + { + size += (pix - 64000) * 3; + } if (r_farsee->value > 0) + { size *= 2; + } if (sw_surfcacheoverride->value > size) { @@ -299,7 +303,6 @@ R_InitCaches (void) sc_base->size = sc_size; } - /* ================== D_FlushCaches @@ -331,7 +334,7 @@ D_SCAlloc ================= */ static surfcache_t * -D_SCAlloc (int width, int size) +D_SCAlloc(int width, int size) { surfcache_t *new; @@ -345,7 +348,7 @@ D_SCAlloc (int width, int size) Com_Error(ERR_FATAL, "%s: bad cache size %d\n", __func__, size); } - // Add header size + /* Add header size */ size += ((char*)sc_base->data - (char*)sc_base); size = (size + 3) & ~3; if (size > sc_size) @@ -353,27 +356,33 @@ D_SCAlloc (int width, int size) Com_Error(ERR_FATAL, "%s: %i > cache size of %i", __func__, size, sc_size); } - // if there is not size bytes after the rover, reset to the start + /* if there is not size bytes after the rover, reset to the start */ if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size) { sc_rover = sc_base; } - // colect and free surfcache_t blocks until the rover block is large enough + /* colect and free surfcache_t blocks until the rover block is large enough */ new = sc_rover; if (sc_rover->owner) + { *sc_rover->owner = NULL; + } while (new->size < size) { - // free another + /* free another */ sc_rover = sc_rover->next; + if (!sc_rover) { Com_Error(ERR_FATAL, "%s: hit the end of memory", __func__); } + if (sc_rover->owner) + { *sc_rover->owner = NULL; + } new->size += sc_rover->size; new->next = sc_rover->next; @@ -391,12 +400,17 @@ D_SCAlloc (int width, int size) new->size = size; } else + { sc_rover = new->next; + } new->width = width; + // DEBUG if (width > 0) + { new->height = (size - sizeof(*new) + sizeof(new->data)) / width; + } new->owner = NULL; // should be set properly after return diff --git a/src/client/refresh/vk/vk_model.c b/src/client/refresh/vk/vk_model.c index 68c99e40..dada35c3 100644 --- a/src/client/refresh/vk/vk_model.c +++ b/src/client/refresh/vk/vk_model.c @@ -420,7 +420,7 @@ Mod_LoadFaces(model_t *loadmodel, const byte *mod_base, const lump_t *l, } /* create lightmaps and polygons */ - if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP))) + if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANSPARENT | SURF_WARP))) { Vk_CreateSurfaceLightmap(out); } @@ -546,7 +546,7 @@ Mod_LoadQFaces(model_t *loadmodel, const byte *mod_base, const lump_t *l, } /* create lightmaps and polygons */ - if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP))) + if (!(out->texinfo->flags & (SURF_SKY | SURF_TRANSPARENT | SURF_WARP))) { Vk_CreateSurfaceLightmap(out); } diff --git a/src/client/refresh/vk/vk_surf.c b/src/client/refresh/vk/vk_surf.c index da239b6b..e321f100 100644 --- a/src/client/refresh/vk/vk_surf.c +++ b/src/client/refresh/vk/vk_surf.c @@ -230,7 +230,7 @@ R_RenderBrushPoly(msurface_t *fa, float *modelMatrix, float alpha, entity_t *cur dynamic: if (r_dynamic->value) { - if (!(fa->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP))) + if (!(fa->texinfo->flags & (SURF_SKY | SURF_TRANSPARENT | SURF_WARP))) { is_dynamic = true; } @@ -306,6 +306,10 @@ R_DrawAlphaSurfaces(void) { color[3] = 0.66f; } + else if (s->texinfo->flags & SURF_ALPHATEST) + { + color[3] = 0.99f; + } if (s->flags & SURF_DRAWTURB) { @@ -434,7 +438,7 @@ Vk_RenderLightmappedPoly(msurface_t *surf, float *modelMatrix, float alpha, enti dynamic: if (r_dynamic->value) { - if (!(surf->texinfo->flags & (SURF_SKY | SURF_TRANS33 | SURF_TRANS66 | SURF_WARP))) + if (!(surf->texinfo->flags & (SURF_SKY | SURF_TRANSPARENT | SURF_WARP))) { is_dynamic = true; } @@ -642,7 +646,7 @@ R_DrawInlineBModel(entity_t *currententity, const model_t *currentmodel, float * if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - if (psurf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66)) + if (psurf->texinfo->flags & SURF_TRANSPARENT) { /* add to the translucent chain */ psurf->texturechain = r_alpha_surfaces; @@ -835,7 +839,7 @@ R_RecursiveWorldNode(entity_t *currententity, mnode_t *node) /* just adds to visible sky bounds */ RE_AddSkySurface(surf); } - else if (surf->texinfo->flags & (SURF_TRANS33 | SURF_TRANS66)) + else if (surf->texinfo->flags & SURF_TRANSPARENT) { /* add to the translucent chain */ surf->texturechain = r_alpha_surfaces; diff --git a/src/common/header/files.h b/src/common/header/files.h index ef15b165..0b80f42c 100644 --- a/src/common/header/files.h +++ b/src/common/header/files.h @@ -511,6 +511,7 @@ typedef struct #define SURF_TRANS66 0x20 #define SURF_FLOWING 0x40 /* scroll towards angle */ #define SURF_NODRAW 0x80 /* don't bother referencing the texture */ +#define SURF_ALPHATEST 0x02000000 typedef struct { diff --git a/src/common/header/shared.h b/src/common/header/shared.h index 9f329bc1..3041d2fb 100644 --- a/src/common/header/shared.h +++ b/src/common/header/shared.h @@ -497,6 +497,9 @@ typedef struct cvar_s #define SURF_TRANS66 0x20 #define SURF_FLOWING 0x40 /* scroll towards angle */ #define SURF_NODRAW 0x80 /* don't bother referencing the texture */ +#define SURF_ALPHATEST 0x02000000 /* KMQUAKE2 Alpha test flag */ +/* Transparnet but not explicitly warp */ +#define SURF_TRANSPARENT (SURF_TRANS33 | SURF_TRANS66 | SURF_ALPHATEST) /* content masks */ #define MASK_ALL (-1)