mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-26 06:20:48 +00:00
R_RecursiveLightPoint: Share part of light logic
This commit is contained in:
parent
a381c9dc5d
commit
8f5a40710b
18 changed files with 548 additions and 1108 deletions
1
Makefile
1
Makefile
|
@ -1141,6 +1141,7 @@ REFVK_OBJS_ := \
|
|||
src/client/refresh/vk/vk_draw.o \
|
||||
src/client/refresh/vk/vk_image.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_model.o \
|
||||
src/client/refresh/vk/vk_pipeline.o \
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#ifndef REF_MODEL_H
|
||||
#define REF_MODEL_H
|
||||
|
||||
#include "../../ref_model.h"
|
||||
|
||||
/* Whole model */
|
||||
|
||||
typedef struct model_s
|
||||
|
|
|
@ -106,129 +106,6 @@ GL3_PushDlights(void)
|
|||
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
|
||||
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
|
||||
// for shadow position and maybe lighting on model?
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -36,40 +36,6 @@ typedef struct gl3_alias_vtx_s {
|
|||
|
||||
/* 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 */
|
||||
|
||||
// this, must be struct model_s, not gl3model_s,
|
||||
|
|
|
@ -106,129 +106,6 @@ GL4_PushDlights(void)
|
|||
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
|
||||
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
|
||||
// for shadow position and maybe lighting on model?
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -36,40 +36,6 @@ typedef struct gl4_alias_vtx_s {
|
|||
|
||||
/* 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 */
|
||||
|
||||
// this, must be struct model_s, not gl4model_s,
|
||||
|
|
|
@ -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;
|
|
@ -121,6 +121,8 @@ enum {
|
|||
SURF_UNDERWATER = 0x80
|
||||
};
|
||||
|
||||
/* in memory representation */
|
||||
|
||||
typedef struct mvertex_s
|
||||
{
|
||||
vec3_t position;
|
||||
|
@ -200,6 +202,64 @@ typedef struct mpoly_s
|
|||
mvtx_t verts[4]; /* variable sized */
|
||||
} 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 */
|
||||
#define LGNODE_LEAF (1u<<31)
|
||||
#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 void BSPX_LightGridValue(const bspxlightgrid_t *grid, const lightstyle_t *lightstyles,
|
||||
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_ */
|
||||
|
|
|
@ -252,20 +252,6 @@ typedef struct clipplane_s
|
|||
byte rightedge;
|
||||
} 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
|
||||
{
|
||||
int u, v, count;
|
||||
|
|
|
@ -42,35 +42,6 @@ BRUSH MODELS
|
|||
// 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;
|
||||
|
||||
//===================================================================
|
||||
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -226,7 +104,7 @@ R_LightPoint (const entity_t *currententity, vec3_t p, vec3_t color)
|
|||
end[2] = p[2] - 2048;
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -258,6 +258,10 @@ void Vk_ShutdownImages (void);
|
|||
void Vk_FreeUnusedImages (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);
|
||||
struct model_s *RE_RegisterModel (const char *name);
|
||||
struct image_s *RE_RegisterSkin (const char *name);
|
||||
|
@ -298,6 +302,24 @@ typedef struct
|
|||
#define MAX_LIGHTMAPS 256
|
||||
#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
|
||||
{
|
||||
float inverse_intensity;
|
||||
|
|
|
@ -47,8 +47,6 @@ BRUSH MODELS
|
|||
// in memory representation
|
||||
//
|
||||
|
||||
#include "../../ref_model.h"
|
||||
|
||||
/* Whole model */
|
||||
|
||||
typedef struct model_s
|
||||
|
|
|
@ -173,129 +173,6 @@ LIGHT SAMPLING
|
|||
|
||||
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
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
322
src/client/refresh/vk/vk_lightmap.c
Normal file
322
src/client/refresh/vk/vk_lightmap.c
Normal 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);
|
||||
}
|
||||
|
|
@ -34,29 +34,7 @@ int c_visible_textures;
|
|||
static vec3_t modelorg; /* relative to viewpoint */
|
||||
msurface_t *r_alpha_surfaces;
|
||||
|
||||
static void LM_InitBlock(void);
|
||||
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;
|
||||
vklightmapstate_t vk_lms;
|
||||
|
||||
static void
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue