[skin] Implement top/bottom colors for gl

They don't work yet if the entity does not have an external skin.
This commit is contained in:
Bill Currie 2024-01-15 10:28:02 +09:00
parent 0539f07c1a
commit 346ed29f49
3 changed files with 92 additions and 31 deletions

View file

@ -122,9 +122,13 @@ tex_t *Skin_DupTex (const tex_t *tex);
typedef struct skin_s { typedef struct skin_s {
tex_t *tex; tex_t *tex;
uint32_t id; uint32_t id;
uint32_t fb;
} skin_t; } skin_t;
typedef struct glskin_s {
uint32_t id;
uint32_t fb;
} glskin_t;
skin_t *Skin_Get (uint32_t skin) __attribute__((pure)); skin_t *Skin_Get (uint32_t skin) __attribute__((pure));
void sw_Skin_SetupSkin (skin_t *skin, int cmap); void sw_Skin_SetupSkin (skin_t *skin, int cmap);
@ -137,5 +141,6 @@ uint32_t glsl_Skin_Colormap (const colormap_t *colormap);
void gl_Skin_SetupSkin (skin_t *skin, int cmap); void gl_Skin_SetupSkin (skin_t *skin, int cmap);
void gl_Skin_Destroy (skin_t *skin); void gl_Skin_Destroy (skin_t *skin);
glskin_t gl_Skin_Get (const skin_t *skin, const colormap_t *colormap);
#endif// __mod_internal_h #endif// __mod_internal_h

View file

@ -41,6 +41,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "QF/cvar.h" #include "QF/cvar.h"
#include "QF/fbsearch.h"
#include "QF/image.h" #include "QF/image.h"
#include "QF/model.h" #include "QF/model.h"
#include "QF/skin.h" #include "QF/skin.h"
@ -54,11 +55,18 @@
#include "mod_internal.h" #include "mod_internal.h"
#include "r_internal.h" #include "r_internal.h"
// FIXME colormap (top/bottom colors) typedef struct {
//static byte skin_cmap[MAX_TRANSLATIONS][256]; const tex_t *tex;
glskin_t skin;
} skinpair_t;
#define MAX_GLSKINS 64
static skinpair_t skin_table[256][MAX_GLSKINS];
static int skin_counts[256];
static void static void
build_skin_8 (tex_t *tex, int texnum, byte *translate, build_skin_8 (const tex_t *tex, int texnum, byte *translate,
unsigned scaled_width, unsigned scaled_height, bool alpha) unsigned scaled_width, unsigned scaled_height, bool alpha)
{ {
// Improvements should be mirrored in GL_ResampleTexture in gl_textures.c // Improvements should be mirrored in GL_ResampleTexture in gl_textures.c
@ -84,7 +92,7 @@ build_skin_8 (tex_t *tex, int texnum, byte *translate,
} }
static void static void
build_skin_32 (tex_t *tex, int texnum, byte *translate, build_skin_32 (const tex_t *tex, int texnum, byte *translate,
unsigned scaled_width, unsigned scaled_height, bool alpha) unsigned scaled_width, unsigned scaled_height, bool alpha)
{ {
// Improvements should be mirrored in GL_ResampleTexture in gl_textures.c // Improvements should be mirrored in GL_ResampleTexture in gl_textures.c
@ -124,12 +132,40 @@ build_skin_32 (tex_t *tex, int texnum, byte *translate,
gl_aniso); gl_aniso);
} }
void static int
gl_Skin_SetupSkin (skin_t *skin, int cmap) skinpair_cmp (const void *_tex, const void *_skinpair)
{ {
//skin->tex = Skin_DupTex (skin->tex); const tex_t *tex = _tex;
tex_t *tex = skin->tex; const skinpair_t *skinpair = _skinpair;
skin->tex = nullptr; // tex memory is only temporarily allocated intptr_t diff = (intptr_t) tex - (intptr_t) skinpair->tex;
return diff < 0 ? -1 : diff > 0 ? 1 : 0;
}
glskin_t
gl_Skin_Get (const skin_t *skin, const colormap_t *colormap)
{
if (!skin || !colormap) {
return (glskin_t) {};
}
byte top = colormap->top & 0x0f;
byte bot = colormap->bottom & 0x0f;
int ind = top | (bot << 4);
skinpair_t *sp = fbsearch (skin->tex, skin_table[ind], skin_counts[ind],
sizeof (skinpair_t), skinpair_cmp);
if (sp && sp->tex == skin->tex) {
return sp->skin;
}
if (skin_counts[ind] == MAX_GLSKINS) {
return (glskin_t) {};
}
sp = sp ? sp + 1 : skin_table[ind];
int insert = sp - skin_table[ind];
memmove (&skin_table[ind][insert + 1], &skin_table[ind][insert],
sizeof (skinpair_t[skin_counts[ind] - insert]));
skin_counts[ind]++;
sp->tex = skin->tex;
auto build_skin = vid.is8bit ? build_skin_8 : build_skin_32; auto build_skin = vid.is8bit ? build_skin_8 : build_skin_32;
@ -141,24 +177,43 @@ gl_Skin_SetupSkin (skin_t *skin, int cmap)
swidth = max (swidth, 1); swidth = max (swidth, 1);
sheight = max (sheight, 1); sheight = max (sheight, 1);
int size = tex->width * tex->height; byte palette[256];
Skin_SetPalette (palette, top, bot);
qfglGenTextures (1, &sp->skin.id);
build_skin_32 (sp->tex, sp->skin.id, palette, swidth, sheight, false);
int size = sp->tex->width * sp->tex->height;
byte fbskin[size]; byte fbskin[size];
qfglGenTextures (1, &skin->id); if (Mod_CalcFullbright (fbskin, skin->tex->data, size)) {
// FIXME colormap (top/bottom colors) tex_t fb_tex = *sp->tex;
build_skin_32 (tex, skin->id, vid.colormap8, swidth, sheight, false);
if (Mod_CalcFullbright (fbskin, tex->data, size)) {
tex_t fb_tex = *tex;
fb_tex.data = fbskin; fb_tex.data = fbskin;
qfglGenTextures (1, &skin->fb); qfglGenTextures (1, &sp->skin.fb);
build_skin (&fb_tex, skin->fb, vid.colormap8, swidth, sheight, true); build_skin (&fb_tex, sp->skin.fb, palette, swidth, sheight, true);
} }
return sp->skin;
}
void
gl_Skin_SetupSkin (skin_t *skin, int cmap)
{
skin->tex = Skin_DupTex (skin->tex);
} }
void void
gl_Skin_Destroy (skin_t *skin) gl_Skin_Destroy (skin_t *skin)
{ {
qfglDeleteTextures (1, &skin->id); for (int i = 0; i < 256; i++) {
if (skin->fb) { for (int j = skin_counts[i]; j-- > 0; ) {
qfglDeleteTextures (1, &skin->fb); auto sp = &skin_table[i][j];
if (sp->tex == skin->tex) {
qfglDeleteTextures (1, &sp->skin.id);
if (sp->skin.fb) {
qfglDeleteTextures (1, &sp->skin.fb);
}
skin_counts[i]--;
memmove (&skin_table[i][j], &skin_table[i][j + 1],
sizeof (skinpair_t[skin_counts[i] - j]));
}
}
} }
} }

