foundryvtt / foundryvtt

Public issue tracking and documentation for Foundry Virtual Tabletop - software connecting RPG gamers in a shared multiplayer environment with an intuitive interface and powerful API.
https://foundryvtt.com/
202 stars 10 forks source link

Provide a better tool for modeling sunlight in outdoor areas as a more targeted alternative to global illumination for mixed indoor/outdoor areas. #3078

Closed aaclayton closed 3 months ago

aaclayton commented 3 years ago

This Epic Will Be Solved By

Original Request Below

Originally in GitLab by @Adriannom

Currently, there are very poor workarounds for doing outside lighting when a scene has both inside areas and an outside area. Lighting only works correctly if the scene is either inside-only or outside-only.

The sunlight tool would allow you to draw an origin and a line. The origin would tell you which part of the scene to flood with sunlight (blocked by closed circuits of walls) while the line would indicate the direction and length of shadows (gentle shadows that exist even in bright vision, just to give an extra feel with the lighting).

Note that the sunlight origin isn't the origin in the same way that normal light sources are, it only indicates which areas count as outside. Perhaps there's a better word than origin?

Any sunlight sources are also turned off when the scene is changed to night time. A good counterpart to the sunlight tool would be a moonlight tool, which allows dim light to be designated in the same way, only at night.

Extra points for giving an API that @tposney can use in the About-time mod.

aaclayton commented 2 years ago

Originally in GitLab by @Razeick

Instead of Global illumination or Sunlight for outdoor areas. Wouldn't a global vision make more sense? Currently if I put a token with an extremely high Dim/Bright Vision in a scene with global illumination off their vision matches the scene darkness level. They also can see the outdoors clearly if I have the scene darkness set to zero. And they only have partial vision when it comes to looking into dark interior structures. The example being if I have a scene with an abandoned house, an outdoor area and the settings above, my token can see the outside of the house with no issues and can only see partially through any of the windows and doors. The only problem is once they step inside and close any sources that would let light in is that they can still see. It seems to me what would better is to have another global vision setting where the line of sight is unrestricted but is disabled when the scene darkness reaches a certain point and a another different way for the token to know when it is "inside" to disable the "global vision" The way for the token to know it is inside could maybe be a way for the user to mark certain grid squares, similarly to how the Difficult terrain and Terrain layer modules mark spaces?

aaclayton commented 3 years ago

Originally in GitLab by @cube1us

I concur.

aaclayton commented 3 years ago

Originally in GitLab by @arcanistzed

This should be reconsidered with the addition of overhead tiles which could act as the masks described by many commenters.

aaclayton commented 3 years ago

Originally in GitLab by @baoghal

