Jump to content
The Dark Mod Forums

Trying to simulate bounce lighting... the (not so) easy way


MirceaKitsune
 Share

Recommended Posts

Almost there! More on / off comparisons for the time being, by toggling gas lamps and electric lights. If you look at dark spots in the distance you can see the slight ambiental brightness extending just a bit past the radius of the normal shadow-casting light. I'm thrilled by how physically accurate this feels, it's almost like I'm rendering in Blender with Cycles!

65fBLlf.jpg

vDaNMWu.jpg

k2DnkBW.jpg

ta9WKUA.jpg

222b7yV.jpg

Yr7pVyo.jpg

  • Like 1
Link to comment
Share on other sites

Here we go, next version 2.0 of the irradiance patch is out! Significant things that changed:

  • The spawnarg "areaLock" "origin" was added to contain bounce lights to their portal room. This fixes lights leaking through walls and causing ugly unjustified brightness on the other side. It should further improve performance too.
  • The spawnarg "ai_see" "0" is included to prevent the lights changing gameplay. This is a subtle effect for visual purposes only, not powerful enough to justify the AI seeing you more from the indirect light.
  • The spawnarg "hide_distance" was included to disable the effect beyond a given range and improve performance. Note that it's currently disabled due to #5699 causing the light to shine on lamps that are turned off.
  • Tweaked the color brightness and radius of each irradiance lamp to better match the light it represents.
  • Renamed "bounce" to "irradiance". While I'm trying to simulate bounce lighting, there's no bouncing going on as this is a rough estimation of irradiance with one ambient light, that name seemed more fitting.

Known issues remaining:

  • The areaLock spawnarg will cause the light not to travel through open doors or other portal surfaces, and will produce discrete cutoffs across portals where irradiance lamps intersect them. This is the only way to preventing wall leaks and far better compared to them, so for now it remains a necessary evil.
  • Performance will drop by a noticeable amount albeit it remains bearable. Ambient lights are among the cheapest type as they don't do diffuse / specular / shadows, the drop is minimized thanks to this but even they have their impact.
  • Playing with the mod on more complex maps may cause the engine to crash. Just created #5764 for more information on that. If you try it out in a complex FM expect occasional engine crashes to the desktop.

Things left to do that can be done:

  • At the moment all bounce lights use the builtin texture "lights/ambient_biground". Next time I may make a custom material I can also tweak for this purpose. This is namely to include flickering for the irradiance of flame based lights, which is a texture effect so no further performance impact should occur. Possibly expect that tomorrow.

tdm_irradiance_v2.0.pk4

At this point the pk4 is in a state where you can use it sanely: Please do so and let me know what you think! Remember this isn't a FM mod, do NOT place it in your fms folder unless you explicitly want to test it only with that FM: Put it directly inside your darkmod directory instead. It will automatically work on any FM you choose to play... only requirement is that it's using the official light defs for lamps which virtually every mission does. If you suspect it's being overridden or need an easier way to find it, append "Z-" at the start of the file name first so the engine always loads it last.

Link to comment
Share on other sites

1 hour ago, Filizitas said:

Does it still skip through the walls?

I added the "areaLock origin" spawnarg which sacrifices accuracy to stop wall leaks. You'll never have irradiance leak through a brush room again, but in exchange will see the effect cut off against any and every portal. This is definitely the better option and far less ugly... typically you'll only see it if you look closely, though I expect a lot of players will report the bright lines depending on how maps do their portal setup. I fear this may make it impossible to propose as an official change, though I'm satisfied even with being able to have this as an usable mod for the time being.

Link to comment
Share on other sites

Ending the night with something pretty: Here's a compilation of the best screenshots capturing the effect, taken in between recent tweaks. I find it marvelous to imagine this actually works in realtime, without any special lights or anything being pre-compiled in the FM itself, nor having to calculate any actual bounces. So close yet so far... there are sadly deal breakers I won't be able to surpass without engine changes, but I'll leave that one for tomorrow.

rERxx70.jpg
vnoYwy0.jpg
y2LsUgL.jpg
h7jX7ZF.jpg
vVgdlHU.jpg
Ghq7yAr.jpg
TvWdyYw.jpg
sqJM9JD.jpg
iAOzJUu.jpg
ilPF2CP.jpg
RgwQC0E.jpg
lNj4n3k.jpg
SryzEZj.jpg
bGRzxhE.jpg
EMC3AYA.jpg
OWLBwo3.jpg

  • Like 3
Link to comment
Share on other sites

