light: bounce: refactor to do in a second lighting pass

This commit is contained in:
Eric Wasylishen 2016-05-19 02:53:18 -06:00
parent 8db1f56a20
commit a0f636a69a
4 changed files with 179 additions and 33 deletions

View File

@ -25,6 +25,7 @@
#include <common/bspfile.h>
#include <common/log.h>
#include <common/threads.h>
#include <common/polylib.h>
#include <light/litfile.h>
#ifdef __cplusplus
@ -48,6 +49,9 @@ qboolean TestSky(const vec3_t start, const vec3_t dirn, const dmodel_t *self);
qboolean TestLight(const vec3_t start, const vec3_t stop, const dmodel_t *self);
qboolean DirtTrace(const vec3_t start, const vec3_t stop, const dmodel_t *self, vec3_t hitpoint_out, plane_t *hitplane_out, const bsp2_dface_t **face_out);
int
SampleTexture(const bsp2_dface_t *face, const bsp2_t *bsp, const vec3_t point);
typedef struct {
vec_t light;
vec3_t color;
@ -134,6 +138,10 @@ typedef struct {
/* for sphere culling */
vec3_t origin;
vec_t radius;
// for radiosity
vec3_t radiosity;
vec3_t texturecolor;
/* stuff used by CalcPoint */
vec_t starts, startt, st_step;
@ -153,6 +161,8 @@ struct ltface_ctx
lightmap_t lightmaps[MAXLIGHTMAPS + 1];
};
extern struct ltface_ctx *ltface_ctxs;
/* bounce lights */
typedef struct {
@ -162,7 +172,12 @@ typedef struct {
vec_t area;
const bsp2_dleaf_t *leaf;
} bouncelight_t;
void AddBounceLight(const vec3_t pos, const vec3_t color, const vec3_t surfnormal, vec_t area, const bsp2_t *bsp);
int NumBounceLights();
const bouncelight_t *BounceLightAtIndex(int i);
winding_t *WindingFromFace (const bsp2_t *bsp, const bsp2_dface_t *f);
extern const bouncelight_t *bouncelights;
extern int numbouncelights;
extern byte thepalette[768];
@ -171,11 +186,11 @@ extern byte thepalette[768];
extern const modelinfo_t *const *tracelist;
extern const modelinfo_t *const *selfshadowlist;
struct ltface_ctx;
struct ltface_ctx *LightFaceInit(const bsp2_t *bsp);
void LightFaceInit(const bsp2_t *bsp, struct ltface_ctx *ctx);
void LightFaceShutdown(struct ltface_ctx *ctx);
const modelinfo_t *ModelInfoForFace(const bsp2_t *bsp, int facenum);
void LightFace(bsp2_dface_t *face, facesup_t *facesup, const modelinfo_t *modelinfo, struct ltface_ctx *ctx);
void LightFaceIndirect(bsp2_dface_t *face, facesup_t *facesup, const modelinfo_t *modelinfo, struct ltface_ctx *ctx);
void MakeTnodes(const bsp2_t *bsp);
/* access the final phong-shaded vertex normal */

View File

@ -109,6 +109,8 @@ uint32_t *extended_texinfo_flags = NULL;
char mapfilename[1024];
struct ltface_ctx *ltface_ctxs;
void
GetFileSpace(byte **lightdata, byte **colordata, byte **deluxdata, int size)
{
@ -175,7 +177,9 @@ LightThread(void *arg)
if (facenum == -1)
break;
ctx = LightFaceInit(bsp);
ctx = &ltface_ctxs[facenum];
LightFaceInit(bsp, ctx);
/* Find the correct model offset */
face_modelinfo = ModelInfoForFace(bsp, facenum);
@ -206,12 +210,44 @@ LightThread(void *arg)
LightFace(bsp->dfaces + facenum, faces_sup + facenum, face_modelinfo, ctx);
}
LightFaceShutdown(ctx);
/* If bouncing, keep lightmaps in memory because we run a second lighting pass.
* Otherwise free memory now, so only (# threads) lightmaps are in memory at a time.
*/
if (!bounce) {
LightFaceShutdown(ctx);
}
}
return NULL;
}
static void *
LightThreadBounce(void *arg)
{
int facenum;
const bsp2_t *bsp = (const bsp2_t *) arg;
const modelinfo_t *face_modelinfo;
struct ltface_ctx *ctx;
while (1) {
facenum = GetThreadWork();
if (facenum == -1)
break;
ctx = &ltface_ctxs[facenum];
/* Find the correct model offset */
face_modelinfo = ModelInfoForFace(bsp, facenum);
if (face_modelinfo == NULL)
continue;
LightFaceIndirect(bsp->dfaces + facenum, NULL, face_modelinfo, ctx);
LightFaceShutdown(ctx);
}
return NULL;
}
static void
FindModelInfo(const bsp2_t *bsp, const char *lmscaleoverride)
{
@ -692,9 +728,18 @@ LightWorld(bspdata_t *bspdata, qboolean forcedscale)
CalcualateVertexNormals(bsp);
/* ericw -- alloc memory */
ltface_ctxs = (struct ltface_ctx *)calloc(bsp->numfaces, sizeof(struct ltface_ctx));
logprint("==LightThread==\n");
RunThreadsOn(0, bsp->numfaces, LightThread, bsp);
logprint("Lighting Completed.\n\n");
if (bounce) {
logprint("==LightThreadBounce==\n");
RunThreadsOn(0, bsp->numfaces, LightThreadBounce, bsp);
}
logprint("Lighting Completed.\n\n");
bsp->lightdatasize = file_p - filebase;
logprint("lightdatasize: %i\n", bsp->lightdatasize);
@ -760,12 +805,11 @@ LoadExtendedTexinfoFlags(const char *sourcefilename, const bsp2_t *bsp)
// radiosity
mutex radlights_lock;
map<string, vec3_struct_t> texturecolors;
std::vector<bouncelight_t> radlights;
// for access from C
const bouncelight_t *bouncelights;
int numbouncelights;
class patch_t {
public:
@ -790,6 +834,7 @@ public:
}
};
#if 0
void
GetDirectLighting(const vec3_t origin, const vec3_t normal, vec3_t colorout)
{
@ -826,6 +871,7 @@ GetDirectLighting(const vec3_t origin, const vec3_t normal, vec3_t colorout)
std::vector<patch_t *> triangleIndexToPatch;
std::unordered_map<int, std::vector<patch_t *>> facenumToPatches;
mutex facenumToPatches_mutex;
#endif
/*
=============
@ -863,7 +909,7 @@ winding_t *WindingFromFace (const bsp2_t *bsp, const bsp2_dface_t *f)
return w;
}
#if 0
void SavePatch (const bsp2_t *bsp, const bsp2_dface_t *sourceface, winding_t *w)
{
int i = sourceface - bsp->dfaces;
@ -983,6 +1029,32 @@ MakeBounceLightsThread (void *arg)
return NULL;
}
#endif
void AddBounceLight(const vec3_t pos, const vec3_t color, const vec3_t surfnormal, vec_t area, const bsp2_t *bsp)
{
bouncelight_t l;
VectorCopy(pos, l.pos);
VectorCopy(color, l.color);
VectorCopy(surfnormal, l.surfnormal);
l.area = area;
l.leaf = Light_PointInLeaf(bsp, pos);
unique_lock<mutex> lck { radlights_lock };
radlights.push_back(l);
}
int NumBounceLights()
{
return radlights.size();
}
const bouncelight_t *BounceLightAtIndex(int i)
{
return &radlights.at(i);
}
#if 0
// Returns color in [0,1]
void Texture_AvgColor (const bsp2_t *bsp, const miptex_t *miptex, vec3_t color)
@ -1075,6 +1147,7 @@ void MakeBounceLights (const bsp2_t *bsp)
bouncelights = radlights.data();
numbouncelights = radlights.size();
}
#endif
// end radiosity
@ -1431,12 +1504,6 @@ main(int argc, const char **argv)
SetupDirt();
MakeTnodes(bsp);
if (bounce) {
MakeTextureColors(bsp);
MakeBounceLights(bsp);
}
LightWorld(&bspdata, !!lmscaleoverride);
/*invalidate any bspx lighting info early*/

View File

@ -1632,8 +1632,9 @@ LightFace_Bounce(const bsp2_t *bsp, const bsp2_dface_t *face, const lightsurf_t
/* use a style 0 light map */
lightmap = Lightmap_ForStyle(lightmaps, 0, lightsurf);
const int numbouncelights = NumBounceLights();
for (int j=0; j<numbouncelights; j++) {
const bouncelight_t *vpl = &bouncelights[j];
const bouncelight_t *vpl = BounceLightAtIndex(j);
if (VisCullEntity(bsp, lightsurf->pvs, vpl->leaf))
continue;
@ -1715,6 +1716,21 @@ void SetupDirt( void ) {
logprint("%9d dirtmap vectors\n", numDirtVectors );
}
static const lightmap_t *
Lightmap_ForStyle_ReadOnly(const struct ltface_ctx *ctx, const int style)
{
const lightmap_t *lightmap = ctx->lightmaps;
int i;
for (i = 0; i < MAXLIGHTMAPS; i++, lightmap++) {
if (lightmap->style == style)
return lightmap;
if (lightmap->style == 255)
break;
}
return NULL;
}
/*
* ============
* DirtForSample
@ -1945,15 +1961,18 @@ WriteLightmaps(bsp2_dface_t *face, facesup_t *facesup, const lightsurf_t *lights
}
}
struct ltface_ctx *LightFaceInit(const bsp2_t *bsp)
void LightFaceInit(const bsp2_t *bsp, struct ltface_ctx *ctx)
{
//windows stack probes can get expensive when its 64mb...
//also, this avoids stack overflows, or the need to guess stack sizes.
struct ltface_ctx *ctx = calloc(1, sizeof(*ctx));
if (ctx)
ctx->bsp = bsp;
return ctx;
int i;
memset(ctx, 0, sizeof(*ctx));
ctx->bsp = bsp;
for (i = 0; i < MAXLIGHTMAPS + 1; i++)
ctx->lightmaps[i].style = 255;
}
void LightFaceShutdown(struct ltface_ctx *ctx)
{
int i;
@ -1977,8 +1996,6 @@ void LightFaceShutdown(struct ltface_ctx *ctx)
if (ctx->lightsurf.pvs)
free(ctx->lightsurf.pvs);
free(ctx);
}
const char *
@ -2052,7 +2069,7 @@ LightFace(bsp2_dface_t *face, facesup_t *facesup, const modelinfo_t *modelinfo,
* clamp any values that may have gone negative.
*/
if (!dirtDebug && !phongDebug && !bouncedebug) {
if (!dirtDebug && !phongDebug) {
/* positive lights */
for (lighte = lights; (entity = *lighte); lighte++)
{
@ -2084,11 +2101,6 @@ LightFace(bsp2_dface_t *face, facesup_t *facesup, const modelinfo_t *modelinfo,
LightFace_Sky (sun, lightsurf, lightmaps);
}
if (!dirtDebug && !phongDebug) {
/* add indirect lighting */
LightFace_Bounce(bsp, face, lightsurf, lightmaps);
}
/* replace lightmaps with AO for debugging */
if (dirtDebug)
LightFace_DirtDebug(lightsurf, lightmaps);
@ -2120,6 +2132,58 @@ LightFace(bsp2_dface_t *face, facesup_t *facesup, const modelinfo_t *modelinfo,
Lightmap_Soften(&lightmaps[i], lightsurf);
}
}
/* Calc average brightness */
// FIXME: don't count occluded samples
VectorSet(lightsurf->radiosity, 0, 0, 0);
lightmap_t *lightmap = Lightmap_ForStyle(lightmaps, 0, lightsurf);
sample = lightmap->samples;
for (j = 0; j < lightsurf->numpoints; j++, sample++) {
vec3_t color;
VectorCopy(sample->color, color);
VectorAdd(lightsurf->radiosity, color, lightsurf->radiosity);
}
VectorScale(lightsurf->radiosity, 1.0/lightsurf->numpoints, lightsurf->radiosity);
// clamp components at 512
// for (int i=0;i<3;i++)
// lightsurf->radiosity[i] = qmin(512.0f, lightsurf->radiosity[i]);
/* Calc average texture color */
VectorSet(lightsurf->texturecolor, 0, 0, 0);
for (j = 0; j < lightsurf->numpoints; j++) {
int palidx = SampleTexture(face, bsp, lightsurf->points[j]);
vec3_t texcolor = {thepalette[3*palidx], thepalette[3*palidx + 1], thepalette[3*palidx + 2]};
VectorAdd(lightsurf->texturecolor, texcolor, lightsurf->texturecolor);
}
VectorScale(lightsurf->texturecolor, 1.0f/lightsurf->numpoints, lightsurf->texturecolor);
// make bounce light
if (bounce) {
vec3_t emitcolor;
for (int k=0; k<3; k++) {
emitcolor[k] = (lightsurf->radiosity[k] / 255.0f) * (lightsurf->texturecolor[k] / 255.0f);
}
winding_t *w = WindingFromFace(bsp, face);
AddBounceLight(lightsurf->midpoint, emitcolor, lightsurf->plane.normal, WindingArea(w), bsp);
free(w);
} else {
WriteLightmaps(face, facesup, lightsurf, lightmaps);
}
}
void
LightFaceIndirect(bsp2_dface_t *face, facesup_t *facesup, const modelinfo_t *modelinfo, struct ltface_ctx *ctx)
{
lightmap_t *lightmaps = ctx->lightmaps;
lightsurf_t *lightsurf = &ctx->lightsurf;
if (bouncedebug)
{
Lightmap_ClearAll(lightmaps);
}
/* add indirect lighting */
LightFace_Bounce(ctx->bsp, face, lightsurf, lightmaps);
WriteLightmaps(face, facesup, lightsurf, lightmaps);
}

View File

@ -345,7 +345,7 @@ vec_t fix_coord(vec_t in, int width)
}
}
static int
int
SampleTexture(const bsp2_dface_t *face, const bsp2_t *bsp, const vec3_t point)
{
vec_t texcoord[2];