R_RecursiveLightPoint: Share part of light logic

This commit is contained in:
Denis Pauk 2023-10-06 18:38:24 +03:00
parent a381c9dc5d
commit 8f5a40710b
18 changed files with 548 additions and 1108 deletions

View file

@ -1141,6 +1141,7 @@ REFVK_OBJS_ := \
src/client/refresh/vk/vk_draw.o \ src/client/refresh/vk/vk_draw.o \
src/client/refresh/vk/vk_image.o \ src/client/refresh/vk/vk_image.o \
src/client/refresh/vk/vk_light.o \ src/client/refresh/vk/vk_light.o \
src/client/refresh/vk/vk_lightmap.o \
src/client/refresh/vk/vk_mesh.o \ src/client/refresh/vk/vk_mesh.o \
src/client/refresh/vk/vk_model.o \ src/client/refresh/vk/vk_model.o \
src/client/refresh/vk/vk_pipeline.o \ src/client/refresh/vk/vk_pipeline.o \

View file

@ -92,3 +92,126 @@ BSPX_LightGridValue(const bspxlightgrid_t *grid, const lightstyle_t *lightstyles
VectorScale(res_diffuse, 1.0/s, res_diffuse); //average the successful ones VectorScale(res_diffuse, 1.0/s, res_diffuse); //average the successful ones
} }
int
R_RecursiveLightPoint(const msurface_t *surfaces, const mnode_t *node,
const lightstyle_t *lightstyles, const vec3_t start, const vec3_t end,
vec3_t pointcolor, vec3_t lightspot, float modulate)
{
float front, back, frac;
int side;
cplane_t *plane;
vec3_t mid;
const msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
byte *lightmap;
int maps;
int r;
if (node->contents != CONTENTS_NODE)
{
return -1; /* didn't hit anything */
}
/* calculate mid point */
plane = node->plane;
front = DotProduct(start, plane->normal) - plane->dist;
back = DotProduct(end, plane->normal) - plane->dist;
side = front < 0;
if ((back < 0) == side)
{
return R_RecursiveLightPoint(surfaces, node->children[side],
lightstyles, start, end, pointcolor, lightspot, modulate);
}
frac = front / (front - back);
mid[0] = start[0] + (end[0] - start[0]) * frac;
mid[1] = start[1] + (end[1] - start[1]) * frac;
mid[2] = start[2] + (end[2] - start[2]) * frac;
/* go down front side */
r = R_RecursiveLightPoint(surfaces, node->children[side],
lightstyles, start, mid, pointcolor, lightspot, modulate);
if (r >= 0)
{
return r; /* hit something */
}
if ((back < 0) == side)
{
return -1; /* didn't hit anuthing */
}
/* check for impact on this node */
VectorCopy(mid, lightspot);
surf = surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++)
{
if (surf->flags & (SURF_DRAWTURB | SURF_DRAWSKY))
{
continue; /* no lightmaps */
}
tex = surf->texinfo;
s = DotProduct(mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct(mid, tex->vecs[1]) + tex->vecs[1][3];
if ((s < surf->texturemins[0]) ||
(t < surf->texturemins[1]))
{
continue;
}
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if ((ds > surf->extents[0]) || (dt > surf->extents[1]))
{
continue;
}
if (!surf->samples)
{
return 0;
}
ds >>= surf->lmshift;
dt >>= surf->lmshift;
lightmap = surf->samples;
VectorCopy(vec3_origin, pointcolor);
lightmap += 3 * (dt * ((surf->extents[0] >> surf->lmshift) + 1) + ds);
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++)
{
const float *rgb;
int j;
rgb = lightstyles[surf->styles[maps]].rgb;
/* Apply light level to models */
for (j = 0; j < 3; j++)
{
float scale;
scale = rgb[j] * modulate;
pointcolor[j] += lightmap[j] * scale * (1.0 / 255);
}
lightmap += 3 * ((surf->extents[0] >> surf->lmshift) + 1) *
((surf->extents[1] >> surf->lmshift) + 1);
}
return 1;
}
/* go down back side */
return R_RecursiveLightPoint(surfaces, node->children[!side],
lightstyles, mid, end, pointcolor, lightspot, modulate);
}

View file