Version 3.0. Not much changed this time: I made a custom material to use a square falloff image, this helps the lamp cover more ground to make the most of the effect. Tried making flame irradiance pulsate but it didn't work, prolly too subtle to matter. Unless a major change comes to mind this should be the last one for now.

tdm_irradiance_v3.0.pk4

At the moment this mod is still hit by three major deal breakers:

  1. On maps with a lot of portals the cutoff looks hideous and is barely better than letting the light shine through walls. It needs a better way to prevent wall leaks, obviously without using shadows.
  2. Performance is too affected on complex maps, I'd say I'm seeing -30 FPS at the very least. For such a simple estimation it's downright silly: We could have a smart algorithm doing real ray bounces at this cost.
  3. I'm not happy with overriding the base light classes to attach lights on top of other lights: I'd rather every light on the map gets an irradiance volume tailored to its exact appearance. This would be easy for me to do with a script that runs once scans all lights and attaches customized ambience to them... the next update would likely be that, but I don't know if I should bother unless #1 and #2 are also resolved (and this).

Based on my experience making this mod, I have an idea on how we could do this properly with an engine change. @cabalistic@duzenko and other graphics devs I'd like your input here please. It's based on two essential things:

  1. An ambient light decreasing with distance is a good enough estimation for irradiance and provides realistic results. As it's directionless and requires no per-pixel effects (specular or normal mapping) this approach can in theory be very cheap too. In my opinion it looks far better than having nothing, would work great until some hypothetical future where we had real ray tracing... as a rule our engine already uses many such good tricks.
  2. The shape and radius of the indirect light doesn't need to exceed that of the direct light but should be equal to it. The effect is only visible in and intended for areas covered by the light's radius box, but not touched by its direct light due to shadows or surface direction.

Knowing this I had the following thought: Suppose we had a setting to let every light have an ambient component, meaning any standard light material is treated like it has the "ambientLight" flag but without affecting the normal functionality of the direct light. The cvar multiplies the effect of the ambient component, when enabled you'd set it to something like 0.125 (since "_color 0.125 0.125 0.125" gives the best result in my tests). The ambient part uses all light properties normally: Same texture, color, etc... only difference is the brightness being multiplied by the cvar. The advantage of this method is we can get the exact same effect as what I'm doing here but without any extra lights, instead computing the ambiance as part of the same light using existing data to make the calculation as cheap as possible.

As the ambient component must remain shadowless to play its role, this doesn't solve the wall leak issue. I have an idea for that but will leave it for later, I don't want to overwhelm with too much at once. I'd like to hear thoughts on this proposal: How easy and cheap would it be to let all direct lights act as ambient lights too for players who want this?

Edited by MirceaKitsune
Link to comment
Share on other sites

Now that I think of it, one way to keep a light from bleeding to unwanted surfaces is to use the "spectrum" keyword.

It pairs light materials to surface materials or entities.

As of 2.08 and newer, there are two new spectrum options:

lightspectrum = acts like standard spectrum for entities except it allows ambient lights to render

nospectrum = entity ignores the spectrum attributes of all lights ( probably should be applied to AI depending on the scene )

( see interaction.cpp )

It may be worthwhile to design something like spectrum for shadows.

  • Like 1

Please visit TDM's IndieDB site and help promote the mod:

 

http://www.indiedb.com/mods/the-dark-mod

 

(Yeah, shameless promotion... but traffic is traffic folks...)

Link to comment
Share on other sites

49 minutes ago, nbohr1more said:

Now that I think of it, one way to keep a light from bleeding to unwanted surfaces is to use the "spectrum" keyword.

It pairs light materials to surface materials or entities.

As of 2.08 and newer, there are two new spectrum options:

lightspectrum = acts like standard spectrum for entities except it allows ambient lights to render

nospectrum = entity ignores the spectrum attributes of all lights ( probably should be applied to AI depending on the scene )

( see interaction.cpp )

It may be worthwhile to design something like spectrum for shadows.

Thank you! That sounds like it would need to be map specific though: It's not a material I must blacklist from being lit, but the backsides of walls fully covering the light... they might be using the same texture or be part of the same brush as the side that should be illuminated. How would I be using it exactly? Also it seems spawnargs like "areaLock" and "spectrum" aren't documented on the wiki... could be useful if those obscure settings were noted down somewhere.

Heading off for a bit and will be back in an hour or two. Let me know what you think of my engine-side suggestion in the meantime, that idea got me curious too: I feel we could easily solve the first part with a cvar giving all lights the ability to act as ambient lights too then toning down the ambient pass, which would be simpler than using extra lights and likely more performance friendly.

