[vulkan] Use palette lookups for top/bottom colors

As the RGB curves for many of the color rows are not linearly related,
my idea of scaling the brightest color in the row just didn't work.
Using a masked palette lookup works much better as it allows any curves.
Also, because the palette is uploaded as a grid and the coordinates are
calculated on the CPU, the system is extendable beyond 8-bit palettes.

This isn't quite complete as the top and bottom colors are still in
separate layers but their indices and masks can fit in just one, but
this requires reworking the texture setup (for another commit).
This commit is contained in:
Bill Currie 2022-11-15 11:47:28 +09:00
parent 4d7f72948d
commit 668f7f2cd2
7 changed files with 54 additions and 24 deletions

View file

@ -58,8 +58,7 @@ typedef struct qfv_alias_skin_s {
VkDeviceMemory memory;
VkImage image;
VkImageView view;
byte colora[4];
byte colorb[4];
byte colors[4];
VkDescriptorSet descriptor;
} qfv_alias_skin_t;

View file

@ -38,6 +38,7 @@
typedef struct palettectx_s {
struct qfv_tex_s *palette;
VkSampler sampler;
VkDescriptorSet descriptor;
} palettectx_t;
struct vulkan_ctx_s;
@ -45,5 +46,6 @@ struct vulkan_ctx_s;
void Vulkan_Palette_Update (struct vulkan_ctx_s *ctx, const byte *palette);
void Vulkan_Palette_Init (struct vulkan_ctx_s *ctx, const byte *palette);
void Vulkan_Palette_Shutdown (struct vulkan_ctx_s *ctx);
VkDescriptorSet Vulkan_Palette_Descriptor (struct vulkan_ctx_s *ctx) __attribute__((pure));
#endif//__QF_Vulkan_qf_palette_h

View file