@ -181,129 +181,6 @@ R_PushDlights(void)
} }
} }
static int
R_RecursiveLightPoint(const msurface_t *surfaces, const mnode_t *node,
const lightstyle_t *lightstyles, const vec3_t start, const vec3_t end,
vec3_t pointcolor, vec3_t lightspot)
{
float front, back, frac;
int side;
cplane_t *plane;
vec3_t mid;
const msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
byte *lightmap;
int maps;
int r;
if (node->contents != CONTENTS_NODE)
{
return -1; /* didn't hit anything */
}
/* calculate mid point */
plane = node->plane;
front = DotProduct(start, plane->normal) - plane->dist;
back = DotProduct(end, plane->normal) - plane->dist;
side = front < 0;
if ((back < 0) == side)
{
return R_RecursiveLightPoint(surfaces, node->children[side],
lightstyles, start, end, pointcolor, lightspot);
}
frac = front / (front - back);
mid[0] = start[0] + (end[0] - start[0]) * frac;
mid[1] = start[1] + (end[1] - start[1]) * frac;
mid[2] = start[2] + (end[2] - start[2]) * frac;
/* go down front side */
r = R_RecursiveLightPoint(surfaces, node->children[side],
lightstyles, start, mid, pointcolor, lightspot);
if (r >= 0)
{
return r; /* hit something */
}
if ((back < 0) == side)
{
return -1; /* didn't hit anuthing */
}
/* check for impact on this node */
VectorCopy(mid, lightspot);
surf = surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++)
{
if (surf->flags & (SURF_DRAWTURB | SURF_DRAWSKY))
{
continue; /* no lightmaps */
}
tex = surf->texinfo;
s = DotProduct(mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct(mid, tex->vecs[1]) + tex->vecs[1][3];
if ((s < surf->texturemins[0]) ||
(t < surf->texturemins[1]))
{
continue;
}
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if ((ds > surf->extents[0]) || (dt > surf->extents[1]))
{
continue;
}
if (!surf->samples)
{
return 0;
}
ds >>= surf->lmshift;
dt >>= surf->lmshift;
lightmap = surf->samples;
VectorCopy(vec3_origin, pointcolor);
lightmap += 3 * (dt * ((surf->extents[0] >> surf->lmshift) + 1) + ds);
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++)
{
const float *rgb;
int j;
rgb = lightstyles[surf->styles[maps]].rgb;
/* Apply light level to models */
for (j = 0; j < 3; j++)
{
float scale;
scale = rgb[j] * r_modulate->value;
pointcolor[j] += lightmap[j] * scale * (1.0 / 255);
}
lightmap += 3 * ((surf->extents[0] >> surf->lmshift) + 1) *
((surf->extents[1] >> surf->lmshift) + 1);
}
return 1;
}
/* go down back side */
return R_RecursiveLightPoint(surfaces, node->children[!side],
lightstyles, mid, end, pointcolor, lightspot);
}
void void
R_LightPoint(entity_t *currententity, vec3_t p, vec3_t color) R_LightPoint(entity_t *currententity, vec3_t p, vec3_t color)
{ {
@ -324,7 +201,7 @@ R_LightPoint(entity_t *currententity, vec3_t p, vec3_t color)
end[2] = p[2] - 2048; end[2] = p[2] - 2048;
r = R_RecursiveLightPoint(r_worldmodel->surfaces, r_worldmodel->nodes, r = R_RecursiveLightPoint(r_worldmodel->surfaces, r_worldmodel->nodes,
r_newrefdef.lightstyles, p, end, pointcolor, lightspot); r_newrefdef.lightstyles, p, end, pointcolor, lightspot, r_modulate->value);
if (r == -1) if (r == -1)
{ {

View file

@ -27,8 +27,6 @@
#ifndef REF_MODEL_H #ifndef REF_MODEL_H
#define REF_MODEL_H #define REF_MODEL_H
#include "../../ref_model.h"
/* Whole model */ /* Whole model */
typedef struct model_s typedef struct model_s

View file

@ -106,129 +106,6 @@ GL3_PushDlights(void)
GL3_UpdateUBOLights(); GL3_UpdateUBOLights();
} }
static int
R_RecursiveLightPoint(const msurface_t *surfaces, const mnode_t *node,
const lightstyle_t *lightstyles, const vec3_t start, const vec3_t end,
vec3_t pointcolor, vec3_t lightspot)
{
float front, back, frac;
int side;
cplane_t *plane;
vec3_t mid;
const msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
byte *lightmap;
int maps;
int r;
if (node->contents != CONTENTS_NODE)
{
return -1; /* didn't hit anything */
}
/* calculate mid point */
plane = node->plane;
front = DotProduct(start, plane->normal) - plane->dist;
back = DotProduct(end, plane->normal) - plane->dist;
side = front < 0;
if ((back < 0) == side)
{
return R_RecursiveLightPoint(surfaces, node->children[side],
lightstyles, start, end, pointcolor, lightspot);
}
frac = front / (front - back);
mid[0] = start[0] + (end[0] - start[0]) * frac;
mid[1] = start[1] + (end[1] - start[1]) * frac;
mid[2] = start[2] + (end[2] - start[2]) * frac;
/* go down front side */
r = R_RecursiveLightPoint(surfaces, node->children[side],
lightstyles, start, mid, pointcolor, lightspot);
if (r >= 0)
{
return r; /* hit something */
}
if ((back < 0) == side)
{
return -1; /* didn't hit anuthing */
}
/* check for impact on this node */
VectorCopy(mid, lightspot);
surf = surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++)
{
if (surf->flags & (SURF_DRAWTURB | SURF_DRAWSKY))
{
continue; /* no lightmaps */
}
tex = surf->texinfo;
s = DotProduct(mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct(mid, tex->vecs[1]) + tex->vecs[1][3];
if ((s < surf->texturemins[0]) ||
(t < surf->texturemins[1]))
{
continue;
}
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if ((ds > surf->extents[0]) || (dt > surf->extents[1]))
{
continue;
}
if (!surf->samples)
{
return 0;
}
ds >>= surf->lmshift;
dt >>= surf->lmshift;
lightmap = surf->samples;
VectorCopy(vec3_origin, pointcolor);
lightmap += 3 * (dt * ((surf->extents[0] >> surf->lmshift) + 1) + ds);
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++)
{
const float *rgb;
int j;
rgb = lightstyles[surf->styles[maps]].rgb;
/* Apply light level to models */
for (j = 0; j < 3; j++)
{
float scale;
scale = rgb[j] * r_modulate->value;
pointcolor[j] += lightmap[j] * scale * (1.0 / 255);
}
lightmap += 3 * ((surf->extents[0] >> surf->lmshift) + 1) *
((surf->extents[1] >> surf->lmshift) + 1);
}
return 1;
}
/* go down back side */
return R_RecursiveLightPoint(surfaces, node->children[!side],
lightstyles, mid, end, pointcolor, lightspot);
}
void void
GL3_LightPoint(entity_t *currententity, vec3_t p, vec3_t color) GL3_LightPoint(entity_t *currententity, vec3_t p, vec3_t color)
{ {
@ -252,7 +129,7 @@ GL3_LightPoint(entity_t *currententity, vec3_t p, vec3_t color)
// TODO: don't just aggregate the color, but also save position of brightest+nearest light // TODO: don't just aggregate the color, but also save position of brightest+nearest light
// for shadow position and maybe lighting on model? // for shadow position and maybe lighting on model?
r = R_RecursiveLightPoint(gl3_worldmodel->surfaces, gl3_worldmodel->nodes, r = R_RecursiveLightPoint(gl3_worldmodel->surfaces, gl3_worldmodel->nodes,
gl3_newrefdef.lightstyles, p, end, pointcolor, lightspot); gl3_newrefdef.lightstyles, p, end, pointcolor, lightspot, r_modulate->value);
if (r == -1) if (r == -1)
{ {

View file

@ -36,40 +36,6 @@ typedef struct gl3_alias_vtx_s {
/* in memory representation */ /* in memory representation */
typedef struct msurface_s
{
int visframe; /* should be drawn when node is crossed */
cplane_t *plane;
int flags;
int firstedge; /* look up in model->surfedges[], negative numbers */
int numedges; /* are backwards edges */
short texturemins[2];
short extents[2];
short lmshift;
int light_s, light_t; /* gl lightmap coordinates */
int dlight_s, dlight_t; /* gl lightmap coordinates for dynamic lightmaps */
mpoly_t *polys; /* multiple if warped */
struct msurface_s *texturechain;
// struct msurface_s *lightmapchain; not used/needed anymore
mtexinfo_t *texinfo;
/* lighting info */
int dlightframe;
int dlightbits;
int lightmaptexturenum;
byte styles[MAXLIGHTMAPS]; // MAXLIGHTMAPS = MAX_LIGHTMAPS_PER_SURFACE (defined in local.h)
// I think cached_light is not used/needed anymore
//float cached_light[MAXLIGHTMAPS]; /* values currently used in lightmap */
byte *samples; /* [numstyles*surfsize] */
} msurface_t;
/* Whole model */ /* Whole model */
// this, must be struct model_s, not gl3model_s, // this, must be struct model_s, not gl3model_s,

View file

@ -106,129 +106,6 @@ GL4_PushDlights(void)
GL4_UpdateUBOLights(); GL4_UpdateUBOLights();
} }
static int
R_RecursiveLightPoint(const msurface_t *surfaces, const mnode_t *node,
const lightstyle_t *lightstyles, const vec3_t start, const vec3_t end,
vec3_t pointcolor, vec3_t lightspot)
{
float front, back, frac;
int side;
cplane_t *plane;
vec3_t mid;
const msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
byte *lightmap;
int maps;
int r;
if (node->contents != CONTENTS_NODE)
{
return -1; /* didn't hit anything */
}
/* calculate mid point */
plane = node->plane;
front = DotProduct(start, plane->normal) - plane->dist;
back = DotProduct(end, plane->normal) - plane->dist;
side = front < 0;
if ((back < 0) == side)
{
return R_RecursiveLightPoint(surfaces, node->children[side],
lightstyles, start, end, pointcolor, lightspot);
}
frac = front / (front - back);
mid[0] = start[0] + (end[0] - start[0]) * frac;
mid[1] = start[1] + (end[1] - start[1]) * frac;
mid[2] = start[2] + (end[2] - start[2]) * frac;
/* go down front side */
r = R_RecursiveLightPoint(surfaces, node->children[side],
lightstyles, start, mid, pointcolor, lightspot);
if (r >= 0)
{
return r; /* hit something */
}
if ((back < 0) == side)
{
return -1; /* didn't hit anuthing */
}
/* check for impact on this node */
VectorCopy(mid, lightspot);
surf = surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++)
{
if (surf->flags & (SURF_DRAWTURB | SURF_DRAWSKY))
{
continue; /* no lightmaps */
}
tex = surf->texinfo;
s = DotProduct(mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct(mid, tex->vecs[1]) + tex->vecs[1][3];
if ((s < surf->texturemins[0]) ||
(t < surf->texturemins[1]))
{
continue;
}
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if ((ds > surf->extents[0]) || (dt > surf->extents[1]))
{
continue;
}
if (!surf->samples)
{
return 0;
}
ds >>= surf->lmshift;
dt >>= surf->lmshift;
lightmap = surf->samples;
VectorCopy(vec3_origin, pointcolor);
lightmap += 3 * (dt * ((surf->extents[0] >> surf->lmshift) + 1) + ds);
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++)
{
const float *rgb;
int j;
rgb = lightstyles[surf->styles[maps]].rgb;
/* Apply light level to models */
for (j = 0; j < 3; j++)
{
float scale;
scale = rgb[j] * r_modulate->value;
pointcolor[j] += lightmap[j] * scale * (1.0 / 255);
}
lightmap += 3 * ((surf->extents[0] >> surf->lmshift) + 1) *
((surf->extents[1] >> surf->lmshift) + 1);
}
return 1;
}
/* go down back side */
return R_RecursiveLightPoint(surfaces, node->children[!side],
lightstyles, mid, end, pointcolor, lightspot);
}
void void
GL4_LightPoint(entity_t *currententity, vec3_t p, vec3_t color) GL4_LightPoint(entity_t *currententity, vec3_t p, vec3_t color)
{ {
@ -252,7 +129,7 @@ GL4_LightPoint(entity_t *currententity, vec3_t p, vec3_t color)
// TODO: don't just aggregate the color, but also save position of brightest+nearest light // TODO: don't just aggregate the color, but also save position of brightest+nearest light
// for shadow position and maybe lighting on model? // for shadow position and maybe lighting on model?
r = R_RecursiveLightPoint(gl4_worldmodel->surfaces, gl4_worldmodel->nodes, r = R_RecursiveLightPoint(gl4_worldmodel->surfaces, gl4_worldmodel->nodes,
gl4_newrefdef.lightstyles, p, end, pointcolor, lightspot); gl4_newrefdef.lightstyles, p, end, pointcolor, lightspot, r_modulate->value);
if (r == -1) if (r == -1)
{ {

View file

@ -36,40 +36,6 @@ typedef struct gl4_alias_vtx_s {
/* in memory representation */ /* in memory representation */
typedef struct msurface_s
{
int visframe; /* should be drawn when node is crossed */
cplane_t *plane;
int flags;
int firstedge; /* look up in model->surfedges[], negative numbers */
int numedges; /* are backwards edges */
short texturemins[2];
short extents[2];
short lmshift;
int light_s, light_t; /* gl lightmap coordinates */
int dlight_s, dlight_t; /* gl lightmap coordinates for dynamic lightmaps */
mpoly_t *polys; /* multiple if warped */
struct msurface_s *texturechain;
// struct msurface_s *lightmapchain; not used/needed anymore
mtexinfo_t *texinfo;
/* lighting info */
int dlightframe;
int dlightbits;
int lightmaptexturenum;
byte styles[MAXLIGHTMAPS]; // MAXLIGHTMAPS = MAX_LIGHTMAPS_PER_SURFACE (defined in local.h)
// I think cached_light is not used/needed anymore
//float cached_light[MAXLIGHTMAPS]; /* values currently used in lightmap */
byte *samples; /* [numstyles*surfsize] */
} msurface_t;
/* Whole model */ /* Whole model */
// this, must be struct model_s, not gl4model_s, // this, must be struct model_s, not gl4model_s,

View file

@ -1,39 +0,0 @@
/* in memory representation */
typedef struct msurface_s
{
int visframe; /* should be drawn when node is crossed */
cplane_t *plane;
int flags;
int firstedge; /* look up in model->surfedges[], negative numbers */
int numedges; /* are backwards edges */
short texturemins[2];
short extents[2];
short lmshift;
int light_s, light_t; /* gl lightmap coordinates */
int dlight_s, dlight_t; /* gl lightmap coordinates for dynamic lightmaps */
mpoly_t *polys; /* multiple if warped */
struct msurface_s *texturechain;
struct msurface_s *lightmapchain;
mtexinfo_t *texinfo;
/* decoupled lm */
float lmvecs[2][4];
float lmvlen[2];
/* lighting info */
int dlightframe;
int dlightbits;
int lightmaptexturenum;
byte styles[MAXLIGHTMAPS];
float cached_light[MAXLIGHTMAPS]; /* values currently used in lightmap */
byte *samples; /* [numstyles*surfsize] */
} msurface_t;

View file

@ -121,9 +121,11 @@ enum {
SURF_UNDERWATER = 0x80 SURF_UNDERWATER = 0x80
}; };
/* in memory representation */
typedef struct mvertex_s typedef struct mvertex_s
{ {
vec3_t position; vec3_t position;
} mvertex_t; } mvertex_t;
typedef struct medge_s typedef struct medge_s
@ -184,22 +186,80 @@ typedef struct mleaf_s
* (ok, it has the layout used for rendering brushes, but is not used there) * (ok, it has the layout used for rendering brushes, but is not used there)
*/ */
typedef struct mvtx_s { typedef struct mvtx_s {
vec3_t pos; vec3_t pos;
float texCoord[2]; float texCoord[2];
float lmTexCoord[2]; /* lightmap texture coordinate (sometimes unused) */ float lmTexCoord[2]; /* lightmap texture coordinate (sometimes unused) */
vec3_t normal; vec3_t normal;
int lightFlags; /* bit i set means: dynlight i affects surface */ int lightFlags; /* bit i set means: dynlight i affects surface */
} mvtx_t; } mvtx_t;
typedef struct mpoly_s typedef struct mpoly_s
{ {
struct mpoly_s *next; struct mpoly_s *next;
struct mpoly_s *chain; struct mpoly_s *chain;
int numverts; int numverts;
int flags; /* for SURF_UNDERWATER (not needed anymore?) */ int flags; /* for SURF_UNDERWATER (not needed anymore?) */
mvtx_t verts[4]; /* variable sized */ mvtx_t verts[4]; /* variable sized */
} mpoly_t; } mpoly_t;
/* soft render specific surface cache */
typedef struct surfcache_s
{
struct surfcache_s *next;
struct surfcache_s **owner; /* NULL is an empty chunk of memory */
int lightadj[MAXLIGHTMAPS]; /* checked for strobe flush */
int dlight;
int size; /* including header */
unsigned width;
unsigned height; /* DEBUG only needed for debug */
float mipscale;
struct image_s *image;
byte data[4]; /* width * height elements */
} surfcache_t;
typedef struct msurface_s
{
int visframe; /* should be drawn when node is crossed */
cplane_t *plane;
int flags;
int firstedge; /* look up in model->surfedges[], negative numbers */
int numedges; /* are backwards edges */
short texturemins[2];
short extents[2];
short lmshift;
int light_s, light_t; /* lightmap coordinates */
int dlight_s, dlight_t; /* lightmap coordinates for dynamic lightmaps */
mpoly_t *polys; /* multiple if warped */
struct msurface_s *texturechain;
struct msurface_s *lightmapchain;
mtexinfo_t *texinfo;
/* decoupled lm */
float lmvecs[2][4];
float lmvlen[2];
/* lighting info */
int dlightframe;
int dlightbits;
int lightmaptexturenum;
byte styles[MAXLIGHTMAPS];
byte *samples; /* [numstyles*surfsize] */
/* unused in gl* renders */
float cached_light[MAXLIGHTMAPS]; /* values currently used in lightmap */
/* used in soft only */
struct msurface_s *nextalphasurface;
struct surfcache_s *cachespots[MIPLEVELS]; /* surface generation data */
} msurface_t;
/* BSPX Light octtree */ /* BSPX Light octtree */
#define LGNODE_LEAF (1u<<31) #define LGNODE_LEAF (1u<<31)
#define LGNODE_MISSING (1u<<30) #define LGNODE_MISSING (1u<<30)
@ -306,5 +366,8 @@ extern void R_BoundPoly(int numverts, float *verts, vec3_t mins, vec3_t maxs);
extern bspxlightgrid_t *BSPX_LightGridLoad(const bspx_header_t *bspx_header, const byte *mod_base); extern bspxlightgrid_t *BSPX_LightGridLoad(const bspx_header_t *bspx_header, const byte *mod_base);
extern void BSPX_LightGridValue(const bspxlightgrid_t *grid, const lightstyle_t *lightstyles, extern void BSPX_LightGridValue(const bspxlightgrid_t *grid, const lightstyle_t *lightstyles,
const vec3_t point, vec3_t res_diffuse); const vec3_t point, vec3_t res_diffuse);
extern int R_RecursiveLightPoint(const msurface_t *surfaces, const mnode_t *node,
const lightstyle_t *lightstyles, const vec3_t start, const vec3_t end,
vec3_t pointcolor, vec3_t lightspot, float modulate);
#endif /* SRC_CLIENT_REFRESH_REF_SHARED_H_ */ #endif /* SRC_CLIENT_REFRESH_REF_SHARED_H_ */

View file

@ -252,20 +252,6 @@ typedef struct clipplane_s
byte rightedge; byte rightedge;
} clipplane_t; } clipplane_t;
typedef struct surfcache_s
{
struct surfcache_s *next;
struct surfcache_s **owner; // NULL is an empty chunk of memory
int lightadj[MAXLIGHTMAPS]; // checked for strobe flush
int dlight;
int size; // including header
unsigned width;
unsigned height; // DEBUG only needed for debug
float mipscale;
image_t *image;
byte data[4]; // width * height elements
} surfcache_t;
typedef struct espan_s typedef struct espan_s
{ {
int u, v, count; int u, v, count;

View file

@ -42,35 +42,6 @@ BRUSH MODELS
// in memory representation // in memory representation
// //
typedef struct msurface_s
{
int visframe; // should be drawn when node is crossed
int dlightframe;
int dlightbits;
cplane_t *plane;
int flags;
int firstedge; // look up in model->surfedges[], negative numbers
int numedges; // are backwards edges
// surface generation data
struct surfcache_s *cachespots[MIPLEVELS];
short texturemins[2];
short extents[2];
short lmshift;
mtexinfo_t *texinfo;
// lighting info
byte styles[MAXLIGHTMAPS];
byte *samples; // [numstyles*surfsize*3]
struct msurface_s *nextalphasurface;
} msurface_t;
//=================================================================== //===================================================================
// //

View file

@ -75,128 +75,6 @@ LIGHT SAMPLING
============================================================================= =============================================================================
*/ */
static int
R_RecursiveLightPoint(const msurface_t *surfaces, const mnode_t *node,
const lightstyle_t *lightstyles, const vec3_t start, const vec3_t end,
vec3_t pointcolor, vec3_t lightspot)
{
float front, back, frac;
int side;
cplane_t *plane;
vec3_t mid;
const msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
byte *lightmap;
int maps;
int r;
if (node->contents != CONTENTS_NODE)
{
return -1; /* didn't hit anything */
}
/* calculate mid point */
plane = node->plane;
front = DotProduct(start, plane->normal) - plane->dist;
back = DotProduct(end, plane->normal) - plane->dist;
side = front < 0;
if ((back < 0) == side)
{
return R_RecursiveLightPoint(surfaces, node->children[side],
lightstyles, start, end, pointcolor, lightspot);
}
frac = front / (front - back);
mid[0] = start[0] + (end[0] - start[0]) * frac;
mid[1] = start[1] + (end[1] - start[1]) * frac;
mid[2] = start[2] + (end[2] - start[2]) * frac;
/* go down front side */
r = R_RecursiveLightPoint(surfaces, node->children[side],
lightstyles, start, mid, pointcolor, lightspot);
if (r >= 0)
{
return r; /* hit something */
}
if ((back < 0) == side)
{
return -1; /* didn't hit anuthing */
}
/* check for impact on this node */
VectorCopy(mid, lightspot);
surf = surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++)
{
if (surf->flags & (SURF_DRAWTURB | SURF_DRAWSKY))
{
continue; /* no lightmaps */
}
tex = surf->texinfo;
s = DotProduct(mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct(mid, tex->vecs[1]) + tex->vecs[1][3];
if ((s < surf->texturemins[0]) ||
(t < surf->texturemins[1]))
{
continue;
}
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if ((ds > surf->extents[0]) || (dt > surf->extents[1]))
{
continue;
}
if (!surf->samples)
{
return 0;
}
ds >>= surf->lmshift;
dt >>= surf->lmshift;
lightmap = surf->samples;
VectorCopy(vec3_origin, pointcolor);
lightmap += 3 * (dt * ((surf->extents[0] >> surf->lmshift) + 1) + ds);
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++)
{
const float *rgb;
int j;
rgb = lightstyles[surf->styles[maps]].rgb;
/* Apply light level to models */
for (j = 0; j < 3; j++)
{
float scale;
scale = rgb[j] * r_modulate->value;
pointcolor[j] += lightmap[j] * scale * (1.0 / 255);
}
lightmap += 3 * ((surf->extents[0] >> surf->lmshift) + 1) *
((surf->extents[1] >> surf->lmshift) + 1);
}
return 1;
}
/* go down back side */
return R_RecursiveLightPoint(surfaces, node->children[!side],
lightstyles, mid, end, pointcolor, lightspot);
}
vec3_t lightspot; vec3_t lightspot;
@ -226,7 +104,7 @@ R_LightPoint (const entity_t *currententity, vec3_t p, vec3_t color)
end[2] = p[2] - 2048; end[2] = p[2] - 2048;
r = R_RecursiveLightPoint(r_worldmodel->surfaces, r_worldmodel->nodes, r = R_RecursiveLightPoint(r_worldmodel->surfaces, r_worldmodel->nodes,
r_newrefdef.lightstyles, p, end, pointcolor, lightspot); r_newrefdef.lightstyles, p, end, pointcolor, lightspot, r_modulate->value);
if (r == -1) if (r == -1)
{ {

View file

@ -258,6 +258,10 @@ void Vk_ShutdownImages (void);
void Vk_FreeUnusedImages (void); void Vk_FreeUnusedImages (void);
qboolean Vk_ImageHasFreeSpace(void); qboolean Vk_ImageHasFreeSpace(void);
void LM_InitBlock(void);
void LM_UploadBlock(qboolean dynamic);
qboolean LM_AllocBlock(int w, int h, int *x, int *y);
void RE_BeginRegistration (const char *model); void RE_BeginRegistration (const char *model);
struct model_s *RE_RegisterModel (const char *name); struct model_s *RE_RegisterModel (const char *name);
struct image_s *RE_RegisterSkin (const char *name); struct image_s *RE_RegisterSkin (const char *name);
@ -298,6 +302,24 @@ typedef struct
#define MAX_LIGHTMAPS 256 #define MAX_LIGHTMAPS 256
#define DYNLIGHTMAP_OFFSET MAX_LIGHTMAPS #define DYNLIGHTMAP_OFFSET MAX_LIGHTMAPS
#define BLOCK_WIDTH 128
#define BLOCK_HEIGHT 128
typedef struct
{
int current_lightmap_texture;
msurface_t *lightmap_surfaces[MAX_LIGHTMAPS];
int allocated[BLOCK_WIDTH];
// the lightmap texture data needs to be kept in
// main memory so texsubimage can update properly
byte lightmap_buffer[4*BLOCK_WIDTH*BLOCK_HEIGHT];
} vklightmapstate_t;
extern vklightmapstate_t vk_lms;
typedef struct typedef struct
{ {
float inverse_intensity; float inverse_intensity;

View file

@ -47,8 +47,6 @@ BRUSH MODELS
// in memory representation // in memory representation
// //
#include "../../ref_model.h"
/* Whole model */ /* Whole model */
typedef struct model_s typedef struct model_s

View file

@ -173,129 +173,6 @@ LIGHT SAMPLING
vec3_t lightspot; vec3_t lightspot;
static int
R_RecursiveLightPoint(const msurface_t *surfaces, const mnode_t *node,
const lightstyle_t *lightstyles, const vec3_t start, const vec3_t end,
vec3_t pointcolor, vec3_t lightspot)
{
float front, back, frac;
int side;
cplane_t *plane;
vec3_t mid;
const msurface_t *surf;
int s, t, ds, dt;
int i;
mtexinfo_t *tex;
byte *lightmap;
int maps;
int r;
if (node->contents != CONTENTS_NODE)
{
return -1; /* didn't hit anything */
}
/* calculate mid point */
plane = node->plane;
front = DotProduct(start, plane->normal) - plane->dist;
back = DotProduct(end, plane->normal) - plane->dist;
side = front < 0;
if ((back < 0) == side)
{
return R_RecursiveLightPoint(surfaces, node->children[side],
lightstyles, start, end, pointcolor, lightspot);
}
frac = front / (front - back);
mid[0] = start[0] + (end[0] - start[0]) * frac;
mid[1] = start[1] + (end[1] - start[1]) * frac;
mid[2] = start[2] + (end[2] - start[2]) * frac;
/* go down front side */
r = R_RecursiveLightPoint(surfaces, node->children[side],
lightstyles, start, mid, pointcolor, lightspot);
if (r >= 0)
{
return r; /* hit something */
}
if ((back < 0) == side)
{
return -1; /* didn't hit anuthing */
}
/* check for impact on this node */
VectorCopy(mid, lightspot);
surf = surfaces + node->firstsurface;
for (i = 0; i < node->numsurfaces; i++, surf++)
{
if (surf->flags & (SURF_DRAWTURB | SURF_DRAWSKY))
{
continue; /* no lightmaps */
}
tex = surf->texinfo;
s = DotProduct(mid, tex->vecs[0]) + tex->vecs[0][3];
t = DotProduct(mid, tex->vecs[1]) + tex->vecs[1][3];
if ((s < surf->texturemins[0]) ||
(t < surf->texturemins[1]))
{
continue;
}
ds = s - surf->texturemins[0];
dt = t - surf->texturemins[1];
if ((ds > surf->extents[0]) || (dt > surf->extents[1]))
{
continue;
}
if (!surf->samples)
{
return 0;
}
ds >>= surf->lmshift;
dt >>= surf->lmshift;
lightmap = surf->samples;
VectorCopy(vec3_origin, pointcolor);
lightmap += 3 * (dt * ((surf->extents[0] >> surf->lmshift) + 1) + ds);
for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++)
{
const float *rgb;
int j;
rgb = lightstyles[surf->styles[maps]].rgb;
/* Apply light level to models */
for (j = 0; j < 3; j++)
{
float scale;
scale = rgb[j] * r_modulate->value;
pointcolor[j] += lightmap[j] * scale * (1.0 / 255);
}
lightmap += 3 * ((surf->extents[0] >> surf->lmshift) + 1) *
((surf->extents[1] >> surf->lmshift) + 1);
}
return 1;
}
/* go down back side */
return R_RecursiveLightPoint(surfaces, node->children[!side],
lightstyles, mid, end, pointcolor, lightspot);
}
void void
R_LightPoint(vec3_t p, vec3_t color, entity_t *currententity) R_LightPoint(vec3_t p, vec3_t color, entity_t *currententity)
{ {
@ -315,7 +192,7 @@ R_LightPoint(vec3_t p, vec3_t color, entity_t *currententity)
end[2] = p[2] - 2048; end[2] = p[2] - 2048;
r = R_RecursiveLightPoint(r_worldmodel->surfaces, r_worldmodel->nodes, r = R_RecursiveLightPoint(r_worldmodel->surfaces, r_worldmodel->nodes,
r_newrefdef.lightstyles, p, end, pointcolor, lightspot); r_newrefdef.lightstyles, p, end, pointcolor, lightspot, r_modulate->value);
if (r == -1) if (r == -1)
{ {

View file

@ -0,0 +1,322 @@
/*
* Copyright (C) 1997-2001 Id Software, Inc.
* Copyright (C) 2018-2019 Krzysztof Kondrak
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Lightmap handling
*
* =======================================================================
*/
#include "header/local.h"
#define LIGHTMAP_BYTES 4
void
LM_InitBlock(void)
{
memset(vk_lms.allocated, 0, sizeof(vk_lms.allocated));
}
void
LM_UploadBlock(qboolean dynamic)
{
int texture;
if (dynamic)
{
texture = 0;
}
else
{
texture = vk_lms.current_lightmap_texture;
}
if (dynamic)
{
int i;
int height = 0;
for (i = 0; i < BLOCK_WIDTH; i++)
{
if (vk_lms.allocated[i] > height)
{
height = vk_lms.allocated[i];
}
}
QVk_UpdateTextureData(&vk_state.lightmap_textures[texture], vk_lms.lightmap_buffer, 0, 0, BLOCK_WIDTH, height);
}
else
{
if (vk_state.lightmap_textures[texture].resource.image != VK_NULL_HANDLE)
{
QVk_UpdateTextureData(&vk_state.lightmap_textures[texture], vk_lms.lightmap_buffer, 0, 0, BLOCK_WIDTH, BLOCK_HEIGHT);
}
else
{
QVVKTEXTURE_CLEAR(vk_state.lightmap_textures[texture]);
QVk_CreateTexture(&vk_state.lightmap_textures[texture], vk_lms.lightmap_buffer,
BLOCK_WIDTH, BLOCK_HEIGHT, vk_current_lmap_sampler, false);
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[texture].resource.image,
VK_OBJECT_TYPE_IMAGE, va("Image: dynamic lightmap #%d", texture));
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[texture].imageView,
VK_OBJECT_TYPE_IMAGE_VIEW, va("Image View: dynamic lightmap #%d", texture));
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[texture].descriptorSet,
VK_OBJECT_TYPE_DESCRIPTOR_SET, va("Descriptor Set: dynamic lightmap #%d", texture));
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[texture].resource.memory,
VK_OBJECT_TYPE_DEVICE_MEMORY, va("Memory: dynamic lightmap #%d", texture));
}
if (++vk_lms.current_lightmap_texture == MAX_LIGHTMAPS)
{
ri.Sys_Error(ERR_DROP,
"%s() - MAX_LIGHTMAPS exceeded\n", __func__);
}
}
}
/*
* returns a texture number and the position inside it
*/
qboolean
LM_AllocBlock(int w, int h, int *x, int *y)
{
int i, best;
best = BLOCK_HEIGHT;
for (i = 0; i < BLOCK_WIDTH - w; i++)
{
int j, best2;
best2 = 0;
for (j = 0; j < w; j++)
{
if (vk_lms.allocated[i + j] >= best)
{
break;
}
if (vk_lms.allocated[i + j] > best2)
{
best2 = vk_lms.allocated[i + j];
}
}
if (j == w)
{
/* this is a valid spot */
*x = i;
*y = best = best2;
}
}
if (best + h > BLOCK_HEIGHT)
{
return false;
}
for (i = 0; i < w; i++)
{
vk_lms.allocated[*x + i] = best + h;
}
return true;
}
void
Vk_BuildPolygonFromSurface(model_t *currentmodel, msurface_t *fa)
{
int i, lnumverts;
medge_t *pedges, *r_pedge;
float *vec;
mpoly_t *poly;
vec3_t total;
vec3_t normal;
/* reconstruct the polygon */
pedges = currentmodel->edges;
lnumverts = fa->numedges;
VectorClear(total);
/* draw texture */
poly = Hunk_Alloc(sizeof(mpoly_t) +
(lnumverts - 4) * sizeof(mvtx_t));
poly->next = fa->polys;
poly->flags = fa->flags;
fa->polys = poly;
poly->numverts = lnumverts;
VectorCopy(fa->plane->normal, normal);
if(fa->flags & SURF_PLANEBACK)
{
// if for some reason the normal sticks to the back of the plane, invert it
// so it's usable for the shader
for (i=0; i<3; ++i) normal[i] = -normal[i];
}
for (i = 0; i < lnumverts; i++)
{
mvtx_t* vert;
float s, t;
int lindex;
vert = &poly->verts[i];
lindex = currentmodel->surfedges[fa->firstedge + i];
if (lindex > 0)
{
r_pedge = &pedges[lindex];
vec = currentmodel->vertexes[r_pedge->v[0]].position;
}
else
{
r_pedge = &pedges[-lindex];
vec = currentmodel->vertexes[r_pedge->v[1]].position;
}
s = DotProduct(vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
s /= fa->texinfo->image->width;
t = DotProduct(vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
t /= fa->texinfo->image->height;
VectorAdd(total, vec, total);
VectorCopy(vec, vert->pos);
vert->texCoord[0] = s;
vert->texCoord[1] = t;
/* lightmap texture coordinates */
s = DotProduct(vec, fa->lmvecs[0]) + fa->lmvecs[0][3];
s -= fa->texturemins[0];
s += fa->light_s * (1 << fa->lmshift);
s += (1 << fa->lmshift) * 0.5;
s /= BLOCK_WIDTH * (1 << fa->lmshift);
t = DotProduct(vec, fa->lmvecs[1]) + fa->lmvecs[1][3];
t -= fa->texturemins[1];
t += fa->light_t * (1 << fa->lmshift);
t += (1 << fa->lmshift) * 0.5;
t /= BLOCK_HEIGHT * (1 << fa->lmshift);
vert->lmTexCoord[0] = s;
vert->lmTexCoord[1] = t;
VectorCopy(normal, vert->normal);
vert->lightFlags = 0;
}
}
void
Vk_CreateSurfaceLightmap(msurface_t *surf)
{
int smax, tmax;
byte *base;
if (surf->flags & (SURF_DRAWSKY | SURF_DRAWTURB))
{
return;
}
smax = (surf->extents[0] >> surf->lmshift) + 1;
tmax = (surf->extents[1] >> surf->lmshift) + 1;
if (!LM_AllocBlock(smax, tmax, &surf->light_s, &surf->light_t))
{
LM_UploadBlock(false);
LM_InitBlock();
if (!LM_AllocBlock(smax, tmax, &surf->light_s, &surf->light_t))
{
ri.Sys_Error(ERR_FATAL,
"%s: Consecutive calls to LM_AllocBlock(%d,%d) failed\n",
__func__, smax, tmax);
}
}
surf->lightmaptexturenum = vk_lms.current_lightmap_texture;
base = vk_lms.lightmap_buffer;
base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * LIGHTMAP_BYTES;
R_SetCacheState(surf);
R_BuildLightMap(surf, base, BLOCK_WIDTH * LIGHTMAP_BYTES);
}
void
Vk_BeginBuildingLightmaps(model_t *m)
{
static lightstyle_t lightstyles[MAX_LIGHTSTYLES];
int i;
memset(vk_lms.allocated, 0, sizeof(vk_lms.allocated));
r_framecount = 1; /* no dlightcache */
/* setup the base lightstyles so the lightmaps
won't have to be regenerated the first time
they're seen */
for (i = 0; i < MAX_LIGHTSTYLES; i++)
{
lightstyles[i].rgb[0] = 1;
lightstyles[i].rgb[1] = 1;
lightstyles[i].rgb[2] = 1;
lightstyles[i].white = 3;
}
r_newrefdef.lightstyles = lightstyles;
vk_lms.current_lightmap_texture = 0;
/*
** initialize the dynamic lightmap textures
*/
if (vk_state.lightmap_textures[DYNLIGHTMAP_OFFSET].resource.image == VK_NULL_HANDLE)
{
for (i = DYNLIGHTMAP_OFFSET; i < MAX_LIGHTMAPS*2; i++)
{
unsigned dummy[BLOCK_WIDTH * BLOCK_HEIGHT];
QVVKTEXTURE_CLEAR(vk_state.lightmap_textures[i]);
QVk_CreateTexture(&vk_state.lightmap_textures[i], (unsigned char*)dummy,
BLOCK_WIDTH, BLOCK_HEIGHT, vk_current_lmap_sampler, false);
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[i].resource.image,
VK_OBJECT_TYPE_IMAGE, va("Image: dynamic lightmap #%d", i));
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[i].imageView,
VK_OBJECT_TYPE_IMAGE_VIEW, va("Image View: dynamic lightmap #%d", i));
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[i].descriptorSet,
VK_OBJECT_TYPE_DESCRIPTOR_SET, va("Descriptor Set: dynamic lightmap #%d", i));
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[i].resource.memory,
VK_OBJECT_TYPE_DEVICE_MEMORY, va("Memory: dynamic lightmap #%d", i));
}
}
}
void
Vk_EndBuildingLightmaps(void)
{
LM_UploadBlock(false);
}

View file

@ -34,29 +34,7 @@ int c_visible_textures;
static vec3_t modelorg; /* relative to viewpoint */ static vec3_t modelorg; /* relative to viewpoint */
msurface_t *r_alpha_surfaces; msurface_t *r_alpha_surfaces;
static void LM_InitBlock(void); vklightmapstate_t vk_lms;
static void LM_UploadBlock(qboolean dynamic);
static qboolean LM_AllocBlock(int w, int h, int *x, int *y);
#define LIGHTMAP_BYTES 4
#define BLOCK_WIDTH 128
#define BLOCK_HEIGHT 128
typedef struct
{
int current_lightmap_texture;
msurface_t *lightmap_surfaces[MAX_LIGHTMAPS];
int allocated[BLOCK_WIDTH];
// the lightmap texture data needs to be kept in
// main memory so texsubimage can update properly
byte lightmap_buffer[4*BLOCK_WIDTH*BLOCK_HEIGHT];
} vklightmapstate_t;
static vklightmapstate_t vk_lms;
static void static void
DrawVkPoly(mpoly_t *p, image_t *texture, float *color) DrawVkPoly(mpoly_t *p, image_t *texture, float *color)
@ -1038,304 +1016,3 @@ R_MarkLeaves(void)
} }
} }
} }
/*
=============================================================================
LIGHTMAP ALLOCATION
=============================================================================
*/
static void LM_InitBlock( void )
{
memset(vk_lms.allocated, 0, sizeof(vk_lms.allocated));
}
static void
LM_UploadBlock(qboolean dynamic)
{
int texture;
if (dynamic)
{
texture = 0;
}
else
{
texture = vk_lms.current_lightmap_texture;
}
if (dynamic)
{
int i;
int height = 0;
for (i = 0; i < BLOCK_WIDTH; i++)
{
if (vk_lms.allocated[i] > height)
{
height = vk_lms.allocated[i];
}
}
QVk_UpdateTextureData(&vk_state.lightmap_textures[texture], vk_lms.lightmap_buffer, 0, 0, BLOCK_WIDTH, height);
}
else
{
if (vk_state.lightmap_textures[texture].resource.image != VK_NULL_HANDLE)
{
QVk_UpdateTextureData(&vk_state.lightmap_textures[texture], vk_lms.lightmap_buffer, 0, 0, BLOCK_WIDTH, BLOCK_HEIGHT);
}
else
{
QVVKTEXTURE_CLEAR(vk_state.lightmap_textures[texture]);
QVk_CreateTexture(&vk_state.lightmap_textures[texture], vk_lms.lightmap_buffer,
BLOCK_WIDTH, BLOCK_HEIGHT, vk_current_lmap_sampler, false);
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[texture].resource.image,
VK_OBJECT_TYPE_IMAGE, va("Image: dynamic lightmap #%d", texture));
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[texture].imageView,
VK_OBJECT_TYPE_IMAGE_VIEW, va("Image View: dynamic lightmap #%d", texture));
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[texture].descriptorSet,
VK_OBJECT_TYPE_DESCRIPTOR_SET, va("Descriptor Set: dynamic lightmap #%d", texture));
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[texture].resource.memory,
VK_OBJECT_TYPE_DEVICE_MEMORY, va("Memory: dynamic lightmap #%d", texture));
}
if (++vk_lms.current_lightmap_texture == MAX_LIGHTMAPS)
{
ri.Sys_Error(ERR_DROP,
"%s() - MAX_LIGHTMAPS exceeded\n", __func__);
}
}
}
/*
* returns a texture number and the position inside it
*/
static qboolean
LM_AllocBlock(int w, int h, int *x, int *y)
{
int i, best;
best = BLOCK_HEIGHT;
for (i = 0; i < BLOCK_WIDTH - w; i++)
{
int j, best2;
best2 = 0;
for (j = 0; j < w; j++)
{
if (vk_lms.allocated[i + j] >= best)
{
break;
}
if (vk_lms.allocated[i + j] > best2)
{
best2 = vk_lms.allocated[i + j];
}
}
if (j == w)
{
/* this is a valid spot */
*x = i;
*y = best = best2;
}
}
if (best + h > BLOCK_HEIGHT)
{
return false;
}
for (i = 0; i < w; i++)
{
vk_lms.allocated[*x + i] = best + h;
}
return true;
}
void
Vk_BuildPolygonFromSurface(model_t *currentmodel, msurface_t *fa)
{
int i, lnumverts;
medge_t *pedges, *r_pedge;
float *vec;
mpoly_t *poly;
vec3_t total;
vec3_t normal;
/* reconstruct the polygon */
pedges = currentmodel->edges;
lnumverts = fa->numedges;
VectorClear(total);
/* draw texture */
poly = Hunk_Alloc(sizeof(mpoly_t) +
(lnumverts - 4) * sizeof(mvtx_t));
poly->next = fa->polys;
poly->flags = fa->flags;
fa->polys = poly;
poly->numverts = lnumverts;
VectorCopy(fa->plane->normal, normal);
if(fa->flags & SURF_PLANEBACK)
{
// if for some reason the normal sticks to the back of the plane, invert it
// so it's usable for the shader
for (i=0; i<3; ++i) normal[i] = -normal[i];
}
for (i = 0; i < lnumverts; i++)
{
mvtx_t* vert;
float s, t;
int lindex;
vert = &poly->verts[i];
lindex = currentmodel->surfedges[fa->firstedge + i];
if (lindex > 0)
{
r_pedge = &pedges[lindex];
vec = currentmodel->vertexes[r_pedge->v[0]].position;
}
else
{
r_pedge = &pedges[-lindex];
vec = currentmodel->vertexes[r_pedge->v[1]].position;
}
s = DotProduct(vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
s /= fa->texinfo->image->width;
t = DotProduct(vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
t /= fa->texinfo->image->height;
VectorAdd(total, vec, total);
VectorCopy(vec, vert->pos);
vert->texCoord[0] = s;
vert->texCoord[1] = t;
/* lightmap texture coordinates */
s = DotProduct(vec, fa->lmvecs[0]) + fa->lmvecs[0][3];
s -= fa->texturemins[0];
s += fa->light_s * (1 << fa->lmshift);
s += (1 << fa->lmshift) * 0.5;
s /= BLOCK_WIDTH * (1 << fa->lmshift);
t = DotProduct(vec, fa->lmvecs[1]) + fa->lmvecs[1][3];
t -= fa->texturemins[1];
t += fa->light_t * (1 << fa->lmshift);
t += (1 << fa->lmshift) * 0.5;
t /= BLOCK_HEIGHT * (1 << fa->lmshift);
vert->lmTexCoord[0] = s;
vert->lmTexCoord[1] = t;
VectorCopy(normal, vert->normal);
vert->lightFlags = 0;
}
}
void
Vk_CreateSurfaceLightmap(msurface_t *surf)
{
int smax, tmax;
byte *base;
if (surf->flags & (SURF_DRAWSKY | SURF_DRAWTURB))
{
return;
}
smax = (surf->extents[0] >> surf->lmshift) + 1;
tmax = (surf->extents[1] >> surf->lmshift) + 1;
if (!LM_AllocBlock(smax, tmax, &surf->light_s, &surf->light_t))
{
LM_UploadBlock(false);
LM_InitBlock();
if (!LM_AllocBlock(smax, tmax, &surf->light_s, &surf->light_t))
{
ri.Sys_Error(ERR_FATAL,
"%s: Consecutive calls to LM_AllocBlock(%d,%d) failed\n",
__func__, smax, tmax);
}
}
surf->lightmaptexturenum = vk_lms.current_lightmap_texture;
base = vk_lms.lightmap_buffer;
base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * LIGHTMAP_BYTES;
R_SetCacheState(surf);
R_BuildLightMap(surf, base, BLOCK_WIDTH * LIGHTMAP_BYTES);
}
void
Vk_BeginBuildingLightmaps(model_t *m)
{
static lightstyle_t lightstyles[MAX_LIGHTSTYLES];
int i;
memset(vk_lms.allocated, 0, sizeof(vk_lms.allocated));
r_framecount = 1; /* no dlightcache */
/* setup the base lightstyles so the lightmaps
won't have to be regenerated the first time
they're seen */
for (i = 0; i < MAX_LIGHTSTYLES; i++)
{
lightstyles[i].rgb[0] = 1;
lightstyles[i].rgb[1] = 1;
lightstyles[i].rgb[2] = 1;
lightstyles[i].white = 3;
}
r_newrefdef.lightstyles = lightstyles;
vk_lms.current_lightmap_texture = 0;
/*
** initialize the dynamic lightmap textures
*/
if (vk_state.lightmap_textures[DYNLIGHTMAP_OFFSET].resource.image == VK_NULL_HANDLE)
{
for (i = DYNLIGHTMAP_OFFSET; i < MAX_LIGHTMAPS*2; i++)
{
unsigned dummy[BLOCK_WIDTH * BLOCK_HEIGHT];
QVVKTEXTURE_CLEAR(vk_state.lightmap_textures[i]);
QVk_CreateTexture(&vk_state.lightmap_textures[i], (unsigned char*)dummy,
BLOCK_WIDTH, BLOCK_HEIGHT, vk_current_lmap_sampler, false);
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[i].resource.image,
VK_OBJECT_TYPE_IMAGE, va("Image: dynamic lightmap #%d", i));
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[i].imageView,
VK_OBJECT_TYPE_IMAGE_VIEW, va("Image View: dynamic lightmap #%d", i));
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[i].descriptorSet,
VK_OBJECT_TYPE_DESCRIPTOR_SET, va("Descriptor Set: dynamic lightmap #%d", i));
QVk_DebugSetObjectName((uint64_t)vk_state.lightmap_textures[i].resource.memory,
VK_OBJECT_TYPE_DEVICE_MEMORY, va("Memory: dynamic lightmap #%d", i));
}
}
}
void
Vk_EndBuildingLightmaps(void)
{
LM_UploadBlock(false);
}