Edited by MirceaKitsune
Link to comment
Share on other sites

A little further pondering... The areaLock keyword is mainly meant to handle unexpected light performance impact by

making it easier to keep part of the light radius outside the area from rendering. Before this keyword, mappers would need to tediously adjust the light radius of lights near walls to keep performance acceptable.

What strikes me is a common denominator for this thread and some common complaints about light radius management is that mappers may like noshadows lights but not when they pass through walls and floors. A material flag that says, "this is a wall" might be the most mapper friendly way to address most of these issues including the one in this thread.

I will see if I can devise a flag like this.

  • Like 1

Please visit TDM's IndieDB site and help promote the mod:

 

http://www.indiedb.com/mods/the-dark-mod

 

(Yeah, shameless promotion... but traffic is traffic folks...)

Link to comment
Share on other sites

That would definitely be appreciated: If you do that I can quickly update my setup to try it out. Granted I can (hopefully) still run the engine from SVN and no dependencies broke since, will need to verify this later.

There's one satisfactory solution that comes to mind: Something akin to areaLock so the light is contained within the walls of its portal room, but by ignoring open portals themselves and including nearby rooms if any portal leading to it is touched. This would solve everything in that department: No lights emanating through walls but also no cutoffs against portal surfaces.

Such a system would have another huge advantage: We could run it on all standard lights so the shadow algorithm ignores meshes that are within radius of the light but in other rooms the light can't reach. This could hugely improve performance if enabled on all light sources by eliminating useless calculations.

Here's an image to show just what I mean: With the current system the light in this room would still calculate the statue outside right? Despite the statue never being able to receive any light or cast any shadows... big waste of FPS, it should be ignored entirely. If we masked walls the light can't surpass without masking their portal too, the issue of wall leaks for such lights would be resolved, while as a bonus all lights would get a performance boost by using it behind the scenes.

nsv5SiC.png

Simplest way of doing this that comes to mind: From the perspective of lights do exactly what we're doing for the player, which is calculating what portal surfaces are seen and open each other from that perspective. Before drawing anything lights should do what the player's camera does to cull rooms they can't see and remove them from their existence.

Link to comment
Share on other sites

B3hPr9D.png

Here's another telling image of what I mean. The rooms colored in green are ones the light calculates, the one in red and its contents are non-existent to that light. In this case the light would illuminate the room it's in, the larger room in the center because it's touching the nearby portal leading to it, but not the last room to the left despite intersecting it as it's not reaching the only open portal leading there from the light's perspective. Ignore the fact that there's no ceiling, left that out for easier visualization... if that were considered then all rooms as well as the outside world would exist to the light in this scenario.

Performance improvement aside, imagine that's a radial ambient light: If you're standing in the middle room you'll see its walls illuminated by the irradiance, this is desired as there's an open portal and you can say the light is coming through that door. If you're standing in the red room or outside of the whole box however, you don't see any of the walls there illuminated, as none of the light's rays would have had how to travel there.

Link to comment
Share on other sites

2 hours ago, MirceaKitsune said:

That would definitely be appreciated: If you do that I can quickly update my setup to try it out. Granted I can (hopefully) still run the engine from SVN and no dependencies broke since, will need to verify this later.

There's one satisfactory solution that comes to mind: Something akin to areaLock so the light is contained within the walls of its portal room, but by ignoring open portals themselves and including nearby rooms if any portal leading to it is touched. This would solve everything in that department: No lights emanating through walls but also no cutoffs against portal surfaces.

Such a system would have another huge advantage: We could run it on all standard lights so the shadow algorithm ignores meshes that are within radius of the light but in other rooms the light can't reach. This could hugely improve performance if enabled on all light sources by eliminating useless calculations.

Here's an image to show just what I mean: With the current system the light in this room would still calculate the statue outside right? Despite the statue never being able to receive any light or cast any shadows... big waste of FPS, it should be ignored entirely. If we masked walls the light can't surpass without masking their portal too, the issue of wall leaks for such lights would be resolved, while as a bonus all lights would get a performance boost by using it behind the scenes.

nsv5SiC.png

Simplest way of doing this that comes to mind: From the perspective of lights do exactly what we're doing for the player, which is calculating what portal surfaces are seen and open each other from that perspective. Before drawing anything lights should do what the player's camera does to cull rooms they can't see and remove them from their existence.

A completely "sealed" room will not render outside geometry.

( Sealed with brushes, either caulk or world spawn )

 

