light: bounce styled lights
This commit is contained in:
parent
4c1a12cf67
commit
48a6314dfb
|
|
@ -25,12 +25,13 @@
|
|||
#include <common/mathlib.hh>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
typedef struct {
|
||||
vec3_t pos;
|
||||
vec3_t color;
|
||||
std::map<int, glm::vec3> colorByStyle;
|
||||
vec3_t surfnormal;
|
||||
vec_t area;
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ void WorldToTexCoord(const vec3_t world, const texinfo_t *tex, vec_t coord[2]);
|
|||
void PrintFaceInfo(const bsp2_dface_t *face, const bsp2_t *bsp);
|
||||
// FIXME: remove light param. add normal param and dir params.
|
||||
vec_t GetLightValue(const globalconfig_t &cfg, const light_t *entity, vec_t dist);
|
||||
void GetDirectLighting(const globalconfig_t &cfg, raystream_t *rs, const vec3_t origin, const vec3_t normal, vec3_t colorout);
|
||||
std::map<int, glm::vec3> GetDirectLighting(const globalconfig_t &cfg, raystream_t *rs, const vec3_t origin, const vec3_t normal);
|
||||
void SetupDirt(globalconfig_t &cfg);
|
||||
float DirtAtPoint(const globalconfig_t &cfg, raystream_t *rs, const vec3_t point, const vec3_t normal, const dmodel_t *selfshadow);
|
||||
void LightFace(const bsp2_t *bsp, bsp2_dface_t *face, facesup_t *facesup, const globalconfig_t &cfg);
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ public:
|
|||
vec3_t center;
|
||||
vec3_t samplepoint; // 1 unit above center
|
||||
plane_t plane;
|
||||
vec3_t directlight;
|
||||
std::map<int, glm::vec3> lightByStyle;
|
||||
};
|
||||
|
||||
static unique_ptr<patch_t>
|
||||
|
|
@ -75,7 +75,7 @@ MakePatch (const globalconfig_t &cfg, winding_t *w)
|
|||
// calculate direct light
|
||||
|
||||
raystream_t *rs = MakeRayStream(numDirtVectors);
|
||||
GetDirectLighting(cfg, rs, p->samplepoint, p->plane.normal, p->directlight);
|
||||
p->lightByStyle = GetDirectLighting(cfg, rs, p->samplepoint, p->plane.normal);
|
||||
delete rs;
|
||||
|
||||
return p;
|
||||
|
|
@ -132,7 +132,7 @@ Face_LookupTextureColor(const bsp2_t *bsp, const bsp2_dface_t *face, vec3_t colo
|
|||
}
|
||||
|
||||
static void
|
||||
AddBounceLight(const vec3_t pos, const vec3_t color, const vec3_t surfnormal, vec_t area, const bsp2_dface_t *face, const bsp2_t *bsp);
|
||||
AddBounceLight(const vec3_t pos, const std::map<int, glm::vec3> &colorByStyle, const vec3_t surfnormal, vec_t area, const bsp2_dface_t *face, const bsp2_t *bsp);
|
||||
|
||||
static void *
|
||||
MakeBounceLightsThread (void *arg)
|
||||
|
|
@ -172,17 +172,22 @@ MakeBounceLightsThread (void *arg)
|
|||
winding = nullptr; // DiceWinding frees winding
|
||||
|
||||
// average them, area weighted
|
||||
vec3_t sum = {0,0,0};
|
||||
map<int, glm::vec3> sum;
|
||||
float totalarea = 0;
|
||||
|
||||
for (const auto &patch : patches) {
|
||||
const float patcharea = WindingArea(patch->w);
|
||||
totalarea += patcharea;
|
||||
|
||||
VectorMA(sum, patcharea, patch->directlight, sum);
|
||||
for (const auto &styleColor : patch->lightByStyle) {
|
||||
sum[styleColor.first] = sum[styleColor.first] + (patcharea * styleColor.second);
|
||||
}
|
||||
// printf(" %f %f %f\n", patch->directlight[0], patch->directlight[1], patch->directlight[2]);
|
||||
}
|
||||
VectorScale(sum, 1.0/totalarea, sum);
|
||||
|
||||
for (auto &styleColor : sum) {
|
||||
styleColor.second *= (1.0/totalarea);
|
||||
}
|
||||
|
||||
// avoid small, or zero-area patches ("sum" would be nan)
|
||||
if (totalarea < 1) {
|
||||
|
|
@ -198,29 +203,35 @@ MakeBounceLightsThread (void *arg)
|
|||
VectorMA(blendedcolor, cfg.bouncecolorscale.floatValue(), texturecolor, blendedcolor);
|
||||
VectorMA(blendedcolor, 1-cfg.bouncecolorscale.floatValue(), gray, blendedcolor);
|
||||
|
||||
// final color to emit
|
||||
vec3_t emitcolor;
|
||||
for (int k=0; k<3; k++) {
|
||||
emitcolor[k] = (sum[k] / 255.0f) * (blendedcolor[k] / 255.0f);
|
||||
// final colors to emit
|
||||
map<int, glm::vec3> emitcolors;
|
||||
for (const auto &styleColor : sum) {
|
||||
glm::vec3 emitcolor(0);
|
||||
for (int k=0; k<3; k++) {
|
||||
emitcolor[k] = (styleColor.second[k] / 255.0f) * (blendedcolor[k] / 255.0f);
|
||||
}
|
||||
emitcolors[styleColor.first] = emitcolor;
|
||||
}
|
||||
|
||||
AddBounceLight(facemidpoint, emitcolor, faceplane.normal, facearea, face, bsp);
|
||||
|
||||
AddBounceLight(facemidpoint, emitcolors, faceplane.normal, facearea, face, bsp);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
AddBounceLight(const vec3_t pos, const vec3_t color, const vec3_t surfnormal, vec_t area, const bsp2_dface_t *face, const bsp2_t *bsp)
|
||||
AddBounceLight(const vec3_t pos, const std::map<int, glm::vec3> &colorByStyle, const vec3_t surfnormal, vec_t area, const bsp2_dface_t *face, const bsp2_t *bsp)
|
||||
{
|
||||
Q_assert(color[0] >= 0);
|
||||
Q_assert(color[1] >= 0);
|
||||
Q_assert(color[2] >= 0);
|
||||
for (const auto &styleColor : colorByStyle) {
|
||||
Q_assert(styleColor.second[0] >= 0);
|
||||
Q_assert(styleColor.second[1] >= 0);
|
||||
Q_assert(styleColor.second[2] >= 0);
|
||||
}
|
||||
Q_assert(area > 0);
|
||||
|
||||
bouncelight_t l = {0};
|
||||
VectorCopy(pos, l.pos);
|
||||
VectorCopy(color, l.color);
|
||||
l.colorByStyle = colorByStyle;
|
||||
VectorCopy(surfnormal, l.surfnormal);
|
||||
l.area = area;
|
||||
|
||||
|
|
|
|||
179
light/ltface.cc
179
light/ltface.cc
|
|
@ -840,6 +840,14 @@ Lightmap_ForStyle(lightmapdict_t *lightmaps, const int style, const lightsurf_t
|
|||
return &lightmaps->back();
|
||||
}
|
||||
|
||||
static void
|
||||
Lightmap_ClearAll(lightmapdict_t *lightmaps)
|
||||
{
|
||||
for (auto &lm : *lightmaps) {
|
||||
lm.style = 255;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Lightmap_Save
|
||||
*
|
||||
|
|
@ -1214,26 +1222,21 @@ static void LightFace_SampleMipTex(miptex_t *tex, const float *projectionmatrix,
|
|||
}
|
||||
|
||||
// FIXME: factor out / merge with LightFace
|
||||
void
|
||||
GetDirectLighting(const globalconfig_t &cfg, raystream_t *rs, const vec3_t origin, const vec3_t normal, vec3_t colorout)
|
||||
std::map<int, glm::vec3>
|
||||
GetDirectLighting(const globalconfig_t &cfg, raystream_t *rs, const vec3_t origin, const vec3_t normal)
|
||||
{
|
||||
std::map<int, glm::vec3> result;
|
||||
|
||||
float occlusion = DirtAtPoint(cfg, rs, origin, normal, /* FIXME: pass selfshadow? */ nullptr);
|
||||
if (std::isnan(occlusion)) {
|
||||
// HACK: getting an invalid normal of (0, 0, 0).
|
||||
occlusion = 0.0f;
|
||||
}
|
||||
|
||||
VectorSet(colorout, 0, 0, 0);
|
||||
|
||||
for (const light_t &entity : GetLights()) {
|
||||
vec3_t surfpointToLightDir;
|
||||
float surfpointToLightDist;
|
||||
vec3_t color, normalcontrib;
|
||||
|
||||
// NOTE: skip styled lights
|
||||
if (entity.style.intValue() != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GetLightContrib(cfg, &entity, normal, origin, false, color, surfpointToLightDir, normalcontrib, &surfpointToLightDist);
|
||||
|
||||
|
|
@ -1250,7 +1253,7 @@ GetDirectLighting(const globalconfig_t &cfg, raystream_t *rs, const vec3_t origi
|
|||
continue;
|
||||
}
|
||||
|
||||
VectorAdd(colorout, color, colorout);
|
||||
result[entity.style.intValue()] += vec3_t_to_glm(color);
|
||||
}
|
||||
|
||||
for (const sun_t &sun : GetSuns()) {
|
||||
|
|
@ -1280,8 +1283,12 @@ GetDirectLighting(const globalconfig_t &cfg, raystream_t *rs, const vec3_t origi
|
|||
dirt = Dirt_GetScaleFactor(cfg, occlusion, nullptr, 0.0, /* FIXME: pass */ nullptr);
|
||||
}
|
||||
|
||||
VectorMA(colorout, dirt * cosangle * sun.sunlight / 255.0f, sun.sunlight_color, colorout);
|
||||
const int sunstyle = 0;
|
||||
const glm::vec3 sunContrib = (dirt * cosangle * sun.sunlight / 255.0f) * vec3_t_to_glm(sun.sunlight_color);
|
||||
result[sunstyle] += sunContrib;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1633,34 +1640,37 @@ static void
|
|||
LightFace_BounceLightsDebug(const lightsurf_t *lightsurf, lightmapdict_t *lightmaps)
|
||||
{
|
||||
Q_assert(debugmode == debugmode_bouncelights);
|
||||
|
||||
// reset all lightmaps to black (lazily)
|
||||
Lightmap_ClearAll(lightmaps);
|
||||
|
||||
/* use a style 0 light map */
|
||||
lightmap_t *lightmap = Lightmap_ForStyle(lightmaps, 0, lightsurf);
|
||||
|
||||
vec3_t patch_color = {0,0,0};
|
||||
std::vector<bouncelight_t> vpls = BounceLightsForFaceNum(Face_GetNum(lightsurf->bsp, lightsurf->face));
|
||||
if (vpls.size()) {
|
||||
Q_assert(vpls.size() == 1); // for now only 1 vpl per face
|
||||
|
||||
const auto &vpl = vpls.at(0);
|
||||
VectorScale(vpl.color, 255, patch_color);
|
||||
for (const auto &styleColor : vpl.colorByStyle) {
|
||||
const glm::vec3 patch_color = styleColor.second * 255.0f;
|
||||
|
||||
lightmap_t *lightmap = Lightmap_ForStyle(lightmaps, styleColor.first, lightsurf);
|
||||
|
||||
/* Overwrite each point with the emitted color... */
|
||||
for (int i = 0; i < lightsurf->numpoints; i++) {
|
||||
lightsample_t *sample = &lightmap->samples[i];
|
||||
glm_to_vec3_t(patch_color, sample->color);
|
||||
}
|
||||
|
||||
Lightmap_Save(lightmaps, lightsurf, lightmap, styleColor.first);
|
||||
}
|
||||
}
|
||||
|
||||
/* Overwrite each point with the emitted color... */
|
||||
for (int i = 0; i < lightsurf->numpoints; i++) {
|
||||
lightsample_t *sample = &lightmap->samples[i];
|
||||
VectorCopy(patch_color, sample->color);
|
||||
}
|
||||
|
||||
Lightmap_Save(lightmaps, lightsurf, lightmap, 0);
|
||||
}
|
||||
|
||||
// returns color in [0,255]
|
||||
static inline void
|
||||
BounceLight_ColorAtDist(const globalconfig_t &cfg, const bouncelight_t *vpl, vec_t dist, vec3_t color)
|
||||
BounceLight_ColorAtDist(const globalconfig_t &cfg, const bouncelight_t *vpl, int style, vec_t dist, vec3_t color)
|
||||
{
|
||||
// get light contribution
|
||||
VectorScale(vpl->color, vpl->area, color);
|
||||
glm_to_vec3_t(vpl->colorByStyle.at(style) * vpl->area, color);
|
||||
|
||||
// clamp away hotspots
|
||||
if (dist < 128) {
|
||||
|
|
@ -1676,7 +1686,7 @@ BounceLight_ColorAtDist(const globalconfig_t &cfg, const bouncelight_t *vpl, vec
|
|||
// dir: vpl -> sample point direction
|
||||
// returns color in [0,255]
|
||||
static inline void
|
||||
GetIndirectLighting (const globalconfig_t &cfg, const bouncelight_t *vpl, const vec3_t dir, vec_t dist, const vec3_t origin, const vec3_t normal, vec3_t color)
|
||||
GetIndirectLighting (const globalconfig_t &cfg, const bouncelight_t *vpl, int style, const vec3_t dir, vec_t dist, const vec3_t origin, const vec3_t normal, vec3_t color)
|
||||
{
|
||||
VectorSet(color, 0, 0, 0);
|
||||
|
||||
|
|
@ -1698,14 +1708,14 @@ GetIndirectLighting (const globalconfig_t &cfg, const bouncelight_t *vpl, const
|
|||
return; // vpl behind sample face
|
||||
|
||||
// get light contribution
|
||||
BounceLight_ColorAtDist(cfg, vpl, dist, color);
|
||||
BounceLight_ColorAtDist(cfg, vpl, style, dist, color);
|
||||
|
||||
// apply angle scale
|
||||
VectorScale(color, dp1 * dp2, color);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
BounceLight_SphereCull(const bsp2_t *bsp, const bouncelight_t *vpl, const lightsurf_t *lightsurf)
|
||||
BounceLight_SphereCull(const bsp2_t *bsp, const bouncelight_t *vpl, int style, const lightsurf_t *lightsurf)
|
||||
{
|
||||
const globalconfig_t &cfg = *lightsurf->cfg;
|
||||
|
||||
|
|
@ -1720,7 +1730,7 @@ BounceLight_SphereCull(const bsp2_t *bsp, const bouncelight_t *vpl, const lights
|
|||
vec_t dist = VectorLength(dir) + lightsurf->radius;
|
||||
|
||||
// get light contribution
|
||||
BounceLight_ColorAtDist(cfg, vpl, dist, color);
|
||||
BounceLight_ColorAtDist(cfg, vpl, style, dist, color);
|
||||
|
||||
if (LightSample_Brightness(color) < 0.25)
|
||||
return true;
|
||||
|
|
@ -1733,7 +1743,6 @@ LightFace_Bounce(const bsp2_t *bsp, const bsp2_dface_t *face, const lightsurf_t
|
|||
{
|
||||
const globalconfig_t &cfg = *lightsurf->cfg;
|
||||
//const dmodel_t *shadowself = lightsurf->modelinfo->shadowself.boolValue() ? lightsurf->modelinfo->model : NULL;
|
||||
lightmap_t *lightmap;
|
||||
|
||||
if (!cfg.bounce.boolValue())
|
||||
return;
|
||||
|
|
@ -1742,67 +1751,71 @@ LightFace_Bounce(const bsp2_t *bsp, const bsp2_dface_t *face, const lightsurf_t
|
|||
|| debugmode == debugmode_none))
|
||||
return;
|
||||
|
||||
/* use a style 0 light map */
|
||||
lightmap = Lightmap_ForStyle(lightmaps, 0, lightsurf);
|
||||
|
||||
bool hit = false;
|
||||
|
||||
for (const bouncelight_t &vpl : BounceLights()) {
|
||||
if (BounceLight_SphereCull(bsp, &vpl, lightsurf))
|
||||
continue;
|
||||
|
||||
raystream_t *rs = lightsurf->stream;
|
||||
rs->clearPushedRays();
|
||||
|
||||
for (int i = 0; i < lightsurf->numpoints; i++) {
|
||||
if (lightsurf->occluded[i])
|
||||
// FIXME: This will trace the same ray multiple times, once per style,
|
||||
// if the bouncelight is hitting a face with multiple styles.
|
||||
for (const auto &styleColor : vpl.colorByStyle) {
|
||||
bool hit = false;
|
||||
const int style = styleColor.first;
|
||||
lightmap_t *lightmap = Lightmap_ForStyle(lightmaps, style, lightsurf);
|
||||
|
||||
if (BounceLight_SphereCull(bsp, &vpl, style, lightsurf))
|
||||
continue;
|
||||
|
||||
vec3_t dir; // vpl -> sample point
|
||||
VectorSubtract(lightsurf->points[i], vpl.pos, dir);
|
||||
vec_t dist = VectorNormalize(dir);
|
||||
raystream_t *rs = lightsurf->stream;
|
||||
rs->clearPushedRays();
|
||||
|
||||
vec3_t indirect = {0};
|
||||
GetIndirectLighting(cfg, &vpl, dir, dist, lightsurf->points[i], lightsurf->normals[i], indirect);
|
||||
|
||||
if (LightSample_Brightness(indirect) < 0.25)
|
||||
continue;
|
||||
|
||||
rs->pushRay(i, vpl.pos, dir, dist, /*shadowself*/ nullptr, indirect);
|
||||
}
|
||||
|
||||
total_bounce_rays += rs->numPushedRays();
|
||||
rs->tracePushedRaysOcclusion();
|
||||
|
||||
const int N = rs->numPushedRays();
|
||||
for (int j = 0; j < N; j++) {
|
||||
if (rs->getPushedRayOccluded(j))
|
||||
continue;
|
||||
|
||||
const int i = rs->getPushedRayPointIndex(j);
|
||||
vec3_t indirect = {0};
|
||||
rs->getPushedRayColor(j, indirect);
|
||||
|
||||
Q_assert(!std::isnan(indirect[0]));
|
||||
|
||||
/* Use dirt scaling on the indirect lighting.
|
||||
* Except, not in bouncedebug mode.
|
||||
*/
|
||||
if (debugmode != debugmode_bounce) {
|
||||
const vec_t dirtscale = Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], NULL, 0.0, lightsurf);
|
||||
VectorScale(indirect, dirtscale, indirect);
|
||||
for (int i = 0; i < lightsurf->numpoints; i++) {
|
||||
if (lightsurf->occluded[i])
|
||||
continue;
|
||||
|
||||
vec3_t dir; // vpl -> sample point
|
||||
VectorSubtract(lightsurf->points[i], vpl.pos, dir);
|
||||
vec_t dist = VectorNormalize(dir);
|
||||
|
||||
vec3_t indirect = {0};
|
||||
GetIndirectLighting(cfg, &vpl, style, dir, dist, lightsurf->points[i], lightsurf->normals[i], indirect);
|
||||
|
||||
if (LightSample_Brightness(indirect) < 0.25)
|
||||
continue;
|
||||
|
||||
rs->pushRay(i, vpl.pos, dir, dist, /*shadowself*/ nullptr, indirect);
|
||||
}
|
||||
|
||||
lightsample_t *sample = &lightmap->samples[i];
|
||||
VectorAdd(sample->color, indirect, sample->color);
|
||||
total_bounce_rays += rs->numPushedRays();
|
||||
rs->tracePushedRaysOcclusion();
|
||||
|
||||
hit = true;
|
||||
total_bounce_ray_hits++;
|
||||
const int N = rs->numPushedRays();
|
||||
for (int j = 0; j < N; j++) {
|
||||
if (rs->getPushedRayOccluded(j))
|
||||
continue;
|
||||
|
||||
const int i = rs->getPushedRayPointIndex(j);
|
||||
vec3_t indirect = {0};
|
||||
rs->getPushedRayColor(j, indirect);
|
||||
|
||||
Q_assert(!std::isnan(indirect[0]));
|
||||
|
||||
/* Use dirt scaling on the indirect lighting.
|
||||
* Except, not in bouncedebug mode.
|
||||
*/
|
||||
if (debugmode != debugmode_bounce) {
|
||||
const vec_t dirtscale = Dirt_GetScaleFactor(cfg, lightsurf->occlusion[i], NULL, 0.0, lightsurf);
|
||||
VectorScale(indirect, dirtscale, indirect);
|
||||
}
|
||||
|
||||
lightsample_t *sample = &lightmap->samples[i];
|
||||
VectorAdd(sample->color, indirect, sample->color);
|
||||
|
||||
hit = true;
|
||||
total_bounce_ray_hits++;
|
||||
}
|
||||
|
||||
// If this style of this bounce light contributed anything, save.
|
||||
if (hit)
|
||||
Lightmap_Save(lightmaps, lightsurf, lightmap, style);
|
||||
}
|
||||
}
|
||||
|
||||
if (hit)
|
||||
Lightmap_Save(lightmaps, lightsurf, lightmap, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
Loading…
Reference in New Issue