light: fix artifacting with translucent shadows

Embree is allowed to call the filter function more than necessary.
The previous implementation had side effects that would cause
the translucent shadows to get darker in this case.

As a limitation, we're back to only allowing 1 layer of glass per ray.
This commit is contained in:
Eric Wasylishen 2022-12-07 00:15:21 -07:00
parent 3e673d2119
commit a70c8f4835
5 changed files with 128 additions and 7 deletions

View File

@ -42,6 +42,10 @@ public:
std::vector<qvec3f> _ray_colors; std::vector<qvec3f> _ray_colors;
std::vector<qvec3d> _ray_normalcontribs; std::vector<qvec3d> _ray_normalcontribs;
std::vector<bool> _ray_hit_glass;
std::vector<qvec3f> _ray_glass_color;
std::vector<float> _ray_glass_opacity;
// This is set to the modelinfo's switchshadstyle if the ray hit // This is set to the modelinfo's switchshadstyle if the ray hit
// a dynamic shadow caster. (note that for rays that hit dynamic // a dynamic shadow caster. (note that for rays that hit dynamic
// shadow casters, all of the other hit data is assuming the ray went // shadow casters, all of the other hit data is assuming the ray went
@ -63,6 +67,9 @@ public:
_point_indices.resize(size); _point_indices.resize(size);
_ray_colors.resize(size); _ray_colors.resize(size);
_ray_normalcontribs.resize(size); _ray_normalcontribs.resize(size);
_ray_hit_glass.resize(size);
_ray_glass_color.resize(size);
_ray_glass_opacity.resize(size);
_ray_dynamic_styles.resize(size); _ray_dynamic_styles.resize(size);
} }
@ -74,10 +81,23 @@ public:
return _point_indices[j]; return _point_indices[j];
} }
inline qvec3f &getPushedRayColor(size_t j) inline qvec3f getPushedRayColor(size_t j)
{ {
Q_assert(j < _maxrays); Q_assert(j < _maxrays);
return _ray_colors[j]; qvec3f result = _ray_colors[j];
if (_ray_hit_glass[j]) {
const qvec3f glasscolor = _ray_glass_color[j];
const float opacity = _ray_glass_opacity[j];
// multiply ray color by glass color
const qvec3f tinted = result * glasscolor;
// lerp ray color between original ray color and fully tinted by the glass texture color, based on the glass opacity
result = mix(result, tinted, opacity);
}
return result;
} }
inline qvec3d &getPushedRayNormalContrib(size_t j) inline qvec3d &getPushedRayNormalContrib(size_t j)
@ -210,6 +230,7 @@ public:
if (normalcontrib) { if (normalcontrib) {
_ray_normalcontribs[_numrays] = *normalcontrib; _ray_normalcontribs[_numrays] = *normalcontrib;
} }
_ray_hit_glass[_numrays] = false;
_ray_dynamic_styles[_numrays] = 0; _ray_dynamic_styles[_numrays] = 0;
_numrays++; _numrays++;
} }
@ -296,6 +317,7 @@ public:
if (normalcontrib) { if (normalcontrib) {
_ray_normalcontribs[_numrays] = *normalcontrib; _ray_normalcontribs[_numrays] = *normalcontrib;
} }
_ray_hit_glass[_numrays] = false;
_ray_dynamic_styles[_numrays] = 0; _ray_dynamic_styles[_numrays] = 0;
_numrays++; _numrays++;
} }

View File

@ -678,11 +678,9 @@ static void AddGlassToRay(RTCIntersectContext *context, unsigned rayIndex, float
Q_assert(rayIndex < rs->_numrays); Q_assert(rayIndex < rs->_numrays);
// multiply ray color by glass color rs->_ray_hit_glass[rayIndex] = true;
qvec3f tinted = rs->_ray_colors[rayIndex] * glasscolor; rs->_ray_glass_color[rayIndex] = glasscolor;
rs->_ray_glass_opacity[rayIndex] = opacity;
// lerp ray color between original ray color and fully tinted by the glass texture color, based on the glass opacity
rs->_ray_colors[rayIndex] = mix(rs->_ray_colors[rayIndex], tinted, opacity);
} }
static void AddDynamicOccluderToRay(RTCIntersectContext *context, unsigned rayIndex, int style) static void AddDynamicOccluderToRay(RTCIntersectContext *context, unsigned rayIndex, int style)

View File