Performance problems happen when:

1) The statue intersects with the room

2) A light whose origin is outside the room has a radius that goes inside the room

3) The room has open portals leading to the statue or light(s)

 

The biggest hurdle is understanding that portal closure is not necessarily line-of-sight.

Portal culling typically happens only when the object is behind two portals.

https://iddevnet.dhewm3.org/doom3/visportals.html

 

The areaLocked keyword is meant to help in scenarios where it is not fully possible to:

1) Prevent lights from rendering to parts of a model that are outside of your room ( normally only brushes split at the room boundary )

2) Prevent lights from outside the room from traversing into it

3) Fully close portals in a way that would cause geometry culling for a light inside your room

Please visit TDM's IndieDB site and help promote the mod:

 

http://www.indiedb.com/mods/the-dark-mod

 

(Yeah, shameless promotion... but traffic is traffic folks...)

Link to comment
Share on other sites

Correct. The problem is how lights that go through a wall and intersect another room will always render in that room as well, rather than just the room where their origin is located. Using the areaLock spawnarg stops this and binds the light to its room, but this brings the situation in the opposite extreme as it now cuts off against every portal.

What I'm proposing is something in between that would be a lot more logical, a selective areaLock if you will: The light renders in the room where its origin is present, as well as other rooms it intersects but only if its bounding box is also intersecting at least one open portal leading to that other room. This would ensure the light operates only in spaces it's logically able to access and doesn't leak out or bother calculating anything outside, without cutting off in front of open portals in exchange.

All the light needs to do is loop through the portal surfaces of its room of origin, check if its bounding box touches any portal, if it does then include the room behind that portal, loop through the portals in that room next to see if any of those are intersected, repeat until all portals in all rooms touched by the light have been calculated. The light radius is a box and portals are 2D surfaces, the calculation would be very simple and light on the CPU if done in the right order with according loop breaks. Here's a simplified version of the function used to calculate intersections, obviously needs adapting to proper C++ notations and the actual variables the engine works with:

// self.mins is the starting position of the light's bounding box (bottom-left-back vertice)
// self.maxs is the ending end of the light's bounding box (top-right-front vertice)
// portal_vertices is an array containing the positions of all vertices of this visportal surface
bool light:check_intersection(vec3d[] portal_vertices)
{
	for(int i = 0; i < length(portal_vertices); i++)
	{
		vec3d v = portal_vertices[i];
		if(v.x >= self.mins.x && v.x <= self.maxs.x && v.y >= self.mins.y && v.y <= self.maxs.y && v.z >= self.mins.z && v.z <= self.maxs.z)
			return true
	}
	return false;
}

This function would be called in a per-portal loop. Rooms typically don't have more than 5 or 10 portals, and the vast majority of portal faces are rectangles so just 4 vertices to check intersection against... the whole check should be cheap enough to run on the living room digital clock without lagging :P

If I'm not missing something obvious here I'll prolly post this one on the bug tracker too so the idea doesn't get lost now that we found it. It hits two birds with one stone: A cheap performance optimization for all lights, and a way to fix those pesky wall leaks and truly make this irradiance patch viable.

Link to comment
Share on other sites

Sounds reasonable enough...

I guess the snag for this is that good looking lights have long falloff patterns...

thus you will find that the radius check will almost always hit the portal unless you have:

* Ultra tiny lights

* Huge rooms

* Ugly short falloff images

 

Please visit TDM's IndieDB site and help promote the mod:

 

http://www.indiedb.com/mods/the-dark-mod

 

(Yeah, shameless promotion... but traffic is traffic folks...)

Link to comment
Share on other sites

Opened #5765 for my proposed upgrade to areaLock and having a version that lets light travel through touched portals. Once that's fixed I should be able to get this working as intended! I don't know the engine code but provided some pointers based on what I saw there, it seems easy to do for those who know C++ and the structure of our engine functions better.

https://github.com/fholger/thedarkmod/blob/fe6b04bade680304b1809c9c0f4b866931152edd/renderer/RenderWorld.cpp#L1680

The portal touch scanning can probably be done in this function, granted there's an easy way of knowing a room's portals and which other room they lead to (via the areaNum ID). I'm assuming we can then call AddLightRefToArea(light, area) or every visleaf we want that light to show up in.

Edited by MirceaKitsune
Link to comment
Share on other sites

