[vulkan] Implement very basic lighting for forward

Both alias and iqm (yay unified fragment shader). It's meh, but that's
1996 tech for you (hey, it was full-on 3d and we liked it!).
This commit is contained in:
Bill Currie 2024-01-20 14:42:21 +09:00
parent b22f104163
commit 8bf688748c
4 changed files with 249 additions and 54 deletions

View file

@ -338,7 +338,14 @@ properties = {
descriptorSets = (matrix_set, texture_set, texture_set); descriptorSets = (matrix_set, texture_set, texture_set);
pushConstants = { pushConstants = {
vertex = { Model = mat4; blend = float; }; vertex = { Model = mat4; blend = float; };
fragment = { colors = uint; base_color = vec4; fog = vec4; }; fragment = {
colors = uint;
ambient = float;
shadelight = float;
lightvec = vec4;
base_color = vec4;
fog = vec4;
};
}; };
}; };
}; };
@ -396,7 +403,14 @@ properties = {
descriptorSets = (matrix_set, texture_set, texture_set, bone_set); descriptorSets = (matrix_set, texture_set, texture_set, bone_set);
pushConstants = { pushConstants = {
vertex = { Model = mat4; blend = float; }; vertex = { Model = mat4; blend = float; };
fragment = { colors = uint; base_color = vec4; fog = vec4; }; fragment = {
colors = uint;
ambient = float;
shadelight = float;
lightvec = vec4;
base_color = vec4;
fog = vec4;
};
}; };
}; };
}; };
@ -1113,7 +1127,7 @@ renderpasses = {
color = $color.alias; color = $color.alias;
tasks = ( tasks = (
{ func = alias_draw; { func = alias_draw;
params = (main, 1); }, params = (main, 2); },
); );
stages = ( stages = (
@ -1128,7 +1142,7 @@ renderpasses = {
color = $color.iqm; color = $color.iqm;
tasks = ( tasks = (
{ func = iqm_draw; { func = iqm_draw;
params = (1); }, params = (2); },
); );
stages = ( stages = (

View file

@ -6,6 +6,9 @@ layout (set = 2, binding = 0) uniform sampler2DArray Skin;
layout (push_constant) uniform PushConstants { layout (push_constant) uniform PushConstants {
layout (offset = 68) layout (offset = 68)
uint colors; uint colors;
float ambient;
float shadelight;
vec4 lightvec;
vec4 base_color; vec4 base_color;
vec4 fog; vec4 fog;
}; };
@ -26,5 +29,11 @@ main (void)
c += texture (Palette, vec2 (cmap.x, rows.x)) * cmap.y; c += texture (Palette, vec2 (cmap.x, rows.x)) * cmap.y;
c += texture (Palette, vec2 (cmap.z, rows.y)) * cmap.w; c += texture (Palette, vec2 (cmap.z, rows.y)) * cmap.w;
frag_color = c + e;//fogBlend (c); float light = ambient;
float d = dot (normal, lightvec.xyz);
d = min (d, 0.0);
light -= d * shadelight;
light = max (light, 0.0) / 255;
frag_color = light * c + e;//fogBlend (c);
} }

View file

@ -52,6 +52,7 @@
#include "mod_internal.h" #include "mod_internal.h"
#include "r_internal.h" #include "r_internal.h"
#include "r_local.h"
#include "vid_vulkan.h" #include "vid_vulkan.h"
typedef struct { typedef struct {
@ -62,6 +63,17 @@ typedef struct {
vec4f_t fog; vec4f_t fog;
} alias_push_constants_t; } alias_push_constants_t;
typedef struct {
mat4f_t mat;
float blend;
byte colors[4];
float ambient;
float shadelight;
vec4f_t lightvec;
vec4f_t base_color;
vec4f_t fog;
} fwd_push_constants_t;
typedef struct { typedef struct {
mat4f_t mat; mat4f_t mat;
float blend; float blend;
@ -132,6 +144,54 @@ push_alias_constants (const mat4f_t mat, float blend, byte *colors,
QFV_PushConstants (device, cmd, layout, pass ? 5 : 2, push_constants); QFV_PushConstants (device, cmd, layout, pass ? 5 : 2, push_constants);
} }
static void
push_fwd_constants (const mat4f_t mat, float blend, byte *colors,
vec4f_t base_color, const alight_t *lighting,
int pass, qfv_taskctx_t *taskctx)
{
auto ctx = taskctx->ctx;
auto device = ctx->device;
auto cmd = taskctx->cmd;
auto layout = taskctx->pipeline->layout;
fwd_push_constants_t constants = {
.blend = blend,
.colors = { VEC4_EXP (colors) },
.ambient = lighting->ambientlight,
.shadelight = lighting->shadelight,
.lightvec = { VectorExpand (lighting->lightvec) },
.base_color = base_color,
};
qfv_push_constants_t push_constants[] = {
{ VK_SHADER_STAGE_VERTEX_BIT,
field_offset (fwd_push_constants_t, mat),
sizeof (mat4f_t), mat },
{ VK_SHADER_STAGE_VERTEX_BIT,
field_offset (fwd_push_constants_t, blend),
sizeof (float), &constants.blend },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (fwd_push_constants_t, colors),
sizeof (constants.colors), constants.colors },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (fwd_push_constants_t, ambient),
sizeof (constants.ambient), &constants.ambient },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (fwd_push_constants_t, shadelight),
sizeof (constants.shadelight), &constants.shadelight },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (fwd_push_constants_t, lightvec),
sizeof (constants.lightvec), &constants.lightvec },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (fwd_push_constants_t, base_color),
sizeof (constants.base_color), &constants.base_color },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (fwd_push_constants_t, fog),
sizeof (constants.fog), &constants.fog },
};
QFV_PushConstants (device, cmd, layout, 8, push_constants);
}
static void static void
push_shadow_constants (const mat4f_t mat, float blend, uint16_t *matrix_base, push_shadow_constants (const mat4f_t mat, float blend, uint16_t *matrix_base,
qfv_taskctx_t *taskctx) qfv_taskctx_t *taskctx)
@ -161,7 +221,7 @@ push_shadow_constants (const mat4f_t mat, float blend, uint16_t *matrix_base,
} }
static void static void
alias_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass, alias_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, int pass,
renderer_t *renderer) renderer_t *renderer)
{ {
auto model = renderer->model; auto model = renderer->model;
@ -190,8 +250,9 @@ 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] = {};
QuatCopy (renderer->colormod, base_color); QuatCopy (renderer->colormod, base_color);
byte colors[4] = {};
QuatCopy (skin->colors, colors); QuatCopy (skin->colors, colors);
auto colormap = Entity_GetColormap (ent); auto colormap = Entity_GetColormap (ent);
if (colormap) { if (colormap) {
@ -235,8 +296,16 @@ alias_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass,
push_shadow_constants (Transform_GetWorldMatrixPtr (transform), push_shadow_constants (Transform_GetWorldMatrixPtr (transform),
blend, matrix_base, taskctx); blend, matrix_base, taskctx);
} else { } else {
push_alias_constants (Transform_GetWorldMatrixPtr (transform), if (pass > 1) {
blend, colors, base_color, pass, taskctx); alight_t lighting;
R_Setup_Lighting (ent, &lighting);
push_fwd_constants (Transform_GetWorldMatrixPtr (transform),
blend, colors, base_color, &lighting,
pass, taskctx);
} else {
push_alias_constants (Transform_GetWorldMatrixPtr (transform),
blend, colors, base_color, pass, taskctx);
}
} }
dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0); dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0);
QFV_CmdEndLabel (device, cmd); QFV_CmdEndLabel (device, cmd);

