[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);
pushConstants = {
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);
pushConstants = {
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;
tasks = (
{ func = alias_draw;
params = (main, 1); },
params = (main, 2); },
);
stages = (
@ -1128,7 +1142,7 @@ renderpasses = {
color = $color.iqm;
tasks = (
{ func = iqm_draw;
params = (1); },
params = (2); },
);
stages = (

View file

@ -6,6 +6,9 @@ layout (set = 2, binding = 0) uniform sampler2DArray Skin;
layout (push_constant) uniform PushConstants {
layout (offset = 68)
uint colors;
float ambient;
float shadelight;
vec4 lightvec;
vec4 base_color;
vec4 fog;
};
@ -26,5 +29,11 @@ main (void)
c += texture (Palette, vec2 (cmap.x, rows.x)) * cmap.y;
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 "r_internal.h"
#include "r_local.h"
#include "vid_vulkan.h"
typedef struct {
@ -62,6 +63,17 @@ typedef struct {
vec4f_t fog;
} 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 {
mat4f_t mat;
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);
}
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)
@ -161,7 +221,7 @@ push_shadow_constants (const mat4f_t mat, float blend, uint16_t *matrix_base,
}
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)
{
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);
}
vec4f_t base_color;
byte colors[4] = {};
QuatCopy (renderer->colormod, base_color);
byte colors[4] = {};
QuatCopy (skin->colors, colors);
auto colormap = Entity_GetColormap (ent);
if (colormap) {
@ -235,8 +296,16 @@ alias_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass,
push_shadow_constants (Transform_GetWorldMatrixPtr (transform),
blend, matrix_base, taskctx);
} else {
push_alias_constants (Transform_GetWorldMatrixPtr (transform),
blend, colors, base_color, pass, taskctx);
if (pass > 1) {
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);
QFV_CmdEndLabel (device, cmd);

View file

@ -57,16 +57,31 @@
typedef struct {
mat4f_t mat;
float blend;
uint32_t matrix_base;
byte colors[4];
vec4f_t base_color;
vec4f_t fog;
} 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
emit_commands (VkCommandBuffer cmd, int pose1, int pose2,
qfv_iqm_skin_t *skins,
uint32_t numPC, qfv_push_constants_t *constants,
iqm_t *iqm, qfv_taskctx_t *taskctx, entity_t ent)
{
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
: VK_INDEX_TYPE_UINT16;
dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0, indexType);
QFV_PushConstants (device, cmd, layout, numPC, constants);
for (int i = 0; i < iqm->num_meshes; i++) {
if (skins) {
VkDescriptorSet sets[] = {
@ -187,7 +201,118 @@ Vulkan_IQMRemoveSkin (vulkan_ctx_t *ctx, qfv_iqm_skin_t *skin)
}
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 device = ctx->device;
@ -200,6 +325,9 @@ iqm_draw_ent (qfv_taskctx_t *taskctx, entity_t ent, bool pass, bool shadow)
iqmframe_t *frame;
uint16_t *matrix_base = taskctx->data;
vec4f_t base_color;
QuatCopy (renderer->colormod, base_color);
byte colors[4] = {};
auto colormap = Entity_GetColormap (ent);
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);
iqm_push_constants_t constants = {
.blend = R_IQMGetLerpedFrames (animation, iqm),
.matrix_base = matrix_base ? *matrix_base : 0,
.colors = { VEC4_EXP (colors) },
.base_color = { VEC4_EXP (renderer->colormod) },
};
float blend = R_IQMGetLerpedFrames (animation, iqm);
frame = R_IQMBlendFrames (iqm, animation->pose1, animation->pose2,
constants.blend, 0);
blend, 0);
vec4f_t *bone_data;
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);
if (shadow) {
qfv_push_constants_t push_constants[] = {
{ VK_SHADER_STAGE_VERTEX_BIT,
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 },
};
push_shadow_constants (Transform_GetWorldMatrixPtr (transform),
blend, matrix_base, taskctx);
emit_commands (taskctx->cmd, animation->pose1, animation->pose2,
nullptr, 3, push_constants, iqm, taskctx, ent);
nullptr, iqm, taskctx, ent);
} else {
qfv_push_constants_t push_constants[] = {
{ VK_SHADER_STAGE_VERTEX_BIT,
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_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 },
};
if (pass > 1) {
alight_t lighting;
R_Setup_Lighting (ent, &lighting);
push_fwd_constants (Transform_GetWorldMatrixPtr (transform),
blend, colors, base_color, &lighting,
pass, taskctx);
} else {
push_iqm_constants (Transform_GetWorldMatrixPtr (transform),
blend, colors, base_color, pass, taskctx);
}
emit_commands (taskctx->cmd, animation->pose1, animation->pose2,
pass ? skins : nullptr,
pass ? 5 : 2, push_constants,
iqm, taskctx, ent);
pass ? skins : nullptr, iqm, taskctx, ent);
}
}