@ -0,0 +1,87 @@
// Game: Quake 2
// Format: Quake2 (Valve)
// entity 0
{
"mapversion" "220"
"classname" "worldspawn"
"_tb_textures" "textures/e1u1"
"_bounce" "0"
"_tb_def" "builtin:Quake2.fgd"
// brush 0
{
( -160 -256 16 ) ( -160 -255 16 ) ( -160 -256 17 ) e1u1/floor1_1 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1
( 80 -384 16 ) ( 80 -384 17 ) ( 81 -384 16 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( 80 -256 16 ) ( 81 -256 16 ) ( 80 -255 16 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( 496 -32 32 ) ( 496 -31 32 ) ( 497 -32 32 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( 496 368 32 ) ( 497 368 32 ) ( 496 368 33 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( 496 -32 32 ) ( 496 -32 33 ) ( 496 -31 32 ) e1u1/floor1_1 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1
}
// brush 1
{
( -160 -384 32 ) ( -160 -383 32 ) ( -160 -384 33 ) e1u1/floor1_1 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1
( -160 -384 32 ) ( -160 -384 33 ) ( -159 -384 32 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( -160 -384 32 ) ( -159 -384 32 ) ( -160 -383 32 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( 256 -320 288 ) ( 256 -319 288 ) ( 257 -320 288 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( 256 -320 48 ) ( 257 -320 48 ) ( 256 -320 49 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( 496 -320 48 ) ( 496 -320 49 ) ( 496 -319 48 ) e1u1/floor1_1 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1
}
// brush 2
{
( -160 304 32 ) ( -160 305 32 ) ( -160 304 33 ) e1u1/floor1_1 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1
( -160 304 32 ) ( -160 304 33 ) ( -159 304 32 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( -160 304 32 ) ( -159 304 32 ) ( -160 305 32 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( 256 368 288 ) ( 256 369 288 ) ( 257 368 288 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( 256 368 48 ) ( 257 368 48 ) ( 256 368 49 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( 496 368 48 ) ( 496 368 49 ) ( 496 369 48 ) e1u1/floor1_1 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1
}
// brush 3
{
( -160 240 32 ) ( -160 241 32 ) ( -160 240 33 ) e1u1/floor1_1 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1
( -784 -320 32 ) ( -784 -320 33 ) ( -783 -320 32 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( -784 240 32 ) ( -783 240 32 ) ( -784 241 32 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( -368 304 288 ) ( -368 305 288 ) ( -367 304 288 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( -368 304 48 ) ( -367 304 48 ) ( -368 304 49 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( -128 304 48 ) ( -128 304 49 ) ( -128 305 48 ) e1u1/floor1_1 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1
}
// brush 4
{
( -160 -256 288 ) ( -160 -255 288 ) ( -160 -256 289 ) e1u1/floor1_1 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1
( 80 -320 288 ) ( 80 -320 289 ) ( 81 -320 288 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( 80 -256 288 ) ( 81 -256 288 ) ( 80 -255 288 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( 496 -32 304 ) ( 496 -31 304 ) ( 497 -32 304 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( 496 304 304 ) ( 497 304 304 ) ( 496 304 305 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( 496 -32 304 ) ( 496 -32 305 ) ( 496 -31 304 ) e1u1/floor1_1 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1
}
// brush 5
{
( 496 240 32 ) ( 496 241 32 ) ( 496 240 33 ) e1u1/floor1_1 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1
( -128 -320 32 ) ( -128 -320 33 ) ( -127 -320 32 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( -128 240 32 ) ( -127 240 32 ) ( -128 241 32 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( 288 304 288 ) ( 288 305 288 ) ( 289 304 288 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1
( 288 304 48 ) ( 289 304 48 ) ( 288 304 49 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1
( 528 304 48 ) ( 528 304 49 ) ( 528 305 48 ) e1u1/floor1_1 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1
}
// brush 6
{
( 64 -176 176 ) ( 64 -175 176 ) ( 64 -176 177 ) e1u1/skip [ 0 -1 0 0 ] [ 0 0 -1 16 ] 0 1 1 32 128 0
( 24 -176 176 ) ( 24 -176 177 ) ( 25 -176 176 ) e1u1/skip [ -1.0000000000000002 0 0 16 ] [ 0 0 -1.0000000000000002 16 ] 0 1 1 32 128 0
( 24 -176 208 ) ( 25 -176 208 ) ( 24 -175 208 ) e1u1/skip [ 0 -1.0000000000000002 0 0 ] [ -1.0000000000000002 0 0 0 ] 0 1 1 32 128 0
( 336 48 224 ) ( 336 49 224 ) ( 337 48 224 ) e1u1/test [ 1 0 0 0 ] [ 0 -1 0 32 ] 0 2 2 32 16 0
( 336 0 184 ) ( 337 0 184 ) ( 336 0 185 ) e1u1/skip [ 1.0000000000000002 0 0 0 ] [ 0 0 -1.0000000000000002 16 ] 0 1 1 32 128 0
( 256 48 184 ) ( 256 48 185 ) ( 256 49 184 ) e1u1/skip [ 0 -1 0 0 ] [ 0 0 -1 16 ] 0 1 1 32 128 0
}
}
// entity 1
{
"classname" "info_player_start"
"origin" "152 -256 96"
"angle" "90"
}
// entity 2
{
"classname" "light"
"origin" "152 -96 248"
"light" "150"
"delay" "3"
"_anglesense" "0"
}

Binary file not shown.

View File

@ -222,3 +222,17 @@ TEST_CASE("q2_dirt") {
CHECK(sample == qvec3b(96)); CHECK(sample == qvec3b(96));
}); });
} }
TEST_CASE("q2_light_translucency") {
INFO("liquids cast translucent colored shadows (sampling texture) by default");
auto [bsp, bspx] = LoadTestmap("q2_light_translucency.map", {});
auto *face_under_water = BSP_FindFaceAtPoint(&bsp, &bsp.dmodels[0], {152, -96, 32});
REQUIRE(face_under_water);
CheckFaceLuxels(bsp, *face_under_water, [](qvec3b sample){
INFO("green color from the texture");
CHECK(sample == qvec3b(100, 150, 100));
});
}