View file

@ -57,16 +57,31 @@
typedef struct { typedef struct {
mat4f_t mat; mat4f_t mat;
float blend; float blend;
uint32_t matrix_base;
byte colors[4]; byte colors[4];
vec4f_t base_color; vec4f_t base_color;
vec4f_t fog; vec4f_t fog;
} iqm_push_constants_t; } iqm_push_constants_t;
typedef struct {
mat4f_t mat;
float blend;
byte colors[4];
float ambient;
float shadelight;
vec4f_t lightvec;
vec4f_t base_color;
vec4f_t fog;
} fwd_push_constants_t;
typedef struct {
mat4f_t mat;
float blend;
uint32_t matrix_base;
} shadow_push_constants_t;
static void static void
emit_commands (VkCommandBuffer cmd, int pose1, int pose2, emit_commands (VkCommandBuffer cmd, int pose1, int pose2,
qfv_iqm_skin_t *skins, qfv_iqm_skin_t *skins,
uint32_t numPC, qfv_push_constants_t *constants,
iqm_t *iqm, qfv_taskctx_t *taskctx, entity_t ent) iqm_t *iqm, qfv_taskctx_t *taskctx, entity_t ent)
{ {
auto ctx = taskctx->ctx; auto ctx = taskctx->ctx;
@ -89,7 +104,6 @@ emit_commands (VkCommandBuffer cmd, int pose1, int pose2,
VkIndexType indexType = iqm->num_verts > 0xfff0 ? VK_INDEX_TYPE_UINT32 VkIndexType indexType = iqm->num_verts > 0xfff0 ? VK_INDEX_TYPE_UINT32
: VK_INDEX_TYPE_UINT16; : VK_INDEX_TYPE_UINT16;
dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, indexType); dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, indexType);
QFV_PushConstants (device, cmd, layout, numPC, constants);
for (int i = 0; i < iqm->num_meshes; i++) { for (int i = 0; i < iqm->num_meshes; i++) {
if (skins) { if (skins) {
VkDescriptorSet sets[] = { VkDescriptorSet sets[] = {
@ -187,7 +201,118 @@ Vulkan_IQMRemoveSkin (vulkan_ctx_t *ctx, qfv_iqm_skin_t *skin)
} }
static void static void
iqm_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass, bool shadow) push_iqm_constants (const mat4f_t mat, float blend, byte *colors,
vec4f_t base_color, int pass, qfv_taskctx_t *taskctx)
{
auto ctx = taskctx->ctx;
auto device = ctx->device;
auto cmd = taskctx->cmd;
auto layout = taskctx->pipeline->layout;
iqm_push_constants_t constants = {
.blend = blend,
.colors = { VEC4_EXP (colors) },
.base_color = base_color,
};
qfv_push_constants_t push_constants[] = {
{ VK_SHADER_STAGE_VERTEX_BIT,
field_offset (iqm_push_constants_t, mat),
sizeof (mat4f_t), mat },
{ VK_SHADER_STAGE_VERTEX_BIT,
field_offset (iqm_push_constants_t, blend),
sizeof (float), &constants.blend },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
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 },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (iqm_push_constants_t, fog),
sizeof (constants.fog), &constants.fog },
};
QFV_PushConstants (device, cmd, layout, pass ? 5 : 2, push_constants);
}
static void
push_fwd_constants (const mat4f_t mat, float blend, byte *colors,
vec4f_t base_color, const alight_t *lighting,
int pass, qfv_taskctx_t *taskctx)
{
auto ctx = taskctx->ctx;
auto device = ctx->device;
auto cmd = taskctx->cmd;
auto layout = taskctx->pipeline->layout;
fwd_push_constants_t constants = {
.blend = blend,
.colors = { VEC4_EXP (colors) },
.ambient = lighting->ambientlight,
.shadelight = lighting->shadelight,
.lightvec = { VectorExpand (lighting->lightvec) },
.base_color = base_color,
};
qfv_push_constants_t push_constants[] = {
{ VK_SHADER_STAGE_VERTEX_BIT,
field_offset (fwd_push_constants_t, mat),
sizeof (mat4f_t), mat },
{ VK_SHADER_STAGE_VERTEX_BIT,
field_offset (fwd_push_constants_t, blend),
sizeof (float), &constants.blend },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (fwd_push_constants_t, colors),
sizeof (constants.colors), constants.colors },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (fwd_push_constants_t, ambient),
sizeof (constants.ambient), &constants.ambient },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (fwd_push_constants_t, shadelight),
sizeof (constants.shadelight), &constants.shadelight },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (fwd_push_constants_t, lightvec),
sizeof (constants.lightvec), &constants.lightvec },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (fwd_push_constants_t, base_color),
sizeof (constants.base_color), &constants.base_color },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (fwd_push_constants_t, fog),
sizeof (constants.fog), &constants.fog },
};
QFV_PushConstants (device, cmd, layout, 8, push_constants);
}
static void
push_shadow_constants (const mat4f_t mat, float blend, uint16_t *matrix_base,
qfv_taskctx_t *taskctx)
{
auto ctx = taskctx->ctx;
auto device = ctx->device;
auto cmd = taskctx->cmd;
auto layout = taskctx->pipeline->layout;
shadow_push_constants_t constants = {
.blend = blend,
.matrix_base = *matrix_base,
};
qfv_push_constants_t push_constants[] = {
{ VK_SHADER_STAGE_VERTEX_BIT,
field_offset (shadow_push_constants_t, mat),
sizeof (mat4f_t), mat },
{ VK_SHADER_STAGE_VERTEX_BIT,
field_offset (shadow_push_constants_t, blend),
sizeof (float), &constants.blend },
{ VK_SHADER_STAGE_VERTEX_BIT,
field_offset (shadow_push_constants_t, matrix_base),
sizeof (uint32_t), &constants.matrix_base },
};
QFV_PushConstants (device, cmd, layout, 3, push_constants);
}
static void
iqm_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, int pass, bool shadow)
{ {
auto ctx = taskctx->ctx; auto ctx = taskctx->ctx;
auto device = ctx->device; auto device = ctx->device;
@ -200,6 +325,9 @@ iqm_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass, bool shadow)
iqmframe_t *frame; iqmframe_t *frame;
uint16_t *matrix_base = taskctx->data; uint16_t *matrix_base = taskctx->data;
vec4f_t base_color;
QuatCopy (renderer->colormod, base_color);
byte colors[4] = {}; byte colors[4] = {};
auto colormap = Entity_GetColormap (ent); auto colormap = Entity_GetColormap (ent);
if (colormap) { if (colormap) {
@ -208,14 +336,9 @@ iqm_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass, bool shadow)
} }
auto animation = Entity_GetAnimation (ent); auto animation = Entity_GetAnimation (ent);
iqm_push_constants_t constants = { float blend = R_IQMGetLerpedFrames (animation, iqm);
.blend = R_IQMGetLerpedFrames (animation, iqm),
.matrix_base = matrix_base ? *matrix_base : 0,
.colors = { VEC4_EXP (colors) },
.base_color = { VEC4_EXP (renderer->colormod) },
};
frame = R_IQMBlendFrames (iqm, animation->pose1, animation->pose2, frame = R_IQMBlendFrames (iqm, animation->pose1, animation->pose2,
constants.blend, 0); blend, 0);
vec4f_t *bone_data; vec4f_t *bone_data;
dfunc->vkMapMemory (device->dev, mesh->bones->memory, 0, VK_WHOLE_SIZE, dfunc->vkMapMemory (device->dev, mesh->bones->memory, 0, VK_WHOLE_SIZE,
@ -243,43 +366,23 @@ iqm_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass, bool shadow)
transform_t transform = Entity_Transform (ent); transform_t transform = Entity_Transform (ent);
if (shadow) { if (shadow) {
qfv_push_constants_t push_constants[] = { push_shadow_constants (Transform_GetWorldMatrixPtr (transform),
{ VK_SHADER_STAGE_VERTEX_BIT, blend, matrix_base, taskctx);
field_offset (iqm_push_constants_t, mat),
sizeof (mat4f_t), Transform_GetWorldMatrixPtr (transform) },
{ VK_SHADER_STAGE_VERTEX_BIT,
field_offset (iqm_push_constants_t, blend),
sizeof (float), &constants.blend },
{ VK_SHADER_STAGE_VERTEX_BIT,
field_offset (iqm_push_constants_t, matrix_base),
sizeof (uint32_t), &constants.matrix_base },
};
emit_commands (taskctx->cmd, animation->pose1, animation->pose2, emit_commands (taskctx->cmd, animation->pose1, animation->pose2,
nullptr, 3, push_constants, iqm, taskctx, ent); nullptr, iqm, taskctx, ent);
} else { } else {
qfv_push_constants_t push_constants[] = { if (pass > 1) {
{ VK_SHADER_STAGE_VERTEX_BIT, alight_t lighting;
field_offset (iqm_push_constants_t, mat), R_Setup_Lighting (ent, &lighting);
sizeof (mat4f_t), Transform_GetWorldMatrixPtr (transform) }, push_fwd_constants (Transform_GetWorldMatrixPtr (transform),
{ VK_SHADER_STAGE_VERTEX_BIT, blend, colors, base_color, &lighting,
field_offset (iqm_push_constants_t, blend), pass, taskctx);
sizeof (float), &constants.blend }, } else {
{ VK_SHADER_STAGE_FRAGMENT_BIT, push_iqm_constants (Transform_GetWorldMatrixPtr (transform),
field_offset (iqm_push_constants_t, colors), blend, colors, base_color, pass, taskctx);
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 },
{ VK_SHADER_STAGE_FRAGMENT_BIT,
field_offset (iqm_push_constants_t, fog),
sizeof (constants.fog), &constants.fog },
};
emit_commands (taskctx->cmd, animation->pose1, animation->pose2, emit_commands (taskctx->cmd, animation->pose1, animation->pose2,
pass ? skins : nullptr, pass ? skins : nullptr, iqm, taskctx, ent);
pass ? 5 : 2, push_constants,
iqm, taskctx, ent);
} }
} }