mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-24 20:51:35 +00:00
[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:
parent
0539f07c1a
commit
346ed29f49
3 changed files with 92 additions and 31 deletions
|
@ -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
|
||||||
|
|
|
@ -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]));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue