mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-22 02:11:19 +00:00
[vulkan] Create shadow maps and basic data
I will definitely need to look into sparse images later (2.3GB for marcher) but the shadow map images, views and matrices are created.
This commit is contained in:
parent
562f3c2fe2
commit
1cf40be484
3 changed files with 342 additions and 37 deletions
|
@ -48,26 +48,43 @@ typedef struct qfv_light_s {
|
|||
} qfv_light_t;
|
||||
|
||||
typedef struct qfv_lightset_s DARRAY_TYPE (qfv_light_t) qfv_lightset_t;
|
||||
typedef struct qfv_lightleafset_s DARRAY_TYPE (int) qfv_lightleafset_t;
|
||||
typedef struct qfv_lightleafset_s DARRAY_TYPE (int) qfv_lightintset_t;
|
||||
typedef struct qfv_lightvisset_s DARRAY_TYPE (byte) qfv_lightvisset_t;
|
||||
typedef struct qfv_lightmatset_s DARRAY_TYPE (mat4f_t) qfv_lightmatset_t;
|
||||
|
||||
#define NUM_LIGHTS 256
|
||||
#define NUM_STYLES 64
|
||||
#define MaxLights 256
|
||||
|
||||
#define StyleMask 0x07f
|
||||
#define ModelMask 0x380
|
||||
#define ShadowMask 0xc00
|
||||
|
||||
#define LM_LINEAR (0 << 7) // light - dist (or radius + dist if -ve)
|
||||
#define LM_INVERSE (1 << 7) // distFactor1 * light / dist
|
||||
#define LM_INVERSE2 (2 << 7) // distFactor2 * light / (dist * dist)
|
||||
#define LM_INFINITE (3 << 7) // light
|
||||
#define LM_AMBIENT (4 << 7) // light
|
||||
#define LM_INVERSE3 (5 << 7) // distFactor2 * light / (dist + distFactor2)**2
|
||||
|
||||
#define ST_NONE (0 << 10) // no shadows
|
||||
#define ST_PLANE (1 << 10) // single plane shadow map (small spotlight)
|
||||
#define ST_CASCADE (2 << 10) // cascaded shadow maps
|
||||
#define ST_CUBE (3 << 10) // cubemap (omni, large spotlight)
|
||||
|
||||
#define NumStyles 64
|
||||
|
||||
typedef struct qfv_light_buffer_s {
|
||||
float intensity[NUM_STYLES + 4];
|
||||
float intensity[NumStyles + 4];
|
||||
float distFactor1;
|
||||
float distFactor2;
|
||||
int lightCount;
|
||||
qfv_light_t lights[NUM_LIGHTS] __attribute__((aligned(16)));
|
||||
mat4f_t shadowMat[NUM_LIGHTS];
|
||||
vec4f_t shadowCascade[NUM_LIGHTS];
|
||||
qfv_light_t lights[MaxLights] __attribute__((aligned(16)));
|
||||
mat4f_t shadowMat[MaxLights];
|
||||
vec4f_t shadowCascade[MaxLights];
|
||||
} qfv_light_buffer_t;
|
||||
|
||||
#define LIGHTING_BUFFER_INFOS 1
|
||||
#define LIGHTING_ATTACH_INFOS 5
|
||||
#define LIGHTING_SHADOW_INFOS NUM_LIGHTS
|
||||
#define LIGHTING_SHADOW_INFOS MaxLights
|
||||
#define LIGHTING_DESCRIPTORS (LIGHTING_BUFFER_INFOS + LIGHTING_ATTACH_INFOS + 1)
|
||||
|
||||
typedef struct lightingframe_s {
|
||||
|
@ -100,10 +117,13 @@ typedef struct lightingctx_s {
|
|||
VkPipelineLayout layout;
|
||||
VkSampler sampler;
|
||||
VkDeviceMemory light_memory;
|
||||
VkDeviceMemory shadow_memory;
|
||||
qfv_lightset_t lights;
|
||||
qfv_lightleafset_t lightleafs;
|
||||
qfv_lightintset_t lightleafs;
|
||||
qfv_lightmatset_t lightmats;
|
||||
//qfv_imageviewset_t lightviews;
|
||||
qfv_imageset_t lightimages;
|
||||
qfv_lightintset_t lightlayers;
|
||||
qfv_imageviewset_t lightviews;
|
||||
} lightingctx_t;
|
||||
|
||||
struct vulkan_ctx_s;
|
||||
|
|
|
@ -14,7 +14,7 @@ struct LightData {
|
|||
vec3 direction;
|
||||
float cone;
|
||||
};
|
||||
|
||||
//XXX can't include :( be sure to keep up to date with qf_lighting.h
|
||||
#define MaxLights 256
|
||||
|
||||
#define StyleMask 0x07f
|
||||
|
@ -29,8 +29,8 @@ struct LightData {
|
|||
#define LM_INVERSE3 (5 << 7) // distFactor2 * light / (dist + distFactor2)**2
|
||||
|
||||
#define ST_NONE (0 << 10) // no shadows
|
||||
#define ST_CASCADE (1 << 10) // cascaded shadow maps
|
||||
#define ST_PLANE (2 << 10) // single plane shadow map (small spotlight)
|
||||
#define ST_PLANE (1 << 10) // single plane shadow map (small spotlight)
|
||||
#define ST_CASCADE (2 << 10) // cascaded shadow maps
|
||||
#define ST_CUBE (3 << 10) // cubemap (omni, large spotlight)
|
||||
|
||||
layout (set = 2, binding = 0) uniform sampler2DArrayShadow shadowCascade[MaxLights];
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
#include "QF/Vulkan/descriptor.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/projection.h"
|
||||
#include "QF/Vulkan/staging.h"
|
||||
|
||||
#include "compat.h"
|
||||
|
@ -63,6 +65,8 @@
|
|||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
||||
static vec4f_t ref_direction = { 0, 0, 1, 0 };
|
||||
|
||||
static void
|
||||
find_visible_lights (vulkan_ctx_t *ctx)
|
||||
{
|
||||
|
@ -126,12 +130,12 @@ update_lights (vulkan_ctx_t *ctx)
|
|||
|
||||
find_visible_lights (ctx);
|
||||
|
||||
dlight_t *lights[NUM_LIGHTS];
|
||||
dlight_t *lights[MaxLights];
|
||||
qfv_packet_t *packet = QFV_PacketAcquire (ctx->staging);
|
||||
qfv_light_buffer_t *light_data = QFV_PacketExtend (packet,
|
||||
sizeof (*light_data));
|
||||
|
||||
for (int i = 0; i < NUM_STYLES; i++) {
|
||||
for (int i = 0; i < NumStyles; i++) {
|
||||
light_data->intensity[i] = d_lightstylevalue[i] / 65536.0;
|
||||
}
|
||||
// dynamic lights seem a tad faint, so 16x map lights
|
||||
|
@ -144,8 +148,8 @@ update_lights (vulkan_ctx_t *ctx)
|
|||
light_data->distFactor2 = 1 / 16384.0;
|
||||
|
||||
light_data->lightCount = 0;
|
||||
R_FindNearLights (r_origin, NUM_LIGHTS - 1, lights);
|
||||
for (int i = 0; i < NUM_LIGHTS - 1; i++) {
|
||||
R_FindNearLights (r_origin, MaxLights - 1, lights);
|
||||
for (int i = 0; i < MaxLights - 1; i++) {
|
||||
if (!lights[i]) {
|
||||
break;
|
||||
}
|
||||
|
@ -158,7 +162,7 @@ update_lights (vulkan_ctx_t *ctx)
|
|||
light_data->lights[i].cone = 1;
|
||||
}
|
||||
for (size_t i = 0; (i < lframe->lightvis.size
|
||||
&& light_data->lightCount < NUM_LIGHTS); i++) {
|
||||
&& light_data->lightCount < MaxLights); i++) {
|
||||
if (lframe->lightvis.a[i]) {
|
||||
light_data->lights[light_data->lightCount++] = lctx->lights.a[i];
|
||||
}
|
||||
|
@ -285,6 +289,9 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx)
|
|||
DARRAY_INIT (&lctx->lights, 16);
|
||||
DARRAY_INIT (&lctx->lightleafs, 16);
|
||||
DARRAY_INIT (&lctx->lightmats, 16);
|
||||
DARRAY_INIT (&lctx->lightlayers, 16);
|
||||
DARRAY_INIT (&lctx->lightimages, 16);
|
||||
DARRAY_INIT (&lctx->lightviews, 16);
|
||||
|
||||
size_t frames = ctx->frames.size;
|
||||
DARRAY_INIT (&lctx->frames, frames);
|
||||
|
@ -388,13 +395,33 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx)
|
|||
lframe->shadowWrite = base_image_write;
|
||||
lframe->shadowWrite.dstSet = shadow_set->a[i];
|
||||
lframe->shadowWrite.dstBinding = 0;
|
||||
lframe->shadowWrite.descriptorCount = NUM_LIGHTS;
|
||||
lframe->shadowWrite.descriptorCount = MaxLights;
|
||||
lframe->shadowWrite.pImageInfo = lframe->shadowInfo;
|
||||
}
|
||||
free (attach_set);
|
||||
free (lights_set);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_shadows (vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
lightingctx_t *lctx = ctx->lighting_context;
|
||||
|
||||
if (lctx->shadow_memory) {
|
||||
dfunc->vkFreeMemory (device->dev, lctx->shadow_memory, 0);
|
||||
}
|
||||
for (size_t i = 0; i < lctx->lightviews.size; i++) {
|
||||
dfunc->vkDestroyImageView (device->dev, lctx->lightviews.a[i], 0);
|
||||
}
|
||||
for (size_t i = 0; i < lctx->lightimages.size; i++) {
|
||||
dfunc->vkDestroyImage (device->dev, lctx->lightimages.a[i], 0);
|
||||
}
|
||||
lctx->lightimages.size = 0;
|
||||
lctx->lightviews.size = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx)
|
||||
{
|
||||
|
@ -402,6 +429,8 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx)
|
|||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
lightingctx_t *lctx = ctx->lighting_context;
|
||||
|
||||
clear_shadows (ctx);
|
||||
|
||||
for (size_t i = 0; i < lctx->frames.size; i++) {
|
||||
lightingframe_t *lframe = &lctx->frames.a[i];
|
||||
dfunc->vkDestroyBuffer (device->dev, lframe->light_buffer, 0);
|
||||
|
@ -412,12 +441,15 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx)
|
|||
DARRAY_CLEAR (&lctx->lights);
|
||||
DARRAY_CLEAR (&lctx->lightleafs);
|
||||
DARRAY_CLEAR (&lctx->lightmats);
|
||||
DARRAY_CLEAR (&lctx->lightimages);
|
||||
DARRAY_CLEAR (&lctx->lightlayers);
|
||||
DARRAY_CLEAR (&lctx->lightviews);
|
||||
free (lctx->frames.a);
|
||||
free (lctx);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_light (qfv_light_t *light, int leaf)
|
||||
dump_light (qfv_light_t *light, int leaf, mat4f_t mat)
|
||||
{
|
||||
Sys_MaskPrintf (SYS_vulkan,
|
||||
"[%g, %g, %g] %d %d %d, "
|
||||
|
@ -429,6 +461,10 @@ dump_light (qfv_light_t *light, int leaf)
|
|||
VectorExpand (light->position), light->light,
|
||||
VectorExpand (light->direction), light->cone,
|
||||
leaf);
|
||||
Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 0));
|
||||
Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 1));
|
||||
Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 2));
|
||||
Sys_MaskPrintf (SYS_vulkan, " " VEC4F_FMT "\n", MAT4_ROW (mat, 3));
|
||||
}
|
||||
|
||||
static float
|
||||
|
@ -516,13 +552,12 @@ parse_sun (lightingctx_t *lctx, plitem_t *entity)
|
|||
return;
|
||||
}
|
||||
VectorSet (1, 1, 1, light.color);
|
||||
light.data = 3 << 7; //FIXME magic number (LM_INFINITE)
|
||||
light.data = LM_INFINITE | ST_CASCADE;
|
||||
light.light = sunlight;
|
||||
sun_vector (sunangle, light.direction);
|
||||
light.cone = 1;
|
||||
DARRAY_APPEND (&lctx->lights, light);
|
||||
DARRAY_APPEND (&lctx->lightleafs, -1);
|
||||
dump_light (&light, -1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -577,9 +612,11 @@ parse_light (qfv_light_t *light, const plitem_t *entity,
|
|||
}
|
||||
|
||||
if ((str = PL_String (PL_ObjectForKey (entity, "delay")))) {
|
||||
model = atoi (str) & 0x7;
|
||||
if (model == 2) model = 5; //FIXME for marcher (need a map)
|
||||
light->data |= model << 7;
|
||||
model = (atoi (str) & 0x7) << 7;
|
||||
if (model == LM_INVERSE2) {
|
||||
model = LM_INVERSE3; //FIXME for marcher (need a map)
|
||||
}
|
||||
light->data |= model;
|
||||
}
|
||||
|
||||
if ((str = PL_String (PL_ObjectForKey (entity, "color")))
|
||||
|
@ -588,18 +625,263 @@ parse_light (qfv_light_t *light, const plitem_t *entity,
|
|||
VectorScale (light->color, 1/255.0, light->color);
|
||||
}
|
||||
|
||||
//FIXME magic numbers
|
||||
if (model == 3) { // infinite
|
||||
light->data |= 1 << 10; // cascade
|
||||
} else if (model != 4) {// ambient
|
||||
if (model == LM_INFINITE) {
|
||||
light->data |= ST_CASCADE;
|
||||
} else if (model != LM_AMBIENT) {
|
||||
if (light->cone > -0.5) {
|
||||
light->data |= 3 << 10; // cube
|
||||
light->data |= ST_CUBE;
|
||||
} else {
|
||||
light->data |= 2 << 10; // plane
|
||||
light->data |= ST_PLANE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
create_light_matrices (lightingctx_t *lctx)
|
||||
{
|
||||
DARRAY_RESIZE (&lctx->lightmats, lctx->lights.size);
|
||||
for (size_t i = 0; i < lctx->lights.size; i++) {
|
||||
qfv_light_t *light = &lctx->lights.a[i];
|
||||
mat4f_t view;
|
||||
mat4f_t proj;
|
||||
|
||||
switch (light->data & ShadowMask) {
|
||||
case ST_NONE:
|
||||
case ST_CUBE:
|
||||
mat4fidentity (view);
|
||||
break;
|
||||
case ST_CASCADE:
|
||||
case ST_PLANE:
|
||||
//FIXME will fail for -ref_direction
|
||||
mat4fquat (view, qrotf (loadvec3f (light->direction),
|
||||
ref_direction));
|
||||
break;
|
||||
}
|
||||
VectorNegate (light->position, view[3]);
|
||||
|
||||
switch (light->data & ShadowMask) {
|
||||
case ST_NONE:
|
||||
mat4fidentity (proj);
|
||||
break;
|
||||
case ST_CUBE:
|
||||
QFV_PerspectiveTan (proj, 1, 1);
|
||||
break;
|
||||
case ST_CASCADE:
|
||||
// dependent on view fustrum and cascade level
|
||||
mat4fidentity (proj);
|
||||
break;
|
||||
case ST_PLANE:
|
||||
QFV_PerspectiveCos (proj, light->cone, 1);
|
||||
break;
|
||||
}
|
||||
mmulf (lctx->lightmats.a[i], proj, view);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
light_compare (const void *_l2, const void *_l1)
|
||||
{
|
||||
const qfv_light_t *l1 = _l1;
|
||||
const qfv_light_t *l2 = _l2;
|
||||
|
||||
if (l1->light == l2->light) {
|
||||
return (l1->data & ShadowMask) - (l2->data & ShadowMask);
|
||||
}
|
||||
return l1->light - l2->light;
|
||||
}
|
||||
|
||||
static VkImage
|
||||
create_map (int size, int layers, int cube, vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
if (layers < 6) {
|
||||
cube = 0;
|
||||
}
|
||||
|
||||
VkImageCreateInfo createInfo = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 0,
|
||||
cube ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0, VK_IMAGE_TYPE_2D,
|
||||
VK_FORMAT_X8_D24_UNORM_PACK32,
|
||||
{ size, size, 1 }, 1, layers,
|
||||
VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL,
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
|
||||
| VK_IMAGE_USAGE_SAMPLED_BIT, VK_SHARING_MODE_EXCLUSIVE,
|
||||
0, 0,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
};
|
||||
VkImage image;
|
||||
dfunc->vkCreateImage (device->dev, &createInfo, 0, &image);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE, image,
|
||||
va (ctx->va_ctx, "image:shadowmap:%d:%d",
|
||||
size, layers));
|
||||
return image;
|
||||
}
|
||||
|
||||
static VkImageView
|
||||
create_view (VkImage image, int baseLayer, int data, int id, vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
int layers = 0;
|
||||
VkImageViewType type = 0;
|
||||
const char *viewtype = 0;
|
||||
|
||||
switch (data & ShadowMask) {
|
||||
case ST_NONE:
|
||||
return 0;
|
||||
case ST_PLANE:
|
||||
layers = 1;
|
||||
type = VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewtype = "plane";
|
||||
break;
|
||||
case ST_CASCADE:
|
||||
layers = 4;
|
||||
type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
viewtype = "cascade";
|
||||
break;
|
||||
case ST_CUBE:
|
||||
layers = 6;
|
||||
type = VK_IMAGE_VIEW_TYPE_CUBE;
|
||||
viewtype = "cube";
|
||||
break;
|
||||
}
|
||||
|
||||
VkImageViewCreateInfo createInfo = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 0,
|
||||
0,
|
||||
image, type, VK_FORMAT_X8_D24_UNORM_PACK32,
|
||||
{
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
},
|
||||
{ VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, baseLayer, layers }
|
||||
};
|
||||
|
||||
VkImageView view;
|
||||
dfunc->vkCreateImageView (device->dev, &createInfo, 0, &view);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_IMAGE_VIEW, view,
|
||||
va (ctx->va_ctx, "iview:shadowmap:%s:%d",
|
||||
viewtype, id));
|
||||
return view;
|
||||
}
|
||||
|
||||
static void
|
||||
build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
qfv_physdev_t *physDev = device->physDev;
|
||||
int maxLayers = physDev->properties.limits.maxImageArrayLayers;
|
||||
qfv_light_t *lights = lctx->lights.a;
|
||||
int numLights = lctx->lights.size;
|
||||
int size = -1;
|
||||
int numLayers = 0;
|
||||
int totalLayers = 0;
|
||||
int *imageMap = alloca (numLights * sizeof (int));
|
||||
size_t memsize = 0;
|
||||
|
||||
DARRAY_RESIZE (&lctx->lightlayers, numLights);
|
||||
qsort (lights, numLights, sizeof (qfv_light_t), light_compare);
|
||||
for (int i = 0; i < numLights; i++) {
|
||||
int shadow = lights[i].data & ShadowMask;
|
||||
int layers = 1;
|
||||
if (shadow == ST_CASCADE || shadow == ST_NONE) {
|
||||
// cascade shadows will be handled separately, and "none" has no
|
||||
// shadow map at all
|
||||
imageMap[i] = -1;
|
||||
continue;
|
||||
}
|
||||
if (shadow == ST_CUBE) {
|
||||
layers = 6;
|
||||
}
|
||||
if (size != (int) lights[i].light || numLayers + layers > maxLayers) {
|
||||
if (numLayers) {
|
||||
VkImage shadow_map = create_map (size, numLayers, 1, ctx);
|
||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
||||
numLayers = 0;
|
||||
}
|
||||
size = lights[i].light;
|
||||
}
|
||||
imageMap[i] = lctx->lightimages.size;
|
||||
lctx->lightlayers.a[i] = numLayers;
|
||||
numLayers += layers;
|
||||
totalLayers += layers;
|
||||
}
|
||||
if (numLayers) {
|
||||
VkImage shadow_map = create_map (size, numLayers, 1, ctx);
|
||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
||||
}
|
||||
|
||||
numLayers = 0;
|
||||
size = 1024;
|
||||
for (int i = 0; i < numLights; i++) {
|
||||
int shadow = lights[i].data & ShadowMask;
|
||||
int layers = 4;
|
||||
|
||||
if (shadow != ST_CASCADE) {
|
||||
continue;
|
||||
}
|
||||
if (numLayers + layers > maxLayers) {
|
||||
VkImage shadow_map = create_map (size, numLayers, 0, ctx);
|
||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
||||
numLayers = 0;
|
||||
}
|
||||
imageMap[i] = lctx->lightimages.size;
|
||||
lctx->lightlayers.a[i] = numLayers;
|
||||
numLayers += layers;
|
||||
totalLayers += layers;
|
||||
}
|
||||
if (numLayers) {
|
||||
VkImage shadow_map = create_map (size, numLayers, 0, ctx);
|
||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < lctx->lightimages.size; i++) {
|
||||
memsize += QFV_GetImageSize (device, lctx->lightimages.a[i]);
|
||||
}
|
||||
lctx->shadow_memory = QFV_AllocImageMemory (device, lctx->lightimages.a[0],
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
memsize, 0);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
|
||||
lctx->shadow_memory, "memory:shadowmap");
|
||||
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < lctx->lightimages.size; i++) {
|
||||
dfunc->vkBindImageMemory (device->dev, lctx->lightimages.a[i],
|
||||
lctx->shadow_memory, offset);
|
||||
offset += QFV_GetImageSize (device, lctx->lightimages.a[i]);
|
||||
}
|
||||
|
||||
DARRAY_RESIZE (&lctx->lightviews, numLights);
|
||||
for (int i = 0; i < numLights; i++) {
|
||||
if (imageMap[i] == -1) {
|
||||
lctx->lightviews.a[i] = 0;
|
||||
continue;
|
||||
}
|
||||
lctx->lightviews.a[i] = create_view (lctx->lightimages.a[imageMap[i]],
|
||||
lctx->lightlayers.a[i],
|
||||
lctx->lights.a[i].data, i, ctx);
|
||||
}
|
||||
Sys_MaskPrintf (SYS_vulkan, "shadow maps: %d layers in %zd images: %zd\n",
|
||||
totalLayers, lctx->lightimages.size, memsize);
|
||||
}
|
||||
|
||||
static void
|
||||
locate_lights (model_t *model, lightingctx_t *lctx)
|
||||
{
|
||||
qfv_light_t *lights = lctx->lights.a;
|
||||
DARRAY_RESIZE (&lctx->lightleafs, lctx->lights.size);
|
||||
for (size_t i = 0; i < lctx->lights.size; i++) {
|
||||
mleaf_t *leaf = Mod_PointInLeaf (&lights[i].position[0], model);
|
||||
lctx->lightleafs.a[i] = leaf - model->brush.leafs - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx)
|
||||
{
|
||||
|
@ -610,6 +892,8 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx)
|
|||
lctx->lightleafs.size = 0;
|
||||
lctx->lightmats.size = 0;
|
||||
|
||||
clear_shadows (ctx);
|
||||
|
||||
script_t *script = Script_New ();
|
||||
Script_Start (script, "ent data", entity_data);
|
||||
|
||||
|
@ -654,12 +938,6 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx)
|
|||
|
||||
parse_light (&light, entity, targets);
|
||||
DARRAY_APPEND (&lctx->lights, light);
|
||||
mleaf_t *leaf = Mod_PointInLeaf (&light.position[0],
|
||||
model);
|
||||
DARRAY_APPEND (&lctx->lightleafs,
|
||||
leaf - model->brush.leafs - 1);
|
||||
dump_light (&light,
|
||||
lctx->lightleafs.a[lctx->lightleafs.size - 1]);
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < ctx->frames.size; i++) {
|
||||
|
@ -675,4 +953,11 @@ Vulkan_LoadLights (model_t *model, const char *entity_data, vulkan_ctx_t *ctx)
|
|||
PL_Free (entities);
|
||||
}
|
||||
Sys_MaskPrintf (SYS_vulkan, "loaded %zd lights\n", lctx->lights.size);
|
||||
build_shadow_maps (lctx, ctx);
|
||||
create_light_matrices (lctx);
|
||||
locate_lights (model, lctx);
|
||||
for (size_t i = 0; i < lctx->lights.size; i++) {
|
||||
dump_light (&lctx->lights.a[i], lctx->lightleafs.a[i],
|
||||
lctx->lightmats.a[i]);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue