[iqm] Load skins correctly for qskin

Missing any possibility for fullbrights or colors (only because no
attempt is made to load such), and more deferred breakage, but it acted
as a nice proof of concept for cleaner skin loading (taking advantage of
resources and QFV_PacketCopyImage).
This commit is contained in:
Bill Currie 2024-01-20 01:03:56 +09:00
parent 99445758a3
commit fc5b1d5f6e
3 changed files with 33 additions and 47 deletions

View file

@ -100,17 +100,17 @@ vulkan_iqm_init_image (iqm_t *iqm, int meshnum, qfv_resobj_t *image)
dstring_copystr (str, material);
QFS_StripExtension (str->str, str->str);
tex_t dummy_tex;
tex_t dummy_tex = {
.width = 2,
.height = 2,
.format = tex_rgba,
};
tex_t *tex;
if (!(tex = LoadImage (va (0, "textures/%s", str->str), 0))) {
dummy_tex = (tex_t) {
.width = 2,
.height = 2,
.format = tex_rgba,
};
tex = &dummy_tex;
}
QFV_ResourceInitTexImage (image, material, 1, tex);
image->image.num_layers = 3;
dstring_delete (str);
}
@ -118,8 +118,6 @@ static void
iqm_transfer_texture (tex_t *tex, VkImage image, qfv_stagebuf_t *stage,
qfv_device_t *device)
{
qfv_devfuncs_t *dfunc = device->funcs;
if (tex->format != tex_rgb && tex->format != tex_rgba) {
Sys_Error ("can't transfer iqm image");
}
@ -127,37 +125,21 @@ iqm_transfer_texture (tex_t *tex, VkImage image, qfv_stagebuf_t *stage,
size_t layer_size = tex->width * tex->height * tex->format;
qfv_packet_t *packet = QFV_PacketAcquire (stage);
byte *dst = QFV_PacketExtend (packet, layer_size);
byte *dst = QFV_PacketExtend (packet, layer_size * 3);
qfv_imagebarrier_t ib = imageBarriers[qfv_LT_Undefined_to_TransferDst];
ib.barrier.image = image;
ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages,
0, 0, 0, 0, 0,
1, &ib.barrier);
memcpy (dst, tex->data, layer_size);
VkBufferImageCopy copy = {
packet->offset, 0, 0,
{VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1},
{0, 0, 0}, {tex->width, tex->height, 1},
};
dfunc->vkCmdCopyBufferToImage (packet->cmd, packet->stage->buffer,
image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &copy);
// don't have glow/color maps yet
memset (dst + layer_size, 0, 2 * layer_size);
int mipLevels = QFV_MipLevels (tex->width, tex->height);
if (mipLevels == 1) {
ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly];
ib.barrier.image = image;
ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages,
0, 0, 0, 0, 0,
1, &ib.barrier);
} else {
int mipLevels = QFV_MipLevels (tex->width, tex->height);
auto ib = mipLevels == 1
? &imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]
: nullptr;
QFV_PacketCopyImage (packet, image, tex->width, tex->height, ib);
if (mipLevels != 1) {
QFV_GenerateMipMaps (device, packet->cmd, image, mipLevels,
tex->width, tex->height, 1);
tex->width, tex->height, 3);
}
QFV_PacketSubmit (packet);
}
@ -444,7 +426,7 @@ Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx)
.type = qfv_res_image_view,
.image_view = {
.image = image_ind,
.type = VK_IMAGE_VIEW_TYPE_2D,
.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY,
.format = mesh->mesh->objects[image_ind].image.format,
.subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,

View file

@ -190,7 +190,7 @@ alias_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass,
skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin);
}
vec4f_t base_color;
byte colors[4];
byte colors[4] = {};
QuatCopy (renderer->colormod, base_color);
QuatCopy (skin->colors, colors);
auto colormap = Entity_GetColormap (ent);

View file

@ -58,8 +58,7 @@ typedef struct {
mat4f_t mat;
float blend;
uint32_t matrix_base;
byte colorA[4];
byte colorB[4];
byte colors[4];
vec4f_t base_color;
vec4f_t fog;
} iqm_push_constants_t;
@ -201,12 +200,18 @@ iqm_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass)
iqmframe_t *frame;
uint16_t *matrix_base = taskctx->data;
byte colors[4] = {};
auto colormap = Entity_GetColormap (ent);
if (colormap) {
colors[0] = colormap->top * 16 + 8;
colors[1] = colormap->bottom * 16 + 8;
}
auto animation = Entity_GetAnimation (ent);
iqm_push_constants_t constants = {
.blend = R_IQMGetLerpedFrames (animation, iqm),
.matrix_base = matrix_base ? *matrix_base : 0,
.colorA = { VEC4_EXP (skins[0].colora) },
.colorB = { VEC4_EXP (skins[0].colorb) },
.colors = { VEC4_EXP (colors) },
.base_color = { VEC4_EXP (renderer->colormod) },
};
frame = R_IQMBlendFrames (iqm, animation->pose1, animation->pose2,
@ -244,15 +249,14 @@ iqm_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass)
{ VK_SHADER_STAGE_VERTEX_BIT,
field_offset (iqm_push_constants_t, blend),
sizeof (float), &constants.blend },
#if 0
{ VK_SHADER_STAGE_VERTEX_BIT,
field_offset (iqm_push_constants_t, matrix_base),
sizeof (uint32_t), &constants.matrix_base },
#endif
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (iqm_push_constants_t, colorA),
sizeof (constants.colorA), constants.colorA },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (iqm_push_constants_t, colorB),
sizeof (constants.colorB), constants.colorB },
field_offset (iqm_push_constants_t, colors),
sizeof (constants.colors), constants.colors },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (iqm_push_constants_t, base_color),
sizeof (constants.base_color), &constants.base_color },
@ -263,7 +267,7 @@ iqm_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass)
emit_commands (taskctx->cmd, animation->pose1, animation->pose2,
pass ? skins : 0,
pass ? 7 : 3, push_constants,
pass ? 5 : 3, push_constants,
iqm, taskctx, ent);
}