View file

@ -558,14 +558,14 @@ gl_R_DrawAliasModel (entity_t e)
// if the model has a colorised/external skin, use it, otherwise use // if the model has a colorised/external skin, use it, otherwise use
// the skin embedded in the model data // the skin embedded in the model data
if (renderer->skin && !gl_nocolors) { if (!gl_nocolors) {
skin_t *skin = Skin_Get (renderer->skin); skin_t *skin = renderer->skin ? Skin_Get (renderer->skin) : nullptr;
auto colormap = Entity_GetColormap (e);
auto glskin = gl_Skin_Get (skin, colormap);
if (skin) { if (glskin.id) {
texture = skin->id; texture = glskin.id;
if (gl_fb_models) { fb_texture = glskin.fb;
fb_texture = skin->fb;
}
} }
} }
if (!texture) { if (!texture) {
@ -574,9 +574,10 @@ gl_R_DrawAliasModel (entity_t e)
e.reg); e.reg);
skindesc = R_AliasGetSkindesc (animation, renderer->skinnum, paliashdr); skindesc = R_AliasGetSkindesc (animation, renderer->skinnum, paliashdr);
texture = skindesc->texnum; texture = skindesc->texnum;
if (gl_fb_models && !is_fullbright) { fb_texture = skindesc->fb_texnum;
fb_texture = skindesc->fb_texnum; }
} if (!gl_fb_models || is_fullbright) {
fb_texture = 0;
} }
if (paliashdr->mdl.ident == HEADER_MDL16) { if (paliashdr->mdl.ident == HEADER_MDL16) {