[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); dstring_copystr (str, material);
QFS_StripExtension (str->str, str->str); QFS_StripExtension (str->str, str->str);
tex_t dummy_tex; tex_t dummy_tex = {
.width = 2,
.height = 2,
.format = tex_rgba,
};
tex_t *tex; tex_t *tex;
if (!(tex = LoadImage (va (0, "textures/%s", str->str), 0))) { if (!(tex = LoadImage (va (0, "textures/%s", str->str), 0))) {
dummy_tex = (tex_t) {
.width = 2,
.height = 2,
.format = tex_rgba,
};
tex = &dummy_tex; tex = &dummy_tex;
} }
QFV_ResourceInitTexImage (image, material, 1, tex); QFV_ResourceInitTexImage (image, material, 1, tex);
image->image.num_layers = 3;
dstring_delete (str); dstring_delete (str);
} }
@ -118,8 +118,6 @@ static void
iqm_transfer_texture (tex_t *tex, VkImage image, qfv_stagebuf_t *stage, iqm_transfer_texture (tex_t *tex, VkImage image, qfv_stagebuf_t *stage,
qfv_device_t *device) qfv_device_t *device)
{ {
qfv_devfuncs_t *dfunc = device->funcs;
if (tex->format != tex_rgb && tex->format != tex_rgba) { if (tex->format != tex_rgb && tex->format != tex_rgba) {
Sys_Error ("can't transfer iqm image"); 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; size_t layer_size = tex->width * tex->height * tex->format;
qfv_packet_t *packet = QFV_PacketAcquire (stage); 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); memcpy (dst, tex->data, layer_size);
VkBufferImageCopy copy = { // don't have glow/color maps yet
packet->offset, 0, 0, memset (dst + layer_size, 0, 2 * layer_size);
{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);
int mipLevels = QFV_MipLevels (tex->width, tex->height); int mipLevels = QFV_MipLevels (tex->width, tex->height);
if (mipLevels == 1) { auto ib = mipLevels == 1
ib = imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]; ? &imageBarriers[qfv_LT_TransferDst_to_ShaderReadOnly]
ib.barrier.image = image; : nullptr;
ib.barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS; QFV_PacketCopyImage (packet, image, tex->width, tex->height, ib);
ib.barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
dfunc->vkCmdPipelineBarrier (packet->cmd, ib.srcStages, ib.dstStages, if (mipLevels != 1) {
0, 0, 0, 0, 0,
1, &ib.barrier);
} else {
QFV_GenerateMipMaps (device, packet->cmd, image, mipLevels, QFV_GenerateMipMaps (device, packet->cmd, image, mipLevels,
tex->width, tex->height, 1); tex->width, tex->height, 3);
} }
QFV_PacketSubmit (packet); QFV_PacketSubmit (packet);
} }
@ -444,7 +426,7 @@ Vulkan_Mod_IQMFinish (model_t *mod, vulkan_ctx_t *ctx)
.type = qfv_res_image_view, .type = qfv_res_image_view,
.image_view = { .image_view = {
.image = image_ind, .image = image_ind,
.type = VK_IMAGE_VIEW_TYPE_2D, .type = VK_IMAGE_VIEW_TYPE_2D_ARRAY,
.format = mesh->mesh->objects[image_ind].image.format, .format = mesh->mesh->objects[image_ind].image.format,
.subresourceRange = { .subresourceRange = {
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .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); skin = (qfv_alias_skin_t *) ((byte *) hdr + skindesc->skin);
} }
vec4f_t base_color; vec4f_t base_color;
byte colors[4]; byte colors[4] = {};
QuatCopy (renderer->colormod, base_color); QuatCopy (renderer->colormod, base_color);
QuatCopy (skin->colors, colors); QuatCopy (skin->colors, colors);
auto colormap = Entity_GetColormap (ent); auto colormap = Entity_GetColormap (ent);

View file

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