I have an even better proposal for doing light cutting, aimed at achieving the same two benefits: No wall leaks for my irradiance lights, plus a performance optimization for all other lights by discarding areas they can't reach before calculation. Essentially the same thing but portal independent and done per brush. It's better as it's not regarded as a hack like areaLock, and will also work for brushes that aren't part of any portal (eg: little side walls). It should be about as cheap too since we'd only do this for worldspawn, simple geometry typically involving a few 8-vertice cubes (and we could discard the back-faces).

The light simply loops through all worldspawn brushes it intersects preforming the same intersection check: If that brush or a set of overlapping brushes block that direction without leaving any cracks, so that no vertice / edge / face of the light's box reaches past that brush and the brush fully stops it, the light is cut and discards everything behind those brushes.... obviously if the brush in cause is using a non-transparent texture, and we include closed portal doors here.

light_cutting.thumb.png.283469298b570ddb0508d3152fe796d7.png

As Cabalistic pointed out, it can (kind of) be seen as duplicating the functionality of shadows, albeit it doesn't feel anything like shadows to me: It's a way of chopping the light before we calculate any lighting and shadows to discard what that light doesn't need to see... think of the light as a normal cubic brush in Darkradiant, then using the brush cut tool to cut 2D planes across it so it doesn't go through other brushes. What I'm suggesting here is NOT volumetric projection as we don't project anything: We'd only cut the light's box to a convex shape (no inner holes) when it can't get past a set of surfaces before deciding what gets included in its calculations.

Link to comment
Share on other sites

I've been playing with this and the player lantern really works nicely with this. It lights up areas that the lantern alone couldn't light up very well such as small nooks and cupboards, as well as making the general area feel brighter and easier to see.

Even if this doesn't get support for every light, I'd support at least the player lantern getting this treatment.

  • Like 2
Link to comment
Share on other sites

On 10/2/2021 at 9:05 AM, Gin said:

I've been playing with this and the player lantern really works nicely with this. It lights up areas that the lantern alone couldn't light up very well such as small nooks and cupboards, as well as making the general area feel brighter and easier to see.

Even if this doesn't get support for every light, I'd support at least the player lantern getting this treatment.

The mod enables it for all of the default lights which was my intent. At the moment this one is on hold I'm afraid: The engine developers don't seem to have a satisfactory solution to fixing the wall leak issue, I'd have to make a scriptobject to resize the light in realtime using traces which would be slow and complicated to do. The mod is usable but at the moment will produce ugly cutoffs in front of portals as well as bad performance.

Link to comment
Share on other sites

3 hours ago, lowenz said:

Any updated version?

No more updates since last time I'm afraid. I can't get it to work right without engine changes, and so far no one has a plan in that regard. I'd really love it but unless a core dev finds a better solution I don't know how much further this can go.

I have a proper idea in mind, but it needs someone implementing it. My idea is essentially a realtime voxel cubemap painted from the brightening of surfaces by lights, with each 3D pixel casting some radial fuzz in any zone hit by a bright lamp... a bit like 3D bloom in light casting if you will. That would be the equivalent of one bounce and also take into account the colors of surfaces for more realism. It could be done automatically per-light or with one global light... obviously I prefer the option which enables it on any map without requiring an entity being placed by the mapper, most old FM's will never have this then.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

  • Recent Status Updates

    • irg

      Watching warmly for The Black Parade, The Broken Goddess and Blood Death Wish Ep.4. Sometimes the best things in life actually are free.
      · 0 replies
    • STiFU

      We are taking our son on his very first holiday trip to see the sea for the first time. 🙂 Will be back in a week.
      · 2 replies
    • Gilkar

      When I was a young man my father was so ignorant I could hardly stand to have him around. As I grew older I was amazed at how much the old man had learned in such a short time.
      · 2 replies
    • jaxa

      RTX 3090 Super, RTX 3070 Ti 16 GB, RTX 2060 12 GB
      https://wccftech.com/nvidia-launching-rtx-3090-super-rtx-3070-ti-16gb-and-rtx-2060-12gb-by-january-2022/
      · 0 replies
    • duzenko

      CPU benchmark time - compiling DarkRadiant (2nd run)
      i5 8600K 6C/6T@4.4GHz DDR4 2x2133MHz 9MB cache
      Parallel builds: 1. 3:57 Parallel builds: 6 (default). 2:28 r5 1600AF 6C/12T@3.3GHz DDR4 1x2666MHz 16 MB cache, temp folder on HDD
      Parallel builds: 1. 5:05 Parallel builds: 4. 2:47 Parallel builds: 6. 2:55 Parallel builds: 12 (default). 2:57
      · 6 replies
×
×
  • Create New...