light: bounce: refactor to do in a second lighting pass
This commit is contained in:
parent
8db1f56a20
commit
a0f636a69a
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 = <face_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 = <face_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*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
Loading…
Reference in New Issue