Walls (and doors, windows, and so on are all represented by line segments. These appear to basically be all the same in that some line segments allow line of sight and some block line of sight.

In the hypothetical flood-fill light source, the user would plant one or more of these lights in the scene. It would flood fill the area in light, until it reached a line segment that permitted LOS. When it encountered one of these line segments, the system responsible for lighting could place an arbitrary light source on the flood side (or directly on) the light segment, at the midpoint. This is not a light that can be directly controlled or moved by the user, as it is a child of and controlled through the conjectural flood light. These window lights might be configurable throught the main spotlight, setting their dim and bright distances.

The result of procedurally generated "window light" would be an even light in the outdoor areas of the map, and where there was visibility through a wall segment, there would be light that is cast (by the programmatic source) through the window. It replicates the user adding light sources to every window on the map, and then trying to go through them all to adjust their brightness.

As far as performance considerations or whether or not it can be done, that is an exercise for the programmer. Some might see manually placing and tweaking lights and drawing perfect masks and being 100% configurable as desirable, but I believe that most users would find that to get tedious extremely fast, hence the request for a solution that saves the user time. Speculating about the reasons for the non-existence of a feature is just speculation. Maybe they are too busy with more important features, maybe there are technical problems, maybe they just didn't think of it, or maybe they want suggestions from the crowd.

aaclayton commented 3 years ago

Originally in GitLab by @schultzcole

That question is probably among the reasons why a sunlight tool is not already in. There are a bunch of edge cases and considerations that need to be accounted for when you start thinking about these things. How far should sunlight penetrate into the darkness of an unlit interior area? Is that dim light, or bright light, or how much of each should penetrate? What angle should the light passing in through the opening have? What if you want a scenario where no light enters through an opening at all?

The questions you raise about the walls method are part of why I'm in the mask camp. By using walls to determine sunlight/darkness areas, sunlight would need to be a special case in the lighting/walls system, because in order for it to behave correctly, it shouldn't use the wall visibility restrictions that normal ambient lights and line of sight use. As you mentioned, if it did try to do it that way, opening a door or having a window would bathe an entire room in light. Would a new setting need to be added to walls to allow/restrict sunlight penetration?

With the mask method, all areas under the mask would have no sunlight applied to them, whatsoever. You would then manually place small ambient light sources to simulate sunlight passing in through those openings. This has the benefit of being 100% user configurable on a per opening basis. Although I do admit that this would likely result in a similar performance impact to the current workaround method.

aaclayton commented 3 years ago

Originally in GitLab by @zeel02

So how would either implementation handle doors?

The expected result is that light from outside should shine through an open door, illuminating a section of the interior.

However, if sunlight is based on closed shapes the door either means the shape stops being closed when open (which would flood the whole room) or the shape only cares that a wall exists, which would mean light would not pass through the door ever. Unless doors are handled in their own special way, or any wall that's part of a closed shape but doesn't block light/vision treats the light from outside as a regular source of light that doesn't flood the room, but can shine into it.

But for the mask method, how would doors work? If you mask the inside of the building and indicate it as "inside" so that sunlight won't illuminate it, then it still wouldn't illuminate it even if there are no walls, right?

aaclayton commented 3 years ago

Originally in GitLab by @baoghal

Having tried to get this to work well myself, I would very much like to plant one light somewhere on my map to represent the outside lighting. It would be very nice to have this one source "flood fill" the area it is placed in. This source could also be associated with the light level for the scene and could actually just replace global illumination altogether. The process I go through right now is suboptimal. To handle maps with both exterior and interior lighting, I have to place extremely large radius lights all over the map (one in front of every door and every window, and around exterior walls) in order to "flood fill" my exterior areas when one light that "flood fills" would do the trick.

aaclayton commented 3 years ago

Originally in GitLab by @Adriannom

@aaclayton I think you misunderstand me, I don't claim that FVTT is broken! :)

However, the day and night cycle feature is broken, in the situation where a scene has both indoor and outdoor areas.

When you're indoors, your vision is limited. Unfortunately, the only way to have far vision in the outdoor areas is to hack a solution by placing some or many large light sources outside, but the problem is that when you transition to night, the daylight still exists outside, at night time! If you don't have problems with lighting in indoor/outdoor scenes, then I guess you're not using the day/night feature on those scenes?

The darkness threshold on light sources will sadly only turn lights on at night, you can't turn them off instead, so I don't see a workaround here. If you want a quick fix, then maybe implement two-way darkness thresholds? Though that's not as sexy as a proper sunlight tool with cool sun shadows and all...

aaclayton commented 3 years ago

Thanks for the feedback @Adriannom and @schultzcole .

I agree that there is an opportunity to improve things here by adding a new feature to the environment, but I disagree that in it's current state Foundry VTT is "broken". I don't have any problems creating hybrid indoor/outdoor scenes, it just requires a little bit of creativity on where to place light sources.

I'm happy to keep this open as a feature request to consider in the future, but it's not something that jumps to the front of the prioritization queue.

aaclayton commented 3 years ago

Originally in GitLab by @schultzcole

I mentioned the mask method because I know Atropos briefly mentioned it before. Additionally, I think it would be better to have it be a manually defined polygonal mask rather than defined by existing walls. There are edge cases not addressed by using walls to define sunlight areas, for instance an interior area that isn't fully enclosed by walls, or an area that is fully enclosed but you want to have sunlight, such as a courtyard.

aaclayton commented 3 years ago

Originally in GitLab by @Adriannom

@aaclayton As Cole mentions, since this doesn't work around corners you need to add X amount of light sources to achieve this, which can be problematic. Further than that though, what happens if you cycle to night time? Doing so is a native feature of Foundry, but it's not compatible with your workaround for outside lighting. So mixed indoor/outdoor lighting is actually currently broken.

But there is a different question we can ask other than "Is this required?", namely "Would this be awesome?". Dynamic lighting is a fantastic feature that provides a significant level of immersion and every time that immersion breaks it really is a waste. Proper outside lighting in mixed indoor/outdoor scenes would, in my opinion, be an awesome addition to an awesome feature.

I would love to see the dynamic lighting system improve in general too, it really has a lot of potential.

@schultzcole Is a mask really the only way to go for either weather or sunlight? Is it not possible to flood areas that aren't surrounded by closed-circuit walls?

aaclayton commented 3 years ago

Originally in GitLab by @schultzcole

In situations with lots of buildings, like an urban map, you might need quite a lot of light sources to illuminate the entire exterior, potentially causing performance issues.

I recall you mentioning a possible feature of adding an indoors mask for weather effects. Ideally that same indoors mask could be used for global illumination, though I imagine the effort difference between weather effects and illumination would be extensive.

aaclayton commented 3 years ago

Is a tool for this really required? My typical approach is to set the standard level of lighting in the scene for the indoor portions and then to place large light sources to illuminate the outdoor areas. Do you have an example of when this approach doesn't work?

Feu-Secret commented 7 months ago

Currently, the darkness level is applied on the whole scene. We should allow at minimum region or texture masking to exclude some parts of the map. We should also explore non-uniform level masking (with a texture height method or other solutions => scene regions)

caewok commented 7 months ago

My Elevated Vision module allows the user to configure an ambient light as a "sun/moon." It treats the light as directional, and allows the user to assign it azimuth and elevation angle (above the horizon). Shadows are directional—meaning the shadows are parallel—as would be the case for an infinitely distant light source. Alternatively, my Light Mask module has long allowed the user to define a light without a bounding polygon, which can give a simliar effect to that of Elevated Vision's sun/moon without all the fancy shadows.

I mention this so the Foundry devs and users can check out that user interface and see its benefits and limitations. I also mention it so you understand where I am coming from when I say I have thought about this issue of sunlight vs indoor lighting for awhile.

Some observations:

  1. I dislike the idea of using textures/drawings/tiles to mask light arbitrarily based on only the shape of the mask. It is disconnected from the physical reality of the scene, and so ultimately seems to me to be a stop-gap solution that stands in the way of a more elegant physical solution. From a user perspective, the user should be able to create a room, add a roof, and expect Foundry to understand whether light from outside can penetrate into the room. Drawings and tiles to define light areas is just an additional step that, because it has no physical basis, is ultimately confusing.

  2. It is possible to set lights in Foundry to represent the sun/moon/other large light sources. You can do it in base Foundry by giving a light a very large radius. Foundry could improve on this by allowing lights without boundaries (easy) or do something like Elevated Vision does for a more sophisticated physical light source at a distance. My claim, here, is that it would be better to physically model lights rather than try to arbitrarily set tokens to have "outdoor" and "indoor" vision.

  3. Large outdoor lights (2) work well, except that they still create harsh shadows because there is no ambient light modeling. I recommend giving lights a defined ambient property, adjustable by users, that substitutes for more complex ray shading that we definitely don't want to do. If a pixel in the scene can be reached (indirectly) by the light, it gets at least ambient light even if shadowed. Modeling ambient light correctly would likely be too hard, but it should be possible to cheat a bit to guess whether a given pixel is inside/outside compared to a sun/moon light source. The trick is to figure out a simple way to determine if a given pixel is contained by walls such that it cannot reach the large light source. For example, Elevated Vision constructs a scene graph from the walls so it can know how to fill elevation in a given area bounded by walls. Something like that could tell you if a given point is within the light bounds of a sun light source. I am sure more clever people than me could come up with other tests. For pixels that "connect" to the light source, apply the ambient light; for those blocked from the light (e.g., contained within a room), do not.

  4. Indoors should be defined by walls and roof tiles, not drawings or other invisible polygons. Really, this means that lights (and roofs, and walls) must have an elevation. If the light is above the roof, then the roof blocks. Similarly, heights of walls should matter. You can keep them infinitely high for basic setup, but if you want a token to be lit by the sun when on a roof but not be lit by the sun when under the roof, then you need defined heights for walls. This may sound complicated, but it gets you a simple user interface. If you have a light at 10', and it is outside, you can easily see that it does not penetrate the building. Drag that light inside the building, and now the light is contained within the building. Move the light elevation up, and now you see it illuminates the roof instead of the inside of the building.

LukasPrism commented 7 months ago

From a game mechanics perspective it would be great to have some lights defined as uniquely sunlight/moonlight (and ideally custom labels) so that features that are affected by such things can be automated. Things like sunlight sensitivity, or the Morning Glory weapon from AHD.

rapus95 commented 7 months ago

Hopefully this will also be implemented using tools that build onto #9772. As it was always only refered to an outside map with many indoor areas like houses which would be fully surrounded by walls, I also want to propose the opposite. An underground map which is mostly indoors but has several light shafts through which outdoor light can flood the underground. If using the regions of the linked issue, that would just be marking those light shafts as individual regions and setting the "is outdoor"-flag on all of them. If you then change the light color or darkness of the "outdoor light", this will carry on to all regions at the same time. Which is way better than having multiple light objects that need to be held in sync manually.

aaclayton commented 3 months ago

Closing this issue which is now encompassed by the #9772 epic.