@ -125,8 +125,7 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize,
int w, h;
skin = Hunk_Alloc (0, sizeof (qfv_alias_skin_t));
QuatCopy (vid.palette32 + (TOP_RANGE + 15) * 4, skin->colora);
QuatCopy (vid.palette32 + (BOTTOM_RANGE + 15) * 4, skin->colorb);
QuatSet (TOP_RANGE + 7, BOTTOM_RANGE + 7, 0, 0, skin->colors);
skindesc->skin = (byte *) skin - (byte *) header;
//FIXME move all skins into arrays(?)
w = header->mdl.skinwidth;
@ -175,13 +174,31 @@ Vulkan_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *skinpix, int skinsize,
skinsize);
Mod_ClearFullbright (tskin, tskin, skinsize);
static byte map_palette[] = {
0x08, 0x00, 0x00,
0x18, 0xff, 0x00,
0x28, 0xff, 0x00,
0x38, 0xff, 0x00,
0x48, 0xff, 0x00,
0x58, 0xff, 0x00,
0x68, 0xff, 0x00,
0x78, 0xff, 0x00,
0x88, 0xff, 0x00,
0x98, 0xff, 0x00,
0xa8, 0xff, 0x00,
0xb8, 0xff, 0x00,
0xc8, 0xff, 0x00,
0xd8, 0xff, 0x00,
0xe8, 0xff, 0x00,
0xf8, 0xff, 0x00,
};
Skin_CalcTopColors (tskin + skinsize, tskin, skinsize);
Vulkan_ExpandPalette (cola_data, tskin + skinsize, vid.palette, 1,
Vulkan_ExpandPalette (cola_data, tskin + skinsize, map_palette, 1,
skinsize);
Skin_ClearTopColors (tskin, tskin, skinsize);
Skin_CalcBottomColors (tskin + skinsize, tskin, skinsize);
Vulkan_ExpandPalette (colb_data, tskin + skinsize, vid.palette, 1,
Vulkan_ExpandPalette (colb_data, tskin + skinsize, map_palette, 1,
skinsize);
Skin_ClearBottomColors (tskin, tskin, skinsize);

View file

@ -426,7 +426,7 @@
);
};
alias_layout = {
setLayouts = (matrix_set, texture_set);
setLayouts = (matrix_set, texture_set, texture_set);
pushConstantRanges = (
{
stageFlags = vertex;

View file

@ -1,11 +1,11 @@
#version 450
layout (set = 1, binding = 0) uniform sampler2DArray Skin;
layout (set = 1, binding = 0) uniform sampler2D Palette;
layout (set = 2, binding = 0) uniform sampler2DArray Skin;
layout (push_constant) uniform PushConstants {
layout (offset = 68)
uint colorA;
uint colorB;
uint colors;
vec4 base_color;
vec4 fog;
};
@ -26,9 +26,14 @@ main (void)
vec4 e;
int i;
vec3 light = vec3 (0);
vec4 rows = unpackUnorm4x8(colors);
vec2 cols = vec2 (texture (Skin, vec3 (st, 1)).r,
texture (Skin, vec3 (st, 2)).r);
vec2 mask = vec2 (texture (Skin, vec3 (st, 1)).g,
texture (Skin, vec3 (st, 2)).g);
c = texture (Skin, vec3 (st, 0)) * base_color;
c += texture (Skin, vec3 (st, 1)) * unpackUnorm4x8(colorA) * 2;
c += texture (Skin, vec3 (st, 2)) * unpackUnorm4x8(colorB) * 2;
c += texture (Palette, vec2 (cols.x, rows.x)) * mask.x;
c += texture (Palette, vec2 (cols.y, rows.y)) * mask.y;
e = texture (Skin, vec3 (st, 3));
frag_color = c;

View file

@ -42,6 +42,7 @@
#include "QF/Vulkan/qf_alias.h"
#include "QF/Vulkan/qf_matrices.h"
#include "QF/Vulkan/qf_palette.h"
#include "QF/Vulkan/qf_renderpass.h"
#include "QF/Vulkan/qf_texture.h"
#include "QF/Vulkan/debug.h"
@ -54,8 +55,7 @@
typedef struct {
mat4f_t mat;
float blend;
byte colorA[4];
byte colorB[4];
byte colors[4];
vec4f_t base_color;
vec4f_t fog;
} alias_push_constants_t;
@ -108,7 +108,7 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2,
skin->descriptor,
};
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
actx->layout, 1, 1, sets, 0, 0);
actx->layout, 2, 1, sets, 0, 0);
}
dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0);
@ -144,11 +144,8 @@ Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame)
field_offset (alias_push_constants_t, blend),
sizeof (float), &constants.blend },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (alias_push_constants_t, colorA),
sizeof (constants.colorA), constants.colorA },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (alias_push_constants_t, colorB),
sizeof (constants.colorB), constants.colorB },
field_offset (alias_push_constants_t, colors),
sizeof (constants.colors), constants.colors },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (alias_push_constants_t, base_color),
sizeof (constants.base_color), &constants.base_color },
@ -165,8 +162,7 @@ Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame)
skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin);
}
QuatCopy (renderer->colormod, constants.base_color);
QuatCopy (skin->colora, constants.colorA);
QuatCopy (skin->colorb, constants.colorB);
QuatCopy (skin->colors, constants.colors);
QuatZero (constants.fog);
emit_commands (aframe->cmdSet.a[QFV_aliasDepth],
@ -174,7 +170,7 @@ Vulkan_DrawAlias (entity_t ent, qfv_renderframe_t *rFrame)
0, 2, push_constants, hdr, rFrame, ent);
emit_commands (aframe->cmdSet.a[QFV_aliasGBuffer],
animation->pose1, animation->pose2,
skin, 6, push_constants, hdr, rFrame, ent);
skin, 5, push_constants, hdr, rFrame, ent);
}
static void
@ -210,9 +206,10 @@ alias_begin_subpass (QFV_AliasSubpass subpass, VkPipeline pipeline,
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
VkDescriptorSet sets[] = {
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
Vulkan_Palette_Descriptor (ctx),
};
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
actx->layout, 0, 1, sets, 0, 0);
actx->layout, 0, 2, sets, 0, 0);
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);

View file

@ -78,6 +78,9 @@ Vulkan_Palette_Init (vulkan_ctx_t *ctx, const byte *palette)
.data = (byte *) palette,
};
pctx->palette = Vulkan_LoadTex (ctx, &tex, 0, "palette");
pctx->descriptor = Vulkan_CreateCombinedImageSampler (ctx,
pctx->palette->view,
pctx->sampler);
qfvPopDebug (ctx);
}
@ -94,3 +97,10 @@ Vulkan_Palette_Shutdown (vulkan_ctx_t *ctx)
qfvPopDebug (ctx);
}
VkDescriptorSet
Vulkan_Palette_Descriptor (struct vulkan_ctx_s *ctx)
{
__auto_type pctx = ctx->palette_context;
return pctx->descriptor;
}